diff options
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 18 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 53 |
2 files changed, 39 insertions, 32 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 3327f13c3..e07f691f4 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -220,12 +220,20 @@ class Mapper(object): def _is_orphan(self, obj): optimistic = has_identity(obj) for (key,klass) in self.delete_orphans: - if not getattr(klass, key).hasparent(obj, optimistic=optimistic): - if not has_identity(obj): - raise exceptions.FlushError("instance %s is an unsaved, pending instance and is an orphan (is not attached to any parent '%s' instance via that classes' '%s' attribute)" % (obj, klass.__name__, key)) - return True + if getattr(klass, key).hasparent(obj, optimistic=optimistic): + return False else: - return False + if len(self.delete_orphans): + if not has_identity(obj): + raise exceptions.FlushError("instance %s is an unsaved, pending instance and is an orphan (is not attached to %s)" % + ( + obj, + ", nor ".join(["any parent '%s' instance via that classes' '%s' attribute" % (klass.__name__, key) for (key,klass) in self.delete_orphans]) + )) + else: + return True + else: + return False def _get_props(self): self.compile() diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 6e5590bb0..c4b75f644 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -470,7 +470,6 @@ class EagerLoader(AbstractRelationLoader): else: decorated_row = decorator(row) else: - # AliasedClauses, keyed to the lead mapper used in the query clauses = self.clauses_by_lead_mapper[selectcontext.mapper] decorated_row = clauses._decorate_row(row) # check for identity key @@ -481,36 +480,36 @@ class EagerLoader(AbstractRelationLoader): self.parent_property._get_strategy(LazyLoader).process_row(selectcontext, instance, row, identitykey, isnew) return - if not self.uselist: - self.logger.debug("eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key)) - if isnew: - # set a scalar object instance directly on the parent object, - # bypassing SmartProperty event handlers. - instance.__dict__[self.key] = self.mapper._instance(selectcontext, decorated_row, None) + # TODO: recursion check a speed hit...? try to get a "termination point" into the AliasedClauses + # or EagerRowAdapter ? + selectcontext.recursion_stack.add(self) + try: + if not self.uselist: + self.logger.debug("eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key)) + if isnew: + # set a scalar object instance directly on the parent object, + # bypassing SmartProperty event handlers. + instance.__dict__[self.key] = self.mapper._instance(selectcontext, decorated_row, None) + else: + # call _instance on the row, even though the object has been created, + # so that we further descend into properties + self.mapper._instance(selectcontext, decorated_row, None) else: - # call _instance on the row, even though the object has been created, - # so that we further descend into properties - self.mapper._instance(selectcontext, decorated_row, None) - else: - if isnew: - self.logger.debug("initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key)) - # call the SmartProperty's initialize() method to create a new, blank list - l = getattr(instance.__class__, self.key).initialize(instance) + if isnew: + self.logger.debug("initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key)) + # call the SmartProperty's initialize() method to create a new, blank list + l = getattr(instance.__class__, self.key).initialize(instance) - # create an appender object which will add set-like semantics to the list - appender = util.UniqueAppender(l.data) + # create an appender object which will add set-like semantics to the list + appender = util.UniqueAppender(l.data) - # store it in the "scratch" area, which is local to this load operation. - selectcontext.attributes[(instance, self.key)] = appender - result_list = selectcontext.attributes[(instance, self.key)] - self.logger.debug("eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key)) - # TODO: recursion check a speed hit...? try to get a "termination point" into the AliasedClauses - # or EagerRowAdapter ? - selectcontext.recursion_stack.add(self) - try: + # store it in the "scratch" area, which is local to this load operation. + selectcontext.attributes[(instance, self.key)] = appender + result_list = selectcontext.attributes[(instance, self.key)] + self.logger.debug("eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key)) self.mapper._instance(selectcontext, decorated_row, result_list) - finally: - selectcontext.recursion_stack.remove(self) + finally: + selectcontext.recursion_stack.remove(self) EagerLoader.logger = logging.class_logger(EagerLoader) |
