def __call__(self): if not mapper.has_identity(self.instance): return None localparent = mapper.object_mapper(self.instance, raiseerror=False) 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.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 self.instance._state.unmodified] if strategy._should_log_debug: strategy.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str(self.instance, self.key), group and ','.join(group) or 'None')) session = sessionlib.object_session(self.instance) if session is None: raise exceptions.UnboundExecutionError("Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (self.instance.__class__, self.key)) query = session.query(localparent) if not self.optimizing_statement: ident = self.instance._instance_key[1] query._get(None, ident=ident, only_load_props=group, refresh_instance=self.instance._state) else: statement, params = self.optimizing_statement(self.instance) query.from_statement(statement).params(params)._get(None, only_load_props=group, refresh_instance=self.instance._state) return attributes.ATTR_WAS_SET
def __session(self): sess = object_session(self.instance) if sess is not None and self.autoflush and sess.autoflush and self.instance in sess: sess.flush() if not has_identity(self.instance): return None else: return sess
def assign(self, collection): instance = self.state.obj() if has_identity(instance): oldlist = list(self) else: oldlist = [] self.attr.get_history(self.state).replace(oldlist, collection) return oldlist
def assign(self, collection): instance = self.instance if has_identity(instance): oldlist = list(self) else: oldlist = [] self.attr._get_collection_history(self.instance._state, passive=True).replace(oldlist, collection) return oldlist
def assign(self, collection): instance = self.instance if has_identity(instance): oldlist = list(self) else: oldlist = [] self.attr._get_collection(self.instance._state, passive=True).replace(oldlist, collection) return oldlist
def lazyload(): if self._should_log_debug: self.logger.debug( "lazy load attribute %s on instance %s" % (self.key, mapperutil.instance_str(instance))) if not mapper.has_identity(instance): return None session = sessionlib.object_session(instance) if session is None: try: session = mapper.object_mapper(instance).get_session() except exceptions.InvalidRequestError: raise exceptions.InvalidRequestError( "Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) # if we have a simple straight-primary key load, use mapper.get() # to possibly save a DB round trip q = session.query(self.mapper).autoflush(False) if self.use_get: params = {} for col, bind in self.lazybinds.iteritems(): params[bind.key] = self.parent.get_attr_by_column( instance, col) ident = [] nonnulls = False for primary_key in self.select_mapper.primary_key: bind = self.lazyreverse[primary_key] v = params[bind.key] if v is not None: nonnulls = True ident.append(v) if not nonnulls: return None if options: q = q.options(*options) return q.get(ident) elif self.order_by is not False: q = q.order_by(self.order_by) elif self.secondary is not None and self.secondary.default_order_by( ) is not None: q = q.order_by(self.secondary.default_order_by()) if options: q = q.options(*options) q = q.filter(self.lazy_clause(instance)) result = q.all() if self.uselist: return result else: if result: return result[0] else: return None
def __session(self): instance = self.state.obj() sess = object_session(instance) if sess is not None and instance in sess and sess.autoflush: sess.flush() if not has_identity(instance): return None else: return sess
def lazyload(): if self._should_log_debug: self.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str( instance, self.key), str(self.group))) if not mapper.has_identity(instance): return None try: pk = self.parent.pks_by_table[self.columns[0].table] except KeyError: pk = self.columns[0].table.primary_key clause = sql.and_() for primary_key in pk: attr = self.parent.get_attr_by_column(instance, primary_key) if not attr: return None clause.clauses.append(primary_key == attr) session = sessionlib.object_session(instance) if session is None: raise exceptions.InvalidRequestError( "Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) localparent = mapper.object_mapper(instance) if self.group is not None: groupcols = [ p for p in localparent.props.values() if isinstance(p.strategy, DeferredColumnLoader) and p.group == self.group ] result = session.execute( localparent, sql.select([g.columns[0] for g in groupcols], clause, use_labels=True), None) try: row = result.fetchone() for prop in groupcols: if prop is self: continue # set a scalar object instance directly on the object, # bypassing SmartProperty event handlers. sessionlib.attribute_manager.init_instance_attribute( instance, prop.key, uselist=False) instance.__dict__[prop.key] = row[prop.columns[0]] return row[self.columns[0]] finally: result.close() else: return session.scalar( localparent, sql.select([self.columns[0]], clause, use_labels=True), None)
def __call__(self): instance = self.instance if not mapper.has_identity(instance): return None instance_mapper = mapper.object_mapper(instance) prop = instance_mapper.get_property(self.key) strategy = prop._get_strategy(LazyLoader) if strategy._should_log_debug: strategy.logger.debug("lazy load attribute %s on instance %s" % (self.key, mapperutil.instance_str(instance))) session = sessionlib.object_session(instance) if session is None: try: session = instance_mapper.get_session() except exceptions.InvalidRequestError: raise exceptions.UnboundExecutionError("Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) q = session.query(prop.mapper).autoflush(False) 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_attr_by_column(instance, 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 strategy.order_by is not False: q = q.order_by(strategy.order_by) elif strategy.secondary is not None and strategy.secondary.default_order_by() is not None: q = q.order_by(strategy.secondary.default_order_by()) if self.options: q = q._conditional_options(*self.options) q = q.filter(strategy.lazy_clause(instance)) result = q.all() if strategy.uselist: return result else: if result: return result[0] else: return None
def lazyload(): if not mapper.has_identity(instance): return None if props is not None: group = props elif self.group is not None: group = [ p for p in localparent.iterate_properties if isinstance(p.strategy, DeferredColumnLoader) and p.group == self.group ] else: group = [self.parent_property] if self._should_log_debug: self.logger.debug( "deferred load %s group %s" % (mapperutil.attribute_str(instance, self.key), group and ','.join([p.key for p in group]) or 'None')) session = sessionlib.object_session(instance) if session is None: raise exceptions.InvalidRequestError( "Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) if create_statement is None: (clause, param_map) = localparent._get_clause ident = instance._instance_key[1] params = {} for i, primary_key in enumerate(localparent.primary_key): params[param_map[primary_key].key] = ident[i] statement = sql.select([p.columns[0] for p in group], clause, from_obj=[localparent.mapped_table], use_labels=True) else: statement, params = create_statement() # TODO: have the "fetch of one row" operation go through the same channels as a query._get() # deferred load of several attributes should be a specialized case of a query refresh operation conn = session.connection(mapper=localparent, instance=instance) result = conn.execute(statement, params) try: row = result.fetchone() for prop in group: sessionlib.attribute_manager.set_committed_value( instance, prop.key, row[prop.columns[0]]) return attributes.ATTR_WAS_SET finally: result.close()
def lazyload(): self.logger.debug("lazy load attribute %s on instance %s" % (self.key, mapperutil.instance_str(instance))) params = {} allparams = True # if the instance wasnt loaded from the database, then it cannot lazy load # child items. one reason for this is that a bi-directional relationship # will not update properly, since bi-directional uses lazy loading functions # in both directions, and this instance will not be present in the lazily-loaded # results of the other objects since its not in the database if not mapper.has_identity(instance): return None #print "setting up loader, lazywhere", str(self.lazywhere), "binds", self.lazybinds for col, bind in self.lazybinds.iteritems(): params[bind.key] = self.parent.get_attr_by_column(instance, col) if params[bind.key] is None: allparams = False break if not allparams: return None session = sessionlib.object_session(instance) if session is None: try: session = mapper.object_mapper(instance).get_session() except exceptions.InvalidRequestError: raise exceptions.InvalidRequestError("Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) # if we have a simple straight-primary key load, use mapper.get() # to possibly save a DB round trip if self.use_get: ident = [] for primary_key in self.select_mapper.pks_by_table[self.select_mapper.mapped_table]: bind = self.lazyreverse[primary_key] ident.append(params[bind.key]) return session.query(self.mapper).get(ident) elif self.order_by is not False: order_by = self.order_by elif self.secondary is not None and self.secondary.default_order_by() is not None: order_by = self.secondary.default_order_by() else: order_by = False result = session.query(self.mapper, with_options=options).select_whereclause(self.lazywhere, order_by=order_by, params=params) if self.uselist: return result else: if len(result): return result[0] else: return None
def lazyload(): if self._should_log_debug: self.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str(instance, self.key), str(self.group))) if not mapper.has_identity(instance): return None try: pk = self.parent.pks_by_table[self.columns[0].table] except KeyError: pk = self.columns[0].table.primary_key clause = sql.and_() for primary_key in pk: attr = self.parent.get_attr_by_column(instance, primary_key) if not attr: return None clause.clauses.append(primary_key == attr) session = sessionlib.object_session(instance) if session is None: raise exceptions.InvalidRequestError("Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) localparent = mapper.object_mapper(instance) if self.group is not None: groupcols = [p for p in localparent.props.values() if isinstance(p.strategy, DeferredColumnLoader) and p.group==self.group] result = session.execute(localparent, sql.select([g.columns[0] for g in groupcols], clause, use_labels=True), None) try: row = result.fetchone() for prop in groupcols: if prop is self: continue # set a scalar object instance directly on the object, # bypassing SmartProperty event handlers. sessionlib.attribute_manager.init_instance_attribute(instance, prop.key, uselist=False) instance.__dict__[prop.key] = row[prop.columns[0]] return row[self.columns[0]] finally: result.close() else: return session.scalar(localparent, sql.select([self.columns[0]], clause, use_labels=True),None)
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)
def lazyload(): self.logger.debug("lazy load attribute %s on instance %s" % (self.key, mapperutil.instance_str(instance))) params = {} allparams = True # if the instance wasnt loaded from the database, then it cannot lazy load # child items. one reason for this is that a bi-directional relationship # will not update properly, since bi-directional uses lazy loading functions # in both directions, and this instance will not be present in the lazily-loaded # results of the other objects since its not in the database if not mapper.has_identity(instance): return None #print "setting up loader, lazywhere", str(self.lazywhere), "binds", self.lazybinds for col, bind in self.lazybinds.iteritems(): params[bind.key] = self.parent.get_attr_by_column( instance, col) if params[bind.key] is None: allparams = False break if not allparams: return None session = sessionlib.object_session(instance) if session is None: try: session = mapper.object_mapper(instance).get_session() except exceptions.InvalidRequestError: raise exceptions.InvalidRequestError( "Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) # if we have a simple straight-primary key load, use mapper.get() # to possibly save a DB round trip if self.use_get: ident = [] for primary_key in self.select_mapper.pks_by_table[ self.select_mapper.mapped_table]: bind = self.lazyreverse[primary_key] ident.append(params[bind.key]) return session.query(self.mapper).get(ident) elif self.order_by is not False: order_by = self.order_by elif self.secondary is not None and self.secondary.default_order_by( ) is not None: order_by = self.secondary.default_order_by() else: order_by = False result = session.query(self.mapper, with_options=options).select_whereclause( self.lazywhere, order_by=order_by, params=params) if self.uselist: return result else: if len(result): return result[0] else: return None
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 flush_context.post_exec() if session.extension is not None: session.extension.after_flush_postexec(session, flush_context)