Reputation: 4554
I'm using an Ansible template to include variables in a SQL import file, and everything was working fine until lately where ansible is now parsing the quotes around variables in the template and eliminating some of them, where it never used to.
For example, the following...
INSERT INTO `my_table` VALUES (1, '{{ var.one }}', NULL, '{{ var.two }}');
...is now resulting in...
INSERT INTO `my_table` VALUES (1, 'value-one, NULL, value-two');
Notice that the two single quotes in the middle have been removed. This breaks the SQL. As per the MySQL/ANSI standards, I'm supposed to be using single quotes for string literals, and backticks only for identifiers. So what's the solution here? And does anyone know when this behaviour changed?
I'm using Ansible 2.9.27
As requested, here is the simple template task call...
- name: Copy SQL Dynamic Data Dump File for import
template: src=data.sql.j2 dest=/tmp/data.sql
Upvotes: 0
Views: 1924
Reputation: 67984
This issue has already been solved. The example below works for me both in 2.10 and 2.12
shell> cat import.sql.j2
INSERT INTO my_table VALUES (1, '{{ var.one }}', NULL, '{{ var.two }}');
and the task
- template:
src: import.sql.j2
dest: import.sql
vars:
var:
one: value-one
two: value-two
give valid SQL
shell> cat import.sql
INSERT INTO my_table VALUES (1, 'value-one', NULL, 'value-two');
As a workaround put the single quote into the expression
shell> cat import.sql.j2
INSERT INTO my_table VALUES (1, {{ "'" }}{{ var.one }}{{ "'" }}, NULL, {{ "'" }}{{ var.two }}{{ "'" }});
Use sed to make these changes globally, e.g.
shell> cat templates/import.sql.j2
INSERT INTO my_table VALUES (1, '{{ var.one }}', NULL, '{{ var.two }}');
shell> for i in templates/*; do sed -i "s/'/{{ \"'\" }}/g" $i; done
shell> cat templates/import.sql.j2
INSERT INTO my_table VALUES (1, {{ "'" }}{{ var.one }}{{ "'" }}, NULL, {{ "'" }}{{ var.two }}{{ "'" }});
Optionally choose a linter and validate SQL. The validate option in the template module doesn't work for sqlfluff hence the next command task is used below. The testing of the line length is excluded (--exclude-rules L016).
- template:
src: import.sql.j2
dest: import.sql
register: result
vars:
var:
one: value-one
two: value-two
- command: "sqlfluff lint {{ result.dest }} --exclude-rules L016"
changed_when: false
Upvotes: 1
Reputation: 4554
So apparently this is related to a known bug in Jinja2 that was fixed in 2.11. I'm using 3.0.3 though so it's odd that its still a problem, so I launched a bug report with Ansible and they've confirmed the behaviour. The way Jinja2 Native is used in templating has changed in Ansible 2.11 which should alieviate the problem, however until it's available in the release channel for our distro, we've been able to fix the problem by disabling "native" support in Jinja2 which we were using. This may cause other problems, but we're stuck since Ansible 2.9 is only receiving security patches now.
My Bug report is here: https://github.com/ansible/ansible/issues/76761
The Jinja2 Bug report is here: https://github.com/pallets/jinja/issues/1020
Upvotes: 0