dbt return macro 内部实现简单说明

jinja2 默认是没有return macro 的,dbt 在实现的时候比较有意思,通过一个exception 触发的,以下是简单说明

参考使用

  • 一个包含return 的macro
{% macro demoapp(name,version) %}
   {%  if version =='v1' %}
       {{return("appdemo") }}
    {% else %}
        {{return("dalongdemo")}}
    {% endif %}
    {{name }} --  {{version}}
{% endmacro  %}
  • 简单说明
    以上如果version 为v1 会返回appdemo ,否则为dalongdemo,后边部分是不会执行的,一个使用生成效果
{{ config(materialized='table') }}
 
select * from  {{demoapp('dalong','v1')}}

编译sql

dbt 内部实现简单说明

实际上return 为dbt 通过context 传递为jinja2 模版引擎的,return 实现是一个exception,这样执行就异常了,但是dbt 自己处理了异常

  • context 变量定义
@contextmember("return")
    @staticmethod
    def _return(data: Any) -> NoReturn:
        """The `return` function can be used in macros to return data to the
        caller. The type of the data (`dict`, `list`, `int`, etc) will be
        preserved through the return call.
 
        :param data: The data to return to the caller
 
 
        > macros/example.sql:
 
            {% macro get_data() %}
              {{ return([1,2,3]) }}
            {% endmacro %}
 
        > models/my_model.sql:
 
            select
              -- getdata() returns a list!
              {% for i in getdata() %}
                {{ i }}
                {% if not loop.last %},{% endif %}
              {% endfor %}
 
        """
        raise MacroReturn(data)
  • MacroReturn 实现
class MacroReturn(DbtBaseException):
    """This is how we return a value from a macro, not an exception.
 
    Hack of all hacks
    """
 
    def __init__(self, value) -> None:
        self.value = value
  • 调用部分
    dbt_common/clients/jinja.py BaseMacroGenerator 类
def call_macro(self, *args, **kwargs):
    # called from __call__ methods
    if self.context is None:
        raise DbtInternalError("Context is still None in call_macro!")
    assert self.context is not None
 
    macro = self.get_macro()
 
    with self.exception_handler():
        try:
            return macro(*args, **kwargs)
        except MacroReturn as e:
            return e.value

说明

dbt 对于renturn macro 的实现比较有意思,实际上是通过raise exception 实现的,这样jinja2的模版就具有了特定条件返回执行的能力了

参考资料

dbt_common/clients/jinja.py
dbt_common/exceptions/macros.py
core/dbt/context/base.py

posted on   荣锋亮  阅读(10)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2023-03-26 hilla 2.0 发布
2022-03-26 minio 4*4 集群 故障测试
2022-03-26 nocodb minio 集成试用
2022-03-26 nocodb 核心入口依赖
2022-03-26 minio 纠删码测试
2021-03-26 使用外部db 加速dremio 查询
2021-03-26 开发一个cube.js cratedb driver

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示