diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-10-06 20:12:28 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-10-06 20:50:51 -0400 |
| commit | 22d5a1e415d603d253870719466152b9e817e1e5 (patch) | |
| tree | 742d84eea2913e6c4fabe2e10d0cf12793aaf7e2 /lib/sqlalchemy | |
| parent | 1b25ed907fb7311d28d2273c9b9858b50c1a7afc (diff) | |
| download | sqlalchemy-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.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategy_options.py | 77 |
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): |
