From: Mike Bayer Date: Wed, 30 Jun 2021 13:22:00 +0000 (-0400) Subject: apply quoting to "ON CONSTRAINT" symbol X-Git-Tag: rel_1_4_21~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dee57477882f8876fd97071a790fe3d3ee2164c5;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git apply quoting to "ON CONSTRAINT" symbol Fixed issue in :meth:`_postgresql.Insert.on_conflict_do_nothing` and :meth:`_postgresql.Insert.on_conflict_do_update` where the name of a unique constraint passed as the ``constraint`` parameter would not be properly quoted if it contained characters which required quoting. Fixes: #6696 Change-Id: I4ffca9b8c72cef4ed39e2de96831ccc11a620422 --- diff --git a/doc/build/changelog/unreleased_14/6696.rst b/doc/build/changelog/unreleased_14/6696.rst new file mode 100644 index 0000000000..e1ff871da5 --- /dev/null +++ b/doc/build/changelog/unreleased_14/6696.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, postgresql + :tickets: 6696 + + Fixed issue in :meth:`_postgresql.Insert.on_conflict_do_nothing` and + :meth:`_postgresql.Insert.on_conflict_do_update` where the name of a unique + constraint passed as the ``constraint`` parameter would not be properly + quoted if it contained characters which required quoting. + diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 4c78981329..4c654a643b 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -2322,7 +2322,9 @@ class PGCompiler(compiler.SQLCompiler): def _on_conflict_target(self, clause, **kw): if clause.constraint_target is not None: - target_text = "ON CONSTRAINT %s" % clause.constraint_target + target_text = "ON CONSTRAINT %s" % self.preparer.quote( + clause.constraint_target + ) elif clause.inferred_target_elements is not None: target_text = "(%s)" % ", ".join( ( diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py index 2f91580a93..e48de9d21d 100644 --- a/test/dialect/postgresql/test_compiler.py +++ b/test/dialect/postgresql/test_compiler.py @@ -28,6 +28,7 @@ from sqlalchemy import Text from sqlalchemy import text from sqlalchemy import tuple_ from sqlalchemy import types as sqltypes +from sqlalchemy import UniqueConstraint from sqlalchemy import update from sqlalchemy.dialects import postgresql from sqlalchemy.dialects.postgresql import aggregate_order_by @@ -2339,6 +2340,31 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL): "DO UPDATE SET myid = excluded.myid", ) + def test_do_nothing_quoted_string_constraint_target(self): + """test #6696""" + i = insert(self.table1, values=dict(name="foo")) + i = i.on_conflict_do_nothing(constraint="Some Constraint Name") + self.assert_compile( + i, + "INSERT INTO mytable (name) VALUES " + '(%(name)s) ON CONFLICT ON CONSTRAINT "Some Constraint Name" ' + "DO NOTHING", + ) + + def test_do_nothing_quoted_named_constraint_target(self): + """test #6696""" + i = insert(self.table1, values=dict(name="foo")) + unique_constr = UniqueConstraint( + self.table1.c.myid, name="Some Constraint Name" + ) + i = i.on_conflict_do_nothing(constraint=unique_constr) + self.assert_compile( + i, + "INSERT INTO mytable (name) VALUES " + '(%(name)s) ON CONFLICT ON CONSTRAINT "Some Constraint Name" ' + "DO NOTHING", + ) + def test_do_update_index_elements_where_target(self): i = insert(self.table1, values=dict(name="foo")) i = i.on_conflict_do_update(