self.closed = False
self.executioncontext = executioncontext
self.echo = engine.echo=="debug"
+ self.__key_cache = {}
if executioncontext:
self.rowcount = executioncontext.get_rowcount(cursor)
else:
self.closed = True
if self.connection.should_close_with_result and self.dialect.supports_autoclose_results:
self.connection.close()
- def _get_col(self, row, key):
- if isinstance(key, sql.ColumnElement):
- try:
- rec = self.props[key._label.lower()]
- except KeyError:
+
+ def _convert_key(self, key):
+ """given a key, which could be a ColumnElement, string, etc., matches it to the
+ appropriate key we got from the result set's metadata; then cache it locally for quick re-access."""
+ try:
+ return self.__key_cache[key]
+ except KeyError:
+ if isinstance(key, sql.ColumnElement):
try:
- rec = self.props[key.key.lower()]
+ rec = self.props[key._label.lower()]
except KeyError:
- rec = self.props[key.name.lower()]
- elif isinstance(key, str):
- rec = self.props[key.lower()]
- else:
- rec = self.props[key]
+ try:
+ rec = self.props[key.key.lower()]
+ except KeyError:
+ rec = self.props[key.name.lower()]
+ elif isinstance(key, str):
+ rec = self.props[key.lower()]
+ else:
+ rec = self.props[key]
+ self.__key_cache[key] = rec
+ return rec
+ def _has_key(self, row, key):
+ try:
+ self._convert_key(key)
+ return True
+ except KeyError:
+ return False
+
+ def _get_col(self, row, key):
+ rec = self._convert_key(key)
return rec[0].dialect_impl(self.dialect).convert_result_value(row[rec[1]], self.dialect)
def __iter__(self):
return (other is self) or (other == tuple([self.__parent._get_col(self.__row, key) for key in range(0, len(self.__row))]))
def __repr__(self):
return repr(tuple([self.__parent._get_col(self.__row, key) for key in range(0, len(self.__row))]))
+ def has_key(self, key):
+ return self.__parent._has_key(self.__row, key)
def __getitem__(self, key):
return self.__parent._get_col(self.__row, key)
def __getattr__(self, name):
return elem.obj
ret = False
- elements = [getobj(elem) for elem in self.targettask.tosave_elements if elem.obj is not None and not elem.is_preprocessed(self)]
+ elements = [getobj(elem) for elem in self.targettask.polymorphic_tosave_elements if elem.obj is not None and not elem.is_preprocessed(self)]
if len(elements):
ret = True
self.processor.preprocess_dependencies(self.targettask, elements, trans, delete=False)
- elements = [getobj(elem) for elem in self.targettask.todelete_elements if elem.obj is not None and not elem.is_preprocessed(self)]
+ elements = [getobj(elem) for elem in self.targettask.polymorphic_todelete_elements if elem.obj is not None and not elem.is_preprocessed(self)]
if len(elements):
ret = True
self.processor.preprocess_dependencies(self.targettask, elements, trans, delete=True)
def execute(self, trans, delete):
if not delete:
- self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.tosave_elements if elem.obj is not None], trans, delete=False)
+ self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.polymorphic_tosave_elements if elem.obj is not None], trans, delete=False)
else:
- self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.todelete_elements if elem.obj is not None], trans, delete=True)
+ self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.polymorphic_todelete_elements if elem.obj is not None], trans, delete=True)
def get_object_dependencies(self, obj, trans, passive):
return self.processor.get_object_dependencies(obj, trans, passive=passive)
return UOWDependencyProcessor(self.processor, task)
class UOWTask(object):
+ """represents the full list of objects that are to be saved/deleted by a specific Mapper."""
def __init__(self, uowtransaction, mapper):
if uowtransaction is not None:
uowtransaction.tasks[mapper] = self
child.execute(trans)
for task in self.inheriting_tasks:
task._execute_childtasks(trans)
+ def _execute_cyclical_dependencies(self, trans, isdelete):
+ for dep in self.cyclical_dependencies:
+ dep.execute(trans, isdelete)
+ for task in self.inheriting_tasks:
+ task._execute_cyclical_dependencies(trans, isdelete)
+ def _execute_per_element_childtasks(self, trans, isdelete):
+ if isdelete:
+ for element in self.todelete_elements:
+ for task in element.childtasks:
+ task.execute(trans)
+ else:
+ for element in self.tosave_elements:
+ for task in element.childtasks:
+ task.execute(trans)
+ for task in self.inheriting_tasks:
+ task._execute_per_element_childtasks(trans, isdelete)
def execute(self, trans):
"""executes this UOWTask. saves objects to be saved, processes all dependencies
self.circular.execute(trans)
return
- # TODO: apply the same recursive inheritance logic to the cyclical tasks/dependencies
# TODO: add a visitation system to the UOW classes and have this execution called
# from a separate executor object ? (would also handle dumping)
self._save_objects(trans)
- for dep in self.cyclical_dependencies:
- dep.execute(trans, False)
- for element in self.tosave_elements:
- for task in element.childtasks:
- task.execute(trans)
+ self._execute_cyclical_dependencies(trans, False)
+ self._execute_per_element_childtasks(trans, False)
self._execute_dependencies(trans)
- for dep in self.cyclical_dependencies:
- dep.execute(trans, True)
+ self._execute_cyclical_dependencies(trans, True)
self._execute_childtasks(trans)
- for element in self.todelete_elements:
- for task in element.childtasks:
- task.execute(trans)
+ self._execute_per_element_childtasks(trans, True)
self._delete_objects(trans)
+ def _polymorphic_elements(self):
+ for rec in self.objects.values():
+ yield rec
+ for task in self.inheriting_tasks:
+ for rec in task._polymorphic_elements():
+ yield rec
+
+ polymorphic_tosave_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if not rec.isdelete])
+ polymorphic_todelete_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if rec.isdelete])
+
tosave_elements = property(lambda self: [rec for rec in self.objects.values() if not rec.isdelete])
todelete_elements = property(lambda self:[rec for rec in self.objects.values() if rec.isdelete])
tosave_objects = property(lambda self:[rec.obj for rec in self.objects.values() if rec.obj is not None and not rec.listonly and rec.isdelete is False])
def _dump_processor(proc, deletes):
if deletes:
- val = [t for t in proc.targettask.objects.values() if t.isdelete]
+ val = proc.targettask.polymorphic_todelete_elements
else:
- val = [t for t in proc.targettask.objects.values() if not t.isdelete]
+ val = proc.targettask.polymorphic_tosave_elements
buf.write(_indent() + " |- %s attribute on %s (UOWDependencyProcessor(%d) processing %s)\n" % (
repr(proc.processor.key),