diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-01 17:20:31 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-01 18:59:41 -0400 |
| commit | 20c0f774e5517514da811bc446812baa6b1f32f1 (patch) | |
| tree | 31130474fc5aabcd7143ac5b0ba585c25700169a /lib/sqlalchemy/sql | |
| parent | dc5ade010da55c1158ee7294c9e882cc52cd6e01 (diff) | |
| download | sqlalchemy-20c0f774e5517514da811bc446812baa6b1f32f1.tar.gz | |
Default caching to opt-out for 3rd party dialects
Added a new flag to the :class:`_engine.Dialect` class called
:attr:`_engine.Dialect.supports_statement_cache`. This flag now needs to be present
directly on a dialect class in order for SQLAlchemy's
:ref:`query cache <sql_caching>` to take effect for that dialect. The
rationale is based on discovered issues such as :ticket:`6173` revealing
that dialects which hardcode literal values from the compiled statement,
often the numerical parameters used for LIMIT / OFFSET, will not be
compatible with caching until these dialects are revised to use the
parameters present in the statement only. For third party dialects where
this flag is not applied, the SQL logging will show the message "dialect
does not support caching", indicating the dialect should seek to apply this
flag once they have verified that no per-statement literal values are being
rendered within the compilation phase.
Fixes: #6184
Change-Id: I6fd5b5d94200458d4cb0e14f2f556dbc25e27e22
Diffstat (limited to 'lib/sqlalchemy/sql')
| -rw-r--r-- | lib/sqlalchemy/sql/elements.py | 42 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/selectable.py | 8 |
2 files changed, 36 insertions, 14 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index b64427d51..7a27690b8 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -514,7 +514,7 @@ class ClauseElement( schema_translate_map=None, **kw ): - if compiled_cache is not None: + if compiled_cache is not None and dialect._supports_statement_cache: elem_cache_key = self._generate_cache_key() else: elem_cache_key = None @@ -553,11 +553,13 @@ class ClauseElement( schema_translate_map=schema_translate_map, **kw ) - cache_hit = ( - dialect.CACHING_DISABLED - if compiled_cache is None - else dialect.NO_CACHE_KEY - ) + + if not dialect._supports_statement_cache: + cache_hit = dialect.NO_DIALECT_SUPPORT + elif compiled_cache is None: + cache_hit = dialect.CACHING_DISABLED + else: + cache_hit = dialect.NO_CACHE_KEY return compiled_sql, extracted_params, cache_hit @@ -1429,6 +1431,34 @@ class BindParameter(roles.InElementRole, ColumnElement): else: return self.value + def render_literal_execute(self): + """Produce a copy of this bound parameter that will enable the + :paramref:`_sql.BindParameter.literal_execute` flag. + + The :paramref:`_sql.BindParameter.literal_execute` flag will + have the effect of the parameter rendered in the compiled SQL + string using ``[POSTCOMPILE]`` form, which is a special form that + is converted to be a rendering of the literal value of the parameter + at SQL execution time. The rationale is to support caching + of SQL statement strings that can embed per-statement literal values, + such as LIMIT and OFFSET parameters, in the final SQL string that + is passed to the DBAPI. Dialects in particular may want to use + this method within custom compilation schemes. + + .. versionadded:: 1.4.5 + + .. seealso:: + + :ref:`engine_thirdparty_caching` + + """ + return self.__class__( + self.key, + self.value, + type_=self.type, + literal_execute=True, + ) + def _with_binary_element_type(self, type_): c = ClauseElement._clone(self) c.type = type_ diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 189deec41..a2e5780f8 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -69,14 +69,6 @@ class _OffsetLimitParam(BindParameter): def _limit_offset_value(self): return self.effective_value - def _render_literal_execute(self): - return _OffsetLimitParam( - self.key, - self.value, - type_=self.type, - literal_execute=True, - ) - @util.deprecated( "1.4", |
