Files
boarding-pass/db.py
T

108 lines
3.3 KiB
Python

import sqlite3
from contextlib import contextmanager
import config
SCHEMA = """
CREATE TABLE IF NOT EXISTS pending_flights (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'queued'
CHECK (status IN ('queued','pending_review','track_unavailable',
'approved','rejected','decode_failed')),
image_path TEXT NOT NULL,
raw_bcbp TEXT,
passenger_name TEXT,
pnr TEXT,
from_iata TEXT,
to_iata TEXT,
from_icao TEXT,
to_icao TEXT,
operating_carrier_iata TEXT,
operating_carrier_icao TEXT,
flight_number TEXT,
julian_day INTEGER,
flight_date TEXT,
known_departure_time TEXT,
compartment TEXT,
seat TEXT,
process_after TEXT,
fetch_attempts INTEGER NOT NULL DEFAULT 0,
track_coordinates TEXT,
track_times TEXT,
track_point_count INTEGER,
flightaware_url TEXT,
takeoff_actual TEXT,
landing_actual TEXT,
gate_departure_scheduled TEXT,
gate_departure_actual TEXT,
gate_arrival_scheduled TEXT,
gate_arrival_actual TEXT,
departure_utc_offset TEXT,
arrival_utc_offset TEXT,
schedule_error TEXT,
airtrail_flight_id INTEGER,
parse_warnings TEXT,
error_message TEXT,
reviewed_at TEXT,
approved_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_pending_flights_status_process_after
ON pending_flights(status, process_after);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT
);
"""
def get_connection() -> sqlite3.Connection:
config.ensure_dirs()
conn = sqlite3.connect(config.DB_PATH, timeout=30)
conn.row_factory = sqlite3.Row
conn.execute("PRAGMA journal_mode=WAL")
conn.execute("PRAGMA foreign_keys=ON")
return conn
@contextmanager
def connect():
conn = get_connection()
try:
yield conn
conn.commit()
finally:
conn.close()
# Columns added after the original schema. CREATE TABLE IF NOT EXISTS above
# is a no-op against an already-existing table, so anything added there
# needs a matching entry here too or it silently never appears on an
# upgraded (vs. freshly created) database.
MIGRATIONS = [
("takeoff_actual", "TEXT"),
("landing_actual", "TEXT"),
("gate_departure_scheduled", "TEXT"),
("gate_departure_actual", "TEXT"),
("gate_arrival_scheduled", "TEXT"),
("gate_arrival_actual", "TEXT"),
("departure_utc_offset", "TEXT"),
("arrival_utc_offset", "TEXT"),
("schedule_error", "TEXT"),
]
def _run_migrations(conn: sqlite3.Connection) -> None:
existing = {row["name"] for row in conn.execute("PRAGMA table_info(pending_flights)")}
for column, coltype in MIGRATIONS:
if column not in existing:
conn.execute(f"ALTER TABLE pending_flights ADD COLUMN {column} {coltype}")
def init_db() -> None:
with connect() as conn:
conn.executescript(SCHEMA)
_run_migrations(conn)