@@ -20,13 +20,13 @@ def render_jinja_sql_template(template, param_style=None):
2020 str: The rendered SQL query.
2121 """
2222
23- escaped_template = _escape_jinja_template (template )
24-
2523 # Default to pyformat for backwards compatibility
2624 # Note: Some databases like Trino require "qmark" or "format" style
27- jinja_sql = JinjaSql (
28- param_style = param_style if param_style is not None else "pyformat"
29- )
25+ effective_param_style = param_style if param_style is not None else "pyformat"
26+
27+ escaped_template = _escape_jinja_template (template , effective_param_style )
28+
29+ jinja_sql = JinjaSql (param_style = effective_param_style )
3030 parsed_content = jinja_sql .env .parse (escaped_template )
3131 required_variables = meta .find_undeclared_variables (parsed_content )
3232 jinja_sql_data = {
@@ -40,9 +40,14 @@ def _get_variable_value(variable_name):
4040 return getattr (__main__ , variable_name )
4141
4242
43- def _escape_jinja_template (template ):
43+ def _escape_jinja_template (template , param_style : str = "pyformat" ):
4444 # see https://github.com/sripathikrishnan/jinjasql/issues/28 and https://stackoverflow.com/q/8657508/2761695
4545 # we have to replace % by %% in the SQL query due to how SQL alchemy interprets %
46- # but only if the { is not preceded by { or followed by }, because those are jinja blocks
47- # we use lookbehind ?<= and lookahead ?= regex matchers to capture the { and } symbols
48- return re .sub (r"(?<=[^{])%(?=[^}])" , "%%" , template )
46+ # but ONLY for param styles that use % (format and pyformat)
47+ # For other param styles (qmark), % has no special meaning
48+ # and should not be escaped (e.g., in date format strings like '%m-%d-%Y')
49+ if param_style in ("format" , "pyformat" ):
50+ # Only escape % if it's not part of a jinja block (not preceded by { or followed by })
51+ # we use lookbehind ?<= and lookahead ?= regex matchers to capture the { and } symbols
52+ return re .sub (r"(?<=[^{])%(?=[^}])" , "%%" , template )
53+ return template
0 commit comments