interfaces.py 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286
  1. # engine/interfaces.py
  2. # Copyright (C) 2005-2017 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. """Define core interfaces used by the engine system."""
  8. from .. import util
  9. # backwards compat
  10. from ..sql.compiler import Compiled, TypeCompiler
  11. class Dialect(object):
  12. """Define the behavior of a specific database and DB-API combination.
  13. Any aspect of metadata definition, SQL query generation,
  14. execution, result-set handling, or anything else which varies
  15. between databases is defined under the general category of the
  16. Dialect. The Dialect acts as a factory for other
  17. database-specific object implementations including
  18. ExecutionContext, Compiled, DefaultGenerator, and TypeEngine.
  19. All Dialects implement the following attributes:
  20. name
  21. identifying name for the dialect from a DBAPI-neutral point of view
  22. (i.e. 'sqlite')
  23. driver
  24. identifying name for the dialect's DBAPI
  25. positional
  26. True if the paramstyle for this Dialect is positional.
  27. paramstyle
  28. the paramstyle to be used (some DB-APIs support multiple
  29. paramstyles).
  30. convert_unicode
  31. True if Unicode conversion should be applied to all ``str``
  32. types.
  33. encoding
  34. type of encoding to use for unicode, usually defaults to
  35. 'utf-8'.
  36. statement_compiler
  37. a :class:`.Compiled` class used to compile SQL statements
  38. ddl_compiler
  39. a :class:`.Compiled` class used to compile DDL statements
  40. server_version_info
  41. a tuple containing a version number for the DB backend in use.
  42. This value is only available for supporting dialects, and is
  43. typically populated during the initial connection to the database.
  44. default_schema_name
  45. the name of the default schema. This value is only available for
  46. supporting dialects, and is typically populated during the
  47. initial connection to the database.
  48. execution_ctx_cls
  49. a :class:`.ExecutionContext` class used to handle statement execution
  50. execute_sequence_format
  51. either the 'tuple' or 'list' type, depending on what cursor.execute()
  52. accepts for the second argument (they vary).
  53. preparer
  54. a :class:`~sqlalchemy.sql.compiler.IdentifierPreparer` class used to
  55. quote identifiers.
  56. supports_alter
  57. ``True`` if the database supports ``ALTER TABLE``.
  58. max_identifier_length
  59. The maximum length of identifier names.
  60. supports_unicode_statements
  61. Indicate whether the DB-API can receive SQL statements as Python
  62. unicode strings
  63. supports_unicode_binds
  64. Indicate whether the DB-API can receive string bind parameters
  65. as Python unicode strings
  66. supports_sane_rowcount
  67. Indicate whether the dialect properly implements rowcount for
  68. ``UPDATE`` and ``DELETE`` statements.
  69. supports_sane_multi_rowcount
  70. Indicate whether the dialect properly implements rowcount for
  71. ``UPDATE`` and ``DELETE`` statements when executed via
  72. executemany.
  73. preexecute_autoincrement_sequences
  74. True if 'implicit' primary key functions must be executed separately
  75. in order to get their value. This is currently oriented towards
  76. PostgreSQL.
  77. implicit_returning
  78. use RETURNING or equivalent during INSERT execution in order to load
  79. newly generated primary keys and other column defaults in one execution,
  80. which are then available via inserted_primary_key.
  81. If an insert statement has returning() specified explicitly,
  82. the "implicit" functionality is not used and inserted_primary_key
  83. will not be available.
  84. dbapi_type_map
  85. A mapping of DB-API type objects present in this Dialect's
  86. DB-API implementation mapped to TypeEngine implementations used
  87. by the dialect.
  88. This is used to apply types to result sets based on the DB-API
  89. types present in cursor.description; it only takes effect for
  90. result sets against textual statements where no explicit
  91. typemap was present.
  92. colspecs
  93. A dictionary of TypeEngine classes from sqlalchemy.types mapped
  94. to subclasses that are specific to the dialect class. This
  95. dictionary is class-level only and is not accessed from the
  96. dialect instance itself.
  97. supports_default_values
  98. Indicates if the construct ``INSERT INTO tablename DEFAULT
  99. VALUES`` is supported
  100. supports_sequences
  101. Indicates if the dialect supports CREATE SEQUENCE or similar.
  102. sequences_optional
  103. If True, indicates if the "optional" flag on the Sequence() construct
  104. should signal to not generate a CREATE SEQUENCE. Applies only to
  105. dialects that support sequences. Currently used only to allow PostgreSQL
  106. SERIAL to be used on a column that specifies Sequence() for usage on
  107. other backends.
  108. supports_native_enum
  109. Indicates if the dialect supports a native ENUM construct.
  110. This will prevent types.Enum from generating a CHECK
  111. constraint when that type is used.
  112. supports_native_boolean
  113. Indicates if the dialect supports a native boolean construct.
  114. This will prevent types.Boolean from generating a CHECK
  115. constraint when that type is used.
  116. dbapi_exception_translation_map
  117. A dictionary of names that will contain as values the names of
  118. pep-249 exceptions ("IntegrityError", "OperationalError", etc)
  119. keyed to alternate class names, to support the case where a
  120. DBAPI has exception classes that aren't named as they are
  121. referred to (e.g. IntegrityError = MyException). In the vast
  122. majority of cases this dictionary is empty.
  123. .. versionadded:: 1.0.5
  124. """
  125. _has_events = False
  126. def create_connect_args(self, url):
  127. """Build DB-API compatible connection arguments.
  128. Given a :class:`~sqlalchemy.engine.url.URL` object, returns a tuple
  129. consisting of a `*args`/`**kwargs` suitable to send directly
  130. to the dbapi's connect function.
  131. """
  132. raise NotImplementedError()
  133. @classmethod
  134. def type_descriptor(cls, typeobj):
  135. """Transform a generic type to a dialect-specific type.
  136. Dialect classes will usually use the
  137. :func:`.types.adapt_type` function in the types module to
  138. accomplish this.
  139. The returned result is cached *per dialect class* so can
  140. contain no dialect-instance state.
  141. """
  142. raise NotImplementedError()
  143. def initialize(self, connection):
  144. """Called during strategized creation of the dialect with a
  145. connection.
  146. Allows dialects to configure options based on server version info or
  147. other properties.
  148. The connection passed here is a SQLAlchemy Connection object,
  149. with full capabilities.
  150. The initialize() method of the base dialect should be called via
  151. super().
  152. """
  153. pass
  154. def reflecttable(
  155. self, connection, table, include_columns, exclude_columns):
  156. """Load table description from the database.
  157. Given a :class:`.Connection` and a
  158. :class:`~sqlalchemy.schema.Table` object, reflect its columns and
  159. properties from the database.
  160. The implementation of this method is provided by
  161. :meth:`.DefaultDialect.reflecttable`, which makes use of
  162. :class:`.Inspector` to retrieve column information.
  163. Dialects should **not** seek to implement this method, and should
  164. instead implement individual schema inspection operations such as
  165. :meth:`.Dialect.get_columns`, :meth:`.Dialect.get_pk_constraint`,
  166. etc.
  167. """
  168. raise NotImplementedError()
  169. def get_columns(self, connection, table_name, schema=None, **kw):
  170. """Return information about columns in `table_name`.
  171. Given a :class:`.Connection`, a string
  172. `table_name`, and an optional string `schema`, return column
  173. information as a list of dictionaries with these keys:
  174. name
  175. the column's name
  176. type
  177. [sqlalchemy.types#TypeEngine]
  178. nullable
  179. boolean
  180. default
  181. the column's default value
  182. autoincrement
  183. boolean
  184. sequence
  185. a dictionary of the form
  186. {'name' : str, 'start' :int, 'increment': int, 'minvalue': int,
  187. 'maxvalue': int, 'nominvalue': bool, 'nomaxvalue': bool,
  188. 'cycle': bool}
  189. Additional column attributes may be present.
  190. """
  191. raise NotImplementedError()
  192. def get_primary_keys(self, connection, table_name, schema=None, **kw):
  193. """Return information about primary keys in `table_name`.
  194. Deprecated. This method is only called by the default
  195. implementation of :meth:`.Dialect.get_pk_constraint`. Dialects should
  196. instead implement the :meth:`.Dialect.get_pk_constraint` method
  197. directly.
  198. """
  199. raise NotImplementedError()
  200. def get_pk_constraint(self, connection, table_name, schema=None, **kw):
  201. """Return information about the primary key constraint on
  202. table_name`.
  203. Given a :class:`.Connection`, a string
  204. `table_name`, and an optional string `schema`, return primary
  205. key information as a dictionary with these keys:
  206. constrained_columns
  207. a list of column names that make up the primary key
  208. name
  209. optional name of the primary key constraint.
  210. """
  211. raise NotImplementedError()
  212. def get_foreign_keys(self, connection, table_name, schema=None, **kw):
  213. """Return information about foreign_keys in `table_name`.
  214. Given a :class:`.Connection`, a string
  215. `table_name`, and an optional string `schema`, return foreign
  216. key information as a list of dicts with these keys:
  217. name
  218. the constraint's name
  219. constrained_columns
  220. a list of column names that make up the foreign key
  221. referred_schema
  222. the name of the referred schema
  223. referred_table
  224. the name of the referred table
  225. referred_columns
  226. a list of column names in the referred table that correspond to
  227. constrained_columns
  228. """
  229. raise NotImplementedError()
  230. def get_table_names(self, connection, schema=None, **kw):
  231. """Return a list of table names for `schema`."""
  232. raise NotImplementedError()
  233. def get_temp_table_names(self, connection, schema=None, **kw):
  234. """Return a list of temporary table names on the given connection,
  235. if supported by the underlying backend.
  236. """
  237. raise NotImplementedError()
  238. def get_view_names(self, connection, schema=None, **kw):
  239. """Return a list of all view names available in the database.
  240. schema:
  241. Optional, retrieve names from a non-default schema.
  242. """
  243. raise NotImplementedError()
  244. def get_temp_view_names(self, connection, schema=None, **kw):
  245. """Return a list of temporary view names on the given connection,
  246. if supported by the underlying backend.
  247. """
  248. raise NotImplementedError()
  249. def get_view_definition(self, connection, view_name, schema=None, **kw):
  250. """Return view definition.
  251. Given a :class:`.Connection`, a string
  252. `view_name`, and an optional string `schema`, return the view
  253. definition.
  254. """
  255. raise NotImplementedError()
  256. def get_indexes(self, connection, table_name, schema=None, **kw):
  257. """Return information about indexes in `table_name`.
  258. Given a :class:`.Connection`, a string
  259. `table_name` and an optional string `schema`, return index
  260. information as a list of dictionaries with these keys:
  261. name
  262. the index's name
  263. column_names
  264. list of column names in order
  265. unique
  266. boolean
  267. """
  268. raise NotImplementedError()
  269. def get_unique_constraints(
  270. self, connection, table_name, schema=None, **kw):
  271. r"""Return information about unique constraints in `table_name`.
  272. Given a string `table_name` and an optional string `schema`, return
  273. unique constraint information as a list of dicts with these keys:
  274. name
  275. the unique constraint's name
  276. column_names
  277. list of column names in order
  278. \**kw
  279. other options passed to the dialect's get_unique_constraints()
  280. method.
  281. .. versionadded:: 0.9.0
  282. """
  283. raise NotImplementedError()
  284. def get_check_constraints(
  285. self, connection, table_name, schema=None, **kw):
  286. r"""Return information about check constraints in `table_name`.
  287. Given a string `table_name` and an optional string `schema`, return
  288. check constraint information as a list of dicts with these keys:
  289. name
  290. the check constraint's name
  291. sqltext
  292. the check constraint's SQL expression
  293. \**kw
  294. other options passed to the dialect's get_check_constraints()
  295. method.
  296. .. versionadded:: 1.1.0
  297. """
  298. raise NotImplementedError()
  299. def normalize_name(self, name):
  300. """convert the given name to lowercase if it is detected as
  301. case insensitive.
  302. this method is only used if the dialect defines
  303. requires_name_normalize=True.
  304. """
  305. raise NotImplementedError()
  306. def denormalize_name(self, name):
  307. """convert the given name to a case insensitive identifier
  308. for the backend if it is an all-lowercase name.
  309. this method is only used if the dialect defines
  310. requires_name_normalize=True.
  311. """
  312. raise NotImplementedError()
  313. def has_table(self, connection, table_name, schema=None):
  314. """Check the existence of a particular table in the database.
  315. Given a :class:`.Connection` object and a string
  316. `table_name`, return True if the given table (possibly within
  317. the specified `schema`) exists in the database, False
  318. otherwise.
  319. """
  320. raise NotImplementedError()
  321. def has_sequence(self, connection, sequence_name, schema=None):
  322. """Check the existence of a particular sequence in the database.
  323. Given a :class:`.Connection` object and a string
  324. `sequence_name`, return True if the given sequence exists in
  325. the database, False otherwise.
  326. """
  327. raise NotImplementedError()
  328. def _get_server_version_info(self, connection):
  329. """Retrieve the server version info from the given connection.
  330. This is used by the default implementation to populate the
  331. "server_version_info" attribute and is called exactly
  332. once upon first connect.
  333. """
  334. raise NotImplementedError()
  335. def _get_default_schema_name(self, connection):
  336. """Return the string name of the currently selected schema from
  337. the given connection.
  338. This is used by the default implementation to populate the
  339. "default_schema_name" attribute and is called exactly
  340. once upon first connect.
  341. """
  342. raise NotImplementedError()
  343. def do_begin(self, dbapi_connection):
  344. """Provide an implementation of ``connection.begin()``, given a
  345. DB-API connection.
  346. The DBAPI has no dedicated "begin" method and it is expected
  347. that transactions are implicit. This hook is provided for those
  348. DBAPIs that might need additional help in this area.
  349. Note that :meth:`.Dialect.do_begin` is not called unless a
  350. :class:`.Transaction` object is in use. The
  351. :meth:`.Dialect.do_autocommit`
  352. hook is provided for DBAPIs that need some extra commands emitted
  353. after a commit in order to enter the next transaction, when the
  354. SQLAlchemy :class:`.Connection` is used in its default "autocommit"
  355. mode.
  356. :param dbapi_connection: a DBAPI connection, typically
  357. proxied within a :class:`.ConnectionFairy`.
  358. """
  359. raise NotImplementedError()
  360. def do_rollback(self, dbapi_connection):
  361. """Provide an implementation of ``connection.rollback()``, given
  362. a DB-API connection.
  363. :param dbapi_connection: a DBAPI connection, typically
  364. proxied within a :class:`.ConnectionFairy`.
  365. """
  366. raise NotImplementedError()
  367. def do_commit(self, dbapi_connection):
  368. """Provide an implementation of ``connection.commit()``, given a
  369. DB-API connection.
  370. :param dbapi_connection: a DBAPI connection, typically
  371. proxied within a :class:`.ConnectionFairy`.
  372. """
  373. raise NotImplementedError()
  374. def do_close(self, dbapi_connection):
  375. """Provide an implementation of ``connection.close()``, given a DBAPI
  376. connection.
  377. This hook is called by the :class:`.Pool` when a connection has been
  378. detached from the pool, or is being returned beyond the normal
  379. capacity of the pool.
  380. .. versionadded:: 0.8
  381. """
  382. raise NotImplementedError()
  383. def create_xid(self):
  384. """Create a two-phase transaction ID.
  385. This id will be passed to do_begin_twophase(),
  386. do_rollback_twophase(), do_commit_twophase(). Its format is
  387. unspecified.
  388. """
  389. raise NotImplementedError()
  390. def do_savepoint(self, connection, name):
  391. """Create a savepoint with the given name.
  392. :param connection: a :class:`.Connection`.
  393. :param name: savepoint name.
  394. """
  395. raise NotImplementedError()
  396. def do_rollback_to_savepoint(self, connection, name):
  397. """Rollback a connection to the named savepoint.
  398. :param connection: a :class:`.Connection`.
  399. :param name: savepoint name.
  400. """
  401. raise NotImplementedError()
  402. def do_release_savepoint(self, connection, name):
  403. """Release the named savepoint on a connection.
  404. :param connection: a :class:`.Connection`.
  405. :param name: savepoint name.
  406. """
  407. raise NotImplementedError()
  408. def do_begin_twophase(self, connection, xid):
  409. """Begin a two phase transaction on the given connection.
  410. :param connection: a :class:`.Connection`.
  411. :param xid: xid
  412. """
  413. raise NotImplementedError()
  414. def do_prepare_twophase(self, connection, xid):
  415. """Prepare a two phase transaction on the given connection.
  416. :param connection: a :class:`.Connection`.
  417. :param xid: xid
  418. """
  419. raise NotImplementedError()
  420. def do_rollback_twophase(self, connection, xid, is_prepared=True,
  421. recover=False):
  422. """Rollback a two phase transaction on the given connection.
  423. :param connection: a :class:`.Connection`.
  424. :param xid: xid
  425. :param is_prepared: whether or not
  426. :meth:`.TwoPhaseTransaction.prepare` was called.
  427. :param recover: if the recover flag was passed.
  428. """
  429. raise NotImplementedError()
  430. def do_commit_twophase(self, connection, xid, is_prepared=True,
  431. recover=False):
  432. """Commit a two phase transaction on the given connection.
  433. :param connection: a :class:`.Connection`.
  434. :param xid: xid
  435. :param is_prepared: whether or not
  436. :meth:`.TwoPhaseTransaction.prepare` was called.
  437. :param recover: if the recover flag was passed.
  438. """
  439. raise NotImplementedError()
  440. def do_recover_twophase(self, connection):
  441. """Recover list of uncommitted prepared two phase transaction
  442. identifiers on the given connection.
  443. :param connection: a :class:`.Connection`.
  444. """
  445. raise NotImplementedError()
  446. def do_executemany(self, cursor, statement, parameters, context=None):
  447. """Provide an implementation of ``cursor.executemany(statement,
  448. parameters)``."""
  449. raise NotImplementedError()
  450. def do_execute(self, cursor, statement, parameters, context=None):
  451. """Provide an implementation of ``cursor.execute(statement,
  452. parameters)``."""
  453. raise NotImplementedError()
  454. def do_execute_no_params(self, cursor, statement, parameters,
  455. context=None):
  456. """Provide an implementation of ``cursor.execute(statement)``.
  457. The parameter collection should not be sent.
  458. """
  459. raise NotImplementedError()
  460. def is_disconnect(self, e, connection, cursor):
  461. """Return True if the given DB-API error indicates an invalid
  462. connection"""
  463. raise NotImplementedError()
  464. def connect(self):
  465. """return a callable which sets up a newly created DBAPI connection.
  466. The callable accepts a single argument "conn" which is the
  467. DBAPI connection itself. It has no return value.
  468. This is used to set dialect-wide per-connection options such as
  469. isolation modes, unicode modes, etc.
  470. If a callable is returned, it will be assembled into a pool listener
  471. that receives the direct DBAPI connection, with all wrappers removed.
  472. If None is returned, no listener will be generated.
  473. """
  474. return None
  475. def reset_isolation_level(self, dbapi_conn):
  476. """Given a DBAPI connection, revert its isolation to the default.
  477. Note that this is a dialect-level method which is used as part
  478. of the implementation of the :class:`.Connection` and
  479. :class:`.Engine`
  480. isolation level facilities; these APIs should be preferred for
  481. most typical use cases.
  482. .. seealso::
  483. :meth:`.Connection.get_isolation_level` - view current level
  484. :attr:`.Connection.default_isolation_level` - view default level
  485. :paramref:`.Connection.execution_options.isolation_level` -
  486. set per :class:`.Connection` isolation level
  487. :paramref:`.create_engine.isolation_level` -
  488. set per :class:`.Engine` isolation level
  489. """
  490. raise NotImplementedError()
  491. def set_isolation_level(self, dbapi_conn, level):
  492. """Given a DBAPI connection, set its isolation level.
  493. Note that this is a dialect-level method which is used as part
  494. of the implementation of the :class:`.Connection` and
  495. :class:`.Engine`
  496. isolation level facilities; these APIs should be preferred for
  497. most typical use cases.
  498. .. seealso::
  499. :meth:`.Connection.get_isolation_level` - view current level
  500. :attr:`.Connection.default_isolation_level` - view default level
  501. :paramref:`.Connection.execution_options.isolation_level` -
  502. set per :class:`.Connection` isolation level
  503. :paramref:`.create_engine.isolation_level` -
  504. set per :class:`.Engine` isolation level
  505. """
  506. raise NotImplementedError()
  507. def get_isolation_level(self, dbapi_conn):
  508. """Given a DBAPI connection, return its isolation level.
  509. When working with a :class:`.Connection` object, the corresponding
  510. DBAPI connection may be procured using the
  511. :attr:`.Connection.connection` accessor.
  512. Note that this is a dialect-level method which is used as part
  513. of the implementation of the :class:`.Connection` and
  514. :class:`.Engine` isolation level facilities;
  515. these APIs should be preferred for most typical use cases.
  516. .. seealso::
  517. :meth:`.Connection.get_isolation_level` - view current level
  518. :attr:`.Connection.default_isolation_level` - view default level
  519. :paramref:`.Connection.execution_options.isolation_level` -
  520. set per :class:`.Connection` isolation level
  521. :paramref:`.create_engine.isolation_level` -
  522. set per :class:`.Engine` isolation level
  523. """
  524. raise NotImplementedError()
  525. @classmethod
  526. def get_dialect_cls(cls, url):
  527. """Given a URL, return the :class:`.Dialect` that will be used.
  528. This is a hook that allows an external plugin to provide functionality
  529. around an existing dialect, by allowing the plugin to be loaded
  530. from the url based on an entrypoint, and then the plugin returns
  531. the actual dialect to be used.
  532. By default this just returns the cls.
  533. .. versionadded:: 1.0.3
  534. """
  535. return cls
  536. @classmethod
  537. def engine_created(cls, engine):
  538. """A convenience hook called before returning the final :class:`.Engine`.
  539. If the dialect returned a different class from the
  540. :meth:`.get_dialect_cls`
  541. method, then the hook is called on both classes, first on
  542. the dialect class returned by the :meth:`.get_dialect_cls` method and
  543. then on the class on which the method was called.
  544. The hook should be used by dialects and/or wrappers to apply special
  545. events to the engine or its components. In particular, it allows
  546. a dialect-wrapping class to apply dialect-level events.
  547. .. versionadded:: 1.0.3
  548. """
  549. pass
  550. class CreateEnginePlugin(object):
  551. """A set of hooks intended to augment the construction of an
  552. :class:`.Engine` object based on entrypoint names in a URL.
  553. The purpose of :class:`.CreateEnginePlugin` is to allow third-party
  554. systems to apply engine, pool and dialect level event listeners without
  555. the need for the target application to be modified; instead, the plugin
  556. names can be added to the database URL. Target applications for
  557. :class:`.CreateEnginePlugin` include:
  558. * connection and SQL performance tools, e.g. which use events to track
  559. number of checkouts and/or time spent with statements
  560. * connectivity plugins such as proxies
  561. Plugins are registered using entry points in a similar way as that
  562. of dialects::
  563. entry_points={
  564. 'sqlalchemy.plugins': [
  565. 'myplugin = myapp.plugins:MyPlugin'
  566. ]
  567. A plugin that uses the above names would be invoked from a database
  568. URL as in::
  569. from sqlalchemy import create_engine
  570. engine = create_engine(
  571. "mysql+pymysql://scott:tiger@localhost/test?plugin=myplugin")
  572. The ``plugin`` argument supports multiple instances, so that a URL
  573. may specify multiple plugins; they are loaded in the order stated
  574. in the URL::
  575. engine = create_engine(
  576. "mysql+pymysql://scott:tiger@localhost/"
  577. "test?plugin=plugin_one&plugin=plugin_twp&plugin=plugin_three")
  578. A plugin can receive additional arguments from the URL string as
  579. well as from the keyword arguments passed to :func:`.create_engine`.
  580. The :class:`.URL` object and the keyword dictionary are passed to the
  581. constructor so that these arguments can be extracted from the url's
  582. :attr:`.URL.query` collection as well as from the dictionary::
  583. class MyPlugin(CreateEnginePlugin):
  584. def __init__(self, url, kwargs):
  585. self.my_argument_one = url.query.pop('my_argument_one')
  586. self.my_argument_two = url.query.pop('my_argument_two')
  587. self.my_argument_three = kwargs.pop('my_argument_three', None)
  588. Arguments like those illustrated above would be consumed from the
  589. following::
  590. from sqlalchemy import create_engine
  591. engine = create_engine(
  592. "mysql+pymysql://scott:tiger@localhost/"
  593. "test?plugin=myplugin&my_argument_one=foo&my_argument_two=bar",
  594. my_argument_three='bat')
  595. The URL and dictionary are used for subsequent setup of the engine
  596. as they are, so the plugin can modify their arguments in-place.
  597. Arguments that are only understood by the plugin should be popped
  598. or otherwise removed so that they aren't interpreted as erroneous
  599. arguments afterwards.
  600. When the engine creation process completes and produces the
  601. :class:`.Engine` object, it is again passed to the plugin via the
  602. :meth:`.CreateEnginePlugin.engine_created` hook. In this hook, additional
  603. changes can be made to the engine, most typically involving setup of
  604. events (e.g. those defined in :ref:`core_event_toplevel`).
  605. .. versionadded:: 1.1
  606. """
  607. def __init__(self, url, kwargs):
  608. """Contruct a new :class:`.CreateEnginePlugin`.
  609. The plugin object is instantiated individually for each call
  610. to :func:`.create_engine`. A single :class:`.Engine` will be
  611. passed to the :meth:`.CreateEnginePlugin.engine_created` method
  612. corresponding to this URL.
  613. :param url: the :class:`.URL` object. The plugin should inspect
  614. what it needs here as well as remove its custom arguments from the
  615. :attr:`.URL.query` collection. The URL can be modified in-place
  616. in any other way as well.
  617. :param kwargs: The keyword arguments passed to :func`.create_engine`.
  618. The plugin can read and modify this dictionary in-place, to affect
  619. the ultimate arguments used to create the engine. It should
  620. remove its custom arguments from the dictionary as well.
  621. """
  622. self.url = url
  623. def handle_dialect_kwargs(self, dialect_cls, dialect_args):
  624. """parse and modify dialect kwargs"""
  625. def handle_pool_kwargs(self, pool_cls, pool_args):
  626. """parse and modify pool kwargs"""
  627. def engine_created(self, engine):
  628. """Receive the :class:`.Engine` object when it is fully constructed.
  629. The plugin may make additional changes to the engine, such as
  630. registering engine or connection pool events.
  631. """
  632. class ExecutionContext(object):
  633. """A messenger object for a Dialect that corresponds to a single
  634. execution.
  635. ExecutionContext should have these data members:
  636. connection
  637. Connection object which can be freely used by default value
  638. generators to execute SQL. This Connection should reference the
  639. same underlying connection/transactional resources of
  640. root_connection.
  641. root_connection
  642. Connection object which is the source of this ExecutionContext. This
  643. Connection may have close_with_result=True set, in which case it can
  644. only be used once.
  645. dialect
  646. dialect which created this ExecutionContext.
  647. cursor
  648. DB-API cursor procured from the connection,
  649. compiled
  650. if passed to constructor, sqlalchemy.engine.base.Compiled object
  651. being executed,
  652. statement
  653. string version of the statement to be executed. Is either
  654. passed to the constructor, or must be created from the
  655. sql.Compiled object by the time pre_exec() has completed.
  656. parameters
  657. bind parameters passed to the execute() method. For compiled
  658. statements, this is a dictionary or list of dictionaries. For
  659. textual statements, it should be in a format suitable for the
  660. dialect's paramstyle (i.e. dict or list of dicts for non
  661. positional, list or list of lists/tuples for positional).
  662. isinsert
  663. True if the statement is an INSERT.
  664. isupdate
  665. True if the statement is an UPDATE.
  666. should_autocommit
  667. True if the statement is a "committable" statement.
  668. prefetch_cols
  669. a list of Column objects for which a client-side default
  670. was fired off. Applies to inserts and updates.
  671. postfetch_cols
  672. a list of Column objects for which a server-side default or
  673. inline SQL expression value was fired off. Applies to inserts
  674. and updates.
  675. """
  676. exception = None
  677. """A DBAPI-level exception that was caught when this ExecutionContext
  678. attempted to execute a statement.
  679. This attribute is meaningful only within the
  680. :meth:`.ConnectionEvents.dbapi_error` event.
  681. .. versionadded:: 0.9.7
  682. .. seealso::
  683. :attr:`.ExecutionContext.is_disconnect`
  684. :meth:`.ConnectionEvents.dbapi_error`
  685. """
  686. is_disconnect = None
  687. """Boolean flag set to True or False when a DBAPI-level exception
  688. is caught when this ExecutionContext attempted to execute a statement.
  689. This attribute is meaningful only within the
  690. :meth:`.ConnectionEvents.dbapi_error` event.
  691. .. versionadded:: 0.9.7
  692. .. seealso::
  693. :attr:`.ExecutionContext.exception`
  694. :meth:`.ConnectionEvents.dbapi_error`
  695. """
  696. def create_cursor(self):
  697. """Return a new cursor generated from this ExecutionContext's
  698. connection.
  699. Some dialects may wish to change the behavior of
  700. connection.cursor(), such as postgresql which may return a PG
  701. "server side" cursor.
  702. """
  703. raise NotImplementedError()
  704. def pre_exec(self):
  705. """Called before an execution of a compiled statement.
  706. If a compiled statement was passed to this ExecutionContext,
  707. the `statement` and `parameters` datamembers must be
  708. initialized after this statement is complete.
  709. """
  710. raise NotImplementedError()
  711. def post_exec(self):
  712. """Called after the execution of a compiled statement.
  713. If a compiled statement was passed to this ExecutionContext,
  714. the `last_insert_ids`, `last_inserted_params`, etc.
  715. datamembers should be available after this method completes.
  716. """
  717. raise NotImplementedError()
  718. def result(self):
  719. """Return a result object corresponding to this ExecutionContext.
  720. Returns a ResultProxy.
  721. """
  722. raise NotImplementedError()
  723. def handle_dbapi_exception(self, e):
  724. """Receive a DBAPI exception which occurred upon execute, result
  725. fetch, etc."""
  726. raise NotImplementedError()
  727. def should_autocommit_text(self, statement):
  728. """Parse the given textual statement and return True if it refers to
  729. a "committable" statement"""
  730. raise NotImplementedError()
  731. def lastrow_has_defaults(self):
  732. """Return True if the last INSERT or UPDATE row contained
  733. inlined or database-side defaults.
  734. """
  735. raise NotImplementedError()
  736. def get_rowcount(self):
  737. """Return the DBAPI ``cursor.rowcount`` value, or in some
  738. cases an interpreted value.
  739. See :attr:`.ResultProxy.rowcount` for details on this.
  740. """
  741. raise NotImplementedError()
  742. class Connectable(object):
  743. """Interface for an object which supports execution of SQL constructs.
  744. The two implementations of :class:`.Connectable` are
  745. :class:`.Connection` and :class:`.Engine`.
  746. Connectable must also implement the 'dialect' member which references a
  747. :class:`.Dialect` instance.
  748. """
  749. def connect(self, **kwargs):
  750. """Return a :class:`.Connection` object.
  751. Depending on context, this may be ``self`` if this object
  752. is already an instance of :class:`.Connection`, or a newly
  753. procured :class:`.Connection` if this object is an instance
  754. of :class:`.Engine`.
  755. """
  756. def contextual_connect(self):
  757. """Return a :class:`.Connection` object which may be part of an ongoing
  758. context.
  759. Depending on context, this may be ``self`` if this object
  760. is already an instance of :class:`.Connection`, or a newly
  761. procured :class:`.Connection` if this object is an instance
  762. of :class:`.Engine`.
  763. """
  764. raise NotImplementedError()
  765. @util.deprecated("0.7",
  766. "Use the create() method on the given schema "
  767. "object directly, i.e. :meth:`.Table.create`, "
  768. ":meth:`.Index.create`, :meth:`.MetaData.create_all`")
  769. def create(self, entity, **kwargs):
  770. """Emit CREATE statements for the given schema entity.
  771. """
  772. raise NotImplementedError()
  773. @util.deprecated("0.7",
  774. "Use the drop() method on the given schema "
  775. "object directly, i.e. :meth:`.Table.drop`, "
  776. ":meth:`.Index.drop`, :meth:`.MetaData.drop_all`")
  777. def drop(self, entity, **kwargs):
  778. """Emit DROP statements for the given schema entity.
  779. """
  780. raise NotImplementedError()
  781. def execute(self, object, *multiparams, **params):
  782. """Executes the given construct and returns a :class:`.ResultProxy`."""
  783. raise NotImplementedError()
  784. def scalar(self, object, *multiparams, **params):
  785. """Executes and returns the first column of the first row.
  786. The underlying cursor is closed after execution.
  787. """
  788. raise NotImplementedError()
  789. def _run_visitor(self, visitorcallable, element,
  790. **kwargs):
  791. raise NotImplementedError()
  792. def _execute_clauseelement(self, elem, multiparams=None, params=None):
  793. raise NotImplementedError()
  794. class ExceptionContext(object):
  795. """Encapsulate information about an error condition in progress.
  796. This object exists solely to be passed to the
  797. :meth:`.ConnectionEvents.handle_error` event, supporting an interface that
  798. can be extended without backwards-incompatibility.
  799. .. versionadded:: 0.9.7
  800. """
  801. connection = None
  802. """The :class:`.Connection` in use during the exception.
  803. This member is present, except in the case of a failure when
  804. first connecting.
  805. .. seealso::
  806. :attr:`.ExceptionContext.engine`
  807. """
  808. engine = None
  809. """The :class:`.Engine` in use during the exception.
  810. This member should always be present, even in the case of a failure
  811. when first connecting.
  812. .. versionadded:: 1.0.0
  813. """
  814. cursor = None
  815. """The DBAPI cursor object.
  816. May be None.
  817. """
  818. statement = None
  819. """String SQL statement that was emitted directly to the DBAPI.
  820. May be None.
  821. """
  822. parameters = None
  823. """Parameter collection that was emitted directly to the DBAPI.
  824. May be None.
  825. """
  826. original_exception = None
  827. """The exception object which was caught.
  828. This member is always present.
  829. """
  830. sqlalchemy_exception = None
  831. """The :class:`sqlalchemy.exc.StatementError` which wraps the original,
  832. and will be raised if exception handling is not circumvented by the event.
  833. May be None, as not all exception types are wrapped by SQLAlchemy.
  834. For DBAPI-level exceptions that subclass the dbapi's Error class, this
  835. field will always be present.
  836. """
  837. chained_exception = None
  838. """The exception that was returned by the previous handler in the
  839. exception chain, if any.
  840. If present, this exception will be the one ultimately raised by
  841. SQLAlchemy unless a subsequent handler replaces it.
  842. May be None.
  843. """
  844. execution_context = None
  845. """The :class:`.ExecutionContext` corresponding to the execution
  846. operation in progress.
  847. This is present for statement execution operations, but not for
  848. operations such as transaction begin/end. It also is not present when
  849. the exception was raised before the :class:`.ExecutionContext`
  850. could be constructed.
  851. Note that the :attr:`.ExceptionContext.statement` and
  852. :attr:`.ExceptionContext.parameters` members may represent a
  853. different value than that of the :class:`.ExecutionContext`,
  854. potentially in the case where a
  855. :meth:`.ConnectionEvents.before_cursor_execute` event or similar
  856. modified the statement/parameters to be sent.
  857. May be None.
  858. """
  859. is_disconnect = None
  860. """Represent whether the exception as occurred represents a "disconnect"
  861. condition.
  862. This flag will always be True or False within the scope of the
  863. :meth:`.ConnectionEvents.handle_error` handler.
  864. SQLAlchemy will defer to this flag in order to determine whether or not
  865. the connection should be invalidated subsequently. That is, by
  866. assigning to this flag, a "disconnect" event which then results in
  867. a connection and pool invalidation can be invoked or prevented by
  868. changing this flag.
  869. """
  870. invalidate_pool_on_disconnect = True
  871. """Represent whether all connections in the pool should be invalidated
  872. when a "disconnect" condition is in effect.
  873. Setting this flag to False within the scope of the
  874. :meth:`.ConnectionEvents.handle_error` event will have the effect such
  875. that the full collection of connections in the pool will not be
  876. invalidated during a disconnect; only the current connection that is the
  877. subject of the error will actually be invalidated.
  878. The purpose of this flag is for custom disconnect-handling schemes where
  879. the invalidation of other connections in the pool is to be performed
  880. based on other conditions, or even on a per-connection basis.
  881. .. versionadded:: 1.0.3
  882. """