From 455ef041871fe944a0f3b7b1f5073663f20a99be Mon Sep 17 00:00:00 2001
From: Patrick Cloke <clokep@users.noreply.github.com>
Date: Tue, 7 Nov 2023 14:02:09 -0500
Subject: [PATCH] Avoid updating the same rows multiple times with
 simple_update_many_txn. (#16609)

simple_update_many_txn had a bug in it which would cause each
update to be applied twice.
---
 changelog.d/16609.bugfix    | 1 +
 synapse/storage/database.py | 5 +----
 tests/storage/test_base.py  | 4 ++--
 3 files changed, 4 insertions(+), 6 deletions(-)
 create mode 100644 changelog.d/16609.bugfix

diff --git a/changelog.d/16609.bugfix b/changelog.d/16609.bugfix
new file mode 100644
index 0000000000..a52d395cd3
--- /dev/null
+++ b/changelog.d/16609.bugfix
@@ -0,0 +1 @@
+Fix a long-standing bug where some queries updated the same row twice. Introduced in Synapse 1.57.0.
diff --git a/synapse/storage/database.py b/synapse/storage/database.py
index 792f2e7cdf..f50a4ce2fc 100644
--- a/synapse/storage/database.py
+++ b/synapse/storage/database.py
@@ -2060,10 +2060,7 @@ class DatabasePool:
 
         # List of tuples of (value values, then key values)
         # (This matches the order needed for the query)
-        args = [tuple(x) + tuple(y) for x, y in zip(value_values, key_values)]
-
-        for ks, vs in zip(key_values, value_values):
-            args.append(tuple(vs) + tuple(ks))
+        args = [tuple(vv) + tuple(kv) for vv, kv in zip(value_values, key_values)]
 
         # 'col1 = ?, col2 = ?, ...'
         set_clause = ", ".join(f"{n} = ?" for n in value_names)
diff --git a/tests/storage/test_base.py b/tests/storage/test_base.py
index de4fcfe026..f34b6b2dcf 100644
--- a/tests/storage/test_base.py
+++ b/tests/storage/test_base.py
@@ -363,12 +363,12 @@ class SQLBaseStoreTestCase(unittest.TestCase):
             self.mock_execute_batch.assert_called_once_with(
                 self.mock_txn,
                 "UPDATE tablename SET col3 = ? WHERE col1 = ? AND col2 = ?",
-                [("val3", "val1", "val2"), ("val3", "val1", "val2")],
+                [("val3", "val1", "val2")],
             )
         else:
             self.mock_txn.executemany.assert_called_once_with(
                 "UPDATE tablename SET col3 = ? WHERE col1 = ? AND col2 = ?",
-                [("val3", "val1", "val2"), ("val3", "val1", "val2")],
+                [("val3", "val1", "val2")],
             )
 
         # key_values and value_values must be the same length.
-- 
GitLab