How to call macro by name

I want to call a macro m1 in pre_hook. I have many tables, and each of them needs to call the pre_hook to run a DDL. I want to pass the table name as args in m1, and by this arg to call another macro dynamically to run the DDL for that arg. So how to call macro by name in string?

I tried

adapter.execute_macro('tbl1_ddl_macro', tbl_name='tbl1')

but got “‘dbt.context.providers.RuntimeDatabaseWrapper object’ has no attribute ‘execute_macro’”

Thanks.

i think execute_macro is not available to the Jinja object adapter for now.
u can try using if else

{% macro macro_m1(table_name) -%}
    {% set macro_name = table_name ~ '_macro' %}
    {% if macro_name == 'table_1_macro' %}
        {{ table_1_macro() }}
    {% elif macro_name == 'table_2_macro' %}
        {{table_2_macro()}}
    {% endif %}
{%- endmacro %}

{% macro table_1_macro() -%}

{{print("inside table_1 macro")}}

{%- endmacro %}

{% macro table_2_macro() -%}

{{print("inside table_2 macro")}}

{%- endmacro %}

Thanks Surya. This should work.
I also tried

adapter.dispatch('my_macro'')(tbl)

However this only works when I hard code “my_macro”. If pass a variable to dispatch, it will throw

AttributeError: 'Name' object has no attribute 'value'

i think the macro name from where ur calling the adapter.diapatch should match with the macro name given in the dispatch function.

EX:-

{% macro macro_m1(table_name) -%}
{{ return(adapter.dispatch(‘macro_m1’)()) }}
{%- endmacro %}

{% macro default__macro_m1() -%}

{{print(“inside macro_m1 macro”)}}

{%- endmacro %}

I put dispatch declaration in dbt-project.yml. The weird thing is if I use:

{{ return(adapter.dispatch('foo', 'ddls')(tbl)) }}

it works. If I make first arg as variable it doesn’t work:

{% set foo_macro = 'foo' %}
{{ return(adapter.dispatch(foo_macro, 'ddls')(tbl)) }}

The error is

AttributeError: 'Name' object has no attribute 'value'

I’m also running into this issue, running dbt v1.4.6. Does anyone know if this is fixed in a later version? Or on the roadmap to be fixed?

I am able to get a macro by name (and invoke it) by using context.get…

{% set foo_macro = context.get(‘foo’) %}
{% set result = foo_macro() %}

1 Like