dbt 部分macro 中namespace的使用简单说明

比如在dbt adapter 中的snapshot_check_all_get_existing_columns 中就使用了namepace 这个对象,以下简单说明下

namespace 对象的作用

实际上就是进行跨scope 的数据共享,因为jinja2 每个block 中的设置的变量是不能跨范围共享,解决方法就是使用namespace

参考使用

{% set ns = namespace(found=false) %}
{% for item in items %}
    {% if item.check_something() %}
        {% set ns.found = true %}
    {% endif %}
    * {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}

dbt snapshot_check_all_get_existing_columns 内部处理

{% macro snapshot_check_all_get_existing_columns(node, target_exists, check_cols_config) -%}
    {%- if not target_exists -%}
        {#-- no table yet -> return whatever the query does --#}
        {{ return((false, query_columns)) }}
    {%- endif -%}
 
    {#-- handle any schema changes --#}
    {%- set target_relation = adapter.get_relation(database=node.database, schema=node.schema, identifier=node.alias) -%}
 
    {% if check_cols_config == 'all' %}
        {%- set query_columns = get_columns_in_query(node['compiled_code']) -%}
 
    {% elif check_cols_config is iterable and (check_cols_config | length) > 0 %}
        {#-- query for proper casing/quoting, to support comparison below --#}
        {%- set select_check_cols_from_target -%}
            {#-- N.B. The whitespace below is necessary to avoid edge case issue with comments --#}
            {#-- See: https://github.com/dbt-labs/dbt-core/issues/6781 --#}
            select {{ check_cols_config | join(', ') }} from (
                {{ node['compiled_code'] }}
            ) subq
        {%- endset -%}
        {% set query_columns = get_columns_in_query(select_check_cols_from_target) %}
 
    {% else %}
        {% do exceptions.raise_compiler_error("Invalid value for 'check_cols': " ~ check_cols_config) %}
    {% endif %}
 
    {%- set existing_cols = adapter.get_columns_in_relation(target_relation) | map(attribute = 'name') | list -%}
    # 定义namespace 实现跨block 功能的复用
    {%- set ns = namespace() -%} {#-- handle for-loop scoping with a namespace --#}
    {%- set ns.column_added = false -%}
 
    {%- set intersection = [] -%}
    {%- for col in query_columns -%}
        {%- if col in existing_cols -%}
            {%- do intersection.append(adapter.quote(col)) -%}
        {%- else -%}
            {% set ns.column_added = true %}
        {%- endif -%}
    {%- endfor -%}
    {{ return((ns.column_added, intersection)) }}
{%- endmacro %}

说明

namespace 实际属于jinja2 的特性,只是dbt 使用了此特性而已,所以看到部分dbt macro 使用此定义不应该陌生

参考资料

dbt/include/global_project/macros/materializations/snapshots/strategies.sql
https://jinja.palletsprojects.com/en/3.0.x/templates/

posted on 2024-06-14 06:00  荣锋亮  阅读(15)  评论(0编辑  收藏  举报

导航