--- /dev/null
+.. change::
+ :tags: bug, mysql
+ :tickets: 11731
+
+ Fixed issue in MySQL dialect where using INSERT..FROM SELECT in combination
+ with ON DUPLICATE KEY UPDATE would erroneously render on MySQL 8 and above
+ the "AS new" clause, leading to syntax failures. This clause is required
+ on MySQL 8 to follow the VALUES clause if use of the "new" alias is
+ present, however is not permitted to follow a FROM SELECT clause.
+
clauses = []
- requires_mysql8_alias = (
+ requires_mysql8_alias = statement.select is None and (
self.dialect._requires_alias_for_on_duplicate_key
)
self.assert_compile(stmt, expected_sql, dialect=dialect)
+ @testing.variation("version", ["mysql8", "all_others"])
+ def test_from_select(self, version: Variation):
+ stmt = insert(self.table).from_select(
+ ["id", "bar"],
+ select(self.table.c.id, literal("bar2")),
+ )
+ stmt = stmt.on_duplicate_key_update(
+ bar=stmt.inserted.bar, baz=stmt.inserted.baz
+ )
+
+ expected_sql = (
+ "INSERT INTO foos (id, bar) SELECT foos.id, %s AS anon_1 "
+ "FROM foos "
+ "ON DUPLICATE KEY UPDATE bar = VALUES(bar), baz = VALUES(baz)"
+ )
+ if version.all_others:
+ dialect = None
+ elif version.mysql8:
+ dialect = mysql.dialect()
+ dialect._requires_alias_for_on_duplicate_key = True
+ else:
+ version.fail()
+
+ self.assert_compile(stmt, expected_sql, dialect=dialect)
+
def test_from_literal(self):
stmt = insert(self.table).values(
[{"id": 1, "bar": "ab"}, {"id": 2, "bar": "b"}]
from sqlalchemy import exc
from sqlalchemy import func
from sqlalchemy import Integer
+from sqlalchemy import literal
+from sqlalchemy import select
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy.dialects.mysql import insert
[(1, "ab", "bz", False)],
)
+ def test_on_duplicate_key_from_select(self, connection):
+ foos = self.tables.foos
+ conn = connection
+ conn.execute(insert(foos).values(dict(id=1, bar="b", baz="bz")))
+ stmt = insert(foos).from_select(
+ ["id", "bar", "baz"],
+ select(foos.c.id, literal("bar2"), literal("baz2")),
+ )
+ stmt = stmt.on_duplicate_key_update(bar=stmt.inserted.bar)
+
+ conn.execute(stmt)
+ eq_(
+ conn.execute(foos.select().where(foos.c.id == 1)).fetchall(),
+ [(1, "bar2", "bz", False)],
+ )
+
def test_on_duplicate_key_update_singlerow(self, connection):
foos = self.tables.foos
conn = connection