def fetchObjRef(self, objRef): """ Given an unarchived object reference, this method returns the actual object for it (or None if the reference is NULL or dangling). While this method assumes that obj refs are stored as 64-bit numbers containing the class id and object serial number, subclasses are certainly able to override that assumption by overriding this method. """ assert isinstance(objRef, types.LongType), 'type=%r, objRef=%r' % (type(objRef), objRef) if objRef == 0: return None else: klassId, serialNum = objRefSplit(objRef) if klassId == 0 or serialNum == 0: # invalid! we don't use 0 serial numbers return self.objRefZeroSerialNum(objRef) klass = self.klassForId(klassId) # Check if we already have this in memory first key = ObjectKey() key.initFromClassNameAndSerialNum(klass.name(), serialNum) obj = self._objects.get(key, None) if obj: return obj clauses = 'where %s=%d' % (klass.sqlSerialColumnName(), serialNum) objs = self.fetchObjectsOfClass(klass, clauses, isDeep=False) if len(objs) == 1: return objs[0] elif len(objs) > 1: raise ValueError, 'Multiple objects.' # @@ 2000-11-22 ce: expand the msg with more information else: return self.objRefDangles(objRef)
def _insertObject(self, obj, unknownSerialNums): # New objects not in the persistent store have serial numbers less than 1 if obj.serialNum() > 0: try: rep = repr(obj) except Exception: rep = '(repr exception)' assert obj.serialNum() < 1, 'obj=%s' % rep # try to get the next ID (if database supports this) idNum = self.retrieveNextInsertId(obj.klass()) # SQL insert sql = obj.sqlInsertStmt(unknownSerialNums, idNum) conn, cur = self.executeSQL(sql) try: # Get new id/serial num if idNum is None: idNum = self.retrieveLastInsertId(conn, cur) # Update object obj.setSerialNum(idNum) obj.setKey(ObjectKey().initFromObject(obj)) obj.setChanged(False) # Update our object pool self._objects[obj.key()] = obj finally: self.doneWithConnection(conn)
def fetchObjectsOfClass(self, aClass, clauses='', isDeep=1, refreshAttrs=1, serialNum=None): """ Fetches a list of objects of a specific class. The list may be empty if no objects are found. aClass can be a Klass object (from the MiddleKit object model), the name of the class (e.g., a string) or a Python class. The clauses argument can be any SQL clauses such as 'where x<5 order by x'. Obviously, these could be specific to your SQL database, thereby making your code non-portable. Use your best judgement. serialNum can be a specific serial number if you are looking for a specific object. If serialNum is provided, it overrides the clauses. You should label all arguments other than aClass: objs = store.fetchObjectsOfClass('Foo', clauses='where x<5') The reason for labeling is that this method is likely to undergo improvements in the future which could include additional arguments. No guarantees are made about the order of the arguments except that aClass will always be the first. Raises an exception if aClass parameter is invalid. """ klass = self._klassForClass(aClass) # Fetch objects of subclasses first, because the code below will be modifying clauses and serialNum deepObjs = [] if isDeep: for subklass in klass.subklasses(): deepObjs.extend( self.fetchObjectsOfClass(subklass, clauses, isDeep, refreshAttrs, serialNum)) # Now get objects of this exact class objs = [] if not klass.isAbstract(): fetchSQLStart = klass.fetchSQLStart() className = klass.name() if serialNum is not None: clauses = 'where %s=%d' % (klass.sqlIdName(), serialNum) if self._markDeletes: clauses = self.addDeletedToClauses(clauses) conn, cur = self.executeSQL(fetchSQLStart + clauses + ';') for row in cur.fetchall(): serialNum = row[0] key = ObjectKey().initFromClassNameAndSerialNum( className, serialNum) obj = self._objects.get(key, None) if obj is None: pyClass = klass.pyClass() obj = pyClass() assert isinstance( obj, MiddleObject ), 'Not a MiddleObject. obj = %r, type = %r, MiddleObject = %r' % ( obj, type(obj), MiddleObject) obj.readStoreData(self, row) obj.setKey(key) self._objects[key] = obj else: # Existing object if refreshAttrs: obj.readStoreData(self, row) objs.append(obj) objs.extend(deepObjs) return objs
def objectForClassAndSerial(self, klass, serialNum, default=NoDefault): if isinstance(klass, BaseKlass): klass = klass.name() elif isinstance(klass, (type, ClassType)): klass = klass.__name__ else: assert isinstance(klass, str) key = ObjectKey().initFromClassNameAndSerialNum(klass, serialNum) return self.objectForKey(key, default)
def objRefInMem(self, objRef): """ Return the object corresponding to the given objref if and only if it has been loaded into memory. If the object has never been fetched from the database, None is returned. """ assert isinstance(objRef, types.LongType), 'type=%r, objRef=%r' % (type(objRef), objRef) if objRef == 0: return 0 else: klassId, serialNum = objRefSplit(objRef) if klassId == 0 or serialNum == 0: # invalid! we don't use 0 serial numbers return self.objRefZeroSerialNum(objRef) klass = self.klassForId(klassId) # return whether we have this object in memory key = ObjectKey() key.initFromClassNameAndSerialNum(klass.name(), serialNum) return self._objects.get(key, None)
def objRefInMem(self, objRef): """Return referenced object in memory. Returns the object corresponding to the given objref if and only if it has been loaded into memory. If the object has never been fetched from the database, None is returned. """ assert isinstance(objRef, long), 'type=%r, objRef=%r' % (type(objRef), objRef) if objRef == 0: return 0 else: klassId, serialNum = objRefSplit(objRef) if klassId == 0 or serialNum == 0: # invalid! we don't use 0 serial numbers return self.objRefZeroSerialNum(objRef) klass = self.klassForId(klassId) # return whether we have this object in memory key = ObjectKey() key.initFromClassNameAndSerialNum(klass.name(), serialNum) return self._objects.get(key)
def fetchObjRef(self, objRef): """Fetch referenced object. Given an unarchived object reference, this method returns the actual object for it (or None if the reference is NULL or dangling). While this method assumes that obj refs are stored as 64-bit numbers containing the class id and object serial number, subclasses are certainly able to override that assumption by overriding this method. """ assert isinstance(objRef, long), 'type=%r, objRef=%r' % (type(objRef), objRef) if objRef == 0: return None else: klassId, serialNum = objRefSplit(objRef) if klassId == 0 or serialNum == 0: # invalid! we don't use 0 serial numbers return self.objRefZeroSerialNum(objRef) klass = self.klassForId(klassId) # Check if we already have this in memory first key = ObjectKey() key.initFromClassNameAndSerialNum(klass.name(), serialNum) obj = self._objects.get(key) if obj: return obj clauses = 'where %s=%d' % (klass.sqlSerialColumnName(), serialNum) objs = self.fetchObjectsOfClass(klass, clauses, isDeep=False) if len(objs) == 1: return objs[0] elif len(objs) > 1: # @@ 2000-11-22 ce: expand the msg with more information raise ValueError('Multiple objects.') else: return self.objRefDangles(objRef)
def _insertObject(self, object, unknownSerialNums): # New objects not in the persistent store have serial numbers less than 1 if object.serialNum() > 0: try: rep = repr(object) except: rep = '(repr exception)' assert object.serialNum() < 1, 'object=%s' % rep # SQL insert sql = object.sqlInsertStmt(unknownSerialNums) conn, cur = self.executeSQL(sql) # Get new id/serial num idNum = self.retrieveLastInsertId(conn, cur) # Update object object.setSerialNum(idNum) object.setKey(ObjectKey().initFromObject(object)) object.setChanged(0) # Update our object pool self._objects[object.key()] = object