5151}
5252
5353
54- # pylint: disable=too-many-locals
54+ JINJAPATTERN = re .compile (
55+ r"(\s*(?:\{\{[\s\S]*?\}\}|\{%[\s\S]*?%\}))+" ,
56+ re .DOTALL ,
57+ )
58+
59+
60+ # pylint: disable=too-many-locals, too-many-branches
5561def get_metric_expression (metric_name : str , metrics : Dict [str , OGMetricSchema ]) -> str :
5662 """
5763 Return a SQL expression for a given dbt metric using sqlglot.
@@ -93,6 +99,11 @@ def get_metric_expression(metric_name: str, metrics: Dict[str, OGMetricSchema])
9399 if metric .get ("skip_parsing" ):
94100 return sql .strip ()
95101
102+ # if the metric expression contains Jinja syntax, we can't parse it as SQL;
103+ # instead we fallback to the regex method
104+ if re .search (JINJAPATTERN , sql ):
105+ return replace_metric_syntax (sql , metric ["depends_on" ], metrics )
106+
96107 try :
97108 expression = sqlglot .parse_one (sql , dialect = metric ["dialect" ])
98109 tokens = expression .find_all (exp .Column )
@@ -108,8 +119,7 @@ def get_metric_expression(metric_name: str, metrics: Dict[str, OGMetricSchema])
108119
109120 return expression .sql (dialect = metric ["dialect" ])
110121 except ParseError :
111- sql = replace_metric_syntax (sql , metric ["depends_on" ], metrics )
112- return sql
122+ return replace_metric_syntax (sql , metric ["depends_on" ], metrics )
113123
114124 sorted_metric = dict (sorted (metric .items ()))
115125 raise Exception (f"Unable to generate metric expression from: { sorted_metric } " )
@@ -300,7 +310,7 @@ def convert_query_to_projection(sql: str, dialect: MFSQLEngine) -> str:
300310 )
301311
302312 # replace aliases with their original expressions
303- for node , _ , _ in metric_expression .walk ():
313+ for node in metric_expression .walk ():
304314 if isinstance (node , Identifier ) and node .sql () in aliases :
305315 node .replace (parse_one (aliases [node .sql ()]))
306316
@@ -310,12 +320,12 @@ def convert_query_to_projection(sql: str, dialect: MFSQLEngine) -> str:
310320
311321 # Remove DISTINCT from metric to avoid conficting with CASE
312322 distinct = False
313- for node , _ , _ in metric_expression .this .walk ():
323+ for node in metric_expression .this .walk ():
314324 if isinstance (node , Distinct ):
315325 distinct = True
316326 node .replace (node .expressions [0 ])
317327
318- for node , _ , _ in where_expression .walk ():
328+ for node in where_expression .walk ():
319329 if isinstance (node , Identifier ) and node .sql () in aliases :
320330 node .replace (parse_one (aliases [node .sql ()]))
321331
0 commit comments