diff options
Diffstat (limited to 'lib/sqlalchemy')
38 files changed, 114 insertions, 17 deletions
diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py index 7fc914f1b..fcf0c31d3 100644 --- a/lib/sqlalchemy/dialects/firebird/base.py +++ b/lib/sqlalchemy/dialects/firebird/base.py @@ -623,6 +623,7 @@ class FBDialect(default.DefaultDialect): """Firebird dialect""" name = "firebird" + supports_statement_cache = True max_identifier_length = 31 diff --git a/lib/sqlalchemy/dialects/firebird/fdb.py b/lib/sqlalchemy/dialects/firebird/fdb.py index 14954b073..18ed65f45 100644 --- a/lib/sqlalchemy/dialects/firebird/fdb.py +++ b/lib/sqlalchemy/dialects/firebird/fdb.py @@ -66,6 +66,8 @@ from ... import util class FBDialect_fdb(FBDialect_kinterbasdb): + supports_statement_cache = True + def __init__(self, enable_rowcount=True, retaining=False, **kwargs): super(FBDialect_fdb, self).__init__( enable_rowcount=enable_rowcount, retaining=retaining, **kwargs diff --git a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py index 4c937e0de..7c91db639 100644 --- a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py +++ b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py @@ -78,6 +78,7 @@ class FBExecutionContext_kinterbasdb(FBExecutionContext): class FBDialect_kinterbasdb(FBDialect): driver = "kinterbasdb" + supports_statement_cache = True supports_sane_rowcount = False supports_sane_multi_rowcount = False execution_ctx_cls = FBExecutionContext_kinterbasdb diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index bfa1cf08c..1fef42c53 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -2576,6 +2576,7 @@ def _schema_elements(schema): class MSDialect(default.DefaultDialect): # will assume it's at least mssql2005 name = "mssql" + supports_statement_cache = True supports_default_values = True supports_empty_insert = False execution_ctx_cls = MSExecutionContext diff --git a/lib/sqlalchemy/dialects/mssql/mxodbc.py b/lib/sqlalchemy/dialects/mssql/mxodbc.py index da4e45f07..637b04869 100644 --- a/lib/sqlalchemy/dialects/mssql/mxodbc.py +++ b/lib/sqlalchemy/dialects/mssql/mxodbc.py @@ -126,6 +126,7 @@ class MSDialect_mxodbc(MxODBCConnector, MSDialect): # this is only needed if "native ODBC" mode is used, # which is now disabled by default. # statement_compiler = MSSQLStrictCompiler + supports_statement_cache = True execution_ctx_cls = MSExecutionContext_mxodbc diff --git a/lib/sqlalchemy/dialects/mssql/pymssql.py b/lib/sqlalchemy/dialects/mssql/pymssql.py index 5110badb9..4cc6c4696 100644 --- a/lib/sqlalchemy/dialects/mssql/pymssql.py +++ b/lib/sqlalchemy/dialects/mssql/pymssql.py @@ -65,6 +65,7 @@ class MSIdentifierPreparer_pymssql(MSIdentifierPreparer): class MSDialect_pymssql(MSDialect): + supports_statement_cache = True supports_native_decimal = True driver = "pymssql" diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py index 6b2fffc4e..99ab37228 100644 --- a/lib/sqlalchemy/dialects/mssql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py @@ -431,6 +431,7 @@ class MSExecutionContext_pyodbc(MSExecutionContext): class MSDialect_pyodbc(PyODBCConnector, MSDialect): + supports_statement_cache = True # mssql still has problems with this on Linux supports_sane_rowcount_returning = False diff --git a/lib/sqlalchemy/dialects/mysql/aiomysql.py b/lib/sqlalchemy/dialects/mysql/aiomysql.py index c8c7c0f97..6c77e7525 100644 --- a/lib/sqlalchemy/dialects/mysql/aiomysql.py +++ b/lib/sqlalchemy/dialects/mysql/aiomysql.py @@ -266,6 +266,7 @@ class AsyncAdapt_aiomysql_dbapi: class MySQLDialect_aiomysql(MySQLDialect_pymysql): driver = "aiomysql" + supports_statement_cache = True supports_server_side_cursors = True _sscursor = AsyncAdapt_aiomysql_ss_cursor diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index b3c338bad..986ed8757 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -2511,6 +2511,8 @@ class MySQLDialect(default.DefaultDialect): """ name = "mysql" + supports_statement_cache = True + supports_alter = True # MySQL has no true "boolean" type; we diff --git a/lib/sqlalchemy/dialects/mysql/cymysql.py b/lib/sqlalchemy/dialects/mysql/cymysql.py index 0d7ba5594..ec9fd6edd 100644 --- a/lib/sqlalchemy/dialects/mysql/cymysql.py +++ b/lib/sqlalchemy/dialects/mysql/cymysql.py @@ -43,6 +43,7 @@ class _cymysqlBIT(BIT): class MySQLDialect_cymysql(MySQLDialect_mysqldb): driver = "cymysql" + supports_statement_cache = True description_encoding = None supports_sane_rowcount = True diff --git a/lib/sqlalchemy/dialects/mysql/mariadb.py b/lib/sqlalchemy/dialects/mysql/mariadb.py index 0dbb579e8..8ebde462b 100644 --- a/lib/sqlalchemy/dialects/mysql/mariadb.py +++ b/lib/sqlalchemy/dialects/mysql/mariadb.py @@ -3,6 +3,7 @@ from .base import MySQLDialect class MariaDBDialect(MySQLDialect): is_mariadb = True + supports_statement_cache = True name = "mariadb" @@ -18,5 +19,5 @@ def loader(driver): MariaDBDialect, driver_cls, ), - {}, + {"supports_statement_cache": True}, ) diff --git a/lib/sqlalchemy/dialects/mysql/mariadbconnector.py b/lib/sqlalchemy/dialects/mysql/mariadbconnector.py index ddc11f6e6..6e3a24950 100644 --- a/lib/sqlalchemy/dialects/mysql/mariadbconnector.py +++ b/lib/sqlalchemy/dialects/mysql/mariadbconnector.py @@ -57,6 +57,7 @@ class MySQLIdentifierPreparer_mariadbconnector(MySQLIdentifierPreparer): class MySQLDialect_mariadbconnector(MySQLDialect): driver = "mariadbconnector" + supports_statement_cache = True # set this to True at the module level to prevent the driver from running # against a backend that server detects as MySQL. currently this appears to diff --git a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py index 5ed675b13..80f20688b 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqlconnector.py +++ b/lib/sqlalchemy/dialects/mysql/mysqlconnector.py @@ -85,6 +85,7 @@ class _myconnpyBIT(BIT): class MySQLDialect_mysqlconnector(MySQLDialect): driver = "mysqlconnector" + supports_statement_cache = True supports_unicode_binds = True diff --git a/lib/sqlalchemy/dialects/mysql/mysqldb.py b/lib/sqlalchemy/dialects/mysql/mysqldb.py index 0318b5077..274f3eea4 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqldb.py +++ b/lib/sqlalchemy/dialects/mysql/mysqldb.py @@ -77,6 +77,7 @@ class MySQLIdentifierPreparer_mysqldb(MySQLIdentifierPreparer): class MySQLDialect_mysqldb(MySQLDialect): driver = "mysqldb" + supports_statement_cache = True supports_unicode_statements = True supports_sane_rowcount = True supports_sane_multi_rowcount = True diff --git a/lib/sqlalchemy/dialects/mysql/oursql.py b/lib/sqlalchemy/dialects/mysql/oursql.py index 5c8c7b7c2..06a6115b4 100644 --- a/lib/sqlalchemy/dialects/mysql/oursql.py +++ b/lib/sqlalchemy/dialects/mysql/oursql.py @@ -55,6 +55,7 @@ class MySQLExecutionContext_oursql(MySQLExecutionContext): class MySQLDialect_oursql(MySQLDialect): driver = "oursql" + supports_statement_cache = True if util.py2k: supports_unicode_binds = True diff --git a/lib/sqlalchemy/dialects/mysql/pymysql.py b/lib/sqlalchemy/dialects/mysql/pymysql.py index 0c321f854..09b5abffe 100644 --- a/lib/sqlalchemy/dialects/mysql/pymysql.py +++ b/lib/sqlalchemy/dialects/mysql/pymysql.py @@ -35,6 +35,7 @@ from ...util import py3k class MySQLDialect_pymysql(MySQLDialect_mysqldb): driver = "pymysql" + supports_statement_cache = True description_encoding = None diff --git a/lib/sqlalchemy/dialects/mysql/pyodbc.py b/lib/sqlalchemy/dialects/mysql/pyodbc.py index 048586b59..7bc9ff14f 100644 --- a/lib/sqlalchemy/dialects/mysql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mysql/pyodbc.py @@ -72,6 +72,7 @@ class MySQLExecutionContext_pyodbc(MySQLExecutionContext): class MySQLDialect_pyodbc(PyODBCConnector, MySQLDialect): + supports_statement_cache = True colspecs = util.update_copy(MySQLDialect.colspecs, {Time: _pyodbcTIME}) supports_unicode_statements = True execution_ctx_cls = MySQLExecutionContext_pyodbc diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index 46fcbbbe1..11ad61675 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -1093,10 +1093,10 @@ class OracleCompiler(compiler.SQLCompiler): offset_clause = select._offset_clause if select._simple_int_clause(limit_clause): - limit_clause = limit_clause._render_literal_execute() + limit_clause = limit_clause.render_literal_execute() if select._simple_int_clause(offset_clause): - offset_clause = offset_clause._render_literal_execute() + offset_clause = offset_clause.render_literal_execute() # currently using form at: # https://blogs.oracle.com/oraclemagazine/\ @@ -1434,6 +1434,7 @@ class OracleExecutionContext(default.DefaultExecutionContext): class OracleDialect(default.DefaultDialect): name = "oracle" + supports_statement_cache = True supports_alter = True supports_unicode_statements = False supports_unicode_binds = False diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index 38b92117b..87c817066 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -797,6 +797,7 @@ class OracleExecutionContext_cx_oracle(OracleExecutionContext): class OracleDialect_cx_oracle(OracleDialect): + supports_statement_cache = True execution_ctx_cls = OracleExecutionContext_cx_oracle statement_compiler = OracleCompiler_cx_oracle diff --git a/lib/sqlalchemy/dialects/postgresql/asyncpg.py b/lib/sqlalchemy/dialects/postgresql/asyncpg.py index 4580421f6..8cd5bee41 100644 --- a/lib/sqlalchemy/dialects/postgresql/asyncpg.py +++ b/lib/sqlalchemy/dialects/postgresql/asyncpg.py @@ -850,6 +850,7 @@ _pg_types = { class PGDialect_asyncpg(PGDialect): driver = "asyncpg" + supports_statement_cache = True supports_unicode_statements = True supports_server_side_cursors = True diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 97eb07bdb..2c4e316b3 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -3062,6 +3062,7 @@ class PGDeferrableConnectionCharacteristic( class PGDialect(default.DefaultDialect): name = "postgresql" + supports_statement_cache = True supports_alter = True max_identifier_length = 63 supports_sane_rowcount = True diff --git a/lib/sqlalchemy/dialects/postgresql/pg8000.py b/lib/sqlalchemy/dialects/postgresql/pg8000.py index 43df6edea..eaf6ccbb8 100644 --- a/lib/sqlalchemy/dialects/postgresql/pg8000.py +++ b/lib/sqlalchemy/dialects/postgresql/pg8000.py @@ -252,6 +252,7 @@ class PGIdentifierPreparer_pg8000(PGIdentifierPreparer): class PGDialect_pg8000(PGDialect): driver = "pg8000" + supports_statement_cache = True supports_unicode_statements = True diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py index 16f9ecefa..c2b679022 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py @@ -634,6 +634,9 @@ EXECUTEMANY_VALUES_PLUS_BATCH = util.symbol( class PGDialect_psycopg2(PGDialect): driver = "psycopg2" + + supports_statement_cache = True + if util.py2k: # turn off supports_unicode_statements for Python 2. psycopg2 supports # unicode statements in Py2K. But! it does not support unicode *bound diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py b/lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py index a449f9e65..780244be9 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2cffi.py @@ -28,6 +28,7 @@ from .psycopg2 import PGDialect_psycopg2 class PGDialect_psycopg2cffi(PGDialect_psycopg2): driver = "psycopg2cffi" supports_unicode_statements = True + supports_statement_cache = True # psycopg2cffi's first release is 2.5.0, but reports # __version__ as 2.4.4. Subsequent releases seem to have diff --git a/lib/sqlalchemy/dialects/postgresql/pygresql.py b/lib/sqlalchemy/dialects/postgresql/pygresql.py index 64dd7262d..718bbf78f 100644 --- a/lib/sqlalchemy/dialects/postgresql/pygresql.py +++ b/lib/sqlalchemy/dialects/postgresql/pygresql.py @@ -193,6 +193,7 @@ class _PGIdentifierPreparer(PGIdentifierPreparer): class PGDialect_pygresql(PGDialect): driver = "pygresql" + supports_statement_cache = True statement_compiler = _PGCompiler preparer = _PGIdentifierPreparer diff --git a/lib/sqlalchemy/dialects/postgresql/pypostgresql.py b/lib/sqlalchemy/dialects/postgresql/pypostgresql.py index 6e4db217d..7d4783867 100644 --- a/lib/sqlalchemy/dialects/postgresql/pypostgresql.py +++ b/lib/sqlalchemy/dialects/postgresql/pypostgresql.py @@ -52,6 +52,7 @@ class PGExecutionContext_pypostgresql(PGExecutionContext): class PGDialect_pypostgresql(PGDialect): driver = "pypostgresql" + supports_statement_cache = True supports_unicode_statements = True supports_unicode_binds = True description_encoding = None diff --git a/lib/sqlalchemy/dialects/sqlite/aiosqlite.py b/lib/sqlalchemy/dialects/sqlite/aiosqlite.py index e4b7d1d52..1d09a619d 100644 --- a/lib/sqlalchemy/dialects/sqlite/aiosqlite.py +++ b/lib/sqlalchemy/dialects/sqlite/aiosqlite.py @@ -299,6 +299,7 @@ class SQLiteExecutionContext_aiosqlite(SQLiteExecutionContext): class SQLiteDialect_aiosqlite(SQLiteDialect_pysqlite): driver = "aiosqlite" + supports_statement_cache = True is_async = True diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index 691ca642d..83c2a8ea7 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -1796,6 +1796,7 @@ class SQLiteDialect(default.DefaultDialect): supports_cast = True supports_multivalues_insert = True tuple_in_values = True + supports_statement_cache = True default_paramstyle = "qmark" execution_ctx_cls = SQLiteExecutionContext diff --git a/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py b/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py index 8f0f46acb..ff02d4dee 100644 --- a/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py +++ b/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py @@ -98,6 +98,7 @@ from ... import util class SQLiteDialect_pysqlcipher(SQLiteDialect_pysqlite): driver = "pysqlcipher" + supports_statement_cache = True pragmas = ("kdf_iter", "cipher", "cipher_page_size", "cipher_use_hmac") diff --git a/lib/sqlalchemy/dialects/sqlite/pysqlite.py b/lib/sqlalchemy/dialects/sqlite/pysqlite.py index c940faf38..0b091e73b 100644 --- a/lib/sqlalchemy/dialects/sqlite/pysqlite.py +++ b/lib/sqlalchemy/dialects/sqlite/pysqlite.py @@ -443,6 +443,7 @@ class _SQLite_pysqliteDate(DATE): class SQLiteDialect_pysqlite(SQLiteDialect): default_paramstyle = "qmark" + supports_statement_cache = True colspecs = util.update_copy( SQLiteDialect.colspecs, diff --git a/lib/sqlalchemy/dialects/sybase/base.py b/lib/sqlalchemy/dialects/sybase/base.py index 49243be78..fd5e5b3b6 100644 --- a/lib/sqlalchemy/dialects/sybase/base.py +++ b/lib/sqlalchemy/dialects/sybase/base.py @@ -632,6 +632,7 @@ class SybaseDialect(default.DefaultDialect): supports_unicode_statements = False supports_sane_rowcount = False supports_sane_multi_rowcount = False + supports_statement_cache = True supports_native_boolean = False supports_unicode_binds = False diff --git a/lib/sqlalchemy/dialects/sybase/mxodbc.py b/lib/sqlalchemy/dialects/sybase/mxodbc.py index 6b2f07c54..7002217c0 100644 --- a/lib/sqlalchemy/dialects/sybase/mxodbc.py +++ b/lib/sqlalchemy/dialects/sybase/mxodbc.py @@ -28,6 +28,7 @@ class SybaseExecutionContext_mxodbc(SybaseExecutionContext): class SybaseDialect_mxodbc(MxODBCConnector, SybaseDialect): execution_ctx_cls = SybaseExecutionContext_mxodbc + supports_statement_cache = True dialect = SybaseDialect_mxodbc diff --git a/lib/sqlalchemy/dialects/sybase/pyodbc.py b/lib/sqlalchemy/dialects/sybase/pyodbc.py index bbd6d968a..bbaaa7e02 100644 --- a/lib/sqlalchemy/dialects/sybase/pyodbc.py +++ b/lib/sqlalchemy/dialects/sybase/pyodbc.py @@ -77,6 +77,7 @@ class SybaseExecutionContext_pyodbc(SybaseExecutionContext): class SybaseDialect_pyodbc(PyODBCConnector, SybaseDialect): execution_ctx_cls = SybaseExecutionContext_pyodbc + supports_statement_cache = True colspecs = {sqltypes.Numeric: _SybNumeric_pyodbc} diff --git a/lib/sqlalchemy/dialects/sybase/pysybase.py b/lib/sqlalchemy/dialects/sybase/pysybase.py index d6d2f2ed2..0c5557e99 100644 --- a/lib/sqlalchemy/dialects/sybase/pysybase.py +++ b/lib/sqlalchemy/dialects/sybase/pysybase.py @@ -62,6 +62,8 @@ class SybaseDialect_pysybase(SybaseDialect): execution_ctx_cls = SybaseExecutionContext_pysybase statement_compiler = SybaseSQLCompiler_pysybase + supports_statement_cache = True + colspecs = {sqltypes.Numeric: _SybNumeric, sqltypes.Float: sqltypes.Float} @classmethod diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 7391e7b01..5193a0273 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -44,6 +44,7 @@ CACHE_HIT = util.symbol("CACHE_HIT") CACHE_MISS = util.symbol("CACHE_MISS") CACHING_DISABLED = util.symbol("CACHING_DISABLED") NO_CACHE_KEY = util.symbol("NO_CACHE_KEY") +NO_DIALECT_SUPPORT = util.symbol("NO_DIALECT_SUPPORT") class DefaultDialect(interfaces.Dialect): @@ -57,6 +58,7 @@ class DefaultDialect(interfaces.Dialect): supports_comments = False inline_comments = False use_setinputsizes = False + supports_statement_cache = True # the first value we'd get for an autoincrement # column. @@ -215,6 +217,7 @@ class DefaultDialect(interfaces.Dialect): CACHE_MISS = CACHE_MISS CACHING_DISABLED = CACHING_DISABLED NO_CACHE_KEY = NO_CACHE_KEY + NO_DIALECT_SUPPORT = NO_DIALECT_SUPPORT @util.deprecated_params( convert_unicode=( @@ -320,6 +323,13 @@ class DefaultDialect(interfaces.Dialect): self._decoder = processors.to_unicode_processor_factory(self.encoding) @util.memoized_property + def _supports_statement_cache(self): + return ( + self.__class__.__dict__.get("supports_statement_cache", False) + is True + ) + + @util.memoized_property def _type_memos(self): return weakref.WeakKeyDictionary() @@ -771,6 +781,8 @@ class StrCompileDialect(DefaultDialect): type_compiler = compiler.StrSQLTypeCompiler preparer = compiler.IdentifierPreparer + supports_statement_cache = True + supports_sequences = True sequences_optional = True preexecute_autoincrement_sequences = False @@ -1137,6 +1149,12 @@ class DefaultExecutionContext(interfaces.ExecutionContext): return "generated in %.5fs" % (now - self.compiled._gen_time,) elif ch is CACHING_DISABLED: return "caching disabled %.5fs" % (now - self.compiled._gen_time,) + elif ch is NO_DIALECT_SUPPORT: + return "dialect %s+%s does not support caching %.5fs" % ( + self.dialect.name, + self.dialect.driver, + now - self.compiled._gen_time, + ) else: return "unknown" diff --git a/lib/sqlalchemy/engine/interfaces.py b/lib/sqlalchemy/engine/interfaces.py index 24e0e5b0d..5e6cc524e 100644 --- a/lib/sqlalchemy/engine/interfaces.py +++ b/lib/sqlalchemy/engine/interfaces.py @@ -152,6 +152,24 @@ class Dialect(object): _has_events = False + supports_statement_cache = True + """indicates if this dialect supports caching. + + All dialects that are compatible with statement caching should set this + flag to True directly on each dialect class and subclass that supports + it. SQLAlchemy tests that this flag is locally present on each dialect + subclass before it will use statement caching. This is to provide + safety for legacy or new dialects that are not yet fully tested to be + compliant with SQL statement caching. + + .. versionadded:: 1.4.5 + + .. seealso:: + + :ref:`engine_thirdparty_caching` + + """ + def create_connect_args(self, url): """Build DB-API compatible connection arguments. 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", |
