🐙

dbt macro tips advent calendar 2022 day 16 - dispach

2022/12/16に公開

便利なデータ変換ツールである dbt の中のmacroに関するtipsを書いていく dbt macro tips Advent Calendar 2022 16日目です。

先日はmacro overrideの話をしました。

dispach

macroは呼び出し順序があり、書き換えられるという話をしました。
ここで更に複雑な話として、macroの呼び出し解決の際に、ターゲットとなるDWHごとに実際の処理を切り替えたい場合dispachというものを使うという話をします。

https://docs.getdbt.com/reference/dbt-jinja-functions/dispatch

OSSのpakcage等を眺めていたり、dbt-coreのmacroを眺めていたりすると次のようなmacroを見かけると思います。

macros/concat.sql
{% macro concat(fields) -%}
    {{ return(adapter.dispatch('concat')(fields)) }}
{%- endmacro %}

{% macro default__concat(fields) -%}
    {{ return(dbt_utils.concat(fields)) }}
{%- endmacro %}

{% macro redshift__concat(fields) %}
    {% for field in fields %}
        nullif({{ field }},'') {{ ' || ' if not loop.last }}
    {% endfor %}
{% endmacro %}

adapter.dispatch('concat')(fields)

という記述があります。コレが今回のキモとなります。
このconcatのmacroを呼び出した場合、まずはじめに concatが呼ばれその後adapter.dispatch('concat')(fields)に至ります。
そして、実行時のtargetのadapterを確認してredshiftがターゲットの場合は redshift__concat それ以外の場合は default__concat を呼び出します。

つまり、default__**redshift__**, bigquery__**, snowflake__** というような名前のmacroはdispach経由で呼び出される、その対象のDWH専用のmacroという位置づけになります。
dbtはこの仕組があるから、異なるDWHを使っていても、ある程度共通のコード資産を作れるわけですね。

ところで、皆様がお使いの場合、普通はただ単一のDWHを相手にすることが多いので、『もしかして、これってpackage開発者向けの話?』となると思います。
それは、そう。なんですが実は1つ覚えておかないといけないのは先日のシステムで使用されているmacroを書き換える場合の話になります。

macroをoverrideして書き換える場合いくつかの選択肢があります。

  1. concatのような大本のdispachを呼び出す前のものを書き換える
  2. redshift__**, bigqurey__**, snowflake__** のような専用のものを書き換える。
  3. default__**しかない場合、自分が使っているものを追加する。

これらは、どれをとってもいいとは思います。保守性等を考えてお好きな手段を使うのが良いと思います。
逆に、うまく行かないケースとして redshift__**, bigqurey__**, snowflake__** のような専用のmacroがあるのに、defualt__** を書き換えてしまうケースです。

このケースだけはうまく行かないので、dbt-coreのコードを読んで、システム挙動を書き換える場合は、この点にだけはご注意を。


17日目はpersist_docs改造の話をします。

Discussion