SQLGlot
SQLGlot — это написанный на чистом Python парсер, транспилер, оптимизатор и форматировщик SQL, поддерживающий более двадцати диалектов (PostgreSQL, MySQL, ClickHouse, BigQuery, Snowflake, Spark SQL и других). SQLGlot разбирает запрос в абстрактное синтаксическое дерево (AST), которое можно анализировать и преобразовывать программно, а затем сгенерировать обратно в SQL на любом из поддерживаемых диалектов.
Плагин ydb-sqlglot-plugin добавляет в SQLGlot диалект YDB. После его установки SQLGlot умеет как разбирать запросы на YQL, так и генерировать YQL из запросов, написанных на других диалектах. Преобразование двунаправленное: любой поддерживаемый диалект ↔ YQL.
В отличие от готового конвертера SQL-диалектов, который работает как внешний сервис и встроен в графические инструменты, плагин — это библиотека, которую вы подключаете в собственный Python-код. Это даёт два важных преимущества:
- Локальная обработка. Запросы не покидают вашу машину — никакие данные не отправляются на внешний HTTPS-сервис. Подходит для работы с конфиденциальными запросами.
- Программный доступ к AST. Кроме транспиляции, доступны разбор запроса, анализ происхождения столбцов (column lineage), оптимизация и форматирование — всё, что умеет SQLGlot.
Возможности
- Транспиляция запросов из других диалектов в YQL и обратно.
- Разбор YQL-запроса в AST для программного анализа и модификации.
- Анализ происхождения столбцов (column lineage) — отслеживание того, из каких таблиц и колонок получается каждый результирующий столбец.
- Оптимизация и форматирование запросов средствами SQLGlot.
- Поддержка специфичных для YQL конструкций: именованных выражений (
$variable), модульных функций (DateTime::GetYear()),FLATTEN, лямбда-выражений, контейнерных типов и других.
Примечание
Полный список поддерживаемого функционала и актуальные ограничения приведены в README репозитория плагина.
Установка
Плагин публикуется в PyPI под именем ydb-sqlglot-plugin:
pip install ydb-sqlglot-plugin
Требования:
- Python 3.9 или новее.
- SQLGlot версии 28.6.0 или новее (устанавливается автоматически как зависимость).
Плагин распространяется под лицензией Apache 2.0.
Быстрый старт
После установки диалект YDB доступен в SQLGlot автоматически — дополнительные импорты не нужны. У него два эквивалентных имени, ydb и yql; любое из них можно указывать в аргументах read и write.
Преобразование запроса из MySQL в YQL:
import sqlglot
result = sqlglot.transpile(
"SELECT * FROM users WHERE id = 1",
read="mysql",
write="ydb",
)[0]
print(result)
# SELECT * FROM `users` WHERE id = 1
Обратное преобразование — из YQL в PostgreSQL. Именованное выражение YQL ($t = (...)) превращается в CTE (WITH ... AS):
import sqlglot
result = sqlglot.transpile(
"$t = (SELECT id FROM users); SELECT * FROM $t AS t",
read="ydb",
write="postgres",
)[0]
print(result)
# WITH t AS (SELECT id FROM users) SELECT * FROM t AS t
Совет
Функция sqlglot.transpile() возвращает список строк — по одной на каждый оператор в исходном тексте. Если в запросе один оператор, берите первый элемент ([0]).
Примеры использования
Перенос запросов из других СУБД
При миграции в YDB плагин автоматически приводит конструкции исходного диалекта к правилам YQL. Например, имена с указанием схемы (schema.table) преобразуются в путь YDB с обратными кавычками:
import sqlglot
print(sqlglot.transpile("SELECT * FROM analytics.events", read="postgres", write="ydb")[0])
# SELECT * FROM `analytics/events`
Коррелированные подзапросы, не поддерживаемые в YDB напрямую, по возможности переписываются в JOIN, а конструкции WITH — в именованные выражения YQL.
Разбор запроса в AST
Если нужна не только транспиляция, но и анализ структуры запроса, разберите его в дерево с помощью sqlglot.parse_one():
import sqlglot
from sqlglot import exp
tree = sqlglot.parse_one("SELECT id, name FROM `users` WHERE age > 18", dialect="ydb")
# Перечислить все таблицы, к которым обращается запрос
for table in tree.find_all(exp.Table):
print(table.name)
# users
# Сгенерировать запрос обратно — на любом диалекте
print(tree.sql(dialect="clickhouse"))
Анализ происхождения столбцов
Поскольку YQL разбирается в стандартное AST SQLGlot, для запросов на YQL работает встроенный в SQLGlot анализ происхождения данных (column lineage). Это позволяет проследить, из каких исходных таблиц и колонок получается каждый результирующий столбец:
from sqlglot.lineage import lineage
node = lineage(
"total",
"SELECT SUM(amount) AS total FROM orders",
dialect="ydb",
)
print(node.name)
# total
Анализ происхождения полезен при построении инструментов документирования данных, оценке влияния изменений схемы (impact analysis) и аудите запросов.
Сопоставление функций и типов
Плагин содержит таблицы соответствий между стандартными SQL-конструкциями и их аналогами в YDB.
Типы данных приводятся к эквивалентам YDB:
| Тип в исходном диалекте | YDB |
|---|---|
TINYINT |
Int8 |
INT |
Int32 |
BIGINT |
Int64 |
VARCHAR, TEXT |
Utf8 |
TIMESTAMP |
Timestamp |
Функции сопоставляются по семейству значений:
- Дата и время:
DATE_TRUNC,EXTRACT, операции с интервалами. - Строки:
CONCAT,UPPER,LOWER,LENGTHи другие. - Коллекции:
ARRAY,ARRAY_FILTER,UNNEST→FLATTEN BY. - Условные и числовые:
NULLIF,ROUND,COUNT(). - JSON:
JSON_VALUE,JSON_QUERYс поддержкой сопутствующих конструкций.