Jinja: шаблонизатор поверх SQL
SQL не умеет циклы и условия — Jinja добавляет их поверх, до того как запрос уйдёт в хранилище.
Jinja — шаблонизатор, который dbt применяет к моделям до отправки в хранилище: он раскрывает
{{ ... }}и{% ... %}в обычный SQL, добавляя переменные, циклы и условия.
Две фазы: компиляция и выполнение
Ключ к пониманию Jinja — это два момента времени. Сначала dbt компилирует модель: раскрывает всю Jinja в чистый SQL. Только потом этот SQL выполняется в хранилище. Хранилище никогда не видит Jinja — оно получает обычный SQL. ref(), source(), config() из прошлых уроков — всё это и есть Jinja.
{{ ... }} -- выражение: подставить значение (ref, переменную, результат макроса)
{% ... %} -- инструкция: логика (if, for, set), сама в SQL не попадает
Переменные через set
{% set statuses = ['paid', 'shipped', 'delivered'] %}
select *
from {{ ref('stg_orders') }}
where status in (
{% for s in statuses %}
'{{ s }}'{% if not loop.last %},{% endif %}
{% endfor %}
)
После компиляции это превратится в обычный SQL: where status in ('paid','shipped','delivered'). Цикл for сгенерировал список, а loop.last поставил запятые между элементами, но не после последнего.
Условия через if
Вы уже видели это в инкрементальных моделях — {% if is_incremental() %}. Условия позволяют включать куски SQL в зависимости от ситуации. Ещё пример — разное поведение в dev и prod:
select * from {{ ref('events') }}
{% if target.name == 'dev' %}
where created_at >= current_date - 7 -- в dev берём только неделю, чтобы быстрее
{% endif %}
Как посмотреть результат компиляции
# Скомпилировать модели в чистый SQL (без выполнения)
dbt compile
# Результат лежит в target/compiled/...
# Полезно, чтобы увидеть, во что превратилась Jinja
Как работает под капотом
dbt — это, по сути, генератор SQL на Jinja. На этапе compile он проходит по файлу, исполняет все {% %}-инструкции и подставляет все {{ }}-выражения, получая финальный SQL-текст. Переменные, циклы и условия дают то, чего нет в чистом SQL: способность переиспользовать и параметризовать запросы. Но важно помнить: Jinja работает над текстом запроса, а не над строками данных. Цикл for разворачивает SQL-текст, а не перебирает записи таблицы.
Частые ошибки
- Думать, что Jinja выполняется в хранилище. Нет — она раскрывается до отправки; хранилище видит чистый SQL.
- Путать компиляцию и выполнение. Цикл
forгенерирует текст запроса, а не итерирует данные. - Перебарщивать с логикой. Слишком хитрая Jinja превращает модель в нечитаемую; сложное лучше вынести в макрос.
Итоги
- Jinja добавляет к SQL переменные, циклы и условия; dbt раскрывает её в чистый SQL на этапе компиляции.
- Хранилище видит только готовый SQL — Jinja работает над текстом запроса, не над данными.
dbt compileпоказывает, во что превратилась Jinja.