summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-10-06 20:12:28 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2013-10-06 20:50:51 -0400
commit22d5a1e415d603d253870719466152b9e817e1e5 (patch)
tree742d84eea2913e6c4fabe2e10d0cf12793aaf7e2 /lib/sqlalchemy
parent1b25ed907fb7311d28d2273c9b9858b50c1a7afc (diff)
downloadsqlalchemy-22d5a1e415d603d253870719466152b9e817e1e5.tar.gz
11th hour realization that Load() needs to do the _chop_path() thing as
well. this probably has some bugs
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/interfaces.py3
-rw-r--r--lib/sqlalchemy/orm/strategy_options.py77
2 files changed, 55 insertions, 25 deletions
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index 18723e4f6..f61396750 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -430,6 +430,9 @@ class StrategizedProperty(MapperProperty):
# that the path is stated in terms of our base
search_path = dict.__getitem__(path, self)
+ #if self.key == "email_address":
+ # import pdb
+ # pdb.set_trace()
# search among: exact match, "attr.*", "default" strategy
# if any.
for path_key in (
diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py
index 5f7eb2c25..c066c2dff 100644
--- a/lib/sqlalchemy/orm/strategy_options.py
+++ b/lib/sqlalchemy/orm/strategy_options.py
@@ -92,7 +92,14 @@ class Load(Generative, MapperOption):
self._process(query, False)
def _process(self, query, raiseerr):
- query._attributes.update(self.context)
+ current_path = query._current_path
+ if current_path:
+ for (token, start_path), loader in self.context.items():
+ chopped_start_path = self._chop_path(start_path, current_path)
+ if chopped_start_path is not None:
+ query._attributes[(token, chopped_start_path)] = loader
+ else:
+ query._attributes.update(self.context)
def _generate_path(self, path, attr, wildcard_key, raiseerr=True):
if raiseerr and not path.has_entity:
@@ -205,6 +212,25 @@ class Load(Generative, MapperOption):
self.__dict__.update(state)
self.path = PathRegistry.deserialize(self.path)
+ def _chop_path(self, to_chop, path):
+ i = -1
+
+ for i, (c_token, p_token) in enumerate(zip(to_chop, path.path)):
+ if isinstance(c_token, util.string_types):
+ # TODO: this is approximated from the _UnboundLoad
+ # version and probably has issues, not fully covered.
+
+ if i == 0 and c_token.endswith(':' + _DEFAULT_TOKEN):
+ return to_chop
+ elif c_token != 'relationship:%s' % (_WILDCARD_TOKEN,) and c_token != p_token.key:
+ return None
+
+ if c_token is p_token:
+ continue
+ else:
+ return None
+ return to_chop[i+1:]
+
class _UnboundLoad(Load):
"""Represent a loader option that isn't tied to a root entity.
@@ -289,6 +315,23 @@ class _UnboundLoad(Load):
return opt
+ def _chop_path(self, to_chop, path):
+ i = -1
+ for i, (c_token, (p_mapper, p_prop)) in enumerate(zip(to_chop, path.pairs())):
+ if isinstance(c_token, util.string_types):
+ if i == 0 and c_token.endswith(':' + _DEFAULT_TOKEN):
+ return to_chop
+ elif c_token != 'relationship:%s' % (_WILDCARD_TOKEN,) and c_token != p_prop.key:
+ return None
+ elif isinstance(c_token, PropComparator):
+ if c_token.property is not p_prop:
+ return None
+ else:
+ i += 1
+
+ return to_chop[i:]
+
+
def _bind_loader(self, query, context, raiseerr):
start_path = self.path
# _current_path implies we're in a
@@ -349,22 +392,6 @@ class _UnboundLoad(Load):
else:
effective_path.set(context, "loader", loader)
- def _chop_path(self, to_chop, path):
- i = -1
- for i, (c_token, (p_mapper, p_prop)) in enumerate(zip(to_chop, path.pairs())):
- if isinstance(c_token, util.string_types):
- if i == 0 and c_token.endswith(':' + _DEFAULT_TOKEN):
- return to_chop
- elif c_token != 'relationship:%s' % (_WILDCARD_TOKEN,) and c_token != p_prop.key:
- return None
- elif isinstance(c_token, PropComparator):
- if c_token.property is not p_prop:
- return None
- else:
- i += 1
-
- return to_chop[i:]
-
def _find_entity_prop_comparator(self, query, token, mapper, raiseerr):
if _is_aliased_class(mapper):
searchfor = mapper
@@ -749,7 +776,7 @@ def defaultload(*keys):
return _UnboundLoad._from_keys(_UnboundLoad.defaultload, keys, False, {})
@loader_option()
-def defer(loadopt, key, *addl_attrs):
+def defer(loadopt, key):
"""Indicate that the given column-oriented attribute should be deferred, e.g.
not loaded until accessed.
@@ -801,17 +828,17 @@ def defer(loadopt, key, *addl_attrs):
"""
return loadopt.set_column_strategy(
- (key, ) + addl_attrs,
+ (key, ),
{"deferred": True, "instrument": True}
)
@defer._add_unbound_fn
-def defer(*key):
- return _UnboundLoad._from_keys(_UnboundLoad.defer, key, False, {})
+def defer(key, *addl_attrs):
+ return _UnboundLoad._from_keys(_UnboundLoad.defer, (key, ) + addl_attrs, False, {})
@loader_option()
-def undefer(loadopt, key, *addl_attrs):
+def undefer(loadopt, key):
"""Indicate that the given column-oriented attribute should be undeferred, e.g.
specified within the SELECT statement of the entity as a whole.
@@ -845,13 +872,13 @@ def undefer(loadopt, key, *addl_attrs):
"""
return loadopt.set_column_strategy(
- (key, ) + addl_attrs,
+ (key, ),
{"deferred": False, "instrument": True}
)
@undefer._add_unbound_fn
-def undefer(*key):
- return _UnboundLoad._from_keys(_UnboundLoad.undefer, key, False, {})
+def undefer(key, *addl_attrs):
+ return _UnboundLoad._from_keys(_UnboundLoad.undefer, (key, ) + addl_attrs, False, {})
@loader_option()
def undefer_group(loadopt, name):