Commit 94b2c942 authored by Tim Peters's avatar Tim Peters

Tentative fix.

parent 5a09264e
......@@ -70,7 +70,9 @@ merge_error(int p1, int p2, int p3, int reason)
* However, it's not OK for s2 and s3 to, between them, end up deleting all
* the keys. This is a higher-level constraint, due to that the caller of
* bucket_merge() doesn't have enough info to unlink the resulting empty
* bucket from its BTree correctly.
* bucket from its BTree correctly. It's also not OK if s2 or s3 are empty,
* because the transaction that emptied the bucket unlinked the bucket from
* the tree, and nothing we do here can get it linked back in again.
*
* Key insertion: s2 or s3 can add a new key, provided the other transaction
* doesn't insert the same key. It's not OK even if they insert the same
......@@ -115,6 +117,13 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
if (i3.next(&i3) < 0)
goto err;
/* If either "after" bucket was empty, punt. */
if (i2.position < 0 || i3.position < 0)
{
merge_error(i1.position, i2.position, i3.position, 12);
goto err;
}
/* Consult zodb/btrees/interfaces.py for the meaning of the last
* argument passed to merge_error().
*/
......
......@@ -178,7 +178,7 @@ class MappingBase(Base):
test_merge(base, b1, b2, bm, 'merge insert from empty')
def testMergeEmptyAndFill(self):
def testFailMergeEmptyAndFill(self):
base, b1, b2, bm, e1, e2, items = self._setupConflict()
b1.clear()
......@@ -186,7 +186,7 @@ class MappingBase(Base):
b2.update(e2)
bm.update(e2)
test_merge(base, b1, b2, bm, 'merge insert from empty')
test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1)
def testMergeEmpty(self):
base, b1, b2, bm, e1, e2, items = self._setupConflict()
......@@ -275,7 +275,7 @@ class SetTests(Base):
test_merge(base, b1, b2, bm, 'merge insert from empty')
def testMergeEmptyAndFill(self):
def testFailMergeEmptyAndFill(self):
base, b1, b2, bm, e1, e2, items = self._setupConflict()
b1.clear()
......@@ -283,7 +283,7 @@ class SetTests(Base):
b2.update(e2)
bm.update(e2)
test_merge(base, b1, b2, bm, 'merge insert from empty')
test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1)
def testMergeEmpty(self):
base, b1, b2, bm, e1, e2, items = self._setupConflict()
......@@ -810,7 +810,6 @@ class NastyConfict(Base, TestCase):
self.assert_(str(detail).startswith('database conflict error'))
transaction.abort()
else:
print list(copy.items())
self.fail("expected ConflictError")
......
......@@ -187,6 +187,9 @@ class BTreesConflictError(ConflictError):
# 11; conflicting changes in an internal BTree node
'Conflicting changes in an internal BTree node',
# 12; i2 or i3 was empty
'Empty bucket in a transaction',
]
def __init__(self, p1, p2, p3, reason):
......
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