summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-12-22 18:14:31 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-12-22 18:15:30 -0500
commit5cc18bb80077e98418b4a8066c0bc628209f3ada (patch)
tree1c6cc5c68aa2cb027565f023767b3f52c5b06a49
parentb973cbd8939f2cc0e29c668fffd507958c3e455a (diff)
downloadsqlalchemy-5cc18bb80077e98418b4a8066c0bc628209f3ada.tar.gz
expand out Index if passed to "constraint"
Fixed bug where the PostgreSQL :paramref:`_postgresql.OnConflictClause.constraint` parameter would accept an :class:`.Index` object, however would not expand this index out into its individual index expressions, instead rendering its name in an ON CONFLICT ON CONSTRAINT clause, which is not accepted by PostgreSQL; the "constraint name" form only accepts unique or exclude constraint names. The parameter continues to accept the index but now expands it out into its component expressions for the render. Fixes: #9023 Change-Id: I6baf243e26bfe578bf3f193c162dd7a623b6ede9
-rw-r--r--doc/build/changelog/unreleased_14/9023.rst12
-rw-r--r--lib/sqlalchemy/dialects/postgresql/dml.py2
-rw-r--r--test/dialect/postgresql/test_on_conflict.py39
3 files changed, 52 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_14/9023.rst b/doc/build/changelog/unreleased_14/9023.rst
new file mode 100644
index 000000000..d17a0cc98
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/9023.rst
@@ -0,0 +1,12 @@
+.. change::
+ :tags: bug, postgresql
+ :tickets: 9023
+
+ Fixed bug where the PostgreSQL
+ :paramref:`_postgresql.OnConflictClause.constraint` parameter would accept
+ an :class:`.Index` object, however would not expand this index out into its
+ individual index expressions, instead rendering its name in an ON CONFLICT
+ ON CONSTRAINT clause, which is not accepted by PostgreSQL; the "constraint
+ name" form only accepts unique or exclude constraint names. The parameter
+ continues to accept the index but now expands it out into its component
+ expressions for the render.
diff --git a/lib/sqlalchemy/dialects/postgresql/dml.py b/lib/sqlalchemy/dialects/postgresql/dml.py
index 645bedf17..27075191d 100644
--- a/lib/sqlalchemy/dialects/postgresql/dml.py
+++ b/lib/sqlalchemy/dialects/postgresql/dml.py
@@ -213,7 +213,7 @@ class OnConflictClause(ClauseElement):
if constraint is not None:
if not isinstance(constraint, str) and isinstance(
constraint,
- (schema.Index, schema.Constraint, ext.ExcludeConstraint),
+ (schema.Constraint, ext.ExcludeConstraint),
):
constraint = getattr(constraint, "name") or constraint
diff --git a/test/dialect/postgresql/test_on_conflict.py b/test/dialect/postgresql/test_on_conflict.py
index 3cdad78f0..8ef0f158e 100644
--- a/test/dialect/postgresql/test_on_conflict.py
+++ b/test/dialect/postgresql/test_on_conflict.py
@@ -682,6 +682,45 @@ class OnConflictTest(fixtures.TablesTest):
[(1, "name1", "mail2@gmail.com", "unique_name")],
)
+ def test_on_conflict_do_update_constraint_can_be_index(self, connection):
+ """test #9023"""
+
+ users = self.tables.users_xtra
+
+ connection.execute(
+ insert(users),
+ dict(
+ id=1,
+ name="name1",
+ login_email="mail1@gmail.com",
+ lets_index_this="unique_name",
+ ),
+ )
+
+ i = insert(users)
+ i = i.on_conflict_do_update(
+ constraint=self.unique_partial_index,
+ set_=dict(
+ name=i.excluded.name, login_email=i.excluded.login_email
+ ),
+ )
+
+ connection.execute(
+ i,
+ [
+ dict(
+ name="name1",
+ login_email="mail2@gmail.com",
+ lets_index_this="unique_name",
+ )
+ ],
+ )
+
+ eq_(
+ connection.execute(users.select()).fetchall(),
+ [(1, "name1", "mail2@gmail.com", "unique_name")],
+ )
+
def test_on_conflict_do_update_no_row_actually_affected(self, connection):
users = self.tables.users_xtra