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 """