Exemple #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)
Exemple #2
0
    def execute(self, source, dest, parent, child, clearkeys):
        # TODO: break the "dictionary" case into a separate method like 'update' above,
        # reduce conditionals
        if source is None:
            if self.issecondary is False:
                source = parent
            elif self.issecondary is True:
                source = child
        if clearkeys or source is None:
            value = None
            clearkeys = True
        else:
            try:
                value = self.source_mapper._get_state_attr_by_column(
                    source, self.source_column)
            except exceptions.UnmappedColumnError:
                self._raise_col_to_prop(False)
        if isinstance(dest, dict):
            dest[self.dest_column.key] = value
        else:
            if clearkeys and self.dest_primary_key():
                raise exceptions.AssertionError(
                    "Dependency rule tried to blank-out primary key column '%s' on instance '%s'"
                    % (str(self.dest_column), mapperutil.state_str(dest)))

            if logging.is_debug_enabled(self.logger):
                self.logger.debug(
                    "execute() instances: %s(%s)->%s(%s) ('%s')" %
                    (mapperutil.state_str(source), str(self.source_column),
                     mapperutil.state_str(dest), str(self.dest_column), value))
            try:
                self.dest_mapper._set_state_attr_by_column(
                    dest, self.dest_column, value)
            except exceptions.UnmappedColumnError:
                self._raise_col_to_prop(True)
Exemple #3
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)
def _organize_states_for_save(base_mapper, states, uowtransaction):
    """Make an initial pass across a set of states for INSERT or
    UPDATE.

    This includes splitting out into distinct lists for
    each, calling before_insert/before_update, obtaining
    key information for each state including its dictionary,
    mapper, the connection to use for the execution per state,
    and the identity flag.

    """

    states_to_insert = []
    states_to_update = []

    for state, dict_, mapper, connection in _connections_for_states(base_mapper, uowtransaction, states):

        has_identity = bool(state.key)
        instance_key = state.key or mapper._identity_key_from_state(state)

        row_switch = None

        # call before_XXX extensions
        if not has_identity:
            mapper.dispatch.before_insert(mapper, connection, state)
        else:
            mapper.dispatch.before_update(mapper, connection, state)

        # detect if we have a "pending" instance (i.e. has
        # no instance_key attached to it), and another instance
        # with the same identity key already exists as persistent.
        # convert to an UPDATE if so.
        if not has_identity and instance_key in uowtransaction.session.identity_map:
            instance = uowtransaction.session.identity_map[instance_key]
            existing = attributes.instance_state(instance)
            if not uowtransaction.is_deleted(existing):
                raise orm_exc.FlushError(
                    "New instance %s with identity key %s conflicts "
                    "with persistent instance %s" % (state_str(state), instance_key, state_str(existing))
                )

            base_mapper._log_debug(
                "detected row switch for identity %s.  " "will update %s, remove %s from " "transaction",
                instance_key,
                state_str(state),
                state_str(existing),
            )

            # remove the "delete" flag from the existing element
            uowtransaction.remove_state_actions(existing)
            row_switch = existing

        if not has_identity and not row_switch:
            states_to_insert.append((state, dict_, mapper, connection, has_identity, instance_key, row_switch))
        else:
            states_to_update.append((state, dict_, mapper, connection, has_identity, instance_key, row_switch))

    return states_to_insert, states_to_update
Exemple #5
0
 def _repr_task_element(self, te, attribute=None, process=False):
     if getattr(te, 'state', None) is None:
         objid = "(placeholder)"
     else:
         if attribute is not None:
             objid = "%s.%s" % (mapperutil.state_str(te.state), attribute)
         else:
             objid = mapperutil.state_str(te.state)
     if process:
         return "Process %s" % (objid)
     else:
         return "%s %s" % ((te.isdelete and "Delete" or "Save"), objid)
Exemple #6
0
 def _repr_task_element(self, te, attribute=None, process=False):
     if getattr(te, 'state', None) is None:
         objid = "(placeholder)"
     else:
         if attribute is not None:
             objid = "%s.%s" % (mapperutil.state_str(te.state), attribute)
         else:
             objid = mapperutil.state_str(te.state)
     if process:
         return "Process %s" % (objid)
     else:
         return "%s %s" % ((te.isdelete and "Delete" or "Save"), objid)
Exemple #7
0
 def _repr_task_element(self, te, attribute=None, process=False):
     if getattr(te, 'state', None) is None:
         objid = "(placeholder)"
     else:
         if attribute is not None:
             objid = "%s.%s" % (mapperutil.state_str(te.state), attribute)
         else:
             objid = mapperutil.state_str(te.state)
     if self.verbose:
         return "%s (UOWTaskElement(%s, %s))" % (objid, hex(id(te)), (te.listonly and 'listonly' or (te.isdelete and 'delete' or 'save')))
     elif process:
         return "Process %s" % (objid)
     else:
         return "%s %s" % ((te.isdelete and "Delete" or "Save"), objid)
Exemple #8
0
    def _load_for_state(self, state, passive):
        if not state.key:
            return attributes.ATTR_EMPTY

        if passive is attributes.PASSIVE_NO_FETCH:
            return attributes.PASSIVE_NO_RESULT

        prop = self.parent_property
        localparent = state.manager.mapper

        if self.group:
            toload = [
                p.key for p in localparent.iterate_properties
                if isinstance(p, StrategizedProperty) and isinstance(
                    p.strategy, DeferredColumnLoader) and p.group == self.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]

        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)
        query._load_on_ident(state.key,
                             only_load_props=group,
                             refresh_state=state)
        return attributes.ATTR_WAS_SET
Exemple #9
0
 def __repr__(self):
     return "%s(%s, %s, delete=%s)" % (
         self.__class__.__name__,
         self.dependency_processor,
         mapperutil.state_str(self.state),
         self.delete
     )
Exemple #10
0
 def __repr__(self):
     return "%s(%s, %s, delete=%s)" % (
         self.__class__.__name__,
         self.dependency_processor,
         mapperutil.state_str(self.state),
         self.delete
     )
Exemple #11
0
 def _repr_task_element(self, te, attribute=None, process=False):
     if getattr(te, 'state', None) is None:
         objid = "(placeholder)"
     else:
         if attribute is not None:
             objid = "%s.%s" % (mapperutil.state_str(te.state), attribute)
         else:
             objid = mapperutil.state_str(te.state)
     if self.verbose:
         return "%s (UOWTaskElement(%s, %s))" % (objid, hex(
             id(te)), (te.listonly and 'listonly' or
                       (te.isdelete and 'delete' or 'save')))
     elif process:
         return "Process %s" % (objid)
     else:
         return "%s %s" % ((te.isdelete and "Delete" or "Save"), objid)
Exemple #12
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
Exemple #13
0
def clear(dest, dest_mapper, synchronize_pairs):
    for l, r in synchronize_pairs:
        if r.primary_key:
            raise AssertionError(
                "Dependency rule tried to blank-out primary key column '%s' on instance '%s'"
                % (r, mapperutil.state_str(dest)))
        try:
            dest_mapper._set_state_attr_by_column(dest, r, None)
        except exc.UnmappedColumnError:
            _raise_col_to_prop(True, None, l, dest_mapper, r)
Exemple #14
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
Exemple #15
0
def clear(dest, dest_mapper, synchronize_pairs):
    for l, r in synchronize_pairs:
        if r.primary_key:
            raise AssertionError(
                "Dependency rule tried to blank-out primary key "
                "column '%s' on instance '%s'" % (r, mapperutil.state_str(dest))
            )
        try:
            dest_mapper._set_state_attr_by_column(dest, dest.dict, r, None)
        except exc.UnmappedColumnError:
            _raise_col_to_prop(True, None, l, dest_mapper, r)
Exemple #16
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)
Exemple #17
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
Exemple #18
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
Exemple #19
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
Exemple #20
0
    def _load_for_state(self, state, passive):
        if not state.key:
            return attributes.ATTR_EMPTY

        if passive is attributes.PASSIVE_NO_FETCH:
            return attributes.PASSIVE_NO_RESULT

        prop = self.parent_property
        localparent = state.manager.mapper

        if self.group:
            toload = [
                    p.key for p in 
                    localparent.iterate_properties 
                    if isinstance(p, StrategizedProperty) and 
                      isinstance(p.strategy, DeferredColumnLoader) and 
                      p.group==self.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]

        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)
        query._load_on_ident(state.key, 
                    only_load_props=group, refresh_state=state)
        return attributes.ATTR_WAS_SET
Exemple #21
0
    def _load_for_state(self, state, passive):
        if not state.key and \
            (not self.parent_property.load_on_pending or not state.session_id):
            return attributes.ATTR_EMPTY

        instance_mapper = state.manager.mapper
        prop = self.parent_property
        key = self.key
        prop_mapper = self.mapper
        pending = not state.key

        if (
                (passive is attributes.PASSIVE_NO_FETCH or \
                    passive is attributes.PASSIVE_NO_FETCH_RELATED) and
                not self.use_get
            ) or (
                passive is attributes.PASSIVE_ONLY_PERSISTENT and
                pending
            ):
            return attributes.PASSIVE_NO_RESULT

        session = sessionlib._state_session(state)
        if not session:
            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), key))

        # if we have a simple primary key load, check the
        # identity map without generating a Query at all
        if self.use_get:
            if session._flushing:
                get_attr = instance_mapper._get_committed_state_attr_by_column
            else:
                get_attr = instance_mapper._get_state_attr_by_column

            dict_ = state.dict
            if passive is attributes.PASSIVE_NO_FETCH_RELATED:
                attr_passive = attributes.PASSIVE_OFF
            else:
                attr_passive = passive

            ident = [
                get_attr(state,
                         state.dict,
                         self._equated_columns[pk],
                         passive=attr_passive)
                for pk in prop_mapper.primary_key
            ]
            if attributes.PASSIVE_NO_RESULT in ident:
                return attributes.PASSIVE_NO_RESULT

            if _none_set.issuperset(ident):
                return None

            ident_key = prop_mapper.identity_key_from_primary_key(ident)
            instance = Query._get_from_identity(session, ident_key, passive)
            if instance is not None:
                return instance
            elif passive is attributes.PASSIVE_NO_FETCH or \
                passive is attributes.PASSIVE_NO_FETCH_RELATED:
                return attributes.PASSIVE_NO_RESULT

        q = session.query(prop_mapper)._adapt_all_clauses()

        # don't autoflush on pending
        if pending:
            q = q.autoflush(False)

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

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

        if self.use_get:
            return q._load_on_ident(ident_key)

        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'))

        lazy_clause = self.lazy_clause(state)

        if pending:
            bind_values = sql_util.bind_values(lazy_clause)
            if None in bind_values:
                return None

        q = q.filter(lazy_clause)

        result = q.all()
        if self.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
Exemple #22
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
Exemple #23
0
 def __repr__(self):
     return "%s(%s)" % (self.__class__.__name__,
                        mapperutil.state_str(self.state))
Exemple #24
0
 def __repr__(self):
     return "%s(%s)" % (
         self.__class__.__name__,
         mapperutil.state_str(self.state)
     )
Exemple #25
0
    def _load_for_state(self, state, passive):
        if not state.key and \
            (not self.parent_property.load_on_pending or not state.session_id):
            return attributes.ATTR_EMPTY

        instance_mapper = state.manager.mapper
        prop = self.parent_property
        key = self.key
        prop_mapper = self.mapper
        pending = not state.key

        if (
                (passive is attributes.PASSIVE_NO_FETCH or \
                    passive is attributes.PASSIVE_NO_FETCH_RELATED) and 
                not self.use_get
            ) or (
                passive is attributes.PASSIVE_ONLY_PERSISTENT and 
                pending
            ):
            return attributes.PASSIVE_NO_RESULT

        session = sessionlib._state_session(state)
        if not session:
            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), key)
            )

        # if we have a simple primary key load, check the 
        # identity map without generating a Query at all
        if self.use_get:
            if session._flushing:
                get_attr = instance_mapper._get_committed_state_attr_by_column
            else:
                get_attr = instance_mapper._get_state_attr_by_column

            dict_ = state.dict
            if passive is attributes.PASSIVE_NO_FETCH_RELATED:
                attr_passive = attributes.PASSIVE_OFF
            else:
                attr_passive = passive

            ident = [
                get_attr(
                        state,
                        state.dict,
                        self._equated_columns[pk],
                        passive=attr_passive)
                for pk in prop_mapper.primary_key
            ]
            if attributes.PASSIVE_NO_RESULT in ident:
                return attributes.PASSIVE_NO_RESULT

            if _none_set.issuperset(ident):
                return None

            ident_key = prop_mapper.identity_key_from_primary_key(ident)
            instance = Query._get_from_identity(session, ident_key, passive)
            if instance is not None:
                return instance
            elif passive is attributes.PASSIVE_NO_FETCH or \
                passive is attributes.PASSIVE_NO_FETCH_RELATED:
                return attributes.PASSIVE_NO_RESULT

        q = session.query(prop_mapper)._adapt_all_clauses()

        # don't autoflush on pending
        if pending:
            q = q.autoflush(False)

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

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

        if self.use_get:
            return q._load_on_ident(ident_key)

        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'))

        lazy_clause = self.lazy_clause(state)

        if pending:
            bind_values = sql_util.bind_values(lazy_clause)
            if None in bind_values:
                return None

        q = q.filter(lazy_clause)

        result = q.all()
        if self.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
Exemple #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
Exemple #27
0
def _organize_states_for_save(base_mapper, states, uowtransaction):
    """Make an initial pass across a set of states for INSERT or
    UPDATE.
    
    This includes splitting out into distinct lists for
    each, calling before_insert/before_update, obtaining
    key information for each state including its dictionary,
    mapper, the connection to use for the execution per state,
    and the identity flag.
    
    """

    states_to_insert = []
    states_to_update = []

    for state, dict_, mapper, connection in _connections_for_states(
                                            base_mapper, uowtransaction, 
                                            states):

        has_identity = bool(state.key)
        instance_key = state.key or mapper._identity_key_from_state(state)

        row_switch = None

        # call before_XXX extensions
        if not has_identity:
            mapper.dispatch.before_insert(mapper, connection, state)
        else:
            mapper.dispatch.before_update(mapper, connection, state)

        # detect if we have a "pending" instance (i.e. has 
        # no instance_key attached to it), and another instance 
        # with the same identity key already exists as persistent. 
        # convert to an UPDATE if so.
        if not has_identity and \
            instance_key in uowtransaction.session.identity_map:
            instance = \
                uowtransaction.session.identity_map[instance_key]
            existing = attributes.instance_state(instance)
            if not uowtransaction.is_deleted(existing):
                raise orm_exc.FlushError(
                    "New instance %s with identity key %s conflicts "
                    "with persistent instance %s" % 
                    (state_str(state), instance_key,
                     state_str(existing)))

            base_mapper._log_debug(
                "detected row switch for identity %s.  "
                "will update %s, remove %s from "
                "transaction", instance_key, 
                state_str(state), state_str(existing))

            # remove the "delete" flag from the existing element
            uowtransaction.remove_state_actions(existing)
            row_switch = existing

        if not has_identity and not row_switch:
            states_to_insert.append(
                (state, dict_, mapper, connection, 
                has_identity, instance_key, row_switch)
            )
        else:
            states_to_update.append(
                (state, dict_, mapper, connection, 
                has_identity, instance_key, row_switch)
            )

    return states_to_insert, states_to_update