From: Mike Bayer Date: Mon, 4 Dec 2006 21:17:05 +0000 (+0000) Subject: fixed up some debug logging to be conditional, adds speed. made some X-Git-Tag: rel_0_3_2~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76772de158636eed95884df836e5d55030bfc815;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git fixed up some debug logging to be conditional, adds speed. made some attribute-related lambdas more direct. --- diff --git a/CHANGES b/CHANGES index 8e013d73a8..45caad5772 100644 --- a/CHANGES +++ b/CHANGES @@ -1,10 +1,13 @@ 0.3.2 +- major speed enhancements vs. 0.3.1 + - made conditional dozens of debug log calls that were + time-intensive to generate log messages + - fixed bug in cascade rules whereby the entire object graph + could be unnecessarily cascaded on the save/update cascade - added keywords for EXCEPT, INTERSECT, EXCEPT ALL, INTERSECT ALL [ticket:247] - added label() function to Select class, when scalar=True is used to create a scalar subquery. -- added extra check to "stop" cascading on save/update/save-update if -an instance is detected to be already in the session. - fix to session.update() to preserve "dirty" status of incoming object - sending a selectable to an IN no longer creates a "union" out of multiple selects; only one selectable to an IN is allowed now (make a union yourself diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index f7fb98673e..915ccd209f 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -25,17 +25,17 @@ class InstrumentedAttribute(object): self.mutable_scalars = mutable_scalars if copy_function is None: if uselist: - self._copyfunc = lambda x: [y for y in x] + self.copy = lambda x:[y for y in x] else: # scalar values are assumed to be immutable unless a copy function # is passed - self._copyfunc = lambda x: x + self.copy = lambda x:x else: - self._copyfunc = copy_function + self.copy = lambda x:copy_function(x) if compare_function is None: - self._compare_function = lambda x,y: x == y + self.is_equal = lambda x,y: x == y else: - self._compare_function = compare_function + self.is_equal = compare_function self.extensions = util.to_list(extension or []) def __set__(self, obj, value): @@ -47,11 +47,6 @@ class InstrumentedAttribute(object): return self return self.get(obj) - def is_equal(self, x, y): - return self._compare_function(x, y) - def copy(self, value): - return self._copyfunc(value) - def check_mutable_modified(self, obj): if self.mutable_scalars: h = self.get_history(obj, passive=True) diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index a3a92841de..82234c34a8 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -18,6 +18,8 @@ class ColumnLoader(LoaderStrategy): def init(self): super(ColumnLoader, self).init() self.columns = self.parent_property.columns + self._should_log_debug = logging.is_debug_enabled(self.logger) + def setup_query(self, context, eagertable=None, **kwargs): for c in self.columns: if eagertable is not None: @@ -27,11 +29,13 @@ class ColumnLoader(LoaderStrategy): def init_class_attribute(self): self.logger.info("register managed attribute %s on class %s" % (self.key, self.parent.class_.__name__)) - sessionlib.attribute_manager.register_attribute(self.parent.class_, self.key, uselist=False, copy_function=lambda x: self.columns[0].type.copy_value(x), compare_function=lambda x,y:self.columns[0].type.compare_values(x,y), mutable_scalars=self.columns[0].type.is_mutable()) + coltype = self.columns[0].type + sessionlib.attribute_manager.register_attribute(self.parent.class_, self.key, uselist=False, copy_function=coltype.copy_value, compare_function=coltype.compare_values, mutable_scalars=self.columns[0].type.is_mutable()) def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: - self.logger.debug("populating %s with %s/%s" % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) + if self._should_log_debug: + self.logger.debug("populating %s with %s/%s" % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) instance.__dict__[self.key] = row[self.columns[0]] ColumnLoader.logger = logging.class_logger(ColumnLoader) @@ -43,6 +47,7 @@ class DeferredColumnLoader(LoaderStrategy): super(DeferredColumnLoader, self).init() self.columns = self.parent_property.columns self.group = self.parent_property.group + self._should_log_debug = logging.is_debug_enabled(self.logger) def init_class_attribute(self): self.logger.info("register managed attribute %s on class %s" % (self.key, self.parent.class_.__name__)) @@ -66,7 +71,8 @@ class DeferredColumnLoader(LoaderStrategy): if prop is not self.parent_property: return prop._get_strategy(DeferredColumnLoader).setup_loader(instance) def lazyload(): - self.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str(instance, self.key), str(self.group))) + if self._should_log_debug: + self.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str(instance, self.key), str(self.group))) try: pk = self.parent.pks_by_table[self.columns[0].table] except KeyError: @@ -130,6 +136,7 @@ class AbstractRelationLoader(LoaderStrategy): self.attributeext = self.parent_property.attributeext self.order_by = self.parent_property.order_by self.remote_side = self.parent_property.remote_side + self._should_log_debug = logging.is_debug_enabled(self.logger) def _init_instance_attribute(self, instance, callable_=None): return sessionlib.attribute_manager.init_instance_attribute(instance, self.key, self.uselist, cascade=self.cascade, trackparent=True, callable_=callable_) @@ -144,7 +151,8 @@ class NoLoader(AbstractRelationLoader): def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: if not self.is_default or len(selectcontext.options): - self.logger.debug("set instance-level no loader on %s" % mapperutil.attribute_str(instance, self.key)) + if self._should_log_debug: + self.logger.debug("set instance-level no loader on %s" % mapperutil.attribute_str(instance, self.key)) self._init_instance_attribute(instance) NoLoader.logger = logging.class_logger(NoLoader) @@ -297,7 +305,7 @@ class EagerLoader(AbstractRelationLoader): self.clauses = {} self.clauses_by_lead_mapper = {} - self.__should_log_debug = logging.is_debug_enabled(self.logger) + class AliasedClauses(object): """defines a set of join conditions and table aliases which are aliased on a randomly-generated alias name, corresponding to the connection of an optional parent AliasedClauses object and a @@ -480,7 +488,7 @@ class EagerLoader(AbstractRelationLoader): identity_key = self.mapper.identity_key_from_row(decorated_row) except KeyError: # else degrade to a lazy loader - if self.__should_log_debug: + if self._should_log_debug: self.logger.debug("degrade to lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) self.parent_property._get_strategy(LazyLoader).process_row(selectcontext, instance, row, identitykey, isnew) return @@ -490,7 +498,7 @@ class EagerLoader(AbstractRelationLoader): selectcontext.recursion_stack.add(self) try: if not self.uselist: - if self.__should_log_debug: + if self._should_log_debug: self.logger.debug("eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key)) if isnew: # set a scalar object instance directly on the parent object, @@ -502,7 +510,7 @@ class EagerLoader(AbstractRelationLoader): self.mapper._instance(selectcontext, decorated_row, None) else: if isnew: - if self.__should_log_debug: + if self._should_log_debug: self.logger.debug("initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key)) # call the SmartProperty's initialize() method to create a new, blank list l = getattr(instance.__class__, self.key).initialize(instance) @@ -513,7 +521,7 @@ class EagerLoader(AbstractRelationLoader): # store it in the "scratch" area, which is local to this load operation. selectcontext.attributes[(instance, self.key)] = appender result_list = selectcontext.attributes[(instance, self.key)] - if self.__should_log_debug: + if self._should_log_debug: self.logger.debug("eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key)) self.mapper._instance(selectcontext, decorated_row, result_list) finally: diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py index 4ecf8b4a04..3c1238287b 100644 --- a/lib/sqlalchemy/orm/unitofwork.py +++ b/lib/sqlalchemy/orm/unitofwork.py @@ -116,17 +116,13 @@ class UnitOfWork(object): attribute_manager.set_callable(obj, key, func, uselist, **kwargs) def register_clean(self, obj): - try: + if obj in self.new: self.new.remove(obj) - except KeyError: - pass if not hasattr(obj, '_instance_key'): mapper = object_mapper(obj) obj._instance_key = mapper.instance_key(obj) - try: + if hasattr(obj, '_sa_insert_order'): delattr(obj, '_sa_insert_order') - except AttributeError: - pass self.identity_map[obj._instance_key] = obj attribute_manager.commit(obj)