]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fix psycopg2 pre_ping with autocommit
authorFederico Caselli <cfederico87@gmail.com>
Mon, 11 Apr 2022 21:19:16 +0000 (23:19 +0200)
committerFederico Caselli <cfederico87@gmail.com>
Wed, 13 Apr 2022 20:29:55 +0000 (22:29 +0200)
Fixed an issue what would cause autocommit mode to be reset
when using pre_ping in conjunction engine level autocommit
on the psycopg2 driver.

Fixes: #7930
Change-Id: I4cccaf1b7f8cbacd853689458080784114fcc390

doc/build/changelog/unreleased_14/7930.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/_psycopg_common.py
lib/sqlalchemy/dialects/postgresql/psycopg.py
test/dialect/postgresql/test_dialect.py

diff --git a/doc/build/changelog/unreleased_14/7930.rst b/doc/build/changelog/unreleased_14/7930.rst
new file mode 100644 (file)
index 0000000..bf4f998
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, postgresql
+    :tickets: 7930
+
+    Fixed an issue what would cause autocommit mode to be reset
+    when using pre_ping in conjunction engine level autocommit
+    on the psycopg2 driver.
index 7f936fefbfeeae369c9ff39aeaba4ddf948adca3..e7d5e77c393d890daf8a764d9d79000589881f32 100644 (file)
@@ -170,15 +170,17 @@ class _PGDialect_common_psycopg(PGDialect):
 
     def do_ping(self, dbapi_connection):
         cursor = None
+        before_autocommit = dbapi_connection.autocommit
         try:
-            self._do_autocommit(dbapi_connection, True)
+            if not before_autocommit:
+                self._do_autocommit(dbapi_connection, True)
             cursor = dbapi_connection.cursor()
             try:
                 cursor.execute(self._dialect_specific_select_one)
             finally:
                 cursor.close()
-                if not dbapi_connection.closed:
-                    self._do_autocommit(dbapi_connection, False)
+                if not before_autocommit and not dbapi_connection.closed:
+                    self._do_autocommit(dbapi_connection, before_autocommit)
         except self.dbapi.Error as err:
             if self.is_disconnect(err, dbapi_connection, cursor):
                 return False
index 9207221df6d706b2ac252298d9e0a00affe3106c..b811d1cabbc41c8a162db5be445a88d1c5cf49f1 100644 (file)
@@ -385,12 +385,14 @@ class PGDialect_psycopg(_PGDialect_common_psycopg):
             != self._psycopg_TransactionStatus.IDLE
         ):
             dbapi_conn.rollback()
-        before = dbapi_conn.autocommit
+        before_autocommit = dbapi_conn.autocommit
         try:
-            self._do_autocommit(dbapi_conn, True)
+            if not before_autocommit:
+                self._do_autocommit(dbapi_conn, True)
             dbapi_conn.execute(command)
         finally:
-            self._do_autocommit(dbapi_conn, before)
+            if not before_autocommit:
+                self._do_autocommit(dbapi_conn, before_autocommit)
 
     def do_rollback_twophase(
         self, connection, xid, is_prepared=True, recover=False
index fb3a522fc12693337fb55f27a6547f8e2ed00796..0093eb5ba7a7b0b5100b199bac5f57df9dd00189 100644 (file)
@@ -1068,6 +1068,23 @@ class MiscBackendTest(
                 dbapi_conn.rollback()
             eq_(val, "off")
 
+    @testing.combinations((True,), (False,), argnames="autocommit")
+    def test_autocommit_pre_ping(self, testing_engine, autocommit):
+        engine = testing_engine(
+            options={
+                "isolation_level": "AUTOCOMMIT"
+                if autocommit
+                else "SERIALIZABLE",
+                "pool_pre_ping": True,
+            }
+        )
+        for i in range(4):
+            with engine.connect() as conn:
+                conn.execute(text("select 1")).scalar()
+
+                dbapi_conn = conn.connection.dbapi_connection
+                eq_(dbapi_conn.autocommit, autocommit)
+
     def test_deferrable_flag_engine(self):
         engine = engines.testing_engine(
             options={