diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2021-08-10 01:36:24 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@ci3.zzzcomputing.com> | 2021-08-10 01:36:24 +0000 |
| commit | 70a33dd32f2609f2de6421c3b28ef4cc4496fdae (patch) | |
| tree | 108f7d59d828ebdd9c15dfb6a9b8050512496b5d /lib/sqlalchemy/orm | |
| parent | cb8906bab1776bafed48ef69ded0768461f7e7b8 (diff) | |
| parent | 65d4f98b69328f734abb16aa62952ab6aae576f2 (diff) | |
| download | sqlalchemy-70a33dd32f2609f2de6421c3b28ef4cc4496fdae.tar.gz | |
Merge "create concise + deterministic cache key for unboundload.options"
Diffstat (limited to 'lib/sqlalchemy/orm')
| -rw-r--r-- | lib/sqlalchemy/orm/strategy_options.py | 109 |
1 files changed, 95 insertions, 14 deletions
diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 399e33b89..ea1e5ea2a 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -28,6 +28,7 @@ from .. import util from ..sql import and_ from ..sql import coercions from ..sql import roles +from ..sql import traversals from ..sql import visitors from ..sql.base import _generative from ..sql.base import Generative @@ -615,16 +616,88 @@ class _UnboundLoad(Load): self.local_opts = {} self._extra_criteria = () - _cache_key_traversal = [ - ("path", visitors.ExtendedInternalTraversal.dp_multi_list), - ("strategy", visitors.ExtendedInternalTraversal.dp_plain_obj), - ("_to_bind", visitors.ExtendedInternalTraversal.dp_has_cache_key_list), - ("_extra_criteria", visitors.InternalTraversal.dp_clauseelement_list), - ( - "local_opts", - visitors.ExtendedInternalTraversal.dp_string_multi_dict, - ), - ] + def _gen_cache_key(self, anon_map, bindparams, _unbound_option_seen=None): + """Inlined gen_cache_key + + Original traversal is:: + + + _cache_key_traversal = [ + ("path", visitors.ExtendedInternalTraversal.dp_multi_list), + ("strategy", visitors.ExtendedInternalTraversal.dp_plain_obj), + ( + "_to_bind", + visitors.ExtendedInternalTraversal.dp_has_cache_key_list, + ), + ( + "_extra_criteria", + visitors.InternalTraversal.dp_clauseelement_list), + ( + "local_opts", + visitors.ExtendedInternalTraversal.dp_string_multi_dict, + ), + ] + + The inlining is so that the "_to_bind" list can be flattened to not + repeat the same UnboundLoad options over and over again. + + See #6869 + + """ + + idself = id(self) + cls = self.__class__ + + if idself in anon_map: + return (anon_map[idself], cls) + else: + id_ = anon_map[idself] + + vis = traversals._cache_key_traversal_visitor + + seen = _unbound_option_seen + if seen is None: + seen = set() + + return ( + (id_, cls) + + vis.visit_multi_list( + "path", self.path, self, anon_map, bindparams + ) + + ("strategy", self.strategy) + + ( + ( + "_to_bind", + tuple( + elem._gen_cache_key( + anon_map, bindparams, _unbound_option_seen=seen + ) + for elem in self._to_bind + if elem not in seen and not seen.add(elem) + ), + ) + if self._to_bind + else () + ) + + ( + ( + "_extra_criteria", + tuple( + elem._gen_cache_key(anon_map, bindparams) + for elem in self._extra_criteria + ), + ) + if self._extra_criteria + else () + ) + + ( + vis.visit_string_multi_dict( + "local_opts", self.local_opts, self, anon_map, bindparams + ) + if self.local_opts + else () + ) + ) _is_chain_link = False @@ -663,12 +736,20 @@ class _UnboundLoad(Load): assert cloned.is_class_strategy == self.is_class_strategy assert cloned.is_opts_only == self.is_opts_only - new_to_bind = { + uniq = set() + + cloned._to_bind = parent._to_bind + + cloned._to_bind[:] = [ + elem + for elem in cloned._to_bind + if elem not in uniq and not uniq.add(elem) + ] + [ elem._apply_to_parent(parent, applied, bound, to_bind) for elem in to_bind - } - cloned._to_bind = parent._to_bind - cloned._to_bind.extend(new_to_bind) + if elem not in uniq and not uniq.add(elem) + ] + cloned.local_opts.update(self.local_opts) return cloned |
