dbt test block 简单说明二

以前简单说明过dbt test block,属于一个自定义的扩展,同时也简单说明了一些使用,实际上dbt 的test 也是一个物化处理,支持物化的类型为test

参考manifest

  • test 类型的定义

因为存在此定义,按照dbt 的处理会基于物化的规则来进行sql 生成处理

test 物化参考定义

  • 参考macro 定义

老版本的global,新版本的adapter 中

  • test 处理
 
{%- materialization test, default -%}
 
  {% set relations = [] %}
  # 可以看到会有一个是否保存结果的配置,这个官方文档也有说明
  {% if should_store_failures() %}
 
    {% set identifier = model['alias'] %}
    {% set old_relation = adapter.get_relation(database=database, schema=schema, identifier=identifier) %}
    {% set target_relation = api.Relation.create(
        identifier=identifier, schema=schema, database=database, type='table') -%} %}
 
    {% if old_relation %}
        {% do adapter.drop_relation(old_relation) %}
    {% endif %}
 
    {% call statement(auto_begin=True) %}
        {{ create_table_as(False, target_relation, sql) }}
    {% endcall %}
 
    {% do relations.append(target_relation) %}
 
    {% set main_sql %}
        select *
        from {{ target_relation }}
    {% endset %}
 
    {{ adapter.commit() }}
 
  {% else %}
 
      {% set main_sql = sql %}
 
  {% endif %}
  # 以下几个是通用的配置,实际官方文档也有介绍
  {% set limit = config.get('limit') %}
  {% set fail_calc = config.get('fail_calc') %}
  {% set warn_if = config.get('warn_if') %}
  {% set error_if = config.get('error_if') %}
 
  {% call statement('main', fetch_result=True) -%}
   # get_test_sql 获取生成test sql 的macro 
    {{ get_test_sql(main_sql, fail_calc, warn_if, error_if, limit)}}
 
  {%- endcall %}
 
  {{ return({'relations': relations}) }}
 
{%- endmaterialization -%}
  • get_test_sql 处理
    会结合传递的fail_calc,warn_if,error_if,limit
{% macro get_test_sql(main_sql, fail_calc, warn_if, error_if, limit) -%}
  {{ adapter.dispatch('get_test_sql', 'dbt')(main_sql, fail_calc, warn_if, error_if, limit) }}
{%- endmacro %}
 
{% macro default__get_test_sql(main_sql, fail_calc, warn_if, error_if, limit) -%}
    select
      {{ fail_calc }} as failures,
      {{ fail_calc }} {{ warn_if }} as should_warn,
      {{ fail_calc }} {{ error_if }} as should_error
    from (
      {{ main_sql }}
      {{ "limit " ~ limit if limit != none }}
    ) dbt_internal_test
{%- endmacro %}
  • get_where_subquery macro 处理
    如果阅读官方文档了,可以看到会有关于where 的处理,同时也可以自定义,当然目前此部分与其他基于dispatch 处理的模式不太一样,是一个代码层处理的,参考处理
 
# 此处是上下文的
def _build_test_namespace(self):
    depends_on_macros = []
    # all generic tests use a macro named 'get_where_subquery' to wrap 'model' arg
    # see generic_test_builders.build_model_str
    get_where_subquery = self.macro_resolver.macros_by_name.get("get_where_subquery")
    if get_where_subquery:
        depends_on_macros.append(get_where_subquery.unique_id)
    if self.model.depends_on and self.model.depends_on.macros:
        depends_on_macros.extend(self.model.depends_on.macros)
    lookup_macros = depends_on_macros.copy()
    for macro_unique_id in lookup_macros:
        lookup_macro = self.macro_resolver.macros.get(macro_unique_id)
        if lookup_macro:
            depends_on_macros.extend(lookup_macro.depends_on.macros)
 
    macro_namespace = TestMacroNamespace(
        self.macro_resolver, self._ctx, self.model, self.thread_ctx, depends_on_macros
    )
    self.namespace = macro_namespace

解析部分
generic_test_builders 会进行test 模型macro 的处理

 
def build_model_str(self):
    targ = self.target
    if isinstance(self.target, UnparsedModelUpdate):
        if self.version:
            target_str = f"ref('{targ.name}', version='{self.version}')"
        else:
            target_str = f"ref('{targ.name}')"
    elif isinstance(self.target, UnparsedNodeUpdate):
        target_str = f"ref('{targ.name}')"
    elif isinstance(self.target, UnpatchedSourceDefinition):
        target_str = f"source('{targ.source.name}', '{targ.table.name}')"
    return f"{{{{ get_where_subquery({target_str}) }}}}"

生成元数据信息

说明

dbt 实际上几个比较核心的功能基本都是基于物化配置处理的,只是部分内部实现上稍有一些不同,同时注意dbt test 命令应该在dbt run 执行之后,否则
数据结果可能会不符合实际(这个流程也比较符合实际数据处理的流程)

参考资料

core/dbt/context/providers.py
core/dbt/parser/generic_test.py
https://docs.getdbt.com/reference/data-test-configs
https://docs.getdbt.com/reference/resource-configs/where

posted on 2024-04-29 07:33  荣锋亮  阅读(8)  评论(0编辑  收藏  举报

导航