summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-04-01 17:20:31 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-04-01 18:59:41 -0400
commit20c0f774e5517514da811bc446812baa6b1f32f1 (patch)
tree31130474fc5aabcd7143ac5b0ba585c25700169a /lib/sqlalchemy/sql
parentdc5ade010da55c1158ee7294c9e882cc52cd6e01 (diff)
downloadsqlalchemy-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.py42
-rw-r--r--lib/sqlalchemy/sql/selectable.py8
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",