From d35251dc19b6f2d1cacbb622a578c81f33d8553a Mon Sep 17 00:00:00 2001 From: "R. David Murray" Date: Tue, 1 Jun 2010 01:32:12 +0000 Subject: #8845: expose sqlite3 inTransaction as RO in_transaction Connection attribute. Patch by R. David Murray, unit tests by Shashwat Anand. --- Doc/library/sqlite3.rst | 10 +++++++++- Doc/whatsnew/3.2.rst | 12 ++++++++++++ Lib/sqlite3/test/dbapi.py | 23 +++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/_sqlite/connection.c | 2 ++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index ad6a641..3db5116 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -227,6 +227,13 @@ Connection Objects one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". See section :ref:`sqlite3-controlling-transactions` for a more detailed explanation. +.. attribute:: Connection.in_transaction + + .. versionadded:: 3.2 + + :cont:`True` if a transaction is active (there are uncommitted changes), + :const:`False` otherwise. Read-only attribute. + .. method:: Connection.cursor([cursorClass]) @@ -806,7 +813,8 @@ So if you are within a transaction and issue a command like ``CREATE TABLE before executing that command. There are two reasons for doing that. The first is that some of these commands don't work within transactions. The other reason is that sqlite3 needs to keep track of the transaction state (if a transaction -is active or not). +is active or not). The current transaction state is exposed through the +:attr:`Connection.in_transaction` attribute of the connection object. You can control which kind of ``BEGIN`` statements sqlite3 implicitly executes (or none at all) via the *isolation_level* parameter to the :func:`connect` diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index e61ad44..265f928 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -100,6 +100,18 @@ New, Improved, and Deprecated Modules (Contributed by Tarek Ziade.) +* The *sqlite3* module has some new features: + + * XXX *enable_load_extension* + + * XXX *load_extension* + + * New :class:`~sqlite3.Connection` attribute + :attr:`~sqlite3.Connection.in_transaction` is :const:`True` when there + are uncommitted changes, and :const:`False` otherwise. (Contributed + by R. David Murray and Shashwat Anand, :issue:`8845`.) + + Multi-threading =============== diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index ced6679..51253d0 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -84,6 +84,7 @@ class ModuleTests(unittest.TestCase): "NotSupportedError is not a subclass of DatabaseError") class ConnectionTests(unittest.TestCase): + def setUp(self): self.cx = sqlite.connect(":memory:") cu = self.cx.cursor() @@ -140,6 +141,28 @@ class ConnectionTests(unittest.TestCase): self.assertEqual(self.cx.ProgrammingError, sqlite.ProgrammingError) self.assertEqual(self.cx.NotSupportedError, sqlite.NotSupportedError) + def CheckInTransaction(self): + # Can't use db from setUp because we want to test initial state. + cx = sqlite.connect(":memory:") + cu = cx.cursor() + self.assertEqual(cx.in_transaction, False) + cu.execute("create table transactiontest(id integer primary key, name text)") + self.assertEqual(cx.in_transaction, False) + cu.execute("insert into transactiontest(name) values (?)", ("foo",)) + self.assertEqual(cx.in_transaction, True) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, True) + cx.commit() + self.assertEqual(cx.in_transaction, False) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, False) + + def CheckInTransactionRO(self): + with self.assertRaises(AttributeError): + self.cx.in_transaction = True + class CursorTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") diff --git a/Misc/ACKS b/Misc/ACKS index 5091941..b75ff6c 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -19,6 +19,7 @@ Billy G. Allie Kevin Altis Joe Amenta Mark Anacker +Shashwat Anand Anders Andersen John Anderson Erik Andersén diff --git a/Misc/NEWS b/Misc/NEWS index a65de66..68f36fc 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -398,6 +398,9 @@ C-API Library ------- +- Issue #8845: sqlite3 Connection objects now have a read-only in_transaction + attribute that is True iff there are uncommitted changes. + - Issue #1289118: datetime.timedelta objects can now be multiplied by float and divided by float and int objects. Results are rounded to the nearest multiple of timedelta.resolution with ties resolved using round-half-to-even diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 184bdee..8bfc9ba 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -23,6 +23,7 @@ #include "cache.h" #include "module.h" +#include "structmember.h" #include "connection.h" #include "statement.h" #include "cursor.h" @@ -1551,6 +1552,7 @@ static struct PyMemberDef connection_members[] = {"NotSupportedError", T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), READONLY}, {"row_factory", T_OBJECT, offsetof(pysqlite_Connection, row_factory)}, {"text_factory", T_OBJECT, offsetof(pysqlite_Connection, text_factory)}, + {"in_transaction", T_BOOL, offsetof(pysqlite_Connection, inTransaction), READONLY}, {NULL} }; -- cgit v0.12