From: Cristian Sabaila Date: Wed, 3 Nov 2021 01:39:08 +0000 (-0400) Subject: Fixed issue in visit_on_duplicate_key_update within a composed expression X-Git-Tag: rel_2_0_0b1~675^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5740a843ed805d0b066b1e56e8bf3c584c32cf6b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Fixed issue in visit_on_duplicate_key_update within a composed expression 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. Fixes: #7281 Closes: #7285 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7285 Pull-request-sha: 3e6ad6f2fecc6ae36a10a5a34b5d3d393483edbb Change-Id: I83377c20eae6358fead9e7e361127938e538a71c --- diff --git a/doc/build/changelog/unreleased_14/7281.rst b/doc/build/changelog/unreleased_14/7281.rst new file mode 100644 index 0000000000..a5ca9a1622 --- /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 4827df12f1..684f35c5f8 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 708039f943..ba162b4902 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 65d5b8364e..5a4e6ca8d5 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):