You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1904 lines
						
					
					
						
							64 KiB
						
					
					
				
			
		
		
	
	
							1904 lines
						
					
					
						
							64 KiB
						
					
					
				# engine/default.py
 | 
						|
# Copyright (C) 2005-2022 the SQLAlchemy authors and contributors
 | 
						|
# <see AUTHORS file>
 | 
						|
#
 | 
						|
# This module is part of SQLAlchemy and is released under
 | 
						|
# the MIT License: https://www.opensource.org/licenses/mit-license.php
 | 
						|
 | 
						|
"""Default implementations of per-dialect sqlalchemy.engine classes.
 | 
						|
 | 
						|
These are semi-private implementation classes which are only of importance
 | 
						|
to database dialect authors; dialects will usually use the classes here
 | 
						|
as the base class for their own corresponding classes.
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
import codecs
 | 
						|
import functools
 | 
						|
import random
 | 
						|
import re
 | 
						|
import weakref
 | 
						|
 | 
						|
from . import characteristics
 | 
						|
from . import cursor as _cursor
 | 
						|
from . import interfaces
 | 
						|
from .base import Connection
 | 
						|
from .. import event
 | 
						|
from .. import exc
 | 
						|
from .. import pool
 | 
						|
from .. import processors
 | 
						|
from .. import types as sqltypes
 | 
						|
from .. import util
 | 
						|
from ..sql import compiler
 | 
						|
from ..sql import expression
 | 
						|
from ..sql.elements import quoted_name
 | 
						|
 | 
						|
AUTOCOMMIT_REGEXP = re.compile(
 | 
						|
    r"\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER)", re.I | re.UNICODE
 | 
						|
)
 | 
						|
 | 
						|
# When we're handed literal SQL, ensure it's a SELECT query
 | 
						|
SERVER_SIDE_CURSOR_RE = re.compile(r"\s*SELECT", re.I | re.UNICODE)
 | 
						|
 | 
						|
 | 
						|
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):
 | 
						|
    """Default implementation of Dialect"""
 | 
						|
 | 
						|
    statement_compiler = compiler.SQLCompiler
 | 
						|
    ddl_compiler = compiler.DDLCompiler
 | 
						|
    type_compiler = compiler.GenericTypeCompiler
 | 
						|
    preparer = compiler.IdentifierPreparer
 | 
						|
    supports_alter = True
 | 
						|
    supports_comments = False
 | 
						|
    inline_comments = False
 | 
						|
    use_setinputsizes = False
 | 
						|
    supports_statement_cache = True
 | 
						|
 | 
						|
    # the first value we'd get for an autoincrement
 | 
						|
    # column.
 | 
						|
    default_sequence_base = 1
 | 
						|
 | 
						|
    # most DBAPIs happy with this for execute().
 | 
						|
    # not cx_oracle.
 | 
						|
    execute_sequence_format = tuple
 | 
						|
 | 
						|
    supports_schemas = True
 | 
						|
    supports_views = True
 | 
						|
    supports_sequences = False
 | 
						|
    sequences_optional = False
 | 
						|
    preexecute_autoincrement_sequences = False
 | 
						|
    supports_identity_columns = False
 | 
						|
    postfetch_lastrowid = True
 | 
						|
    implicit_returning = False
 | 
						|
    full_returning = False
 | 
						|
    insert_executemany_returning = False
 | 
						|
 | 
						|
    cte_follows_insert = False
 | 
						|
 | 
						|
    supports_native_enum = False
 | 
						|
    supports_native_boolean = False
 | 
						|
    non_native_boolean_check_constraint = True
 | 
						|
 | 
						|
    supports_simple_order_by_label = True
 | 
						|
 | 
						|
    tuple_in_values = False
 | 
						|
 | 
						|
    connection_characteristics = util.immutabledict(
 | 
						|
        {"isolation_level": characteristics.IsolationLevelCharacteristic()}
 | 
						|
    )
 | 
						|
 | 
						|
    engine_config_types = util.immutabledict(
 | 
						|
        [
 | 
						|
            ("convert_unicode", util.bool_or_str("force")),
 | 
						|
            ("pool_timeout", util.asint),
 | 
						|
            ("echo", util.bool_or_str("debug")),
 | 
						|
            ("echo_pool", util.bool_or_str("debug")),
 | 
						|
            ("pool_recycle", util.asint),
 | 
						|
            ("pool_size", util.asint),
 | 
						|
            ("max_overflow", util.asint),
 | 
						|
            ("future", util.asbool),
 | 
						|
        ]
 | 
						|
    )
 | 
						|
 | 
						|
    # if the NUMERIC type
 | 
						|
    # returns decimal.Decimal.
 | 
						|
    # *not* the FLOAT type however.
 | 
						|
    supports_native_decimal = False
 | 
						|
 | 
						|
    if util.py3k:
 | 
						|
        supports_unicode_statements = True
 | 
						|
        supports_unicode_binds = True
 | 
						|
        returns_unicode_strings = sqltypes.String.RETURNS_UNICODE
 | 
						|
        description_encoding = None
 | 
						|
    else:
 | 
						|
        supports_unicode_statements = False
 | 
						|
        supports_unicode_binds = False
 | 
						|
        returns_unicode_strings = sqltypes.String.RETURNS_UNKNOWN
 | 
						|
        description_encoding = "use_encoding"
 | 
						|
 | 
						|
    name = "default"
 | 
						|
 | 
						|
    # length at which to truncate
 | 
						|
    # any identifier.
 | 
						|
    max_identifier_length = 9999
 | 
						|
    _user_defined_max_identifier_length = None
 | 
						|
 | 
						|
    isolation_level = None
 | 
						|
 | 
						|
    # sub-categories of max_identifier_length.
 | 
						|
    # currently these accommodate for MySQL which allows alias names
 | 
						|
    # of 255 but DDL names only of 64.
 | 
						|
    max_index_name_length = None
 | 
						|
    max_constraint_name_length = None
 | 
						|
 | 
						|
    supports_sane_rowcount = True
 | 
						|
    supports_sane_multi_rowcount = True
 | 
						|
    colspecs = {}
 | 
						|
    default_paramstyle = "named"
 | 
						|
 | 
						|
    supports_default_values = False
 | 
						|
    """dialect supports INSERT... DEFAULT VALUES syntax"""
 | 
						|
 | 
						|
    supports_default_metavalue = False
 | 
						|
    """dialect supports INSERT... VALUES (DEFAULT) syntax"""
 | 
						|
 | 
						|
    # not sure if this is a real thing but the compiler will deliver it
 | 
						|
    # if this is the only flag enabled.
 | 
						|
    supports_empty_insert = True
 | 
						|
    """dialect supports INSERT () VALUES ()"""
 | 
						|
 | 
						|
    supports_multivalues_insert = False
 | 
						|
 | 
						|
    supports_is_distinct_from = True
 | 
						|
 | 
						|
    supports_server_side_cursors = False
 | 
						|
 | 
						|
    server_side_cursors = False
 | 
						|
 | 
						|
    # extra record-level locking features (#4860)
 | 
						|
    supports_for_update_of = False
 | 
						|
 | 
						|
    server_version_info = None
 | 
						|
 | 
						|
    default_schema_name = None
 | 
						|
 | 
						|
    construct_arguments = None
 | 
						|
    """Optional set of argument specifiers for various SQLAlchemy
 | 
						|
    constructs, typically schema items.
 | 
						|
 | 
						|
    To implement, establish as a series of tuples, as in::
 | 
						|
 | 
						|
        construct_arguments = [
 | 
						|
            (schema.Index, {
 | 
						|
                "using": False,
 | 
						|
                "where": None,
 | 
						|
                "ops": None
 | 
						|
            })
 | 
						|
        ]
 | 
						|
 | 
						|
    If the above construct is established on the PostgreSQL dialect,
 | 
						|
    the :class:`.Index` construct will now accept the keyword arguments
 | 
						|
    ``postgresql_using``, ``postgresql_where``, nad ``postgresql_ops``.
 | 
						|
    Any other argument specified to the constructor of :class:`.Index`
 | 
						|
    which is prefixed with ``postgresql_`` will raise :class:`.ArgumentError`.
 | 
						|
 | 
						|
    A dialect which does not include a ``construct_arguments`` member will
 | 
						|
    not participate in the argument validation system.  For such a dialect,
 | 
						|
    any argument name is accepted by all participating constructs, within
 | 
						|
    the namespace of arguments prefixed with that dialect name.  The rationale
 | 
						|
    here is so that third-party dialects that haven't yet implemented this
 | 
						|
    feature continue to function in the old way.
 | 
						|
 | 
						|
    .. versionadded:: 0.9.2
 | 
						|
 | 
						|
    .. seealso::
 | 
						|
 | 
						|
        :class:`.DialectKWArgs` - implementing base class which consumes
 | 
						|
        :attr:`.DefaultDialect.construct_arguments`
 | 
						|
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    # indicates symbol names are
 | 
						|
    # UPPERCASEd if they are case insensitive
 | 
						|
    # within the database.
 | 
						|
    # if this is True, the methods normalize_name()
 | 
						|
    # and denormalize_name() must be provided.
 | 
						|
    requires_name_normalize = False
 | 
						|
 | 
						|
    reflection_options = ()
 | 
						|
 | 
						|
    dbapi_exception_translation_map = util.immutabledict()
 | 
						|
    """mapping used in the extremely unusual case that a DBAPI's
 | 
						|
    published exceptions don't actually have the __name__ that they
 | 
						|
    are linked towards.
 | 
						|
 | 
						|
    .. versionadded:: 1.0.5
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    is_async = False
 | 
						|
 | 
						|
    CACHE_HIT = CACHE_HIT
 | 
						|
    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=(
 | 
						|
            "1.3",
 | 
						|
            "The :paramref:`_sa.create_engine.convert_unicode` parameter "
 | 
						|
            "and corresponding dialect-level parameters are deprecated, "
 | 
						|
            "and will be removed in a future release.  Modern DBAPIs support "
 | 
						|
            "Python Unicode natively and this parameter is unnecessary.",
 | 
						|
        ),
 | 
						|
        empty_in_strategy=(
 | 
						|
            "1.4",
 | 
						|
            "The :paramref:`_sa.create_engine.empty_in_strategy` keyword is "
 | 
						|
            "deprecated, and no longer has any effect.  All IN expressions "
 | 
						|
            "are now rendered using "
 | 
						|
            'the "expanding parameter" strategy which renders a set of bound'
 | 
						|
            'expressions, or an "empty set" SELECT, at statement execution'
 | 
						|
            "time.",
 | 
						|
        ),
 | 
						|
        case_sensitive=(
 | 
						|
            "1.4",
 | 
						|
            "The :paramref:`_sa.create_engine.case_sensitive` parameter "
 | 
						|
            "is deprecated and will be removed in a future release. "
 | 
						|
            "Applications should work with result column names in a case "
 | 
						|
            "sensitive fashion.",
 | 
						|
        ),
 | 
						|
        server_side_cursors=(
 | 
						|
            "1.4",
 | 
						|
            "The :paramref:`_sa.create_engine.server_side_cursors` parameter "
 | 
						|
            "is deprecated and will be removed in a future release.  Please "
 | 
						|
            "use the "
 | 
						|
            ":paramref:`_engine.Connection.execution_options.stream_results` "
 | 
						|
            "parameter.",
 | 
						|
        ),
 | 
						|
    )
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        convert_unicode=False,
 | 
						|
        encoding="utf-8",
 | 
						|
        paramstyle=None,
 | 
						|
        dbapi=None,
 | 
						|
        implicit_returning=None,
 | 
						|
        case_sensitive=True,
 | 
						|
        supports_native_boolean=None,
 | 
						|
        max_identifier_length=None,
 | 
						|
        label_length=None,
 | 
						|
        # int() is because the @deprecated_params decorator cannot accommodate
 | 
						|
        # the direct reference to the "NO_LINTING" object
 | 
						|
        compiler_linting=int(compiler.NO_LINTING),
 | 
						|
        server_side_cursors=False,
 | 
						|
        **kwargs
 | 
						|
    ):
 | 
						|
 | 
						|
        if not getattr(self, "ported_sqla_06", True):
 | 
						|
            util.warn(
 | 
						|
                "The %s dialect is not yet ported to the 0.6 format"
 | 
						|
                % self.name
 | 
						|
            )
 | 
						|
 | 
						|
        if server_side_cursors:
 | 
						|
            if not self.supports_server_side_cursors:
 | 
						|
                raise exc.ArgumentError(
 | 
						|
                    "Dialect %s does not support server side cursors" % self
 | 
						|
                )
 | 
						|
            else:
 | 
						|
                self.server_side_cursors = True
 | 
						|
 | 
						|
        self.convert_unicode = convert_unicode
 | 
						|
        self.encoding = encoding
 | 
						|
        self.positional = False
 | 
						|
        self._ischema = None
 | 
						|
        self.dbapi = dbapi
 | 
						|
        if paramstyle is not None:
 | 
						|
            self.paramstyle = paramstyle
 | 
						|
        elif self.dbapi is not None:
 | 
						|
            self.paramstyle = self.dbapi.paramstyle
 | 
						|
        else:
 | 
						|
            self.paramstyle = self.default_paramstyle
 | 
						|
        if implicit_returning is not None:
 | 
						|
            self.implicit_returning = implicit_returning
 | 
						|
        self.positional = self.paramstyle in ("qmark", "format", "numeric")
 | 
						|
        self.identifier_preparer = self.preparer(self)
 | 
						|
        self.type_compiler = self.type_compiler(self)
 | 
						|
        if supports_native_boolean is not None:
 | 
						|
            self.supports_native_boolean = supports_native_boolean
 | 
						|
        self.case_sensitive = case_sensitive
 | 
						|
 | 
						|
        self._user_defined_max_identifier_length = max_identifier_length
 | 
						|
        if self._user_defined_max_identifier_length:
 | 
						|
            self.max_identifier_length = (
 | 
						|
                self._user_defined_max_identifier_length
 | 
						|
            )
 | 
						|
        self.label_length = label_length
 | 
						|
        self.compiler_linting = compiler_linting
 | 
						|
        if self.description_encoding == "use_encoding":
 | 
						|
            self._description_decoder = (
 | 
						|
                processors.to_unicode_processor_factory
 | 
						|
            )(encoding)
 | 
						|
        elif self.description_encoding is not None:
 | 
						|
            self._description_decoder = (
 | 
						|
                processors.to_unicode_processor_factory
 | 
						|
            )(self.description_encoding)
 | 
						|
        self._encoder = codecs.getencoder(self.encoding)
 | 
						|
        self._decoder = processors.to_unicode_processor_factory(self.encoding)
 | 
						|
 | 
						|
    def _ensure_has_table_connection(self, arg):
 | 
						|
 | 
						|
        if not isinstance(arg, Connection):
 | 
						|
            raise exc.ArgumentError(
 | 
						|
                "The argument passed to Dialect.has_table() should be a "
 | 
						|
                "%s, got %s. "
 | 
						|
                "Additionally, the Dialect.has_table() method is for "
 | 
						|
                "internal dialect "
 | 
						|
                "use only; please use "
 | 
						|
                "``inspect(some_engine).has_table(<tablename>>)`` "
 | 
						|
                "for public API use." % (Connection, type(arg))
 | 
						|
            )
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def _supports_statement_cache(self):
 | 
						|
        ssc = self.__class__.__dict__.get("supports_statement_cache", None)
 | 
						|
        if ssc is None:
 | 
						|
            util.warn(
 | 
						|
                "Dialect %s:%s will not make use of SQL compilation caching "
 | 
						|
                "as it does not set the 'supports_statement_cache' attribute "
 | 
						|
                "to ``True``.  This can have "
 | 
						|
                "significant performance implications including some "
 | 
						|
                "performance degradations in comparison to prior SQLAlchemy "
 | 
						|
                "versions.  Dialect maintainers should seek to set this "
 | 
						|
                "attribute to True after appropriate development and testing "
 | 
						|
                "for SQLAlchemy 1.4 caching support.   Alternatively, this "
 | 
						|
                "attribute may be set to False which will disable this "
 | 
						|
                "warning." % (self.name, self.driver),
 | 
						|
                code="cprf",
 | 
						|
            )
 | 
						|
 | 
						|
        return bool(ssc)
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def _type_memos(self):
 | 
						|
        return weakref.WeakKeyDictionary()
 | 
						|
 | 
						|
    @property
 | 
						|
    def dialect_description(self):
 | 
						|
        return self.name + "+" + self.driver
 | 
						|
 | 
						|
    @property
 | 
						|
    def supports_sane_rowcount_returning(self):
 | 
						|
        """True if this dialect supports sane rowcount even if RETURNING is
 | 
						|
        in use.
 | 
						|
 | 
						|
        For dialects that don't support RETURNING, this is synonymous with
 | 
						|
        ``supports_sane_rowcount``.
 | 
						|
 | 
						|
        """
 | 
						|
        return self.supports_sane_rowcount
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def get_pool_class(cls, url):
 | 
						|
        return getattr(cls, "poolclass", pool.QueuePool)
 | 
						|
 | 
						|
    def get_dialect_pool_class(self, url):
 | 
						|
        return self.get_pool_class(url)
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def load_provisioning(cls):
 | 
						|
        package = ".".join(cls.__module__.split(".")[0:-1])
 | 
						|
        try:
 | 
						|
            __import__(package + ".provision")
 | 
						|
        except ImportError:
 | 
						|
            pass
 | 
						|
 | 
						|
    def initialize(self, connection):
 | 
						|
        try:
 | 
						|
            self.server_version_info = self._get_server_version_info(
 | 
						|
                connection
 | 
						|
            )
 | 
						|
        except NotImplementedError:
 | 
						|
            self.server_version_info = None
 | 
						|
        try:
 | 
						|
            self.default_schema_name = self._get_default_schema_name(
 | 
						|
                connection
 | 
						|
            )
 | 
						|
        except NotImplementedError:
 | 
						|
            self.default_schema_name = None
 | 
						|
 | 
						|
        try:
 | 
						|
            self.default_isolation_level = self.get_default_isolation_level(
 | 
						|
                connection.connection
 | 
						|
            )
 | 
						|
        except NotImplementedError:
 | 
						|
            self.default_isolation_level = None
 | 
						|
 | 
						|
        if self.returns_unicode_strings is sqltypes.String.RETURNS_UNKNOWN:
 | 
						|
            if util.py3k:
 | 
						|
                raise exc.InvalidRequestError(
 | 
						|
                    "RETURNS_UNKNOWN is unsupported in Python 3"
 | 
						|
                )
 | 
						|
            self.returns_unicode_strings = self._check_unicode_returns(
 | 
						|
                connection
 | 
						|
            )
 | 
						|
 | 
						|
        if (
 | 
						|
            self.description_encoding is not None
 | 
						|
            and self._check_unicode_description(connection)
 | 
						|
        ):
 | 
						|
            self._description_decoder = self.description_encoding = None
 | 
						|
 | 
						|
        if not self._user_defined_max_identifier_length:
 | 
						|
            max_ident_length = self._check_max_identifier_length(connection)
 | 
						|
            if max_ident_length:
 | 
						|
                self.max_identifier_length = max_ident_length
 | 
						|
 | 
						|
        if (
 | 
						|
            self.label_length
 | 
						|
            and self.label_length > self.max_identifier_length
 | 
						|
        ):
 | 
						|
            raise exc.ArgumentError(
 | 
						|
                "Label length of %d is greater than this dialect's"
 | 
						|
                " maximum identifier length of %d"
 | 
						|
                % (self.label_length, self.max_identifier_length)
 | 
						|
            )
 | 
						|
 | 
						|
    def on_connect(self):
 | 
						|
        # inherits the docstring from interfaces.Dialect.on_connect
 | 
						|
        return None
 | 
						|
 | 
						|
    def _check_max_identifier_length(self, connection):
 | 
						|
        """Perform a connection / server version specific check to determine
 | 
						|
        the max_identifier_length.
 | 
						|
 | 
						|
        If the dialect's class level max_identifier_length should be used,
 | 
						|
        can return None.
 | 
						|
 | 
						|
        .. versionadded:: 1.3.9
 | 
						|
 | 
						|
        """
 | 
						|
        return None
 | 
						|
 | 
						|
    def get_default_isolation_level(self, dbapi_conn):
 | 
						|
        """Given a DBAPI connection, return its isolation level, or
 | 
						|
        a default isolation level if one cannot be retrieved.
 | 
						|
 | 
						|
        May be overridden by subclasses in order to provide a
 | 
						|
        "fallback" isolation level for databases that cannot reliably
 | 
						|
        retrieve the actual isolation level.
 | 
						|
 | 
						|
        By default, calls the :meth:`_engine.Interfaces.get_isolation_level`
 | 
						|
        method, propagating any exceptions raised.
 | 
						|
 | 
						|
        .. versionadded:: 1.3.22
 | 
						|
 | 
						|
        """
 | 
						|
        return self.get_isolation_level(dbapi_conn)
 | 
						|
 | 
						|
    def _check_unicode_returns(self, connection, additional_tests=None):
 | 
						|
        # this now runs in py2k only and will be removed in 2.0; disabled for
 | 
						|
        # Python 3 in all cases under #5315
 | 
						|
        if util.py2k and not self.supports_unicode_statements:
 | 
						|
            cast_to = util.binary_type
 | 
						|
        else:
 | 
						|
            cast_to = util.text_type
 | 
						|
 | 
						|
        if self.positional:
 | 
						|
            parameters = self.execute_sequence_format()
 | 
						|
        else:
 | 
						|
            parameters = {}
 | 
						|
 | 
						|
        def check_unicode(test):
 | 
						|
            statement = cast_to(expression.select(test).compile(dialect=self))
 | 
						|
            try:
 | 
						|
                cursor = connection.connection.cursor()
 | 
						|
                connection._cursor_execute(cursor, statement, parameters)
 | 
						|
                row = cursor.fetchone()
 | 
						|
                cursor.close()
 | 
						|
            except exc.DBAPIError as de:
 | 
						|
                # note that _cursor_execute() will have closed the cursor
 | 
						|
                # if an exception is thrown.
 | 
						|
                util.warn(
 | 
						|
                    "Exception attempting to "
 | 
						|
                    "detect unicode returns: %r" % de
 | 
						|
                )
 | 
						|
                return False
 | 
						|
            else:
 | 
						|
                return isinstance(row[0], util.text_type)
 | 
						|
 | 
						|
        tests = [
 | 
						|
            # detect plain VARCHAR
 | 
						|
            expression.cast(
 | 
						|
                expression.literal_column("'test plain returns'"),
 | 
						|
                sqltypes.VARCHAR(60),
 | 
						|
            ),
 | 
						|
            # detect if there's an NVARCHAR type with different behavior
 | 
						|
            # available
 | 
						|
            expression.cast(
 | 
						|
                expression.literal_column("'test unicode returns'"),
 | 
						|
                sqltypes.Unicode(60),
 | 
						|
            ),
 | 
						|
        ]
 | 
						|
 | 
						|
        if additional_tests:
 | 
						|
            tests += additional_tests
 | 
						|
 | 
						|
        results = {check_unicode(test) for test in tests}
 | 
						|
 | 
						|
        if results.issuperset([True, False]):
 | 
						|
            return sqltypes.String.RETURNS_CONDITIONAL
 | 
						|
        else:
 | 
						|
            return (
 | 
						|
                sqltypes.String.RETURNS_UNICODE
 | 
						|
                if results == {True}
 | 
						|
                else sqltypes.String.RETURNS_BYTES
 | 
						|
            )
 | 
						|
 | 
						|
    def _check_unicode_description(self, connection):
 | 
						|
        # all DBAPIs on Py2K return cursor.description as encoded
 | 
						|
 | 
						|
        if util.py2k and not self.supports_unicode_statements:
 | 
						|
            cast_to = util.binary_type
 | 
						|
        else:
 | 
						|
            cast_to = util.text_type
 | 
						|
 | 
						|
        cursor = connection.connection.cursor()
 | 
						|
        try:
 | 
						|
            cursor.execute(
 | 
						|
                cast_to(
 | 
						|
                    expression.select(
 | 
						|
                        expression.literal_column("'x'").label("some_label")
 | 
						|
                    ).compile(dialect=self)
 | 
						|
                )
 | 
						|
            )
 | 
						|
            return isinstance(cursor.description[0][0], util.text_type)
 | 
						|
        finally:
 | 
						|
            cursor.close()
 | 
						|
 | 
						|
    def type_descriptor(self, typeobj):
 | 
						|
        """Provide a database-specific :class:`.TypeEngine` object, given
 | 
						|
        the generic object which comes from the types module.
 | 
						|
 | 
						|
        This method looks for a dictionary called
 | 
						|
        ``colspecs`` as a class or instance-level variable,
 | 
						|
        and passes on to :func:`_types.adapt_type`.
 | 
						|
 | 
						|
        """
 | 
						|
        return sqltypes.adapt_type(typeobj, self.colspecs)
 | 
						|
 | 
						|
    def has_index(self, connection, table_name, index_name, schema=None):
 | 
						|
        if not self.has_table(connection, table_name, schema=schema):
 | 
						|
            return False
 | 
						|
        for idx in self.get_indexes(connection, table_name, schema=schema):
 | 
						|
            if idx["name"] == index_name:
 | 
						|
                return True
 | 
						|
        else:
 | 
						|
            return False
 | 
						|
 | 
						|
    def validate_identifier(self, ident):
 | 
						|
        if len(ident) > self.max_identifier_length:
 | 
						|
            raise exc.IdentifierError(
 | 
						|
                "Identifier '%s' exceeds maximum length of %d characters"
 | 
						|
                % (ident, self.max_identifier_length)
 | 
						|
            )
 | 
						|
 | 
						|
    def connect(self, *cargs, **cparams):
 | 
						|
        # inherits the docstring from interfaces.Dialect.connect
 | 
						|
        return self.dbapi.connect(*cargs, **cparams)
 | 
						|
 | 
						|
    def create_connect_args(self, url):
 | 
						|
        # inherits the docstring from interfaces.Dialect.create_connect_args
 | 
						|
        opts = url.translate_connect_args()
 | 
						|
        opts.update(url.query)
 | 
						|
        return [[], opts]
 | 
						|
 | 
						|
    def set_engine_execution_options(self, engine, opts):
 | 
						|
        supported_names = set(self.connection_characteristics).intersection(
 | 
						|
            opts
 | 
						|
        )
 | 
						|
        if supported_names:
 | 
						|
            characteristics = util.immutabledict(
 | 
						|
                (name, opts[name]) for name in supported_names
 | 
						|
            )
 | 
						|
 | 
						|
            @event.listens_for(engine, "engine_connect")
 | 
						|
            def set_connection_characteristics(connection, branch):
 | 
						|
                if not branch:
 | 
						|
                    self._set_connection_characteristics(
 | 
						|
                        connection, characteristics
 | 
						|
                    )
 | 
						|
 | 
						|
    def set_connection_execution_options(self, connection, opts):
 | 
						|
        supported_names = set(self.connection_characteristics).intersection(
 | 
						|
            opts
 | 
						|
        )
 | 
						|
        if supported_names:
 | 
						|
            characteristics = util.immutabledict(
 | 
						|
                (name, opts[name]) for name in supported_names
 | 
						|
            )
 | 
						|
            self._set_connection_characteristics(connection, characteristics)
 | 
						|
 | 
						|
    def _set_connection_characteristics(self, connection, characteristics):
 | 
						|
 | 
						|
        characteristic_values = [
 | 
						|
            (name, self.connection_characteristics[name], value)
 | 
						|
            for name, value in characteristics.items()
 | 
						|
        ]
 | 
						|
 | 
						|
        if connection.in_transaction():
 | 
						|
            trans_objs = [
 | 
						|
                (name, obj)
 | 
						|
                for name, obj, value in characteristic_values
 | 
						|
                if obj.transactional
 | 
						|
            ]
 | 
						|
            if trans_objs:
 | 
						|
                if connection._is_future:
 | 
						|
                    raise exc.InvalidRequestError(
 | 
						|
                        "This connection has already initialized a SQLAlchemy "
 | 
						|
                        "Transaction() object via begin() or autobegin; "
 | 
						|
                        "%s may not be altered unless rollback() or commit() "
 | 
						|
                        "is called first."
 | 
						|
                        % (", ".join(name for name, obj in trans_objs))
 | 
						|
                    )
 | 
						|
                else:
 | 
						|
                    util.warn(
 | 
						|
                        "Connection is already established with a "
 | 
						|
                        "Transaction; "
 | 
						|
                        "setting %s may implicitly rollback or "
 | 
						|
                        "commit "
 | 
						|
                        "the existing transaction, or have no effect until "
 | 
						|
                        "next transaction"
 | 
						|
                        % (", ".join(name for name, obj in trans_objs))
 | 
						|
                    )
 | 
						|
 | 
						|
        dbapi_connection = connection.connection.dbapi_connection
 | 
						|
        for name, characteristic, value in characteristic_values:
 | 
						|
            characteristic.set_characteristic(self, dbapi_connection, value)
 | 
						|
        connection.connection._connection_record.finalize_callback.append(
 | 
						|
            functools.partial(self._reset_characteristics, characteristics)
 | 
						|
        )
 | 
						|
 | 
						|
    def _reset_characteristics(self, characteristics, dbapi_connection):
 | 
						|
        for characteristic_name in characteristics:
 | 
						|
            characteristic = self.connection_characteristics[
 | 
						|
                characteristic_name
 | 
						|
            ]
 | 
						|
            characteristic.reset_characteristic(self, dbapi_connection)
 | 
						|
 | 
						|
    def do_begin(self, dbapi_connection):
 | 
						|
        pass
 | 
						|
 | 
						|
    def do_rollback(self, dbapi_connection):
 | 
						|
        dbapi_connection.rollback()
 | 
						|
 | 
						|
    def do_commit(self, dbapi_connection):
 | 
						|
        dbapi_connection.commit()
 | 
						|
 | 
						|
    def do_close(self, dbapi_connection):
 | 
						|
        dbapi_connection.close()
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def _dialect_specific_select_one(self):
 | 
						|
        return str(expression.select(1).compile(dialect=self))
 | 
						|
 | 
						|
    def do_ping(self, dbapi_connection):
 | 
						|
        cursor = None
 | 
						|
        try:
 | 
						|
            cursor = dbapi_connection.cursor()
 | 
						|
            try:
 | 
						|
                cursor.execute(self._dialect_specific_select_one)
 | 
						|
            finally:
 | 
						|
                cursor.close()
 | 
						|
        except self.dbapi.Error as err:
 | 
						|
            if self.is_disconnect(err, dbapi_connection, cursor):
 | 
						|
                return False
 | 
						|
            else:
 | 
						|
                raise
 | 
						|
        else:
 | 
						|
            return True
 | 
						|
 | 
						|
    def create_xid(self):
 | 
						|
        """Create a random two-phase transaction ID.
 | 
						|
 | 
						|
        This id will be passed to do_begin_twophase(), do_rollback_twophase(),
 | 
						|
        do_commit_twophase().  Its format is unspecified.
 | 
						|
        """
 | 
						|
 | 
						|
        return "_sa_%032x" % random.randint(0, 2 ** 128)
 | 
						|
 | 
						|
    def do_savepoint(self, connection, name):
 | 
						|
        connection.execute(expression.SavepointClause(name))
 | 
						|
 | 
						|
    def do_rollback_to_savepoint(self, connection, name):
 | 
						|
        connection.execute(expression.RollbackToSavepointClause(name))
 | 
						|
 | 
						|
    def do_release_savepoint(self, connection, name):
 | 
						|
        connection.execute(expression.ReleaseSavepointClause(name))
 | 
						|
 | 
						|
    def do_executemany(self, cursor, statement, parameters, context=None):
 | 
						|
        cursor.executemany(statement, parameters)
 | 
						|
 | 
						|
    def do_execute(self, cursor, statement, parameters, context=None):
 | 
						|
        cursor.execute(statement, parameters)
 | 
						|
 | 
						|
    def do_execute_no_params(self, cursor, statement, context=None):
 | 
						|
        cursor.execute(statement)
 | 
						|
 | 
						|
    def is_disconnect(self, e, connection, cursor):
 | 
						|
        return False
 | 
						|
 | 
						|
    def reset_isolation_level(self, dbapi_conn):
 | 
						|
        # default_isolation_level is read from the first connection
 | 
						|
        # after the initial set of 'isolation_level', if any, so is
 | 
						|
        # the configured default of this dialect.
 | 
						|
        self.set_isolation_level(dbapi_conn, self.default_isolation_level)
 | 
						|
 | 
						|
    def normalize_name(self, name):
 | 
						|
        if name is None:
 | 
						|
            return None
 | 
						|
        if util.py2k:
 | 
						|
            if isinstance(name, str):
 | 
						|
                name = name.decode(self.encoding)
 | 
						|
 | 
						|
        name_lower = name.lower()
 | 
						|
        name_upper = name.upper()
 | 
						|
 | 
						|
        if name_upper == name_lower:
 | 
						|
            # name has no upper/lower conversion, e.g. non-european characters.
 | 
						|
            # return unchanged
 | 
						|
            return name
 | 
						|
        elif name_upper == name and not (
 | 
						|
            self.identifier_preparer._requires_quotes
 | 
						|
        )(name_lower):
 | 
						|
            # name is all uppercase and doesn't require quoting; normalize
 | 
						|
            # to all lower case
 | 
						|
            return name_lower
 | 
						|
        elif name_lower == name:
 | 
						|
            # name is all lower case, which if denormalized means we need to
 | 
						|
            # force quoting on it
 | 
						|
            return quoted_name(name, quote=True)
 | 
						|
        else:
 | 
						|
            # name is mixed case, means it will be quoted in SQL when used
 | 
						|
            # later, no normalizes
 | 
						|
            return name
 | 
						|
 | 
						|
    def denormalize_name(self, name):
 | 
						|
        if name is None:
 | 
						|
            return None
 | 
						|
 | 
						|
        name_lower = name.lower()
 | 
						|
        name_upper = name.upper()
 | 
						|
 | 
						|
        if name_upper == name_lower:
 | 
						|
            # name has no upper/lower conversion, e.g. non-european characters.
 | 
						|
            # return unchanged
 | 
						|
            return name
 | 
						|
        elif name_lower == name and not (
 | 
						|
            self.identifier_preparer._requires_quotes
 | 
						|
        )(name_lower):
 | 
						|
            name = name_upper
 | 
						|
        if util.py2k:
 | 
						|
            if not self.supports_unicode_binds:
 | 
						|
                name = name.encode(self.encoding)
 | 
						|
            else:
 | 
						|
                name = unicode(name)  # noqa
 | 
						|
        return name
 | 
						|
 | 
						|
    def get_driver_connection(self, connection):
 | 
						|
        return connection
 | 
						|
 | 
						|
 | 
						|
class _RendersLiteral(object):
 | 
						|
    def literal_processor(self, dialect):
 | 
						|
        def process(value):
 | 
						|
            return "'%s'" % value
 | 
						|
 | 
						|
        return process
 | 
						|
 | 
						|
 | 
						|
class _StrDateTime(_RendersLiteral, sqltypes.DateTime):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
class _StrDate(_RendersLiteral, sqltypes.Date):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
class _StrTime(_RendersLiteral, sqltypes.Time):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
class StrCompileDialect(DefaultDialect):
 | 
						|
 | 
						|
    statement_compiler = compiler.StrSQLCompiler
 | 
						|
    ddl_compiler = compiler.DDLCompiler
 | 
						|
    type_compiler = compiler.StrSQLTypeCompiler
 | 
						|
    preparer = compiler.IdentifierPreparer
 | 
						|
 | 
						|
    supports_statement_cache = True
 | 
						|
 | 
						|
    supports_identity_columns = True
 | 
						|
 | 
						|
    supports_sequences = True
 | 
						|
    sequences_optional = True
 | 
						|
    preexecute_autoincrement_sequences = False
 | 
						|
    implicit_returning = False
 | 
						|
 | 
						|
    supports_native_boolean = True
 | 
						|
 | 
						|
    supports_multivalues_insert = True
 | 
						|
    supports_simple_order_by_label = True
 | 
						|
 | 
						|
    colspecs = {
 | 
						|
        sqltypes.DateTime: _StrDateTime,
 | 
						|
        sqltypes.Date: _StrDate,
 | 
						|
        sqltypes.Time: _StrTime,
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
class DefaultExecutionContext(interfaces.ExecutionContext):
 | 
						|
    isinsert = False
 | 
						|
    isupdate = False
 | 
						|
    isdelete = False
 | 
						|
    is_crud = False
 | 
						|
    is_text = False
 | 
						|
    isddl = False
 | 
						|
    executemany = False
 | 
						|
    compiled = None
 | 
						|
    statement = None
 | 
						|
    result_column_struct = None
 | 
						|
    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
 | 
						|
    invoked_statement = None
 | 
						|
 | 
						|
    _is_implicit_returning = False
 | 
						|
    _is_explicit_returning = False
 | 
						|
    _is_future_result = False
 | 
						|
    _is_server_side = False
 | 
						|
 | 
						|
    _soft_closed = False
 | 
						|
 | 
						|
    # a hook for SQLite's translation of
 | 
						|
    # result column names
 | 
						|
    # NOTE: pyhive is using this hook, can't remove it :(
 | 
						|
    _translate_colname = None
 | 
						|
 | 
						|
    _expanded_parameters = util.immutabledict()
 | 
						|
 | 
						|
    cache_hit = NO_CACHE_KEY
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _init_ddl(
 | 
						|
        cls,
 | 
						|
        dialect,
 | 
						|
        connection,
 | 
						|
        dbapi_connection,
 | 
						|
        execution_options,
 | 
						|
        compiled_ddl,
 | 
						|
    ):
 | 
						|
        """Initialize execution context for a DDLElement construct."""
 | 
						|
 | 
						|
        self = cls.__new__(cls)
 | 
						|
        self.root_connection = connection
 | 
						|
        self._dbapi_connection = dbapi_connection
 | 
						|
        self.dialect = connection.dialect
 | 
						|
 | 
						|
        self.compiled = compiled = compiled_ddl
 | 
						|
        self.isddl = True
 | 
						|
 | 
						|
        self.execution_options = execution_options
 | 
						|
 | 
						|
        self._is_future_result = (
 | 
						|
            connection._is_future
 | 
						|
            or self.execution_options.get("future_result", False)
 | 
						|
        )
 | 
						|
 | 
						|
        self.unicode_statement = util.text_type(compiled)
 | 
						|
        if compiled.schema_translate_map:
 | 
						|
            schema_translate_map = self.execution_options.get(
 | 
						|
                "schema_translate_map", {}
 | 
						|
            )
 | 
						|
 | 
						|
            rst = compiled.preparer._render_schema_translates
 | 
						|
            self.unicode_statement = rst(
 | 
						|
                self.unicode_statement, schema_translate_map
 | 
						|
            )
 | 
						|
 | 
						|
        if not dialect.supports_unicode_statements:
 | 
						|
            self.statement = dialect._encoder(self.unicode_statement)[0]
 | 
						|
        else:
 | 
						|
            self.statement = self.unicode_statement
 | 
						|
 | 
						|
        self.cursor = self.create_cursor()
 | 
						|
        self.compiled_parameters = []
 | 
						|
 | 
						|
        if dialect.positional:
 | 
						|
            self.parameters = [dialect.execute_sequence_format()]
 | 
						|
        else:
 | 
						|
            self.parameters = [{}]
 | 
						|
 | 
						|
        return self
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _init_compiled(
 | 
						|
        cls,
 | 
						|
        dialect,
 | 
						|
        connection,
 | 
						|
        dbapi_connection,
 | 
						|
        execution_options,
 | 
						|
        compiled,
 | 
						|
        parameters,
 | 
						|
        invoked_statement,
 | 
						|
        extracted_parameters,
 | 
						|
        cache_hit=CACHING_DISABLED,
 | 
						|
    ):
 | 
						|
        """Initialize execution context for a Compiled construct."""
 | 
						|
 | 
						|
        self = cls.__new__(cls)
 | 
						|
        self.root_connection = connection
 | 
						|
        self._dbapi_connection = dbapi_connection
 | 
						|
        self.dialect = connection.dialect
 | 
						|
        self.extracted_parameters = extracted_parameters
 | 
						|
        self.invoked_statement = invoked_statement
 | 
						|
        self.compiled = compiled
 | 
						|
        self.cache_hit = cache_hit
 | 
						|
 | 
						|
        self.execution_options = execution_options
 | 
						|
 | 
						|
        self._is_future_result = (
 | 
						|
            connection._is_future
 | 
						|
            or self.execution_options.get("future_result", False)
 | 
						|
        )
 | 
						|
 | 
						|
        self.result_column_struct = (
 | 
						|
            compiled._result_columns,
 | 
						|
            compiled._ordered_columns,
 | 
						|
            compiled._textual_ordered_columns,
 | 
						|
            compiled._loose_column_name_matching,
 | 
						|
        )
 | 
						|
        self.isinsert = compiled.isinsert
 | 
						|
        self.isupdate = compiled.isupdate
 | 
						|
        self.isdelete = compiled.isdelete
 | 
						|
        self.is_text = compiled.isplaintext
 | 
						|
 | 
						|
        if self.isinsert or self.isupdate or self.isdelete:
 | 
						|
            self.is_crud = True
 | 
						|
            self._is_explicit_returning = bool(compiled.statement._returning)
 | 
						|
            self._is_implicit_returning = bool(
 | 
						|
                compiled.returning and not compiled.statement._returning
 | 
						|
            )
 | 
						|
 | 
						|
        if not parameters:
 | 
						|
            self.compiled_parameters = [
 | 
						|
                compiled.construct_params(
 | 
						|
                    extracted_parameters=extracted_parameters
 | 
						|
                )
 | 
						|
            ]
 | 
						|
        else:
 | 
						|
            self.compiled_parameters = [
 | 
						|
                compiled.construct_params(
 | 
						|
                    m,
 | 
						|
                    _group_number=grp,
 | 
						|
                    extracted_parameters=extracted_parameters,
 | 
						|
                )
 | 
						|
                for grp, m in enumerate(parameters)
 | 
						|
            ]
 | 
						|
 | 
						|
            self.executemany = len(parameters) > 1
 | 
						|
 | 
						|
        # this must occur before create_cursor() since the statement
 | 
						|
        # has to be regexed in some cases for server side cursor
 | 
						|
        if util.py2k:
 | 
						|
            self.unicode_statement = util.text_type(compiled.string)
 | 
						|
        else:
 | 
						|
            self.unicode_statement = compiled.string
 | 
						|
 | 
						|
        self.cursor = self.create_cursor()
 | 
						|
 | 
						|
        if self.compiled.insert_prefetch or self.compiled.update_prefetch:
 | 
						|
            if self.executemany:
 | 
						|
                self._process_executemany_defaults()
 | 
						|
            else:
 | 
						|
                self._process_executesingle_defaults()
 | 
						|
 | 
						|
        processors = compiled._bind_processors
 | 
						|
 | 
						|
        if compiled.literal_execute_params or compiled.post_compile_params:
 | 
						|
            if self.executemany:
 | 
						|
                raise exc.InvalidRequestError(
 | 
						|
                    "'literal_execute' or 'expanding' parameters can't be "
 | 
						|
                    "used with executemany()"
 | 
						|
                )
 | 
						|
 | 
						|
            expanded_state = compiled._process_parameters_for_postcompile(
 | 
						|
                self.compiled_parameters[0]
 | 
						|
            )
 | 
						|
 | 
						|
            # re-assign self.unicode_statement
 | 
						|
            self.unicode_statement = expanded_state.statement
 | 
						|
 | 
						|
            # used by set_input_sizes() which is needed for Oracle
 | 
						|
            self._expanded_parameters = expanded_state.parameter_expansion
 | 
						|
 | 
						|
            processors = dict(processors)
 | 
						|
            processors.update(expanded_state.processors)
 | 
						|
            positiontup = expanded_state.positiontup
 | 
						|
        elif compiled.positional:
 | 
						|
            positiontup = self.compiled.positiontup
 | 
						|
 | 
						|
        if compiled.schema_translate_map:
 | 
						|
            schema_translate_map = self.execution_options.get(
 | 
						|
                "schema_translate_map", {}
 | 
						|
            )
 | 
						|
            rst = compiled.preparer._render_schema_translates
 | 
						|
            self.unicode_statement = rst(
 | 
						|
                self.unicode_statement, schema_translate_map
 | 
						|
            )
 | 
						|
 | 
						|
        # final self.unicode_statement is now assigned, encode if needed
 | 
						|
        # by dialect
 | 
						|
        if not dialect.supports_unicode_statements:
 | 
						|
            self.statement = self.unicode_statement.encode(
 | 
						|
                self.dialect.encoding
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            self.statement = self.unicode_statement
 | 
						|
 | 
						|
        # Convert the dictionary of bind parameter values
 | 
						|
        # into a dict or list to be sent to the DBAPI's
 | 
						|
        # execute() or executemany() method.
 | 
						|
        parameters = []
 | 
						|
        if compiled.positional:
 | 
						|
            for compiled_params in self.compiled_parameters:
 | 
						|
                param = [
 | 
						|
                    processors[key](compiled_params[key])
 | 
						|
                    if key in processors
 | 
						|
                    else compiled_params[key]
 | 
						|
                    for key in positiontup
 | 
						|
                ]
 | 
						|
                parameters.append(dialect.execute_sequence_format(param))
 | 
						|
        else:
 | 
						|
            encode = not dialect.supports_unicode_statements
 | 
						|
            if encode:
 | 
						|
                encoder = dialect._encoder
 | 
						|
            for compiled_params in self.compiled_parameters:
 | 
						|
 | 
						|
                if encode:
 | 
						|
                    param = {
 | 
						|
                        encoder(key)[0]: processors[key](compiled_params[key])
 | 
						|
                        if key in processors
 | 
						|
                        else compiled_params[key]
 | 
						|
                        for key in compiled_params
 | 
						|
                    }
 | 
						|
                else:
 | 
						|
                    param = {
 | 
						|
                        key: processors[key](compiled_params[key])
 | 
						|
                        if key in processors
 | 
						|
                        else compiled_params[key]
 | 
						|
                        for key in compiled_params
 | 
						|
                    }
 | 
						|
 | 
						|
                parameters.append(param)
 | 
						|
 | 
						|
        self.parameters = dialect.execute_sequence_format(parameters)
 | 
						|
 | 
						|
        return self
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _init_statement(
 | 
						|
        cls,
 | 
						|
        dialect,
 | 
						|
        connection,
 | 
						|
        dbapi_connection,
 | 
						|
        execution_options,
 | 
						|
        statement,
 | 
						|
        parameters,
 | 
						|
    ):
 | 
						|
        """Initialize execution context for a string SQL statement."""
 | 
						|
 | 
						|
        self = cls.__new__(cls)
 | 
						|
        self.root_connection = connection
 | 
						|
        self._dbapi_connection = dbapi_connection
 | 
						|
        self.dialect = connection.dialect
 | 
						|
        self.is_text = True
 | 
						|
 | 
						|
        self.execution_options = execution_options
 | 
						|
 | 
						|
        self._is_future_result = (
 | 
						|
            connection._is_future
 | 
						|
            or self.execution_options.get("future_result", False)
 | 
						|
        )
 | 
						|
 | 
						|
        if not parameters:
 | 
						|
            if self.dialect.positional:
 | 
						|
                self.parameters = [dialect.execute_sequence_format()]
 | 
						|
            else:
 | 
						|
                self.parameters = [{}]
 | 
						|
        elif isinstance(parameters[0], dialect.execute_sequence_format):
 | 
						|
            self.parameters = parameters
 | 
						|
        elif isinstance(parameters[0], dict):
 | 
						|
            if dialect.supports_unicode_statements:
 | 
						|
                self.parameters = parameters
 | 
						|
            else:
 | 
						|
                self.parameters = [
 | 
						|
                    {dialect._encoder(k)[0]: d[k] for k in d}
 | 
						|
                    for d in parameters
 | 
						|
                ] or [{}]
 | 
						|
        else:
 | 
						|
            self.parameters = [
 | 
						|
                dialect.execute_sequence_format(p) for p in parameters
 | 
						|
            ]
 | 
						|
 | 
						|
        self.executemany = len(parameters) > 1
 | 
						|
 | 
						|
        if not dialect.supports_unicode_statements and isinstance(
 | 
						|
            statement, util.text_type
 | 
						|
        ):
 | 
						|
            self.unicode_statement = statement
 | 
						|
            self.statement = dialect._encoder(statement)[0]
 | 
						|
        else:
 | 
						|
            self.statement = self.unicode_statement = statement
 | 
						|
 | 
						|
        self.cursor = self.create_cursor()
 | 
						|
        return self
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _init_default(
 | 
						|
        cls, dialect, connection, dbapi_connection, execution_options
 | 
						|
    ):
 | 
						|
        """Initialize execution context for a ColumnDefault construct."""
 | 
						|
 | 
						|
        self = cls.__new__(cls)
 | 
						|
        self.root_connection = connection
 | 
						|
        self._dbapi_connection = dbapi_connection
 | 
						|
        self.dialect = connection.dialect
 | 
						|
 | 
						|
        self.execution_options = execution_options
 | 
						|
 | 
						|
        self._is_future_result = (
 | 
						|
            connection._is_future
 | 
						|
            or self.execution_options.get("future_result", False)
 | 
						|
        )
 | 
						|
 | 
						|
        self.cursor = self.create_cursor()
 | 
						|
        return self
 | 
						|
 | 
						|
    def _get_cache_stats(self):
 | 
						|
        if self.compiled is None:
 | 
						|
            return "raw sql"
 | 
						|
 | 
						|
        now = util.perf_counter()
 | 
						|
 | 
						|
        ch = self.cache_hit
 | 
						|
 | 
						|
        if ch is NO_CACHE_KEY:
 | 
						|
            return "no key %.5fs" % (now - self.compiled._gen_time,)
 | 
						|
        elif ch is CACHE_HIT:
 | 
						|
            return "cached since %.4gs ago" % (now - self.compiled._gen_time,)
 | 
						|
        elif ch is CACHE_MISS:
 | 
						|
            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"
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def identifier_preparer(self):
 | 
						|
        if self.compiled:
 | 
						|
            return self.compiled.preparer
 | 
						|
        elif "schema_translate_map" in self.execution_options:
 | 
						|
            return self.dialect.identifier_preparer._with_schema_translate(
 | 
						|
                self.execution_options["schema_translate_map"]
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            return self.dialect.identifier_preparer
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def engine(self):
 | 
						|
        return self.root_connection.engine
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def postfetch_cols(self):
 | 
						|
        return self.compiled.postfetch
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def prefetch_cols(self):
 | 
						|
        if self.isinsert:
 | 
						|
            return self.compiled.insert_prefetch
 | 
						|
        elif self.isupdate:
 | 
						|
            return self.compiled.update_prefetch
 | 
						|
        else:
 | 
						|
            return ()
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def returning_cols(self):
 | 
						|
        self.compiled.returning
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def no_parameters(self):
 | 
						|
        return self.execution_options.get("no_parameters", False)
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def should_autocommit(self):
 | 
						|
        autocommit = self.execution_options.get(
 | 
						|
            "autocommit",
 | 
						|
            not self.compiled
 | 
						|
            and self.statement
 | 
						|
            and expression.PARSE_AUTOCOMMIT
 | 
						|
            or False,
 | 
						|
        )
 | 
						|
 | 
						|
        if autocommit is expression.PARSE_AUTOCOMMIT:
 | 
						|
            return self.should_autocommit_text(self.unicode_statement)
 | 
						|
        else:
 | 
						|
            return autocommit
 | 
						|
 | 
						|
    def _execute_scalar(self, stmt, type_, parameters=None):
 | 
						|
        """Execute a string statement on the current cursor, returning a
 | 
						|
        scalar result.
 | 
						|
 | 
						|
        Used to fire off sequences, default phrases, and "select lastrowid"
 | 
						|
        types of statements individually or in the context of a parent INSERT
 | 
						|
        or UPDATE statement.
 | 
						|
 | 
						|
        """
 | 
						|
 | 
						|
        conn = self.root_connection
 | 
						|
        if (
 | 
						|
            isinstance(stmt, util.text_type)
 | 
						|
            and not self.dialect.supports_unicode_statements
 | 
						|
        ):
 | 
						|
            stmt = self.dialect._encoder(stmt)[0]
 | 
						|
 | 
						|
        if "schema_translate_map" in self.execution_options:
 | 
						|
            schema_translate_map = self.execution_options.get(
 | 
						|
                "schema_translate_map", {}
 | 
						|
            )
 | 
						|
 | 
						|
            rst = self.identifier_preparer._render_schema_translates
 | 
						|
            stmt = rst(stmt, schema_translate_map)
 | 
						|
 | 
						|
        if not parameters:
 | 
						|
            if self.dialect.positional:
 | 
						|
                parameters = self.dialect.execute_sequence_format()
 | 
						|
            else:
 | 
						|
                parameters = {}
 | 
						|
 | 
						|
        conn._cursor_execute(self.cursor, stmt, parameters, context=self)
 | 
						|
        r = self.cursor.fetchone()[0]
 | 
						|
        if type_ is not None:
 | 
						|
            # apply type post processors to the result
 | 
						|
            proc = type_._cached_result_processor(
 | 
						|
                self.dialect, self.cursor.description[0][1]
 | 
						|
            )
 | 
						|
            if proc:
 | 
						|
                return proc(r)
 | 
						|
        return r
 | 
						|
 | 
						|
    @property
 | 
						|
    def connection(self):
 | 
						|
        conn = self.root_connection
 | 
						|
        if conn._is_future:
 | 
						|
            return conn
 | 
						|
        else:
 | 
						|
            return conn._branch()
 | 
						|
 | 
						|
    def should_autocommit_text(self, statement):
 | 
						|
        return AUTOCOMMIT_REGEXP.match(statement)
 | 
						|
 | 
						|
    def _use_server_side_cursor(self):
 | 
						|
        if not self.dialect.supports_server_side_cursors:
 | 
						|
            return False
 | 
						|
 | 
						|
        if self.dialect.server_side_cursors:
 | 
						|
            # this is deprecated
 | 
						|
            use_server_side = self.execution_options.get(
 | 
						|
                "stream_results", True
 | 
						|
            ) and (
 | 
						|
                (
 | 
						|
                    self.compiled
 | 
						|
                    and isinstance(
 | 
						|
                        self.compiled.statement, expression.Selectable
 | 
						|
                    )
 | 
						|
                    or (
 | 
						|
                        (
 | 
						|
                            not self.compiled
 | 
						|
                            or isinstance(
 | 
						|
                                self.compiled.statement, expression.TextClause
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                        and self.unicode_statement
 | 
						|
                        and SERVER_SIDE_CURSOR_RE.match(self.unicode_statement)
 | 
						|
                    )
 | 
						|
                )
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            use_server_side = self.execution_options.get(
 | 
						|
                "stream_results", False
 | 
						|
            )
 | 
						|
 | 
						|
        return use_server_side
 | 
						|
 | 
						|
    def create_cursor(self):
 | 
						|
        if (
 | 
						|
            # inlining initial preference checks for SS cursors
 | 
						|
            self.dialect.supports_server_side_cursors
 | 
						|
            and (
 | 
						|
                self.execution_options.get("stream_results", False)
 | 
						|
                or (
 | 
						|
                    self.dialect.server_side_cursors
 | 
						|
                    and self._use_server_side_cursor()
 | 
						|
                )
 | 
						|
            )
 | 
						|
        ):
 | 
						|
            self._is_server_side = True
 | 
						|
            return self.create_server_side_cursor()
 | 
						|
        else:
 | 
						|
            self._is_server_side = False
 | 
						|
            return self.create_default_cursor()
 | 
						|
 | 
						|
    def create_default_cursor(self):
 | 
						|
        return self._dbapi_connection.cursor()
 | 
						|
 | 
						|
    def create_server_side_cursor(self):
 | 
						|
        raise NotImplementedError()
 | 
						|
 | 
						|
    def pre_exec(self):
 | 
						|
        pass
 | 
						|
 | 
						|
    def get_out_parameter_values(self, names):
 | 
						|
        raise NotImplementedError(
 | 
						|
            "This dialect does not support OUT parameters"
 | 
						|
        )
 | 
						|
 | 
						|
    def post_exec(self):
 | 
						|
        pass
 | 
						|
 | 
						|
    def get_result_processor(self, type_, colname, coltype):
 | 
						|
        """Return a 'result processor' for a given type as present in
 | 
						|
        cursor.description.
 | 
						|
 | 
						|
        This has a default implementation that dialects can override
 | 
						|
        for context-sensitive result type handling.
 | 
						|
 | 
						|
        """
 | 
						|
        return type_._cached_result_processor(self.dialect, coltype)
 | 
						|
 | 
						|
    def get_lastrowid(self):
 | 
						|
        """return self.cursor.lastrowid, or equivalent, after an INSERT.
 | 
						|
 | 
						|
        This may involve calling special cursor functions, issuing a new SELECT
 | 
						|
        on the cursor (or a new one), or returning a stored value that was
 | 
						|
        calculated within post_exec().
 | 
						|
 | 
						|
        This function will only be called for dialects which support "implicit"
 | 
						|
        primary key generation, keep preexecute_autoincrement_sequences set to
 | 
						|
        False, and when no explicit id value was bound to the statement.
 | 
						|
 | 
						|
        The function is called once for an INSERT statement that would need to
 | 
						|
        return the last inserted primary key for those dialects that make use
 | 
						|
        of the lastrowid concept.  In these cases, it is called directly after
 | 
						|
        :meth:`.ExecutionContext.post_exec`.
 | 
						|
 | 
						|
        """
 | 
						|
        return self.cursor.lastrowid
 | 
						|
 | 
						|
    def handle_dbapi_exception(self, e):
 | 
						|
        pass
 | 
						|
 | 
						|
    @property
 | 
						|
    def rowcount(self):
 | 
						|
        return self.cursor.rowcount
 | 
						|
 | 
						|
    def supports_sane_rowcount(self):
 | 
						|
        return self.dialect.supports_sane_rowcount
 | 
						|
 | 
						|
    def supports_sane_multi_rowcount(self):
 | 
						|
        return self.dialect.supports_sane_multi_rowcount
 | 
						|
 | 
						|
    def _setup_result_proxy(self):
 | 
						|
        if self.is_crud or self.is_text:
 | 
						|
            result = self._setup_dml_or_text_result()
 | 
						|
        else:
 | 
						|
            strategy = self.cursor_fetch_strategy
 | 
						|
            if self._is_server_side and strategy is _cursor._DEFAULT_FETCH:
 | 
						|
                strategy = _cursor.BufferedRowCursorFetchStrategy(
 | 
						|
                    self.cursor, self.execution_options
 | 
						|
                )
 | 
						|
            cursor_description = (
 | 
						|
                strategy.alternate_cursor_description
 | 
						|
                or self.cursor.description
 | 
						|
            )
 | 
						|
            if cursor_description is None:
 | 
						|
                strategy = _cursor._NO_CURSOR_DQL
 | 
						|
 | 
						|
            if self._is_future_result:
 | 
						|
                if self.root_connection.should_close_with_result:
 | 
						|
                    raise exc.InvalidRequestError(
 | 
						|
                        "can't use future_result=True with close_with_result"
 | 
						|
                    )
 | 
						|
                result = _cursor.CursorResult(
 | 
						|
                    self, strategy, cursor_description
 | 
						|
                )
 | 
						|
            else:
 | 
						|
                result = _cursor.LegacyCursorResult(
 | 
						|
                    self, strategy, cursor_description
 | 
						|
                )
 | 
						|
 | 
						|
        if (
 | 
						|
            self.compiled
 | 
						|
            and not self.isddl
 | 
						|
            and self.compiled.has_out_parameters
 | 
						|
        ):
 | 
						|
            self._setup_out_parameters(result)
 | 
						|
 | 
						|
        self._soft_closed = result._soft_closed
 | 
						|
 | 
						|
        return result
 | 
						|
 | 
						|
    def _setup_out_parameters(self, result):
 | 
						|
 | 
						|
        out_bindparams = [
 | 
						|
            (param, name)
 | 
						|
            for param, name in self.compiled.bind_names.items()
 | 
						|
            if param.isoutparam
 | 
						|
        ]
 | 
						|
        out_parameters = {}
 | 
						|
 | 
						|
        for bindparam, raw_value in zip(
 | 
						|
            [param for param, name in out_bindparams],
 | 
						|
            self.get_out_parameter_values(
 | 
						|
                [name for param, name in out_bindparams]
 | 
						|
            ),
 | 
						|
        ):
 | 
						|
 | 
						|
            type_ = bindparam.type
 | 
						|
            impl_type = type_.dialect_impl(self.dialect)
 | 
						|
            dbapi_type = impl_type.get_dbapi_type(self.dialect.dbapi)
 | 
						|
            result_processor = impl_type.result_processor(
 | 
						|
                self.dialect, dbapi_type
 | 
						|
            )
 | 
						|
            if result_processor is not None:
 | 
						|
                raw_value = result_processor(raw_value)
 | 
						|
            out_parameters[bindparam.key] = raw_value
 | 
						|
 | 
						|
        result.out_parameters = out_parameters
 | 
						|
 | 
						|
    def _setup_dml_or_text_result(self):
 | 
						|
        if self.isinsert:
 | 
						|
            if self.compiled.postfetch_lastrowid:
 | 
						|
                self.inserted_primary_key_rows = (
 | 
						|
                    self._setup_ins_pk_from_lastrowid()
 | 
						|
                )
 | 
						|
            # else if not self._is_implicit_returning,
 | 
						|
            # the default inserted_primary_key_rows accessor will
 | 
						|
            # return an "empty" primary key collection when accessed.
 | 
						|
 | 
						|
        strategy = self.cursor_fetch_strategy
 | 
						|
        if self._is_server_side and strategy is _cursor._DEFAULT_FETCH:
 | 
						|
            strategy = _cursor.BufferedRowCursorFetchStrategy(
 | 
						|
                self.cursor, self.execution_options
 | 
						|
            )
 | 
						|
        cursor_description = (
 | 
						|
            strategy.alternate_cursor_description or self.cursor.description
 | 
						|
        )
 | 
						|
        if cursor_description is None:
 | 
						|
            strategy = _cursor._NO_CURSOR_DML
 | 
						|
 | 
						|
        if self._is_future_result:
 | 
						|
            result = _cursor.CursorResult(self, strategy, cursor_description)
 | 
						|
        else:
 | 
						|
            result = _cursor.LegacyCursorResult(
 | 
						|
                self, strategy, cursor_description
 | 
						|
            )
 | 
						|
 | 
						|
        if self.isinsert:
 | 
						|
            if self._is_implicit_returning:
 | 
						|
                rows = result.all()
 | 
						|
 | 
						|
                self.returned_default_rows = rows
 | 
						|
 | 
						|
                self.inserted_primary_key_rows = (
 | 
						|
                    self._setup_ins_pk_from_implicit_returning(result, rows)
 | 
						|
                )
 | 
						|
 | 
						|
                # test that it has a cursor metadata that is accurate. the
 | 
						|
                # first row will have been fetched and current assumptions
 | 
						|
                # are that the result has only one row, until executemany()
 | 
						|
                # support is added here.
 | 
						|
                assert result._metadata.returns_rows
 | 
						|
                result._soft_close()
 | 
						|
            elif not self._is_explicit_returning:
 | 
						|
                result._soft_close()
 | 
						|
 | 
						|
                # we assume here the result does not return any rows.
 | 
						|
                # *usually*, this will be true.  However, some dialects
 | 
						|
                # such as that of MSSQL/pyodbc need to SELECT a post fetch
 | 
						|
                # function so this is not necessarily true.
 | 
						|
                # assert not result.returns_rows
 | 
						|
 | 
						|
        elif self.isupdate and self._is_implicit_returning:
 | 
						|
            row = result.fetchone()
 | 
						|
            self.returned_default_rows = [row]
 | 
						|
            result._soft_close()
 | 
						|
 | 
						|
            # test that it has a cursor metadata that is accurate.
 | 
						|
            # the rows have all been fetched however.
 | 
						|
            assert result._metadata.returns_rows
 | 
						|
 | 
						|
        elif not result._metadata.returns_rows:
 | 
						|
            # no results, get rowcount
 | 
						|
            # (which requires open cursor on some drivers
 | 
						|
            # such as kintersbasdb, mxodbc)
 | 
						|
            result.rowcount
 | 
						|
            result._soft_close()
 | 
						|
        return result
 | 
						|
 | 
						|
    @util.memoized_property
 | 
						|
    def inserted_primary_key_rows(self):
 | 
						|
        # if no specific "get primary key" strategy was set up
 | 
						|
        # during execution, return a "default" primary key based
 | 
						|
        # on what's in the compiled_parameters and nothing else.
 | 
						|
        return self._setup_ins_pk_from_empty()
 | 
						|
 | 
						|
    def _setup_ins_pk_from_lastrowid(self):
 | 
						|
        getter = self.compiled._inserted_primary_key_from_lastrowid_getter
 | 
						|
 | 
						|
        lastrowid = self.get_lastrowid()
 | 
						|
        return [getter(lastrowid, self.compiled_parameters[0])]
 | 
						|
 | 
						|
    def _setup_ins_pk_from_empty(self):
 | 
						|
        getter = self.compiled._inserted_primary_key_from_lastrowid_getter
 | 
						|
        return [getter(None, param) for param in self.compiled_parameters]
 | 
						|
 | 
						|
    def _setup_ins_pk_from_implicit_returning(self, result, rows):
 | 
						|
 | 
						|
        if not rows:
 | 
						|
            return []
 | 
						|
 | 
						|
        getter = self.compiled._inserted_primary_key_from_returning_getter
 | 
						|
        compiled_params = self.compiled_parameters
 | 
						|
 | 
						|
        return [
 | 
						|
            getter(row, param) for row, param in zip(rows, compiled_params)
 | 
						|
        ]
 | 
						|
 | 
						|
    def lastrow_has_defaults(self):
 | 
						|
        return (self.isinsert or self.isupdate) and bool(
 | 
						|
            self.compiled.postfetch
 | 
						|
        )
 | 
						|
 | 
						|
    def _set_input_sizes(self):
 | 
						|
        """Given a cursor and ClauseParameters, call the appropriate
 | 
						|
        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.
 | 
						|
 | 
						|
        """
 | 
						|
        if self.isddl or self.is_text:
 | 
						|
            return
 | 
						|
 | 
						|
        inputsizes = self.compiled._get_set_input_sizes_lookup(
 | 
						|
            include_types=self.include_set_input_sizes,
 | 
						|
            exclude_types=self.exclude_set_input_sizes,
 | 
						|
        )
 | 
						|
 | 
						|
        if inputsizes is None:
 | 
						|
            return
 | 
						|
 | 
						|
        if self.dialect._has_events:
 | 
						|
            inputsizes = dict(inputsizes)
 | 
						|
            self.dialect.dispatch.do_setinputsizes(
 | 
						|
                inputsizes, self.cursor, self.statement, self.parameters, self
 | 
						|
            )
 | 
						|
 | 
						|
        has_escaped_names = bool(self.compiled.escaped_bind_names)
 | 
						|
        if has_escaped_names:
 | 
						|
            escaped_bind_names = self.compiled.escaped_bind_names
 | 
						|
 | 
						|
        if self.dialect.positional:
 | 
						|
            items = [
 | 
						|
                (key, self.compiled.binds[key])
 | 
						|
                for key in self.compiled.positiontup
 | 
						|
            ]
 | 
						|
        else:
 | 
						|
            items = [
 | 
						|
                (key, bindparam)
 | 
						|
                for bindparam, key in self.compiled.bind_names.items()
 | 
						|
            ]
 | 
						|
 | 
						|
        generic_inputsizes = []
 | 
						|
        for key, bindparam in items:
 | 
						|
            if bindparam in self.compiled.literal_execute_params:
 | 
						|
                continue
 | 
						|
 | 
						|
            if key in self._expanded_parameters:
 | 
						|
                if bindparam.type._is_tuple_type:
 | 
						|
                    num = len(bindparam.type.types)
 | 
						|
                    dbtypes = inputsizes[bindparam]
 | 
						|
                    generic_inputsizes.extend(
 | 
						|
                        (
 | 
						|
                            (
 | 
						|
                                escaped_bind_names.get(paramname, paramname)
 | 
						|
                                if has_escaped_names
 | 
						|
                                else paramname
 | 
						|
                            ),
 | 
						|
                            dbtypes[idx % num],
 | 
						|
                            bindparam.type.types[idx % num],
 | 
						|
                        )
 | 
						|
                        for idx, paramname in enumerate(
 | 
						|
                            self._expanded_parameters[key]
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
                else:
 | 
						|
                    dbtype = inputsizes.get(bindparam, None)
 | 
						|
                    generic_inputsizes.extend(
 | 
						|
                        (
 | 
						|
                            (
 | 
						|
                                escaped_bind_names.get(paramname, paramname)
 | 
						|
                                if has_escaped_names
 | 
						|
                                else paramname
 | 
						|
                            ),
 | 
						|
                            dbtype,
 | 
						|
                            bindparam.type,
 | 
						|
                        )
 | 
						|
                        for paramname in self._expanded_parameters[key]
 | 
						|
                    )
 | 
						|
            else:
 | 
						|
                dbtype = inputsizes.get(bindparam, None)
 | 
						|
 | 
						|
                escaped_name = (
 | 
						|
                    escaped_bind_names.get(key, key)
 | 
						|
                    if has_escaped_names
 | 
						|
                    else key
 | 
						|
                )
 | 
						|
 | 
						|
                generic_inputsizes.append(
 | 
						|
                    (escaped_name, dbtype, bindparam.type)
 | 
						|
                )
 | 
						|
        try:
 | 
						|
            self.dialect.do_set_input_sizes(
 | 
						|
                self.cursor, generic_inputsizes, self
 | 
						|
            )
 | 
						|
        except BaseException as e:
 | 
						|
            self.root_connection._handle_dbapi_exception(
 | 
						|
                e, None, None, None, self
 | 
						|
            )
 | 
						|
 | 
						|
    def _exec_default(self, column, default, type_):
 | 
						|
        if default.is_sequence:
 | 
						|
            return self.fire_sequence(default, type_)
 | 
						|
        elif default.is_callable:
 | 
						|
            self.current_column = column
 | 
						|
            return default.arg(self)
 | 
						|
        elif default.is_clause_element:
 | 
						|
            return self._exec_default_clause_element(column, default, type_)
 | 
						|
        else:
 | 
						|
            return default.arg
 | 
						|
 | 
						|
    def _exec_default_clause_element(self, column, default, type_):
 | 
						|
        # execute a default that's a complete clause element.  Here, we have
 | 
						|
        # to re-implement a miniature version of the compile->parameters->
 | 
						|
        # cursor.execute() sequence, since we don't want to modify the state
 | 
						|
        # of the connection  / result in progress or create new connection/
 | 
						|
        # result objects etc.
 | 
						|
        # .. versionchanged:: 1.4
 | 
						|
 | 
						|
        if not default._arg_is_typed:
 | 
						|
            default_arg = expression.type_coerce(default.arg, type_)
 | 
						|
        else:
 | 
						|
            default_arg = default.arg
 | 
						|
        compiled = expression.select(default_arg).compile(dialect=self.dialect)
 | 
						|
        compiled_params = compiled.construct_params()
 | 
						|
        processors = compiled._bind_processors
 | 
						|
        if compiled.positional:
 | 
						|
            positiontup = compiled.positiontup
 | 
						|
            parameters = self.dialect.execute_sequence_format(
 | 
						|
                [
 | 
						|
                    processors[key](compiled_params[key])
 | 
						|
                    if key in processors
 | 
						|
                    else compiled_params[key]
 | 
						|
                    for key in positiontup
 | 
						|
                ]
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            parameters = dict(
 | 
						|
                (
 | 
						|
                    key,
 | 
						|
                    processors[key](compiled_params[key])
 | 
						|
                    if key in processors
 | 
						|
                    else compiled_params[key],
 | 
						|
                )
 | 
						|
                for key in compiled_params
 | 
						|
            )
 | 
						|
        return self._execute_scalar(
 | 
						|
            util.text_type(compiled), type_, parameters=parameters
 | 
						|
        )
 | 
						|
 | 
						|
    current_parameters = None
 | 
						|
    """A dictionary of parameters applied to the current row.
 | 
						|
 | 
						|
    This attribute is only available in the context of a user-defined default
 | 
						|
    generation function, e.g. as described at :ref:`context_default_functions`.
 | 
						|
    It consists of a dictionary which includes entries for each column/value
 | 
						|
    pair that is to be part of the INSERT or UPDATE statement. The keys of the
 | 
						|
    dictionary will be the key value of each :class:`_schema.Column`,
 | 
						|
    which is usually
 | 
						|
    synonymous with the name.
 | 
						|
 | 
						|
    Note that the :attr:`.DefaultExecutionContext.current_parameters` attribute
 | 
						|
    does not accommodate for the "multi-values" feature of the
 | 
						|
    :meth:`_expression.Insert.values` method.  The
 | 
						|
    :meth:`.DefaultExecutionContext.get_current_parameters` method should be
 | 
						|
    preferred.
 | 
						|
 | 
						|
    .. seealso::
 | 
						|
 | 
						|
        :meth:`.DefaultExecutionContext.get_current_parameters`
 | 
						|
 | 
						|
        :ref:`context_default_functions`
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    def get_current_parameters(self, isolate_multiinsert_groups=True):
 | 
						|
        """Return a dictionary of parameters applied to the current row.
 | 
						|
 | 
						|
        This method can only be used in the context of a user-defined default
 | 
						|
        generation function, e.g. as described at
 | 
						|
        :ref:`context_default_functions`. When invoked, a dictionary is
 | 
						|
        returned which includes entries for each column/value pair that is part
 | 
						|
        of the INSERT or UPDATE statement. The keys of the dictionary will be
 | 
						|
        the key value of each :class:`_schema.Column`,
 | 
						|
        which is usually synonymous
 | 
						|
        with the name.
 | 
						|
 | 
						|
        :param isolate_multiinsert_groups=True: indicates that multi-valued
 | 
						|
         INSERT constructs created using :meth:`_expression.Insert.values`
 | 
						|
         should be
 | 
						|
         handled by returning only the subset of parameters that are local
 | 
						|
         to the current column default invocation.   When ``False``, the
 | 
						|
         raw parameters of the statement are returned including the
 | 
						|
         naming convention used in the case of multi-valued INSERT.
 | 
						|
 | 
						|
        .. versionadded:: 1.2  added
 | 
						|
           :meth:`.DefaultExecutionContext.get_current_parameters`
 | 
						|
           which provides more functionality over the existing
 | 
						|
           :attr:`.DefaultExecutionContext.current_parameters`
 | 
						|
           attribute.
 | 
						|
 | 
						|
        .. seealso::
 | 
						|
 | 
						|
            :attr:`.DefaultExecutionContext.current_parameters`
 | 
						|
 | 
						|
            :ref:`context_default_functions`
 | 
						|
 | 
						|
        """
 | 
						|
        try:
 | 
						|
            parameters = self.current_parameters
 | 
						|
            column = self.current_column
 | 
						|
        except AttributeError:
 | 
						|
            raise exc.InvalidRequestError(
 | 
						|
                "get_current_parameters() can only be invoked in the "
 | 
						|
                "context of a Python side column default function"
 | 
						|
            )
 | 
						|
 | 
						|
        compile_state = self.compiled.compile_state
 | 
						|
        if (
 | 
						|
            isolate_multiinsert_groups
 | 
						|
            and self.isinsert
 | 
						|
            and compile_state._has_multi_parameters
 | 
						|
        ):
 | 
						|
            if column._is_multiparam_column:
 | 
						|
                index = column.index + 1
 | 
						|
                d = {column.original.key: parameters[column.key]}
 | 
						|
            else:
 | 
						|
                d = {column.key: parameters[column.key]}
 | 
						|
                index = 0
 | 
						|
            keys = compile_state._dict_parameters.keys()
 | 
						|
            d.update(
 | 
						|
                (key, parameters["%s_m%d" % (key, index)]) for key in keys
 | 
						|
            )
 | 
						|
            return d
 | 
						|
        else:
 | 
						|
            return parameters
 | 
						|
 | 
						|
    def get_insert_default(self, column):
 | 
						|
        if column.default is None:
 | 
						|
            return None
 | 
						|
        else:
 | 
						|
            return self._exec_default(column, column.default, column.type)
 | 
						|
 | 
						|
    def get_update_default(self, column):
 | 
						|
        if column.onupdate is None:
 | 
						|
            return None
 | 
						|
        else:
 | 
						|
            return self._exec_default(column, column.onupdate, column.type)
 | 
						|
 | 
						|
    def _process_executemany_defaults(self):
 | 
						|
        key_getter = self.compiled._within_exec_param_key_getter
 | 
						|
 | 
						|
        scalar_defaults = {}
 | 
						|
 | 
						|
        insert_prefetch = self.compiled.insert_prefetch
 | 
						|
        update_prefetch = self.compiled.update_prefetch
 | 
						|
 | 
						|
        # pre-determine scalar Python-side defaults
 | 
						|
        # to avoid many calls of get_insert_default()/
 | 
						|
        # get_update_default()
 | 
						|
        for c in insert_prefetch:
 | 
						|
            if c.default and not c.default.is_sequence and c.default.is_scalar:
 | 
						|
                scalar_defaults[c] = c.default.arg
 | 
						|
 | 
						|
        for c in update_prefetch:
 | 
						|
            if c.onupdate and c.onupdate.is_scalar:
 | 
						|
                scalar_defaults[c] = c.onupdate.arg
 | 
						|
 | 
						|
        for param in self.compiled_parameters:
 | 
						|
            self.current_parameters = param
 | 
						|
            for c in insert_prefetch:
 | 
						|
                if c in scalar_defaults:
 | 
						|
                    val = scalar_defaults[c]
 | 
						|
                else:
 | 
						|
                    val = self.get_insert_default(c)
 | 
						|
                if val is not None:
 | 
						|
                    param[key_getter(c)] = val
 | 
						|
            for c in update_prefetch:
 | 
						|
                if c in scalar_defaults:
 | 
						|
                    val = scalar_defaults[c]
 | 
						|
                else:
 | 
						|
                    val = self.get_update_default(c)
 | 
						|
                if val is not None:
 | 
						|
                    param[key_getter(c)] = val
 | 
						|
 | 
						|
        del self.current_parameters
 | 
						|
 | 
						|
    def _process_executesingle_defaults(self):
 | 
						|
        key_getter = self.compiled._within_exec_param_key_getter
 | 
						|
        self.current_parameters = (
 | 
						|
            compiled_parameters
 | 
						|
        ) = self.compiled_parameters[0]
 | 
						|
 | 
						|
        for c in self.compiled.insert_prefetch:
 | 
						|
            if c.default and not c.default.is_sequence and c.default.is_scalar:
 | 
						|
                val = c.default.arg
 | 
						|
            else:
 | 
						|
                val = self.get_insert_default(c)
 | 
						|
 | 
						|
            if val is not None:
 | 
						|
                compiled_parameters[key_getter(c)] = val
 | 
						|
 | 
						|
        for c in self.compiled.update_prefetch:
 | 
						|
            val = self.get_update_default(c)
 | 
						|
 | 
						|
            if val is not None:
 | 
						|
                compiled_parameters[key_getter(c)] = val
 | 
						|
        del self.current_parameters
 | 
						|
 | 
						|
 | 
						|
DefaultDialect.execution_ctx_cls = DefaultExecutionContext
 |