update executemany() enhancement breaks versioning

Issue #3556 resolved
Mike Bayer repo owner created an issue
diff --git a/test/orm/test_versioning.py b/test/orm/test_versioning.py
index d46799c..67d580e 100644
--- a/test/orm/test_versioning.py
+++ b/test/orm/test_versioning.py
@@ -952,6 +952,46 @@ class ServerVersioningTest(fixtures.MappedTest):
             )
         self.assert_sql_execution(testing.db, sess.flush, *statements)

+    def test_multi_update(self):
+        sess = self._fixture()
+
+        f1 = self.classes.Foo(value='f1')
+        f2 = self.classes.Foo(value='f2')
+        f3 = self.classes.Foo(value='f3')
+        sess.add_all([f1, f2, f3])
+        sess.flush()
+
+        f1.value = 'f1a'
+        f2.value = 'f2a'
+        f3.value = 'f3a'
+
+        statements = [
+            # note that the assertsql tests the rule against
+            # "default" - on a "returning" backend, the statement
+            # includes "RETURNING"
+            CompiledSQL(
+                "UPDATE version_table SET version_id=2, value=:value "
+                "WHERE version_table.id = :version_table_id AND "
+                "version_table.version_id = :version_table_version_id",
+                lambda ctx: [
+                    {
+                        "version_table_id": 1,
+                        "version_table_version_id": 1, "value": "f2"}]
+            )
+        ]
+        if not testing.db.dialect.implicit_returning:
+            # DBs without implicit returning, we must immediately
+            # SELECT for the new version id
+            statements.append(
+                CompiledSQL(
+                    "SELECT version_table.version_id "
+                    "AS version_table_version_id "
+                    "FROM version_table WHERE version_table.id = :param_1",
+                    lambda ctx: [{"param_1": 1}]
+                )
+            )
+        self.assert_sql_execution(testing.db, sess.flush, *statements)
+
     def test_delete_col(self):
         sess = self._fixture()

PG:

#!


File "/Users/classic/dev/sqlalchemy/test/../lib/sqlalchemy/engine/result.py", line 1026, in fetchone
    self.cursor, self.context)
  File "/Users/classic/dev/sqlalchemy/test/../lib/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
    exc_info
  File "/Users/classic/dev/sqlalchemy/test/../lib/sqlalchemy/util/compat.py", line 199, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb)
  File "/Users/classic/dev/sqlalchemy/test/../lib/sqlalchemy/engine/result.py", line 1017, in fetchone
    row = self._fetchone_impl()
  File "/Users/classic/dev/sqlalchemy/test/../lib/sqlalchemy/engine/result.py", line 898, in _fetchone_impl
    return self.cursor.fetchone()
ProgrammingError: (psycopg2.ProgrammingError) no results to fetch

Comments (3)

  1. Mike Bayer reporter
    diff --git a/lib/sqlalchemy/orm/persistence.py b/lib/sqlalchemy/orm/persistence.py
    index d89a93d..71d62c7 100644
    --- a/lib/sqlalchemy/orm/persistence.py
    +++ b/lib/sqlalchemy/orm/persistence.py
    @@ -645,7 +645,7 @@ def _emit_update_statements(base_mapper, uowtransaction,
             assert_singlerow = connection.dialect.supports_sane_rowcount
             assert_multirow = assert_singlerow and \
                 connection.dialect.supports_sane_multi_rowcount
    -        allow_multirow = not needs_version_id or assert_multirow
    +        allow_multirow = assert_multirow and not needs_version_id
    
             if hasvalue:
                 for state, state_dict, params, mapper, \
    
  2. Mike Bayer reporter
    • Fixed regression in 1.0 where new feature of using "executemany" for UPDATE statements in the ORM (e.g. :ref:feature_updatemany) would break on Postgresql and other RETURNING backends when using server-side version generation schemes, as the server side value is retrieved via RETURNING which is not supported with executemany. fixes #3556

    → <<cset 1e0afd584c12>>

  3. Mike Bayer reporter
    • Fixed regression in 1.0 where new feature of using "executemany" for UPDATE statements in the ORM (e.g. :ref:feature_updatemany) would break on Postgresql and other RETURNING backends when using server-side version generation schemes, as the server side value is retrieved via RETURNING which is not supported with executemany. fixes #3556

    → <<cset 4f54607923a1>>

  4. Log in to comment