base.py 120 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339
  1. # engine/base.py
  2. # Copyright (C) 2005-2022 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
  7. from __future__ import with_statement
  8. import contextlib
  9. import sys
  10. from .interfaces import Connectable
  11. from .interfaces import ExceptionContext
  12. from .util import _distill_params
  13. from .util import _distill_params_20
  14. from .util import TransactionalContext
  15. from .. import exc
  16. from .. import inspection
  17. from .. import log
  18. from .. import util
  19. from ..sql import compiler
  20. from ..sql import util as sql_util
  21. """Defines :class:`_engine.Connection` and :class:`_engine.Engine`.
  22. """
  23. _EMPTY_EXECUTION_OPTS = util.immutabledict()
  24. class Connection(Connectable):
  25. """Provides high-level functionality for a wrapped DB-API connection.
  26. **This is the SQLAlchemy 1.x.x version** of the :class:`_engine.Connection`
  27. class. For the :term:`2.0 style` version, which features some API
  28. differences, see :class:`_future.Connection`.
  29. The :class:`_engine.Connection` object is procured by calling
  30. the :meth:`_engine.Engine.connect` method of the :class:`_engine.Engine`
  31. object, and provides services for execution of SQL statements as well
  32. as transaction control.
  33. The Connection object is **not** thread-safe. While a Connection can be
  34. shared among threads using properly synchronized access, it is still
  35. possible that the underlying DBAPI connection may not support shared
  36. access between threads. Check the DBAPI documentation for details.
  37. The Connection object represents a single DBAPI connection checked out
  38. from the connection pool. In this state, the connection pool has no affect
  39. upon the connection, including its expiration or timeout state. For the
  40. connection pool to properly manage connections, connections should be
  41. returned to the connection pool (i.e. ``connection.close()``) whenever the
  42. connection is not in use.
  43. .. index::
  44. single: thread safety; Connection
  45. """
  46. _is_future = False
  47. _sqla_logger_namespace = "sqlalchemy.engine.Connection"
  48. # used by sqlalchemy.engine.util.TransactionalContext
  49. _trans_context_manager = None
  50. def __init__(
  51. self,
  52. engine,
  53. connection=None,
  54. close_with_result=False,
  55. _branch_from=None,
  56. _execution_options=None,
  57. _dispatch=None,
  58. _has_events=None,
  59. _allow_revalidate=True,
  60. ):
  61. """Construct a new Connection."""
  62. self.engine = engine
  63. self.dialect = engine.dialect
  64. self.__branch_from = _branch_from
  65. if _branch_from:
  66. # branching is always "from" the root connection
  67. assert _branch_from.__branch_from is None
  68. self._dbapi_connection = connection
  69. self._execution_options = _execution_options
  70. self._echo = _branch_from._echo
  71. self.should_close_with_result = False
  72. self.dispatch = _dispatch
  73. self._has_events = _branch_from._has_events
  74. else:
  75. self._dbapi_connection = (
  76. connection
  77. if connection is not None
  78. else engine.raw_connection()
  79. )
  80. self._transaction = self._nested_transaction = None
  81. self.__savepoint_seq = 0
  82. self.__in_begin = False
  83. self.should_close_with_result = close_with_result
  84. self.__can_reconnect = _allow_revalidate
  85. self._echo = self.engine._should_log_info()
  86. if _has_events is None:
  87. # if _has_events is sent explicitly as False,
  88. # then don't join the dispatch of the engine; we don't
  89. # want to handle any of the engine's events in that case.
  90. self.dispatch = self.dispatch._join(engine.dispatch)
  91. self._has_events = _has_events or (
  92. _has_events is None and engine._has_events
  93. )
  94. assert not _execution_options
  95. self._execution_options = engine._execution_options
  96. if self._has_events or self.engine._has_events:
  97. self.dispatch.engine_connect(self, _branch_from is not None)
  98. @util.memoized_property
  99. def _message_formatter(self):
  100. if "logging_token" in self._execution_options:
  101. token = self._execution_options["logging_token"]
  102. return lambda msg: "[%s] %s" % (token, msg)
  103. else:
  104. return None
  105. def _log_info(self, message, *arg, **kw):
  106. fmt = self._message_formatter
  107. if fmt:
  108. message = fmt(message)
  109. self.engine.logger.info(message, *arg, **kw)
  110. def _log_debug(self, message, *arg, **kw):
  111. fmt = self._message_formatter
  112. if fmt:
  113. message = fmt(message)
  114. self.engine.logger.debug(message, *arg, **kw)
  115. @property
  116. def _schema_translate_map(self):
  117. return self._execution_options.get("schema_translate_map", None)
  118. def schema_for_object(self, obj):
  119. """Return the schema name for the given schema item taking into
  120. account current schema translate map.
  121. """
  122. name = obj.schema
  123. schema_translate_map = self._execution_options.get(
  124. "schema_translate_map", None
  125. )
  126. if (
  127. schema_translate_map
  128. and name in schema_translate_map
  129. and obj._use_schema_map
  130. ):
  131. return schema_translate_map[name]
  132. else:
  133. return name
  134. def _branch(self):
  135. """Return a new Connection which references this Connection's
  136. engine and connection; but does not have close_with_result enabled,
  137. and also whose close() method does nothing.
  138. .. deprecated:: 1.4 the "branching" concept will be removed in
  139. SQLAlchemy 2.0 as well as the "Connection.connect()" method which
  140. is the only consumer for this.
  141. The Core uses this very sparingly, only in the case of
  142. custom SQL default functions that are to be INSERTed as the
  143. primary key of a row where we need to get the value back, so we have
  144. to invoke it distinctly - this is a very uncommon case.
  145. Userland code accesses _branch() when the connect()
  146. method is called. The branched connection
  147. acts as much as possible like the parent, except that it stays
  148. connected when a close() event occurs.
  149. """
  150. return self.engine._connection_cls(
  151. self.engine,
  152. self._dbapi_connection,
  153. _branch_from=self.__branch_from if self.__branch_from else self,
  154. _execution_options=self._execution_options,
  155. _has_events=self._has_events,
  156. _dispatch=self.dispatch,
  157. )
  158. def _generate_for_options(self):
  159. """define connection method chaining behavior for execution_options"""
  160. if self._is_future:
  161. return self
  162. else:
  163. c = self.__class__.__new__(self.__class__)
  164. c.__dict__ = self.__dict__.copy()
  165. return c
  166. def __enter__(self):
  167. return self
  168. def __exit__(self, type_, value, traceback):
  169. self.close()
  170. def execution_options(self, **opt):
  171. r""" Set non-SQL options for the connection which take effect
  172. during execution.
  173. For a "future" style connection, this method returns this same
  174. :class:`_future.Connection` object with the new options added.
  175. For a legacy connection, this method returns a copy of this
  176. :class:`_engine.Connection` which references the same underlying DBAPI
  177. connection, but also defines the given execution options which will
  178. take effect for a call to
  179. :meth:`execute`. As the new :class:`_engine.Connection` references the
  180. same underlying resource, it's usually a good idea to ensure that
  181. the copies will be discarded immediately, which is implicit if used
  182. as in::
  183. result = connection.execution_options(stream_results=True).\
  184. execute(stmt)
  185. Note that any key/value can be passed to
  186. :meth:`_engine.Connection.execution_options`,
  187. and it will be stored in the
  188. ``_execution_options`` dictionary of the :class:`_engine.Connection`.
  189. It
  190. is suitable for usage by end-user schemes to communicate with
  191. event listeners, for example.
  192. The keywords that are currently recognized by SQLAlchemy itself
  193. include all those listed under :meth:`.Executable.execution_options`,
  194. as well as others that are specific to :class:`_engine.Connection`.
  195. :param autocommit: Available on: Connection, statement.
  196. When True, a COMMIT will be invoked after execution
  197. when executed in 'autocommit' mode, i.e. when an explicit
  198. transaction is not begun on the connection. Note that this
  199. is **library level, not DBAPI level autocommit**. The DBAPI
  200. connection will remain in a real transaction unless the
  201. "AUTOCOMMIT" isolation level is used.
  202. .. deprecated:: 1.4 The "autocommit" execution option is deprecated
  203. and will be removed in SQLAlchemy 2.0. See
  204. :ref:`migration_20_autocommit` for discussion.
  205. :param compiled_cache: Available on: Connection.
  206. A dictionary where :class:`.Compiled` objects
  207. will be cached when the :class:`_engine.Connection`
  208. compiles a clause
  209. expression into a :class:`.Compiled` object. This dictionary will
  210. supersede the statement cache that may be configured on the
  211. :class:`_engine.Engine` itself. If set to None, caching
  212. is disabled, even if the engine has a configured cache size.
  213. Note that the ORM makes use of its own "compiled" caches for
  214. some operations, including flush operations. The caching
  215. used by the ORM internally supersedes a cache dictionary
  216. specified here.
  217. :param logging_token: Available on: :class:`_engine.Connection`,
  218. :class:`_engine.Engine`.
  219. Adds the specified string token surrounded by brackets in log
  220. messages logged by the connection, i.e. the logging that's enabled
  221. either via the :paramref:`_sa.create_engine.echo` flag or via the
  222. ``logging.getLogger("sqlalchemy.engine")`` logger. This allows a
  223. per-connection or per-sub-engine token to be available which is
  224. useful for debugging concurrent connection scenarios.
  225. .. versionadded:: 1.4.0b2
  226. .. seealso::
  227. :ref:`dbengine_logging_tokens` - usage example
  228. :paramref:`_sa.create_engine.logging_name` - adds a name to the
  229. name used by the Python logger object itself.
  230. :param isolation_level: Available on: :class:`_engine.Connection`.
  231. Set the transaction isolation level for the lifespan of this
  232. :class:`_engine.Connection` object.
  233. Valid values include those string
  234. values accepted by the :paramref:`_sa.create_engine.isolation_level`
  235. parameter passed to :func:`_sa.create_engine`. These levels are
  236. semi-database specific; see individual dialect documentation for
  237. valid levels.
  238. The isolation level option applies the isolation level by emitting
  239. statements on the DBAPI connection, and **necessarily affects the
  240. original Connection object overall**, not just the copy that is
  241. returned by the call to :meth:`_engine.Connection.execution_options`
  242. method. The isolation level will remain at the given setting until
  243. the DBAPI connection itself is returned to the connection pool, i.e.
  244. the :meth:`_engine.Connection.close` method on the original
  245. :class:`_engine.Connection` is called,
  246. where an event handler will emit
  247. additional statements on the DBAPI connection in order to revert the
  248. isolation level change.
  249. .. warning:: The ``isolation_level`` execution option should
  250. **not** be used when a transaction is already established, that
  251. is, the :meth:`_engine.Connection.begin`
  252. method or similar has been
  253. called. A database cannot change the isolation level on a
  254. transaction in progress, and different DBAPIs and/or
  255. SQLAlchemy dialects may implicitly roll back or commit
  256. the transaction, or not affect the connection at all.
  257. .. note:: The ``isolation_level`` execution option is implicitly
  258. reset if the :class:`_engine.Connection` is invalidated, e.g. via
  259. the :meth:`_engine.Connection.invalidate` method, or if a
  260. disconnection error occurs. The new connection produced after
  261. the invalidation will not have the isolation level re-applied
  262. to it automatically.
  263. .. seealso::
  264. :paramref:`_sa.create_engine.isolation_level`
  265. - set per :class:`_engine.Engine` isolation level
  266. :meth:`_engine.Connection.get_isolation_level`
  267. - view current level
  268. :ref:`SQLite Transaction Isolation <sqlite_isolation_level>`
  269. :ref:`PostgreSQL Transaction Isolation <postgresql_isolation_level>`
  270. :ref:`MySQL Transaction Isolation <mysql_isolation_level>`
  271. :ref:`SQL Server Transaction Isolation <mssql_isolation_level>`
  272. :ref:`session_transaction_isolation` - for the ORM
  273. :param no_parameters: When ``True``, if the final parameter
  274. list or dictionary is totally empty, will invoke the
  275. statement on the cursor as ``cursor.execute(statement)``,
  276. not passing the parameter collection at all.
  277. Some DBAPIs such as psycopg2 and mysql-python consider
  278. percent signs as significant only when parameters are
  279. present; this option allows code to generate SQL
  280. containing percent signs (and possibly other characters)
  281. that is neutral regarding whether it's executed by the DBAPI
  282. or piped into a script that's later invoked by
  283. command line tools.
  284. :param stream_results: Available on: Connection, statement.
  285. Indicate to the dialect that results should be
  286. "streamed" and not pre-buffered, if possible. This is a limitation
  287. of many DBAPIs. The flag is currently understood within a subset
  288. of dialects within the PostgreSQL and MySQL categories, and
  289. may be supported by other third party dialects as well.
  290. .. seealso::
  291. :ref:`engine_stream_results`
  292. :param schema_translate_map: Available on: Connection, Engine.
  293. A dictionary mapping schema names to schema names, that will be
  294. applied to the :paramref:`_schema.Table.schema` element of each
  295. :class:`_schema.Table`
  296. encountered when SQL or DDL expression elements
  297. are compiled into strings; the resulting schema name will be
  298. converted based on presence in the map of the original name.
  299. .. versionadded:: 1.1
  300. .. seealso::
  301. :ref:`schema_translating`
  302. .. seealso::
  303. :meth:`_engine.Engine.execution_options`
  304. :meth:`.Executable.execution_options`
  305. :meth:`_engine.Connection.get_execution_options`
  306. """ # noqa
  307. c = self._generate_for_options()
  308. c._execution_options = c._execution_options.union(opt)
  309. if self._has_events or self.engine._has_events:
  310. self.dispatch.set_connection_execution_options(c, opt)
  311. self.dialect.set_connection_execution_options(c, opt)
  312. return c
  313. def get_execution_options(self):
  314. """Get the non-SQL options which will take effect during execution.
  315. .. versionadded:: 1.3
  316. .. seealso::
  317. :meth:`_engine.Connection.execution_options`
  318. """
  319. return self._execution_options
  320. @property
  321. def closed(self):
  322. """Return True if this connection is closed."""
  323. # note this is independent for a "branched" connection vs.
  324. # the base
  325. return self._dbapi_connection is None and not self.__can_reconnect
  326. @property
  327. def invalidated(self):
  328. """Return True if this connection was invalidated."""
  329. # prior to 1.4, "invalid" was stored as a state independent of
  330. # "closed", meaning an invalidated connection could be "closed",
  331. # the _dbapi_connection would be None and closed=True, yet the
  332. # "invalid" flag would stay True. This meant that there were
  333. # three separate states (open/valid, closed/valid, closed/invalid)
  334. # when there is really no reason for that; a connection that's
  335. # "closed" does not need to be "invalid". So the state is now
  336. # represented by the two facts alone.
  337. if self.__branch_from:
  338. return self.__branch_from.invalidated
  339. return self._dbapi_connection is None and not self.closed
  340. @property
  341. def connection(self):
  342. """The underlying DB-API connection managed by this Connection.
  343. This is a SQLAlchemy connection-pool proxied connection
  344. which then has the attribute
  345. :attr:`_pool._ConnectionFairy.dbapi_connection` that refers to the
  346. actual driver connection.
  347. .. seealso::
  348. :ref:`dbapi_connections`
  349. """
  350. if self._dbapi_connection is None:
  351. try:
  352. return self._revalidate_connection()
  353. except (exc.PendingRollbackError, exc.ResourceClosedError):
  354. raise
  355. except BaseException as e:
  356. self._handle_dbapi_exception(e, None, None, None, None)
  357. else:
  358. return self._dbapi_connection
  359. def get_isolation_level(self):
  360. """Return the current isolation level assigned to this
  361. :class:`_engine.Connection`.
  362. This will typically be the default isolation level as determined
  363. by the dialect, unless if the
  364. :paramref:`.Connection.execution_options.isolation_level`
  365. feature has been used to alter the isolation level on a
  366. per-:class:`_engine.Connection` basis.
  367. This attribute will typically perform a live SQL operation in order
  368. to procure the current isolation level, so the value returned is the
  369. actual level on the underlying DBAPI connection regardless of how
  370. this state was set. Compare to the
  371. :attr:`_engine.Connection.default_isolation_level` accessor
  372. which returns the dialect-level setting without performing a SQL
  373. query.
  374. .. versionadded:: 0.9.9
  375. .. seealso::
  376. :attr:`_engine.Connection.default_isolation_level`
  377. - view default level
  378. :paramref:`_sa.create_engine.isolation_level`
  379. - set per :class:`_engine.Engine` isolation level
  380. :paramref:`.Connection.execution_options.isolation_level`
  381. - set per :class:`_engine.Connection` isolation level
  382. """
  383. try:
  384. return self.dialect.get_isolation_level(self.connection)
  385. except BaseException as e:
  386. self._handle_dbapi_exception(e, None, None, None, None)
  387. @property
  388. def default_isolation_level(self):
  389. """The default isolation level assigned to this
  390. :class:`_engine.Connection`.
  391. This is the isolation level setting that the
  392. :class:`_engine.Connection`
  393. has when first procured via the :meth:`_engine.Engine.connect` method.
  394. This level stays in place until the
  395. :paramref:`.Connection.execution_options.isolation_level` is used
  396. to change the setting on a per-:class:`_engine.Connection` basis.
  397. Unlike :meth:`_engine.Connection.get_isolation_level`,
  398. this attribute is set
  399. ahead of time from the first connection procured by the dialect,
  400. so SQL query is not invoked when this accessor is called.
  401. .. versionadded:: 0.9.9
  402. .. seealso::
  403. :meth:`_engine.Connection.get_isolation_level`
  404. - view current level
  405. :paramref:`_sa.create_engine.isolation_level`
  406. - set per :class:`_engine.Engine` isolation level
  407. :paramref:`.Connection.execution_options.isolation_level`
  408. - set per :class:`_engine.Connection` isolation level
  409. """
  410. return self.dialect.default_isolation_level
  411. def _invalid_transaction(self):
  412. if self.invalidated:
  413. raise exc.PendingRollbackError(
  414. "Can't reconnect until invalid %stransaction is rolled "
  415. "back."
  416. % (
  417. "savepoint "
  418. if self._nested_transaction is not None
  419. else ""
  420. ),
  421. code="8s2b",
  422. )
  423. else:
  424. assert not self._is_future
  425. raise exc.PendingRollbackError(
  426. "This connection is on an inactive %stransaction. "
  427. "Please rollback() fully before proceeding."
  428. % (
  429. "savepoint "
  430. if self._nested_transaction is not None
  431. else ""
  432. ),
  433. code="8s2a",
  434. )
  435. def _revalidate_connection(self):
  436. if self.__branch_from:
  437. return self.__branch_from._revalidate_connection()
  438. if self.__can_reconnect and self.invalidated:
  439. if self._transaction is not None:
  440. self._invalid_transaction()
  441. self._dbapi_connection = self.engine.raw_connection(
  442. _connection=self
  443. )
  444. return self._dbapi_connection
  445. raise exc.ResourceClosedError("This Connection is closed")
  446. @property
  447. def _still_open_and_dbapi_connection_is_valid(self):
  448. return self._dbapi_connection is not None and getattr(
  449. self._dbapi_connection, "is_valid", False
  450. )
  451. @property
  452. def info(self):
  453. """Info dictionary associated with the underlying DBAPI connection
  454. referred to by this :class:`_engine.Connection`, allowing user-defined
  455. data to be associated with the connection.
  456. The data here will follow along with the DBAPI connection including
  457. after it is returned to the connection pool and used again
  458. in subsequent instances of :class:`_engine.Connection`.
  459. """
  460. return self.connection.info
  461. @util.deprecated_20(":meth:`.Connection.connect`")
  462. def connect(self, close_with_result=False):
  463. """Returns a branched version of this :class:`_engine.Connection`.
  464. The :meth:`_engine.Connection.close` method on the returned
  465. :class:`_engine.Connection` can be called and this
  466. :class:`_engine.Connection` will remain open.
  467. This method provides usage symmetry with
  468. :meth:`_engine.Engine.connect`, including for usage
  469. with context managers.
  470. """
  471. return self._branch()
  472. def invalidate(self, exception=None):
  473. """Invalidate the underlying DBAPI connection associated with
  474. this :class:`_engine.Connection`.
  475. An attempt will be made to close the underlying DBAPI connection
  476. immediately; however if this operation fails, the error is logged
  477. but not raised. The connection is then discarded whether or not
  478. close() succeeded.
  479. Upon the next use (where "use" typically means using the
  480. :meth:`_engine.Connection.execute` method or similar),
  481. this :class:`_engine.Connection` will attempt to
  482. procure a new DBAPI connection using the services of the
  483. :class:`_pool.Pool` as a source of connectivity (e.g.
  484. a "reconnection").
  485. If a transaction was in progress (e.g. the
  486. :meth:`_engine.Connection.begin` method has been called) when
  487. :meth:`_engine.Connection.invalidate` method is called, at the DBAPI
  488. level all state associated with this transaction is lost, as
  489. the DBAPI connection is closed. The :class:`_engine.Connection`
  490. will not allow a reconnection to proceed until the
  491. :class:`.Transaction` object is ended, by calling the
  492. :meth:`.Transaction.rollback` method; until that point, any attempt at
  493. continuing to use the :class:`_engine.Connection` will raise an
  494. :class:`~sqlalchemy.exc.InvalidRequestError`.
  495. This is to prevent applications from accidentally
  496. continuing an ongoing transactional operations despite the
  497. fact that the transaction has been lost due to an
  498. invalidation.
  499. The :meth:`_engine.Connection.invalidate` method,
  500. just like auto-invalidation,
  501. will at the connection pool level invoke the
  502. :meth:`_events.PoolEvents.invalidate` event.
  503. :param exception: an optional ``Exception`` instance that's the
  504. reason for the invalidation. is passed along to event handlers
  505. and logging functions.
  506. .. seealso::
  507. :ref:`pool_connection_invalidation`
  508. """
  509. if self.__branch_from:
  510. return self.__branch_from.invalidate(exception=exception)
  511. if self.invalidated:
  512. return
  513. if self.closed:
  514. raise exc.ResourceClosedError("This Connection is closed")
  515. if self._still_open_and_dbapi_connection_is_valid:
  516. self._dbapi_connection.invalidate(exception)
  517. self._dbapi_connection = None
  518. def detach(self):
  519. """Detach the underlying DB-API connection from its connection pool.
  520. E.g.::
  521. with engine.connect() as conn:
  522. conn.detach()
  523. conn.execute(text("SET search_path TO schema1, schema2"))
  524. # work with connection
  525. # connection is fully closed (since we used "with:", can
  526. # also call .close())
  527. This :class:`_engine.Connection` instance will remain usable.
  528. When closed
  529. (or exited from a context manager context as above),
  530. the DB-API connection will be literally closed and not
  531. returned to its originating pool.
  532. This method can be used to insulate the rest of an application
  533. from a modified state on a connection (such as a transaction
  534. isolation level or similar).
  535. """
  536. self._dbapi_connection.detach()
  537. def _autobegin(self):
  538. self.begin()
  539. def begin(self):
  540. """Begin a transaction and return a transaction handle.
  541. The returned object is an instance of :class:`.Transaction`.
  542. This object represents the "scope" of the transaction,
  543. which completes when either the :meth:`.Transaction.rollback`
  544. or :meth:`.Transaction.commit` method is called.
  545. .. tip::
  546. The :meth:`_engine.Connection.begin` method is invoked when using
  547. the :meth:`_engine.Engine.begin` context manager method as well.
  548. All documentation that refers to behaviors specific to the
  549. :meth:`_engine.Connection.begin` method also apply to use of the
  550. :meth:`_engine.Engine.begin` method.
  551. Legacy use: nested calls to :meth:`.begin` on the same
  552. :class:`_engine.Connection` will return new :class:`.Transaction`
  553. objects that represent an emulated transaction within the scope of the
  554. enclosing transaction, that is::
  555. trans = conn.begin() # outermost transaction
  556. trans2 = conn.begin() # "nested"
  557. trans2.commit() # does nothing
  558. trans.commit() # actually commits
  559. Calls to :meth:`.Transaction.commit` only have an effect
  560. when invoked via the outermost :class:`.Transaction` object, though the
  561. :meth:`.Transaction.rollback` method of any of the
  562. :class:`.Transaction` objects will roll back the
  563. transaction.
  564. .. tip::
  565. The above "nesting" behavior is a legacy behavior specific to
  566. :term:`1.x style` use and will be removed in SQLAlchemy 2.0. For
  567. notes on :term:`2.0 style` use, see
  568. :meth:`_future.Connection.begin`.
  569. .. seealso::
  570. :meth:`_engine.Connection.begin_nested` - use a SAVEPOINT
  571. :meth:`_engine.Connection.begin_twophase` -
  572. use a two phase /XID transaction
  573. :meth:`_engine.Engine.begin` - context manager available from
  574. :class:`_engine.Engine`
  575. """
  576. if self._is_future:
  577. assert not self.__branch_from
  578. elif self.__branch_from:
  579. return self.__branch_from.begin()
  580. if self.__in_begin:
  581. # for dialects that emit SQL within the process of
  582. # dialect.do_begin() or dialect.do_begin_twophase(), this
  583. # flag prevents "autobegin" from being emitted within that
  584. # process, while allowing self._transaction to remain at None
  585. # until it's complete.
  586. return
  587. elif self._transaction is None:
  588. self._transaction = RootTransaction(self)
  589. return self._transaction
  590. else:
  591. if self._is_future:
  592. raise exc.InvalidRequestError(
  593. "This connection has already initialized a SQLAlchemy "
  594. "Transaction() object via begin() or autobegin; can't "
  595. "call begin() here unless rollback() or commit() "
  596. "is called first."
  597. )
  598. else:
  599. return MarkerTransaction(self)
  600. def begin_nested(self):
  601. """Begin a nested transaction (i.e. SAVEPOINT) and return a
  602. transaction handle, assuming an outer transaction is already
  603. established.
  604. Nested transactions require SAVEPOINT support in the
  605. underlying database. Any transaction in the hierarchy may
  606. ``commit`` and ``rollback``, however the outermost transaction
  607. still controls the overall ``commit`` or ``rollback`` of the
  608. transaction of a whole.
  609. The legacy form of :meth:`_engine.Connection.begin_nested` method has
  610. alternate behaviors based on whether or not the
  611. :meth:`_engine.Connection.begin` method was called previously. If
  612. :meth:`_engine.Connection.begin` was not called, then this method will
  613. behave the same as the :meth:`_engine.Connection.begin` method and
  614. return a :class:`.RootTransaction` object that begins and commits a
  615. real transaction - **no savepoint is invoked**. If
  616. :meth:`_engine.Connection.begin` **has** been called, and a
  617. :class:`.RootTransaction` is already established, then this method
  618. returns an instance of :class:`.NestedTransaction` which will invoke
  619. and manage the scope of a SAVEPOINT.
  620. .. tip::
  621. The above mentioned behavior of
  622. :meth:`_engine.Connection.begin_nested` is a legacy behavior
  623. specific to :term:`1.x style` use. In :term:`2.0 style` use, the
  624. :meth:`_future.Connection.begin_nested` method instead autobegins
  625. the outer transaction that can be committed using
  626. "commit-as-you-go" style; see
  627. :meth:`_future.Connection.begin_nested` for migration details.
  628. .. versionchanged:: 1.4.13 The behavior of
  629. :meth:`_engine.Connection.begin_nested`
  630. as returning a :class:`.RootTransaction` if
  631. :meth:`_engine.Connection.begin` were not called has been restored
  632. as was the case in 1.3.x versions; in previous 1.4.x versions, an
  633. outer transaction would be "autobegun" but would not be committed.
  634. .. seealso::
  635. :meth:`_engine.Connection.begin`
  636. :meth:`_engine.Connection.begin_twophase`
  637. """
  638. if self._is_future:
  639. assert not self.__branch_from
  640. elif self.__branch_from:
  641. return self.__branch_from.begin_nested()
  642. if self._transaction is None:
  643. if not self._is_future:
  644. util.warn_deprecated_20(
  645. "Calling Connection.begin_nested() in 2.0 style use will "
  646. "return a NestedTransaction (SAVEPOINT) in all cases, "
  647. "that will not commit the outer transaction. For code "
  648. "that is cross-compatible between 1.x and 2.0 style use, "
  649. "ensure Connection.begin() is called before calling "
  650. "Connection.begin_nested()."
  651. )
  652. return self.begin()
  653. else:
  654. self._autobegin()
  655. return NestedTransaction(self)
  656. def begin_twophase(self, xid=None):
  657. """Begin a two-phase or XA transaction and return a transaction
  658. handle.
  659. The returned object is an instance of :class:`.TwoPhaseTransaction`,
  660. which in addition to the methods provided by
  661. :class:`.Transaction`, also provides a
  662. :meth:`~.TwoPhaseTransaction.prepare` method.
  663. :param xid: the two phase transaction id. If not supplied, a
  664. random id will be generated.
  665. .. seealso::
  666. :meth:`_engine.Connection.begin`
  667. :meth:`_engine.Connection.begin_twophase`
  668. """
  669. if self.__branch_from:
  670. return self.__branch_from.begin_twophase(xid=xid)
  671. if self._transaction is not None:
  672. raise exc.InvalidRequestError(
  673. "Cannot start a two phase transaction when a transaction "
  674. "is already in progress."
  675. )
  676. if xid is None:
  677. xid = self.engine.dialect.create_xid()
  678. return TwoPhaseTransaction(self, xid)
  679. def recover_twophase(self):
  680. return self.engine.dialect.do_recover_twophase(self)
  681. def rollback_prepared(self, xid, recover=False):
  682. self.engine.dialect.do_rollback_twophase(self, xid, recover=recover)
  683. def commit_prepared(self, xid, recover=False):
  684. self.engine.dialect.do_commit_twophase(self, xid, recover=recover)
  685. def in_transaction(self):
  686. """Return True if a transaction is in progress."""
  687. if self.__branch_from is not None:
  688. return self.__branch_from.in_transaction()
  689. return self._transaction is not None and self._transaction.is_active
  690. def in_nested_transaction(self):
  691. """Return True if a transaction is in progress."""
  692. if self.__branch_from is not None:
  693. return self.__branch_from.in_nested_transaction()
  694. return (
  695. self._nested_transaction is not None
  696. and self._nested_transaction.is_active
  697. )
  698. def _is_autocommit(self):
  699. return (
  700. self._execution_options.get("isolation_level", None)
  701. == "AUTOCOMMIT"
  702. )
  703. def get_transaction(self):
  704. """Return the current root transaction in progress, if any.
  705. .. versionadded:: 1.4
  706. """
  707. if self.__branch_from is not None:
  708. return self.__branch_from.get_transaction()
  709. return self._transaction
  710. def get_nested_transaction(self):
  711. """Return the current nested transaction in progress, if any.
  712. .. versionadded:: 1.4
  713. """
  714. if self.__branch_from is not None:
  715. return self.__branch_from.get_nested_transaction()
  716. return self._nested_transaction
  717. def _begin_impl(self, transaction):
  718. assert not self.__branch_from
  719. if self._echo:
  720. self._log_info("BEGIN (implicit)")
  721. self.__in_begin = True
  722. if self._has_events or self.engine._has_events:
  723. self.dispatch.begin(self)
  724. try:
  725. self.engine.dialect.do_begin(self.connection)
  726. except BaseException as e:
  727. self._handle_dbapi_exception(e, None, None, None, None)
  728. finally:
  729. self.__in_begin = False
  730. def _rollback_impl(self):
  731. assert not self.__branch_from
  732. if self._has_events or self.engine._has_events:
  733. self.dispatch.rollback(self)
  734. if self._still_open_and_dbapi_connection_is_valid:
  735. if self._echo:
  736. if self._is_autocommit():
  737. self._log_info(
  738. "ROLLBACK using DBAPI connection.rollback(), "
  739. "DBAPI should ignore due to autocommit mode"
  740. )
  741. else:
  742. self._log_info("ROLLBACK")
  743. try:
  744. self.engine.dialect.do_rollback(self.connection)
  745. except BaseException as e:
  746. self._handle_dbapi_exception(e, None, None, None, None)
  747. def _commit_impl(self, autocommit=False):
  748. assert not self.__branch_from
  749. # AUTOCOMMIT isolation-level is a dialect-specific concept, however
  750. # if a connection has this set as the isolation level, we can skip
  751. # the "autocommit" warning as the operation will do "autocommit"
  752. # in any case
  753. if autocommit and not self._is_autocommit():
  754. util.warn_deprecated_20(
  755. "The current statement is being autocommitted using "
  756. "implicit autocommit, which will be removed in "
  757. "SQLAlchemy 2.0. "
  758. "Use the .begin() method of Engine or Connection in order to "
  759. "use an explicit transaction for DML and DDL statements."
  760. )
  761. if self._has_events or self.engine._has_events:
  762. self.dispatch.commit(self)
  763. if self._echo:
  764. if self._is_autocommit():
  765. self._log_info(
  766. "COMMIT using DBAPI connection.commit(), "
  767. "DBAPI should ignore due to autocommit mode"
  768. )
  769. else:
  770. self._log_info("COMMIT")
  771. try:
  772. self.engine.dialect.do_commit(self.connection)
  773. except BaseException as e:
  774. self._handle_dbapi_exception(e, None, None, None, None)
  775. def _savepoint_impl(self, name=None):
  776. assert not self.__branch_from
  777. if self._has_events or self.engine._has_events:
  778. self.dispatch.savepoint(self, name)
  779. if name is None:
  780. self.__savepoint_seq += 1
  781. name = "sa_savepoint_%s" % self.__savepoint_seq
  782. if self._still_open_and_dbapi_connection_is_valid:
  783. self.engine.dialect.do_savepoint(self, name)
  784. return name
  785. def _rollback_to_savepoint_impl(self, name):
  786. assert not self.__branch_from
  787. if self._has_events or self.engine._has_events:
  788. self.dispatch.rollback_savepoint(self, name, None)
  789. if self._still_open_and_dbapi_connection_is_valid:
  790. self.engine.dialect.do_rollback_to_savepoint(self, name)
  791. def _release_savepoint_impl(self, name):
  792. assert not self.__branch_from
  793. if self._has_events or self.engine._has_events:
  794. self.dispatch.release_savepoint(self, name, None)
  795. if self._still_open_and_dbapi_connection_is_valid:
  796. self.engine.dialect.do_release_savepoint(self, name)
  797. def _begin_twophase_impl(self, transaction):
  798. assert not self.__branch_from
  799. if self._echo:
  800. self._log_info("BEGIN TWOPHASE (implicit)")
  801. if self._has_events or self.engine._has_events:
  802. self.dispatch.begin_twophase(self, transaction.xid)
  803. if self._still_open_and_dbapi_connection_is_valid:
  804. self.__in_begin = True
  805. try:
  806. self.engine.dialect.do_begin_twophase(self, transaction.xid)
  807. except BaseException as e:
  808. self._handle_dbapi_exception(e, None, None, None, None)
  809. finally:
  810. self.__in_begin = False
  811. def _prepare_twophase_impl(self, xid):
  812. assert not self.__branch_from
  813. if self._has_events or self.engine._has_events:
  814. self.dispatch.prepare_twophase(self, xid)
  815. if self._still_open_and_dbapi_connection_is_valid:
  816. assert isinstance(self._transaction, TwoPhaseTransaction)
  817. try:
  818. self.engine.dialect.do_prepare_twophase(self, xid)
  819. except BaseException as e:
  820. self._handle_dbapi_exception(e, None, None, None, None)
  821. def _rollback_twophase_impl(self, xid, is_prepared):
  822. assert not self.__branch_from
  823. if self._has_events or self.engine._has_events:
  824. self.dispatch.rollback_twophase(self, xid, is_prepared)
  825. if self._still_open_and_dbapi_connection_is_valid:
  826. assert isinstance(self._transaction, TwoPhaseTransaction)
  827. try:
  828. self.engine.dialect.do_rollback_twophase(
  829. self, xid, is_prepared
  830. )
  831. except BaseException as e:
  832. self._handle_dbapi_exception(e, None, None, None, None)
  833. def _commit_twophase_impl(self, xid, is_prepared):
  834. assert not self.__branch_from
  835. if self._has_events or self.engine._has_events:
  836. self.dispatch.commit_twophase(self, xid, is_prepared)
  837. if self._still_open_and_dbapi_connection_is_valid:
  838. assert isinstance(self._transaction, TwoPhaseTransaction)
  839. try:
  840. self.engine.dialect.do_commit_twophase(self, xid, is_prepared)
  841. except BaseException as e:
  842. self._handle_dbapi_exception(e, None, None, None, None)
  843. def _autorollback(self):
  844. if self.__branch_from:
  845. self.__branch_from._autorollback()
  846. if not self.in_transaction():
  847. self._rollback_impl()
  848. def _warn_for_legacy_exec_format(self):
  849. util.warn_deprecated_20(
  850. "The connection.execute() method in "
  851. "SQLAlchemy 2.0 will accept parameters as a single "
  852. "dictionary or a "
  853. "single sequence of dictionaries only. "
  854. "Parameters passed as keyword arguments, tuples or positionally "
  855. "oriented dictionaries and/or tuples "
  856. "will no longer be accepted."
  857. )
  858. def close(self):
  859. """Close this :class:`_engine.Connection`.
  860. This results in a release of the underlying database
  861. resources, that is, the DBAPI connection referenced
  862. internally. The DBAPI connection is typically restored
  863. back to the connection-holding :class:`_pool.Pool` referenced
  864. by the :class:`_engine.Engine` that produced this
  865. :class:`_engine.Connection`. Any transactional state present on
  866. the DBAPI connection is also unconditionally released via
  867. the DBAPI connection's ``rollback()`` method, regardless
  868. of any :class:`.Transaction` object that may be
  869. outstanding with regards to this :class:`_engine.Connection`.
  870. After :meth:`_engine.Connection.close` is called, the
  871. :class:`_engine.Connection` is permanently in a closed state,
  872. and will allow no further operations.
  873. """
  874. if self.__branch_from:
  875. assert not self._is_future
  876. util.warn_deprecated_20(
  877. "The .close() method on a so-called 'branched' connection is "
  878. "deprecated as of 1.4, as are 'branched' connections overall, "
  879. "and will be removed in a future release. If this is a "
  880. "default-handling function, don't close the connection."
  881. )
  882. self._dbapi_connection = None
  883. self.__can_reconnect = False
  884. return
  885. if self._transaction:
  886. self._transaction.close()
  887. skip_reset = True
  888. else:
  889. skip_reset = False
  890. if self._dbapi_connection is not None:
  891. conn = self._dbapi_connection
  892. # as we just closed the transaction, close the connection
  893. # pool connection without doing an additional reset
  894. if skip_reset:
  895. conn._close_no_reset()
  896. else:
  897. conn.close()
  898. # There is a slight chance that conn.close() may have
  899. # triggered an invalidation here in which case
  900. # _dbapi_connection would already be None, however usually
  901. # it will be non-None here and in a "closed" state.
  902. self._dbapi_connection = None
  903. self.__can_reconnect = False
  904. def scalar(self, object_, *multiparams, **params):
  905. """Executes and returns the first column of the first row.
  906. The underlying result/cursor is closed after execution.
  907. """
  908. return self.execute(object_, *multiparams, **params).scalar()
  909. def scalars(self, object_, *multiparams, **params):
  910. """Executes and returns a scalar result set, which yields scalar values
  911. from the first column of each row.
  912. This method is equivalent to calling :meth:`_engine.Connection.execute`
  913. to receive a :class:`_result.Result` object, then invoking the
  914. :meth:`_result.Result.scalars` method to produce a
  915. :class:`_result.ScalarResult` instance.
  916. :return: a :class:`_result.ScalarResult`
  917. .. versionadded:: 1.4.24
  918. """
  919. return self.execute(object_, *multiparams, **params).scalars()
  920. def execute(self, statement, *multiparams, **params):
  921. r"""Executes a SQL statement construct and returns a
  922. :class:`_engine.CursorResult`.
  923. :param statement: The statement to be executed. May be
  924. one of:
  925. * a plain string (deprecated)
  926. * any :class:`_expression.ClauseElement` construct that is also
  927. a subclass of :class:`.Executable`, such as a
  928. :func:`_expression.select` construct
  929. * a :class:`.FunctionElement`, such as that generated
  930. by :data:`.func`, will be automatically wrapped in
  931. a SELECT statement, which is then executed.
  932. * a :class:`.DDLElement` object
  933. * a :class:`.DefaultGenerator` object
  934. * a :class:`.Compiled` object
  935. .. deprecated:: 2.0 passing a string to
  936. :meth:`_engine.Connection.execute` is
  937. deprecated and will be removed in version 2.0. Use the
  938. :func:`_expression.text` construct with
  939. :meth:`_engine.Connection.execute`, or the
  940. :meth:`_engine.Connection.exec_driver_sql`
  941. method to invoke a driver-level
  942. SQL string.
  943. :param \*multiparams/\**params: represent bound parameter
  944. values to be used in the execution. Typically,
  945. the format is either a collection of one or more
  946. dictionaries passed to \*multiparams::
  947. conn.execute(
  948. table.insert(),
  949. {"id":1, "value":"v1"},
  950. {"id":2, "value":"v2"}
  951. )
  952. ...or individual key/values interpreted by \**params::
  953. conn.execute(
  954. table.insert(), id=1, value="v1"
  955. )
  956. In the case that a plain SQL string is passed, and the underlying
  957. DBAPI accepts positional bind parameters, a collection of tuples
  958. or individual values in \*multiparams may be passed::
  959. conn.execute(
  960. "INSERT INTO table (id, value) VALUES (?, ?)",
  961. (1, "v1"), (2, "v2")
  962. )
  963. conn.execute(
  964. "INSERT INTO table (id, value) VALUES (?, ?)",
  965. 1, "v1"
  966. )
  967. Note above, the usage of a question mark "?" or other
  968. symbol is contingent upon the "paramstyle" accepted by the DBAPI
  969. in use, which may be any of "qmark", "named", "pyformat", "format",
  970. "numeric". See `pep-249
  971. <https://www.python.org/dev/peps/pep-0249/>`_ for details on
  972. paramstyle.
  973. To execute a textual SQL statement which uses bound parameters in a
  974. DBAPI-agnostic way, use the :func:`_expression.text` construct.
  975. .. deprecated:: 2.0 use of tuple or scalar positional parameters
  976. is deprecated. All params should be dicts or sequences of dicts.
  977. Use :meth:`.exec_driver_sql` to execute a plain string with
  978. tuple or scalar positional parameters.
  979. """
  980. if isinstance(statement, util.string_types):
  981. util.warn_deprecated_20(
  982. "Passing a string to Connection.execute() is "
  983. "deprecated and will be removed in version 2.0. Use the "
  984. "text() construct, "
  985. "or the Connection.exec_driver_sql() method to invoke a "
  986. "driver-level SQL string."
  987. )
  988. return self._exec_driver_sql(
  989. statement,
  990. multiparams,
  991. params,
  992. _EMPTY_EXECUTION_OPTS,
  993. future=False,
  994. )
  995. try:
  996. meth = statement._execute_on_connection
  997. except AttributeError as err:
  998. util.raise_(
  999. exc.ObjectNotExecutableError(statement), replace_context=err
  1000. )
  1001. else:
  1002. return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS)
  1003. def _execute_function(self, func, multiparams, params, execution_options):
  1004. """Execute a sql.FunctionElement object."""
  1005. return self._execute_clauseelement(
  1006. func.select(), multiparams, params, execution_options
  1007. )
  1008. def _execute_default(
  1009. self,
  1010. default,
  1011. multiparams,
  1012. params,
  1013. # migrate is calling this directly :(
  1014. execution_options=_EMPTY_EXECUTION_OPTS,
  1015. ):
  1016. """Execute a schema.ColumnDefault object."""
  1017. execution_options = self._execution_options.merge_with(
  1018. execution_options
  1019. )
  1020. distilled_parameters = _distill_params(self, multiparams, params)
  1021. if self._has_events or self.engine._has_events:
  1022. (
  1023. default,
  1024. distilled_params,
  1025. event_multiparams,
  1026. event_params,
  1027. ) = self._invoke_before_exec_event(
  1028. default, distilled_parameters, execution_options
  1029. )
  1030. try:
  1031. conn = self._dbapi_connection
  1032. if conn is None:
  1033. conn = self._revalidate_connection()
  1034. dialect = self.dialect
  1035. ctx = dialect.execution_ctx_cls._init_default(
  1036. dialect, self, conn, execution_options
  1037. )
  1038. except (exc.PendingRollbackError, exc.ResourceClosedError):
  1039. raise
  1040. except BaseException as e:
  1041. self._handle_dbapi_exception(e, None, None, None, None)
  1042. ret = ctx._exec_default(None, default, None)
  1043. if self.should_close_with_result:
  1044. self.close()
  1045. if self._has_events or self.engine._has_events:
  1046. self.dispatch.after_execute(
  1047. self,
  1048. default,
  1049. event_multiparams,
  1050. event_params,
  1051. execution_options,
  1052. ret,
  1053. )
  1054. return ret
  1055. def _execute_ddl(self, ddl, multiparams, params, execution_options):
  1056. """Execute a schema.DDL object."""
  1057. execution_options = ddl._execution_options.merge_with(
  1058. self._execution_options, execution_options
  1059. )
  1060. distilled_parameters = _distill_params(self, multiparams, params)
  1061. if self._has_events or self.engine._has_events:
  1062. (
  1063. ddl,
  1064. distilled_params,
  1065. event_multiparams,
  1066. event_params,
  1067. ) = self._invoke_before_exec_event(
  1068. ddl, distilled_parameters, execution_options
  1069. )
  1070. exec_opts = self._execution_options.merge_with(execution_options)
  1071. schema_translate_map = exec_opts.get("schema_translate_map", None)
  1072. dialect = self.dialect
  1073. compiled = ddl.compile(
  1074. dialect=dialect, schema_translate_map=schema_translate_map
  1075. )
  1076. ret = self._execute_context(
  1077. dialect,
  1078. dialect.execution_ctx_cls._init_ddl,
  1079. compiled,
  1080. None,
  1081. execution_options,
  1082. compiled,
  1083. )
  1084. if self._has_events or self.engine._has_events:
  1085. self.dispatch.after_execute(
  1086. self,
  1087. ddl,
  1088. event_multiparams,
  1089. event_params,
  1090. execution_options,
  1091. ret,
  1092. )
  1093. return ret
  1094. def _invoke_before_exec_event(
  1095. self, elem, distilled_params, execution_options
  1096. ):
  1097. if len(distilled_params) == 1:
  1098. event_multiparams, event_params = [], distilled_params[0]
  1099. else:
  1100. event_multiparams, event_params = distilled_params, {}
  1101. for fn in self.dispatch.before_execute:
  1102. elem, event_multiparams, event_params = fn(
  1103. self,
  1104. elem,
  1105. event_multiparams,
  1106. event_params,
  1107. execution_options,
  1108. )
  1109. if event_multiparams:
  1110. distilled_params = list(event_multiparams)
  1111. if event_params:
  1112. raise exc.InvalidRequestError(
  1113. "Event handler can't return non-empty multiparams "
  1114. "and params at the same time"
  1115. )
  1116. elif event_params:
  1117. distilled_params = [event_params]
  1118. else:
  1119. distilled_params = []
  1120. return elem, distilled_params, event_multiparams, event_params
  1121. def _execute_clauseelement(
  1122. self, elem, multiparams, params, execution_options
  1123. ):
  1124. """Execute a sql.ClauseElement object."""
  1125. execution_options = elem._execution_options.merge_with(
  1126. self._execution_options, execution_options
  1127. )
  1128. distilled_params = _distill_params(self, multiparams, params)
  1129. has_events = self._has_events or self.engine._has_events
  1130. if has_events:
  1131. (
  1132. elem,
  1133. distilled_params,
  1134. event_multiparams,
  1135. event_params,
  1136. ) = self._invoke_before_exec_event(
  1137. elem, distilled_params, execution_options
  1138. )
  1139. if distilled_params:
  1140. # ensure we don't retain a link to the view object for keys()
  1141. # which links to the values, which we don't want to cache
  1142. keys = sorted(distilled_params[0])
  1143. for_executemany = len(distilled_params) > 1
  1144. else:
  1145. keys = []
  1146. for_executemany = False
  1147. dialect = self.dialect
  1148. schema_translate_map = execution_options.get(
  1149. "schema_translate_map", None
  1150. )
  1151. compiled_cache = execution_options.get(
  1152. "compiled_cache", self.engine._compiled_cache
  1153. )
  1154. compiled_sql, extracted_params, cache_hit = elem._compile_w_cache(
  1155. dialect=dialect,
  1156. compiled_cache=compiled_cache,
  1157. column_keys=keys,
  1158. for_executemany=for_executemany,
  1159. schema_translate_map=schema_translate_map,
  1160. linting=self.dialect.compiler_linting | compiler.WARN_LINTING,
  1161. )
  1162. ret = self._execute_context(
  1163. dialect,
  1164. dialect.execution_ctx_cls._init_compiled,
  1165. compiled_sql,
  1166. distilled_params,
  1167. execution_options,
  1168. compiled_sql,
  1169. distilled_params,
  1170. elem,
  1171. extracted_params,
  1172. cache_hit=cache_hit,
  1173. )
  1174. if has_events:
  1175. self.dispatch.after_execute(
  1176. self,
  1177. elem,
  1178. event_multiparams,
  1179. event_params,
  1180. execution_options,
  1181. ret,
  1182. )
  1183. return ret
  1184. def _execute_compiled(
  1185. self,
  1186. compiled,
  1187. multiparams,
  1188. params,
  1189. execution_options=_EMPTY_EXECUTION_OPTS,
  1190. ):
  1191. """Execute a sql.Compiled object.
  1192. TODO: why do we have this? likely deprecate or remove
  1193. """
  1194. execution_options = compiled.execution_options.merge_with(
  1195. self._execution_options, execution_options
  1196. )
  1197. distilled_parameters = _distill_params(self, multiparams, params)
  1198. if self._has_events or self.engine._has_events:
  1199. (
  1200. compiled,
  1201. distilled_params,
  1202. event_multiparams,
  1203. event_params,
  1204. ) = self._invoke_before_exec_event(
  1205. compiled, distilled_parameters, execution_options
  1206. )
  1207. dialect = self.dialect
  1208. ret = self._execute_context(
  1209. dialect,
  1210. dialect.execution_ctx_cls._init_compiled,
  1211. compiled,
  1212. distilled_parameters,
  1213. execution_options,
  1214. compiled,
  1215. distilled_parameters,
  1216. None,
  1217. None,
  1218. )
  1219. if self._has_events or self.engine._has_events:
  1220. self.dispatch.after_execute(
  1221. self,
  1222. compiled,
  1223. event_multiparams,
  1224. event_params,
  1225. execution_options,
  1226. ret,
  1227. )
  1228. return ret
  1229. def _exec_driver_sql(
  1230. self, statement, multiparams, params, execution_options, future
  1231. ):
  1232. execution_options = self._execution_options.merge_with(
  1233. execution_options
  1234. )
  1235. distilled_parameters = _distill_params(self, multiparams, params)
  1236. if not future:
  1237. if self._has_events or self.engine._has_events:
  1238. (
  1239. statement,
  1240. distilled_params,
  1241. event_multiparams,
  1242. event_params,
  1243. ) = self._invoke_before_exec_event(
  1244. statement, distilled_parameters, execution_options
  1245. )
  1246. dialect = self.dialect
  1247. ret = self._execute_context(
  1248. dialect,
  1249. dialect.execution_ctx_cls._init_statement,
  1250. statement,
  1251. distilled_parameters,
  1252. execution_options,
  1253. statement,
  1254. distilled_parameters,
  1255. )
  1256. if not future:
  1257. if self._has_events or self.engine._has_events:
  1258. self.dispatch.after_execute(
  1259. self,
  1260. statement,
  1261. event_multiparams,
  1262. event_params,
  1263. execution_options,
  1264. ret,
  1265. )
  1266. return ret
  1267. def _execute_20(
  1268. self,
  1269. statement,
  1270. parameters=None,
  1271. execution_options=_EMPTY_EXECUTION_OPTS,
  1272. ):
  1273. args_10style, kwargs_10style = _distill_params_20(parameters)
  1274. try:
  1275. meth = statement._execute_on_connection
  1276. except AttributeError as err:
  1277. util.raise_(
  1278. exc.ObjectNotExecutableError(statement), replace_context=err
  1279. )
  1280. else:
  1281. return meth(self, args_10style, kwargs_10style, execution_options)
  1282. def exec_driver_sql(
  1283. self, statement, parameters=None, execution_options=None
  1284. ):
  1285. r"""Executes a SQL statement construct and returns a
  1286. :class:`_engine.CursorResult`.
  1287. :param statement: The statement str to be executed. Bound parameters
  1288. must use the underlying DBAPI's paramstyle, such as "qmark",
  1289. "pyformat", "format", etc.
  1290. :param parameters: represent bound parameter values to be used in the
  1291. execution. The format is one of: a dictionary of named parameters,
  1292. a tuple of positional parameters, or a list containing either
  1293. dictionaries or tuples for multiple-execute support.
  1294. E.g. multiple dictionaries::
  1295. conn.exec_driver_sql(
  1296. "INSERT INTO table (id, value) VALUES (%(id)s, %(value)s)",
  1297. [{"id":1, "value":"v1"}, {"id":2, "value":"v2"}]
  1298. )
  1299. Single dictionary::
  1300. conn.exec_driver_sql(
  1301. "INSERT INTO table (id, value) VALUES (%(id)s, %(value)s)",
  1302. dict(id=1, value="v1")
  1303. )
  1304. Single tuple::
  1305. conn.exec_driver_sql(
  1306. "INSERT INTO table (id, value) VALUES (?, ?)",
  1307. (1, 'v1')
  1308. )
  1309. .. note:: The :meth:`_engine.Connection.exec_driver_sql` method does
  1310. not participate in the
  1311. :meth:`_events.ConnectionEvents.before_execute` and
  1312. :meth:`_events.ConnectionEvents.after_execute` events. To
  1313. intercept calls to :meth:`_engine.Connection.exec_driver_sql`, use
  1314. :meth:`_events.ConnectionEvents.before_cursor_execute` and
  1315. :meth:`_events.ConnectionEvents.after_cursor_execute`.
  1316. .. seealso::
  1317. :pep:`249`
  1318. """
  1319. args_10style, kwargs_10style = _distill_params_20(parameters)
  1320. return self._exec_driver_sql(
  1321. statement,
  1322. args_10style,
  1323. kwargs_10style,
  1324. execution_options,
  1325. future=True,
  1326. )
  1327. def _execute_context(
  1328. self,
  1329. dialect,
  1330. constructor,
  1331. statement,
  1332. parameters,
  1333. execution_options,
  1334. *args,
  1335. **kw
  1336. ):
  1337. """Create an :class:`.ExecutionContext` and execute, returning
  1338. a :class:`_engine.CursorResult`."""
  1339. branched = self
  1340. if self.__branch_from:
  1341. # if this is a "branched" connection, do everything in terms
  1342. # of the "root" connection, *except* for .close(), which is
  1343. # the only feature that branching provides
  1344. self = self.__branch_from
  1345. try:
  1346. conn = self._dbapi_connection
  1347. if conn is None:
  1348. conn = self._revalidate_connection()
  1349. context = constructor(
  1350. dialect, self, conn, execution_options, *args, **kw
  1351. )
  1352. except (exc.PendingRollbackError, exc.ResourceClosedError):
  1353. raise
  1354. except BaseException as e:
  1355. self._handle_dbapi_exception(
  1356. e, util.text_type(statement), parameters, None, None
  1357. )
  1358. if (
  1359. self._transaction
  1360. and not self._transaction.is_active
  1361. or (
  1362. self._nested_transaction
  1363. and not self._nested_transaction.is_active
  1364. )
  1365. ):
  1366. self._invalid_transaction()
  1367. elif self._trans_context_manager:
  1368. TransactionalContext._trans_ctx_check(self)
  1369. if self._is_future and self._transaction is None:
  1370. self._autobegin()
  1371. context.pre_exec()
  1372. if dialect.use_setinputsizes:
  1373. context._set_input_sizes()
  1374. cursor, statement, parameters = (
  1375. context.cursor,
  1376. context.statement,
  1377. context.parameters,
  1378. )
  1379. if not context.executemany:
  1380. parameters = parameters[0]
  1381. if self._has_events or self.engine._has_events:
  1382. for fn in self.dispatch.before_cursor_execute:
  1383. statement, parameters = fn(
  1384. self,
  1385. cursor,
  1386. statement,
  1387. parameters,
  1388. context,
  1389. context.executemany,
  1390. )
  1391. if self._echo:
  1392. self._log_info(statement)
  1393. stats = context._get_cache_stats()
  1394. if not self.engine.hide_parameters:
  1395. self._log_info(
  1396. "[%s] %r",
  1397. stats,
  1398. sql_util._repr_params(
  1399. parameters, batches=10, ismulti=context.executemany
  1400. ),
  1401. )
  1402. else:
  1403. self._log_info(
  1404. "[%s] [SQL parameters hidden due to hide_parameters=True]"
  1405. % (stats,)
  1406. )
  1407. evt_handled = False
  1408. try:
  1409. if context.executemany:
  1410. if self.dialect._has_events:
  1411. for fn in self.dialect.dispatch.do_executemany:
  1412. if fn(cursor, statement, parameters, context):
  1413. evt_handled = True
  1414. break
  1415. if not evt_handled:
  1416. self.dialect.do_executemany(
  1417. cursor, statement, parameters, context
  1418. )
  1419. elif not parameters and context.no_parameters:
  1420. if self.dialect._has_events:
  1421. for fn in self.dialect.dispatch.do_execute_no_params:
  1422. if fn(cursor, statement, context):
  1423. evt_handled = True
  1424. break
  1425. if not evt_handled:
  1426. self.dialect.do_execute_no_params(
  1427. cursor, statement, context
  1428. )
  1429. else:
  1430. if self.dialect._has_events:
  1431. for fn in self.dialect.dispatch.do_execute:
  1432. if fn(cursor, statement, parameters, context):
  1433. evt_handled = True
  1434. break
  1435. if not evt_handled:
  1436. self.dialect.do_execute(
  1437. cursor, statement, parameters, context
  1438. )
  1439. if self._has_events or self.engine._has_events:
  1440. self.dispatch.after_cursor_execute(
  1441. self,
  1442. cursor,
  1443. statement,
  1444. parameters,
  1445. context,
  1446. context.executemany,
  1447. )
  1448. context.post_exec()
  1449. result = context._setup_result_proxy()
  1450. if not self._is_future:
  1451. should_close_with_result = branched.should_close_with_result
  1452. if not result._soft_closed and should_close_with_result:
  1453. result._autoclose_connection = True
  1454. if (
  1455. # usually we're in a transaction so avoid relatively
  1456. # expensive / legacy should_autocommit call
  1457. self._transaction is None
  1458. and context.should_autocommit
  1459. ):
  1460. self._commit_impl(autocommit=True)
  1461. # for "connectionless" execution, we have to close this
  1462. # Connection after the statement is complete.
  1463. # legacy stuff.
  1464. if should_close_with_result and context._soft_closed:
  1465. assert not self._is_future
  1466. # CursorResult already exhausted rows / has no rows.
  1467. # close us now
  1468. branched.close()
  1469. except BaseException as e:
  1470. self._handle_dbapi_exception(
  1471. e, statement, parameters, cursor, context
  1472. )
  1473. return result
  1474. def _cursor_execute(self, cursor, statement, parameters, context=None):
  1475. """Execute a statement + params on the given cursor.
  1476. Adds appropriate logging and exception handling.
  1477. This method is used by DefaultDialect for special-case
  1478. executions, such as for sequences and column defaults.
  1479. The path of statement execution in the majority of cases
  1480. terminates at _execute_context().
  1481. """
  1482. if self._has_events or self.engine._has_events:
  1483. for fn in self.dispatch.before_cursor_execute:
  1484. statement, parameters = fn(
  1485. self, cursor, statement, parameters, context, False
  1486. )
  1487. if self._echo:
  1488. self._log_info(statement)
  1489. self._log_info("[raw sql] %r", parameters)
  1490. try:
  1491. for fn in (
  1492. ()
  1493. if not self.dialect._has_events
  1494. else self.dialect.dispatch.do_execute
  1495. ):
  1496. if fn(cursor, statement, parameters, context):
  1497. break
  1498. else:
  1499. self.dialect.do_execute(cursor, statement, parameters, context)
  1500. except BaseException as e:
  1501. self._handle_dbapi_exception(
  1502. e, statement, parameters, cursor, context
  1503. )
  1504. if self._has_events or self.engine._has_events:
  1505. self.dispatch.after_cursor_execute(
  1506. self, cursor, statement, parameters, context, False
  1507. )
  1508. def _safe_close_cursor(self, cursor):
  1509. """Close the given cursor, catching exceptions
  1510. and turning into log warnings.
  1511. """
  1512. try:
  1513. cursor.close()
  1514. except Exception:
  1515. # log the error through the connection pool's logger.
  1516. self.engine.pool.logger.error(
  1517. "Error closing cursor", exc_info=True
  1518. )
  1519. _reentrant_error = False
  1520. _is_disconnect = False
  1521. def _handle_dbapi_exception(
  1522. self, e, statement, parameters, cursor, context
  1523. ):
  1524. exc_info = sys.exc_info()
  1525. is_exit_exception = util.is_exit_exception(e)
  1526. if not self._is_disconnect:
  1527. self._is_disconnect = (
  1528. isinstance(e, self.dialect.dbapi.Error)
  1529. and not self.closed
  1530. and self.dialect.is_disconnect(
  1531. e,
  1532. self._dbapi_connection if not self.invalidated else None,
  1533. cursor,
  1534. )
  1535. ) or (is_exit_exception and not self.closed)
  1536. invalidate_pool_on_disconnect = not is_exit_exception
  1537. if self._reentrant_error:
  1538. util.raise_(
  1539. exc.DBAPIError.instance(
  1540. statement,
  1541. parameters,
  1542. e,
  1543. self.dialect.dbapi.Error,
  1544. hide_parameters=self.engine.hide_parameters,
  1545. dialect=self.dialect,
  1546. ismulti=context.executemany
  1547. if context is not None
  1548. else None,
  1549. ),
  1550. with_traceback=exc_info[2],
  1551. from_=e,
  1552. )
  1553. self._reentrant_error = True
  1554. try:
  1555. # non-DBAPI error - if we already got a context,
  1556. # or there's no string statement, don't wrap it
  1557. should_wrap = isinstance(e, self.dialect.dbapi.Error) or (
  1558. statement is not None
  1559. and context is None
  1560. and not is_exit_exception
  1561. )
  1562. if should_wrap:
  1563. sqlalchemy_exception = exc.DBAPIError.instance(
  1564. statement,
  1565. parameters,
  1566. e,
  1567. self.dialect.dbapi.Error,
  1568. hide_parameters=self.engine.hide_parameters,
  1569. connection_invalidated=self._is_disconnect,
  1570. dialect=self.dialect,
  1571. ismulti=context.executemany
  1572. if context is not None
  1573. else None,
  1574. )
  1575. else:
  1576. sqlalchemy_exception = None
  1577. newraise = None
  1578. if (
  1579. self._has_events or self.engine._has_events
  1580. ) and not self._execution_options.get(
  1581. "skip_user_error_events", False
  1582. ):
  1583. ctx = ExceptionContextImpl(
  1584. e,
  1585. sqlalchemy_exception,
  1586. self.engine,
  1587. self,
  1588. cursor,
  1589. statement,
  1590. parameters,
  1591. context,
  1592. self._is_disconnect,
  1593. invalidate_pool_on_disconnect,
  1594. )
  1595. for fn in self.dispatch.handle_error:
  1596. try:
  1597. # handler returns an exception;
  1598. # call next handler in a chain
  1599. per_fn = fn(ctx)
  1600. if per_fn is not None:
  1601. ctx.chained_exception = newraise = per_fn
  1602. except Exception as _raised:
  1603. # handler raises an exception - stop processing
  1604. newraise = _raised
  1605. break
  1606. if self._is_disconnect != ctx.is_disconnect:
  1607. self._is_disconnect = ctx.is_disconnect
  1608. if sqlalchemy_exception:
  1609. sqlalchemy_exception.connection_invalidated = (
  1610. ctx.is_disconnect
  1611. )
  1612. # set up potentially user-defined value for
  1613. # invalidate pool.
  1614. invalidate_pool_on_disconnect = (
  1615. ctx.invalidate_pool_on_disconnect
  1616. )
  1617. if should_wrap and context:
  1618. context.handle_dbapi_exception(e)
  1619. if not self._is_disconnect:
  1620. if cursor:
  1621. self._safe_close_cursor(cursor)
  1622. with util.safe_reraise(warn_only=True):
  1623. self._autorollback()
  1624. if newraise:
  1625. util.raise_(newraise, with_traceback=exc_info[2], from_=e)
  1626. elif should_wrap:
  1627. util.raise_(
  1628. sqlalchemy_exception, with_traceback=exc_info[2], from_=e
  1629. )
  1630. else:
  1631. util.raise_(exc_info[1], with_traceback=exc_info[2])
  1632. finally:
  1633. del self._reentrant_error
  1634. if self._is_disconnect:
  1635. del self._is_disconnect
  1636. if not self.invalidated:
  1637. dbapi_conn_wrapper = self._dbapi_connection
  1638. if invalidate_pool_on_disconnect:
  1639. self.engine.pool._invalidate(dbapi_conn_wrapper, e)
  1640. self.invalidate(e)
  1641. if self.should_close_with_result:
  1642. assert not self._is_future
  1643. self.close()
  1644. @classmethod
  1645. def _handle_dbapi_exception_noconnection(cls, e, dialect, engine):
  1646. exc_info = sys.exc_info()
  1647. is_disconnect = dialect.is_disconnect(e, None, None)
  1648. should_wrap = isinstance(e, dialect.dbapi.Error)
  1649. if should_wrap:
  1650. sqlalchemy_exception = exc.DBAPIError.instance(
  1651. None,
  1652. None,
  1653. e,
  1654. dialect.dbapi.Error,
  1655. hide_parameters=engine.hide_parameters,
  1656. connection_invalidated=is_disconnect,
  1657. )
  1658. else:
  1659. sqlalchemy_exception = None
  1660. newraise = None
  1661. if engine._has_events:
  1662. ctx = ExceptionContextImpl(
  1663. e,
  1664. sqlalchemy_exception,
  1665. engine,
  1666. None,
  1667. None,
  1668. None,
  1669. None,
  1670. None,
  1671. is_disconnect,
  1672. True,
  1673. )
  1674. for fn in engine.dispatch.handle_error:
  1675. try:
  1676. # handler returns an exception;
  1677. # call next handler in a chain
  1678. per_fn = fn(ctx)
  1679. if per_fn is not None:
  1680. ctx.chained_exception = newraise = per_fn
  1681. except Exception as _raised:
  1682. # handler raises an exception - stop processing
  1683. newraise = _raised
  1684. break
  1685. if sqlalchemy_exception and is_disconnect != ctx.is_disconnect:
  1686. sqlalchemy_exception.connection_invalidated = (
  1687. is_disconnect
  1688. ) = ctx.is_disconnect
  1689. if newraise:
  1690. util.raise_(newraise, with_traceback=exc_info[2], from_=e)
  1691. elif should_wrap:
  1692. util.raise_(
  1693. sqlalchemy_exception, with_traceback=exc_info[2], from_=e
  1694. )
  1695. else:
  1696. util.raise_(exc_info[1], with_traceback=exc_info[2])
  1697. def _run_ddl_visitor(self, visitorcallable, element, **kwargs):
  1698. """run a DDL visitor.
  1699. This method is only here so that the MockConnection can change the
  1700. options given to the visitor so that "checkfirst" is skipped.
  1701. """
  1702. visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
  1703. @util.deprecated(
  1704. "1.4",
  1705. "The :meth:`_engine.Connection.transaction` "
  1706. "method is deprecated and will be "
  1707. "removed in a future release. Use the :meth:`_engine.Engine.begin` "
  1708. "context manager instead.",
  1709. )
  1710. def transaction(self, callable_, *args, **kwargs):
  1711. r"""Execute the given function within a transaction boundary.
  1712. The function is passed this :class:`_engine.Connection`
  1713. as the first argument, followed by the given \*args and \**kwargs,
  1714. e.g.::
  1715. def do_something(conn, x, y):
  1716. conn.execute(text("some statement"), {'x':x, 'y':y})
  1717. conn.transaction(do_something, 5, 10)
  1718. The operations inside the function are all invoked within the
  1719. context of a single :class:`.Transaction`.
  1720. Upon success, the transaction is committed. If an
  1721. exception is raised, the transaction is rolled back
  1722. before propagating the exception.
  1723. .. note::
  1724. The :meth:`.transaction` method is superseded by
  1725. the usage of the Python ``with:`` statement, which can
  1726. be used with :meth:`_engine.Connection.begin`::
  1727. with conn.begin():
  1728. conn.execute(text("some statement"), {'x':5, 'y':10})
  1729. As well as with :meth:`_engine.Engine.begin`::
  1730. with engine.begin() as conn:
  1731. conn.execute(text("some statement"), {'x':5, 'y':10})
  1732. .. seealso::
  1733. :meth:`_engine.Engine.begin` - engine-level transactional
  1734. context
  1735. :meth:`_engine.Engine.transaction` - engine-level version of
  1736. :meth:`_engine.Connection.transaction`
  1737. """
  1738. kwargs["_sa_skip_warning"] = True
  1739. trans = self.begin()
  1740. try:
  1741. ret = self.run_callable(callable_, *args, **kwargs)
  1742. trans.commit()
  1743. return ret
  1744. except:
  1745. with util.safe_reraise():
  1746. trans.rollback()
  1747. @util.deprecated(
  1748. "1.4",
  1749. "The :meth:`_engine.Connection.run_callable` "
  1750. "method is deprecated and will "
  1751. "be removed in a future release. Invoke the callable function "
  1752. "directly, passing the Connection.",
  1753. )
  1754. def run_callable(self, callable_, *args, **kwargs):
  1755. r"""Given a callable object or function, execute it, passing
  1756. a :class:`_engine.Connection` as the first argument.
  1757. The given \*args and \**kwargs are passed subsequent
  1758. to the :class:`_engine.Connection` argument.
  1759. This function, along with :meth:`_engine.Engine.run_callable`,
  1760. allows a function to be run with a :class:`_engine.Connection`
  1761. or :class:`_engine.Engine` object without the need to know
  1762. which one is being dealt with.
  1763. """
  1764. return callable_(self, *args, **kwargs)
  1765. class ExceptionContextImpl(ExceptionContext):
  1766. """Implement the :class:`.ExceptionContext` interface."""
  1767. def __init__(
  1768. self,
  1769. exception,
  1770. sqlalchemy_exception,
  1771. engine,
  1772. connection,
  1773. cursor,
  1774. statement,
  1775. parameters,
  1776. context,
  1777. is_disconnect,
  1778. invalidate_pool_on_disconnect,
  1779. ):
  1780. self.engine = engine
  1781. self.connection = connection
  1782. self.sqlalchemy_exception = sqlalchemy_exception
  1783. self.original_exception = exception
  1784. self.execution_context = context
  1785. self.statement = statement
  1786. self.parameters = parameters
  1787. self.is_disconnect = is_disconnect
  1788. self.invalidate_pool_on_disconnect = invalidate_pool_on_disconnect
  1789. class Transaction(TransactionalContext):
  1790. """Represent a database transaction in progress.
  1791. The :class:`.Transaction` object is procured by
  1792. calling the :meth:`_engine.Connection.begin` method of
  1793. :class:`_engine.Connection`::
  1794. from sqlalchemy import create_engine
  1795. engine = create_engine("postgresql://scott:tiger@localhost/test")
  1796. connection = engine.connect()
  1797. trans = connection.begin()
  1798. connection.execute(text("insert into x (a, b) values (1, 2)"))
  1799. trans.commit()
  1800. The object provides :meth:`.rollback` and :meth:`.commit`
  1801. methods in order to control transaction boundaries. It
  1802. also implements a context manager interface so that
  1803. the Python ``with`` statement can be used with the
  1804. :meth:`_engine.Connection.begin` method::
  1805. with connection.begin():
  1806. connection.execute(text("insert into x (a, b) values (1, 2)"))
  1807. The Transaction object is **not** threadsafe.
  1808. .. seealso::
  1809. :meth:`_engine.Connection.begin`
  1810. :meth:`_engine.Connection.begin_twophase`
  1811. :meth:`_engine.Connection.begin_nested`
  1812. .. index::
  1813. single: thread safety; Transaction
  1814. """
  1815. __slots__ = ()
  1816. _is_root = False
  1817. def __init__(self, connection):
  1818. raise NotImplementedError()
  1819. def _do_deactivate(self):
  1820. """do whatever steps are necessary to set this transaction as
  1821. "deactive", however leave this transaction object in place as far
  1822. as the connection's state.
  1823. for a "real" transaction this should roll back the transaction
  1824. and ensure this transaction is no longer a reset agent.
  1825. this is used for nesting of marker transactions where the marker
  1826. can set the "real" transaction as rolled back, however it stays
  1827. in place.
  1828. for 2.0 we hope to remove this nesting feature.
  1829. """
  1830. raise NotImplementedError()
  1831. @property
  1832. def _deactivated_from_connection(self):
  1833. """True if this transaction is totally deactivated from the connection
  1834. and therefore can no longer affect its state.
  1835. """
  1836. raise NotImplementedError()
  1837. def _do_close(self):
  1838. raise NotImplementedError()
  1839. def _do_rollback(self):
  1840. raise NotImplementedError()
  1841. def _do_commit(self):
  1842. raise NotImplementedError()
  1843. @property
  1844. def is_valid(self):
  1845. return self.is_active and not self.connection.invalidated
  1846. def close(self):
  1847. """Close this :class:`.Transaction`.
  1848. If this transaction is the base transaction in a begin/commit
  1849. nesting, the transaction will rollback(). Otherwise, the
  1850. method returns.
  1851. This is used to cancel a Transaction without affecting the scope of
  1852. an enclosing transaction.
  1853. """
  1854. try:
  1855. self._do_close()
  1856. finally:
  1857. assert not self.is_active
  1858. def rollback(self):
  1859. """Roll back this :class:`.Transaction`.
  1860. The implementation of this may vary based on the type of transaction in
  1861. use:
  1862. * For a simple database transaction (e.g. :class:`.RootTransaction`),
  1863. it corresponds to a ROLLBACK.
  1864. * For a :class:`.NestedTransaction`, it corresponds to a
  1865. "ROLLBACK TO SAVEPOINT" operation.
  1866. * For a :class:`.TwoPhaseTransaction`, DBAPI-specific methods for two
  1867. phase transactions may be used.
  1868. """
  1869. try:
  1870. self._do_rollback()
  1871. finally:
  1872. assert not self.is_active
  1873. def commit(self):
  1874. """Commit this :class:`.Transaction`.
  1875. The implementation of this may vary based on the type of transaction in
  1876. use:
  1877. * For a simple database transaction (e.g. :class:`.RootTransaction`),
  1878. it corresponds to a COMMIT.
  1879. * For a :class:`.NestedTransaction`, it corresponds to a
  1880. "RELEASE SAVEPOINT" operation.
  1881. * For a :class:`.TwoPhaseTransaction`, DBAPI-specific methods for two
  1882. phase transactions may be used.
  1883. """
  1884. try:
  1885. self._do_commit()
  1886. finally:
  1887. assert not self.is_active
  1888. def _get_subject(self):
  1889. return self.connection
  1890. def _transaction_is_active(self):
  1891. return self.is_active
  1892. def _transaction_is_closed(self):
  1893. return not self._deactivated_from_connection
  1894. def _rollback_can_be_called(self):
  1895. # for RootTransaction / NestedTransaction, it's safe to call
  1896. # rollback() even if the transaction is deactive and no warnings
  1897. # will be emitted. tested in
  1898. # test_transaction.py -> test_no_rollback_in_deactive(?:_savepoint)?
  1899. return True
  1900. class MarkerTransaction(Transaction):
  1901. """A 'marker' transaction that is used for nested begin() calls.
  1902. .. deprecated:: 1.4 future connection for 2.0 won't support this pattern.
  1903. """
  1904. __slots__ = ("connection", "_is_active", "_transaction")
  1905. def __init__(self, connection):
  1906. assert connection._transaction is not None
  1907. if not connection._transaction.is_active:
  1908. raise exc.InvalidRequestError(
  1909. "the current transaction on this connection is inactive. "
  1910. "Please issue a rollback first."
  1911. )
  1912. assert not connection._is_future
  1913. util.warn_deprecated_20(
  1914. "Calling .begin() when a transaction is already begun, creating "
  1915. "a 'sub' transaction, is deprecated "
  1916. "and will be removed in 2.0. See the documentation section "
  1917. "'Migrating from the nesting pattern' for background on how "
  1918. "to migrate from this pattern."
  1919. )
  1920. self.connection = connection
  1921. if connection._trans_context_manager:
  1922. TransactionalContext._trans_ctx_check(connection)
  1923. if connection._nested_transaction is not None:
  1924. self._transaction = connection._nested_transaction
  1925. else:
  1926. self._transaction = connection._transaction
  1927. self._is_active = True
  1928. @property
  1929. def _deactivated_from_connection(self):
  1930. return not self.is_active
  1931. @property
  1932. def is_active(self):
  1933. return self._is_active and self._transaction.is_active
  1934. def _deactivate(self):
  1935. self._is_active = False
  1936. def _do_close(self):
  1937. # does not actually roll back the root
  1938. self._deactivate()
  1939. def _do_rollback(self):
  1940. # does roll back the root
  1941. if self._is_active:
  1942. try:
  1943. self._transaction._do_deactivate()
  1944. finally:
  1945. self._deactivate()
  1946. def _do_commit(self):
  1947. self._deactivate()
  1948. class RootTransaction(Transaction):
  1949. """Represent the "root" transaction on a :class:`_engine.Connection`.
  1950. This corresponds to the current "BEGIN/COMMIT/ROLLBACK" that's occurring
  1951. for the :class:`_engine.Connection`. The :class:`_engine.RootTransaction`
  1952. is created by calling upon the :meth:`_engine.Connection.begin` method, and
  1953. remains associated with the :class:`_engine.Connection` throughout its
  1954. active span. The current :class:`_engine.RootTransaction` in use is
  1955. accessible via the :attr:`_engine.Connection.get_transaction` method of
  1956. :class:`_engine.Connection`.
  1957. In :term:`2.0 style` use, the :class:`_future.Connection` also employs
  1958. "autobegin" behavior that will create a new
  1959. :class:`_engine.RootTransaction` whenever a connection in a
  1960. non-transactional state is used to emit commands on the DBAPI connection.
  1961. The scope of the :class:`_engine.RootTransaction` in 2.0 style
  1962. use can be controlled using the :meth:`_future.Connection.commit` and
  1963. :meth:`_future.Connection.rollback` methods.
  1964. """
  1965. _is_root = True
  1966. __slots__ = ("connection", "is_active")
  1967. def __init__(self, connection):
  1968. assert connection._transaction is None
  1969. if connection._trans_context_manager:
  1970. TransactionalContext._trans_ctx_check(connection)
  1971. self.connection = connection
  1972. self._connection_begin_impl()
  1973. connection._transaction = self
  1974. self.is_active = True
  1975. def _deactivate_from_connection(self):
  1976. if self.is_active:
  1977. assert self.connection._transaction is self
  1978. self.is_active = False
  1979. elif self.connection._transaction is not self:
  1980. util.warn("transaction already deassociated from connection")
  1981. @property
  1982. def _deactivated_from_connection(self):
  1983. return self.connection._transaction is not self
  1984. def _do_deactivate(self):
  1985. # called from a MarkerTransaction to cancel this root transaction.
  1986. # the transaction stays in place as connection._transaction, but
  1987. # is no longer active and is no longer the reset agent for the
  1988. # pooled connection. the connection won't support a new begin()
  1989. # until this transaction is explicitly closed, rolled back,
  1990. # or committed.
  1991. assert self.connection._transaction is self
  1992. if self.is_active:
  1993. self._connection_rollback_impl()
  1994. # handle case where a savepoint was created inside of a marker
  1995. # transaction that refers to a root. nested has to be cancelled
  1996. # also.
  1997. if self.connection._nested_transaction:
  1998. self.connection._nested_transaction._cancel()
  1999. self._deactivate_from_connection()
  2000. def _connection_begin_impl(self):
  2001. self.connection._begin_impl(self)
  2002. def _connection_rollback_impl(self):
  2003. self.connection._rollback_impl()
  2004. def _connection_commit_impl(self):
  2005. self.connection._commit_impl()
  2006. def _close_impl(self, try_deactivate=False):
  2007. try:
  2008. if self.is_active:
  2009. self._connection_rollback_impl()
  2010. if self.connection._nested_transaction:
  2011. self.connection._nested_transaction._cancel()
  2012. finally:
  2013. if self.is_active or try_deactivate:
  2014. self._deactivate_from_connection()
  2015. if self.connection._transaction is self:
  2016. self.connection._transaction = None
  2017. assert not self.is_active
  2018. assert self.connection._transaction is not self
  2019. def _do_close(self):
  2020. self._close_impl()
  2021. def _do_rollback(self):
  2022. self._close_impl(try_deactivate=True)
  2023. def _do_commit(self):
  2024. if self.is_active:
  2025. assert self.connection._transaction is self
  2026. try:
  2027. self._connection_commit_impl()
  2028. finally:
  2029. # whether or not commit succeeds, cancel any
  2030. # nested transactions, make this transaction "inactive"
  2031. # and remove it as a reset agent
  2032. if self.connection._nested_transaction:
  2033. self.connection._nested_transaction._cancel()
  2034. self._deactivate_from_connection()
  2035. # ...however only remove as the connection's current transaction
  2036. # if commit succeeded. otherwise it stays on so that a rollback
  2037. # needs to occur.
  2038. self.connection._transaction = None
  2039. else:
  2040. if self.connection._transaction is self:
  2041. self.connection._invalid_transaction()
  2042. else:
  2043. raise exc.InvalidRequestError("This transaction is inactive")
  2044. assert not self.is_active
  2045. assert self.connection._transaction is not self
  2046. class NestedTransaction(Transaction):
  2047. """Represent a 'nested', or SAVEPOINT transaction.
  2048. The :class:`.NestedTransaction` object is created by calling the
  2049. :meth:`_engine.Connection.begin_nested` method of
  2050. :class:`_engine.Connection`.
  2051. When using :class:`.NestedTransaction`, the semantics of "begin" /
  2052. "commit" / "rollback" are as follows:
  2053. * the "begin" operation corresponds to the "BEGIN SAVEPOINT" command, where
  2054. the savepoint is given an explicit name that is part of the state
  2055. of this object.
  2056. * The :meth:`.NestedTransaction.commit` method corresponds to a
  2057. "RELEASE SAVEPOINT" operation, using the savepoint identifier associated
  2058. with this :class:`.NestedTransaction`.
  2059. * The :meth:`.NestedTransaction.rollback` method corresponds to a
  2060. "ROLLBACK TO SAVEPOINT" operation, using the savepoint identifier
  2061. associated with this :class:`.NestedTransaction`.
  2062. The rationale for mimicking the semantics of an outer transaction in
  2063. terms of savepoints so that code may deal with a "savepoint" transaction
  2064. and an "outer" transaction in an agnostic way.
  2065. .. seealso::
  2066. :ref:`session_begin_nested` - ORM version of the SAVEPOINT API.
  2067. """
  2068. __slots__ = ("connection", "is_active", "_savepoint", "_previous_nested")
  2069. def __init__(self, connection):
  2070. assert connection._transaction is not None
  2071. if connection._trans_context_manager:
  2072. TransactionalContext._trans_ctx_check(connection)
  2073. self.connection = connection
  2074. self._savepoint = self.connection._savepoint_impl()
  2075. self.is_active = True
  2076. self._previous_nested = connection._nested_transaction
  2077. connection._nested_transaction = self
  2078. def _deactivate_from_connection(self, warn=True):
  2079. if self.connection._nested_transaction is self:
  2080. self.connection._nested_transaction = self._previous_nested
  2081. elif warn:
  2082. util.warn(
  2083. "nested transaction already deassociated from connection"
  2084. )
  2085. @property
  2086. def _deactivated_from_connection(self):
  2087. return self.connection._nested_transaction is not self
  2088. def _cancel(self):
  2089. # called by RootTransaction when the outer transaction is
  2090. # committed, rolled back, or closed to cancel all savepoints
  2091. # without any action being taken
  2092. self.is_active = False
  2093. self._deactivate_from_connection()
  2094. if self._previous_nested:
  2095. self._previous_nested._cancel()
  2096. def _close_impl(self, deactivate_from_connection, warn_already_deactive):
  2097. try:
  2098. if self.is_active and self.connection._transaction.is_active:
  2099. self.connection._rollback_to_savepoint_impl(self._savepoint)
  2100. finally:
  2101. self.is_active = False
  2102. if deactivate_from_connection:
  2103. self._deactivate_from_connection(warn=warn_already_deactive)
  2104. assert not self.is_active
  2105. if deactivate_from_connection:
  2106. assert self.connection._nested_transaction is not self
  2107. def _do_deactivate(self):
  2108. self._close_impl(False, False)
  2109. def _do_close(self):
  2110. self._close_impl(True, False)
  2111. def _do_rollback(self):
  2112. self._close_impl(True, True)
  2113. def _do_commit(self):
  2114. if self.is_active:
  2115. try:
  2116. self.connection._release_savepoint_impl(self._savepoint)
  2117. finally:
  2118. # nested trans becomes inactive on failed release
  2119. # unconditionally. this prevents it from trying to
  2120. # emit SQL when it rolls back.
  2121. self.is_active = False
  2122. # but only de-associate from connection if it succeeded
  2123. self._deactivate_from_connection()
  2124. else:
  2125. if self.connection._nested_transaction is self:
  2126. self.connection._invalid_transaction()
  2127. else:
  2128. raise exc.InvalidRequestError(
  2129. "This nested transaction is inactive"
  2130. )
  2131. class TwoPhaseTransaction(RootTransaction):
  2132. """Represent a two-phase transaction.
  2133. A new :class:`.TwoPhaseTransaction` object may be procured
  2134. using the :meth:`_engine.Connection.begin_twophase` method.
  2135. The interface is the same as that of :class:`.Transaction`
  2136. with the addition of the :meth:`prepare` method.
  2137. """
  2138. __slots__ = ("connection", "is_active", "xid", "_is_prepared")
  2139. def __init__(self, connection, xid):
  2140. self._is_prepared = False
  2141. self.xid = xid
  2142. super(TwoPhaseTransaction, self).__init__(connection)
  2143. def prepare(self):
  2144. """Prepare this :class:`.TwoPhaseTransaction`.
  2145. After a PREPARE, the transaction can be committed.
  2146. """
  2147. if not self.is_active:
  2148. raise exc.InvalidRequestError("This transaction is inactive")
  2149. self.connection._prepare_twophase_impl(self.xid)
  2150. self._is_prepared = True
  2151. def _connection_begin_impl(self):
  2152. self.connection._begin_twophase_impl(self)
  2153. def _connection_rollback_impl(self):
  2154. self.connection._rollback_twophase_impl(self.xid, self._is_prepared)
  2155. def _connection_commit_impl(self):
  2156. self.connection._commit_twophase_impl(self.xid, self._is_prepared)
  2157. class Engine(Connectable, log.Identified):
  2158. """
  2159. Connects a :class:`~sqlalchemy.pool.Pool` and
  2160. :class:`~sqlalchemy.engine.interfaces.Dialect` together to provide a
  2161. source of database connectivity and behavior.
  2162. This is the **SQLAlchemy 1.x version** of :class:`_engine.Engine`. For
  2163. the :term:`2.0 style` version, which includes some API differences,
  2164. see :class:`_future.Engine`.
  2165. An :class:`_engine.Engine` object is instantiated publicly using the
  2166. :func:`~sqlalchemy.create_engine` function.
  2167. .. seealso::
  2168. :doc:`/core/engines`
  2169. :ref:`connections_toplevel`
  2170. """
  2171. _execution_options = _EMPTY_EXECUTION_OPTS
  2172. _has_events = False
  2173. _connection_cls = Connection
  2174. _sqla_logger_namespace = "sqlalchemy.engine.Engine"
  2175. _is_future = False
  2176. _schema_translate_map = None
  2177. def __init__(
  2178. self,
  2179. pool,
  2180. dialect,
  2181. url,
  2182. logging_name=None,
  2183. echo=None,
  2184. query_cache_size=500,
  2185. execution_options=None,
  2186. hide_parameters=False,
  2187. ):
  2188. self.pool = pool
  2189. self.url = url
  2190. self.dialect = dialect
  2191. if logging_name:
  2192. self.logging_name = logging_name
  2193. self.echo = echo
  2194. self.hide_parameters = hide_parameters
  2195. if query_cache_size != 0:
  2196. self._compiled_cache = util.LRUCache(
  2197. query_cache_size, size_alert=self._lru_size_alert
  2198. )
  2199. else:
  2200. self._compiled_cache = None
  2201. log.instance_logger(self, echoflag=echo)
  2202. if execution_options:
  2203. self.update_execution_options(**execution_options)
  2204. def _lru_size_alert(self, cache):
  2205. if self._should_log_info:
  2206. self.logger.info(
  2207. "Compiled cache size pruning from %d items to %d. "
  2208. "Increase cache size to reduce the frequency of pruning.",
  2209. len(cache),
  2210. cache.capacity,
  2211. )
  2212. @property
  2213. def engine(self):
  2214. return self
  2215. def clear_compiled_cache(self):
  2216. """Clear the compiled cache associated with the dialect.
  2217. This applies **only** to the built-in cache that is established
  2218. via the :paramref:`_engine.create_engine.query_cache_size` parameter.
  2219. It will not impact any dictionary caches that were passed via the
  2220. :paramref:`.Connection.execution_options.query_cache` parameter.
  2221. .. versionadded:: 1.4
  2222. """
  2223. if self._compiled_cache:
  2224. self._compiled_cache.clear()
  2225. def update_execution_options(self, **opt):
  2226. r"""Update the default execution_options dictionary
  2227. of this :class:`_engine.Engine`.
  2228. The given keys/values in \**opt are added to the
  2229. default execution options that will be used for
  2230. all connections. The initial contents of this dictionary
  2231. can be sent via the ``execution_options`` parameter
  2232. to :func:`_sa.create_engine`.
  2233. .. seealso::
  2234. :meth:`_engine.Connection.execution_options`
  2235. :meth:`_engine.Engine.execution_options`
  2236. """
  2237. self._execution_options = self._execution_options.union(opt)
  2238. self.dispatch.set_engine_execution_options(self, opt)
  2239. self.dialect.set_engine_execution_options(self, opt)
  2240. def execution_options(self, **opt):
  2241. """Return a new :class:`_engine.Engine` that will provide
  2242. :class:`_engine.Connection` objects with the given execution options.
  2243. The returned :class:`_engine.Engine` remains related to the original
  2244. :class:`_engine.Engine` in that it shares the same connection pool and
  2245. other state:
  2246. * The :class:`_pool.Pool` used by the new :class:`_engine.Engine`
  2247. is the
  2248. same instance. The :meth:`_engine.Engine.dispose`
  2249. method will replace
  2250. the connection pool instance for the parent engine as well
  2251. as this one.
  2252. * Event listeners are "cascaded" - meaning, the new
  2253. :class:`_engine.Engine`
  2254. inherits the events of the parent, and new events can be associated
  2255. with the new :class:`_engine.Engine` individually.
  2256. * The logging configuration and logging_name is copied from the parent
  2257. :class:`_engine.Engine`.
  2258. The intent of the :meth:`_engine.Engine.execution_options` method is
  2259. to implement "sharding" schemes where multiple :class:`_engine.Engine`
  2260. objects refer to the same connection pool, but are differentiated
  2261. by options that would be consumed by a custom event::
  2262. primary_engine = create_engine("mysql://")
  2263. shard1 = primary_engine.execution_options(shard_id="shard1")
  2264. shard2 = primary_engine.execution_options(shard_id="shard2")
  2265. Above, the ``shard1`` engine serves as a factory for
  2266. :class:`_engine.Connection`
  2267. objects that will contain the execution option
  2268. ``shard_id=shard1``, and ``shard2`` will produce
  2269. :class:`_engine.Connection`
  2270. objects that contain the execution option ``shard_id=shard2``.
  2271. An event handler can consume the above execution option to perform
  2272. a schema switch or other operation, given a connection. Below
  2273. we emit a MySQL ``use`` statement to switch databases, at the same
  2274. time keeping track of which database we've established using the
  2275. :attr:`_engine.Connection.info` dictionary,
  2276. which gives us a persistent
  2277. storage space that follows the DBAPI connection::
  2278. from sqlalchemy import event
  2279. from sqlalchemy.engine import Engine
  2280. shards = {"default": "base", shard_1: "db1", "shard_2": "db2"}
  2281. @event.listens_for(Engine, "before_cursor_execute")
  2282. def _switch_shard(conn, cursor, stmt,
  2283. params, context, executemany):
  2284. shard_id = conn._execution_options.get('shard_id', "default")
  2285. current_shard = conn.info.get("current_shard", None)
  2286. if current_shard != shard_id:
  2287. cursor.execute("use %s" % shards[shard_id])
  2288. conn.info["current_shard"] = shard_id
  2289. .. seealso::
  2290. :meth:`_engine.Connection.execution_options`
  2291. - update execution options
  2292. on a :class:`_engine.Connection` object.
  2293. :meth:`_engine.Engine.update_execution_options`
  2294. - update the execution
  2295. options for a given :class:`_engine.Engine` in place.
  2296. :meth:`_engine.Engine.get_execution_options`
  2297. """
  2298. return self._option_cls(self, opt)
  2299. def get_execution_options(self):
  2300. """Get the non-SQL options which will take effect during execution.
  2301. .. versionadded: 1.3
  2302. .. seealso::
  2303. :meth:`_engine.Engine.execution_options`
  2304. """
  2305. return self._execution_options
  2306. @property
  2307. def name(self):
  2308. """String name of the :class:`~sqlalchemy.engine.interfaces.Dialect`
  2309. in use by this :class:`Engine`."""
  2310. return self.dialect.name
  2311. @property
  2312. def driver(self):
  2313. """Driver name of the :class:`~sqlalchemy.engine.interfaces.Dialect`
  2314. in use by this :class:`Engine`."""
  2315. return self.dialect.driver
  2316. echo = log.echo_property()
  2317. def __repr__(self):
  2318. return "Engine(%r)" % (self.url,)
  2319. def dispose(self):
  2320. """Dispose of the connection pool used by this
  2321. :class:`_engine.Engine`.
  2322. This has the effect of fully closing all **currently checked in**
  2323. database connections. Connections that are still checked out
  2324. will **not** be closed, however they will no longer be associated
  2325. with this :class:`_engine.Engine`,
  2326. so when they are closed individually,
  2327. eventually the :class:`_pool.Pool` which they are associated with will
  2328. be garbage collected and they will be closed out fully, if
  2329. not already closed on checkin.
  2330. A new connection pool is created immediately after the old one has
  2331. been disposed. This new pool, like all SQLAlchemy connection pools,
  2332. does not make any actual connections to the database until one is
  2333. first requested, so as long as the :class:`_engine.Engine`
  2334. isn't used again,
  2335. no new connections will be made.
  2336. .. seealso::
  2337. :ref:`engine_disposal`
  2338. """
  2339. self.pool.dispose()
  2340. self.pool = self.pool.recreate()
  2341. self.dispatch.engine_disposed(self)
  2342. def _execute_default(
  2343. self, default, multiparams=(), params=util.EMPTY_DICT
  2344. ):
  2345. with self.connect() as conn:
  2346. return conn._execute_default(default, multiparams, params)
  2347. @contextlib.contextmanager
  2348. def _optional_conn_ctx_manager(self, connection=None):
  2349. if connection is None:
  2350. with self.connect() as conn:
  2351. yield conn
  2352. else:
  2353. yield connection
  2354. class _trans_ctx(object):
  2355. def __init__(self, conn, transaction, close_with_result):
  2356. self.conn = conn
  2357. self.transaction = transaction
  2358. self.close_with_result = close_with_result
  2359. def __enter__(self):
  2360. self.transaction.__enter__()
  2361. return self.conn
  2362. def __exit__(self, type_, value, traceback):
  2363. try:
  2364. self.transaction.__exit__(type_, value, traceback)
  2365. finally:
  2366. if not self.close_with_result:
  2367. self.conn.close()
  2368. def begin(self, close_with_result=False):
  2369. """Return a context manager delivering a :class:`_engine.Connection`
  2370. with a :class:`.Transaction` established.
  2371. E.g.::
  2372. with engine.begin() as conn:
  2373. conn.execute(
  2374. text("insert into table (x, y, z) values (1, 2, 3)")
  2375. )
  2376. conn.execute(text("my_special_procedure(5)"))
  2377. Upon successful operation, the :class:`.Transaction`
  2378. is committed. If an error is raised, the :class:`.Transaction`
  2379. is rolled back.
  2380. Legacy use only: the ``close_with_result`` flag is normally ``False``,
  2381. and indicates that the :class:`_engine.Connection` will be closed when
  2382. the operation is complete. When set to ``True``, it indicates the
  2383. :class:`_engine.Connection` is in "single use" mode, where the
  2384. :class:`_engine.CursorResult` returned by the first call to
  2385. :meth:`_engine.Connection.execute` will close the
  2386. :class:`_engine.Connection` when that :class:`_engine.CursorResult` has
  2387. exhausted all result rows.
  2388. .. seealso::
  2389. :meth:`_engine.Engine.connect` - procure a
  2390. :class:`_engine.Connection` from
  2391. an :class:`_engine.Engine`.
  2392. :meth:`_engine.Connection.begin` - start a :class:`.Transaction`
  2393. for a particular :class:`_engine.Connection`.
  2394. """
  2395. if self._connection_cls._is_future:
  2396. conn = self.connect()
  2397. else:
  2398. conn = self.connect(close_with_result=close_with_result)
  2399. try:
  2400. trans = conn.begin()
  2401. except:
  2402. with util.safe_reraise():
  2403. conn.close()
  2404. return Engine._trans_ctx(conn, trans, close_with_result)
  2405. @util.deprecated(
  2406. "1.4",
  2407. "The :meth:`_engine.Engine.transaction` "
  2408. "method is deprecated and will be "
  2409. "removed in a future release. Use the :meth:`_engine.Engine.begin` "
  2410. "context "
  2411. "manager instead.",
  2412. )
  2413. def transaction(self, callable_, *args, **kwargs):
  2414. r"""Execute the given function within a transaction boundary.
  2415. The function is passed a :class:`_engine.Connection` newly procured
  2416. from :meth:`_engine.Engine.connect` as the first argument,
  2417. followed by the given \*args and \**kwargs.
  2418. e.g.::
  2419. def do_something(conn, x, y):
  2420. conn.execute(text("some statement"), {'x':x, 'y':y})
  2421. engine.transaction(do_something, 5, 10)
  2422. The operations inside the function are all invoked within the
  2423. context of a single :class:`.Transaction`.
  2424. Upon success, the transaction is committed. If an
  2425. exception is raised, the transaction is rolled back
  2426. before propagating the exception.
  2427. .. note::
  2428. The :meth:`.transaction` method is superseded by
  2429. the usage of the Python ``with:`` statement, which can
  2430. be used with :meth:`_engine.Engine.begin`::
  2431. with engine.begin() as conn:
  2432. conn.execute(text("some statement"), {'x':5, 'y':10})
  2433. .. seealso::
  2434. :meth:`_engine.Engine.begin` - engine-level transactional
  2435. context
  2436. :meth:`_engine.Connection.transaction`
  2437. - connection-level version of
  2438. :meth:`_engine.Engine.transaction`
  2439. """
  2440. kwargs["_sa_skip_warning"] = True
  2441. with self.connect() as conn:
  2442. return conn.transaction(callable_, *args, **kwargs)
  2443. @util.deprecated(
  2444. "1.4",
  2445. "The :meth:`_engine.Engine.run_callable` "
  2446. "method is deprecated and will be "
  2447. "removed in a future release. Use the :meth:`_engine.Engine.begin` "
  2448. "context manager instead.",
  2449. )
  2450. def run_callable(self, callable_, *args, **kwargs):
  2451. r"""Given a callable object or function, execute it, passing
  2452. a :class:`_engine.Connection` as the first argument.
  2453. The given \*args and \**kwargs are passed subsequent
  2454. to the :class:`_engine.Connection` argument.
  2455. This function, along with :meth:`_engine.Connection.run_callable`,
  2456. allows a function to be run with a :class:`_engine.Connection`
  2457. or :class:`_engine.Engine` object without the need to know
  2458. which one is being dealt with.
  2459. """
  2460. kwargs["_sa_skip_warning"] = True
  2461. with self.connect() as conn:
  2462. return conn.run_callable(callable_, *args, **kwargs)
  2463. def _run_ddl_visitor(self, visitorcallable, element, **kwargs):
  2464. with self.begin() as conn:
  2465. conn._run_ddl_visitor(visitorcallable, element, **kwargs)
  2466. @util.deprecated_20(
  2467. ":meth:`_engine.Engine.execute`",
  2468. alternative="All statement execution in SQLAlchemy 2.0 is performed "
  2469. "by the :meth:`_engine.Connection.execute` method of "
  2470. ":class:`_engine.Connection`, "
  2471. "or in the ORM by the :meth:`.Session.execute` method of "
  2472. ":class:`.Session`.",
  2473. )
  2474. def execute(self, statement, *multiparams, **params):
  2475. """Executes the given construct and returns a
  2476. :class:`_engine.CursorResult`.
  2477. The arguments are the same as those used by
  2478. :meth:`_engine.Connection.execute`.
  2479. Here, a :class:`_engine.Connection` is acquired using the
  2480. :meth:`_engine.Engine.connect` method, and the statement executed
  2481. with that connection. The returned :class:`_engine.CursorResult`
  2482. is flagged
  2483. such that when the :class:`_engine.CursorResult` is exhausted and its
  2484. underlying cursor is closed, the :class:`_engine.Connection`
  2485. created here
  2486. will also be closed, which allows its associated DBAPI connection
  2487. resource to be returned to the connection pool.
  2488. """
  2489. connection = self.connect(close_with_result=True)
  2490. return connection.execute(statement, *multiparams, **params)
  2491. @util.deprecated_20(
  2492. ":meth:`_engine.Engine.scalar`",
  2493. alternative="All statement execution in SQLAlchemy 2.0 is performed "
  2494. "by the :meth:`_engine.Connection.execute` method of "
  2495. ":class:`_engine.Connection`, "
  2496. "or in the ORM by the :meth:`.Session.execute` method of "
  2497. ":class:`.Session`; the :meth:`_future.Result.scalar` "
  2498. "method can then be "
  2499. "used to return a scalar result.",
  2500. )
  2501. def scalar(self, statement, *multiparams, **params):
  2502. """Executes and returns the first column of the first row.
  2503. The underlying result/cursor is closed after execution.
  2504. """
  2505. return self.execute(statement, *multiparams, **params).scalar()
  2506. def _execute_clauseelement(
  2507. self,
  2508. elem,
  2509. multiparams=None,
  2510. params=None,
  2511. execution_options=_EMPTY_EXECUTION_OPTS,
  2512. ):
  2513. connection = self.connect(close_with_result=True)
  2514. return connection._execute_clauseelement(
  2515. elem, multiparams, params, execution_options
  2516. )
  2517. def _execute_compiled(
  2518. self,
  2519. compiled,
  2520. multiparams,
  2521. params,
  2522. execution_options=_EMPTY_EXECUTION_OPTS,
  2523. ):
  2524. connection = self.connect(close_with_result=True)
  2525. return connection._execute_compiled(
  2526. compiled, multiparams, params, execution_options
  2527. )
  2528. def connect(self, close_with_result=False):
  2529. """Return a new :class:`_engine.Connection` object.
  2530. The :class:`_engine.Connection` object is a facade that uses a DBAPI
  2531. connection internally in order to communicate with the database. This
  2532. connection is procured from the connection-holding :class:`_pool.Pool`
  2533. referenced by this :class:`_engine.Engine`. When the
  2534. :meth:`_engine.Connection.close` method of the
  2535. :class:`_engine.Connection` object
  2536. is called, the underlying DBAPI connection is then returned to the
  2537. connection pool, where it may be used again in a subsequent call to
  2538. :meth:`_engine.Engine.connect`.
  2539. """
  2540. return self._connection_cls(self, close_with_result=close_with_result)
  2541. @util.deprecated(
  2542. "1.4",
  2543. "The :meth:`_engine.Engine.table_names` "
  2544. "method is deprecated and will be "
  2545. "removed in a future release. Please refer to "
  2546. ":meth:`_reflection.Inspector.get_table_names`.",
  2547. )
  2548. def table_names(self, schema=None, connection=None):
  2549. """Return a list of all table names available in the database.
  2550. :param schema: Optional, retrieve names from a non-default schema.
  2551. :param connection: Optional, use a specified connection.
  2552. """
  2553. with self._optional_conn_ctx_manager(connection) as conn:
  2554. insp = inspection.inspect(conn)
  2555. return insp.get_table_names(schema)
  2556. @util.deprecated(
  2557. "1.4",
  2558. "The :meth:`_engine.Engine.has_table` "
  2559. "method is deprecated and will be "
  2560. "removed in a future release. Please refer to "
  2561. ":meth:`_reflection.Inspector.has_table`.",
  2562. )
  2563. def has_table(self, table_name, schema=None):
  2564. """Return True if the given backend has a table of the given name.
  2565. .. seealso::
  2566. :ref:`metadata_reflection_inspector` - detailed schema inspection
  2567. using the :class:`_reflection.Inspector` interface.
  2568. :class:`.quoted_name` - used to pass quoting information along
  2569. with a schema identifier.
  2570. """
  2571. with self._optional_conn_ctx_manager(None) as conn:
  2572. insp = inspection.inspect(conn)
  2573. return insp.has_table(table_name, schema=schema)
  2574. def _wrap_pool_connect(self, fn, connection):
  2575. dialect = self.dialect
  2576. try:
  2577. return fn()
  2578. except dialect.dbapi.Error as e:
  2579. if connection is None:
  2580. Connection._handle_dbapi_exception_noconnection(
  2581. e, dialect, self
  2582. )
  2583. else:
  2584. util.raise_(
  2585. sys.exc_info()[1], with_traceback=sys.exc_info()[2]
  2586. )
  2587. def raw_connection(self, _connection=None):
  2588. """Return a "raw" DBAPI connection from the connection pool.
  2589. The returned object is a proxied version of the DBAPI
  2590. connection object used by the underlying driver in use.
  2591. The object will have all the same behavior as the real DBAPI
  2592. connection, except that its ``close()`` method will result in the
  2593. connection being returned to the pool, rather than being closed
  2594. for real.
  2595. This method provides direct DBAPI connection access for
  2596. special situations when the API provided by
  2597. :class:`_engine.Connection`
  2598. is not needed. When a :class:`_engine.Connection` object is already
  2599. present, the DBAPI connection is available using
  2600. the :attr:`_engine.Connection.connection` accessor.
  2601. .. seealso::
  2602. :ref:`dbapi_connections`
  2603. """
  2604. return self._wrap_pool_connect(self.pool.connect, _connection)
  2605. class OptionEngineMixin(object):
  2606. _sa_propagate_class_events = False
  2607. def __init__(self, proxied, execution_options):
  2608. self._proxied = proxied
  2609. self.url = proxied.url
  2610. self.dialect = proxied.dialect
  2611. self.logging_name = proxied.logging_name
  2612. self.echo = proxied.echo
  2613. self._compiled_cache = proxied._compiled_cache
  2614. self.hide_parameters = proxied.hide_parameters
  2615. log.instance_logger(self, echoflag=self.echo)
  2616. # note: this will propagate events that are assigned to the parent
  2617. # engine after this OptionEngine is created. Since we share
  2618. # the events of the parent we also disallow class-level events
  2619. # to apply to the OptionEngine class directly.
  2620. #
  2621. # the other way this can work would be to transfer existing
  2622. # events only, using:
  2623. # self.dispatch._update(proxied.dispatch)
  2624. #
  2625. # that might be more appropriate however it would be a behavioral
  2626. # change for logic that assigns events to the parent engine and
  2627. # would like it to take effect for the already-created sub-engine.
  2628. self.dispatch = self.dispatch._join(proxied.dispatch)
  2629. self._execution_options = proxied._execution_options
  2630. self.update_execution_options(**execution_options)
  2631. def _get_pool(self):
  2632. return self._proxied.pool
  2633. def _set_pool(self, pool):
  2634. self._proxied.pool = pool
  2635. pool = property(_get_pool, _set_pool)
  2636. def _get_has_events(self):
  2637. return self._proxied._has_events or self.__dict__.get(
  2638. "_has_events", False
  2639. )
  2640. def _set_has_events(self, value):
  2641. self.__dict__["_has_events"] = value
  2642. _has_events = property(_get_has_events, _set_has_events)
  2643. class OptionEngine(OptionEngineMixin, Engine):
  2644. pass
  2645. Engine._option_cls = OptionEngine