From: Mike Bayer Date: Thu, 4 Nov 2021 17:36:43 +0000 (-0400) Subject: Update "transaction has already begun" language X-Git-Tag: rel_2_0_0b1~668 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fee0855bfe2982927ab21ce7398fa48b90af7ca4;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Update "transaction has already begun" language As future connections will now be autobeginning, there will be more cases where begin() can't be called as well as where isolation level can't be set, which will be surprising as this is a behavioral change for 2.0; additionally, when DBAPI autocommit is set, there isn't actually a DBAPI level transaction in effect even though Connection has a Transaction object. Clarify the language in these two error messages to make it clear that begin() and autobegin are tracking a SQLAlchemy-level Transaction() object, whether or not the DBAPI has actually started a transaction, and that this is the reason rollback() or commit() is required before performing the requsted operation. Additionally make sure the error message mentions "autobegin" as a likely reason this error is being encountered along with what Connection needs the user to do in order to resolve. Change-Id: If8763939eeabc46aa9d9209a56d05ad82b892c5c --- diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index c60a8383fa..5c1a159a69 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -768,7 +768,10 @@ class Connection(Connectable): else: if self._is_future: raise exc.InvalidRequestError( - "a transaction is already begun for this connection" + "This connection has already initialized a SQLAlchemy " + "Transaction() object via begin() or autobegin; can't " + "call begin() here unless rollback() or commit() " + "is called first." ) else: return MarkerTransaction(self) diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 9ec6783b02..b6dae6abc6 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -612,8 +612,10 @@ class DefaultDialect(interfaces.Dialect): if trans_objs: if connection._is_future: raise exc.InvalidRequestError( - "This connection has already begun a transaction; " - "%s may not be altered until transaction end" + "This connection has already initialized a SQLAlchemy " + "Transaction() object via begin() or autobegin; " + "%s may not be altered unless rollback() or commit() " + "is called first." % (", ".join(name for name, obj in trans_objs)) ) else: diff --git a/test/engine/test_transaction.py b/test/engine/test_transaction.py index b8e7edc652..9e61420223 100644 --- a/test/engine/test_transaction.py +++ b/test/engine/test_transaction.py @@ -1568,8 +1568,10 @@ class FutureTransactionTest(fixtures.FutureEngineMixin, fixtures.TablesTest): with testing.db.begin() as conn: assert_raises_message( exc.InvalidRequestError, - "This connection has already begun a transaction; " - "isolation_level may not be altered until transaction end", + r"This connection has already initialized a SQLAlchemy " + r"Transaction\(\) object via begin\(\) or autobegin; " + r"isolation_level may not be altered unless rollback\(\) or " + r"commit\(\) is called first.", conn.execution_options, isolation_level="AUTOCOMMIT", ) @@ -1582,8 +1584,10 @@ class FutureTransactionTest(fixtures.FutureEngineMixin, fixtures.TablesTest): assert_raises_message( exc.InvalidRequestError, - "This connection has already begun a transaction; " - "isolation_level may not be altered until transaction end", + r"This connection has already initialized a SQLAlchemy " + r"Transaction\(\) object via begin\(\) or autobegin; " + r"isolation_level may not be altered unless rollback\(\) or " + r"commit\(\) is called first.", conn.execution_options, isolation_level="AUTOCOMMIT", ) @@ -1822,7 +1826,10 @@ class FutureTransactionTest(fixtures.FutureEngineMixin, fixtures.TablesTest): assert_raises_message( exc.InvalidRequestError, - "a transaction is already begun for this connection", + r"This connection has already initialized a SQLAlchemy " + r"Transaction\(\) object via begin\(\) or autobegin; can't " + r"call begin\(\) here unless rollback\(\) or commit\(\) is " + r"called first.", conn.begin, )