]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Consult compiled paramstyle on execute_compiled
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 15 Mar 2017 14:15:12 +0000 (10:15 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 15 Mar 2017 14:40:30 +0000 (10:40 -0400)
Fixed bug where in the unusual case of passing a
:class:`.Compiled` object directly to :meth:`.Connection.execute`,
the dialect with which the :class:`.Compiled` object were generated
was not consulted for the paramstyle of the string statement, instead
assuming it would match the dialect-level paramstyle, causing
mismatches to occur.

Change-Id: I114e4db2183fbb75bb7c0b0641f5a161855696ee
Fixes: #3938
doc/build/changelog/changelog_12.rst
lib/sqlalchemy/engine/default.py
test/engine/test_execute.py

index 7e6c406da9e1ed407506963ac82568118f098ebf..f2646fdf1c11cfff8c4568083e38425483008c4e 100644 (file)
 .. changelog::
     :version: 1.2.0b1
 
+    .. change:: 3938
+        :tags: bug, engine
+        :tickets: 3938
+
+        Fixed bug where in the unusual case of passing a
+        :class:`.Compiled` object directly to :meth:`.Connection.execute`,
+        the dialect with which the :class:`.Compiled` object were generated
+        was not consulted for the paramstyle of the string statement, instead
+        assuming it would match the dialect-level paramstyle, causing
+        mismatches to occur.
+
     .. change:: 3918
         :tags: bug, ext
         :tickets: 3918
index b8c2d28452c7f4b2fe4ba9eab4c7acff879aa61a..3968663fb4f780bfc474f82ef05ae80883bccf20 100644 (file)
@@ -627,7 +627,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
         # into a dict or list to be sent to the DBAPI's
         # execute() or executemany() method.
         parameters = []
-        if dialect.positional:
+        if compiled.positional:
             for compiled_params in self.compiled_parameters:
                 param = []
                 for key in self.compiled.positiontup:
index 32834f950b8b246211d14ff911a6f7d717d6261b..54a85bf9f51d21ceb3a93e3f35be2b23f71fc3f8 100644 (file)
@@ -19,6 +19,7 @@ from sqlalchemy.engine import result as _result, default
 from sqlalchemy.engine.base import Engine
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing.mock import Mock, call, patch
+from sqlalchemy.testing import mock
 from contextlib import contextmanager
 from sqlalchemy.util import nested
 from sqlalchemy.testing.assertsql import CompiledSQL
@@ -433,6 +434,35 @@ class ExecuteTest(fixtures.TestBase):
                            values(user_name=bindparam('name', None)), [])
         eq_(testing.db.execute(users_autoinc.select()).fetchall(), [(1, None)])
 
+    @testing.only_on("sqlite")
+    def test_execute_compiled_favors_compiled_paramstyle(self):
+        with patch.object(testing.db.dialect, "do_execute") as do_exec:
+            stmt = users.update().values(user_id=1, user_name='foo')
+
+            d1 = default.DefaultDialect(paramstyle="format")
+            d2 = default.DefaultDialect(paramstyle="pyformat")
+
+            testing.db.execute(stmt.compile(dialect=d1))
+            testing.db.execute(stmt.compile(dialect=d2))
+
+            eq_(
+                do_exec.mock_calls, [
+                    call(
+                        mock.ANY,
+                        "UPDATE users SET user_id=%s, user_name=%s",
+                        (1, 'foo'),
+                        mock.ANY
+                    ),
+                    call(
+                        mock.ANY,
+                        "UPDATE users SET user_id=%(user_id)s, "
+                        "user_name=%(user_name)s",
+                       {'user_name': 'foo', 'user_id': 1},
+                        mock.ANY
+                    )
+                ]
+            )
+
     @testing.requires.ad_hoc_engines
     def test_engine_level_options(self):
         eng = engines.testing_engine(options={'execution_options':