Files
airflow-greenplum/sql/dds/dim_routes_load.sql
T
ddadmin 22a0590e1b feat(sql): явное управление storage и автоматизированный E2E-тест через REST API
- Зачем:
  - необходимо визуализировать выбор типа хранения (Heap vs Append-Only) для учебных целей.
  - автоматизировать проверку всей цепочки DWH для исключения ручных ошибок.
  - сделать процесс отладки прозрачным и наглядным через стандартные инструменты Airflow.
- Что:
  - внедрена клауза WITH (appendonly=...) во все DDL; ODS-справочники переведены на AO Row и TRUNCATE+INSERT.
  - создан скрипт scripts/e2e_etl.sh для полного прогона ETL (DDL + 2 дня данных) через REST API.
  - исправлены баги типизации (INTEGER[]), именования полей (amount, passenger_id) и удалены фантомные колонки (contact_data).
  - обновлен e2e-etl-test-protocol.md: добавлен раздел по отладке, чтению логов и перезапуску задач через API.
  - исправлены pytest-контракты под новую логику загрузки.
- Проверка:
  - успешный прогон `make e2e-smoke` (полный цикл от очистки до витрины).
2026-03-03 22:38:26 +03:00

110 lines
3.2 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.
-- Загрузка DDS dim_routes: SCD2 с hashdiff.
-- Учебный комментарий: Используем TEMP TABLE для подготовки дельты.
-- Это избавляет от дублирования логики hashdiff в UPDATE и INSERT блоках.
CREATE TEMP TABLE tmp_routes_src ON COMMIT DROP AS
SELECT
route_no,
departure_airport,
arrival_airport,
airplane_code,
days_of_week,
departure_time,
duration,
md5(
COALESCE(departure_airport, '') || '|' ||
COALESCE(arrival_airport, '') || '|' ||
COALESCE(airplane_code, '') || '|' ||
COALESCE(days_of_week::TEXT, '') || '|' ||
COALESCE(departure_time::TEXT, '') || '|' ||
COALESCE(duration::TEXT, '')
) AS hashdiff,
ROW_NUMBER() OVER (PARTITION BY route_no ORDER BY validity DESC) AS rn
FROM ods.routes;
-- Statement 1: Закрыть устаревшие версии (valid_to = текущая дата).
UPDATE dds.dim_routes AS d
SET valid_to = CURRENT_DATE,
updated_at = now(),
_load_id = '{{ run_id }}',
_load_ts = now()
FROM tmp_routes_src AS s
WHERE s.rn = 1
AND d.route_bk = s.route_no
AND d.valid_to IS NULL
AND d.hashdiff <> s.hashdiff;
-- Statement 1.1: Закрыть "исчезнувшие" маршруты.
UPDATE dds.dim_routes AS d
SET valid_to = CURRENT_DATE,
updated_at = now(),
_load_id = '{{ run_id }}',
_load_ts = now()
WHERE d.valid_to IS NULL
AND NOT EXISTS (
SELECT 1
FROM tmp_routes_src AS s
WHERE s.rn = 1
AND s.route_no = d.route_bk
);
-- Statement 2: Вставить новые версии (для изменённых и новых route_no).
WITH max_sk AS (
-- Учебный комментарий: Генерация SK через MAX() + ROW_NUMBER()
-- Этот подход работает безопасно только потому, что Airflow запускает
-- джобы загрузки для одной таблицы строго последовательно (concurrency=1).
SELECT COALESCE(MAX(route_sk), 0) AS v
FROM dds.dim_routes
)
INSERT INTO dds.dim_routes (
route_sk,
route_bk,
departure_airport,
arrival_airport,
airplane_code,
days_of_week,
departure_time,
duration,
hashdiff,
valid_from,
valid_to,
created_at,
updated_at,
_load_id,
_load_ts
)
SELECT
(SELECT v FROM max_sk) + ROW_NUMBER() OVER (ORDER BY s.route_no)::INTEGER,
s.route_no,
s.departure_airport,
s.arrival_airport,
s.airplane_code,
s.days_of_week,
s.departure_time,
s.duration,
s.hashdiff,
CASE
WHEN EXISTS (
SELECT 1
FROM dds.dim_routes AS d2
WHERE d2.route_bk = s.route_no
) THEN CURRENT_DATE
ELSE '1900-01-01'::DATE
END AS valid_from,
NULL,
now(),
now(),
'{{ run_id }}',
now()
FROM tmp_routes_src AS s
WHERE s.rn = 1
AND NOT EXISTS (
SELECT 1
FROM dds.dim_routes AS d
WHERE d.route_bk = s.route_no
AND d.valid_to IS NULL
AND d.hashdiff = s.hashdiff
);
ANALYZE dds.dim_routes;