def get(self, state, dict_, passive=attributes.PASSIVE_OFF): if self.key in dict_: return dict_[self.key] # Retrieve the session bound to the state in order to perform # a lazy query for the attribute. session = _state_session(state) if session is None: # State is not bound to a session; we cannot proceed. return None # Find class for discriminator. # TODO: Perhaps optimize with some sort of lookup? discriminator = state.attrs[self.parent_token.discriminator.key].value target_class = None for class_ in state.class_._decl_class_registry.values(): name = table_name(class_) if name and name == discriminator: target_class = class_ if target_class is None: # Unknown discriminator; return nothing. return None # Lookup row with the discriminator and id. id = state.attrs[self.parent_token.id.key].value target = session.query(target_class).get(id) # Return found (or not found) target. return target
def get(self, state, dict_, passive=attributes.PASSIVE_OFF): if self.key in dict_: return dict_[self.key] # Retrieve the session bound to the state in order to perform # a lazy query for the attribute. session = _state_session(state) if session is None: # State is not bound to a session; we cannot proceed. return None # Find class for discriminator. # TODO: Perhaps optimize with some sort of lookup? discriminator = self.get_state_discriminator(state) target_class = state.class_._decl_class_registry.get(discriminator) if target_class is None: # Unknown discriminator; return nothing. return None id = self.get_state_id(state) target = session.query(target_class).get(id) # Return found (or not found) target. return target
def lazy_clause(self, state, reverse_direction=False, alias_secondary=False, adapt_source=None): if state is None: return self._lazy_none_clause( reverse_direction, adapt_source=adapt_source) if not reverse_direction: criterion, bind_to_col, rev = \ self.__lazywhere, \ self.__bind_to_col, \ self._equated_columns else: criterion, bind_to_col, rev = \ LazyLoader._create_lazy_clause( self.parent_property, reverse_direction=reverse_direction) if reverse_direction: mapper = self.parent_property.mapper else: mapper = self.parent_property.parent o = state.obj() # strong ref dict_ = attributes.instance_dict(o) # use the "committed state" only if we're in a flush # for this state. sess = sessionlib._state_session(state) if sess is not None and sess._flushing: def visit_bindparam(bindparam): if bindparam.key in bind_to_col: bindparam.callable = \ lambda: mapper._get_committed_state_attr_by_column( state, dict_, bind_to_col[bindparam.key]) else: def visit_bindparam(bindparam): if bindparam.key in bind_to_col: bindparam.callable = lambda: mapper._get_state_attr_by_column( state, dict_, bind_to_col[bindparam.key]) if self.parent_property.secondary is not None and alias_secondary: criterion = sql_util.ClauseAdapter( self.parent_property.secondary.alias()).\ traverse(criterion) criterion = visitors.cloned_traverse( criterion, {}, {'bindparam':visit_bindparam}) if adapt_source: criterion = adapt_source(criterion) return criterion
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 __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
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
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
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
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
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
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