diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-08-05 16:42:26 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-08-05 16:42:26 -0400 |
commit | cc57ea495f6460dd56daa6de57e40047ed999369 (patch) | |
tree | 837f5a84363c387d7f8fdeabc06928cd078028e1 /lib/sqlalchemy/sql/elements.py | |
parent | 2a946254023135eddd222974cf300ffaa5583f02 (diff) | |
download | sqlalchemy-cc57ea495f6460dd56daa6de57e40047ed999369.tar.gz |
Robustness for lambdas, lambda statements
in order to accommodate relationship loaders
with lambda caching, a lot more is needed. This is
a full refactor of the lambda system such that it
now has two levels of caching; the first level caches what
can be known from the __code__ element, then the next level
of caching is against the lambda itself and the contents
of __closure__. This allows for the elements inside
the lambdas, like columns and entities, to change and
then be part of the cache key. Lazy/selectinloads' use of
baked queries had to add distinct cache key elements,
which was attempted here but overall things needed to be
more robust than that.
This commit is broken out from the very long and sprawling
commit at Id6b5c03b1ce9ddb7b280f66792212a0ef0a1c541 .
Change-Id: I29a513c98917b1d503abfdd61e6b6e8800851aa8
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 49 |
1 files changed, 12 insertions, 37 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index ca73a4392..8a506446d 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -32,8 +32,8 @@ from .base import NO_ARG from .base import PARSE_AUTOCOMMIT from .base import SingletonConstant from .coercions import _document_text_coercion -from .traversals import _copy_internals from .traversals import _get_children +from .traversals import HasCopyInternals from .traversals import MemoizedHasCacheKey from .traversals import NO_CACHE from .visitors import cloned_traverse @@ -182,6 +182,7 @@ class ClauseElement( roles.SQLRole, SupportsWrappingAnnotations, MemoizedHasCacheKey, + HasCopyInternals, Traversible, ): """Base class for elements of a programmatically constructed SQL @@ -372,35 +373,6 @@ class ClauseElement( """ return traversals.compare(self, other, **kw) - def _copy_internals(self, omit_attrs=(), **kw): - """Reassign internal elements to be clones of themselves. - - Called during a copy-and-traverse operation on newly - shallow-copied elements to create a deep copy. - - The given clone function should be used, which may be applying - additional transformations to the element (i.e. replacement - traversal, cloned traversal, annotations). - - """ - - try: - traverse_internals = self._traverse_internals - except AttributeError: - # user-defined classes may not have a _traverse_internals - return - - for attrname, obj, meth in _copy_internals.run_generated_dispatch( - self, traverse_internals, "_generated_copy_internals_traversal" - ): - if attrname in omit_attrs: - continue - - if obj is not None: - result = meth(self, attrname, obj, **kw) - if result is not None: - setattr(self, attrname, result) - def get_children(self, omit_attrs=(), **kw): r"""Return immediate child :class:`.visitors.Traversible` elements of this :class:`.visitors.Traversible`. @@ -535,8 +507,6 @@ class ClauseElement( else: elem_cache_key = None - cache_hit = False - if elem_cache_key: cache_key, extracted_params = elem_cache_key key = ( @@ -549,6 +519,7 @@ class ClauseElement( compiled_sql = compiled_cache.get(key) if compiled_sql is None: + cache_hit = dialect.CACHE_MISS compiled_sql = self._compiler( dialect, cache_key=elem_cache_key, @@ -559,7 +530,7 @@ class ClauseElement( ) compiled_cache[key] = compiled_sql else: - cache_hit = True + cache_hit = dialect.CACHE_HIT else: extracted_params = None compiled_sql = self._compiler( @@ -570,6 +541,11 @@ class ClauseElement( schema_translate_map=schema_translate_map, **kw ) + cache_hit = ( + dialect.CACHING_DISABLED + if compiled_cache is None + else dialect.NO_CACHE_KEY + ) return compiled_sql, extracted_params, cache_hit @@ -1343,10 +1319,7 @@ class BindParameter(roles.InElementRole, ColumnElement): if required is NO_ARG: required = value is NO_ARG and callable_ is None if value is NO_ARG: - self._value_required_for_cache = False value = None - else: - self._value_required_for_cache = True if quote is not None: key = quoted_name(key, quote) @@ -1412,6 +1385,7 @@ class BindParameter(roles.InElementRole, ColumnElement): """Return a copy of this :class:`.BindParameter` with the given value set. """ + cloned = self._clone(maintain_key=maintain_key) cloned.value = value cloned.callable = None @@ -1465,7 +1439,8 @@ class BindParameter(roles.InElementRole, ColumnElement): anon_map[idself] = id_ = str(anon_map.index) anon_map.index += 1 - bindparams.append(self) + if bindparams is not None: + bindparams.append(self) return ( id_, |