Упрощение Lineage для SQL-запросов

Зачем нужен инструмент?
По своей работе мне приходится разбирать довольно сложные SQL. При этом это может быть не просто SQL, а ETL, состоящий из нескольких этапов преобразований.
Составление lineage не настолько сложный процесс, насколько долгий и муторный, не говоря уже о головной боли, связанной с тем, что не всегда проставлены alias для таблиц.
Например, для того чтобы понять, откуда приходят поля recipt_no и sku необходимо приложить усилия.
SELECT
recipt_no
,sku
FROM view_store_sales s
JOIN view_rec_line r
r.sku_id = s.sku_id
А теперь добавьте к этому запросу ещё 50 колонок, 5 CTE и 8 этапов преобразования ETL.
Задачка на внимание усложняется.
А еще иногда есть достаточно сложная витрина с огромной кучей показателей, считается долго, была сделана 10 лет назад, а по факту из нее используется пять колонок. И хорошо бы оптимизировать запрос, убрав ненужные таблички, join и колонки из кода. Это еще одна задача на внимательность. Хотелось бы кликнуть на 5 полей, которые нам нужны, и получить четко подсвеченные графы, которые показывают таблицы и колонки, CTE, используемые в запросе.
Что нужно реализовать?
- На вход DDL всех таблиц также возможны запросы, которые формируют таблицы, и SQL финального запроса
- Проставление Alias для всех полей. До этого использовать какой-нибудь линтер.
- Визуальное построение дерева Lineage
- Возможность сохранения этого дерева
- В визуальном редакторе: возможность выбора необходимых полей с подсветкой таблиц, от которых это поле зависит
Какие алгоритмы необходимы?
Лексический анализ
- Регулярные выражения — для описания лексем (идентификаторы, числа, строки).
- Конечные автоматы (DFA/NFA) — лежат в основе распознавания токенов
- Алгоритм преобразования регулярного выражения в NFA (алгоритм Томпсона) и NFA в DFA (конструкция подмножеств).
- Максимальное совпадение (maximal munch) — выбор самого длинного токена.
- Для реализации взять
sqlglot
Семантический анализ
- Обход AST (паттерн Visitor).
- Symbol table и name resolution: иерархия scope“ов. FROM создаёт scope, подзапрос — вложенный, CTE — именованный, LATERAL и коррелированные подзапросы видят внешний scope.
- Раскрытие
*иt.*по каталогу DDL, разрешение алиасов, детекция неоднозначных колонок. - Позиционное сопоставление колонок:
UNION/INTERSECT,INSERT INTO t (a,b) SELECT ...,JOIN,USING. - Рекурсивная инлайнизация вьюх: чтобы дойти до физических таблиц, определения VIEW надо разворачивать рекурсивно (с защитой от циклов).
Lineage — это dataflow-анализ
- Сolumn-level lineage — частный случай use-def chains из теории компиляторов.