104 lines
3.2 KiB
Python
104 lines
3.2 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,
|
|
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"),
|
|
("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)
|