summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-10-01 14:23:01 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-10-01 14:23:01 -0400
commit755aca7f5f3f33339dce4f4b6b92b8b7a9c3d180 (patch)
treead6e161c8c09162d7ef50f1f27bb592846f3d4b9 /lib/sqlalchemy
parent2a2257b1e7d4abb8a7657e10542e0fa45c80a8ca (diff)
downloadsqlalchemy-755aca7f5f3f33339dce4f4b6b92b8b7a9c3d180.tar.gz
- reworked the internals of mapper.cascade_iterator() to
cut down method calls by about 9% in some circumstances. [ticket:1932]
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/interfaces.py14
-rw-r--r--lib/sqlalchemy/orm/mapper.py35
-rw-r--r--lib/sqlalchemy/orm/properties.py3
3 files changed, 35 insertions, 17 deletions
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index 0a65c8a44..fa27859ec 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -76,7 +76,7 @@ class MapperExtension(object):
mapper activity will not be performed.
"""
-
+
def instrument_class(self, mapper, class_):
"""Receive a class when the mapper is first constructed, and has
applied instrumentation to the mapped class.
@@ -418,6 +418,13 @@ class MapperProperty(object):
attribute access, loading behavior, and dependency calculations.
"""
+ cascade = ()
+ """The set of 'cascade' attribute names.
+
+ This collection is checked before the 'cascade_iterator' method is called.
+
+ """
+
def setup(self, context, entity, path, adapter, **kwargs):
"""Called by Query for the purposes of constructing a SQL statement.
@@ -469,6 +476,11 @@ class MapperProperty(object):
halt_on=None):
"""Iterate through instances related to the given instance for
a particular 'cascade', starting with this MapperProperty.
+
+ Return an iterator3-tuples (instance, mapper, state).
+
+ Note that the 'cascade' collection on this MapperProperty is
+ checked first for the given type before cascade_iterator is called.
See PropertyLoader for the related instance implementation.
"""
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 49f5d2190..d27b99601 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -1401,25 +1401,30 @@ class Mapper(object):
"""
visited_instances = util.IdentitySet()
- visitables = [(self._props.itervalues(), 'property', state)]
+ prp, mpp = object(), object()
+
+ visitables = [(deque(self._props.values()), prp, state)]
while visitables:
iterator, item_type, parent_state = visitables[-1]
- try:
- if item_type == 'property':
- prop = iterator.next()
- visitables.append(
- (prop.cascade_iterator(type_, parent_state,
- visited_instances, halt_on), 'mapper', None)
- )
- elif item_type == 'mapper':
- instance, instance_mapper, corresponding_state = \
- iterator.next()
- yield (instance, instance_mapper)
- visitables.append((instance_mapper._props.itervalues(),
- 'property', corresponding_state))
- except StopIteration:
+ if not iterator:
visitables.pop()
+ continue
+
+ if item_type is prp:
+ prop = iterator.popleft()
+ if type_ not in prop.cascade:
+ continue
+ queue = deque(prop.cascade_iterator(type_, parent_state,
+ visited_instances, halt_on))
+ if queue:
+ visitables.append((queue,mpp, None))
+ elif item_type is mpp:
+ instance, instance_mapper, corresponding_state = \
+ iterator.popleft()
+ yield (instance, instance_mapper)
+ visitables.append((deque(instance_mapper._props.values()),
+ prp, corresponding_state))
@_memoized_compiled_property
def _compiled_cache(self):
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index a5e6930b2..4efd2acc9 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -868,7 +868,8 @@ class RelationshipProperty(StrategizedProperty):
# cascade using the mapper local to this
# object, so that its individual properties are located
instance_mapper = instance_state.manager.mapper
- yield (c, instance_mapper, instance_state)
+ yield c, instance_mapper, instance_state
+
def _add_reverse_property(self, key):
other = self.mapper.get_property(key, _compile_mappers=False)