-- FR24 External data schema -- Phase 2, Step 1: Airport schedule (Yandex.Rasp + OpenSky) CREATE SCHEMA IF NOT EXISTS fr24_ext; -- Airport schedule (merged from Yandex + OpenSky) CREATE TABLE IF NOT EXISTS fr24_ext.schedule ( schedule_id BIGSERIAL PRIMARY KEY, flight_date DATE NOT NULL, airport_iata CHAR(3) NOT NULL, direction VARCHAR(10) NOT NULL CHECK (direction IN ('arrival', 'departure')), flight_number VARCHAR(10) NOT NULL, airline_iata CHAR(2), airline_name VARCHAR(100), origin_iata CHAR(3), destination_iata CHAR(3), aircraft_type VARCHAR(10), scheduled_at TIMESTAMPTZ NOT NULL, estimated_at TIMESTAMPTZ, actual_at TIMESTAMPTZ, status VARCHAR(20) DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'delayed', 'cancelled', 'departed', 'arrived')), icao24 CHAR(6), source VARCHAR(20) NOT NULL CHECK (source IN ('yandex', 'opensky', 'merged')), fetched_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (flight_number, airport_iata, scheduled_at, direction) ); CREATE INDEX IF NOT EXISTS idx_schedule_date ON fr24_ext.schedule (flight_date); CREATE INDEX IF NOT EXISTS idx_schedule_airport ON fr24_ext.schedule (airport_iata); CREATE INDEX IF NOT EXISTS idx_schedule_flight ON fr24_ext.schedule (flight_number); CREATE INDEX IF NOT EXISTS idx_schedule_time ON fr24_ext.schedule (scheduled_at); CREATE INDEX IF NOT EXISTS idx_schedule_dir ON fr24_ext.schedule (direction); CREATE INDEX IF NOT EXISTS idx_schedule_status ON fr24_ext.schedule (status); -- Load state / backfill cursor CREATE TABLE IF NOT EXISTS fr24_ext.load_state ( state_key VARCHAR(50) PRIMARY KEY, state_value JSONB NOT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); COMMENT ON TABLE fr24_ext.schedule IS 'Airport schedule from Yandex.Rasp + OpenSky, T-1 mode'; COMMENT ON TABLE fr24_ext.load_state IS 'Backfill cursor and load progress tracking';