Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/interfaces.py: 63%
173 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:35 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:35 +0000
1# engine/interfaces.py
2# Copyright (C) 2005-2023 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: https://www.opensource.org/licenses/mit-license.php
8"""Define core interfaces used by the engine system."""
10from .. import util
11from ..sql.compiler import Compiled # noqa
12from ..sql.compiler import TypeCompiler # noqa
13from ..util.concurrency import await_only
16class Dialect(object):
17 """Define the behavior of a specific database and DB-API combination.
19 Any aspect of metadata definition, SQL query generation,
20 execution, result-set handling, or anything else which varies
21 between databases is defined under the general category of the
22 Dialect. The Dialect acts as a factory for other
23 database-specific object implementations including
24 ExecutionContext, Compiled, DefaultGenerator, and TypeEngine.
26 .. note:: Third party dialects should not subclass :class:`.Dialect`
27 directly. Instead, subclass :class:`.default.DefaultDialect` or
28 descendant class.
30 All dialects include the following attributes. There are many other
31 attributes that may be supported as well:
33 ``name``
34 identifying name for the dialect from a DBAPI-neutral point of view
35 (i.e. 'sqlite')
37 ``driver``
38 identifying name for the dialect's DBAPI
40 ``positional``
41 True if the paramstyle for this Dialect is positional.
43 ``paramstyle``
44 the paramstyle to be used (some DB-APIs support multiple
45 paramstyles).
47 ``encoding``
48 type of encoding to use for unicode, usually defaults to
49 'utf-8'.
51 ``statement_compiler``
52 a :class:`.Compiled` class used to compile SQL statements
54 ``ddl_compiler``
55 a :class:`.Compiled` class used to compile DDL statements
57 ``server_version_info``
58 a tuple containing a version number for the DB backend in use.
59 This value is only available for supporting dialects, and is
60 typically populated during the initial connection to the database.
62 ``default_schema_name``
63 the name of the default schema. This value is only available for
64 supporting dialects, and is typically populated during the
65 initial connection to the database.
67 ``execution_ctx_cls``
68 a :class:`.ExecutionContext` class used to handle statement execution
70 ``execute_sequence_format``
71 either the 'tuple' or 'list' type, depending on what cursor.execute()
72 accepts for the second argument (they vary).
74 ``preparer``
75 a :class:`~sqlalchemy.sql.compiler.IdentifierPreparer` class used to
76 quote identifiers.
78 ``supports_alter``
79 ``True`` if the database supports ``ALTER TABLE`` - used only for
80 generating foreign key constraints in certain circumstances
82 ``max_identifier_length``
83 The maximum length of identifier names.
85 ``supports_sane_rowcount``
86 Indicate whether the dialect properly implements rowcount for
87 ``UPDATE`` and ``DELETE`` statements.
89 ``supports_sane_multi_rowcount``
90 Indicate whether the dialect properly implements rowcount for
91 ``UPDATE`` and ``DELETE`` statements when executed via
92 executemany.
94 ``preexecute_autoincrement_sequences``
95 True if 'implicit' primary key functions must be executed separately
96 in order to get their value. This is currently oriented towards
97 PostgreSQL.
99 ``implicit_returning``
100 use RETURNING or equivalent during INSERT execution in order to load
101 newly generated primary keys and other column defaults in one execution,
102 which are then available via inserted_primary_key.
103 If an insert statement has returning() specified explicitly,
104 the "implicit" functionality is not used and inserted_primary_key
105 will not be available.
107 ``colspecs``
108 A dictionary of TypeEngine classes from sqlalchemy.types mapped
109 to subclasses that are specific to the dialect class. This
110 dictionary is class-level only and is not accessed from the
111 dialect instance itself.
113 ``supports_default_values``
114 Indicates if the construct ``INSERT INTO tablename DEFAULT
115 VALUES`` is supported
117 ``supports_sequences``
118 Indicates if the dialect supports CREATE SEQUENCE or similar.
120 ``sequences_optional``
121 If True, indicates if the "optional" flag on the Sequence() construct
122 should signal to not generate a CREATE SEQUENCE. Applies only to
123 dialects that support sequences. Currently used only to allow PostgreSQL
124 SERIAL to be used on a column that specifies Sequence() for usage on
125 other backends.
127 ``supports_native_enum``
128 Indicates if the dialect supports a native ENUM construct.
129 This will prevent types.Enum from generating a CHECK
130 constraint when that type is used.
132 ``supports_native_boolean``
133 Indicates if the dialect supports a native boolean construct.
134 This will prevent types.Boolean from generating a CHECK
135 constraint when that type is used.
137 ``dbapi_exception_translation_map``
138 A dictionary of names that will contain as values the names of
139 pep-249 exceptions ("IntegrityError", "OperationalError", etc)
140 keyed to alternate class names, to support the case where a
141 DBAPI has exception classes that aren't named as they are
142 referred to (e.g. IntegrityError = MyException). In the vast
143 majority of cases this dictionary is empty.
145 .. versionadded:: 1.0.5
147 """
149 _has_events = False
151 supports_statement_cache = True
152 """indicates if this dialect supports caching.
154 All dialects that are compatible with statement caching should set this
155 flag to True directly on each dialect class and subclass that supports
156 it. SQLAlchemy tests that this flag is locally present on each dialect
157 subclass before it will use statement caching. This is to provide
158 safety for legacy or new dialects that are not yet fully tested to be
159 compliant with SQL statement caching.
161 .. versionadded:: 1.4.5
163 .. seealso::
165 :ref:`engine_thirdparty_caching`
167 """
169 def create_connect_args(self, url):
170 """Build DB-API compatible connection arguments.
172 Given a :class:`.URL` object, returns a tuple
173 consisting of a ``(*args, **kwargs)`` suitable to send directly
174 to the dbapi's connect function. The arguments are sent to the
175 :meth:`.Dialect.connect` method which then runs the DBAPI-level
176 ``connect()`` function.
178 The method typically makes use of the
179 :meth:`.URL.translate_connect_args`
180 method in order to generate a dictionary of options.
182 The default implementation is::
184 def create_connect_args(self, url):
185 opts = url.translate_connect_args()
186 opts.update(url.query)
187 return [[], opts]
189 :param url: a :class:`.URL` object
191 :return: a tuple of ``(*args, **kwargs)`` which will be passed to the
192 :meth:`.Dialect.connect` method.
194 .. seealso::
196 :meth:`.URL.translate_connect_args`
198 """
200 raise NotImplementedError()
202 @classmethod
203 def type_descriptor(cls, typeobj):
204 """Transform a generic type to a dialect-specific type.
206 Dialect classes will usually use the
207 :func:`_types.adapt_type` function in the types module to
208 accomplish this.
210 The returned result is cached *per dialect class* so can
211 contain no dialect-instance state.
213 """
215 raise NotImplementedError()
217 def initialize(self, connection):
218 """Called during strategized creation of the dialect with a
219 connection.
221 Allows dialects to configure options based on server version info or
222 other properties.
224 The connection passed here is a SQLAlchemy Connection object,
225 with full capabilities.
227 The initialize() method of the base dialect should be called via
228 super().
230 .. note:: as of SQLAlchemy 1.4, this method is called **before**
231 any :meth:`_engine.Dialect.on_connect` hooks are called.
233 """
235 pass
237 def get_columns(self, connection, table_name, schema=None, **kw):
238 """Return information about columns in `table_name`.
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:
244 name
245 the column's name
247 type
248 [sqlalchemy.types#TypeEngine]
250 nullable
251 boolean
253 default
254 the column's default value
256 autoincrement
257 boolean
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}
265 Additional column attributes may be present.
266 """
268 raise NotImplementedError()
270 def get_pk_constraint(self, connection, table_name, schema=None, **kw):
271 """Return information about the primary key constraint on
272 table_name`.
274 Given a :class:`_engine.Connection`, a string
275 `table_name`, and an optional string `schema`, return primary
276 key information as a dictionary with these keys:
278 constrained_columns
279 a list of column names that make up the primary key
281 name
282 optional name of the primary key constraint.
284 """
285 raise NotImplementedError()
287 def get_foreign_keys(self, connection, table_name, schema=None, **kw):
288 """Return information about foreign_keys in `table_name`.
290 Given a :class:`_engine.Connection`, a string
291 `table_name`, and an optional string `schema`, return foreign
292 key information as a list of dicts with these keys:
294 name
295 the constraint's name
297 constrained_columns
298 a list of column names that make up the foreign key
300 referred_schema
301 the name of the referred schema
303 referred_table
304 the name of the referred table
306 referred_columns
307 a list of column names in the referred table that correspond to
308 constrained_columns
309 """
311 raise NotImplementedError()
313 def get_table_names(self, connection, schema=None, **kw):
314 """Return a list of table names for `schema`."""
316 raise NotImplementedError()
318 def get_temp_table_names(self, connection, schema=None, **kw):
319 """Return a list of temporary table names on the given connection,
320 if supported by the underlying backend.
322 """
324 raise NotImplementedError()
326 def get_view_names(self, connection, schema=None, **kw):
327 """Return a list of all view names available in the database.
329 :param schema: schema name to query, if not the default schema.
330 """
332 raise NotImplementedError()
334 def get_sequence_names(self, connection, schema=None, **kw):
335 """Return a list of all sequence names available in the database.
337 :param schema: schema name to query, if not the default schema.
339 .. versionadded:: 1.4
340 """
342 raise NotImplementedError()
344 def get_temp_view_names(self, connection, schema=None, **kw):
345 """Return a list of temporary view names on the given connection,
346 if supported by the underlying backend.
348 """
350 raise NotImplementedError()
352 def get_view_definition(self, connection, view_name, schema=None, **kw):
353 """Return view definition.
355 Given a :class:`_engine.Connection`, a string
356 `view_name`, and an optional string `schema`, return the view
357 definition.
358 """
360 raise NotImplementedError()
362 def get_indexes(self, connection, table_name, schema=None, **kw):
363 """Return information about indexes in `table_name`.
365 Given a :class:`_engine.Connection`, a string
366 `table_name` and an optional string `schema`, return index
367 information as a list of dictionaries with these keys:
369 name
370 the index's name
372 column_names
373 list of column names in order
375 unique
376 boolean
377 """
379 raise NotImplementedError()
381 def get_unique_constraints(
382 self, connection, table_name, schema=None, **kw
383 ):
384 r"""Return information about unique constraints in `table_name`.
386 Given a string `table_name` and an optional string `schema`, return
387 unique constraint information as a list of dicts with these keys:
389 name
390 the unique constraint's name
392 column_names
393 list of column names in order
395 \**kw
396 other options passed to the dialect's get_unique_constraints()
397 method.
399 .. versionadded:: 0.9.0
401 """
403 raise NotImplementedError()
405 def get_check_constraints(self, connection, table_name, schema=None, **kw):
406 r"""Return information about check constraints in `table_name`.
408 Given a string `table_name` and an optional string `schema`, return
409 check constraint information as a list of dicts with these keys:
411 * ``name`` -
412 the check constraint's name
414 * ``sqltext`` -
415 the check constraint's SQL expression
417 * ``**kw`` -
418 other options passed to the dialect's get_check_constraints()
419 method.
421 .. versionadded:: 1.1.0
423 """
425 raise NotImplementedError()
427 def get_table_comment(self, connection, table_name, schema=None, **kw):
428 r"""Return the "comment" for the table identified by `table_name`.
430 Given a string `table_name` and an optional string `schema`, return
431 table comment information as a dictionary with this key:
433 text
434 text of the comment
436 Raises ``NotImplementedError`` for dialects that don't support
437 comments.
439 .. versionadded:: 1.2
441 """
443 raise NotImplementedError()
445 def normalize_name(self, name):
446 """convert the given name to lowercase if it is detected as
447 case insensitive.
449 This method is only used if the dialect defines
450 requires_name_normalize=True.
452 """
453 raise NotImplementedError()
455 def denormalize_name(self, name):
456 """convert the given name to a case insensitive identifier
457 for the backend if it is an all-lowercase name.
459 This method is only used if the dialect defines
460 requires_name_normalize=True.
462 """
463 raise NotImplementedError()
465 def has_table(self, connection, table_name, schema=None, **kw):
466 """For internal dialect use, check the existence of a particular table
467 in the database.
469 Given a :class:`_engine.Connection` object, a string table_name and
470 optional schema name, return True if the given table exists in the
471 database, False otherwise.
473 This method serves as the underlying implementation of the
474 public facing :meth:`.Inspector.has_table` method, and is also used
475 internally to implement the "checkfirst" behavior for methods like
476 :meth:`_schema.Table.create` and :meth:`_schema.MetaData.create_all`.
478 .. note:: This method is used internally by SQLAlchemy, and is
479 published so that third-party dialects may provide an
480 implementation. It is **not** the public API for checking for table
481 presence. Please use the :meth:`.Inspector.has_table` method.
482 Alternatively, for legacy cross-compatibility, the
483 :meth:`_engine.Engine.has_table` method may be used.
485 """
487 raise NotImplementedError()
489 def has_index(self, connection, table_name, index_name, schema=None):
490 """Check the existence of a particular index name in the database.
492 Given a :class:`_engine.Connection` object, a string
493 `table_name` and string index name, return True if an index of the
494 given name on the given table exists, false otherwise.
496 The :class:`.DefaultDialect` implements this in terms of the
497 :meth:`.Dialect.has_table` and :meth:`.Dialect.get_indexes` methods,
498 however dialects can implement a more performant version.
501 .. versionadded:: 1.4
503 """
505 raise NotImplementedError()
507 def has_sequence(self, connection, sequence_name, schema=None, **kw):
508 """Check the existence of a particular sequence in the database.
510 Given a :class:`_engine.Connection` object and a string
511 `sequence_name`, return True if the given sequence exists in
512 the database, False otherwise.
513 """
515 raise NotImplementedError()
517 def _get_server_version_info(self, connection):
518 """Retrieve the server version info from the given connection.
520 This is used by the default implementation to populate the
521 "server_version_info" attribute and is called exactly
522 once upon first connect.
524 """
526 raise NotImplementedError()
528 def _get_default_schema_name(self, connection):
529 """Return the string name of the currently selected schema from
530 the given connection.
532 This is used by the default implementation to populate the
533 "default_schema_name" attribute and is called exactly
534 once upon first connect.
536 """
538 raise NotImplementedError()
540 def do_begin(self, dbapi_connection):
541 """Provide an implementation of ``connection.begin()``, given a
542 DB-API connection.
544 The DBAPI has no dedicated "begin" method and it is expected
545 that transactions are implicit. This hook is provided for those
546 DBAPIs that might need additional help in this area.
548 Note that :meth:`.Dialect.do_begin` is not called unless a
549 :class:`.Transaction` object is in use. The
550 :meth:`.Dialect.do_autocommit`
551 hook is provided for DBAPIs that need some extra commands emitted
552 after a commit in order to enter the next transaction, when the
553 SQLAlchemy :class:`_engine.Connection`
554 is used in its default "autocommit"
555 mode.
557 :param dbapi_connection: a DBAPI connection, typically
558 proxied within a :class:`.ConnectionFairy`.
560 """
562 raise NotImplementedError()
564 def do_rollback(self, dbapi_connection):
565 """Provide an implementation of ``connection.rollback()``, given
566 a DB-API connection.
568 :param dbapi_connection: a DBAPI connection, typically
569 proxied within a :class:`.ConnectionFairy`.
571 """
573 raise NotImplementedError()
575 def do_commit(self, dbapi_connection):
576 """Provide an implementation of ``connection.commit()``, given a
577 DB-API connection.
579 :param dbapi_connection: a DBAPI connection, typically
580 proxied within a :class:`.ConnectionFairy`.
582 """
584 raise NotImplementedError()
586 def do_terminate(self, dbapi_connection):
587 """Provide an implementation of ``connection.close()`` that tries as
588 much as possible to not block, given a DBAPI
589 connection.
591 In the vast majority of cases this just calls .close(), however
592 for some asyncio dialects may call upon different API features.
594 This hook is called by the :class:`_pool.Pool`
595 when a connection is being recycled or has been invalidated.
597 .. versionadded:: 1.4.41
599 """
601 raise NotImplementedError()
603 def do_close(self, dbapi_connection):
604 """Provide an implementation of ``connection.close()``, given a DBAPI
605 connection.
607 This hook is called by the :class:`_pool.Pool`
608 when a connection has been
609 detached from the pool, or is being returned beyond the normal
610 capacity of the pool.
612 """
614 raise NotImplementedError()
616 def do_set_input_sizes(self, cursor, list_of_tuples, context):
617 """invoke the cursor.setinputsizes() method with appropriate arguments
619 This hook is called if the dialect.use_inputsizes flag is set to True.
620 Parameter data is passed in a list of tuples (paramname, dbtype,
621 sqltype), where ``paramname`` is the key of the parameter in the
622 statement, ``dbtype`` is the DBAPI datatype and ``sqltype`` is the
623 SQLAlchemy type. The order of tuples is in the correct parameter order.
625 .. versionadded:: 1.4
628 """
629 raise NotImplementedError()
631 def create_xid(self):
632 """Create a two-phase transaction ID.
634 This id will be passed to do_begin_twophase(),
635 do_rollback_twophase(), do_commit_twophase(). Its format is
636 unspecified.
637 """
639 raise NotImplementedError()
641 def do_savepoint(self, connection, name):
642 """Create a savepoint with the given name.
644 :param connection: a :class:`_engine.Connection`.
645 :param name: savepoint name.
647 """
649 raise NotImplementedError()
651 def do_rollback_to_savepoint(self, connection, name):
652 """Rollback a connection to the named savepoint.
654 :param connection: a :class:`_engine.Connection`.
655 :param name: savepoint name.
657 """
659 raise NotImplementedError()
661 def do_release_savepoint(self, connection, name):
662 """Release the named savepoint on a connection.
664 :param connection: a :class:`_engine.Connection`.
665 :param name: savepoint name.
666 """
668 raise NotImplementedError()
670 def do_begin_twophase(self, connection, xid):
671 """Begin a two phase transaction on the given connection.
673 :param connection: a :class:`_engine.Connection`.
674 :param xid: xid
676 """
678 raise NotImplementedError()
680 def do_prepare_twophase(self, connection, xid):
681 """Prepare a two phase transaction on the given connection.
683 :param connection: a :class:`_engine.Connection`.
684 :param xid: xid
686 """
688 raise NotImplementedError()
690 def do_rollback_twophase(
691 self, connection, xid, is_prepared=True, recover=False
692 ):
693 """Rollback a two phase transaction on the given connection.
695 :param connection: a :class:`_engine.Connection`.
696 :param xid: xid
697 :param is_prepared: whether or not
698 :meth:`.TwoPhaseTransaction.prepare` was called.
699 :param recover: if the recover flag was passed.
701 """
703 raise NotImplementedError()
705 def do_commit_twophase(
706 self, connection, xid, is_prepared=True, recover=False
707 ):
708 """Commit a two phase transaction on the given connection.
711 :param connection: a :class:`_engine.Connection`.
712 :param xid: xid
713 :param is_prepared: whether or not
714 :meth:`.TwoPhaseTransaction.prepare` was called.
715 :param recover: if the recover flag was passed.
717 """
719 raise NotImplementedError()
721 def do_recover_twophase(self, connection):
722 """Recover list of uncommitted prepared two phase transaction
723 identifiers on the given connection.
725 :param connection: a :class:`_engine.Connection`.
727 """
729 raise NotImplementedError()
731 def do_executemany(self, cursor, statement, parameters, context=None):
732 """Provide an implementation of ``cursor.executemany(statement,
733 parameters)``."""
735 raise NotImplementedError()
737 def do_execute(self, cursor, statement, parameters, context=None):
738 """Provide an implementation of ``cursor.execute(statement,
739 parameters)``."""
741 raise NotImplementedError()
743 def do_execute_no_params(
744 self, cursor, statement, parameters, context=None
745 ):
746 """Provide an implementation of ``cursor.execute(statement)``.
748 The parameter collection should not be sent.
750 """
752 raise NotImplementedError()
754 def is_disconnect(self, e, connection, cursor):
755 """Return True if the given DB-API error indicates an invalid
756 connection"""
758 raise NotImplementedError()
760 def connect(self, *cargs, **cparams):
761 r"""Establish a connection using this dialect's DBAPI.
763 The default implementation of this method is::
765 def connect(self, *cargs, **cparams):
766 return self.dbapi.connect(*cargs, **cparams)
768 The ``*cargs, **cparams`` parameters are generated directly
769 from this dialect's :meth:`.Dialect.create_connect_args` method.
771 This method may be used for dialects that need to perform programmatic
772 per-connection steps when a new connection is procured from the
773 DBAPI.
776 :param \*cargs: positional parameters returned from the
777 :meth:`.Dialect.create_connect_args` method
779 :param \*\*cparams: keyword parameters returned from the
780 :meth:`.Dialect.create_connect_args` method.
782 :return: a DBAPI connection, typically from the :pep:`249` module
783 level ``.connect()`` function.
785 .. seealso::
787 :meth:`.Dialect.create_connect_args`
789 :meth:`.Dialect.on_connect`
791 """
793 def on_connect_url(self, url):
794 """return a callable which sets up a newly created DBAPI connection.
796 This method is a new hook that supersedes the
797 :meth:`_engine.Dialect.on_connect` method when implemented by a
798 dialect. When not implemented by a dialect, it invokes the
799 :meth:`_engine.Dialect.on_connect` method directly to maintain
800 compatibility with existing dialects. There is no deprecation
801 for :meth:`_engine.Dialect.on_connect` expected.
803 The callable should accept a single argument "conn" which is the
804 DBAPI connection itself. The inner callable has no
805 return value.
807 E.g.::
809 class MyDialect(default.DefaultDialect):
810 # ...
812 def on_connect_url(self, url):
813 def do_on_connect(connection):
814 connection.execute("SET SPECIAL FLAGS etc")
816 return do_on_connect
818 This is used to set dialect-wide per-connection options such as
819 isolation modes, Unicode modes, etc.
821 This method differs from :meth:`_engine.Dialect.on_connect` in that
822 it is passed the :class:`_engine.URL` object that's relevant to the
823 connect args. Normally the only way to get this is from the
824 :meth:`_engine.Dialect.on_connect` hook is to look on the
825 :class:`_engine.Engine` itself, however this URL object may have been
826 replaced by plugins.
828 .. note::
830 The default implementation of
831 :meth:`_engine.Dialect.on_connect_url` is to invoke the
832 :meth:`_engine.Dialect.on_connect` method. Therefore if a dialect
833 implements this method, the :meth:`_engine.Dialect.on_connect`
834 method **will not be called** unless the overriding dialect calls
835 it directly from here.
837 .. versionadded:: 1.4.3 added :meth:`_engine.Dialect.on_connect_url`
838 which normally calls into :meth:`_engine.Dialect.on_connect`.
840 :param url: a :class:`_engine.URL` object representing the
841 :class:`_engine.URL` that was passed to the
842 :meth:`_engine.Dialect.create_connect_args` method.
844 :return: a callable that accepts a single DBAPI connection as an
845 argument, or None.
847 .. seealso::
849 :meth:`_engine.Dialect.on_connect`
851 """
852 return self.on_connect()
854 def on_connect(self):
855 """return a callable which sets up a newly created DBAPI connection.
857 The callable should accept a single argument "conn" which is the
858 DBAPI connection itself. The inner callable has no
859 return value.
861 E.g.::
863 class MyDialect(default.DefaultDialect):
864 # ...
866 def on_connect(self):
867 def do_on_connect(connection):
868 connection.execute("SET SPECIAL FLAGS etc")
870 return do_on_connect
872 This is used to set dialect-wide per-connection options such as
873 isolation modes, Unicode modes, etc.
875 The "do_on_connect" callable is invoked by using the
876 :meth:`_events.PoolEvents.connect` event
877 hook, then unwrapping the DBAPI connection and passing it into the
878 callable.
880 .. versionchanged:: 1.4 the on_connect hook is no longer called twice
881 for the first connection of a dialect. The on_connect hook is still
882 called before the :meth:`_engine.Dialect.initialize` method however.
884 .. versionchanged:: 1.4.3 the on_connect hook is invoked from a new
885 method on_connect_url that passes the URL that was used to create
886 the connect args. Dialects can implement on_connect_url instead
887 of on_connect if they need the URL object that was used for the
888 connection in order to get additional context.
890 If None is returned, no event listener is generated.
892 :return: a callable that accepts a single DBAPI connection as an
893 argument, or None.
895 .. seealso::
897 :meth:`.Dialect.connect` - allows the DBAPI ``connect()`` sequence
898 itself to be controlled.
900 :meth:`.Dialect.on_connect_url` - supersedes
901 :meth:`.Dialect.on_connect` to also receive the
902 :class:`_engine.URL` object in context.
904 """
905 return None
907 def reset_isolation_level(self, dbapi_conn):
908 """Given a DBAPI connection, revert its isolation to the default.
910 Note that this is a dialect-level method which is used as part
911 of the implementation of the :class:`_engine.Connection` and
912 :class:`_engine.Engine`
913 isolation level facilities; these APIs should be preferred for
914 most typical use cases.
916 .. seealso::
918 :meth:`_engine.Connection.get_isolation_level`
919 - view current level
921 :attr:`_engine.Connection.default_isolation_level`
922 - view default level
924 :paramref:`.Connection.execution_options.isolation_level` -
925 set per :class:`_engine.Connection` isolation level
927 :paramref:`_sa.create_engine.isolation_level` -
928 set per :class:`_engine.Engine` isolation level
930 """
932 raise NotImplementedError()
934 def set_isolation_level(self, dbapi_conn, level):
935 """Given a DBAPI connection, set its isolation level.
937 Note that this is a dialect-level method which is used as part
938 of the implementation of the :class:`_engine.Connection` and
939 :class:`_engine.Engine`
940 isolation level facilities; these APIs should be preferred for
941 most typical use cases.
943 .. seealso::
945 :meth:`_engine.Connection.get_isolation_level`
946 - view current level
948 :attr:`_engine.Connection.default_isolation_level`
949 - view default level
951 :paramref:`.Connection.execution_options.isolation_level` -
952 set per :class:`_engine.Connection` isolation level
954 :paramref:`_sa.create_engine.isolation_level` -
955 set per :class:`_engine.Engine` isolation level
957 """
959 raise NotImplementedError()
961 def get_isolation_level(self, dbapi_conn):
962 """Given a DBAPI connection, return its isolation level.
964 When working with a :class:`_engine.Connection` object,
965 the corresponding
966 DBAPI connection may be procured using the
967 :attr:`_engine.Connection.connection` accessor.
969 Note that this is a dialect-level method which is used as part
970 of the implementation of the :class:`_engine.Connection` and
971 :class:`_engine.Engine` isolation level facilities;
972 these APIs should be preferred for most typical use cases.
975 .. seealso::
977 :meth:`_engine.Connection.get_isolation_level`
978 - view current level
980 :attr:`_engine.Connection.default_isolation_level`
981 - view default level
983 :paramref:`.Connection.execution_options.isolation_level` -
984 set per :class:`_engine.Connection` isolation level
986 :paramref:`_sa.create_engine.isolation_level` -
987 set per :class:`_engine.Engine` isolation level
990 """
992 raise NotImplementedError()
994 def get_default_isolation_level(self, dbapi_conn):
995 """Given a DBAPI connection, return its isolation level, or
996 a default isolation level if one cannot be retrieved.
998 This method may only raise NotImplementedError and
999 **must not raise any other exception**, as it is used implicitly upon
1000 first connect.
1002 The method **must return a value** for a dialect that supports
1003 isolation level settings, as this level is what will be reverted
1004 towards when a per-connection isolation level change is made.
1006 The method defaults to using the :meth:`.Dialect.get_isolation_level`
1007 method unless overridden by a dialect.
1009 .. versionadded:: 1.3.22
1011 """
1012 raise NotImplementedError()
1014 @classmethod
1015 def get_dialect_cls(cls, url):
1016 """Given a URL, return the :class:`.Dialect` that will be used.
1018 This is a hook that allows an external plugin to provide functionality
1019 around an existing dialect, by allowing the plugin to be loaded
1020 from the url based on an entrypoint, and then the plugin returns
1021 the actual dialect to be used.
1023 By default this just returns the cls.
1025 .. versionadded:: 1.0.3
1027 """
1028 return cls
1030 @classmethod
1031 def load_provisioning(cls):
1032 """set up the provision.py module for this dialect.
1034 For dialects that include a provision.py module that sets up
1035 provisioning followers, this method should initiate that process.
1037 A typical implementation would be::
1039 @classmethod
1040 def load_provisioning(cls):
1041 __import__("mydialect.provision")
1043 The default method assumes a module named ``provision.py`` inside
1044 the owning package of the current dialect, based on the ``__module__``
1045 attribute::
1047 @classmethod
1048 def load_provisioning(cls):
1049 package = ".".join(cls.__module__.split(".")[0:-1])
1050 try:
1051 __import__(package + ".provision")
1052 except ImportError:
1053 pass
1055 .. versionadded:: 1.3.14
1057 """
1059 @classmethod
1060 def engine_created(cls, engine):
1061 """A convenience hook called before returning the final
1062 :class:`_engine.Engine`.
1064 If the dialect returned a different class from the
1065 :meth:`.get_dialect_cls`
1066 method, then the hook is called on both classes, first on
1067 the dialect class returned by the :meth:`.get_dialect_cls` method and
1068 then on the class on which the method was called.
1070 The hook should be used by dialects and/or wrappers to apply special
1071 events to the engine or its components. In particular, it allows
1072 a dialect-wrapping class to apply dialect-level events.
1074 .. versionadded:: 1.0.3
1076 """
1078 def get_driver_connection(self, connection):
1079 """Returns the connection object as returned by the external driver
1080 package.
1082 For normal dialects that use a DBAPI compliant driver this call
1083 will just return the ``connection`` passed as argument.
1084 For dialects that instead adapt a non DBAPI compliant driver, like
1085 when adapting an asyncio driver, this call will return the
1086 connection-like object as returned by the driver.
1088 .. versionadded:: 1.4.24
1090 """
1091 raise NotImplementedError()
1094class CreateEnginePlugin(object):
1095 """A set of hooks intended to augment the construction of an
1096 :class:`_engine.Engine` object based on entrypoint names in a URL.
1098 The purpose of :class:`_engine.CreateEnginePlugin` is to allow third-party
1099 systems to apply engine, pool and dialect level event listeners without
1100 the need for the target application to be modified; instead, the plugin
1101 names can be added to the database URL. Target applications for
1102 :class:`_engine.CreateEnginePlugin` include:
1104 * connection and SQL performance tools, e.g. which use events to track
1105 number of checkouts and/or time spent with statements
1107 * connectivity plugins such as proxies
1109 A rudimentary :class:`_engine.CreateEnginePlugin` that attaches a logger
1110 to an :class:`_engine.Engine` object might look like::
1113 import logging
1115 from sqlalchemy.engine import CreateEnginePlugin
1116 from sqlalchemy import event
1118 class LogCursorEventsPlugin(CreateEnginePlugin):
1119 def __init__(self, url, kwargs):
1120 # consume the parameter "log_cursor_logging_name" from the
1121 # URL query
1122 logging_name = url.query.get("log_cursor_logging_name", "log_cursor")
1124 self.log = logging.getLogger(logging_name)
1126 def update_url(self, url):
1127 "update the URL to one that no longer includes our parameters"
1128 return url.difference_update_query(["log_cursor_logging_name"])
1130 def engine_created(self, engine):
1131 "attach an event listener after the new Engine is constructed"
1132 event.listen(engine, "before_cursor_execute", self._log_event)
1135 def _log_event(
1136 self,
1137 conn,
1138 cursor,
1139 statement,
1140 parameters,
1141 context,
1142 executemany):
1144 self.log.info("Plugin logged cursor event: %s", statement)
1148 Plugins are registered using entry points in a similar way as that
1149 of dialects::
1151 entry_points={
1152 'sqlalchemy.plugins': [
1153 'log_cursor_plugin = myapp.plugins:LogCursorEventsPlugin'
1154 ]
1156 A plugin that uses the above names would be invoked from a database
1157 URL as in::
1159 from sqlalchemy import create_engine
1161 engine = create_engine(
1162 "mysql+pymysql://scott:tiger@localhost/test?"
1163 "plugin=log_cursor_plugin&log_cursor_logging_name=mylogger"
1164 )
1166 The ``plugin`` URL parameter supports multiple instances, so that a URL
1167 may specify multiple plugins; they are loaded in the order stated
1168 in the URL::
1170 engine = create_engine(
1171 "mysql+pymysql://scott:tiger@localhost/test?"
1172 "plugin=plugin_one&plugin=plugin_twp&plugin=plugin_three")
1174 The plugin names may also be passed directly to :func:`_sa.create_engine`
1175 using the :paramref:`_sa.create_engine.plugins` argument::
1177 engine = create_engine(
1178 "mysql+pymysql://scott:tiger@localhost/test",
1179 plugins=["myplugin"])
1181 .. versionadded:: 1.2.3 plugin names can also be specified
1182 to :func:`_sa.create_engine` as a list
1184 A plugin may consume plugin-specific arguments from the
1185 :class:`_engine.URL` object as well as the ``kwargs`` dictionary, which is
1186 the dictionary of arguments passed to the :func:`_sa.create_engine`
1187 call. "Consuming" these arguments includes that they must be removed
1188 when the plugin initializes, so that the arguments are not passed along
1189 to the :class:`_engine.Dialect` constructor, where they will raise an
1190 :class:`_exc.ArgumentError` because they are not known by the dialect.
1192 As of version 1.4 of SQLAlchemy, arguments should continue to be consumed
1193 from the ``kwargs`` dictionary directly, by removing the values with a
1194 method such as ``dict.pop``. Arguments from the :class:`_engine.URL` object
1195 should be consumed by implementing the
1196 :meth:`_engine.CreateEnginePlugin.update_url` method, returning a new copy
1197 of the :class:`_engine.URL` with plugin-specific parameters removed::
1199 class MyPlugin(CreateEnginePlugin):
1200 def __init__(self, url, kwargs):
1201 self.my_argument_one = url.query['my_argument_one']
1202 self.my_argument_two = url.query['my_argument_two']
1203 self.my_argument_three = kwargs.pop('my_argument_three', None)
1205 def update_url(self, url):
1206 return url.difference_update_query(
1207 ["my_argument_one", "my_argument_two"]
1208 )
1210 Arguments like those illustrated above would be consumed from a
1211 :func:`_sa.create_engine` call such as::
1213 from sqlalchemy import create_engine
1215 engine = create_engine(
1216 "mysql+pymysql://scott:tiger@localhost/test?"
1217 "plugin=myplugin&my_argument_one=foo&my_argument_two=bar",
1218 my_argument_three='bat'
1219 )
1221 .. versionchanged:: 1.4
1223 The :class:`_engine.URL` object is now immutable; a
1224 :class:`_engine.CreateEnginePlugin` that needs to alter the
1225 :class:`_engine.URL` should implement the newly added
1226 :meth:`_engine.CreateEnginePlugin.update_url` method, which
1227 is invoked after the plugin is constructed.
1229 For migration, construct the plugin in the following way, checking
1230 for the existence of the :meth:`_engine.CreateEnginePlugin.update_url`
1231 method to detect which version is running::
1233 class MyPlugin(CreateEnginePlugin):
1234 def __init__(self, url, kwargs):
1235 if hasattr(CreateEnginePlugin, "update_url"):
1236 # detect the 1.4 API
1237 self.my_argument_one = url.query['my_argument_one']
1238 self.my_argument_two = url.query['my_argument_two']
1239 else:
1240 # detect the 1.3 and earlier API - mutate the
1241 # URL directly
1242 self.my_argument_one = url.query.pop('my_argument_one')
1243 self.my_argument_two = url.query.pop('my_argument_two')
1245 self.my_argument_three = kwargs.pop('my_argument_three', None)
1247 def update_url(self, url):
1248 # this method is only called in the 1.4 version
1249 return url.difference_update_query(
1250 ["my_argument_one", "my_argument_two"]
1251 )
1253 .. seealso::
1255 :ref:`change_5526` - overview of the :class:`_engine.URL` change which
1256 also includes notes regarding :class:`_engine.CreateEnginePlugin`.
1259 When the engine creation process completes and produces the
1260 :class:`_engine.Engine` object, it is again passed to the plugin via the
1261 :meth:`_engine.CreateEnginePlugin.engine_created` hook. In this hook, additional
1262 changes can be made to the engine, most typically involving setup of
1263 events (e.g. those defined in :ref:`core_event_toplevel`).
1265 .. versionadded:: 1.1
1267 """ # noqa: E501
1269 def __init__(self, url, kwargs):
1270 """Construct a new :class:`.CreateEnginePlugin`.
1272 The plugin object is instantiated individually for each call
1273 to :func:`_sa.create_engine`. A single :class:`_engine.
1274 Engine` will be
1275 passed to the :meth:`.CreateEnginePlugin.engine_created` method
1276 corresponding to this URL.
1278 :param url: the :class:`_engine.URL` object. The plugin may inspect
1279 the :class:`_engine.URL` for arguments. Arguments used by the
1280 plugin should be removed, by returning an updated :class:`_engine.URL`
1281 from the :meth:`_engine.CreateEnginePlugin.update_url` method.
1283 .. versionchanged:: 1.4
1285 The :class:`_engine.URL` object is now immutable, so a
1286 :class:`_engine.CreateEnginePlugin` that needs to alter the
1287 :class:`_engine.URL` object should implement the
1288 :meth:`_engine.CreateEnginePlugin.update_url` method.
1290 :param kwargs: The keyword arguments passed to
1291 :func:`_sa.create_engine`.
1293 """
1294 self.url = url
1296 def update_url(self, url):
1297 """Update the :class:`_engine.URL`.
1299 A new :class:`_engine.URL` should be returned. This method is
1300 typically used to consume configuration arguments from the
1301 :class:`_engine.URL` which must be removed, as they will not be
1302 recognized by the dialect. The
1303 :meth:`_engine.URL.difference_update_query` method is available
1304 to remove these arguments. See the docstring at
1305 :class:`_engine.CreateEnginePlugin` for an example.
1308 .. versionadded:: 1.4
1310 """
1312 def handle_dialect_kwargs(self, dialect_cls, dialect_args):
1313 """parse and modify dialect kwargs"""
1315 def handle_pool_kwargs(self, pool_cls, pool_args):
1316 """parse and modify pool kwargs"""
1318 def engine_created(self, engine):
1319 """Receive the :class:`_engine.Engine`
1320 object when it is fully constructed.
1322 The plugin may make additional changes to the engine, such as
1323 registering engine or connection pool events.
1325 """
1328class ExecutionContext(object):
1329 """A messenger object for a Dialect that corresponds to a single
1330 execution.
1332 ExecutionContext should have these data members:
1334 connection
1335 Connection object which can be freely used by default value
1336 generators to execute SQL. This Connection should reference the
1337 same underlying connection/transactional resources of
1338 root_connection.
1340 root_connection
1341 Connection object which is the source of this ExecutionContext. This
1342 Connection may have close_with_result=True set, in which case it can
1343 only be used once.
1345 dialect
1346 dialect which created this ExecutionContext.
1348 cursor
1349 DB-API cursor procured from the connection,
1351 compiled
1352 if passed to constructor, sqlalchemy.engine.base.Compiled object
1353 being executed,
1355 statement
1356 string version of the statement to be executed. Is either
1357 passed to the constructor, or must be created from the
1358 sql.Compiled object by the time pre_exec() has completed.
1360 parameters
1361 bind parameters passed to the execute() method. For compiled
1362 statements, this is a dictionary or list of dictionaries. For
1363 textual statements, it should be in a format suitable for the
1364 dialect's paramstyle (i.e. dict or list of dicts for non
1365 positional, list or list of lists/tuples for positional).
1367 isinsert
1368 True if the statement is an INSERT.
1370 isupdate
1371 True if the statement is an UPDATE.
1373 should_autocommit
1374 True if the statement is a "committable" statement.
1376 prefetch_cols
1377 a list of Column objects for which a client-side default
1378 was fired off. Applies to inserts and updates.
1380 postfetch_cols
1381 a list of Column objects for which a server-side default or
1382 inline SQL expression value was fired off. Applies to inserts
1383 and updates.
1384 """
1386 def create_cursor(self):
1387 """Return a new cursor generated from this ExecutionContext's
1388 connection.
1390 Some dialects may wish to change the behavior of
1391 connection.cursor(), such as postgresql which may return a PG
1392 "server side" cursor.
1393 """
1395 raise NotImplementedError()
1397 def pre_exec(self):
1398 """Called before an execution of a compiled statement.
1400 If a compiled statement was passed to this ExecutionContext,
1401 the `statement` and `parameters` datamembers must be
1402 initialized after this statement is complete.
1403 """
1405 raise NotImplementedError()
1407 def get_out_parameter_values(self, out_param_names):
1408 """Return a sequence of OUT parameter values from a cursor.
1410 For dialects that support OUT parameters, this method will be called
1411 when there is a :class:`.SQLCompiler` object which has the
1412 :attr:`.SQLCompiler.has_out_parameters` flag set. This flag in turn
1413 will be set to True if the statement itself has :class:`.BindParameter`
1414 objects that have the ``.isoutparam`` flag set which are consumed by
1415 the :meth:`.SQLCompiler.visit_bindparam` method. If the dialect
1416 compiler produces :class:`.BindParameter` objects with ``.isoutparam``
1417 set which are not handled by :meth:`.SQLCompiler.visit_bindparam`, it
1418 should set this flag explicitly.
1420 The list of names that were rendered for each bound parameter
1421 is passed to the method. The method should then return a sequence of
1422 values corresponding to the list of parameter objects. Unlike in
1423 previous SQLAlchemy versions, the values can be the **raw values** from
1424 the DBAPI; the execution context will apply the appropriate type
1425 handler based on what's present in self.compiled.binds and update the
1426 values. The processed dictionary will then be made available via the
1427 ``.out_parameters`` collection on the result object. Note that
1428 SQLAlchemy 1.4 has multiple kinds of result object as part of the 2.0
1429 transition.
1431 .. versionadded:: 1.4 - added
1432 :meth:`.ExecutionContext.get_out_parameter_values`, which is invoked
1433 automatically by the :class:`.DefaultExecutionContext` when there
1434 are :class:`.BindParameter` objects with the ``.isoutparam`` flag
1435 set. This replaces the practice of setting out parameters within
1436 the now-removed ``get_result_proxy()`` method.
1438 """
1439 raise NotImplementedError()
1441 def post_exec(self):
1442 """Called after the execution of a compiled statement.
1444 If a compiled statement was passed to this ExecutionContext,
1445 the `last_insert_ids`, `last_inserted_params`, etc.
1446 datamembers should be available after this method completes.
1447 """
1449 raise NotImplementedError()
1451 def handle_dbapi_exception(self, e):
1452 """Receive a DBAPI exception which occurred upon execute, result
1453 fetch, etc."""
1455 raise NotImplementedError()
1457 def should_autocommit_text(self, statement):
1458 """Parse the given textual statement and return True if it refers to
1459 a "committable" statement"""
1461 raise NotImplementedError()
1463 def lastrow_has_defaults(self):
1464 """Return True if the last INSERT or UPDATE row contained
1465 inlined or database-side defaults.
1466 """
1468 raise NotImplementedError()
1470 def get_rowcount(self):
1471 """Return the DBAPI ``cursor.rowcount`` value, or in some
1472 cases an interpreted value.
1474 See :attr:`_engine.CursorResult.rowcount` for details on this.
1476 """
1478 raise NotImplementedError()
1481@util.deprecated_20_cls(
1482 ":class:`.Connectable`",
1483 alternative=(
1484 "The :class:`_engine.Engine` will be the only Core "
1485 "object that features a .connect() method, and the "
1486 ":class:`_engine.Connection` will be the only object that features "
1487 "an .execute() method."
1488 ),
1489 constructor=None,
1490)
1491class Connectable(object):
1492 """Interface for an object which supports execution of SQL constructs.
1494 The two implementations of :class:`.Connectable` are
1495 :class:`_engine.Connection` and :class:`_engine.Engine`.
1497 Connectable must also implement the 'dialect' member which references a
1498 :class:`.Dialect` instance.
1500 """
1502 def connect(self, **kwargs):
1503 """Return a :class:`_engine.Connection` object.
1505 Depending on context, this may be ``self`` if this object
1506 is already an instance of :class:`_engine.Connection`, or a newly
1507 procured :class:`_engine.Connection` if this object is an instance
1508 of :class:`_engine.Engine`.
1510 """
1512 engine = None
1513 """The :class:`_engine.Engine` instance referred to by this
1514 :class:`.Connectable`.
1516 May be ``self`` if this is already an :class:`_engine.Engine`.
1518 """
1520 def execute(self, object_, *multiparams, **params):
1521 """Executes the given construct and returns a
1522 :class:`_engine.CursorResult`.
1523 """
1524 raise NotImplementedError()
1526 def scalar(self, object_, *multiparams, **params):
1527 """Executes and returns the first column of the first row.
1529 The underlying cursor is closed after execution.
1530 """
1531 raise NotImplementedError()
1533 def _run_visitor(self, visitorcallable, element, **kwargs):
1534 raise NotImplementedError()
1536 def _execute_clauseelement(self, elem, multiparams=None, params=None):
1537 raise NotImplementedError()
1540class ExceptionContext(object):
1541 """Encapsulate information about an error condition in progress.
1543 This object exists solely to be passed to the
1544 :meth:`_events.ConnectionEvents.handle_error` event,
1545 supporting an interface that
1546 can be extended without backwards-incompatibility.
1548 .. versionadded:: 0.9.7
1550 """
1552 connection = None
1553 """The :class:`_engine.Connection` in use during the exception.
1555 This member is present, except in the case of a failure when
1556 first connecting.
1558 .. seealso::
1560 :attr:`.ExceptionContext.engine`
1563 """
1565 engine = None
1566 """The :class:`_engine.Engine` in use during the exception.
1568 This member should always be present, even in the case of a failure
1569 when first connecting.
1571 .. versionadded:: 1.0.0
1573 """
1575 cursor = None
1576 """The DBAPI cursor object.
1578 May be None.
1580 """
1582 statement = None
1583 """String SQL statement that was emitted directly to the DBAPI.
1585 May be None.
1587 """
1589 parameters = None
1590 """Parameter collection that was emitted directly to the DBAPI.
1592 May be None.
1594 """
1596 original_exception = None
1597 """The exception object which was caught.
1599 This member is always present.
1601 """
1603 sqlalchemy_exception = None
1604 """The :class:`sqlalchemy.exc.StatementError` which wraps the original,
1605 and will be raised if exception handling is not circumvented by the event.
1607 May be None, as not all exception types are wrapped by SQLAlchemy.
1608 For DBAPI-level exceptions that subclass the dbapi's Error class, this
1609 field will always be present.
1611 """
1613 chained_exception = None
1614 """The exception that was returned by the previous handler in the
1615 exception chain, if any.
1617 If present, this exception will be the one ultimately raised by
1618 SQLAlchemy unless a subsequent handler replaces it.
1620 May be None.
1622 """
1624 execution_context = None
1625 """The :class:`.ExecutionContext` corresponding to the execution
1626 operation in progress.
1628 This is present for statement execution operations, but not for
1629 operations such as transaction begin/end. It also is not present when
1630 the exception was raised before the :class:`.ExecutionContext`
1631 could be constructed.
1633 Note that the :attr:`.ExceptionContext.statement` and
1634 :attr:`.ExceptionContext.parameters` members may represent a
1635 different value than that of the :class:`.ExecutionContext`,
1636 potentially in the case where a
1637 :meth:`_events.ConnectionEvents.before_cursor_execute` event or similar
1638 modified the statement/parameters to be sent.
1640 May be None.
1642 """
1644 is_disconnect = None
1645 """Represent whether the exception as occurred represents a "disconnect"
1646 condition.
1648 This flag will always be True or False within the scope of the
1649 :meth:`_events.ConnectionEvents.handle_error` handler.
1651 SQLAlchemy will defer to this flag in order to determine whether or not
1652 the connection should be invalidated subsequently. That is, by
1653 assigning to this flag, a "disconnect" event which then results in
1654 a connection and pool invalidation can be invoked or prevented by
1655 changing this flag.
1658 .. note:: The pool "pre_ping" handler enabled using the
1659 :paramref:`_sa.create_engine.pool_pre_ping` parameter does **not**
1660 consult this event before deciding if the "ping" returned false,
1661 as opposed to receiving an unhandled error. For this use case, the
1662 :ref:`legacy recipe based on engine_connect() may be used
1663 <pool_disconnects_pessimistic_custom>`. A future API allow more
1664 comprehensive customization of the "disconnect" detection mechanism
1665 across all functions.
1667 """
1669 invalidate_pool_on_disconnect = True
1670 """Represent whether all connections in the pool should be invalidated
1671 when a "disconnect" condition is in effect.
1673 Setting this flag to False within the scope of the
1674 :meth:`_events.ConnectionEvents.handle_error`
1675 event will have the effect such
1676 that the full collection of connections in the pool will not be
1677 invalidated during a disconnect; only the current connection that is the
1678 subject of the error will actually be invalidated.
1680 The purpose of this flag is for custom disconnect-handling schemes where
1681 the invalidation of other connections in the pool is to be performed
1682 based on other conditions, or even on a per-connection basis.
1684 .. versionadded:: 1.0.3
1686 """
1689class AdaptedConnection(object):
1690 """Interface of an adapted connection object to support the DBAPI protocol.
1692 Used by asyncio dialects to provide a sync-style pep-249 facade on top
1693 of the asyncio connection/cursor API provided by the driver.
1695 .. versionadded:: 1.4.24
1697 """
1699 __slots__ = ("_connection",)
1701 @property
1702 def driver_connection(self):
1703 """The connection object as returned by the driver after a connect."""
1704 return self._connection
1706 def run_async(self, fn):
1707 """Run the awaitable returned by the given function, which is passed
1708 the raw asyncio driver connection.
1710 This is used to invoke awaitable-only methods on the driver connection
1711 within the context of a "synchronous" method, like a connection
1712 pool event handler.
1714 E.g.::
1716 engine = create_async_engine(...)
1718 @event.listens_for(engine.sync_engine, "connect")
1719 def register_custom_types(dbapi_connection, ...):
1720 dbapi_connection.run_async(
1721 lambda connection: connection.set_type_codec(
1722 'MyCustomType', encoder, decoder, ...
1723 )
1724 )
1726 .. versionadded:: 1.4.30
1728 .. seealso::
1730 :ref:`asyncio_events_run_async`
1732 """
1733 return await_only(fn(self._connection))
1735 def __repr__(self):
1736 return "<AdaptedConnection %s>" % self._connection