]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Accommodate value of None for ON DUPLICATE KEY UPDATE
authorLukas Banic <luko@lingea.cz>
Mon, 10 Jun 2019 15:24:53 +0000 (11:24 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 10 Jun 2019 17:31:41 +0000 (13:31 -0400)
Fixed bug where MySQL ON DUPLICATE KEY UPDATE would not accommodate setting
a column to the value NULL.  Pull request courtesy Lukáš Banič.

Fixes: #4715
Closes: #4716
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4716
Pull-request-sha: bfad6e6bdfb7d6dd5176deaf30d875f3d0f15e06

Change-Id: Ia8831cc171d131bf3824be8db4fd1d231231bba3
(cherry picked from commit 59e9276f04beef4459571cba4226f9d4eaef6be9)

doc/build/changelog/unreleased_13/4715.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mysql/base.py
test/dialect/mysql/test_on_duplicate.py

diff --git a/doc/build/changelog/unreleased_13/4715.rst b/doc/build/changelog/unreleased_13/4715.rst
new file mode 100644 (file)
index 0000000..190adc1
--- /dev/null
@@ -0,0 +1,6 @@
+.. change::
+    :tags: bug, mysql
+    :tickets: 4715
+
+    Fixed bug where MySQL ON DUPLICATE KEY UPDATE would not accommodate setting
+    a column to the value NULL.  Pull request courtesy Lukáš Banič.
\ No newline at end of file
index eb27ddecb5a3f3d08b9b0a1dd71f4cc0a7a6018e..bfd1693d97c74a7615f93e531ea7f3d2e7167448 100644 (file)
@@ -1230,15 +1230,15 @@ class MySQLCompiler(compiler.SQLCompiler):
                 c for c in self.statement.table.c if c.key not in ordered_keys
             ]
         else:
-            # traverse in table column order
             cols = self.statement.table.c
 
         clauses = []
-        for column in cols:
-            val = on_duplicate.update.get(column.key)
-            if val is None:
-                continue
-            elif elements._is_literal(val):
+        # 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]
+
+            if elements._is_literal(val):
                 val = elements.BindParameter(None, val, type_=column.type)
                 value_text = self.process(val.self_group(), use_schema=False)
             elif isinstance(val, elements.BindParameter) and val.type._isnull:
index 0c6f4792901ab60dae4ba8da183479d6dafd41de..077e5ba98cc719ef96adebfe4f826460e51cfd11 100644 (file)
@@ -62,6 +62,21 @@ class OnDuplicateTest(fixtures.TablesTest):
                 [(1, "ab", "bz", False)],
             )
 
+    def test_on_duplicate_key_update_null(self):
+        foos = self.tables.foos
+        with testing.db.connect() as conn:
+            conn.execute(insert(foos, 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(updated_once=None)
+            result = conn.execute(stmt)
+            eq_(result.inserted_primary_key, [2])
+            eq_(
+                conn.execute(foos.select().where(foos.c.id == 1)).fetchall(),
+                [(1, "b", "bz", None)],
+            )
+
     def test_on_duplicate_key_update_preserve_order(self):
         foos = self.tables.foos
         with testing.db.connect() as conn: