sripathikrishnan / jinjasql

Template Language for SQL with Automatic Bind Parameter Extraction
MIT License
807 stars 88 forks source link

Sqlsafe doesn't survive template inheritance #18

Closed ngenain closed 4 years ago

ngenain commented 5 years ago

Hi,

I am having an issue with template inheritance and sqlsafe: the argument doesn't seem to propagate in the inherited templates. Here is a toy example showing my problem: . ├── templates │   ├── tables.sql │   └── test.sql └── test.py

In tables.sql you have listed all your tables you want to include in other sql files. For instance here's the content of tables.sql {% set test_table = 'test' | sqlsafe %}

In test.sql you include tables.sql

{% include 'templates/tables.sql' %}
SELECT * FROM {{ test_table }}

And in test.py I have the following code:

from pathlib import Path
from jinjasql import JinjaSql
from jinja2 import Environment, FileSystemLoader

rtemplate = Environment(loader=FileSystemLoader(str(Path(__file__).parent)))
j = JinjaSql(param_style='pyformat', env=rtemplate)

file_name = str(Path(__file__).parent / 'templates/test.sql')
with open(file_name, 'r') as f:
    template = f.read()
query_params = {}
query, bind_params = j.prepare_query(template, query_params)
print(query)
print(bind_params)

The answer is

SELECT * FROM %(test_table)s 
OrderedDict([('test_table', Undefined)])

The sqlsafe hasn't "survived" template inheritance. I also tried putting the sqlsafe parameter in the tables.sql and I got this answer:

SELECT * FROM  
OrderedDict()

Am I missing something?

Thank you very much for your help

sripathikrishnan commented 4 years ago

For posterity, this is how variable scoping works in Jinja. This stackoverflow answer has more details and workarounds - https://stackoverflow.com/questions/60725409/variable-set-using-the-set-operator-are-not-being-propagated-to-the-parent-templ