X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=daklib%2Fdbconn.py;h=f0049a1a0c1addb7422bef47841cfff45218c9f9;hb=001dcfae0b796b8e592c48fa24da98106270a1a1;hp=aa71c180073f1986b764ffb9bf450158e1213dfe;hpb=71565adc68c3eddfd5459a56a4259451bffb0ee8;p=dak.git diff --git a/daklib/dbconn.py b/daklib/dbconn.py index aa71c180..f0049a1a 100755 --- a/daklib/dbconn.py +++ b/daklib/dbconn.py @@ -55,7 +55,7 @@ from inspect import getargspec import sqlalchemy from sqlalchemy import create_engine, Table, MetaData, Column, Integer, desc from sqlalchemy.orm import sessionmaker, mapper, relation, object_session, \ - backref, MapperExtension, EXT_CONTINUE + backref, MapperExtension, EXT_CONTINUE, object_mapper from sqlalchemy import types as sqltypes # Don't remove this, we re-export the exceptions to scripts which import us @@ -287,6 +287,50 @@ class ORMObject(object): ''' return session.query(cls).get(primary_key) + def session(self, replace = False): + ''' + Returns the current session that is associated with the object. May + return None is object is in detached state. + ''' + + return object_session(self) + + def clone(self, session = None): + ''' + Clones the current object in a new session and returns the new clone. A + fresh session is created if the optional session parameter is not + provided. The function will fail if a session is provided and has + unflushed changes. + + RATIONALE: SQLAlchemy's session is not thread safe. This method clones + an existing object to allow several threads to work with their own + instances of an ORMObject. + + WARNING: Only persistent (committed) objects can be cloned. Changes + made to the original object that are not committed yet will get lost. + The session of the new object will always be rolled back to avoid + ressource leaks. + ''' + + if self.session() is None: + raise RuntimeError( \ + 'Method clone() failed for detached object:\n%s' % self) + self.session().flush() + mapper = object_mapper(self) + primary_key = mapper.primary_key_from_instance(self) + object_class = self.__class__ + if session is None: + session = DBConn().session() + elif len(session.new) + len(session.dirty) + len(session.deleted) > 0: + raise RuntimeError( \ + 'Method clone() failed due to unflushed changes in session.') + new_object = session.query(object_class).get(primary_key) + session.rollback() + if new_object is None: + raise RuntimeError( \ + 'Method clone() failed for non-persistent object:\n%s' % self) + return new_object + __all__.append('ORMObject') ################################################################################ @@ -2860,8 +2904,8 @@ class DBConn(object): # The following tables have primary keys but sqlalchemy # version 0.5 fails to reflect them correctly with database # versions before upgrade #41. - #'changes', - #'build_queue_files', + 'changes', + 'build_queue_files', ) tables_no_primary = ( @@ -2876,8 +2920,8 @@ class DBConn(object): 'suite_build_queue_copy', 'udeb_contents', # see the comment above - 'changes', - 'build_queue_files', + #'changes', + #'build_queue_files', ) views = (