Files
airflow-greenplum/sql/stg/seats_dq.sql
T
ddadmin 5972bcc2d8 refactor(all): унифицированы служебные поля STG — переход на канонический нейминг
- Зачем:
  - STG-слой использовал legacy-имена (batch_id, load_dttm, src_created_at_ts),
    тогда как ODS/DDS/DM уже работали с каноном (_load_id, _load_ts, event_ts).
    Студент видел разные имена для одного понятия — это убрано.
- Что:
  - переименованы колонки в 9 STG DDL: batch_id→_load_id, load_dttm→_load_ts,
    src_created_at_ts→event_ts; добавлен NOT NULL для _load_id во всех таблицах.
  - обновлены 9 STG Load, 9 STG DQ, 9 ODS Load, 9 ODS DQ (INSERT/SELECT/WHERE).
  - обновлены DAG-файлы bookings_to_gp_stage.py и bookings_to_gp_ods.py
    (встроенный SQL резолвера, комментарии; Python-идентификаторы не тронуты).
  - обновлены тесты и ~15 документов (naming_conventions, PRD, db_schema,
    design-docs, qa-plan, README, TESTING и др.).
- Проверка:
  - grep -rn 'load_dttm\|src_created_at_ts' sql/ airflow/ tests/ — 0 совпадений.
  - make test — 4 passed.
  - e2e-etl: day1 прошёл полностью, day2 стартовал без ошибок.
2026-03-10 00:07:08 +03:00

88 lines
3.1 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Проверки качества данных для seats (справочник)
DO $$
DECLARE
v_batch_id TEXT := '{{ run_id }}'::text;
v_src_count BIGINT;
v_stg_count BIGINT;
v_dup_count BIGINT;
v_null_count BIGINT;
v_orphan_airplanes_count BIGINT;
BEGIN
-- Источник: считаем все строки во внешней таблице
SELECT COUNT(*)
INTO v_src_count
FROM stg.seats_ext;
IF v_src_count = 0 THEN
RAISE EXCEPTION
'В источнике seats_ext нет строк. Проверьте: bookings-db запущен, PXF работает, STG DDL применён (bookings_stg_ddl или make ddl-gp).';
END IF;
-- Считаем строки, реально вставленные в stg.seats в этом батче
SELECT COUNT(*)
INTO v_stg_count
FROM stg.seats
WHERE _load_id = v_batch_id;
IF v_src_count <> v_stg_count THEN
RAISE EXCEPTION
'DQ FAILED: несовпадение количества строк. Источник: %, STG: %',
v_src_count,
v_stg_count;
END IF;
-- Проверка на дубликаты составного ключа (airplane_code, seat_no)
-- Используем md5 от ROW, чтобы избежать коллизий при склейке строк.
SELECT COUNT(*) - COUNT(DISTINCT md5(ROW(airplane_code, seat_no)::text))
INTO v_dup_count
FROM stg.seats AS s
WHERE s._load_id = v_batch_id;
IF v_dup_count <> 0 THEN
RAISE EXCEPTION
'DQ FAILED: найдены дубликаты (airplane_code, seat_no) (_load_id=%): %',
v_batch_id,
v_dup_count;
END IF;
-- Проверка обязательных полей: airplane_code, seat_no, fare_conditions
SELECT COUNT(*)
INTO v_null_count
FROM stg.seats AS s
WHERE s._load_id = v_batch_id
AND (s.airplane_code IS NULL OR s.airplane_code = ''
OR s.seat_no IS NULL OR s.seat_no = ''
OR s.fare_conditions IS NULL OR s.fare_conditions = '');
IF v_null_count <> 0 THEN
RAISE EXCEPTION
'DQ FAILED: найдены строки с NULL в обязательных полях (airplane_code, seat_no, fare_conditions) (_load_id=%): %',
v_batch_id,
v_null_count;
END IF;
-- Проверка ссылочной целостности: airplane_code должен существовать в airplanes
SELECT COUNT(*)
INTO v_orphan_airplanes_count
FROM stg.seats AS s
LEFT JOIN stg.airplanes AS a
ON s.airplane_code = a.airplane_code
AND a._load_id = v_batch_id
WHERE s._load_id = v_batch_id
AND a.airplane_code IS NULL;
IF v_orphan_airplanes_count <> 0 THEN
RAISE EXCEPTION
'DQ FAILED: найдены seats с несуществующим airplane_code в airplanes (_load_id=%): %',
v_batch_id,
v_orphan_airplanes_count;
END IF;
RAISE NOTICE
'DQ PASSED: seats ок (_load_id=%): source=% stg=%',
v_batch_id,
v_src_count,
v_stg_count;
END $$;