--- /dev/null
+.. change::
+ :tags: bug, dml, mariadb, mysql
+ :tickets: 12117
+
+ Fixed a bug where the :class:`MySQLCompiler` would not properly compile statements
+ where :meth:`_mysql.Insert.on_duplicate_key_update` was passed values that included
+ :class:`InstrumentedAttribute` as keys.
+ Pull request courtesy of mingyu.
else:
_on_dup_alias_name = "new"
+ on_duplicate_update = {
+ coercions.expect_as_key(roles.DMLColumnRole, key): value
+ for key, value in on_duplicate.update.items()
+ }
+
# traverses through all table columns to preserve table column order
- for column in (col for col in cols if col.key in on_duplicate.update):
- val = on_duplicate.update[column.key]
+ for column in (col for col in cols if col.key in on_duplicate_update):
+ val = on_duplicate_update[column.key]
# TODO: this coercion should be up front. we can't cache
# SQL constructs with non-bound literals buried in them
name_text = self.preparer.quote(column.name)
clauses.append("%s = %s" % (name_text, value_text))
- non_matching = set(on_duplicate.update) - {c.key for c in cols}
+ non_matching = set(on_duplicate_update) - {c.key for c in cols}
if non_matching:
util.warn(
"Additional column names not matching "
from sqlalchemy.dialects.mysql import base as mysql
from sqlalchemy.dialects.mysql import insert
from sqlalchemy.dialects.mysql import match
+from sqlalchemy.orm import DeclarativeBase
+from sqlalchemy.orm import Mapped
+from sqlalchemy.orm import mapped_column
from sqlalchemy.sql import column
from sqlalchemy.sql import delete
from sqlalchemy.sql import table
dialect=dialect,
)
+ def test_on_update_instrumented_attribute_dict(self):
+ class Base(DeclarativeBase):
+ pass
+
+ class T(Base):
+ __tablename__ = "table"
+
+ foo: Mapped[int] = mapped_column(Integer, primary_key=True)
+
+ q = insert(T).values(foo=1).on_duplicate_key_update({T.foo: 2})
+ self.assert_compile(
+ q,
+ (
+ "INSERT INTO `table` (foo) VALUES (%s) "
+ "ON DUPLICATE KEY UPDATE foo = %s"
+ ),
+ {"foo": 1, "param_1": 2},
+ )
+
class RegexpCommon(testing.AssertsCompiledSQL):
def setup_test(self):