Example #1
0
        def fget(instance):
            dict_ = attributes.instance_dict(instance)

            if self.key not in dict_:
                # key not present.  Iterate through related
                # attributes, retrieve their values.  This
                # ensures they all load.
                values = [getattr(instance, key) for key in self._attribute_keys]

                # usually, the load() event will have loaded our key
                # at this point, unless we only loaded relationship()
                # attributes above.  Populate here if that's the case.
                if self.key not in dict_ and not _none_set.issuperset(values):
                    dict_[self.key] = self.composite_class(*values)

            return dict_.get(self.key, None)
Example #2
0
        def fget(instance):
            dict_ = attributes.instance_dict(instance)

            if self.key not in dict_:
                # key not present.  Iterate through related
                # attributes, retrieve their values.  This
                # ensures they all load.
                values = [
                    getattr(instance, key) for key in self._attribute_keys
                ]

                # usually, the load() event will have loaded our key
                # at this point, unless we only loaded relationship()
                # attributes above.  Populate here if that's the case.
                if self.key not in dict_ and not _none_set.issuperset(values):
                    dict_[self.key] = self.composite_class(*values)

            return dict_.get(self.key, None)
Example #3
0
        def fget(instance):
            dict_ = attributes.instance_dict(instance)
            state = attributes.instance_state(instance)

            if self.key not in dict_:
                # key not present.  Iterate through related
                # attributes, retrieve their values.  This
                # ensures they all load.
                values = [getattr(instance, key) for key in self._attribute_keys]

                # current expected behavior here is that the composite is
                # created on access if the object is persistent or if 
                # col attributes have non-None.  This would be better 
                # if the composite were created unconditionally,
                # but that would be a behavioral change.
                if self.key not in dict_ and (
                    state.key is not None or 
                    not _none_set.issuperset(values)
                ):
                    dict_[self.key] = self.composite_class(*values)
                    state.manager.dispatch.refresh(state, None, [self.key])

            return dict_.get(self.key, None)
Example #4
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
Example #5
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