]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fixes: #4663 : Move the explicit in `DefaultDialect` initialization to 4664/head
authorMatthew Wilkes <git@matthewwilkes.name>
Mon, 6 May 2019 15:52:49 +0000 (16:52 +0100)
committerMatthew Wilkes <git@matthewwilkes.name>
Thu, 9 May 2019 18:07:56 +0000 (11:07 -0700)
the pool's `first_connect` handler. This ensures that all dialects will
always roll back after completing their call to `initialize(conn)`.
This has the effect of ensuring that the first connection to a postgresql
database is in the same state as all subsequent connections, i.e. not with
an implicit transaction open from the feature detection queries.

doc/build/changelog/unreleased_14/4663.rst [new file with mode: 0644]
lib/sqlalchemy/engine/default.py
lib/sqlalchemy/engine/strategies.py
test/dialect/postgresql/test_dialect.py
test/engine/test_execute.py

diff --git a/doc/build/changelog/unreleased_14/4663.rst b/doc/build/changelog/unreleased_14/4663.rst
new file mode 100644 (file)
index 0000000..8f214e7
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+   :tags: bug, orm, postgresql
+   :tickets: 4663
+
+   Added additional rollback during engine creation for postgresql
+   engines that prevents the first connection starting having an
+   implicit transaction created earlier than usual.
\ No newline at end of file
index 51e2c4603b04746b1a1039a592d09653536cc143..f6c30cbf47a3a915291c1ff39e7d09b61a0da519 100644 (file)
@@ -312,8 +312,6 @@ class DefaultDialect(interfaces.Dialect):
         ):
             self._description_decoder = self.description_encoding = None
 
-        self.do_rollback(connection.connection)
-
     def on_connect(self):
         """return a callable which sets up a newly created DBAPI connection.
 
index e367ef890423f2ad554d09f3bbae4b86c0ed7298..d3a22e5ac8bef8ac139761befbd37286396a2752 100644 (file)
@@ -197,6 +197,7 @@ class DefaultEngineStrategy(EngineStrategy):
                 )
                 c._execution_options = util.immutabledict()
                 dialect.initialize(c)
+                dialect.do_rollback(c.connection)
 
             event.listen(pool, "first_connect", first_connect, once=True)
 
index c68af2abb89d441749877f10f983e43dfaaed5c5..e49374bcb296455ebd7f960c5095e0b5203ed549 100644 (file)
@@ -500,6 +500,12 @@ class MiscBackendTest(
                 "c %s NOT NULL" % expected,
             )
 
+    def test_initial_transaction_state(self):
+        from psycopg2.extensions import STATUS_IN_TRANSACTION
+        engine = engines.testing_engine()
+        with engine.connect() as conn:
+            assert conn.connection.status != STATUS_IN_TRANSACTION
+
 
 class AutocommitTextTest(test_execute.AutocommitTextTest):
     __only_on__ = "postgresql"
index e18cdfad4cf8758490414e55ba1f1b86e8122b7a..480da712214eaf2bf1afb424d279235e96a90f38 100644 (file)
@@ -660,6 +660,15 @@ class ExecuteTest(fixtures.TestBase):
         eq_(conn._execution_options, {"autocommit": True})
         conn.close()
 
+    def test_initialize_rollback(self):
+        """test a rollback happens during first connect"""
+        eng = create_engine(testing.db.url)
+        with patch.object(eng.dialect, "do_rollback") as do_rollback:
+            assert do_rollback.call_count == 0
+            connection = eng.connect()
+            assert do_rollback.call_count == 1
+        connection.close()
+
     @testing.requires.ad_hoc_engines
     def test_dialect_init_uses_options(self):
         eng = create_engine(testing.db.url)