[Checkins] SVN: relstorage/trunk/ In rare circumstances, ZODB can legitimately commit an object twice in a
Shane Hathaway
shane at hathawaymix.org
Wed Jan 28 20:58:44 EST 2009
Log message for revision 95361:
In rare circumstances, ZODB can legitimately commit an object twice in a
single transaction. Fixed RelStorage to accept that.
Changed:
U relstorage/trunk/CHANGES.txt
U relstorage/trunk/relstorage/adapters/mysql.py
U relstorage/trunk/relstorage/adapters/oracle.py
U relstorage/trunk/relstorage/adapters/postgresql.py
U relstorage/trunk/relstorage/tests/reltestbase.py
-=-
Modified: relstorage/trunk/CHANGES.txt
===================================================================
--- relstorage/trunk/CHANGES.txt 2009-01-28 23:09:52 UTC (rev 95360)
+++ relstorage/trunk/CHANGES.txt 2009-01-29 01:58:44 UTC (rev 95361)
@@ -2,6 +2,8 @@
Next Release
------------
+- In rare circumstances, ZODB can legitimately commit an object twice in a
+ single transaction. Fixed RelStorage to accept that.
Version 1.1.2 (2009-01-27)
Modified: relstorage/trunk/relstorage/adapters/mysql.py
===================================================================
--- relstorage/trunk/relstorage/adapters/mysql.py 2009-01-28 23:09:52 UTC (rev 95360)
+++ relstorage/trunk/relstorage/adapters/mysql.py 2009-01-29 01:58:44 UTC (rev 95361)
@@ -464,7 +464,7 @@
def store_temp(self, cursor, oid, prev_tid, md5sum, data):
"""Store an object in the temporary table."""
stmt = """
- INSERT INTO temp_store (zoid, prev_tid, md5, state)
+ REPLACE INTO temp_store (zoid, prev_tid, md5, state)
VALUES (%s, %s, %s, %s)
"""
cursor.execute(stmt, (oid, prev_tid, md5sum, MySQLdb.Binary(data)))
Modified: relstorage/trunk/relstorage/adapters/oracle.py
===================================================================
--- relstorage/trunk/relstorage/adapters/oracle.py 2009-01-28 23:09:52 UTC (rev 95360)
+++ relstorage/trunk/relstorage/adapters/oracle.py 2009-01-29 01:58:44 UTC (rev 95361)
@@ -536,6 +536,7 @@
def store_temp(self, cursor, oid, prev_tid, md5sum, data):
"""Store an object in the temporary table."""
+ cursor.execute("DELETE FROM temp_store WHERE zoid = :oid", oid=oid)
if len(data) <= 2000:
# Send data inline for speed. Oracle docs say maximum size
# of a RAW is 2000 bytes. cx_Oracle.BINARY corresponds with RAW.
Modified: relstorage/trunk/relstorage/adapters/postgresql.py
===================================================================
--- relstorage/trunk/relstorage/adapters/postgresql.py 2009-01-28 23:09:52 UTC (rev 95360)
+++ relstorage/trunk/relstorage/adapters/postgresql.py 2009-01-29 01:58:44 UTC (rev 95361)
@@ -415,10 +415,11 @@
def store_temp(self, cursor, oid, prev_tid, md5sum, data):
"""Store an object in the temporary table."""
stmt = """
+ DELETE FROM temp_store WHERE zoid = %s;
INSERT INTO temp_store (zoid, prev_tid, md5, state)
VALUES (%s, %s, %s, decode(%s, 'base64'))
"""
- cursor.execute(stmt, (oid, prev_tid, md5sum, encodestring(data)))
+ cursor.execute(stmt, (oid, oid, prev_tid, md5sum, encodestring(data)))
def replace_temp(self, cursor, oid, prev_tid, md5sum, data):
"""Replace an object in the temporary table."""
Modified: relstorage/trunk/relstorage/tests/reltestbase.py
===================================================================
--- relstorage/trunk/relstorage/tests/reltestbase.py 2009-01-28 23:09:52 UTC (rev 95360)
+++ relstorage/trunk/relstorage/tests/reltestbase.py 2009-01-29 01:58:44 UTC (rev 95361)
@@ -21,6 +21,7 @@
from ZODB.DB import DB
from ZODB.utils import p64
from ZODB.FileStorage import FileStorage
+from persistent import Persistent
from persistent.mapping import PersistentMapping
import transaction
@@ -565,9 +566,34 @@
self.assertEquals(len(slept), 1)
finally:
db.close()
+
+ def checkDoubleCommitter(self):
+ # Verify we can store an object that gets committed twice in
+ # a single transaction.
+ db = DB(self._storage)
+ try:
+ conn = db.open()
+ try:
+ conn.root()['dc'] = DoubleCommitter()
+ transaction.commit()
+ conn2 = db.open()
+ self.assertEquals(conn2.root()['dc'].new_attribute, 1)
+ conn2.close()
+ finally:
+ transaction.abort()
+ conn.close()
+ finally:
+ db.close()
+class DoubleCommitter(Persistent):
+ """A crazy persistent class that changes self in __getstate__"""
+ def __getstate__(self):
+ if not hasattr(self, 'new_attribute'):
+ self.new_attribute = 1
+ return Persistent.__getstate__(self)
+
class IteratorDeepCompareUnordered:
# Like IteratorDeepCompare, but compensates for OID order
# differences in transactions.
More information about the Checkins
mailing list