From: Luke O. <lu...@me...> - 2003-05-12 21:41:25
|
Hello all - (Tried sending this, I guess 70K attachments are just on the edge of kosher, so get the file here: http://www.amoebagod.com/SQLObject.zip ) Well, after finding time, and getting today's CVS, I'm very pleased to announce a test implementation of Python-side Transactions for SQLObject. Interface: New exported class 'Transaction' (yes, I know there's already a Transaction class in DBConnection, but I couldn't come up with an alternate name, and they won't clash for now.) Public Transaction methods: t = Transaction() t.commit() t.rollback() New methods in SQLObject: a = Class.newForTransaction(trans, ...) same as classmethod "new()" b = inst.addToTransaction(trans) copies inst to the transaction (inst remains un-transactioned in this case, although you could do inst = inst.addToTransaction(trans) ) inst._persist() is a private func called by Transaction to reset instance to a usable post-transaction copy. Example: from SQLObject import Transaction from Person import Person t = Transaction() a = Person.newForTransaction(t, ...) b = Person(1).addToTransaction(t) b.username = 'John' b.addRole(1) b.roles # note: this queries the existing roles for Person(1) # and mixes in the results. t.commit() # note: a and b are now fully functioning regular objects # that can continue to be used. if possible, b is pulled from # the cache, and both are now available in the cache as expected. # t can also be reused at this point, but it has no memory about # previous efforts. rollback after commit is obviously not supported. Implementation Notes: Internally, the transaction is implemented with an in-memory DBConnection-subclass. This MemoryConnection is not generically useful, it relies heavily on the previous connections of each of the objects to provide for data it does not have (especially for joins), and only maintains a diff from this for joins. Also, many DBAPI methods are not implemented, as they are not relevant to the limited accesses used by the new SQLObject methods. I've tried to be as minimally invasive to SQLObject as feasible, with only the following changes (beyond adding the three methods mentioned above): __new__() now takes an additional argument 'useCache' to forcefully avoid caching of a specific instance. This is for addToTransaction, where we create a clean instance and then switch connections (but don't want any record in the class/original connection cache) new() now sets inst._connection = kw['connection'] if a connection is passed in. I'm not sure if this will break other expected behavior, but it seems reasonable to me. RelatedJoin: performJoin, add, remove: these all now use 'inst' argument instead of self.callingClass to get a connection from. Again, not sure if this will break expected behavior, but seems reasonable to me. (I need this because, along with the previous change, I am expecting true per-object connections when I ask for it. :) And that's it. I've attached the fully changed SQLObject directory, only files with changes are SQLObject.py, Transaction.py (new), and __init__.py (to import Transaction). Again, this is from CVS an hour or two ago. Questions? Comments? Let's go! - Luke |