Допустимость пустых данных по некоторым таблицам

This commit is contained in:
2026-01-18 21:48:47 +03:00
parent ba74b521dc
commit 8946df4a28
7 changed files with 87 additions and 19 deletions
+2 -2
View File
@@ -100,8 +100,8 @@ make bookings-init
- `load_segments_to_stg``check_segments_dq` (инкремент по `book_date` через tickets/bookings)
- `load_boarding_passes_to_stg``check_boarding_passes_dq` (full snapshot)
Важно: для некоторых таблиц “пустое окно инкремента” считается ошибкой (DQ делает `RAISE EXCEPTION`),
а для `boarding_passes` DQ может быть пропущена, если в источнике 0 строк.
Важно: для инкрементальных таблиц “пустое окно инкремента” допустимо — загрузка и DQ логируют `NOTICE` и завершаются успешно.
Для snapshot-справочников (airports/airplanes/routes/seats) пустой источник считается ошибкой (DQ делает `RAISE EXCEPTION`).
8) `finish_summary`
+5 -1
View File
@@ -81,7 +81,11 @@
- **Fail** полезен, когда “ожидаем данные в каждом запуске” (например, учебный генератор должен добавлять день);
- **Skip** полезен, когда “окно может быть пустым и это нормально”.
Рекомендация: зафиксировать политику в документации и сделать поведение единообразным по группам таблиц.
Выбранная политика для учебного стенда:
- Для инкрементальных таблиц (`bookings`, `tickets`, `flights`, `segments`) “пустое окно” **допустимо**:
DQ логирует `NOTICE` и завершает проверку, не падая.
- Для snapshot-справочников (`airports`, `airplanes`, `routes`, `seats`) пустой источник считаем ошибкой:
это почти всегда признак проблем с PXF/источником.
### 3.2. Комментарии в `*_load.sql`: точнее формулировать “идемпотентность”, а не “дедупликацию источника”
+4 -4
View File
@@ -101,7 +101,7 @@
- `total_amount TEXT` - общая сумма
- **Технические колонки:** `src_created_at_ts` (=book_date), `load_dttm`, `batch_id`
- **Стратегия загрузки:** Инкремент по `book_date`
- **DQ проверки:** count (окно инкремента), дубликаты book_ref, NULL обязательных полей
- **DQ проверки:** count (окно инкремента, пустое окно допустимо), дубликаты book_ref, NULL обязательных полей
#### stg.tickets (транзакции, инкремент)
- **Источник:** `bookings.tickets` (через PXF)
@@ -115,7 +115,7 @@
- `outbound TEXT` - направление (в источнике boolean)
- **Технические колонки:** `src_created_at_ts` (из book_date через bookings), `load_dttm`, `batch_id`
- **Стратегия загрузки:** Инкремент по `book_date` (через bookings)
- **DQ проверки:** count (окно инкремента), дубликаты ticket_no, NULL обязательных полей, пустой passenger_name, ссылочная целостность (bookings)
- **DQ проверки:** count (окно инкремента, пустое окно допустимо), дубликаты ticket_no, NULL обязательных полей, пустой passenger_name, ссылочная целостность (bookings)
#### stg.airports (справочник, full load)
- **Источник:** `bookings.airports_data` (через PXF)
@@ -185,7 +185,7 @@
- `actual_arrival TEXT` - фактическое время прилёта
- **Технические колонки:** `src_created_at_ts` (=scheduled_departure), `load_dttm`, `batch_id`
- **Стратегия загрузки:** Инкремент по `scheduled_departure`
- **DQ проверки:** count (окно инкремента), дубликаты flight_id, NULL обязательных полей, ссылочная целостность (routes, batch_id = текущий батч)
- **DQ проверки:** count (окно инкремента, пустое окно допустимо), дубликаты flight_id, NULL обязательных полей, ссылочная целостность (routes, batch_id = текущий батч)
#### stg.segments (транзакции, инкремент)
- **Источник:** `bookings.segments` (через PXF)
@@ -198,7 +198,7 @@
- `price TEXT` - цена
- **Технические колонки:** `src_created_at_ts` (из book_date через tickets), `load_dttm`, `batch_id`
- **Стратегия загрузки:** Инкремент по `book_date` (через tickets)
- **DQ проверки:** count (окно инкремента), дубликаты (ticket_no, flight_id), NULL обязательных полей, ссылочная целостность (tickets, flights)
- **DQ проверки:** count (окно инкремента, пустое окно допустимо), дубликаты (ticket_no, flight_id), NULL обязательных полей, ссылочная целостность (tickets, flights)
#### stg.boarding_passes (транзакции, full snapshot)
- **Источник:** `bookings.boarding_passes` (через PXF)
+18 -2
View File
@@ -26,9 +26,25 @@ BEGIN
WHERE book_date > COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
IF v_src_count = 0 THEN
-- Пустое окно инкремента допустимо: новых данных может не быть.
-- В этом случае ожидаем, что в текущем batch_id тоже 0 строк.
SELECT COUNT(*)
INTO v_stg_count
FROM stg.bookings
WHERE batch_id = v_batch_id;
IF v_stg_count <> 0 THEN
RAISE EXCEPTION
'В источнике bookings_ext нет строк для окна инкремента (book_date > %). Проверьте генерацию данных (make bookings-init / make bookings-generate-day или таск generate_bookings_day).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
'DQ FAILED: источник bookings_ext за окно инкремента пустой, но в stg.bookings есть строки текущего batch_id (batch_id=%): %',
v_batch_id,
v_stg_count;
END IF;
RAISE NOTICE
'В источнике bookings_ext нет строк для окна инкремента (book_date > %). Пропускаем DQ проверки (batch_id=%).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00'),
v_batch_id;
RETURN;
END IF;
-- Считаем строки, реально вставленные в stg.bookings в этом батче
+18 -2
View File
@@ -24,9 +24,25 @@ BEGIN
WHERE scheduled_departure > COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
IF v_src_count = 0 THEN
-- Пустое окно инкремента допустимо: новых данных может не быть.
-- В этом случае ожидаем, что в текущем batch_id тоже 0 строк.
SELECT COUNT(*)
INTO v_stg_count
FROM stg.flights
WHERE batch_id = v_batch_id;
IF v_stg_count <> 0 THEN
RAISE EXCEPTION
'В источнике flights_ext нет строк для окна инкремента (scheduled_departure > %).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
'DQ FAILED: источник flights_ext за окно инкремента пустой, но в stg.flights есть строки текущего batch_id (batch_id=%): %',
v_batch_id,
v_stg_count;
END IF;
RAISE NOTICE
'В источнике flights_ext нет строк для окна инкремента (scheduled_departure > %). Пропускаем DQ проверки (batch_id=%).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00'),
v_batch_id;
RETURN;
END IF;
-- Считаем строки, реально вставленные в stg.flights в этом батче
+18 -2
View File
@@ -27,9 +27,25 @@ BEGIN
WHERE b.book_date > COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
IF v_src_count = 0 THEN
-- Пустое окно инкремента допустимо: новых данных может не быть.
-- В этом случае ожидаем, что в текущем batch_id тоже 0 строк.
SELECT COUNT(*)
INTO v_stg_count
FROM stg.segments
WHERE batch_id = v_batch_id;
IF v_stg_count <> 0 THEN
RAISE EXCEPTION
'В источнике segments_ext нет строк для окна инкремента (book_date > %).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
'DQ FAILED: источник segments_ext за окно инкремента пустой, но в stg.segments есть строки текущего batch_id (batch_id=%): %',
v_batch_id,
v_stg_count;
END IF;
RAISE NOTICE
'В источнике segments_ext нет строк для окна инкремента (book_date > %). Пропускаем DQ проверки (batch_id=%).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00'),
v_batch_id;
RETURN;
END IF;
-- Считаем строки, реально вставленные в stg.segments в этом батче
+18 -2
View File
@@ -26,9 +26,25 @@ BEGIN
WHERE b.book_date > COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
IF v_source_count = 0 THEN
-- Пустое окно инкремента допустимо: новых данных может не быть.
-- В этом случае ожидаем, что в текущем batch_id тоже 0 строк.
SELECT COUNT(*)
INTO v_stg_count
FROM stg.tickets
WHERE batch_id = v_batch_id;
IF v_stg_count <> 0 THEN
RAISE EXCEPTION
'В источнике tickets_ext нет строк для окна инкремента (book_date > %). Проверьте генерацию данных (таск generate_bookings_day).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00');
'DQ FAILED: источник tickets_ext за окно инкремента пустой, но в stg.tickets есть строки текущего batch_id (batch_id=%): %',
v_batch_id,
v_stg_count;
END IF;
RAISE NOTICE
'В источнике tickets_ext нет строк для окна инкремента (book_date > %). Пропускаем DQ проверки (batch_id=%).',
COALESCE(v_prev_ts, TIMESTAMP '1900-01-01 00:00:00'),
v_batch_id;
RETURN;
END IF;
-- Количество в STG (текущий батч)