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