diff options
| -rw-r--r-- | doc/build/changelog/unreleased_14/7281.rst | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/dialects/mysql/base.py | 2 | ||||
| -rw-r--r-- | test/dialect/mysql/test_compiler.py | 4 | ||||
| -rw-r--r-- | test/dialect/mysql/test_on_duplicate.py | 12 |
4 files changed, 20 insertions, 6 deletions
diff --git a/doc/build/changelog/unreleased_14/7281.rst b/doc/build/changelog/unreleased_14/7281.rst new file mode 100644 index 000000000..a5ca9a162 --- /dev/null +++ b/doc/build/changelog/unreleased_14/7281.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, mysql + :tickets: 7281 + :versions: 2.0.0b1 + + Fixed issue in MySQL :meth:`_mysql.Insert.on_duplicate_key_update` which + would render the wrong column name when an expression were used in a VALUES + expression. Pull request courtesy Cristian Sabaila. diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 4827df12f..684f35c5f 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -1302,7 +1302,7 @@ class MySQLCompiler(compiler.SQLCompiler): and obj.table is on_duplicate.inserted_alias ): obj = literal_column( - "VALUES(" + self.preparer.quote(column.name) + ")" + "VALUES(" + self.preparer.quote(obj.name) + ")" ) return obj else: diff --git a/test/dialect/mysql/test_compiler.py b/test/dialect/mysql/test_compiler.py index 708039f94..ba162b490 100644 --- a/test/dialect/mysql/test_compiler.py +++ b/test/dialect/mysql/test_compiler.py @@ -1110,12 +1110,12 @@ class InsertOnDuplicateTest(fixtures.TestBase, AssertsCompiledSQL): ) stmt = stmt.on_duplicate_key_update( bar=func.coalesce(stmt.inserted.bar), - baz=stmt.inserted.baz + "some literal", + baz=stmt.inserted.baz + "some literal" + stmt.inserted.bar, ) expected_sql = ( "INSERT INTO foos (id, bar) VALUES (%s, %s), (%s, %s) ON " "DUPLICATE KEY UPDATE bar = coalesce(VALUES(bar)), " - "baz = (concat(VALUES(baz), %s))" + "baz = (concat(concat(VALUES(baz), %s), VALUES(bar)))" ) self.assert_compile( stmt, diff --git a/test/dialect/mysql/test_on_duplicate.py b/test/dialect/mysql/test_on_duplicate.py index 65d5b8364..5a4e6ca8d 100644 --- a/test/dialect/mysql/test_on_duplicate.py +++ b/test/dialect/mysql/test_on_duplicate.py @@ -100,13 +100,19 @@ class OnDuplicateTest(fixtures.TablesTest): conn.execute(insert(foos).values(dict(id=1, bar="b", baz="bz"))) stmt = insert(foos).values([dict(id=1, bar="ab"), dict(id=2, bar="b")]) stmt = stmt.on_duplicate_key_update( - bar=func.concat(stmt.inserted.bar, "_foo") + bar=func.concat(stmt.inserted.bar, "_foo"), + baz=func.concat(stmt.inserted.bar, "_", foos.c.baz), ) result = conn.execute(stmt) eq_(result.inserted_primary_key, (None,)) eq_( - conn.execute(foos.select().where(foos.c.id == 1)).fetchall(), - [(1, "ab_foo", "bz", False)], + conn.execute(foos.select()).fetchall(), + [ + # first entry triggers ON DUPLICATE + (1, "ab_foo", "ab_bz", False), + # second entry must be an insert + (2, "b", None, False), + ], ) def test_on_duplicate_key_update_preserve_order(self, connection): |
