Jinja and Macros
dex supports Jinja, a powerful templating engine that allows you to add logic, reuse patterns, and dynamically generate SQL or Python code. Combined with macros, you can standardize transformation logic across your models and increase the flexibility and maintainability of your data pipelines.
Jinja brings programming constructs—like variables, loops, conditionals, and functions—into your transformation files. This allows your SQL to behave like code, while still compiling into clean, readable queries that run directly on your cloud warehouse.
What is Jinja?
Jinja is a lightweight templating language that runs before your SQL or Python is executed. It lets you embed logic inside your models using double curly braces {{ ... }}
for expressions and `{% ... %}
` for control structures.
Common use cases include:
Dynamically generating column lists
Controlling behavior with project/environment variables
Adding conditional logic or flags
Looping over fields, tables, or inputs
Example: Basic Jinja
{% set threshold = 100 %}
select *
from orders
where total_amount > {{ threshold }}
In this example, threshold
is a Jinja variable, and it will be replaced before the SQL is compiled and sent to your warehouse.
What is a Macro?
A macro is a reusable block of Jinja code, defined once and called many times. Macros are similar to functions in other programming languages and allow you to abstract complex or repetitive logic.
Macros live in .sql
files under the macros/
folder in your dex project.
Example: Defining and Using a Macro
Define a macro
-- macros/format_currency.sql
{% macro format_currency(column) %}
round({{ column }}, 2)
{% endmacro %}
Use the macro in a model
select
order_id,
{{ format_currency('order_total') }} as formatted_total
from orders
This compiles into:
select
order_id,
round(order_total, 2) as formatted_total
from orders
Jinja Blocks Overview
{{ ... }}
Print a value or expression
{% set var = ... %}
Define a variable
{% if condition %} ... {% endif %}
Conditional logic
{% for item in list %} ... {% endfor %}
Loop over a sequence
{% macro name() %} ... {% endmacro %}
Define a reusable macro
{{ ref('model') }}
Reference another model (dependency)
{{ source('src', 'tbl') }}
Reference a source or seed
{{ config(...) }}
Configure model materialization settings
{{ var('var_name') }}
Access a project or environment variable
Jinja with Environment Variables
Jinja works seamlessly with project and environment variables defined in dex. For example:
select *
from {{ var('default_schema') }}.users
In this case, default_schema
would be a variable set in the dex UI or dbt_project.yml
.
Debugging Jinja and Macros
You can inspect the compiled SQL of any model in the dex interface by clicking Compile Code
in the code editor. This shows exactly what dex will run in your warehouse after all Jinja and macros have been rendered.
If a macro is misused or a variable is missing, dex will show clear errors during compilation.
Best Practices
Use Jinja for logic that varies by environment or use case
Keep macro names descriptive and concise
Store all macros under a dedicated
macros/
folderAvoid overusing Jinja where pure SQL would be simpler
Document macros with comments and parameter descriptions
Last updated
Was this helpful?