]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed 1.0 regression where the eager fetch of cursor.rowcount was
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 5 Jan 2016 15:25:36 +0000 (10:25 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 5 Jan 2016 15:25:36 +0000 (10:25 -0500)
no longer called for an UPDATE or DELETE statement emitted via plain
text or via the :func:`.text` construct, affecting those drivers
that erase cursor.rowcount once the cursor is closed such as SQL
Server ODBC and Firebird drivers.
fixes #3622

doc/build/changelog/changelog_10.rst
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/engine/default.py
lib/sqlalchemy/sql/compiler.py
test/sql/test_rowcount.py

index 25592a3b1ebaae54b10c31e27a9c3f822f6e2c35..782af7320bccdcd20cfe45b8b36efb7a0ee0e73b 100644 (file)
     .. include:: changelog_07.rst
         :start-line: 5
 
+.. changelog::
+    :version: 1.0.12
+    :released:
+
+    .. change::
+        :tags: bug, mssql, firebird
+        :versions: 1.1.0b1
+        :tickets: 3622
+
+        Fixed 1.0 regression where the eager fetch of cursor.rowcount was
+        no longer called for an UPDATE or DELETE statement emitted via plain
+        text or via the :func:`.text` construct, affecting those drivers
+        that erase cursor.rowcount once the cursor is closed such as SQL
+        Server ODBC and Firebird drivers.
+
+
 .. changelog::
     :version: 1.0.11
     :released: December 22, 2015
index eaa435d45dbf1a7bd75a8638d7f91f983024d5f9..31e253eedd5622af68a310dacb41c958e111c928 100644 (file)
@@ -1155,7 +1155,7 @@ class Connection(Connectable):
         if context.compiled:
             context.post_exec()
 
-        if context.is_crud:
+        if context.is_crud or context.is_text:
             result = context._setup_crud_result_proxy()
         else:
             result = context.get_result_proxy()
index 9a7b80bfdc3194cf0c8af04b5c9fd3bda4dab2cf..87278c2bef2f96b82a66a2d7be35504ed2c3c212 100644 (file)
@@ -467,6 +467,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
     isupdate = False
     isdelete = False
     is_crud = False
+    is_text = False
     isddl = False
     executemany = False
     compiled = None
@@ -543,6 +544,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
         self.isinsert = compiled.isinsert
         self.isupdate = compiled.isupdate
         self.isdelete = compiled.isdelete
+        self.is_text = compiled.isplaintext
 
         if not parameters:
             self.compiled_parameters = [compiled.construct_params()]
@@ -622,6 +624,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
         self.root_connection = connection
         self._dbapi_connection = dbapi_connection
         self.dialect = connection.dialect
+        self.is_text = True
 
         # plain text statement
         self.execution_options = connection._execution_options
index 6766c99b7dbf4ac44ec66849312dc64ffe394577..2ca549267899f72655f0d963d2014d797df6ec2b 100644 (file)
@@ -286,6 +286,7 @@ class _CompileLabel(visitors.Visitable):
     def self_group(self, **kw):
         return self
 
+
 class SQLCompiler(Compiled):
 
     """Default implementation of Compiled.
@@ -305,6 +306,8 @@ class SQLCompiler(Compiled):
     INSERT/UPDATE/DELETE
     """
 
+    isplaintext = False
+
     returning = None
     """holds the "returning" collection of columns if
     the statement is CRUD and defines returning columns
@@ -688,6 +691,9 @@ class SQLCompiler(Compiled):
             else:
                 return self.bindparam_string(name, **kw)
 
+        if not self.stack:
+            self.isplaintext = True
+
         # un-escape any \:params
         return BIND_PARAMS_ESC.sub(
             lambda m: m.group(1),
index 46e10e19273fabb49a994f3e5dc25bf0faa9cfde..110f3639fd43cd647ad62f716971d1c98717f0a0 100644 (file)
@@ -1,6 +1,7 @@
 from sqlalchemy import *
 from sqlalchemy.testing import fixtures, AssertsExecutionResults
 from sqlalchemy import testing
+from sqlalchemy.testing import eq_
 
 
 class FoundRowsTest(fixtures.TestBase, AssertsExecutionResults):
@@ -65,6 +66,22 @@ class FoundRowsTest(fixtures.TestBase, AssertsExecutionResults):
         print("expecting 3, dialect reports %s" % r.rowcount)
         assert r.rowcount == 3
 
+    def test_raw_sql_rowcount(self):
+        # test issue #3622, make sure eager rowcount is called for text
+        with testing.db.connect() as conn:
+            result = conn.execute(
+                "update employees set department='Z' where department='C'")
+            eq_(result.rowcount, 3)
+
+    def test_text_rowcount(self):
+        # test issue #3622, make sure eager rowcount is called for text
+        with testing.db.connect() as conn:
+            result = conn.execute(
+                text(
+                    "update employees set department='Z' "
+                    "where department='C'"))
+            eq_(result.rowcount, 3)
+
     def test_delete_rowcount(self):
         # WHERE matches 3, 3 rows deleted
         department = employees_table.c.department