Files
airflow-greenplum/sql/stg/bookings_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

95 lines
3.8 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.
-- Проверка количества строк между источником stg.bookings_ext и стейджем stg.bookings.
-- Считаем строки за то же окно инкремента, что и при загрузке:
-- все записи во внешней таблице с book_date больше максимального event_ts
-- из предыдущих батчей должны совпасть по количеству со строками текущего _load_id.
DO $$
DECLARE
v_batch_id text := '{{ run_id }}'::text;
v_prev_ts timestamp;
v_src_count bigint;
v_stg_count bigint;
v_dup_count bigint;
v_null_amount_count bigint;
BEGIN
-- Опорная метка: максимум event_ts среди предыдущих батчей
SELECT max(event_ts)
INTO v_prev_ts
FROM stg.bookings
WHERE _load_id <> v_batch_id
OR _load_id IS NULL;
-- Источник: считаем строки во внешней таблице, которые вошли в новое окно
SELECT COUNT(*)
INTO v_src_count
FROM stg.bookings_ext
WHERE book_date > COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
IF v_src_count = 0 THEN
-- Пустое окно инкремента допустимо: новых данных может не быть.
-- В этом случае ожидаем, что в текущем _load_id тоже 0 строк.
SELECT COUNT(*)
INTO v_stg_count
FROM stg.bookings
WHERE _load_id = v_batch_id;
IF v_stg_count <> 0 THEN
RAISE EXCEPTION
'DQ FAILED: источник bookings_ext за окно инкремента пустой, но в stg.bookings есть строки текущего _load_id (_load_id=%): %',
v_batch_id,
v_stg_count;
END IF;
RAISE NOTICE
'В источнике bookings_ext нет строк для окна инкремента (book_date > %). Пропускаем DQ проверки (_load_id=%).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00'),
v_batch_id;
RETURN;
END IF;
-- Считаем строки, реально вставленные в stg.bookings в этом батче
SELECT COUNT(*)
INTO v_stg_count
FROM stg.bookings
WHERE _load_id = v_batch_id;
IF v_src_count <> v_stg_count THEN
RAISE EXCEPTION
'Несовпадение количества строк при загрузке bookings: источник=%, stg=%. Проверьте окно инкремента и логи задач загрузки.',
v_src_count,
v_stg_count;
END IF;
-- Проверка на дубликаты book_ref
SELECT COUNT(*) - COUNT(DISTINCT book_ref)
INTO v_dup_count
FROM stg.bookings AS b
WHERE b._load_id = v_batch_id;
IF v_dup_count <> 0 THEN
RAISE EXCEPTION
'DQ FAILED: найдены дубликаты book_ref (_load_id=%): %',
v_batch_id,
v_dup_count;
END IF;
-- Проверка на NULL или пустые total_amount
SELECT COUNT(*)
INTO v_null_amount_count
FROM stg.bookings AS b
WHERE b._load_id = v_batch_id
AND (b.total_amount IS NULL OR b.total_amount = '');
IF v_null_amount_count <> 0 THEN
RAISE EXCEPTION
'DQ FAILED: найдены bookings с NULL или пустым total_amount (_load_id=%): %',
v_batch_id,
v_null_amount_count;
END IF;
RAISE NOTICE
'Проверка количества строк пройдена: источник=%, stg=%',
v_src_count,
v_stg_count;
END $$;