Example #1
0
    def register_object(self,
                        state,
                        isdelete=False,
                        listonly=False,
                        postupdate=False,
                        post_update_cols=None,
                        **kwargs):
        # if object is not in the overall session, do nothing
        if not self.uow._is_valid(state):
            if self._should_log_debug:
                self.logger.debug(
                    "object %s not part of session, not registering for flush"
                    % (mapperutil.state_str(state)))
            return

        if self._should_log_debug:
            self.logger.debug(
                "register object for flush: %s isdelete=%s listonly=%s postupdate=%s"
                %
                (mapperutil.state_str(state), isdelete, listonly, postupdate))

        mapper = _state_mapper(state)

        task = self.get_task_by_mapper(mapper)
        if postupdate:
            task.append_postupdate(state, post_update_cols)
        else:
            task.append(state, listonly, isdelete=isdelete, **kwargs)
Example #2
0
    def register_object(self, state, isdelete=False, listonly=False, postupdate=False, post_update_cols=None):

        # if object is not in the overall session, do nothing
        if not self.session._contains_state(state):
            if self._should_log_debug:
                self.logger.debug("object %s not part of session, not registering for flush" % (mapperutil.state_str(state)))
            return

        if self._should_log_debug:
            self.logger.debug("register object for flush: %s isdelete=%s listonly=%s postupdate=%s" % (mapperutil.state_str(state), isdelete, listonly, postupdate))

        mapper = _state_mapper(state)

        task = self.get_task_by_mapper(mapper)
        if postupdate:
            task.append_postupdate(state, post_update_cols)
        else:
            task.append(state, listonly=listonly, isdelete=isdelete)

        # ensure the mapper for this object has had its
        # DependencyProcessors added.
        if mapper not in self.processors:
            mapper._register_processors(self)
            self.processors.add(mapper)

            if mapper.base_mapper not in self.processors:
                mapper.base_mapper._register_processors(self)
                self.processors.add(mapper.base_mapper)
Example #3
0
    def _register_clean(self, state):
        """register the given object as 'clean' (i.e. persistent) within this unit of work, after
        a save operation has taken place."""

        mapper = _state_mapper(state)
        instance_key = mapper._identity_key_from_state(state)
        
        if '_instance_key' not in state.dict:
            state.dict['_instance_key'] = instance_key
            
        elif state.dict['_instance_key'] != instance_key:
            # primary key switch
            del self.identity_map[state.dict['_instance_key']]
            state.dict['_instance_key'] = instance_key
            
        if hasattr(state, 'insert_order'):
            delattr(state, 'insert_order')
        
        o = state.obj()
        # prevent against last minute dereferences of the object
        # TODO: identify a code path where state.obj() is None
        if o is not None:
            self.identity_map[state.dict['_instance_key']] = o
            state.commit_all()
        
        # remove from new last, might be the last strong ref
        self.new.pop(state, None)
Example #4
0
    def _register_clean(self, state):
        """register the given object as 'clean' (i.e. persistent) within this unit of work, after
        a save operation has taken place."""

        mapper = _state_mapper(state)
        instance_key = mapper._identity_key_from_state(state)
        
        if '_instance_key' not in state.dict:
            state.dict['_instance_key'] = instance_key
            
        elif state.dict['_instance_key'] != instance_key:
            # primary key switch
            del self.identity_map[state.dict['_instance_key']]
            state.dict['_instance_key'] = instance_key
            
        if hasattr(state, 'insert_order'):
            delattr(state, 'insert_order')
        
        o = state.obj()
        # prevent against last minute dereferences of the object
        # TODO: identify a code path where state.obj() is None
        if o is not None:
            self.identity_map[state.dict['_instance_key']] = o
            state.commit_all()
        
        # remove from new last, might be the last strong ref
        self.new.pop(state, None)
Example #5
0
    def register_object(self, state, isdelete=False, listonly=False, postupdate=False, post_update_cols=None):
        
        # if object is not in the overall session, do nothing
        if not self.session._contains_state(state):
            if self._should_log_debug:
                self.logger.debug("object %s not part of session, not registering for flush" % 
                                        (mapperutil.state_str(state)))
            return

        if self._should_log_debug:
            self.logger.debug("register object for flush: %s isdelete=%s listonly=%s postupdate=%s"
                                    % (mapperutil.state_str(state), isdelete, listonly, postupdate))

        mapper = _state_mapper(state)

        task = self.get_task_by_mapper(mapper)
        if postupdate:
            task.append_postupdate(state, post_update_cols)
        else:
            task.append(state, listonly=listonly, isdelete=isdelete)

        # ensure the mapper for this object has had its 
        # DependencyProcessors added.
        if mapper not in self.processors:
            mapper._register_processors(self)
            self.processors.add(mapper)

            if mapper.base_mapper not in self.processors:
                mapper.base_mapper._register_processors(self)
                self.processors.add(mapper.base_mapper)
Example #6
0
 def append(self, state, item, initiator):
     # process "save_update" cascade rules for when an instance is appended to the list of another instance
     sess = _state_session(state)
     if sess:
         prop = _state_mapper(state).get_property(self.key)
         if prop.cascade.save_update and item not in sess:
             sess.add(item)
     return item
Example #7
0
 def append(self, state, item, initiator):
     # process "save_update" cascade rules for when an instance is appended to the list of another instance
     sess = _state_session(state)
     if sess:
         prop = _state_mapper(state).get_property(self.key)
         if prop.cascade.save_update and item not in sess:
             sess.add(item)
     return item
Example #8
0
 def remove(self, state, item, initiator):
     sess = _state_session(state)
     if sess:
         prop = _state_mapper(state).get_property(self.key)
         # expunge pending orphans
         if prop.cascade.delete_orphan and \
             item in sess.new and \
             prop.mapper._is_orphan(attributes.instance_state(item)):
             sess.expunge(item)
Example #9
0
 def remove(self, state, item, initiator):
     sess = _state_session(state)
     if sess:
         prop = _state_mapper(state).get_property(self.key)
         # expunge pending orphans
         if prop.cascade.delete_orphan and \
             item in sess.new and \
             prop.mapper._is_orphan(attributes.instance_state(item)):
                 sess.expunge(item)
Example #10
0
    def __call__(self):
        state = self.state
        if not mapper._state_has_identity(state):
            return None

        instance_mapper = mapper._state_mapper(state)
        prop = instance_mapper.get_property(self.key)
        strategy = prop._get_strategy(LazyLoader)

        if strategy._should_log_debug:
            strategy.logger.debug(
                "loading %s" % mapperutil.state_attribute_str(state, self.key))

        session = sessionlib._state_session(state)
        if session is None:
            raise sa_exc.UnboundExecutionError(
                "Parent instance %s is not bound to a Session; "
                "lazy load operation of attribute '%s' cannot proceed" %
                (mapperutil.state_str(state), self.key))

        q = session.query(prop.mapper)._adapt_all_clauses()

        if self.path:
            q = q._with_current_path(self.path)

        # if we have a simple primary key load, use mapper.get()
        # to possibly save a DB round trip
        if strategy.use_get:
            ident = []
            allnulls = True
            for primary_key in prop.mapper.primary_key:
                val = instance_mapper._get_committed_state_attr_by_column(
                    state, strategy._equated_columns[primary_key])
                allnulls = allnulls and val is None
                ident.append(val)
            if allnulls:
                return None
            if self.options:
                q = q._conditional_options(*self.options)
            return q.get(ident)

        if prop.order_by:
            q = q.order_by(*util.to_list(prop.order_by))

        if self.options:
            q = q._conditional_options(*self.options)
        q = q.filter(strategy.lazy_clause(state))

        result = q.all()
        if strategy.uselist:
            return result
        else:
            if result:
                return result[0]
            else:
                return None
Example #11
0
 def set_row_switch(self, state):
     """mark a deleted object as a 'row switch'.
     
     this indicates that an INSERT statement elsewhere corresponds to this DELETE;
     the INSERT is converted to an UPDATE and the DELETE does not occur.
     """
     mapper = _state_mapper(state)
     task = self.get_task_by_mapper(mapper)
     taskelement = task._objects[state]
     taskelement.isdelete = "rowswitch"
Example #12
0
 def set_row_switch(self, state):
     """mark a deleted object as a 'row switch'.
     
     this indicates that an INSERT statement elsewhere corresponds to this DELETE;
     the INSERT is converted to an UPDATE and the DELETE does not occur.
     """
     mapper = _state_mapper(state)
     task = self.get_task_by_mapper(mapper)
     taskelement = task._objects[state]
     taskelement.isdelete = "rowswitch"
Example #13
0
    def __call__(self):
        state = self.state
        if not mapper._state_has_identity(state):
            return None

        instance_mapper = mapper._state_mapper(state)
        prop = instance_mapper.get_property(self.key)
        strategy = prop._get_strategy(LazyLoader)
        
        if strategy._should_log_debug:
            strategy.logger.debug("loading %s" % mapperutil.state_attribute_str(state, self.key))

        session = sessionlib._state_session(state)
        if session is None:
            raise sa_exc.UnboundExecutionError(
                "Parent instance %s is not bound to a Session; "
                "lazy load operation of attribute '%s' cannot proceed" % 
                (mapperutil.state_str(state), self.key)
            )
        
        q = session.query(prop.mapper)._adapt_all_clauses()
        
        if self.path:
            q = q._with_current_path(self.path)
            
        # if we have a simple primary key load, use mapper.get()
        # to possibly save a DB round trip
        if strategy.use_get:
            ident = []
            allnulls = True
            for primary_key in prop.mapper.primary_key: 
                val = instance_mapper._get_committed_state_attr_by_column(state, strategy._equated_columns[primary_key])
                allnulls = allnulls and val is None
                ident.append(val)
            if allnulls:
                return None
            if self.options:
                q = q._conditional_options(*self.options)
            return q.get(ident)

        if prop.order_by:
            q = q.order_by(*util.to_list(prop.order_by))

        if self.options:
            q = q._conditional_options(*self.options)
        q = q.filter(strategy.lazy_clause(state))

        result = q.all()
        if strategy.uselist:
            return result
        else:
            if result:
                return result[0]
            else:
                return None
 def set(self, state, newvalue, oldvalue, initiator):
     # process "save_update" cascade rules for when an instance is attached to another instance
     if oldvalue is newvalue:
         return newvalue
     sess = _state_session(state)
     if sess:
         prop = _state_mapper(state).get_property(self.key)
         if newvalue is not None and prop.cascade.save_update and newvalue not in sess:
             sess.add(newvalue)
         if prop.cascade.delete_orphan and oldvalue in sess.new:
             sess.expunge(oldvalue)
     return newvalue
Example #15
0
 def set(self, state, newvalue, oldvalue, initiator):
     # process "save_update" cascade rules for when an instance is attached to another instance
     if oldvalue is newvalue:
         return newvalue
     sess = _state_session(state)
     if sess:
         prop = _state_mapper(state).get_property(self.key)
         if newvalue is not None and prop.cascade.save_update and newvalue not in sess:
             sess.add(newvalue)
         if prop.cascade.delete_orphan and oldvalue in sess.new:
             sess.expunge(oldvalue)
     return newvalue
Example #16
0
    def class_level_loader(self, state, props=None):
        if not mapperutil._state_has_identity(state):
            return None

        localparent = mapper._state_mapper(state)

        # adjust for the ColumnProperty associated with the instance
        # not being our own ColumnProperty.
        # TODO: this may no longer be relevant without entity_name.
        prop = localparent.get_property(self.key)
        if prop is not self.parent_property:
            return prop._get_strategy(DeferredColumnLoader).setup_loader(state)

        return LoadDeferredColumns(state, self.key, props)
Example #17
0
    def class_level_loader(self, state, options=None, path=None):
        if not mapperutil._state_has_identity(state):
            return None

        localparent = mapper._state_mapper(state)

        # adjust for the PropertyLoader associated with the instance
        # not being our own PropertyLoader.
        # TODO: this may no longer be relevant without entity_name
        prop = localparent.get_property(self.key)
        if prop is not self.parent_property:
            return prop._get_strategy(LazyLoader).setup_loader(state)

        return LoadLazyAttribute(state, self.key, options, path)
Example #18
0
    def class_level_loader(self, state, props=None):
        if not mapperutil._state_has_identity(state):
            return None

        localparent = mapper._state_mapper(state)

        # adjust for the ColumnProperty associated with the instance
        # not being our own ColumnProperty.
        # TODO: this may no longer be relevant without entity_name.
        prop = localparent.get_property(self.key)
        if prop is not self.parent_property:
            return prop._get_strategy(DeferredColumnLoader).setup_loader(state)

        return LoadDeferredColumns(state, self.key, props)
Example #19
0
    def class_level_loader(self, state, options=None, path=None):
        if not mapperutil._state_has_identity(state):
            return None

        localparent = mapper._state_mapper(state)

        # adjust for the PropertyLoader associated with the instance
        # not being our own PropertyLoader.
        # TODO: this may no longer be relevant without entity_name
        prop = localparent.get_property(self.key)
        if prop is not self.parent_property:
            return prop._get_strategy(LazyLoader).setup_loader(state)

        return LoadLazyAttribute(state, self.key, options, path)
Example #20
0
    def register_object(self, state, isdelete=False, listonly=False, postupdate=False, post_update_cols=None):
        # if object is not in the overall session, do nothing
        if not self.session._contains_state(state):
            if self._should_log_debug:
                self.logger.debug("object %s not part of session, not registering for flush" % (mapperutil.state_str(state)))
            return

        if self._should_log_debug:
            self.logger.debug("register object for flush: %s isdelete=%s listonly=%s postupdate=%s" % (mapperutil.state_str(state), isdelete, listonly, postupdate))

        mapper = _state_mapper(state)

        task = self.get_task_by_mapper(mapper)
        if postupdate:
            task.append_postupdate(state, post_update_cols)
        else:
            task.append(state, listonly=listonly, isdelete=isdelete)
Example #21
0
    def __call__(self, **kw):
        if kw.get('passive') is attributes.PASSIVE_NO_FETCH:
            return attributes.PASSIVE_NO_RESULT

        state = self.state
        
        localparent = mapper._state_mapper(state)
        
        prop = localparent.get_property(self.key)
        strategy = prop._get_strategy(DeferredColumnLoader)

        if strategy.group:
            toload = [
                    p.key for p in 
                    localparent.iterate_properties 
                    if isinstance(p, StrategizedProperty) and 
                      isinstance(p.strategy, DeferredColumnLoader) and 
                      p.group==strategy.group
                    ]
        else:
            toload = [self.key]

        # narrow the keys down to just those which have no history
        group = [k for k in toload if k in state.unmodified]

        if strategy._should_log_debug():
            strategy.logger.debug(
                    "deferred load %s group %s",
                    (mapperutil.state_attribute_str(state, self.key), 
                    group and ','.join(group) or 'None')
            )

        session = sessionlib._state_session(state)
        if session is None:
            raise orm_exc.DetachedInstanceError(
                "Parent instance %s is not bound to a Session; "
                "deferred load operation of attribute '%s' cannot proceed" % 
                (mapperutil.state_str(state), self.key)
                )

        query = session.query(localparent)
        ident = state.key[1]
        query._get(None, ident=ident, 
                    only_load_props=group, refresh_state=state)
        return attributes.ATTR_WAS_SET
Example #22
0
    def __call__(self):
        state = self.state

        if not mapper._state_has_identity(state):
            return None

        localparent = mapper._state_mapper(state)

        prop = localparent.get_property(self.key)
        strategy = prop._get_strategy(DeferredColumnLoader)

        if self.keys:
            toload = self.keys
        elif strategy.group:
            toload = [
                p.key
                for p in localparent.iterate_properties
                if isinstance(p, StrategizedProperty)
                and isinstance(p.strategy, DeferredColumnLoader)
                and p.group == strategy.group
            ]
        else:
            toload = [self.key]

        # narrow the keys down to just those which have no history
        group = [k for k in toload if k in state.unmodified]

        if strategy._should_log_debug:
            strategy.logger.debug(
                "deferred load %s group %s"
                % (mapperutil.state_attribute_str(state, self.key), group and ",".join(group) or "None")
            )

        session = sessionlib._state_session(state)
        if session is None:
            raise sa_exc.UnboundExecutionError(
                "Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed"
                % (mapperutil.state_str(state), self.key)
            )

        query = session.query(localparent)
        ident = state.key[1]
        query._get(None, ident=ident, only_load_props=group, refresh_state=state)
        return attributes.ATTR_WAS_SET
Example #23
0
    def __call__(self):
        state = self.state

        if not mapper._state_has_identity(state):
            return None

        localparent = mapper._state_mapper(state)

        prop = localparent.get_property(self.key)
        strategy = prop._get_strategy(DeferredColumnLoader)

        if self.keys:
            toload = self.keys
        elif strategy.group:
            toload = [
                p.key for p in localparent.iterate_properties
                if isinstance(p, StrategizedProperty)
                and isinstance(p.strategy, DeferredColumnLoader)
                and p.group == strategy.group
            ]
        else:
            toload = [self.key]

        # narrow the keys down to just those which have no history
        group = [k for k in toload if k in state.unmodified]

        if strategy._should_log_debug:
            strategy.logger.debug(
                "deferred load %s group %s" % (mapperutil.state_attribute_str(
                    state, self.key), group and ','.join(group) or 'None'))

        session = sessionlib._state_session(state)
        if session is None:
            raise sa_exc.UnboundExecutionError(
                "Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed"
                % (mapperutil.state_str(state), self.key))

        query = session.query(localparent)
        ident = state.key[1]
        query._get(None,
                   ident=ident,
                   only_load_props=group,
                   refresh_state=state)
        return attributes.ATTR_WAS_SET
Example #24
0
    def _register_clean(self, state):
        """register the given object as 'clean' (i.e. persistent) within this unit of work, after
        a save operation has taken place."""

        mapper = _state_mapper(state)
        instance_key = mapper._identity_key_from_state(state)

        if '_instance_key' not in state.dict:
            state.dict['_instance_key'] = instance_key

        elif state.dict['_instance_key'] != instance_key:
            # primary key switch
            del self.identity_map[state.dict['_instance_key']]
            state.dict['_instance_key'] = instance_key

        if hasattr(state, 'insert_order'):
            delattr(state, 'insert_order')

        self.identity_map[state.dict['_instance_key']] = state.obj()
        state.commit_all()

        # remove from new last, might be the last strong ref
        self.new.pop(state, None)
Example #25
0
    def register_object(self, state, isdelete=False, 
                            listonly=False, postupdate=False, post_update_cols=None):
        
        # if object is not in the overall session, do nothing
        if not self.session._contains_state(state):
            return

        mapper = _state_mapper(state)

        task = self.get_task_by_mapper(mapper)
        if postupdate:
            task.append_postupdate(state, post_update_cols)
        else:
            task.append(state, listonly=listonly, isdelete=isdelete)

        # ensure the mapper for this object has had its 
        # DependencyProcessors added.
        if mapper not in self.processors:
            mapper._register_processors(self)
            self.processors.add(mapper)

            if mapper.base_mapper not in self.processors:
                mapper.base_mapper._register_processors(self)
                self.processors.add(mapper.base_mapper)
Example #26
0
    def __call__(self, **kw):
        state = self.state
        instance_mapper = mapper._state_mapper(state)
        prop = instance_mapper.get_property(self.key)
        strategy = prop._get_strategy(LazyLoader)

        if kw.get('passive') is attributes.PASSIVE_NO_FETCH and \
                                    not strategy.use_get:
            return attributes.PASSIVE_NO_RESULT

        if strategy._should_log_debug():
            strategy.logger.debug(
                "loading %s", mapperutil.state_attribute_str(state, self.key))

        session = sessionlib._state_session(state)
        if session is None:
            raise orm_exc.DetachedInstanceError(
                "Parent instance %s is not bound to a Session; "
                "lazy load operation of attribute '%s' cannot proceed" %
                (mapperutil.state_str(state), self.key))

        q = session.query(prop.mapper)._adapt_all_clauses()

        if state.load_path:
            q = q._with_current_path(state.load_path + (self.key, ))

        # if we have a simple primary key load, use mapper.get()
        # to possibly save a DB round trip
        if strategy.use_get:
            ident = []
            allnulls = True
            for primary_key in prop.mapper.primary_key:
                val = instance_mapper.\
                                _get_committed_state_attr_by_column(
                                    state,
                                    state.dict,
                                    strategy._equated_columns[primary_key],
                                    **kw)
                if val is attributes.PASSIVE_NO_RESULT:
                    return val
                allnulls = allnulls and val is None
                ident.append(val)

            if allnulls:
                return None

            if state.load_options:
                q = q._conditional_options(*state.load_options)

            key = prop.mapper.identity_key_from_primary_key(ident)
            return q._get(key, ident, **kw)

        if prop.order_by:
            q = q.order_by(*util.to_list(prop.order_by))

        for rev in prop._reverse_property:
            # reverse props that are MANYTOONE are loading *this*
            # object from get(), so don't need to eager out to those.
            if rev.direction is interfaces.MANYTOONE and \
                        rev._use_get and \
                        not isinstance(rev.strategy, LazyLoader):
                q = q.options(EagerLazyOption(rev.key, lazy='select'))

        if state.load_options:
            q = q._conditional_options(*state.load_options)

        q = q.filter(strategy.lazy_clause(state))

        result = q.all()
        if strategy.uselist:
            return result
        else:
            l = len(result)
            if l:
                if l > 1:
                    util.warn(
                        "Multiple rows returned with "
                        "uselist=False for lazily-loaded attribute '%s' " %
                        prop)

                return result[0]
            else:
                return None
Example #27
0
    def is_deleted(self, state):
        """return true if the given state is marked as deleted within this UOWTransaction."""

        mapper = _state_mapper(state)
        task = self.get_task_by_mapper(mapper)
        return task.is_deleted(state)
Example #28
0
    def __call__(self, **kw):
        state = self.state
        instance_mapper = mapper._state_mapper(state)
        prop = instance_mapper.get_property(self.key)
        strategy = prop._get_strategy(LazyLoader)

        if kw.get("passive") is attributes.PASSIVE_NO_FETCH and not strategy.use_get:
            return attributes.PASSIVE_NO_RESULT

        if strategy._should_log_debug():
            strategy.logger.debug("loading %s", mapperutil.state_attribute_str(state, self.key))

        session = sessionlib._state_session(state)
        if session is None:
            raise orm_exc.DetachedInstanceError(
                "Parent instance %s is not bound to a Session; "
                "lazy load operation of attribute '%s' cannot proceed" % (mapperutil.state_str(state), self.key)
            )

        q = session.query(prop.mapper)._adapt_all_clauses()

        if state.load_path:
            q = q._with_current_path(state.load_path + (self.key,))

        # if we have a simple primary key load, use mapper.get()
        # to possibly save a DB round trip
        if strategy.use_get:
            ident = []
            allnulls = True
            for primary_key in prop.mapper.primary_key:
                val = instance_mapper._get_committed_state_attr_by_column(
                    state, state.dict, strategy._equated_columns[primary_key], **kw
                )
                if val is attributes.PASSIVE_NO_RESULT:
                    return val
                allnulls = allnulls and val is None
                ident.append(val)

            if allnulls:
                return None

            if state.load_options:
                q = q._conditional_options(*state.load_options)

            key = prop.mapper.identity_key_from_primary_key(ident)
            return q._get(key, ident, **kw)

        if prop.order_by:
            q = q.order_by(*util.to_list(prop.order_by))

        for rev in prop._reverse_property:
            # reverse props that are MANYTOONE are loading *this*
            # object from get(), so don't need to eager out to those.
            if rev.direction is interfaces.MANYTOONE and rev._use_get and not isinstance(rev.strategy, LazyLoader):
                q = q.options(EagerLazyOption(rev.key, lazy="select"))

        if state.load_options:
            q = q._conditional_options(*state.load_options)

        q = q.filter(strategy.lazy_clause(state))

        result = q.all()
        if strategy.uselist:
            return result
        else:
            l = len(result)
            if l:
                if l > 1:
                    util.warn("Multiple rows returned with " "uselist=False for lazily-loaded attribute '%s' " % prop)

                return result[0]
            else:
                return None
Example #29
0
    def is_deleted(self, state):
        """return true if the given state is marked as deleted within this UOWTransaction."""

        mapper = _state_mapper(state)
        task = self.get_task_by_mapper(mapper)
        return task.is_deleted(state)
Example #30
0
    def flush(self, session, objects=None):
        """create a dependency tree of all pending SQL operations within this unit of work and execute."""

        dirty = [x for x in self.identity_map.all_states()
            if x.modified
            or (x.class_._class_state.has_mutable_scalars and x.is_modified())
        ]
        
        if not dirty and not self.deleted and not self.new:
            return
        
        deleted = util.Set(self.deleted)
        new = util.Set(self.new)
        
        dirty = util.Set(dirty).difference(deleted)
        
        flush_context = UOWTransaction(self, session)

        if session.extension is not None:
            session.extension.before_flush(session, flush_context, objects)

        # create the set of all objects we want to operate upon
        if objects:
            # specific list passed in
            objset = util.Set([o._state for o in objects])
        else:
            # or just everything
            objset = util.Set(self.identity_map.all_states()).union(new)
            
        # store objects whose fate has been decided
        processed = util.Set()

        # put all saves/updates into the flush context.  detect top-level orphans and throw them into deleted.
        for state in new.union(dirty).intersection(objset).difference(deleted):
            if state in processed:
                continue

            obj = state.obj()
            is_orphan = _state_mapper(state)._is_orphan(obj)
            if is_orphan and 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 _state_mapper(state).delete_orphans])
                    ))
            flush_context.register_object(state, isdelete=is_orphan)
            processed.add(state)

        # put all remaining deletes into the flush context.
        for state in deleted.intersection(objset).difference(processed):
            flush_context.register_object(state, isdelete=True)

        if len(flush_context.tasks) == 0:
            return
            
        session.create_transaction(autoflush=False)
        flush_context.transaction = session.transaction
        try:
            flush_context.execute()
            
            if session.extension is not None:
                session.extension.after_flush(session, flush_context)
            session.commit()
        except:
            session.rollback()
            raise

        for state in deleted.intersection(objset):
            state.is_deleted = True

        flush_context.post_exec()

        if session.extension is not None:
            session.extension.after_flush_postexec(session, flush_context)
Example #31
0
    def flush(self, session, objects=None):
        """create a dependency tree of all pending SQL operations within this unit of work and execute."""

        dirty = [
            x for x in self.identity_map.all_states() if x.modified or (
                x.class_._class_state.has_mutable_scalars and x.is_modified())
        ]

        if not dirty and not self.deleted and not self.new:
            return

        deleted = util.Set(self.deleted)
        new = util.Set(self.new)

        dirty = util.Set(dirty).difference(deleted)

        flush_context = UOWTransaction(self, session)

        if session.extension is not None:
            session.extension.before_flush(session, flush_context, objects)

        # create the set of all objects we want to operate upon
        if objects:
            # specific list passed in
            objset = util.Set([o._state for o in objects])
        else:
            # or just everything
            objset = util.Set(self.identity_map.all_states()).union(new)

        # store objects whose fate has been decided
        processed = util.Set()

        # put all saves/updates into the flush context.  detect top-level orphans and throw them into deleted.
        for state in new.union(dirty).intersection(objset).difference(deleted):
            if state in processed:
                continue

            flush_context.register_object(
                state, isdelete=_state_mapper(state)._is_orphan(state.obj()))
            processed.add(state)

        # put all remaining deletes into the flush context.
        for state in deleted.intersection(objset).difference(processed):
            flush_context.register_object(state, isdelete=True)

        if len(flush_context.tasks) == 0:
            return

        session.create_transaction(autoflush=False)
        flush_context.transaction = session.transaction
        try:
            flush_context.execute()

            if session.extension is not None:
                session.extension.after_flush(session, flush_context)
            session.commit()
        except:
            session.rollback()
            raise

        flush_context.post_exec()

        if session.extension is not None:
            session.extension.after_flush_postexec(session, flush_context)