Перейти к основному содержимому

pre-hook & post-hook

В этих примерах мы используем символ | для разделения двух различных вариантов форматирования SQL-запросов в pre-hooks и post-hooks. Первый вариант (без скобок) принимает один SQL-запрос в виде строки, в то время как второй (со скобками) принимает несколько SQL-запросов в виде массива строк. Замените SQL-STATEMENT на ваш SQL-запрос.

dbt_project.yml

models:
<resource-path>:
+pre-hook: SQL-statement | [SQL-statement]
+post-hook: SQL-statement | [SQL-statement]

models/<model_name>.sql

{{ config(
pre_hook="SQL-statement" | ["SQL-statement"],
post_hook="SQL-statement" | ["SQL-statement"],
) }}

select ...

models/properties.yml
models:
- name: [<model_name>]
config:
pre_hook: <sql-statement> | [<sql-statement>]
post_hook: <sql-statement> | [<sql-statement>]

Определение

SQL-выражение (или список SQL-выражений), которое выполняется до или после построения модели, seed или snapshot.

Pre- и post-хуки также могут вызывать макросы, которые возвращают SQL-выражения. Если ваш макрос зависит от значений, доступных только во время выполнения, таких как использование конфигураций модели или вызовы ref() к другим ресурсам в качестве входных данных, вам нужно будет обернуть вызов макроса в дополнительный набор фигурных скобок.

Зачем использовать хуки?

dbt стремится предоставить весь необходимый шаблонный SQL (DDL, DML и DCL) через встроенные функции, которые можно быстро и лаконично настроить. В некоторых случаях может быть SQL, который вы хотите или должны выполнить, специфичный для функциональности вашей платформы данных, который dbt пока не предлагает как встроенную функцию. В таких случаях вы можете написать точный SQL, который вам нужен, используя контекст компиляции dbt, и передать его в pre- или post- хук для выполнения до или после вашей модели, seed или snapshot.

Метод render

Метод .render() обычно используется для разрешения или вычисления выражений Jinja (таких как {{ source(...) }}) во время выполнения.

При использовании флага --empty, dbt может пропустить обработку ref() или source() для оптимизации. Чтобы избежать ошибок компиляции и явно указать dbt обработать конкретное отношение (ref() или source()), используйте метод .render() в вашем файле модели. Например:

models.sql
{{ config(
pre_hook = [
"alter external table {{ source('sys', 'customers').render() }} refresh"
]

Примеры

[Redshift] Выгрузка одной модели в S3

model.sql
{{ config(
post_hook = "unload ('select from {{ this }}') to 's3:/bucket_name/{{ this }}"
) }}

select ...

См.: Документация Redshift по UNLOAD

[Apache Spark] Анализ таблиц после создания

dbt_project.yml

models:
jaffle_shop: # это имя проекта
marts:
finance:
+post-hook:
# это может быть список
- "analyze table {{ this }} compute statistics for all columns"
# или вызов макроса
- "{{ analyze_table() }}"

См.: Документация Apache Spark по ANALYZE TABLE

Дополнительные примеры

Мы собрали более подробные примеры здесь.

Примечания по использованию

Хуки являются кумулятивными

Если вы определяете хуки как в вашем dbt_project.yml, так и в блоке config модели, оба набора хуков будут применены к вашей модели.

Порядок выполнения

Если определено несколько экземпляров любых хуков, dbt выполнит каждый хук в следующем порядке:

  1. Хуки из зависимых пакетов будут выполнены перед хуками в активном пакете.
  2. Хуки, определенные в самой модели, будут выполнены после хуков, определенных в dbt_project.yml.
  3. Хуки в данном контексте будут выполнены в порядке их определения.

Поведение транзакций

Если вы используете адаптер, который использует транзакции (например, Postgres или Redshift), стоит отметить, что по умолчанию хуки выполняются внутри той же транзакции, что и создаваемая модель.

Могут быть случаи, когда вам нужно выполнить эти хуки вне транзакции, например:

  • Вы хотите выполнить VACUUM в post-hook, однако это не может быть выполнено в транзакции (Документация Redshift)
  • Вы хотите вставить запись в аудиторскую в начале выполнения и не хотите, чтобы это выражение было отменено, если создание модели не удастся.

Чтобы достичь этого поведения, вы можете использовать один из следующих синтаксисов:

  • Важное замечание: не используйте этот синтаксис, если вы используете базу данных, где dbt не поддерживает транзакции. Это включает базы данных, такие как Snowflake, BigQuery и Spark или Databricks.

Блок конфигурации: используйте вспомогательные макросы before_begin и after_commit

models/<modelname>.sql
{{
config(
pre_hook=before_begin("SQL-statement"),
post_hook=after_commit("SQL-statement")
)
}}

select ...

0