dbt
JuniorПочему мой макрос dbt компилируется совсем не в то, что я ожидал?
Макрос — это шаблон, а не SQL, который выполняется. Отладка шаблона вместо того, что он реально произвёл, — это отладка совершенно не того уровня.
Макрос читается правильно. Скомпилированный SQL совсем не похож на то, что написано в макросе — и этот разрыв почти всегда сводится к одному из трёх конкретных поведений Jinja, а не к багу dbt.
Читайте compiled SQL, а не макрос
dbt compile записывает полностью отрендеренный SQL каждой модели в target/compiled/ — именно этот файл, а не шаблон Jinja, является реальным источником истины о том, что макрос на самом деле произвёл. Всматриваться в исходник макроса и рассуждать о том, что он должен выводить, значит отлаживать не тот слой, который реально выполняется.
Контроль пробелов меняет то, что Jinja вообще считает кодом
{%- ... -%} обрезает пробелы и переносы строк непосредственно вокруг тега. Отсутствие этих дефисов внутри цикла или условия в макросе — самая частая причина, по которой compiled SQL выходит с лишними пустыми строками или, того хуже, с хвостовой запятой, оставшейся от итерации цикла, которая не обрезалась так, как казалось должна была.
Scope переменной внутри макроса не то, чем кажется
Переменная, заданная через {% set x = ... %} внутри цикла {% for %}, не сохраняется за пределами scope этого цикла так, как обычная переменная в большинстве языков — это рутинное поведение Jinja, а не специфика dbt, и обычное решение, когда макросу нужно накапливать значение через итерации цикла, — объект namespace() вместо голого set.
Посмотрите, как это выглядит на вашем собственном пайплайне.
Загрузите реальный event log Spark, run_results.json от dbt или экспорт метрик Flink — и получите конкретные рекомендации, которые нужно одобрить, а не ещё одно эмпирическое правило.