Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/concepts/macros/jinja_macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,6 @@ Some SQL dialects interpret double and single quotes differently. We could repla

## Mixing macro systems

SQLMesh supports both the Jinja and [SQLMesh](./sqlmesh_macros.md) macro systems. We strongly recommend using only one system in a single model - if both are present, they may fail or behave in unintuitive ways.
SQLMesh supports both the Jinja and [SQLMesh](./sqlmesh_macros.md) macro systems.

[Predefined SQLMesh macro variables](./macro_variables.md) can be used in a query containing user-defined Jinja variables and functions. However, predefined variables passed as arguments to a user-defined Jinja macro function must use the Jinja curly brace syntax `{{ start_ds }}` instead of the SQLMesh macro `@` prefix syntax `@start_ds`. Note that curly brace syntax may require quoting to generate the equivalent of the `@` syntax.
Mixing the two systems is not supported, i.e., a SQL model may either use Jinja syntax, or SQLMesh macro syntax, but not both.
4 changes: 3 additions & 1 deletion docs/concepts/macros/sqlmesh_macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -2119,4 +2119,6 @@ Typed macros in SQLMesh not only enhance the development experience by making ma

## Mixing macro systems

SQLMesh supports both SQLMesh and [Jinja](./jinja_macros.md) macro systems. We strongly recommend using only one system in a model - if both are present, they may fail or behave in unintuitive ways.
SQLMesh supports both the Jinja and [SQLMesh](./sqlmesh_macros.md) macro systems.

Mixing the two systems is not supported, i.e., a SQL model may either use Jinja syntax, or SQLMesh macro syntax, but not both.
2 changes: 1 addition & 1 deletion examples/sushi/models/waiter_as_customer_by_day.sql
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ SELECT
FROM sushi.waiters AS w
JOIN sushi.customers as c ON w.waiter_id = c.customer_id
JOIN sushi.waiter_names as wn ON w.waiter_id = wn.id
WHERE w.event_date BETWEEN @start_date AND @end_date;
WHERE w.event_date BETWEEN CAST('{{ start_date }}' AS DATE) AND CAST('{{ end_date }}' AS DATE);

JINJA_END;
80 changes: 45 additions & 35 deletions sqlmesh/core/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,32 +188,38 @@ def _resolve_table(table: str | exp.Table) -> str:
**kwargs,
}

jinja_env_kwargs = render_kwargs.copy()
variables = kwargs.pop("variables", {})
jinja_env_kwargs = {
**{
**render_kwargs,
**_prepare_python_env_for_jinja(macro_evaluator, self._python_env),
**variables,
},
"snapshots": snapshots or {},
"table_mapping": table_mapping,
"deployability_index": deployability_index,
"default_catalog": self._default_catalog,
"runtime_stage": runtime_stage.value,
"resolve_table": _resolve_table,
}

if this_model:
render_kwargs["this_model"] = this_model
jinja_env_kwargs["this_model"] = this_model.sql(
dialect=self._dialect, identify=True, comments=False
)

jinja_env = self._jinja_macro_registry.build_environment(**jinja_env_kwargs)

expressions = [self._expression]
if isinstance(self._expression, d.Jinja):
# Mixing Jinja and SQLMesh macros is not supported
render_sqlmesh_macros = False

jinja_env_kwargs.update(
{
**{
**_prepare_python_env_for_jinja(macro_evaluator, self._python_env),
**variables,
},
"snapshots": snapshots or {},
"table_mapping": table_mapping,
"deployability_index": deployability_index,
"default_catalog": self._default_catalog,
"runtime_stage": runtime_stage.value,
"resolve_table": _resolve_table,
}
)
try:
expressions = []

jinja_env = self._jinja_macro_registry.build_environment(**jinja_env_kwargs)
rendered_expression = jinja_env.from_string(self._expression.name).render()
logger.debug(
f"Rendered Jinja expression for model '{self._model_fqn}' at '{self._path}': '{rendered_expression}'"
Expand All @@ -229,30 +235,34 @@ def _resolve_table(table: str | exp.Table) -> str:
raise ConfigError(
f"Could not render or parse jinja at '{self._path}'.\n{ex}"
) from ex

macro_evaluator.locals.update(render_kwargs)

if variables:
macro_evaluator.locals.setdefault(c.SQLMESH_VARS, {}).update(variables)

for definition in self._macro_definitions:
try:
macro_evaluator.evaluate(definition)
except Exception as ex:
raise_config_error(
f"Failed to evaluate macro '{definition}'.\n\n{ex}\n", self._path
)
else:
render_sqlmesh_macros = True
macro_evaluator.locals.update(render_kwargs)

if variables:
macro_evaluator.locals.setdefault(c.SQLMESH_VARS, {}).update(variables)

for definition in self._macro_definitions:
try:
macro_evaluator.evaluate(definition)
except Exception as ex:
raise_config_error(
f"Failed to evaluate macro '{definition}'.\n\n{ex}\n", self._path
)

resolved_expressions: t.List[t.Optional[exp.Expression]] = []

for expression in expressions:
try:
transformed_expressions = ensure_list(macro_evaluator.transform(expression))
except Exception as ex:
raise_config_error(
f"Failed to resolve macros for\n\n{expression.sql(dialect=self._dialect, pretty=True)}\n\n{ex}\n",
self._path,
)
if render_sqlmesh_macros:
try:
transformed_expressions = ensure_list(macro_evaluator.transform(expression))
except Exception as ex:
raise_config_error(
f"Failed to resolve macros for\n\n{expression.sql(dialect=self._dialect, pretty=True)}\n\n{ex}\n",
self._path,
)
else:
transformed_expressions = [expression]

for expression in t.cast(t.List[exp.Expression], transformed_expressions):
with self._normalize_and_quote(expression) as expression:
Expand Down