diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-06-28 12:47:32 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-06-29 13:46:44 -0400 |
commit | 0286dcb23d8f6facb09391b46581d525982c20a0 (patch) | |
tree | 255d38af67598d2cf6341b7e95d3acd0d18fb431 /lib | |
parent | 5f5b56d646f154ee572c9de80449423304103bad (diff) | |
download | sqlalchemy-0286dcb23d8f6facb09391b46581d525982c20a0.tar.gz |
Remove _generate_path_cache_key()
loader options can now make a deterministic cache key based
on the structure they are given, and this accommodates for
aliased classes as well so that these cache keys are now
"safe". Have baked query call upon
the regular cache key method.
Change-Id: Iaa2ef4064cfb16146f415ca73080f32003dd830d
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sqlalchemy/ext/baked.py | 19 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 28 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/strategy_options.py | 89 |
3 files changed, 7 insertions, 129 deletions
diff --git a/lib/sqlalchemy/ext/baked.py b/lib/sqlalchemy/ext/baked.py index 4f40637c5..ecbf871e2 100644 --- a/lib/sqlalchemy/ext/baked.py +++ b/lib/sqlalchemy/ext/baked.py @@ -194,18 +194,13 @@ class BakedQuery(object): if not cache_path: cache_path = effective_path - if cache_path.path[0].is_aliased_class: - # paths that are against an AliasedClass are unsafe to cache - # with since the AliasedClass is an ad-hoc object. - self.spoil(full=True) - else: - for opt in options: - if opt._is_legacy_option or opt._is_compile_state: - cache_key = opt._generate_path_cache_key(cache_path) - if cache_key is False: - self.spoil(full=True) - elif cache_key is not None: - key += cache_key + for opt in options: + if opt._is_legacy_option or opt._is_compile_state: + ck = opt._generate_cache_key() + if ck is None: + self.spoil(full=True) + else: + key += ck[0] self.add_criteria( lambda q: q._with_current_path(effective_path).options(*options), diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index 9782d92b7..e569c0603 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -715,15 +715,6 @@ class LoaderOption(ORMOption): def process_compile_state(self, compile_state): """Apply a modification to a given :class:`.CompileState`.""" - def _generate_path_cache_key(self, path): - """Used by the "baked lazy loader" to see if this option can be cached. - - .. deprecated:: 2.0 this method is to suit the baked extension which - is itself not part of 2.0. - - """ - return False - class UserDefinedOption(ORMOption): """Base class for a user-defined option that can be consumed from the @@ -782,25 +773,6 @@ class MapperOption(ORMOption): self.process_query(query) - def _generate_path_cache_key(self, path): - """Used by the "baked lazy loader" to see if this option can be cached. - - By default, this method returns the value ``False``, which means - the :class:`.BakedQuery` generated by the lazy loader will - not cache the SQL when this :class:`.MapperOption` is present. - This is the safest option and ensures both that the option is - invoked every time, and also that the cache isn't filled up with - an unlimited number of :class:`_query.Query` objects for an unlimited - number of :class:`.MapperOption` objects. - - For caching support it is recommended to use the - :class:`.UserDefinedOption` class in conjunction with - the :meth:`.Session.do_orm_execute` method so that statements may - be modified before they are cached. - - """ - return False - class LoaderStrategy(object): """Describe the loading behavior of a StrategizedProperty object. diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index a059c67ac..3cc1b97f9 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -114,76 +114,6 @@ class Load(Generative, LoaderOption): serialized.append(loader_path + (obj,)) return serialized - def _generate_path_cache_key(self, path): - if path.path[0].is_aliased_class: - return False - - serialized = [] - for (key, loader_path), obj in self.context.items(): - if key != "loader": - continue - - for local_elem, obj_elem in zip(self.path.path, loader_path): - if local_elem is not obj_elem: - break - else: - endpoint = obj._of_type or obj.path.path[-1] - chopped = self._chop_path(loader_path, path) - - if ( - # means loader_path and path are unrelated, - # this does not need to be part of a cache key - chopped - is None - ) or ( - # means no additional path with loader_path + path - # and the endpoint isn't using of_type so isn't modified - # into an alias or other unsafe entity - not chopped - and not obj._of_type - ): - continue - - serialized_path = [] - - for token in chopped: - if isinstance(token, util.string_types): - serialized_path.append(token) - elif token.is_aliased_class: - return False - elif token.is_property: - serialized_path.append(token.key) - else: - assert token.is_mapper - serialized_path.append(token.class_) - - if not serialized_path or endpoint != serialized_path[-1]: - if endpoint.is_mapper: - serialized_path.append(endpoint.class_) - elif endpoint.is_aliased_class: - return False - - serialized.append( - ( - tuple(serialized_path) - + (obj.strategy or ()) - + ( - tuple( - [ - (key, obj.local_opts[key]) - for key in sorted(obj.local_opts) - ] - ) - if obj.local_opts - else () - ) - ) - ) - if not serialized: - return None - else: - return tuple(serialized) - def _generate(self): cloned = super(Load, self)._generate() cloned.local_opts = {} @@ -588,25 +518,6 @@ class _UnboundLoad(Load): _is_chain_link = False - def _generate_path_cache_key(self, path): - serialized = () - for val in self._to_bind: - for local_elem, val_elem in zip(self.path, val.path): - if local_elem is not val_elem: - break - else: - opt = val._bind_loader([path.path[0]], None, None, False) - if opt: - c_key = opt._generate_path_cache_key(path) - if c_key is False: - return False - elif c_key: - serialized += c_key - if not serialized: - return None - else: - return serialized - def _set_path_strategy(self): self._to_bind.append(self) |