diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-11-07 21:41:11 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-11-07 22:03:16 -0500 |
commit | 942c2429c033255979b6a55de836b9b26370673e (patch) | |
tree | 6d0d97312a67814cda5d39cf23d09b1360b5884b | |
parent | c4a8afa4c6bf5e76c24e8ed0b5c11acc0c8904e3 (diff) | |
download | sqlalchemy-942c2429c033255979b6a55de836b9b26370673e.tar.gz |
Put include_table=True for DO UPDATE..WHERE, but not ON CONFLICT
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
-rw-r--r-- | doc/build/changelog/changelog_11.rst | 11 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/postgresql/base.py | 1 | ||||
-rw-r--r-- | test/dialect/postgresql/test_compiler.py | 12 | ||||
-rw-r--r-- | test/dialect/postgresql/test_on_conflict.py | 44 |
4 files changed, 62 insertions, 6 deletions
diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index afa4389a8..d8f785556 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -22,6 +22,17 @@ :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 diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 9898e4ba4..4c82325f5 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -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: diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py index 52dd699fc..3e7f584bf 100644 --- a/test/dialect/postgresql/test_compiler.py +++ b/test/dialect/postgresql/test_compiler.py @@ -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") diff --git a/test/dialect/postgresql/test_on_conflict.py b/test/dialect/postgresql/test_on_conflict.py index 154d3fe58..9cfe4432a 100644 --- a/test/dialect/postgresql/test_on_conflict.py +++ b/test/dialect/postgresql/test_on_conflict.py @@ -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 |