diff options
Diffstat (limited to 'lib/sqlalchemy/engine')
| -rw-r--r-- | lib/sqlalchemy/engine/__init__.py | 1 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/base.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/default.py | 37 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/interfaces.py | 70 |
4 files changed, 99 insertions, 12 deletions
diff --git a/lib/sqlalchemy/engine/__init__.py b/lib/sqlalchemy/engine/__init__.py index ba57eee51..5f4c5be47 100644 --- a/lib/sqlalchemy/engine/__init__.py +++ b/lib/sqlalchemy/engine/__init__.py @@ -33,6 +33,7 @@ from .cursor import CursorResult from .cursor import FullyBufferedResultProxy from .cursor import ResultProxy from .interfaces import AdaptedConnection +from .interfaces import BindTyping from .interfaces import Compiled from .interfaces import Connectable from .interfaces import CreateEnginePlugin diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 389270e45..61ef29d4a 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -9,6 +9,7 @@ from __future__ import with_statement import contextlib import sys +from .interfaces import BindTyping from .interfaces import Connectable from .interfaces import ConnectionEventsTarget from .interfaces import ExceptionContext @@ -1486,7 +1487,7 @@ class Connection(Connectable): context.pre_exec() - if dialect.use_setinputsizes: + if dialect.bind_typing is BindTyping.SETINPUTSIZES: context._set_input_sizes() cursor, statement, parameters = ( diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 3af24d913..d36ed6e65 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -52,9 +52,13 @@ class DefaultDialect(interfaces.Dialect): supports_alter = True supports_comments = False inline_comments = False - use_setinputsizes = False supports_statement_cache = True + bind_typing = interfaces.BindTyping.NONE + + include_set_input_sizes = None + exclude_set_input_sizes = None + # the first value we'd get for an autoincrement # column. default_sequence_base = 1 @@ -260,6 +264,15 @@ class DefaultDialect(interfaces.Dialect): else: self.server_side_cursors = True + if getattr(self, "use_setinputsizes", False): + util.warn_deprecated( + "The dialect-level use_setinputsizes attribute is " + "deprecated. Please use " + "bind_typing = BindTyping.SETINPUTSIZES", + "2.0", + ) + self.bind_typing = interfaces.BindTyping.SETINPUTSIZES + self.encoding = encoding self.positional = False self._ischema = None @@ -287,6 +300,10 @@ class DefaultDialect(interfaces.Dialect): self.label_length = label_length self.compiler_linting = compiler_linting + @util.memoized_property + def _bind_typing_render_casts(self): + return self.bind_typing is interfaces.BindTyping.RENDER_CASTS + def _ensure_has_table_connection(self, arg): if not isinstance(arg, Connection): @@ -736,9 +753,6 @@ class DefaultExecutionContext(interfaces.ExecutionContext): returned_default_rows = None execution_options = util.immutabledict() - include_set_input_sizes = None - exclude_set_input_sizes = None - cursor_fetch_strategy = _cursor._DEFAULT_FETCH cache_stats = None @@ -1373,8 +1387,14 @@ class DefaultExecutionContext(interfaces.ExecutionContext): style of ``setinputsizes()`` on the cursor, using DB-API types from the bind parameter's ``TypeEngine`` objects. - This method only called by those dialects which require it, - currently cx_oracle, asyncpg and pg8000. + This method only called by those dialects which set + the :attr:`.Dialect.bind_typing` attribute to + :attr:`.BindTyping.SETINPUTSIZES`. cx_Oracle is the only DBAPI + that requires setinputsizes(), pyodbc offers it as an option. + + Prior to SQLAlchemy 2.0, the setinputsizes() approach was also used + for pg8000 and asyncpg, which has been changed to inline rendering + of casts. """ if self.isddl or self.is_text: @@ -1382,10 +1402,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext): compiled = self.compiled - inputsizes = compiled._get_set_input_sizes_lookup( - include_types=self.include_set_input_sizes, - exclude_types=self.exclude_set_input_sizes, - ) + inputsizes = compiled._get_set_input_sizes_lookup() if inputsizes is None: return diff --git a/lib/sqlalchemy/engine/interfaces.py b/lib/sqlalchemy/engine/interfaces.py index 6772a27bd..251d01c5e 100644 --- a/lib/sqlalchemy/engine/interfaces.py +++ b/lib/sqlalchemy/engine/interfaces.py @@ -7,10 +7,60 @@ """Define core interfaces used by the engine system.""" +from enum import Enum + from ..sql.compiler import Compiled # noqa from ..sql.compiler import TypeCompiler # noqa +class BindTyping(Enum): + """Define different methods of passing typing information for + bound parameters in a statement to the database driver. + + .. versionadded:: 2.0 + + """ + + NONE = 1 + """No steps are taken to pass typing information to the database driver. + + This is the default behavior for databases such as SQLite, MySQL / MariaDB, + SQL Server. + + """ + + SETINPUTSIZES = 2 + """Use the pep-249 setinputsizes method. + + This is only implemented for DBAPIs that support this method and for which + the SQLAlchemy dialect has the appropriate infrastructure for that + dialect set up. Current dialects include cx_Oracle as well as + optional support for SQL Server using pyodbc. + + When using setinputsizes, dialects also have a means of only using the + method for certain datatypes using include/exclude lists. + + When SETINPUTSIZES is used, the :meth:`.Dialect.do_set_input_sizes` method + is called for each statement executed which has bound parameters. + + """ + + RENDER_CASTS = 3 + """Render casts or other directives in the SQL string. + + This method is used for all PostgreSQL dialects, including asyncpg, + pg8000, psycopg, psycopg2. Dialects which implement this can choose + which kinds of datatypes are explicitly cast in SQL statements and which + aren't. + + When RENDER_CASTS is used, the compiler will invoke the + :meth:`.SQLCompiler.render_bind_cast` method for each + :class:`.BindParameter` object whose dialect-level type sets the + :attr:`.TypeEngine.render_bind_cast` attribute. + + """ + + class Dialect: """Define the behavior of a specific database and DB-API combination. @@ -156,6 +206,16 @@ class Dialect: """ + bind_typing = BindTyping.NONE + """define a means of passing typing information to the database and/or + driver for bound parameters. + + See :class:`.BindTyping` for values. + + ..versionadded:: 2.0 + + """ + def create_connect_args(self, url): """Build DB-API compatible connection arguments. @@ -587,7 +647,9 @@ class Dialect: def do_set_input_sizes(self, cursor, list_of_tuples, context): """invoke the cursor.setinputsizes() method with appropriate arguments - This hook is called if the dialect.use_inputsizes flag is set to True. + This hook is called if the :attr:`.Dialect.bind_typing` attribute is + set to the + :attr:`.BindTyping.SETINPUTSIZES` value. Parameter data is passed in a list of tuples (paramname, dbtype, sqltype), where ``paramname`` is the key of the parameter in the statement, ``dbtype`` is the DBAPI datatype and ``sqltype`` is the @@ -595,6 +657,12 @@ class Dialect: .. versionadded:: 1.4 + .. versionchanged:: 2.0 - setinputsizes mode is now enabled by + setting :attr:`.Dialect.bind_typing` to + :attr:`.BindTyping.SETINPUTSIZES`. Dialects which accept + a ``use_setinputsizes`` parameter should set this value + appropriately. + """ raise NotImplementedError() |
