]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Put include_table=True for DO UPDATE..WHERE, but not ON CONFLICT
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 8 Nov 2016 02:41:11 +0000 (21:41 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 8 Nov 2016 03:03:16 +0000 (22:03 -0500)
Fixed regression caused by the fix in :ticket:`3807` (version 1.1.0)
where we ensured that the tablename was qualified in the WHERE clause
of the DO UPDATE portion of PostgreSQL's ON CONFLICT, however you
*cannot* put the table name in the  WHERE clause in the actual ON
CONFLICT itself.   This was an incorrect assumption, so that portion
of the change in :ticket:`3807` is rolled back.

Change-Id: I442d8629496a8e405b54711cfcf487761810ae8a
Fixes: #3846
Fixes: #3807
doc/build/changelog/changelog_11.rst
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/postgresql/test_compiler.py
test/dialect/postgresql/test_on_conflict.py

index afa4389a8862a034da47053712736235b3c97b2c..d8f785556a4f5a0faa2fd7d8e60b3d0821d4ad14 100644 (file)
 .. changelog::
     :version: 1.1.4
 
+    .. change::
+        :tags: bug, postgresql
+        :tickets: 3846, 3807
+
+        Fixed regression caused by the fix in :ticket:`3807` (version 1.1.0)
+        where we ensured that the tablename was qualified in the WHERE clause
+        of the DO UPDATE portion of PostgreSQL's ON CONFLICT, however you
+        *cannot* put the table name in the  WHERE clause in the actual ON
+        CONFLICT itself.   This was an incorrect assumption, so that portion
+        of the change in :ticket:`3807` is rolled back.
+
     .. change::
         :tags: bug, orm
         :tickets: 3845
index 9898e4ba4e6da562f070313a5d093709e4ada95e..4c82325f566399bb58c5fad4dc68f2a06bafadc1 100644 (file)
@@ -1433,6 +1433,7 @@ class PGCompiler(compiler.SQLCompiler):
                 target_text += ' WHERE %s' % \
                     self.process(
                         clause.inferred_target_whereclause,
+                        include_table=False,
                         use_schema=False
                     )
         else:
index 52dd699fc6e2c75d070b7e4714fc628916f0b969..3e7f584bf74b0ca370e0623f6148c8b7c08dd697 100644 (file)
@@ -1205,7 +1205,7 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL):
         self.assert_compile(i,
                             'INSERT INTO mytable (name) VALUES '
                             "(%(name)s) ON CONFLICT (name) "
-                            "WHERE mytable.name > %(name_1)s "
+                            "WHERE name > %(name_1)s "
                             'DO UPDATE SET name = excluded.name')
 
     def test_do_update_index_elements_where_target_multivalues(self):
@@ -1223,7 +1223,7 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL):
             "INSERT INTO mytable (name) "
             "VALUES (%(name_m0)s), (%(name_m1)s), (%(name_m2)s) "
             "ON CONFLICT (name) "
-            "WHERE mytable.name > %(name_1)s "
+            "WHERE name > %(name_1)s "
             "DO UPDATE SET name = excluded.name",
             checkparams={
                 'name_1': 'm', 'name_m0': 'foo',
@@ -1246,7 +1246,7 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL):
         self.assert_compile(i,
                             'INSERT INTO mytable (name) VALUES '
                             "(%(name)s) ON CONFLICT (name) "
-                            "WHERE mytable.name > %(name_1)s "
+                            "WHERE name > %(name_1)s "
                             'DO UPDATE SET name = excluded.name')
 
     def test_do_update_unnamed_exclude_constraint_target(self):
@@ -1259,7 +1259,7 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL):
         self.assert_compile(i,
                             'INSERT INTO mytable (name) VALUES '
                             "(%(name)s) ON CONFLICT (name, description) "
-                            "WHERE mytable.description != %(description_1)s "
+                            "WHERE description != %(description_1)s "
                             'DO UPDATE SET name = excluded.name')
 
     def test_do_update_add_whereclause(self):
@@ -1275,7 +1275,7 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL):
         self.assert_compile(i,
                             'INSERT INTO mytable (name) VALUES '
                             "(%(name)s) ON CONFLICT (name, description) "
-                            "WHERE mytable.description != %(description_1)s "
+                            "WHERE description != %(description_1)s "
                             'DO UPDATE SET name = excluded.name '
                             "WHERE mytable.name != %(name_1)s "
                             "AND mytable.description != %(description_2)s")
@@ -1292,7 +1292,7 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL):
         self.assert_compile(i,
                             'INSERT INTO mytable (name) VALUES '
                             "(%(name)s) ON CONFLICT (name, description) "
-                            "WHERE mytable.description != %(description_1)s "
+                            "WHERE description != %(description_1)s "
                             'DO UPDATE SET name = excluded.name '
                             "WHERE mytable.name != excluded.name")
 
index 154d3fe5858b057453636457c1b2c90cc4e7e067..9cfe4432a416477b26f6e548269fbc647466acdc 100644 (file)
@@ -28,6 +28,12 @@ class OnConflictTest(fixtures.TablesTest):
             Column('login_email', String(50)),
             Column('lets_index_this', String(50))
         )
+        cls.unique_partial_index = schema.Index(
+            'idx_unique_partial_name',
+            users_xtra.c.name, users_xtra.c.lets_index_this,
+            unique=True,
+            postgresql_where=users_xtra.c.lets_index_this == 'unique_name')
+
         cls.unique_constraint = schema.UniqueConstraint(
             users_xtra.c.login_email, name='uq_login_email')
         cls.bogus_index = schema.Index(
@@ -405,6 +411,44 @@ class OnConflictTest(fixtures.TablesTest):
                     lets_index_this='bogus')
             )
 
+    def test_on_conflict_do_update_exotic_targets_six(self):
+        users = self.tables.users_xtra
+
+        with testing.db.connect() as conn:
+            conn.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(
+                index_elements=self.unique_partial_index.columns,
+                index_where=self.unique_partial_index.dialect_options
+                ['postgresql']['where'],
+                set_=dict(
+                    name=i.excluded.name,
+                    login_email=i.excluded.login_email),
+            )
+
+            conn.execute(
+                i,
+                [
+                    dict(name='name1', login_email='mail2@gmail.com',
+                         lets_index_this='unique_name'),
+                ]
+            )
+
+            eq_(
+                conn.execute(users.select()).fetchall(),
+                [
+                    (1, 'name1', 'mail2@gmail.com', 'unique_name'),
+                ]
+            )
+
     def test_on_conflict_do_update_no_row_actually_affected(self):
         users = self.tables.users_xtra