Moved the "rollback" which occurs during dialect initialization so that it
occurs after additional dialect-specific initialize steps, in particular
those of the psycopg2 dialect which would inadvertently leave transactional
state on the first new connection, which could interfere with some
psycopg2-specific APIs which require that no transaction is started. Pull
request courtesy Matthew Wilkes.
Fixes: #4663
Closes: #4664
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4664
Pull-request-sha:
e544fe671d443ed06b210ba1cd1d7ba9c5653831
Change-Id: If40a15a1679b4eec0b8b8222f678697728009c30
(cherry picked from commit
f601791a914d3181252493800871c458ad6c46d1)
--- /dev/null
+.. change::
+ :tags: bug, engine, postgresql
+ :tickets: 4663
+
+ Moved the "rollback" which occurs during dialect initialization so that it
+ occurs after additional dialect-specific initialize steps, in particular
+ those of the psycopg2 dialect which would inadvertently leave transactional
+ state on the first new connection, which could interfere with some
+ psycopg2-specific APIs which require that no transaction is started. Pull
+ request courtesy Matthew Wilkes.
+
):
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.
)
c._execution_options = util.immutabledict()
dialect.initialize(c)
+ dialect.do_rollback(c.connection)
event.listen(pool, "first_connect", first_connect, once=True)
from sqlalchemy.testing.assertions import AssertsCompiledSQL
from sqlalchemy.testing.assertions import AssertsExecutionResults
from sqlalchemy.testing.assertions import eq_
+from sqlalchemy.testing.assertions import ne_
from sqlalchemy.testing.mock import Mock
from ...engine import test_execute
"c %s NOT NULL" % expected,
)
+ @testing.requires.psycopg2_compatibility
+ def test_initial_transaction_state(self):
+ from psycopg2.extensions import STATUS_IN_TRANSACTION
+
+ engine = engines.testing_engine()
+ with engine.connect() as conn:
+ ne_(conn.connection.status, STATUS_IN_TRANSACTION)
+
class AutocommitTextTest(test_execute.AutocommitTextTest):
__only_on__ = "postgresql"
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)