1# engine/interfaces.py 
    2# Copyright (C) 2005-2021 the SQLAlchemy authors and contributors 
    3# <see AUTHORS file> 
    4# 
    5# This module is part of SQLAlchemy and is released under 
    6# the MIT License: http://www.opensource.org/licenses/mit-license.php 
    7 
    8"""Define core interfaces used by the engine system.""" 
    9 
    10from .. import util 
    11from ..sql.compiler import Compiled  # noqa 
    12from ..sql.compiler import TypeCompiler  # noqa 
    13 
    14 
    15class Dialect(object): 
    16    """Define the behavior of a specific database and DB-API combination. 
    17 
    18    Any aspect of metadata definition, SQL query generation, 
    19    execution, result-set handling, or anything else which varies 
    20    between databases is defined under the general category of the 
    21    Dialect.  The Dialect acts as a factory for other 
    22    database-specific object implementations including 
    23    ExecutionContext, Compiled, DefaultGenerator, and TypeEngine. 
    24 
    25    .. note:: Third party dialects should not subclass :class:`.Dialect` 
    26       directly.  Instead, subclass :class:`.default.DefaultDialect` or 
    27       descendant class. 
    28 
    29    All dialects include the following attributes.   There are many other 
    30    attributes that may be supported as well: 
    31 
    32    ``name`` 
    33      identifying name for the dialect from a DBAPI-neutral point of view 
    34      (i.e. 'sqlite') 
    35 
    36    ``driver`` 
    37      identifying name for the dialect's DBAPI 
    38 
    39    ``positional`` 
    40      True if the paramstyle for this Dialect is positional. 
    41 
    42    ``paramstyle`` 
    43      the paramstyle to be used (some DB-APIs support multiple 
    44      paramstyles). 
    45 
    46    ``encoding`` 
    47      type of encoding to use for unicode, usually defaults to 
    48      'utf-8'. 
    49 
    50    ``statement_compiler`` 
    51      a :class:`.Compiled` class used to compile SQL statements 
    52 
    53    ``ddl_compiler`` 
    54      a :class:`.Compiled` class used to compile DDL statements 
    55 
    56    ``server_version_info`` 
    57      a tuple containing a version number for the DB backend in use. 
    58      This value is only available for supporting dialects, and is 
    59      typically populated during the initial connection to the database. 
    60 
    61    ``default_schema_name`` 
    62     the name of the default schema.  This value is only available for 
    63     supporting dialects, and is typically populated during the 
    64     initial connection to the database. 
    65 
    66    ``execution_ctx_cls`` 
    67      a :class:`.ExecutionContext` class used to handle statement execution 
    68 
    69    ``execute_sequence_format`` 
    70      either the 'tuple' or 'list' type, depending on what cursor.execute() 
    71      accepts for the second argument (they vary). 
    72 
    73    ``preparer`` 
    74      a :class:`~sqlalchemy.sql.compiler.IdentifierPreparer` class used to 
    75      quote identifiers. 
    76 
    77    ``supports_alter`` 
    78      ``True`` if the database supports ``ALTER TABLE`` - used only for 
    79      generating foreign key constraints in certain circumstances 
    80 
    81    ``max_identifier_length`` 
    82      The maximum length of identifier names. 
    83 
    84    ``supports_sane_rowcount`` 
    85      Indicate whether the dialect properly implements rowcount for 
    86      ``UPDATE`` and ``DELETE`` statements. 
    87 
    88    ``supports_sane_multi_rowcount`` 
    89      Indicate whether the dialect properly implements rowcount for 
    90      ``UPDATE`` and ``DELETE`` statements when executed via 
    91      executemany. 
    92 
    93    ``preexecute_autoincrement_sequences`` 
    94      True if 'implicit' primary key functions must be executed separately 
    95      in order to get their value.   This is currently oriented towards 
    96      PostgreSQL. 
    97 
    98    ``implicit_returning`` 
    99      use RETURNING or equivalent during INSERT execution in order to load 
    100      newly generated primary keys and other column defaults in one execution, 
    101      which are then available via inserted_primary_key. 
    102      If an insert statement has returning() specified explicitly, 
    103      the "implicit" functionality is not used and inserted_primary_key 
    104      will not be available. 
    105 
    106    ``colspecs`` 
    107      A dictionary of TypeEngine classes from sqlalchemy.types mapped 
    108      to subclasses that are specific to the dialect class.  This 
    109      dictionary is class-level only and is not accessed from the 
    110      dialect instance itself. 
    111 
    112    ``supports_default_values`` 
    113      Indicates if the construct ``INSERT INTO tablename DEFAULT 
    114      VALUES`` is supported 
    115 
    116    ``supports_sequences`` 
    117      Indicates if the dialect supports CREATE SEQUENCE or similar. 
    118 
    119    ``sequences_optional`` 
    120      If True, indicates if the "optional" flag on the Sequence() construct 
    121      should signal to not generate a CREATE SEQUENCE. Applies only to 
    122      dialects that support sequences. Currently used only to allow PostgreSQL 
    123      SERIAL to be used on a column that specifies Sequence() for usage on 
    124      other backends. 
    125 
    126    ``supports_native_enum`` 
    127      Indicates if the dialect supports a native ENUM construct. 
    128      This will prevent types.Enum from generating a CHECK 
    129      constraint when that type is used. 
    130 
    131    ``supports_native_boolean`` 
    132      Indicates if the dialect supports a native boolean construct. 
    133      This will prevent types.Boolean from generating a CHECK 
    134      constraint when that type is used. 
    135 
    136    ``dbapi_exception_translation_map`` 
    137       A dictionary of names that will contain as values the names of 
    138       pep-249 exceptions ("IntegrityError", "OperationalError", etc) 
    139       keyed to alternate class names, to support the case where a 
    140       DBAPI has exception classes that aren't named as they are 
    141       referred to (e.g. IntegrityError = MyException).   In the vast 
    142       majority of cases this dictionary is empty. 
    143 
    144       .. versionadded:: 1.0.5 
    145 
    146    """ 
    147 
    148    _has_events = False 
    149 
    150    def create_connect_args(self, url): 
    151        """Build DB-API compatible connection arguments. 
    152 
    153        Given a :class:`.URL` object, returns a tuple 
    154        consisting of a ``(*args, **kwargs)`` suitable to send directly 
    155        to the dbapi's connect function.   The arguments are sent to the 
    156        :meth:`.Dialect.connect` method which then runs the DBAPI-level 
    157        ``connect()`` function. 
    158 
    159        The method typically makes use of the 
    160        :meth:`.URL.translate_connect_args` 
    161        method in order to generate a dictionary of options. 
    162 
    163        The default implementation is:: 
    164 
    165            def create_connect_args(self, url): 
    166                opts = url.translate_connect_args() 
    167                opts.update(url.query) 
    168                return [[], opts] 
    169 
    170        :param url: a :class:`.URL` object 
    171 
    172        :return: a tuple of ``(*args, **kwargs)`` which will be passed to the 
    173         :meth:`.Dialect.connect` method. 
    174 
    175        .. seealso:: 
    176 
    177            :meth:`.URL.translate_connect_args` 
    178 
    179        """ 
    180 
    181        raise NotImplementedError() 
    182 
    183    @classmethod 
    184    def type_descriptor(cls, typeobj): 
    185        """Transform a generic type to a dialect-specific type. 
    186 
    187        Dialect classes will usually use the 
    188        :func:`_types.adapt_type` function in the types module to 
    189        accomplish this. 
    190 
    191        The returned result is cached *per dialect class* so can 
    192        contain no dialect-instance state. 
    193 
    194        """ 
    195 
    196        raise NotImplementedError() 
    197 
    198    def initialize(self, connection): 
    199        """Called during strategized creation of the dialect with a 
    200        connection. 
    201 
    202        Allows dialects to configure options based on server version info or 
    203        other properties. 
    204 
    205        The connection passed here is a SQLAlchemy Connection object, 
    206        with full capabilities. 
    207 
    208        The initialize() method of the base dialect should be called via 
    209        super(). 
    210 
    211        """ 
    212 
    213        pass 
    214 
    215    def reflecttable( 
    216        self, connection, table, include_columns, exclude_columns, resolve_fks 
    217    ): 
    218        """Load table description from the database. 
    219 
    220        Given a :class:`_engine.Connection` and a 
    221        :class:`~sqlalchemy.schema.Table` object, reflect its columns and 
    222        properties from the database. 
    223 
    224        The implementation of this method is provided by 
    225        :meth:`.DefaultDialect.reflecttable`, which makes use of 
    226        :class:`_reflection.Inspector` to retrieve column information. 
    227 
    228        Dialects should **not** seek to implement this method, and should 
    229        instead implement individual schema inspection operations such as 
    230        :meth:`.Dialect.get_columns`, :meth:`.Dialect.get_pk_constraint`, 
    231        etc. 
    232 
    233        """ 
    234 
    235        raise NotImplementedError() 
    236 
    237    def get_columns(self, connection, table_name, schema=None, **kw): 
    238        """Return information about columns in `table_name`. 
    239 
    240        Given a :class:`_engine.Connection`, a string 
    241        `table_name`, and an optional string `schema`, return column 
    242        information as a list of dictionaries with these keys: 
    243 
    244        * ``name`` - 
    245          the column's name 
    246 
    247        * ``type`` - 
    248          [sqlalchemy.types#TypeEngine] 
    249 
    250        * ``nullable`` - 
    251          boolean 
    252 
    253        * ``default`` - 
    254          the column's default value 
    255 
    256        * ``autoincrement`` - 
    257          boolean 
    258 
    259        * ``sequence`` - 
    260          a dictionary of the form 
    261          {'name' : str, 'start' :int, 'increment': int, 'minvalue': int, 
    262          'maxvalue': int, 'nominvalue': bool, 'nomaxvalue': bool, 
    263          'cycle': bool, 'cache': int, 'order': bool} 
    264 
    265        Additional column attributes may be present. 
    266 
    267        """ 
    268 
    269        raise NotImplementedError() 
    270 
    271    @util.deprecated( 
    272        "0.8", 
    273        "The :meth:`.Dialect.get_primary_keys` method is deprecated and " 
    274        "will be removed in a future release.   Please refer to the " 
    275        ":meth:`.Dialect.get_pk_constraint` method. ", 
    276    ) 
    277    def get_primary_keys(self, connection, table_name, schema=None, **kw): 
    278        """Return information about primary keys in `table_name`.""" 
    279 
    280        raise NotImplementedError() 
    281 
    282    def get_pk_constraint(self, connection, table_name, schema=None, **kw): 
    283        """Return information about the primary key constraint on 
    284        table_name`. 
    285 
    286        Given a :class:`_engine.Connection`, a string 
    287        `table_name`, and an optional string `schema`, return primary 
    288        key information as a dictionary with these keys: 
    289 
    290        * ``constrained_columns`` - 
    291          a list of column names that make up the primary key 
    292 
    293        * ``name`` - 
    294          optional name of the primary key constraint. 
    295 
    296        """ 
    297        raise NotImplementedError() 
    298 
    299    def get_foreign_keys(self, connection, table_name, schema=None, **kw): 
    300        """Return information about foreign_keys in `table_name`. 
    301 
    302        Given a :class:`_engine.Connection`, a string 
    303        `table_name`, and an optional string `schema`, return foreign 
    304        key information as a list of dicts with these keys: 
    305 
    306        * ``name`` - 
    307          the constraint's name 
    308 
    309        * ``constrained_columns`` - 
    310          a list of column names that make up the foreign key 
    311 
    312        * ``referred_schema`` - 
    313          the name of the referred schema 
    314 
    315        * ``referred_table`` - 
    316          the name of the referred table 
    317 
    318        * ``referred_columns`` - 
    319          a list of column names in the referred table that correspond to 
    320          constrained_columns 
    321        """ 
    322 
    323        raise NotImplementedError() 
    324 
    325    def get_table_names(self, connection, schema=None, **kw): 
    326        """Return a list of table names for `schema`.""" 
    327 
    328        raise NotImplementedError() 
    329 
    330    def get_temp_table_names(self, connection, schema=None, **kw): 
    331        """Return a list of temporary table names on the given connection, 
    332        if supported by the underlying backend. 
    333 
    334        """ 
    335 
    336        raise NotImplementedError() 
    337 
    338    def get_view_names(self, connection, schema=None, **kw): 
    339        """Return a list of all view names available in the database. 
    340 
    341        :param schema: 
    342          Optional, retrieve names from a non-default schema. 
    343        """ 
    344 
    345        raise NotImplementedError() 
    346 
    347    def get_temp_view_names(self, connection, schema=None, **kw): 
    348        """Return a list of temporary view names on the given connection, 
    349        if supported by the underlying backend. 
    350 
    351        """ 
    352 
    353        raise NotImplementedError() 
    354 
    355    def get_view_definition(self, connection, view_name, schema=None, **kw): 
    356        """Return view definition. 
    357 
    358        Given a :class:`_engine.Connection`, a string 
    359        `view_name`, and an optional string `schema`, return the view 
    360        definition. 
    361        """ 
    362 
    363        raise NotImplementedError() 
    364 
    365    def get_indexes(self, connection, table_name, schema=None, **kw): 
    366        """Return information about indexes in `table_name`. 
    367 
    368        Given a :class:`_engine.Connection`, a string 
    369        `table_name` and an optional string `schema`, return index 
    370        information as a list of dictionaries with these keys: 
    371 
    372        * ``name`` - 
    373          the index's name 
    374 
    375        * ``column_names`` - 
    376          list of column names in order 
    377 
    378        * ``unique`` - 
    379          boolean 
    380 
    381        """ 
    382 
    383        raise NotImplementedError() 
    384 
    385    def get_unique_constraints( 
    386        self, connection, table_name, schema=None, **kw 
    387    ): 
    388        r"""Return information about unique constraints in `table_name`. 
    389 
    390        Given a string `table_name` and an optional string `schema`, return 
    391        unique constraint information as a list of dicts with these keys: 
    392 
    393        * ``name`` - 
    394          the unique constraint's name 
    395 
    396        * ``column_names`` - 
    397          list of column names in order 
    398 
    399        * ``**kw`` - 
    400          other options passed to the dialect's get_unique_constraints() 
    401          method. 
    402 
    403        .. versionadded:: 0.9.0 
    404 
    405        """ 
    406 
    407        raise NotImplementedError() 
    408 
    409    def get_check_constraints(self, connection, table_name, schema=None, **kw): 
    410        r"""Return information about check constraints in `table_name`. 
    411 
    412        Given a string `table_name` and an optional string `schema`, return 
    413        check constraint information as a list of dicts with these keys: 
    414 
    415        * ``name`` - 
    416          the check constraint's name 
    417 
    418        * ``sqltext`` - 
    419          the check constraint's SQL expression 
    420 
    421        * ``**kw`` - 
    422          other options passed to the dialect's get_check_constraints() 
    423          method. 
    424 
    425        .. versionadded:: 1.1.0 
    426 
    427        """ 
    428 
    429        raise NotImplementedError() 
    430 
    431    def get_table_comment(self, connection, table_name, schema=None, **kw): 
    432        r"""Return the "comment" for the table identified by `table_name`. 
    433 
    434        Given a string `table_name` and an optional string `schema`, return 
    435        table comment information as a dictionary with this key: 
    436 
    437        text 
    438           text of the comment 
    439 
    440        Raises ``NotImplementedError`` for dialects that don't support 
    441        comments. 
    442 
    443        .. versionadded:: 1.2 
    444 
    445        """ 
    446 
    447        raise NotImplementedError() 
    448 
    449    def normalize_name(self, name): 
    450        """convert the given name to lowercase if it is detected as 
    451        case insensitive. 
    452 
    453        This method is only used if the dialect defines 
    454        requires_name_normalize=True. 
    455 
    456        """ 
    457        raise NotImplementedError() 
    458 
    459    def denormalize_name(self, name): 
    460        """convert the given name to a case insensitive identifier 
    461        for the backend if it is an all-lowercase name. 
    462 
    463        This method is only used if the dialect defines 
    464        requires_name_normalize=True. 
    465 
    466        """ 
    467        raise NotImplementedError() 
    468 
    469    def has_table(self, connection, table_name, schema=None): 
    470        """Check the existence of a particular table in the database. 
    471 
    472        Given a :class:`_engine.Connection` object and a string 
    473        `table_name`, return True if the given table (possibly within 
    474        the specified `schema`) exists in the database, False 
    475        otherwise. 
    476 
    477        """ 
    478 
    479        raise NotImplementedError() 
    480 
    481    def has_sequence(self, connection, sequence_name, schema=None): 
    482        """Check the existence of a particular sequence in the database. 
    483 
    484        Given a :class:`_engine.Connection` object and a string 
    485        `sequence_name`, return True if the given sequence exists in 
    486        the database, False otherwise. 
    487 
    488        """ 
    489 
    490        raise NotImplementedError() 
    491 
    492    def _get_server_version_info(self, connection): 
    493        """Retrieve the server version info from the given connection. 
    494 
    495        This is used by the default implementation to populate the 
    496        "server_version_info" attribute and is called exactly 
    497        once upon first connect. 
    498 
    499        """ 
    500 
    501        raise NotImplementedError() 
    502 
    503    def _get_default_schema_name(self, connection): 
    504        """Return the string name of the currently selected schema from 
    505        the given connection. 
    506 
    507        This is used by the default implementation to populate the 
    508        "default_schema_name" attribute and is called exactly 
    509        once upon first connect. 
    510 
    511        """ 
    512 
    513        raise NotImplementedError() 
    514 
    515    def do_begin(self, dbapi_connection): 
    516        """Provide an implementation of ``connection.begin()``, given a 
    517        DB-API connection. 
    518 
    519        The DBAPI has no dedicated "begin" method and it is expected 
    520        that transactions are implicit.  This hook is provided for those 
    521        DBAPIs that might need additional help in this area. 
    522 
    523        Note that :meth:`.Dialect.do_begin` is not called unless a 
    524        :class:`.Transaction` object is in use.  The 
    525        :meth:`.Dialect.do_autocommit` 
    526        hook is provided for DBAPIs that need some extra commands emitted 
    527        after a commit in order to enter the next transaction, when the 
    528        SQLAlchemy :class:`_engine.Connection` 
    529        is used in its default "autocommit" 
    530        mode. 
    531 
    532        :param dbapi_connection: a DBAPI connection, typically 
    533         proxied within a :class:`.ConnectionFairy`. 
    534 
    535        """ 
    536 
    537        raise NotImplementedError() 
    538 
    539    def do_rollback(self, dbapi_connection): 
    540        """Provide an implementation of ``connection.rollback()``, given 
    541        a DB-API connection. 
    542 
    543        :param dbapi_connection: a DBAPI connection, typically 
    544         proxied within a :class:`.ConnectionFairy`. 
    545 
    546        """ 
    547 
    548        raise NotImplementedError() 
    549 
    550    def do_commit(self, dbapi_connection): 
    551        """Provide an implementation of ``connection.commit()``, given a 
    552        DB-API connection. 
    553 
    554        :param dbapi_connection: a DBAPI connection, typically 
    555         proxied within a :class:`.ConnectionFairy`. 
    556 
    557        """ 
    558 
    559        raise NotImplementedError() 
    560 
    561    def do_close(self, dbapi_connection): 
    562        """Provide an implementation of ``connection.close()``, given a DBAPI 
    563        connection. 
    564 
    565        This hook is called by the :class:`_pool.Pool` 
    566        when a connection has been 
    567        detached from the pool, or is being returned beyond the normal 
    568        capacity of the pool. 
    569 
    570        """ 
    571 
    572        raise NotImplementedError() 
    573 
    574    def create_xid(self): 
    575        """Create a two-phase transaction ID. 
    576 
    577        This id will be passed to do_begin_twophase(), 
    578        do_rollback_twophase(), do_commit_twophase().  Its format is 
    579        unspecified. 
    580        """ 
    581 
    582        raise NotImplementedError() 
    583 
    584    def do_savepoint(self, connection, name): 
    585        """Create a savepoint with the given name. 
    586 
    587        :param connection: a :class:`_engine.Connection`. 
    588        :param name: savepoint name. 
    589 
    590        """ 
    591 
    592        raise NotImplementedError() 
    593 
    594    def do_rollback_to_savepoint(self, connection, name): 
    595        """Rollback a connection to the named savepoint. 
    596 
    597        :param connection: a :class:`_engine.Connection`. 
    598        :param name: savepoint name. 
    599 
    600        """ 
    601 
    602        raise NotImplementedError() 
    603 
    604    def do_release_savepoint(self, connection, name): 
    605        """Release the named savepoint on a connection. 
    606 
    607        :param connection: a :class:`_engine.Connection`. 
    608        :param name: savepoint name. 
    609        """ 
    610 
    611        raise NotImplementedError() 
    612 
    613    def do_begin_twophase(self, connection, xid): 
    614        """Begin a two phase transaction on the given connection. 
    615 
    616        :param connection: a :class:`_engine.Connection`. 
    617        :param xid: xid 
    618 
    619        """ 
    620 
    621        raise NotImplementedError() 
    622 
    623    def do_prepare_twophase(self, connection, xid): 
    624        """Prepare a two phase transaction on the given connection. 
    625 
    626        :param connection: a :class:`_engine.Connection`. 
    627        :param xid: xid 
    628 
    629        """ 
    630 
    631        raise NotImplementedError() 
    632 
    633    def do_rollback_twophase( 
    634        self, connection, xid, is_prepared=True, recover=False 
    635    ): 
    636        """Rollback a two phase transaction on the given connection. 
    637 
    638        :param connection: a :class:`_engine.Connection`. 
    639        :param xid: xid 
    640        :param is_prepared: whether or not 
    641         :meth:`.TwoPhaseTransaction.prepare` was called. 
    642        :param recover: if the recover flag was passed. 
    643 
    644        """ 
    645 
    646        raise NotImplementedError() 
    647 
    648    def do_commit_twophase( 
    649        self, connection, xid, is_prepared=True, recover=False 
    650    ): 
    651        """Commit a two phase transaction on the given connection. 
    652 
    653 
    654        :param connection: a :class:`_engine.Connection`. 
    655        :param xid: xid 
    656        :param is_prepared: whether or not 
    657         :meth:`.TwoPhaseTransaction.prepare` was called. 
    658        :param recover: if the recover flag was passed. 
    659 
    660        """ 
    661 
    662        raise NotImplementedError() 
    663 
    664    def do_recover_twophase(self, connection): 
    665        """Recover list of uncommitted prepared two phase transaction 
    666        identifiers on the given connection. 
    667 
    668        :param connection: a :class:`_engine.Connection`. 
    669 
    670        """ 
    671 
    672        raise NotImplementedError() 
    673 
    674    def do_executemany(self, cursor, statement, parameters, context=None): 
    675        """Provide an implementation of ``cursor.executemany(statement, 
    676        parameters)``. 
    677 
    678        """ 
    679 
    680        raise NotImplementedError() 
    681 
    682    def do_execute(self, cursor, statement, parameters, context=None): 
    683        """Provide an implementation of ``cursor.execute(statement, 
    684        parameters)``. 
    685 
    686        """ 
    687 
    688        raise NotImplementedError() 
    689 
    690    def do_execute_no_params( 
    691        self, cursor, statement, parameters, context=None 
    692    ): 
    693        """Provide an implementation of ``cursor.execute(statement)``. 
    694 
    695        The parameter collection should not be sent. 
    696 
    697        """ 
    698 
    699        raise NotImplementedError() 
    700 
    701    def is_disconnect(self, e, connection, cursor): 
    702        """Return True if the given DB-API error indicates an invalid 
    703        connection. 
    704 
    705        """ 
    706 
    707        raise NotImplementedError() 
    708 
    709    def connect(self, *cargs, **cparams): 
    710        r"""Establish a connection using this dialect's DBAPI. 
    711 
    712        The default implementation of this method is:: 
    713 
    714            def connect(self, *cargs, **cparams): 
    715                return self.dbapi.connect(*cargs, **cparams) 
    716 
    717        The ``*cargs, **cparams`` parameters are generated directly 
    718        from this dialect's :meth:`.Dialect.create_connect_args` method. 
    719 
    720        This method may be used for dialects that need to perform programmatic 
    721        per-connection steps when a new connection is procured from the 
    722        DBAPI. 
    723 
    724 
    725        :param \*cargs: positional parameters returned from the 
    726         :meth:`.Dialect.create_connect_args` method 
    727 
    728        :param \*\*cparams: keyword parameters returned from the 
    729         :meth:`.Dialect.create_connect_args` method. 
    730 
    731        :return: a DBAPI connection, typically from the :pep:`249` module 
    732         level ``.connect()`` function. 
    733 
    734        .. seealso:: 
    735 
    736            :meth:`.Dialect.create_connect_args` 
    737 
    738            :meth:`.Dialect.on_connect` 
    739 
    740        """ 
    741 
    742    def on_connect(self): 
    743        """Return a callable which sets up a newly created DBAPI connection. 
    744 
    745        The callable should accept a single argument "conn" which is the 
    746        DBAPI connection itself.  The inner callable has no 
    747        return value. 
    748 
    749        E.g.:: 
    750 
    751            class MyDialect(default.DefaultDialect): 
    752                # ... 
    753 
    754                def on_connect(self): 
    755                    def do_on_connect(connection): 
    756                        connection.execute("SET SPECIAL FLAGS etc") 
    757 
    758                    return do_on_connect 
    759 
    760        This is used to set dialect-wide per-connection options such as 
    761        isolation modes, Unicode modes, etc. 
    762 
    763        The "do_on_connect" callable is invoked by using the 
    764        :meth:`_events.PoolEvents.first_connect` and 
    765        :meth:`_events.PoolEvents.connect` event 
    766        hooks, then unwrapping the DBAPI connection and passing it into the 
    767        callable.  The reason it is invoked for both events is so that any 
    768        dialect-level initialization that occurs upon first connection, which 
    769        also makes use of the :meth:`_events.PoolEvents.first_connect` method, 
    770        will 
    771        proceed after this hook has been called. This currently means the 
    772        hook is in fact called twice for the very first  connection in which a 
    773        dialect creates; and once per connection afterwards. 
    774 
    775        If None is returned, no event listener is generated. 
    776 
    777        :return: a callable that accepts a single DBAPI connection as an 
    778         argument, or None. 
    779 
    780        .. seealso:: 
    781 
    782            :meth:`.Dialect.connect` - allows the DBAPI ``connect()`` sequence 
    783            itself to be controlled. 
    784 
    785        """ 
    786        return None 
    787 
    788    def reset_isolation_level(self, dbapi_conn): 
    789        """Given a DBAPI connection, revert its isolation to the default. 
    790 
    791        Note that this is a dialect-level method which is used as part 
    792        of the implementation of the :class:`_engine.Connection` and 
    793        :class:`_engine.Engine` 
    794        isolation level facilities; these APIs should be preferred for 
    795        most typical use cases. 
    796 
    797        .. seealso:: 
    798 
    799            :meth:`_engine.Connection.get_isolation_level` 
    800            - view current level 
    801 
    802            :attr:`_engine.Connection.default_isolation_level` 
    803            - view default level 
    804 
    805            :paramref:`.Connection.execution_options.isolation_level` - 
    806            set per :class:`_engine.Connection` isolation level 
    807 
    808            :paramref:`_sa.create_engine.isolation_level` - 
    809            set per :class:`_engine.Engine` isolation level 
    810 
    811        """ 
    812 
    813        raise NotImplementedError() 
    814 
    815    def set_isolation_level(self, dbapi_conn, level): 
    816        """Given a DBAPI connection, set its isolation level. 
    817 
    818        Note that this is a dialect-level method which is used as part 
    819        of the implementation of the :class:`_engine.Connection` and 
    820        :class:`_engine.Engine` 
    821        isolation level facilities; these APIs should be preferred for 
    822        most typical use cases. 
    823 
    824        .. seealso:: 
    825 
    826            :meth:`_engine.Connection.get_isolation_level` 
    827            - view current level 
    828 
    829            :attr:`_engine.Connection.default_isolation_level` 
    830            - view default level 
    831 
    832            :paramref:`.Connection.execution_options.isolation_level` - 
    833            set per :class:`_engine.Connection` isolation level 
    834 
    835            :paramref:`_sa.create_engine.isolation_level` - 
    836            set per :class:`_engine.Engine` isolation level 
    837 
    838        """ 
    839 
    840        raise NotImplementedError() 
    841 
    842    def get_isolation_level(self, dbapi_conn): 
    843        """Given a DBAPI connection, return its isolation level. 
    844 
    845        When working with a :class:`_engine.Connection` object, 
    846        the corresponding 
    847        DBAPI connection may be procured using the 
    848        :attr:`_engine.Connection.connection` accessor. 
    849 
    850        Note that this is a dialect-level method which is used as part 
    851        of the implementation of the :class:`_engine.Connection` and 
    852        :class:`_engine.Engine` isolation level facilities; 
    853        these APIs should be preferred for most typical use cases. 
    854 
    855 
    856        .. seealso:: 
    857 
    858            :meth:`_engine.Connection.get_isolation_level` 
    859            - view current level 
    860 
    861            :attr:`_engine.Connection.default_isolation_level` 
    862            - view default level 
    863 
    864            :paramref:`.Connection.execution_options.isolation_level` - 
    865            set per :class:`_engine.Connection` isolation level 
    866 
    867            :paramref:`_sa.create_engine.isolation_level` - 
    868            set per :class:`_engine.Engine` isolation level 
    869 
    870 
    871        """ 
    872 
    873        raise NotImplementedError() 
    874 
    875    def get_default_isolation_level(self, dbapi_conn): 
    876        """Given a DBAPI connection, return its isolation level, or 
    877        a default isolation level if one cannot be retrieved. 
    878 
    879        This method may only raise NotImplementedError and 
    880        **must not raise any other exception**, as it is used implicitly upon 
    881        first connect. 
    882 
    883        The method **must return a value** for a dialect that supports 
    884        isolation level settings, as this level is what will be reverted 
    885        towards when a per-connection isolation level change is made. 
    886 
    887        The method defaults to using the :meth:`.Dialect.get_isolation_level` 
    888        method unless overridden by a dialect. 
    889 
    890        .. versionadded:: 1.3.22 
    891 
    892        """ 
    893        raise NotImplementedError() 
    894 
    895    @classmethod 
    896    def get_dialect_cls(cls, url): 
    897        """Given a URL, return the :class:`.Dialect` that will be used. 
    898 
    899        This is a hook that allows an external plugin to provide functionality 
    900        around an existing dialect, by allowing the plugin to be loaded 
    901        from the url based on an entrypoint, and then the plugin returns 
    902        the actual dialect to be used. 
    903 
    904        By default this just returns the cls. 
    905 
    906        .. versionadded:: 1.0.3 
    907 
    908        """ 
    909        return cls 
    910 
    911    @classmethod 
    912    def load_provisioning(cls): 
    913        """Set up the provision.py module for this dialect. 
    914 
    915        For dialects that include a provision.py module that sets up 
    916        provisioning followers, this method should initiate that process. 
    917 
    918        A typical implementation would be:: 
    919 
    920            @classmethod 
    921            def load_provisioning(cls): 
    922                __import__("mydialect.provision") 
    923 
    924        The default method assumes a module named ``provision.py`` inside 
    925        the owning package of the current dialect, based on the ``__module__`` 
    926        attribute:: 
    927 
    928            @classmethod 
    929            def load_provisioning(cls): 
    930                package = ".".join(cls.__module__.split(".")[0:-1]) 
    931                try: 
    932                    __import__(package + ".provision") 
    933                except ImportError: 
    934                    pass 
    935 
    936        .. versionadded:: 1.3.14 
    937 
    938        """ 
    939 
    940    @classmethod 
    941    def engine_created(cls, engine): 
    942        """A convenience hook called before returning the final 
    943        :class:`_engine.Engine`. 
    944 
    945        If the dialect returned a different class from the 
    946        :meth:`.get_dialect_cls` 
    947        method, then the hook is called on both classes, first on 
    948        the dialect class returned by the :meth:`.get_dialect_cls` method and 
    949        then on the class on which the method was called. 
    950 
    951        The hook should be used by dialects and/or wrappers to apply special 
    952        events to the engine or its components.   In particular, it allows 
    953        a dialect-wrapping class to apply dialect-level events. 
    954 
    955        .. versionadded:: 1.0.3 
    956 
    957        """ 
    958        pass 
    959 
    960 
    961class CreateEnginePlugin(object): 
    962    """A set of hooks intended to augment the construction of an 
    963    :class:`_engine.Engine` object based on entrypoint names in a URL. 
    964 
    965    The purpose of :class:`.CreateEnginePlugin` is to allow third-party 
    966    systems to apply engine, pool and dialect level event listeners without 
    967    the need for the target application to be modified; instead, the plugin 
    968    names can be added to the database URL.  Target applications for 
    969    :class:`.CreateEnginePlugin` include: 
    970 
    971    * connection and SQL performance tools, e.g. which use events to track 
    972      number of checkouts and/or time spent with statements 
    973 
    974    * connectivity plugins such as proxies 
    975 
    976    Plugins are registered using entry points in a similar way as that 
    977    of dialects:: 
    978 
    979        entry_points={ 
    980            'sqlalchemy.plugins': [ 
    981                'myplugin = myapp.plugins:MyPlugin' 
    982            ] 
    983 
    984    A plugin that uses the above names would be invoked from a database 
    985    URL as in:: 
    986 
    987        from sqlalchemy import create_engine 
    988 
    989        engine = create_engine( 
    990          "mysql+pymysql://scott:tiger@localhost/test?plugin=myplugin") 
    991 
    992    Alternatively, the :paramref:`.create_engine.plugins" argument may be 
    993    passed as a list to :func:`_sa.create_engine`:: 
    994 
    995        engine = create_engine( 
    996          "mysql+pymysql://scott:tiger@localhost/test", 
    997          plugins=["myplugin"]) 
    998 
    999    .. versionadded:: 1.2.3  plugin names can also be specified 
    1000       to :func:`_sa.create_engine` as a list 
    1001 
    1002    The ``plugin`` argument supports multiple instances, so that a URL 
    1003    may specify multiple plugins; they are loaded in the order stated 
    1004    in the URL:: 
    1005 
    1006        engine = create_engine( 
    1007          "mysql+pymysql://scott:tiger@localhost/" 
    1008          "test?plugin=plugin_one&plugin=plugin_twp&plugin=plugin_three") 
    1009 
    1010    A plugin can receive additional arguments from the URL string as 
    1011    well as from the keyword arguments passed to :func:`_sa.create_engine`. 
    1012    The :class:`.URL` object and the keyword dictionary are passed to the 
    1013    constructor so that these arguments can be extracted from the url's 
    1014    :attr:`.URL.query` collection as well as from the dictionary:: 
    1015 
    1016        class MyPlugin(CreateEnginePlugin): 
    1017            def __init__(self, url, kwargs): 
    1018                self.my_argument_one = url.query.pop('my_argument_one') 
    1019                self.my_argument_two = url.query.pop('my_argument_two') 
    1020                self.my_argument_three = kwargs.pop('my_argument_three', None) 
    1021 
    1022    Arguments like those illustrated above would be consumed from the 
    1023    following:: 
    1024 
    1025        from sqlalchemy import create_engine 
    1026 
    1027        engine = create_engine( 
    1028          "mysql+pymysql://scott:tiger@localhost/" 
    1029          "test?plugin=myplugin&my_argument_one=foo&my_argument_two=bar", 
    1030          my_argument_three='bat') 
    1031 
    1032    The URL and dictionary are used for subsequent setup of the engine 
    1033    as they are, so the plugin can modify their arguments in-place. 
    1034    Arguments that are only understood by the plugin should be popped 
    1035    or otherwise removed so that they aren't interpreted as erroneous 
    1036    arguments afterwards. 
    1037 
    1038    When the engine creation process completes and produces the 
    1039    :class:`_engine.Engine` object, it is again passed to the plugin via the 
    1040    :meth:`.CreateEnginePlugin.engine_created` hook.  In this hook, additional 
    1041    changes can be made to the engine, most typically involving setup of 
    1042    events (e.g. those defined in :ref:`core_event_toplevel`). 
    1043 
    1044    .. versionadded:: 1.1 
    1045 
    1046    """ 
    1047 
    1048    def __init__(self, url, kwargs): 
    1049        """Construct a new :class:`.CreateEnginePlugin`. 
    1050 
    1051        The plugin object is instantiated individually for each call 
    1052        to :func:`_sa.create_engine`.  A single :class:`_engine. 
    1053        Engine` will be 
    1054        passed to the :meth:`.CreateEnginePlugin.engine_created` method 
    1055        corresponding to this URL. 
    1056 
    1057        :param url: the :class:`.URL` object.  The plugin should inspect 
    1058         what it needs here as well as remove its custom arguments from the 
    1059         :attr:`.URL.query` collection.  The URL can be modified in-place 
    1060         in any other way as well. 
    1061        :param kwargs: The keyword arguments passed to :func:`.create_engine`. 
    1062         The plugin can read and modify this dictionary in-place, to affect 
    1063         the ultimate arguments used to create the engine.  It should 
    1064         remove its custom arguments from the dictionary as well. 
    1065 
    1066        """ 
    1067        self.url = url 
    1068 
    1069    def handle_dialect_kwargs(self, dialect_cls, dialect_args): 
    1070        """parse and modify dialect kwargs""" 
    1071 
    1072    def handle_pool_kwargs(self, pool_cls, pool_args): 
    1073        """parse and modify pool kwargs""" 
    1074 
    1075    def engine_created(self, engine): 
    1076        """Receive the :class:`_engine.Engine` 
    1077        object when it is fully constructed. 
    1078 
    1079        The plugin may make additional changes to the engine, such as 
    1080        registering engine or connection pool events. 
    1081 
    1082        """ 
    1083 
    1084 
    1085class ExecutionContext(object): 
    1086    """A messenger object for a Dialect that corresponds to a single 
    1087    execution. 
    1088 
    1089    ExecutionContext should have these data members: 
    1090 
    1091    connection 
    1092      Connection object which can be freely used by default value 
    1093      generators to execute SQL.  This Connection should reference the 
    1094      same underlying connection/transactional resources of 
    1095      root_connection. 
    1096 
    1097    root_connection 
    1098      Connection object which is the source of this ExecutionContext.  This 
    1099      Connection may have close_with_result=True set, in which case it can 
    1100      only be used once. 
    1101 
    1102    dialect 
    1103      dialect which created this ExecutionContext. 
    1104 
    1105    cursor 
    1106      DB-API cursor procured from the connection, 
    1107 
    1108    compiled 
    1109      if passed to constructor, sqlalchemy.engine.base.Compiled object 
    1110      being executed, 
    1111 
    1112    statement 
    1113      string version of the statement to be executed.  Is either 
    1114      passed to the constructor, or must be created from the 
    1115      sql.Compiled object by the time pre_exec() has completed. 
    1116 
    1117    parameters 
    1118      bind parameters passed to the execute() method.  For compiled 
    1119      statements, this is a dictionary or list of dictionaries.  For 
    1120      textual statements, it should be in a format suitable for the 
    1121      dialect's paramstyle (i.e. dict or list of dicts for non 
    1122      positional, list or list of lists/tuples for positional). 
    1123 
    1124    isinsert 
    1125      True if the statement is an INSERT. 
    1126 
    1127    isupdate 
    1128      True if the statement is an UPDATE. 
    1129 
    1130    should_autocommit 
    1131      True if the statement is a "committable" statement. 
    1132 
    1133    prefetch_cols 
    1134      a list of Column objects for which a client-side default 
    1135      was fired off.  Applies to inserts and updates. 
    1136 
    1137    postfetch_cols 
    1138      a list of Column objects for which a server-side default or 
    1139      inline SQL expression value was fired off.  Applies to inserts 
    1140      and updates. 
    1141    """ 
    1142 
    1143    exception = None 
    1144    """A DBAPI-level exception that was caught when this ExecutionContext 
    1145    attempted to execute a statement. 
    1146 
    1147    This attribute is meaningful only within the 
    1148    :meth:`_events.ConnectionEvents.dbapi_error` event. 
    1149 
    1150    .. versionadded:: 0.9.7 
    1151 
    1152    .. seealso:: 
    1153 
    1154        :attr:`.ExecutionContext.is_disconnect` 
    1155 
    1156        :meth:`_events.ConnectionEvents.dbapi_error` 
    1157 
    1158    """ 
    1159 
    1160    is_disconnect = None 
    1161    """Boolean flag set to True or False when a DBAPI-level exception 
    1162    is caught when this ExecutionContext attempted to execute a statement. 
    1163 
    1164    This attribute is meaningful only within the 
    1165    :meth:`_events.ConnectionEvents.dbapi_error` event. 
    1166 
    1167    .. versionadded:: 0.9.7 
    1168 
    1169    .. seealso:: 
    1170 
    1171        :attr:`.ExecutionContext.exception` 
    1172 
    1173        :meth:`_events.ConnectionEvents.dbapi_error` 
    1174 
    1175    """ 
    1176 
    1177    def create_cursor(self): 
    1178        """Return a new cursor generated from this ExecutionContext's 
    1179        connection. 
    1180 
    1181        Some dialects may wish to change the behavior of 
    1182        connection.cursor(), such as postgresql which may return a PG 
    1183        "server side" cursor. 
    1184        """ 
    1185 
    1186        raise NotImplementedError() 
    1187 
    1188    def pre_exec(self): 
    1189        """Called before an execution of a compiled statement. 
    1190 
    1191        If a compiled statement was passed to this ExecutionContext, 
    1192        the `statement` and `parameters` datamembers must be 
    1193        initialized after this statement is complete. 
    1194        """ 
    1195 
    1196        raise NotImplementedError() 
    1197 
    1198    def post_exec(self): 
    1199        """Called after the execution of a compiled statement. 
    1200 
    1201        If a compiled statement was passed to this ExecutionContext, 
    1202        the `last_insert_ids`, `last_inserted_params`, etc. 
    1203        datamembers should be available after this method completes. 
    1204        """ 
    1205 
    1206        raise NotImplementedError() 
    1207 
    1208    def result(self): 
    1209        """Return a result object corresponding to this ExecutionContext. 
    1210 
    1211        Returns a ResultProxy. 
    1212 
    1213        """ 
    1214 
    1215        raise NotImplementedError() 
    1216 
    1217    def handle_dbapi_exception(self, e): 
    1218        """Receive a DBAPI exception which occurred upon execute, result 
    1219        fetch, etc. 
    1220 
    1221        """ 
    1222 
    1223        raise NotImplementedError() 
    1224 
    1225    def should_autocommit_text(self, statement): 
    1226        """Parse the given textual statement and return True if it refers to 
    1227        a "committable" statement 
    1228 
    1229        """ 
    1230 
    1231        raise NotImplementedError() 
    1232 
    1233    def lastrow_has_defaults(self): 
    1234        """Return True if the last INSERT or UPDATE row contained 
    1235        inlined or database-side defaults. 
    1236 
    1237        """ 
    1238 
    1239        raise NotImplementedError() 
    1240 
    1241    def get_rowcount(self): 
    1242        """Return the DBAPI ``cursor.rowcount`` value, or in some 
    1243        cases an interpreted value. 
    1244 
    1245        See :attr:`_engine.ResultProxy.rowcount` for details on this. 
    1246 
    1247        """ 
    1248 
    1249        raise NotImplementedError() 
    1250 
    1251 
    1252class Connectable(object): 
    1253    """Interface for an object which supports execution of SQL constructs. 
    1254 
    1255    The two implementations of :class:`.Connectable` are 
    1256    :class:`_engine.Connection` and :class:`_engine.Engine`. 
    1257 
    1258    Connectable must also implement the 'dialect' member which references a 
    1259    :class:`.Dialect` instance. 
    1260 
    1261    """ 
    1262 
    1263    def connect(self, **kwargs): 
    1264        """Return a :class:`_engine.Connection` object. 
    1265 
    1266        Depending on context, this may be ``self`` if this object 
    1267        is already an instance of :class:`_engine.Connection`, or a newly 
    1268        procured :class:`_engine.Connection` if this object is an instance 
    1269        of :class:`_engine.Engine`. 
    1270 
    1271        """ 
    1272 
    1273    engine = None 
    1274    """The :class:`_engine.Engine` instance referred to by this 
    1275    :class:`.Connectable`. 
    1276 
    1277    May be ``self`` if this is already an :class:`_engine.Engine`. 
    1278 
    1279    """ 
    1280 
    1281    @util.deprecated( 
    1282        "1.3", 
    1283        "The :meth:`_engine.Engine.contextual_connect` and " 
    1284        ":meth:`_engine.Connection.contextual_connect` methods are " 
    1285        "deprecated. This " 
    1286        "method is an artifact of the threadlocal engine strategy which is " 
    1287        "also to be deprecated.   For explicit connections from an " 
    1288        ":class:`_engine.Engine`, use the :meth:`_engine.Engine.connect` " 
    1289        "method.", 
    1290    ) 
    1291    def contextual_connect(self, *arg, **kw): 
    1292        """Return a :class:`_engine.Connection` 
    1293        object which may be part of an ongoing 
    1294        context. 
    1295 
    1296        Depending on context, this may be ``self`` if this object 
    1297        is already an instance of :class:`_engine.Connection`, or a newly 
    1298        procured :class:`_engine.Connection` if this object is an instance 
    1299        of :class:`_engine.Engine`. 
    1300 
    1301        """ 
    1302 
    1303        return self._contextual_connect(*arg, **kw) 
    1304 
    1305    def _contextual_connect(self): 
    1306        raise NotImplementedError() 
    1307 
    1308    @util.deprecated( 
    1309        "0.7", 
    1310        "The :meth:`.Connectable.create` method is deprecated and will be " 
    1311        "removed in a future release.  Please use the ``.create()`` method " 
    1312        "on specific schema objects to emit DDL sequences, including " 
    1313        ":meth:`_schema.Table.create`, :meth:`.Index.create`, and " 
    1314        ":meth:`_schema.MetaData.create_all`.", 
    1315    ) 
    1316    def create(self, entity, **kwargs): 
    1317        """Emit CREATE statements for the given schema entity.""" 
    1318 
    1319        raise NotImplementedError() 
    1320 
    1321    @util.deprecated( 
    1322        "0.7", 
    1323        "The :meth:`.Connectable.drop` method is deprecated and will be " 
    1324        "removed in a future release.  Please use the ``.drop()`` method " 
    1325        "on specific schema objects to emit DDL sequences, including " 
    1326        ":meth:`_schema.Table.drop`, :meth:`.Index.drop`, and " 
    1327        ":meth:`_schema.MetaData.drop_all`.", 
    1328    ) 
    1329    def drop(self, entity, **kwargs): 
    1330        """Emit DROP statements for the given schema entity.""" 
    1331 
    1332        raise NotImplementedError() 
    1333 
    1334    def execute(self, object_, *multiparams, **params): 
    1335        """Executes the given construct and returns a """ 
    1336        """:class:`_engine.ResultProxy`.""" 
    1337        raise NotImplementedError() 
    1338 
    1339    def scalar(self, object_, *multiparams, **params): 
    1340        """Executes and returns the first column of the first row. 
    1341 
    1342        The underlying cursor is closed after execution. 
    1343        """ 
    1344        raise NotImplementedError() 
    1345 
    1346    def _run_visitor(self, visitorcallable, element, **kwargs): 
    1347        raise NotImplementedError() 
    1348 
    1349    def _execute_clauseelement(self, elem, multiparams=None, params=None): 
    1350        raise NotImplementedError() 
    1351 
    1352 
    1353class ExceptionContext(object): 
    1354    """Encapsulate information about an error condition in progress. 
    1355 
    1356    This object exists solely to be passed to the 
    1357    :meth:`_events.ConnectionEvents.handle_error` event, 
    1358    supporting an interface that 
    1359    can be extended without backwards-incompatibility. 
    1360 
    1361    .. versionadded:: 0.9.7 
    1362 
    1363    """ 
    1364 
    1365    connection = None 
    1366    """The :class:`_engine.Connection` in use during the exception. 
    1367 
    1368    This member is present, except in the case of a failure when 
    1369    first connecting. 
    1370 
    1371    .. seealso:: 
    1372 
    1373        :attr:`.ExceptionContext.engine` 
    1374 
    1375 
    1376    """ 
    1377 
    1378    engine = None 
    1379    """The :class:`_engine.Engine` in use during the exception. 
    1380 
    1381    This member should always be present, even in the case of a failure 
    1382    when first connecting. 
    1383 
    1384    .. versionadded:: 1.0.0 
    1385 
    1386    """ 
    1387 
    1388    cursor = None 
    1389    """The DBAPI cursor object. 
    1390 
    1391    May be None. 
    1392 
    1393    """ 
    1394 
    1395    statement = None 
    1396    """String SQL statement that was emitted directly to the DBAPI. 
    1397 
    1398    May be None. 
    1399 
    1400    """ 
    1401 
    1402    parameters = None 
    1403    """Parameter collection that was emitted directly to the DBAPI. 
    1404 
    1405    May be None. 
    1406 
    1407    """ 
    1408 
    1409    original_exception = None 
    1410    """The exception object which was caught. 
    1411 
    1412    This member is always present. 
    1413 
    1414    """ 
    1415 
    1416    sqlalchemy_exception = None 
    1417    """The :class:`sqlalchemy.exc.StatementError` which wraps the original, 
    1418    and will be raised if exception handling is not circumvented by the event. 
    1419 
    1420    May be None, as not all exception types are wrapped by SQLAlchemy. 
    1421    For DBAPI-level exceptions that subclass the dbapi's Error class, this 
    1422    field will always be present. 
    1423 
    1424    """ 
    1425 
    1426    chained_exception = None 
    1427    """The exception that was returned by the previous handler in the 
    1428    exception chain, if any. 
    1429 
    1430    If present, this exception will be the one ultimately raised by 
    1431    SQLAlchemy unless a subsequent handler replaces it. 
    1432 
    1433    May be None. 
    1434 
    1435    """ 
    1436 
    1437    execution_context = None 
    1438    """The :class:`.ExecutionContext` corresponding to the execution 
    1439    operation in progress. 
    1440 
    1441    This is present for statement execution operations, but not for 
    1442    operations such as transaction begin/end.  It also is not present when 
    1443    the exception was raised before the :class:`.ExecutionContext` 
    1444    could be constructed. 
    1445 
    1446    Note that the :attr:`.ExceptionContext.statement` and 
    1447    :attr:`.ExceptionContext.parameters` members may represent a 
    1448    different value than that of the :class:`.ExecutionContext`, 
    1449    potentially in the case where a 
    1450    :meth:`_events.ConnectionEvents.before_cursor_execute` event or similar 
    1451    modified the statement/parameters to be sent. 
    1452 
    1453    May be None. 
    1454 
    1455    """ 
    1456 
    1457    is_disconnect = None 
    1458    """Represent whether the exception as occurred represents a "disconnect" 
    1459    condition. 
    1460 
    1461    This flag will always be True or False within the scope of the 
    1462    :meth:`_events.ConnectionEvents.handle_error` handler. 
    1463 
    1464    SQLAlchemy will defer to this flag in order to determine whether or not 
    1465    the connection should be invalidated subsequently.    That is, by 
    1466    assigning to this flag, a "disconnect" event which then results in 
    1467    a connection and pool invalidation can be invoked or prevented by 
    1468    changing this flag. 
    1469 
    1470 
    1471    .. note:: The pool "pre_ping" handler enabled using the 
    1472        :paramref:`_sa.create_engine.pool_pre_ping` parameter does **not** 
    1473        consult this event before deciding if the "ping" returned false, 
    1474        as opposed to receiving an unhandled error.   For this use case, the 
    1475        :ref:`legacy recipe based on engine_connect() may be used 
    1476        <pool_disconnects_pessimistic_custom>`.  A future API allow more 
    1477        comprehensive customization of the "disconnect" detection mechanism 
    1478        across all functions. 
    1479 
    1480    """ 
    1481 
    1482    invalidate_pool_on_disconnect = True 
    1483    """Represent whether all connections in the pool should be invalidated 
    1484    when a "disconnect" condition is in effect. 
    1485 
    1486    Setting this flag to False within the scope of the 
    1487    :meth:`_events.ConnectionEvents.handle_error` 
    1488    event will have the effect such 
    1489    that the full collection of connections in the pool will not be 
    1490    invalidated during a disconnect; only the current connection that is the 
    1491    subject of the error will actually be invalidated. 
    1492 
    1493    The purpose of this flag is for custom disconnect-handling schemes where 
    1494    the invalidation of other connections in the pool is to be performed 
    1495    based on other conditions, or even on a per-connection basis. 
    1496 
    1497    .. versionadded:: 1.0.3 
    1498 
    1499    """