summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorR. David Murray <rdmurray@bitdance.com>2010-06-01 01:32:12 +0000
committerR. David Murray <rdmurray@bitdance.com>2010-06-01 01:32:12 +0000
commit3efd48af885a6ed3d8a644bf55959723cb7bc50e (patch)
tree643b2d5233cb4c5480f430dff1e5f9e7d99f636e
parent693101170c4ca1ae40b8ef54f7d3384fbb3f7905 (diff)
downloadcpython-3efd48af885a6ed3d8a644bf55959723cb7bc50e.tar.gz
#8845: expose sqlite3 inTransaction as RO in_transaction Connection attribute.
Patch by R. David Murray, unit tests by Shashwat Anand.
-rw-r--r--Doc/library/sqlite3.rst10
-rw-r--r--Doc/whatsnew/3.2.rst12
-rw-r--r--Lib/sqlite3/test/dbapi.py23
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_sqlite/connection.c2
6 files changed, 50 insertions, 1 deletions
diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst
index ad6a641b97..3db5116573 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 e61ad44f5f..265f9282e5 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 ced6679140..51253d0024 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 50919413d9..b75ff6ce36 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 a65de665cc..68f36fcc93 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 184bdeef93..8bfc9ba656 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}
};