Commit bfad323e authored by Tim Peters's avatar Tim Peters

Raise ConnectionStateError if an attempt to close a connection

is made while the connection has a pending subtransaction.
parent c9da918d
...@@ -2,6 +2,20 @@ What's new in ZODB3 3.3 ? ...@@ -2,6 +2,20 @@ What's new in ZODB3 3.3 ?
========================= =========================
Release date: DD-MMM-YYYY Release date: DD-MMM-YYYY
Connection
----------
ZODB intends to raise ConnnectionStateError if an attempt is made to
close a connection while modifications are pending (the connection is
involved in a transaction that hasn't been abort()'ed or commit()'ed).
It was missing the case where the only pending modifications were made
in subtransactions. This has been fixed. If an attempt to close a
connection with pending subtransactions is made now,
ConnnectionStateError: Cannot close a connection with a pending subtransaction
is raised.
transaction transaction
----------- -----------
......
...@@ -540,6 +540,12 @@ class Connection(ExportImport, object): ...@@ -540,6 +540,12 @@ class Connection(ExportImport, object):
raise ConnectionStateError("Cannot close a connection joined to " raise ConnectionStateError("Cannot close a connection joined to "
"a transaction") "a transaction")
if self._tmp is not None:
# There are no direct modifications pending, but a subtransaction
# is pending.
raise ConnectionStateError("Cannot close a connection with a "
"pending subtransaction")
if self._cache is not None: if self._cache is not None:
self._cache.incrgc() # This is a good time to do some GC self._cache.incrgc() # This is a good time to do some GC
......
...@@ -264,7 +264,7 @@ class UserMethodTests(unittest.TestCase): ...@@ -264,7 +264,7 @@ class UserMethodTests(unittest.TestCase):
>>> transaction.commit() >>> transaction.commit()
>>> cn.close() >>> cn.close()
Opening, making a change, committing, and aborting is fine. Opening, making a change, and aborting is fine.
>>> cn = db.open() >>> cn = db.open()
>>> cn.root()['a'] = 1 >>> cn.root()['a'] = 1
>>> transaction.abort() >>> transaction.abort()
...@@ -272,7 +272,7 @@ class UserMethodTests(unittest.TestCase): ...@@ -272,7 +272,7 @@ class UserMethodTests(unittest.TestCase):
But trying to close with a change pending complains. But trying to close with a change pending complains.
>>> cn = db.open() >>> cn = db.open()
>>> cn.root()['a'] = 1 >>> cn.root()['a'] = 10
>>> cn.close() >>> cn.close()
Traceback (most recent call last): Traceback (most recent call last):
... ...
...@@ -281,7 +281,41 @@ class UserMethodTests(unittest.TestCase): ...@@ -281,7 +281,41 @@ class UserMethodTests(unittest.TestCase):
This leaves the connection as it was, so we can still commit This leaves the connection as it was, so we can still commit
the change. the change.
>>> transaction.commit() >>> transaction.commit()
>>> cn2 = db.open()
>>> cn2.root()['a']
10
>>> cn.close(); cn2.close()
Bug: We weren't catching the case where the only changes pending
were in a subtransaction.
>>> cn = db.open()
>>> cn.root()['a'] = 100
>>> transaction.commit(True)
>>> cn.close() # this was succeeding
Traceback (most recent call last):
...
ConnectionStateError: Cannot close a connection with a pending subtransaction
Again this leaves the connection as it was.
>>> transaction.commit()
>>> cn2 = db.open()
>>> cn2.root()['a']
100
>>> cn.close(); cn2.close()
Make sure we can still close a connection after aborting a pending
subtransaction.
>>> cn = db.open()
>>> cn.root()['a'] = 1000
>>> transaction.commit(True)
>>> cn.root()['a']
1000
>>> transaction.abort()
>>> cn.root()['a']
100
>>> cn.close() >>> cn.close()
>>> db.close()
""" """
def test_onCloseCallbacks(self): def test_onCloseCallbacks(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment