Source code for sqlobject.inheritance.iteration

from sqlobject import sqlbuilder
from sqlobject.classregistry import findClass
from sqlobject.dbconnection import Iteration


[docs]class InheritableIteration(Iteration): # Default array size for cursor.fetchmany() defaultArraySize = 10000 def __init__(self, dbconn, rawconn, select, keepConnection=False): super(InheritableIteration, self).__init__(dbconn, rawconn, select, keepConnection) self.lazyColumns = select.ops.get('lazyColumns', False) try: self.cursor.arraysize = self.defaultArraySize self.use_arraysize = True except AttributeError: # pymssql doesn't have arraysize self.use_arraysize = False self._results = [] # Find the index of the childName column childNameIdx = None columns = select.sourceClass.sqlmeta.columnList for i, column in enumerate(columns): if column.name == "childName": childNameIdx = i break self._childNameIdx = childNameIdx
[docs] def next(self): if not self._results: if self.use_arraysize: _results = self.cursor.fetchmany() else: _results = self.cursor.fetchmany(size=self.defaultArraySize) self._results = list(_results) if not self.lazyColumns: self.fetchChildren() if not self._results: self._cleanup() raise StopIteration result = self._results[0] del self._results[0] if self.lazyColumns: obj = self.select.sourceClass.get(result[0], connection=self.dbconn) return obj else: id = result[0] if id in self._childrenResults: childResults = self._childrenResults[id] del self._childrenResults[id] else: childResults = None obj = self.select.sourceClass.get( id, selectResults=result[1:], childResults=childResults, connection=self.dbconn) return obj
[docs] def fetchChildren(self): """Prefetch childrens' data Fetch childrens' data for every subclass in one big .select() to avoid .get() fetching it one by one. """ self._childrenResults = {} if self._childNameIdx is None: return childIdsNames = {} childNameIdx = self._childNameIdx for result in self._results: childName = result[childNameIdx + 1] if childName: ids = childIdsNames.get(childName) if ids is None: ids = childIdsNames[childName] = [] ids.append(result[0]) dbconn = self.dbconn rawconn = self.rawconn cursor = rawconn.cursor() registry = self.select.sourceClass.sqlmeta.registry for childName, ids in childIdsNames.items(): klass = findClass(childName, registry) if len(ids) == 1: select = klass.select(klass.q.id == ids[0], childUpdate=True, connection=dbconn) else: select = klass.select(sqlbuilder.IN(klass.q.id, ids), childUpdate=True, connection=dbconn) query = dbconn.queryForSelect(select) if dbconn.debug: dbconn.printDebug(rawconn, query, 'Select children of the class %s' % childName) self.dbconn._executeRetry(rawconn, cursor, query) for result in cursor.fetchall(): # Inheritance child classes may have no own columns # (that makes sense when child class has a join # that does not apply to parent class objects). # In such cases result[1:] gives an empty tuple # which is interpreted as "no results fetched" in .get(). # So .get() issues another query which is absolutely # meaningless (like "SELECT NULL FROM child WHERE id=1"). # In order to avoid this, we replace empty results # with non-empty tuple. Extra values in selectResults # are Ok - they will be ignored by ._SO_selectInit(). self._childrenResults[result[0]] = result[1:] or (None,)