Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py: 24%

1027 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:35 +0000

1# engine/base.py 

2# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

7from __future__ import with_statement 

8 

9import contextlib 

10import sys 

11 

12from .interfaces import Connectable 

13from .interfaces import ExceptionContext 

14from .util import _distill_params 

15from .util import _distill_params_20 

16from .util import TransactionalContext 

17from .. import exc 

18from .. import inspection 

19from .. import log 

20from .. import util 

21from ..sql import compiler 

22from ..sql import util as sql_util 

23 

24 

25"""Defines :class:`_engine.Connection` and :class:`_engine.Engine`. 

26 

27""" 

28 

29_EMPTY_EXECUTION_OPTS = util.immutabledict() 

30 

31 

32class Connection(Connectable): 

33 """Provides high-level functionality for a wrapped DB-API connection. 

34 

35 **This is the SQLAlchemy 1.x.x version** of the :class:`_engine.Connection` 

36 class. For the :term:`2.0 style` version, which features some API 

37 differences, see :class:`_future.Connection`. 

38 

39 The :class:`_engine.Connection` object is procured by calling 

40 the :meth:`_engine.Engine.connect` method of the :class:`_engine.Engine` 

41 object, and provides services for execution of SQL statements as well 

42 as transaction control. 

43 

44 The Connection object is **not** thread-safe. While a Connection can be 

45 shared among threads using properly synchronized access, it is still 

46 possible that the underlying DBAPI connection may not support shared 

47 access between threads. Check the DBAPI documentation for details. 

48 

49 The Connection object represents a single DBAPI connection checked out 

50 from the connection pool. In this state, the connection pool has no affect 

51 upon the connection, including its expiration or timeout state. For the 

52 connection pool to properly manage connections, connections should be 

53 returned to the connection pool (i.e. ``connection.close()``) whenever the 

54 connection is not in use. 

55 

56 .. index:: 

57 single: thread safety; Connection 

58 

59 """ 

60 

61 _is_future = False 

62 _sqla_logger_namespace = "sqlalchemy.engine.Connection" 

63 

64 # used by sqlalchemy.engine.util.TransactionalContext 

65 _trans_context_manager = None 

66 

67 def __init__( 

68 self, 

69 engine, 

70 connection=None, 

71 close_with_result=False, 

72 _branch_from=None, 

73 _execution_options=None, 

74 _dispatch=None, 

75 _has_events=None, 

76 _allow_revalidate=True, 

77 ): 

78 """Construct a new Connection.""" 

79 self.engine = engine 

80 self.dialect = engine.dialect 

81 self.__branch_from = _branch_from 

82 

83 if _branch_from: 

84 # branching is always "from" the root connection 

85 assert _branch_from.__branch_from is None 

86 self._dbapi_connection = connection 

87 self._execution_options = _execution_options 

88 self._echo = _branch_from._echo 

89 self.should_close_with_result = False 

90 self.dispatch = _dispatch 

91 self._has_events = _branch_from._has_events 

92 else: 

93 self._dbapi_connection = ( 

94 connection 

95 if connection is not None 

96 else engine.raw_connection() 

97 ) 

98 

99 self._transaction = self._nested_transaction = None 

100 self.__savepoint_seq = 0 

101 self.__in_begin = False 

102 self.should_close_with_result = close_with_result 

103 

104 self.__can_reconnect = _allow_revalidate 

105 self._echo = self.engine._should_log_info() 

106 

107 if _has_events is None: 

108 # if _has_events is sent explicitly as False, 

109 # then don't join the dispatch of the engine; we don't 

110 # want to handle any of the engine's events in that case. 

111 self.dispatch = self.dispatch._join(engine.dispatch) 

112 self._has_events = _has_events or ( 

113 _has_events is None and engine._has_events 

114 ) 

115 

116 assert not _execution_options 

117 self._execution_options = engine._execution_options 

118 

119 if self._has_events or self.engine._has_events: 

120 self.dispatch.engine_connect(self, _branch_from is not None) 

121 

122 @util.memoized_property 

123 def _message_formatter(self): 

124 if "logging_token" in self._execution_options: 

125 token = self._execution_options["logging_token"] 

126 return lambda msg: "[%s] %s" % (token, msg) 

127 else: 

128 return None 

129 

130 def _log_info(self, message, *arg, **kw): 

131 fmt = self._message_formatter 

132 

133 if fmt: 

134 message = fmt(message) 

135 

136 if log.STACKLEVEL: 

137 kw["stacklevel"] = 1 + log.STACKLEVEL_OFFSET 

138 

139 self.engine.logger.info(message, *arg, **kw) 

140 

141 def _log_debug(self, message, *arg, **kw): 

142 fmt = self._message_formatter 

143 

144 if fmt: 

145 message = fmt(message) 

146 

147 if log.STACKLEVEL: 

148 kw["stacklevel"] = 1 + log.STACKLEVEL_OFFSET 

149 

150 self.engine.logger.debug(message, *arg, **kw) 

151 

152 @property 

153 def _schema_translate_map(self): 

154 return self._execution_options.get("schema_translate_map", None) 

155 

156 def schema_for_object(self, obj): 

157 """Return the schema name for the given schema item taking into 

158 account current schema translate map. 

159 

160 """ 

161 

162 name = obj.schema 

163 schema_translate_map = self._execution_options.get( 

164 "schema_translate_map", None 

165 ) 

166 

167 if ( 

168 schema_translate_map 

169 and name in schema_translate_map 

170 and obj._use_schema_map 

171 ): 

172 return schema_translate_map[name] 

173 else: 

174 return name 

175 

176 def _branch(self): 

177 """Return a new Connection which references this Connection's 

178 engine and connection; but does not have close_with_result enabled, 

179 and also whose close() method does nothing. 

180 

181 .. deprecated:: 1.4 the "branching" concept will be removed in 

182 SQLAlchemy 2.0 as well as the "Connection.connect()" method which 

183 is the only consumer for this. 

184 

185 The Core uses this very sparingly, only in the case of 

186 custom SQL default functions that are to be INSERTed as the 

187 primary key of a row where we need to get the value back, so we have 

188 to invoke it distinctly - this is a very uncommon case. 

189 

190 Userland code accesses _branch() when the connect() 

191 method is called. The branched connection 

192 acts as much as possible like the parent, except that it stays 

193 connected when a close() event occurs. 

194 

195 """ 

196 return self.engine._connection_cls( 

197 self.engine, 

198 self._dbapi_connection, 

199 _branch_from=self.__branch_from if self.__branch_from else self, 

200 _execution_options=self._execution_options, 

201 _has_events=self._has_events, 

202 _dispatch=self.dispatch, 

203 ) 

204 

205 def _generate_for_options(self): 

206 """define connection method chaining behavior for execution_options""" 

207 

208 if self._is_future: 

209 return self 

210 else: 

211 c = self.__class__.__new__(self.__class__) 

212 c.__dict__ = self.__dict__.copy() 

213 return c 

214 

215 def __enter__(self): 

216 return self 

217 

218 def __exit__(self, type_, value, traceback): 

219 self.close() 

220 

221 def execution_options(self, **opt): 

222 r""" Set non-SQL options for the connection which take effect 

223 during execution. 

224 

225 For a "future" style connection, this method returns this same 

226 :class:`_future.Connection` object with the new options added. 

227 

228 For a legacy connection, this method returns a copy of this 

229 :class:`_engine.Connection` which references the same underlying DBAPI 

230 connection, but also defines the given execution options which will 

231 take effect for a call to 

232 :meth:`execute`. As the new :class:`_engine.Connection` references the 

233 same underlying resource, it's usually a good idea to ensure that 

234 the copies will be discarded immediately, which is implicit if used 

235 as in:: 

236 

237 result = connection.execution_options(stream_results=True).\ 

238 execute(stmt) 

239 

240 Note that any key/value can be passed to 

241 :meth:`_engine.Connection.execution_options`, 

242 and it will be stored in the 

243 ``_execution_options`` dictionary of the :class:`_engine.Connection`. 

244 It 

245 is suitable for usage by end-user schemes to communicate with 

246 event listeners, for example. 

247 

248 The keywords that are currently recognized by SQLAlchemy itself 

249 include all those listed under :meth:`.Executable.execution_options`, 

250 as well as others that are specific to :class:`_engine.Connection`. 

251 

252 :param autocommit: Available on: Connection, statement. 

253 When True, a COMMIT will be invoked after execution 

254 when executed in 'autocommit' mode, i.e. when an explicit 

255 transaction is not begun on the connection. Note that this 

256 is **library level, not DBAPI level autocommit**. The DBAPI 

257 connection will remain in a real transaction unless the 

258 "AUTOCOMMIT" isolation level is used. 

259 

260 .. deprecated:: 1.4 The "autocommit" execution option is deprecated 

261 and will be removed in SQLAlchemy 2.0. See 

262 :ref:`migration_20_autocommit` for discussion. 

263 

264 :param compiled_cache: Available on: Connection. 

265 A dictionary where :class:`.Compiled` objects 

266 will be cached when the :class:`_engine.Connection` 

267 compiles a clause 

268 expression into a :class:`.Compiled` object. This dictionary will 

269 supersede the statement cache that may be configured on the 

270 :class:`_engine.Engine` itself. If set to None, caching 

271 is disabled, even if the engine has a configured cache size. 

272 

273 Note that the ORM makes use of its own "compiled" caches for 

274 some operations, including flush operations. The caching 

275 used by the ORM internally supersedes a cache dictionary 

276 specified here. 

277 

278 :param logging_token: Available on: :class:`_engine.Connection`, 

279 :class:`_engine.Engine`. 

280 

281 Adds the specified string token surrounded by brackets in log 

282 messages logged by the connection, i.e. the logging that's enabled 

283 either via the :paramref:`_sa.create_engine.echo` flag or via the 

284 ``logging.getLogger("sqlalchemy.engine")`` logger. This allows a 

285 per-connection or per-sub-engine token to be available which is 

286 useful for debugging concurrent connection scenarios. 

287 

288 .. versionadded:: 1.4.0b2 

289 

290 .. seealso:: 

291 

292 :ref:`dbengine_logging_tokens` - usage example 

293 

294 :paramref:`_sa.create_engine.logging_name` - adds a name to the 

295 name used by the Python logger object itself. 

296 

297 :param isolation_level: Available on: :class:`_engine.Connection`. 

298 

299 Set the transaction isolation level for the lifespan of this 

300 :class:`_engine.Connection` object. 

301 Valid values include those string 

302 values accepted by the :paramref:`_sa.create_engine.isolation_level` 

303 parameter passed to :func:`_sa.create_engine`. These levels are 

304 semi-database specific; see individual dialect documentation for 

305 valid levels. 

306 

307 The isolation level option applies the isolation level by emitting 

308 statements on the DBAPI connection, and **necessarily affects the 

309 original Connection object overall**, not just the copy that is 

310 returned by the call to :meth:`_engine.Connection.execution_options` 

311 method. The isolation level will remain at the given setting until 

312 the DBAPI connection itself is returned to the connection pool, i.e. 

313 the :meth:`_engine.Connection.close` method on the original 

314 :class:`_engine.Connection` is called, 

315 where an event handler will emit 

316 additional statements on the DBAPI connection in order to revert the 

317 isolation level change. 

318 

319 .. warning:: The ``isolation_level`` execution option should 

320 **not** be used when a transaction is already established, that 

321 is, the :meth:`_engine.Connection.begin` 

322 method or similar has been 

323 called. A database cannot change the isolation level on a 

324 transaction in progress, and different DBAPIs and/or 

325 SQLAlchemy dialects may implicitly roll back or commit 

326 the transaction, or not affect the connection at all. 

327 

328 .. note:: The ``isolation_level`` execution option is implicitly 

329 reset if the :class:`_engine.Connection` is invalidated, e.g. via 

330 the :meth:`_engine.Connection.invalidate` method, or if a 

331 disconnection error occurs. The new connection produced after 

332 the invalidation will not have the isolation level re-applied 

333 to it automatically. 

334 

335 .. seealso:: 

336 

337 :paramref:`_sa.create_engine.isolation_level` 

338 - set per :class:`_engine.Engine` isolation level 

339 

340 :meth:`_engine.Connection.get_isolation_level` 

341 - view current actual level 

342 

343 :ref:`SQLite Transaction Isolation <sqlite_isolation_level>` 

344 

345 :ref:`PostgreSQL Transaction Isolation <postgresql_isolation_level>` 

346 

347 :ref:`MySQL Transaction Isolation <mysql_isolation_level>` 

348 

349 :ref:`SQL Server Transaction Isolation <mssql_isolation_level>` 

350 

351 :ref:`session_transaction_isolation` - for the ORM 

352 

353 :param no_parameters: When ``True``, if the final parameter 

354 list or dictionary is totally empty, will invoke the 

355 statement on the cursor as ``cursor.execute(statement)``, 

356 not passing the parameter collection at all. 

357 Some DBAPIs such as psycopg2 and mysql-python consider 

358 percent signs as significant only when parameters are 

359 present; this option allows code to generate SQL 

360 containing percent signs (and possibly other characters) 

361 that is neutral regarding whether it's executed by the DBAPI 

362 or piped into a script that's later invoked by 

363 command line tools. 

364 

365 :param stream_results: Available on: Connection, statement. 

366 Indicate to the dialect that results should be 

367 "streamed" and not pre-buffered, if possible. For backends 

368 such as PostgreSQL, MySQL and MariaDB, this indicates the use of 

369 a "server side cursor" as opposed to a client side cursor. 

370 Other backends such as that of Oracle may already use server 

371 side cursors by default. 

372 

373 The usage of 

374 :paramref:`_engine.Connection.execution_options.stream_results` is 

375 usually combined with setting a fixed number of rows to to be fetched 

376 in batches, to allow for efficient iteration of database rows while 

377 at the same time not loading all result rows into memory at once; 

378 this can be configured on a :class:`_engine.Result` object using the 

379 :meth:`_engine.Result.yield_per` method, after execution has 

380 returned a new :class:`_engine.Result`. If 

381 :meth:`_engine.Result.yield_per` is not used, 

382 the :paramref:`_engine.Connection.execution_options.stream_results` 

383 mode of operation will instead use a dynamically sized buffer 

384 which buffers sets of rows at a time, growing on each batch 

385 based on a fixed growth size up until a limit which may 

386 be configured using the 

387 :paramref:`_engine.Connection.execution_options.max_row_buffer` 

388 parameter. 

389 

390 When using the ORM to fetch ORM mapped objects from a result, 

391 :meth:`_engine.Result.yield_per` should always be used with 

392 :paramref:`_engine.Connection.execution_options.stream_results`, 

393 so that the ORM does not fetch all rows into new ORM objects at once. 

394 

395 For typical use, the 

396 :paramref:`_engine.Connection.execution_options.yield_per` execution 

397 option should be preferred, which sets up both 

398 :paramref:`_engine.Connection.execution_options.stream_results` and 

399 :meth:`_engine.Result.yield_per` at once. This option is supported 

400 both at a core level by :class:`_engine.Connection` as well as by the 

401 ORM :class:`_engine.Session`; the latter is described at 

402 :ref:`orm_queryguide_yield_per`. 

403 

404 .. seealso:: 

405 

406 :ref:`engine_stream_results` - background on 

407 :paramref:`_engine.Connection.execution_options.stream_results` 

408 

409 :paramref:`_engine.Connection.execution_options.max_row_buffer` 

410 

411 :paramref:`_engine.Connection.execution_options.yield_per` 

412 

413 :ref:`orm_queryguide_yield_per` - in the :ref:`queryguide_toplevel` 

414 describing the ORM version of ``yield_per`` 

415 

416 :param max_row_buffer: Available on: :class:`_engine.Connection`, 

417 :class:`_sql.Executable`. Sets a maximum 

418 buffer size to use when the 

419 :paramref:`_engine.Connection.execution_options.stream_results` 

420 execution option is used on a backend that supports server side 

421 cursors. The default value if not specified is 1000. 

422 

423 .. seealso:: 

424 

425 :paramref:`_engine.Connection.execution_options.stream_results` 

426 

427 :ref:`engine_stream_results` 

428 

429 

430 :param yield_per: Available on: :class:`_engine.Connection`, 

431 :class:`_sql.Executable`. Integer value applied which will 

432 set the :paramref:`_engine.Connection.execution_options.stream_results` 

433 execution option and invoke :meth:`_engine.Result.yield_per` 

434 automatically at once. Allows equivalent functionality as 

435 is present when using this parameter with the ORM. 

436 

437 .. versionadded:: 1.4.40 

438 

439 .. seealso:: 

440 

441 :ref:`engine_stream_results` - background and examples 

442 on using server side cursors with Core. 

443 

444 :ref:`orm_queryguide_yield_per` - in the :ref:`queryguide_toplevel` 

445 describing the ORM version of ``yield_per`` 

446 

447 :param schema_translate_map: Available on: :class:`_engine.Connection`, 

448 :class:`_engine.Engine`, :class:`_sql.Executable`. 

449 

450 :param schema_translate_map: Available on: Connection, Engine. 

451 A dictionary mapping schema names to schema names, that will be 

452 applied to the :paramref:`_schema.Table.schema` element of each 

453 :class:`_schema.Table` 

454 encountered when SQL or DDL expression elements 

455 are compiled into strings; the resulting schema name will be 

456 converted based on presence in the map of the original name. 

457 

458 .. versionadded:: 1.1 

459 

460 .. seealso:: 

461 

462 :ref:`schema_translating` 

463 

464 .. seealso:: 

465 

466 :meth:`_engine.Engine.execution_options` 

467 

468 :meth:`.Executable.execution_options` 

469 

470 :meth:`_engine.Connection.get_execution_options` 

471 

472 

473 """ # noqa 

474 c = self._generate_for_options() 

475 c._execution_options = c._execution_options.union(opt) 

476 if self._has_events or self.engine._has_events: 

477 self.dispatch.set_connection_execution_options(c, opt) 

478 self.dialect.set_connection_execution_options(c, opt) 

479 return c 

480 

481 def get_execution_options(self): 

482 """Get the non-SQL options which will take effect during execution. 

483 

484 .. versionadded:: 1.3 

485 

486 .. seealso:: 

487 

488 :meth:`_engine.Connection.execution_options` 

489 """ 

490 return self._execution_options 

491 

492 @property 

493 def closed(self): 

494 """Return True if this connection is closed.""" 

495 

496 # note this is independent for a "branched" connection vs. 

497 # the base 

498 

499 return self._dbapi_connection is None and not self.__can_reconnect 

500 

501 @property 

502 def invalidated(self): 

503 """Return True if this connection was invalidated.""" 

504 

505 # prior to 1.4, "invalid" was stored as a state independent of 

506 # "closed", meaning an invalidated connection could be "closed", 

507 # the _dbapi_connection would be None and closed=True, yet the 

508 # "invalid" flag would stay True. This meant that there were 

509 # three separate states (open/valid, closed/valid, closed/invalid) 

510 # when there is really no reason for that; a connection that's 

511 # "closed" does not need to be "invalid". So the state is now 

512 # represented by the two facts alone. 

513 

514 if self.__branch_from: 

515 return self.__branch_from.invalidated 

516 

517 return self._dbapi_connection is None and not self.closed 

518 

519 @property 

520 def connection(self): 

521 """The underlying DB-API connection managed by this Connection. 

522 

523 This is a SQLAlchemy connection-pool proxied connection 

524 which then has the attribute 

525 :attr:`_pool._ConnectionFairy.dbapi_connection` that refers to the 

526 actual driver connection. 

527 

528 .. seealso:: 

529 

530 

531 :ref:`dbapi_connections` 

532 

533 """ 

534 

535 if self._dbapi_connection is None: 

536 try: 

537 return self._revalidate_connection() 

538 except (exc.PendingRollbackError, exc.ResourceClosedError): 

539 raise 

540 except BaseException as e: 

541 self._handle_dbapi_exception(e, None, None, None, None) 

542 else: 

543 return self._dbapi_connection 

544 

545 def get_isolation_level(self): 

546 """Return the current **actual** isolation level that's present on 

547 the database within the scope of this connection. 

548 

549 This attribute will perform a live SQL operation against the database 

550 in order to procure the current isolation level, so the value returned 

551 is the actual level on the underlying DBAPI connection regardless of 

552 how this state was set. This will be one of the four actual isolation 

553 modes ``READ UNCOMMITTED``, ``READ COMMITTED``, ``REPEATABLE READ``, 

554 ``SERIALIZABLE``. It will **not** include the ``AUTOCOMMIT`` isolation 

555 level setting. Third party dialects may also feature additional 

556 isolation level settings. 

557 

558 .. note:: This method **will not report** on the ``AUTOCOMMIT`` 

559 isolation level, which is a separate :term:`dbapi` setting that's 

560 independent of **actual** isolation level. When ``AUTOCOMMIT`` is 

561 in use, the database connection still has a "traditional" isolation 

562 mode in effect, that is typically one of the four values 

563 ``READ UNCOMMITTED``, ``READ COMMITTED``, ``REPEATABLE READ``, 

564 ``SERIALIZABLE``. 

565 

566 Compare to the :attr:`_engine.Connection.default_isolation_level` 

567 accessor which returns the isolation level that is present on the 

568 database at initial connection time. 

569 

570 .. versionadded:: 0.9.9 

571 

572 .. seealso:: 

573 

574 :attr:`_engine.Connection.default_isolation_level` 

575 - view default level 

576 

577 :paramref:`_sa.create_engine.isolation_level` 

578 - set per :class:`_engine.Engine` isolation level 

579 

580 :paramref:`.Connection.execution_options.isolation_level` 

581 - set per :class:`_engine.Connection` isolation level 

582 

583 """ 

584 try: 

585 return self.dialect.get_isolation_level(self.connection) 

586 except BaseException as e: 

587 self._handle_dbapi_exception(e, None, None, None, None) 

588 

589 @property 

590 def default_isolation_level(self): 

591 """The initial-connection time isolation level associated with the 

592 :class:`_engine.Dialect` in use. 

593 

594 This value is independent of the 

595 :paramref:`.Connection.execution_options.isolation_level` and 

596 :paramref:`.Engine.execution_options.isolation_level` execution 

597 options, and is determined by the :class:`_engine.Dialect` when the 

598 first connection is created, by performing a SQL query against the 

599 database for the current isolation level before any additional commands 

600 have been emitted. 

601 

602 Calling this accessor does not invoke any new SQL queries. 

603 

604 .. versionadded:: 0.9.9 

605 

606 .. seealso:: 

607 

608 :meth:`_engine.Connection.get_isolation_level` 

609 - view current actual isolation level 

610 

611 :paramref:`_sa.create_engine.isolation_level` 

612 - set per :class:`_engine.Engine` isolation level 

613 

614 :paramref:`.Connection.execution_options.isolation_level` 

615 - set per :class:`_engine.Connection` isolation level 

616 

617 """ 

618 return self.dialect.default_isolation_level 

619 

620 def _invalid_transaction(self): 

621 if self.invalidated: 

622 raise exc.PendingRollbackError( 

623 "Can't reconnect until invalid %stransaction is rolled " 

624 "back." 

625 % ( 

626 "savepoint " 

627 if self._nested_transaction is not None 

628 else "" 

629 ), 

630 code="8s2b", 

631 ) 

632 else: 

633 assert not self._is_future 

634 raise exc.PendingRollbackError( 

635 "This connection is on an inactive %stransaction. " 

636 "Please rollback() fully before proceeding." 

637 % ( 

638 "savepoint " 

639 if self._nested_transaction is not None 

640 else "" 

641 ), 

642 code="8s2a", 

643 ) 

644 

645 def _revalidate_connection(self): 

646 if self.__branch_from: 

647 return self.__branch_from._revalidate_connection() 

648 if self.__can_reconnect and self.invalidated: 

649 if self._transaction is not None: 

650 self._invalid_transaction() 

651 self._dbapi_connection = self.engine.raw_connection( 

652 _connection=self 

653 ) 

654 return self._dbapi_connection 

655 raise exc.ResourceClosedError("This Connection is closed") 

656 

657 @property 

658 def _still_open_and_dbapi_connection_is_valid(self): 

659 return self._dbapi_connection is not None and getattr( 

660 self._dbapi_connection, "is_valid", False 

661 ) 

662 

663 @property 

664 def info(self): 

665 """Info dictionary associated with the underlying DBAPI connection 

666 referred to by this :class:`_engine.Connection`, allowing user-defined 

667 data to be associated with the connection. 

668 

669 The data here will follow along with the DBAPI connection including 

670 after it is returned to the connection pool and used again 

671 in subsequent instances of :class:`_engine.Connection`. 

672 

673 """ 

674 

675 return self.connection.info 

676 

677 @util.deprecated_20(":meth:`.Connection.connect`") 

678 def connect(self, close_with_result=False): 

679 """Returns a branched version of this :class:`_engine.Connection`. 

680 

681 The :meth:`_engine.Connection.close` method on the returned 

682 :class:`_engine.Connection` can be called and this 

683 :class:`_engine.Connection` will remain open. 

684 

685 This method provides usage symmetry with 

686 :meth:`_engine.Engine.connect`, including for usage 

687 with context managers. 

688 

689 """ 

690 

691 return self._branch() 

692 

693 def invalidate(self, exception=None): 

694 """Invalidate the underlying DBAPI connection associated with 

695 this :class:`_engine.Connection`. 

696 

697 An attempt will be made to close the underlying DBAPI connection 

698 immediately; however if this operation fails, the error is logged 

699 but not raised. The connection is then discarded whether or not 

700 close() succeeded. 

701 

702 Upon the next use (where "use" typically means using the 

703 :meth:`_engine.Connection.execute` method or similar), 

704 this :class:`_engine.Connection` will attempt to 

705 procure a new DBAPI connection using the services of the 

706 :class:`_pool.Pool` as a source of connectivity (e.g. 

707 a "reconnection"). 

708 

709 If a transaction was in progress (e.g. the 

710 :meth:`_engine.Connection.begin` method has been called) when 

711 :meth:`_engine.Connection.invalidate` method is called, at the DBAPI 

712 level all state associated with this transaction is lost, as 

713 the DBAPI connection is closed. The :class:`_engine.Connection` 

714 will not allow a reconnection to proceed until the 

715 :class:`.Transaction` object is ended, by calling the 

716 :meth:`.Transaction.rollback` method; until that point, any attempt at 

717 continuing to use the :class:`_engine.Connection` will raise an 

718 :class:`~sqlalchemy.exc.InvalidRequestError`. 

719 This is to prevent applications from accidentally 

720 continuing an ongoing transactional operations despite the 

721 fact that the transaction has been lost due to an 

722 invalidation. 

723 

724 The :meth:`_engine.Connection.invalidate` method, 

725 just like auto-invalidation, 

726 will at the connection pool level invoke the 

727 :meth:`_events.PoolEvents.invalidate` event. 

728 

729 :param exception: an optional ``Exception`` instance that's the 

730 reason for the invalidation. is passed along to event handlers 

731 and logging functions. 

732 

733 .. seealso:: 

734 

735 :ref:`pool_connection_invalidation` 

736 

737 """ 

738 

739 if self.__branch_from: 

740 return self.__branch_from.invalidate(exception=exception) 

741 

742 if self.invalidated: 

743 return 

744 

745 if self.closed: 

746 raise exc.ResourceClosedError("This Connection is closed") 

747 

748 if self._still_open_and_dbapi_connection_is_valid: 

749 self._dbapi_connection.invalidate(exception) 

750 self._dbapi_connection = None 

751 

752 def detach(self): 

753 """Detach the underlying DB-API connection from its connection pool. 

754 

755 E.g.:: 

756 

757 with engine.connect() as conn: 

758 conn.detach() 

759 conn.execute(text("SET search_path TO schema1, schema2")) 

760 

761 # work with connection 

762 

763 # connection is fully closed (since we used "with:", can 

764 # also call .close()) 

765 

766 This :class:`_engine.Connection` instance will remain usable. 

767 When closed 

768 (or exited from a context manager context as above), 

769 the DB-API connection will be literally closed and not 

770 returned to its originating pool. 

771 

772 This method can be used to insulate the rest of an application 

773 from a modified state on a connection (such as a transaction 

774 isolation level or similar). 

775 

776 """ 

777 

778 self._dbapi_connection.detach() 

779 

780 def _autobegin(self): 

781 self.begin() 

782 

783 def begin(self): 

784 """Begin a transaction and return a transaction handle. 

785 

786 The returned object is an instance of :class:`.Transaction`. 

787 This object represents the "scope" of the transaction, 

788 which completes when either the :meth:`.Transaction.rollback` 

789 or :meth:`.Transaction.commit` method is called. 

790 

791 .. tip:: 

792 

793 The :meth:`_engine.Connection.begin` method is invoked when using 

794 the :meth:`_engine.Engine.begin` context manager method as well. 

795 All documentation that refers to behaviors specific to the 

796 :meth:`_engine.Connection.begin` method also apply to use of the 

797 :meth:`_engine.Engine.begin` method. 

798 

799 Legacy use: nested calls to :meth:`.begin` on the same 

800 :class:`_engine.Connection` will return new :class:`.Transaction` 

801 objects that represent an emulated transaction within the scope of the 

802 enclosing transaction, that is:: 

803 

804 trans = conn.begin() # outermost transaction 

805 trans2 = conn.begin() # "nested" 

806 trans2.commit() # does nothing 

807 trans.commit() # actually commits 

808 

809 Calls to :meth:`.Transaction.commit` only have an effect 

810 when invoked via the outermost :class:`.Transaction` object, though the 

811 :meth:`.Transaction.rollback` method of any of the 

812 :class:`.Transaction` objects will roll back the 

813 transaction. 

814 

815 .. tip:: 

816 

817 The above "nesting" behavior is a legacy behavior specific to 

818 :term:`1.x style` use and will be removed in SQLAlchemy 2.0. For 

819 notes on :term:`2.0 style` use, see 

820 :meth:`_future.Connection.begin`. 

821 

822 

823 .. seealso:: 

824 

825 :meth:`_engine.Connection.begin_nested` - use a SAVEPOINT 

826 

827 :meth:`_engine.Connection.begin_twophase` - 

828 use a two phase /XID transaction 

829 

830 :meth:`_engine.Engine.begin` - context manager available from 

831 :class:`_engine.Engine` 

832 

833 """ 

834 if self._is_future: 

835 assert not self.__branch_from 

836 elif self.__branch_from: 

837 return self.__branch_from.begin() 

838 

839 if self.__in_begin: 

840 # for dialects that emit SQL within the process of 

841 # dialect.do_begin() or dialect.do_begin_twophase(), this 

842 # flag prevents "autobegin" from being emitted within that 

843 # process, while allowing self._transaction to remain at None 

844 # until it's complete. 

845 return 

846 elif self._transaction is None: 

847 self._transaction = RootTransaction(self) 

848 return self._transaction 

849 else: 

850 if self._is_future: 

851 raise exc.InvalidRequestError( 

852 "This connection has already initialized a SQLAlchemy " 

853 "Transaction() object via begin() or autobegin; can't " 

854 "call begin() here unless rollback() or commit() " 

855 "is called first." 

856 ) 

857 else: 

858 return MarkerTransaction(self) 

859 

860 def begin_nested(self): 

861 """Begin a nested transaction (i.e. SAVEPOINT) and return a 

862 transaction handle, assuming an outer transaction is already 

863 established. 

864 

865 Nested transactions require SAVEPOINT support in the 

866 underlying database. Any transaction in the hierarchy may 

867 ``commit`` and ``rollback``, however the outermost transaction 

868 still controls the overall ``commit`` or ``rollback`` of the 

869 transaction of a whole. 

870 

871 The legacy form of :meth:`_engine.Connection.begin_nested` method has 

872 alternate behaviors based on whether or not the 

873 :meth:`_engine.Connection.begin` method was called previously. If 

874 :meth:`_engine.Connection.begin` was not called, then this method will 

875 behave the same as the :meth:`_engine.Connection.begin` method and 

876 return a :class:`.RootTransaction` object that begins and commits a 

877 real transaction - **no savepoint is invoked**. If 

878 :meth:`_engine.Connection.begin` **has** been called, and a 

879 :class:`.RootTransaction` is already established, then this method 

880 returns an instance of :class:`.NestedTransaction` which will invoke 

881 and manage the scope of a SAVEPOINT. 

882 

883 .. tip:: 

884 

885 The above mentioned behavior of 

886 :meth:`_engine.Connection.begin_nested` is a legacy behavior 

887 specific to :term:`1.x style` use. In :term:`2.0 style` use, the 

888 :meth:`_future.Connection.begin_nested` method instead autobegins 

889 the outer transaction that can be committed using 

890 "commit-as-you-go" style; see 

891 :meth:`_future.Connection.begin_nested` for migration details. 

892 

893 .. versionchanged:: 1.4.13 The behavior of 

894 :meth:`_engine.Connection.begin_nested` 

895 as returning a :class:`.RootTransaction` if 

896 :meth:`_engine.Connection.begin` were not called has been restored 

897 as was the case in 1.3.x versions; in previous 1.4.x versions, an 

898 outer transaction would be "autobegun" but would not be committed. 

899 

900 

901 .. seealso:: 

902 

903 :meth:`_engine.Connection.begin` 

904 

905 :ref:`session_begin_nested` - ORM support for SAVEPOINT 

906 

907 """ 

908 if self._is_future: 

909 assert not self.__branch_from 

910 elif self.__branch_from: 

911 return self.__branch_from.begin_nested() 

912 

913 if self._transaction is None: 

914 if not self._is_future: 

915 util.warn_deprecated_20( 

916 "Calling Connection.begin_nested() in 2.0 style use will " 

917 "return a NestedTransaction (SAVEPOINT) in all cases, " 

918 "that will not commit the outer transaction. For code " 

919 "that is cross-compatible between 1.x and 2.0 style use, " 

920 "ensure Connection.begin() is called before calling " 

921 "Connection.begin_nested()." 

922 ) 

923 return self.begin() 

924 else: 

925 self._autobegin() 

926 

927 return NestedTransaction(self) 

928 

929 def begin_twophase(self, xid=None): 

930 """Begin a two-phase or XA transaction and return a transaction 

931 handle. 

932 

933 The returned object is an instance of :class:`.TwoPhaseTransaction`, 

934 which in addition to the methods provided by 

935 :class:`.Transaction`, also provides a 

936 :meth:`~.TwoPhaseTransaction.prepare` method. 

937 

938 :param xid: the two phase transaction id. If not supplied, a 

939 random id will be generated. 

940 

941 .. seealso:: 

942 

943 :meth:`_engine.Connection.begin` 

944 

945 :meth:`_engine.Connection.begin_twophase` 

946 

947 """ 

948 

949 if self.__branch_from: 

950 return self.__branch_from.begin_twophase(xid=xid) 

951 

952 if self._transaction is not None: 

953 raise exc.InvalidRequestError( 

954 "Cannot start a two phase transaction when a transaction " 

955 "is already in progress." 

956 ) 

957 if xid is None: 

958 xid = self.engine.dialect.create_xid() 

959 return TwoPhaseTransaction(self, xid) 

960 

961 def recover_twophase(self): 

962 return self.engine.dialect.do_recover_twophase(self) 

963 

964 def rollback_prepared(self, xid, recover=False): 

965 self.engine.dialect.do_rollback_twophase(self, xid, recover=recover) 

966 

967 def commit_prepared(self, xid, recover=False): 

968 self.engine.dialect.do_commit_twophase(self, xid, recover=recover) 

969 

970 def in_transaction(self): 

971 """Return True if a transaction is in progress.""" 

972 if self.__branch_from is not None: 

973 return self.__branch_from.in_transaction() 

974 

975 return self._transaction is not None and self._transaction.is_active 

976 

977 def in_nested_transaction(self): 

978 """Return True if a transaction is in progress.""" 

979 if self.__branch_from is not None: 

980 return self.__branch_from.in_nested_transaction() 

981 

982 return ( 

983 self._nested_transaction is not None 

984 and self._nested_transaction.is_active 

985 ) 

986 

987 def _is_autocommit_isolation(self): 

988 opt_iso = self._execution_options.get("isolation_level", None) 

989 return bool( 

990 opt_iso == "AUTOCOMMIT" 

991 or ( 

992 opt_iso is None 

993 and getattr(self.engine.dialect, "isolation_level", None) 

994 == "AUTOCOMMIT" 

995 ) 

996 ) 

997 

998 def get_transaction(self): 

999 """Return the current root transaction in progress, if any. 

1000 

1001 .. versionadded:: 1.4 

1002 

1003 """ 

1004 

1005 if self.__branch_from is not None: 

1006 return self.__branch_from.get_transaction() 

1007 

1008 return self._transaction 

1009 

1010 def get_nested_transaction(self): 

1011 """Return the current nested transaction in progress, if any. 

1012 

1013 .. versionadded:: 1.4 

1014 

1015 """ 

1016 if self.__branch_from is not None: 

1017 

1018 return self.__branch_from.get_nested_transaction() 

1019 

1020 return self._nested_transaction 

1021 

1022 def _begin_impl(self, transaction): 

1023 assert not self.__branch_from 

1024 

1025 if self._echo: 

1026 if self._is_autocommit_isolation(): 

1027 self._log_info( 

1028 "BEGIN (implicit; DBAPI should not BEGIN due to " 

1029 "autocommit mode)" 

1030 ) 

1031 else: 

1032 self._log_info("BEGIN (implicit)") 

1033 

1034 self.__in_begin = True 

1035 

1036 if self._has_events or self.engine._has_events: 

1037 self.dispatch.begin(self) 

1038 

1039 try: 

1040 self.engine.dialect.do_begin(self.connection) 

1041 except BaseException as e: 

1042 self._handle_dbapi_exception(e, None, None, None, None) 

1043 finally: 

1044 self.__in_begin = False 

1045 

1046 def _rollback_impl(self): 

1047 assert not self.__branch_from 

1048 

1049 if self._has_events or self.engine._has_events: 

1050 self.dispatch.rollback(self) 

1051 

1052 if self._still_open_and_dbapi_connection_is_valid: 

1053 if self._echo: 

1054 if self._is_autocommit_isolation(): 

1055 self._log_info( 

1056 "ROLLBACK using DBAPI connection.rollback(), " 

1057 "DBAPI should ignore due to autocommit mode" 

1058 ) 

1059 else: 

1060 self._log_info("ROLLBACK") 

1061 try: 

1062 self.engine.dialect.do_rollback(self.connection) 

1063 except BaseException as e: 

1064 self._handle_dbapi_exception(e, None, None, None, None) 

1065 

1066 def _commit_impl(self, autocommit=False): 

1067 assert not self.__branch_from 

1068 

1069 # AUTOCOMMIT isolation-level is a dialect-specific concept, however 

1070 # if a connection has this set as the isolation level, we can skip 

1071 # the "autocommit" warning as the operation will do "autocommit" 

1072 # in any case 

1073 if autocommit and not self._is_autocommit_isolation(): 

1074 util.warn_deprecated_20( 

1075 "The current statement is being autocommitted using " 

1076 "implicit autocommit, which will be removed in " 

1077 "SQLAlchemy 2.0. " 

1078 "Use the .begin() method of Engine or Connection in order to " 

1079 "use an explicit transaction for DML and DDL statements." 

1080 ) 

1081 

1082 if self._has_events or self.engine._has_events: 

1083 self.dispatch.commit(self) 

1084 

1085 if self._echo: 

1086 if self._is_autocommit_isolation(): 

1087 self._log_info( 

1088 "COMMIT using DBAPI connection.commit(), " 

1089 "DBAPI should ignore due to autocommit mode" 

1090 ) 

1091 else: 

1092 self._log_info("COMMIT") 

1093 try: 

1094 self.engine.dialect.do_commit(self.connection) 

1095 except BaseException as e: 

1096 self._handle_dbapi_exception(e, None, None, None, None) 

1097 

1098 def _savepoint_impl(self, name=None): 

1099 assert not self.__branch_from 

1100 

1101 if self._has_events or self.engine._has_events: 

1102 self.dispatch.savepoint(self, name) 

1103 

1104 if name is None: 

1105 self.__savepoint_seq += 1 

1106 name = "sa_savepoint_%s" % self.__savepoint_seq 

1107 if self._still_open_and_dbapi_connection_is_valid: 

1108 self.engine.dialect.do_savepoint(self, name) 

1109 return name 

1110 

1111 def _rollback_to_savepoint_impl(self, name): 

1112 assert not self.__branch_from 

1113 

1114 if self._has_events or self.engine._has_events: 

1115 self.dispatch.rollback_savepoint(self, name, None) 

1116 

1117 if self._still_open_and_dbapi_connection_is_valid: 

1118 self.engine.dialect.do_rollback_to_savepoint(self, name) 

1119 

1120 def _release_savepoint_impl(self, name): 

1121 assert not self.__branch_from 

1122 

1123 if self._has_events or self.engine._has_events: 

1124 self.dispatch.release_savepoint(self, name, None) 

1125 

1126 if self._still_open_and_dbapi_connection_is_valid: 

1127 self.engine.dialect.do_release_savepoint(self, name) 

1128 

1129 def _begin_twophase_impl(self, transaction): 

1130 assert not self.__branch_from 

1131 

1132 if self._echo: 

1133 self._log_info("BEGIN TWOPHASE (implicit)") 

1134 if self._has_events or self.engine._has_events: 

1135 self.dispatch.begin_twophase(self, transaction.xid) 

1136 

1137 if self._still_open_and_dbapi_connection_is_valid: 

1138 self.__in_begin = True 

1139 try: 

1140 self.engine.dialect.do_begin_twophase(self, transaction.xid) 

1141 except BaseException as e: 

1142 self._handle_dbapi_exception(e, None, None, None, None) 

1143 finally: 

1144 self.__in_begin = False 

1145 

1146 def _prepare_twophase_impl(self, xid): 

1147 assert not self.__branch_from 

1148 

1149 if self._has_events or self.engine._has_events: 

1150 self.dispatch.prepare_twophase(self, xid) 

1151 

1152 if self._still_open_and_dbapi_connection_is_valid: 

1153 assert isinstance(self._transaction, TwoPhaseTransaction) 

1154 try: 

1155 self.engine.dialect.do_prepare_twophase(self, xid) 

1156 except BaseException as e: 

1157 self._handle_dbapi_exception(e, None, None, None, None) 

1158 

1159 def _rollback_twophase_impl(self, xid, is_prepared): 

1160 assert not self.__branch_from 

1161 

1162 if self._has_events or self.engine._has_events: 

1163 self.dispatch.rollback_twophase(self, xid, is_prepared) 

1164 

1165 if self._still_open_and_dbapi_connection_is_valid: 

1166 assert isinstance(self._transaction, TwoPhaseTransaction) 

1167 try: 

1168 self.engine.dialect.do_rollback_twophase( 

1169 self, xid, is_prepared 

1170 ) 

1171 except BaseException as e: 

1172 self._handle_dbapi_exception(e, None, None, None, None) 

1173 

1174 def _commit_twophase_impl(self, xid, is_prepared): 

1175 assert not self.__branch_from 

1176 

1177 if self._has_events or self.engine._has_events: 

1178 self.dispatch.commit_twophase(self, xid, is_prepared) 

1179 

1180 if self._still_open_and_dbapi_connection_is_valid: 

1181 assert isinstance(self._transaction, TwoPhaseTransaction) 

1182 try: 

1183 self.engine.dialect.do_commit_twophase(self, xid, is_prepared) 

1184 except BaseException as e: 

1185 self._handle_dbapi_exception(e, None, None, None, None) 

1186 

1187 def _autorollback(self): 

1188 if self.__branch_from: 

1189 self.__branch_from._autorollback() 

1190 

1191 if not self.in_transaction(): 

1192 self._rollback_impl() 

1193 

1194 def _warn_for_legacy_exec_format(self): 

1195 util.warn_deprecated_20( 

1196 "The connection.execute() method in " 

1197 "SQLAlchemy 2.0 will accept parameters as a single " 

1198 "dictionary or a " 

1199 "single sequence of dictionaries only. " 

1200 "Parameters passed as keyword arguments, tuples or positionally " 

1201 "oriented dictionaries and/or tuples " 

1202 "will no longer be accepted." 

1203 ) 

1204 

1205 def close(self): 

1206 """Close this :class:`_engine.Connection`. 

1207 

1208 This results in a release of the underlying database 

1209 resources, that is, the DBAPI connection referenced 

1210 internally. The DBAPI connection is typically restored 

1211 back to the connection-holding :class:`_pool.Pool` referenced 

1212 by the :class:`_engine.Engine` that produced this 

1213 :class:`_engine.Connection`. Any transactional state present on 

1214 the DBAPI connection is also unconditionally released via 

1215 the DBAPI connection's ``rollback()`` method, regardless 

1216 of any :class:`.Transaction` object that may be 

1217 outstanding with regards to this :class:`_engine.Connection`. 

1218 

1219 After :meth:`_engine.Connection.close` is called, the 

1220 :class:`_engine.Connection` is permanently in a closed state, 

1221 and will allow no further operations. 

1222 

1223 """ 

1224 

1225 if self.__branch_from: 

1226 assert not self._is_future 

1227 util.warn_deprecated_20( 

1228 "The .close() method on a so-called 'branched' connection is " 

1229 "deprecated as of 1.4, as are 'branched' connections overall, " 

1230 "and will be removed in a future release. If this is a " 

1231 "default-handling function, don't close the connection." 

1232 ) 

1233 self._dbapi_connection = None 

1234 self.__can_reconnect = False 

1235 return 

1236 

1237 if self._transaction: 

1238 self._transaction.close() 

1239 skip_reset = True 

1240 else: 

1241 skip_reset = False 

1242 

1243 if self._dbapi_connection is not None: 

1244 conn = self._dbapi_connection 

1245 

1246 # as we just closed the transaction, close the connection 

1247 # pool connection without doing an additional reset 

1248 if skip_reset: 

1249 conn._close_special(transaction_reset=True) 

1250 else: 

1251 conn.close() 

1252 

1253 # There is a slight chance that conn.close() may have 

1254 # triggered an invalidation here in which case 

1255 # _dbapi_connection would already be None, however usually 

1256 # it will be non-None here and in a "closed" state. 

1257 self._dbapi_connection = None 

1258 self.__can_reconnect = False 

1259 

1260 def scalar(self, object_, *multiparams, **params): 

1261 """Executes and returns the first column of the first row. 

1262 

1263 The underlying result/cursor is closed after execution. 

1264 

1265 """ 

1266 

1267 return self.execute(object_, *multiparams, **params).scalar() 

1268 

1269 def scalars(self, object_, *multiparams, **params): 

1270 """Executes and returns a scalar result set, which yields scalar values 

1271 from the first column of each row. 

1272 

1273 This method is equivalent to calling :meth:`_engine.Connection.execute` 

1274 to receive a :class:`_result.Result` object, then invoking the 

1275 :meth:`_result.Result.scalars` method to produce a 

1276 :class:`_result.ScalarResult` instance. 

1277 

1278 :return: a :class:`_result.ScalarResult` 

1279 

1280 .. versionadded:: 1.4.24 

1281 

1282 """ 

1283 

1284 return self.execute(object_, *multiparams, **params).scalars() 

1285 

1286 def execute(self, statement, *multiparams, **params): 

1287 r"""Executes a SQL statement construct and returns a 

1288 :class:`_engine.CursorResult`. 

1289 

1290 :param statement: The statement to be executed. May be 

1291 one of: 

1292 

1293 * a plain string (deprecated) 

1294 * any :class:`_expression.ClauseElement` construct that is also 

1295 a subclass of :class:`.Executable`, such as a 

1296 :func:`_expression.select` construct 

1297 * a :class:`.FunctionElement`, such as that generated 

1298 by :data:`.func`, will be automatically wrapped in 

1299 a SELECT statement, which is then executed. 

1300 * a :class:`.DDLElement` object 

1301 * a :class:`.DefaultGenerator` object 

1302 * a :class:`.Compiled` object 

1303 

1304 .. deprecated:: 2.0 passing a string to 

1305 :meth:`_engine.Connection.execute` is 

1306 deprecated and will be removed in version 2.0. Use the 

1307 :func:`_expression.text` construct with 

1308 :meth:`_engine.Connection.execute`, or the 

1309 :meth:`_engine.Connection.exec_driver_sql` 

1310 method to invoke a driver-level 

1311 SQL string. 

1312 

1313 :param \*multiparams/\**params: represent bound parameter 

1314 values to be used in the execution. Typically, 

1315 the format is either a collection of one or more 

1316 dictionaries passed to \*multiparams:: 

1317 

1318 conn.execute( 

1319 table.insert(), 

1320 {"id":1, "value":"v1"}, 

1321 {"id":2, "value":"v2"} 

1322 ) 

1323 

1324 ...or individual key/values interpreted by \**params:: 

1325 

1326 conn.execute( 

1327 table.insert(), id=1, value="v1" 

1328 ) 

1329 

1330 In the case that a plain SQL string is passed, and the underlying 

1331 DBAPI accepts positional bind parameters, a collection of tuples 

1332 or individual values in \*multiparams may be passed:: 

1333 

1334 conn.execute( 

1335 "INSERT INTO table (id, value) VALUES (?, ?)", 

1336 (1, "v1"), (2, "v2") 

1337 ) 

1338 

1339 conn.execute( 

1340 "INSERT INTO table (id, value) VALUES (?, ?)", 

1341 1, "v1" 

1342 ) 

1343 

1344 Note above, the usage of a question mark "?" or other 

1345 symbol is contingent upon the "paramstyle" accepted by the DBAPI 

1346 in use, which may be any of "qmark", "named", "pyformat", "format", 

1347 "numeric". See `pep-249 

1348 <https://www.python.org/dev/peps/pep-0249/>`_ for details on 

1349 paramstyle. 

1350 

1351 To execute a textual SQL statement which uses bound parameters in a 

1352 DBAPI-agnostic way, use the :func:`_expression.text` construct. 

1353 

1354 .. deprecated:: 2.0 use of tuple or scalar positional parameters 

1355 is deprecated. All params should be dicts or sequences of dicts. 

1356 Use :meth:`.exec_driver_sql` to execute a plain string with 

1357 tuple or scalar positional parameters. 

1358 

1359 """ 

1360 

1361 if isinstance(statement, util.string_types): 

1362 util.warn_deprecated_20( 

1363 "Passing a string to Connection.execute() is " 

1364 "deprecated and will be removed in version 2.0. Use the " 

1365 "text() construct, " 

1366 "or the Connection.exec_driver_sql() method to invoke a " 

1367 "driver-level SQL string." 

1368 ) 

1369 

1370 return self._exec_driver_sql( 

1371 statement, 

1372 multiparams, 

1373 params, 

1374 _EMPTY_EXECUTION_OPTS, 

1375 future=False, 

1376 ) 

1377 

1378 try: 

1379 meth = statement._execute_on_connection 

1380 except AttributeError as err: 

1381 util.raise_( 

1382 exc.ObjectNotExecutableError(statement), replace_context=err 

1383 ) 

1384 else: 

1385 return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS) 

1386 

1387 def _execute_function(self, func, multiparams, params, execution_options): 

1388 """Execute a sql.FunctionElement object.""" 

1389 

1390 return self._execute_clauseelement( 

1391 func.select(), multiparams, params, execution_options 

1392 ) 

1393 

1394 def _execute_default( 

1395 self, 

1396 default, 

1397 multiparams, 

1398 params, 

1399 # migrate is calling this directly :( 

1400 execution_options=_EMPTY_EXECUTION_OPTS, 

1401 ): 

1402 """Execute a schema.ColumnDefault object.""" 

1403 

1404 execution_options = self._execution_options.merge_with( 

1405 execution_options 

1406 ) 

1407 

1408 distilled_parameters = _distill_params(self, multiparams, params) 

1409 

1410 if self._has_events or self.engine._has_events: 

1411 ( 

1412 default, 

1413 distilled_params, 

1414 event_multiparams, 

1415 event_params, 

1416 ) = self._invoke_before_exec_event( 

1417 default, distilled_parameters, execution_options 

1418 ) 

1419 

1420 try: 

1421 conn = self._dbapi_connection 

1422 if conn is None: 

1423 conn = self._revalidate_connection() 

1424 

1425 dialect = self.dialect 

1426 ctx = dialect.execution_ctx_cls._init_default( 

1427 dialect, self, conn, execution_options 

1428 ) 

1429 except (exc.PendingRollbackError, exc.ResourceClosedError): 

1430 raise 

1431 except BaseException as e: 

1432 self._handle_dbapi_exception(e, None, None, None, None) 

1433 

1434 ret = ctx._exec_default(None, default, None) 

1435 if self.should_close_with_result: 

1436 self.close() 

1437 

1438 if self._has_events or self.engine._has_events: 

1439 self.dispatch.after_execute( 

1440 self, 

1441 default, 

1442 event_multiparams, 

1443 event_params, 

1444 execution_options, 

1445 ret, 

1446 ) 

1447 

1448 return ret 

1449 

1450 def _execute_ddl(self, ddl, multiparams, params, execution_options): 

1451 """Execute a schema.DDL object.""" 

1452 

1453 execution_options = ddl._execution_options.merge_with( 

1454 self._execution_options, execution_options 

1455 ) 

1456 

1457 distilled_parameters = _distill_params(self, multiparams, params) 

1458 

1459 if self._has_events or self.engine._has_events: 

1460 ( 

1461 ddl, 

1462 distilled_params, 

1463 event_multiparams, 

1464 event_params, 

1465 ) = self._invoke_before_exec_event( 

1466 ddl, distilled_parameters, execution_options 

1467 ) 

1468 

1469 exec_opts = self._execution_options.merge_with(execution_options) 

1470 schema_translate_map = exec_opts.get("schema_translate_map", None) 

1471 

1472 dialect = self.dialect 

1473 

1474 compiled = ddl.compile( 

1475 dialect=dialect, schema_translate_map=schema_translate_map 

1476 ) 

1477 ret = self._execute_context( 

1478 dialect, 

1479 dialect.execution_ctx_cls._init_ddl, 

1480 compiled, 

1481 None, 

1482 execution_options, 

1483 compiled, 

1484 ) 

1485 if self._has_events or self.engine._has_events: 

1486 self.dispatch.after_execute( 

1487 self, 

1488 ddl, 

1489 event_multiparams, 

1490 event_params, 

1491 execution_options, 

1492 ret, 

1493 ) 

1494 return ret 

1495 

1496 def _invoke_before_exec_event( 

1497 self, elem, distilled_params, execution_options 

1498 ): 

1499 

1500 if len(distilled_params) == 1: 

1501 event_multiparams, event_params = [], distilled_params[0] 

1502 else: 

1503 event_multiparams, event_params = distilled_params, {} 

1504 

1505 for fn in self.dispatch.before_execute: 

1506 elem, event_multiparams, event_params = fn( 

1507 self, 

1508 elem, 

1509 event_multiparams, 

1510 event_params, 

1511 execution_options, 

1512 ) 

1513 

1514 if event_multiparams: 

1515 distilled_params = list(event_multiparams) 

1516 if event_params: 

1517 raise exc.InvalidRequestError( 

1518 "Event handler can't return non-empty multiparams " 

1519 "and params at the same time" 

1520 ) 

1521 elif event_params: 

1522 distilled_params = [event_params] 

1523 else: 

1524 distilled_params = [] 

1525 

1526 return elem, distilled_params, event_multiparams, event_params 

1527 

1528 def _execute_clauseelement( 

1529 self, elem, multiparams, params, execution_options 

1530 ): 

1531 """Execute a sql.ClauseElement object.""" 

1532 

1533 execution_options = elem._execution_options.merge_with( 

1534 self._execution_options, execution_options 

1535 ) 

1536 

1537 distilled_params = _distill_params(self, multiparams, params) 

1538 

1539 has_events = self._has_events or self.engine._has_events 

1540 if has_events: 

1541 ( 

1542 elem, 

1543 distilled_params, 

1544 event_multiparams, 

1545 event_params, 

1546 ) = self._invoke_before_exec_event( 

1547 elem, distilled_params, execution_options 

1548 ) 

1549 

1550 if distilled_params: 

1551 # ensure we don't retain a link to the view object for keys() 

1552 # which links to the values, which we don't want to cache 

1553 keys = sorted(distilled_params[0]) 

1554 for_executemany = len(distilled_params) > 1 

1555 else: 

1556 keys = [] 

1557 for_executemany = False 

1558 

1559 dialect = self.dialect 

1560 

1561 schema_translate_map = execution_options.get( 

1562 "schema_translate_map", None 

1563 ) 

1564 

1565 compiled_cache = execution_options.get( 

1566 "compiled_cache", self.engine._compiled_cache 

1567 ) 

1568 

1569 compiled_sql, extracted_params, cache_hit = elem._compile_w_cache( 

1570 dialect=dialect, 

1571 compiled_cache=compiled_cache, 

1572 column_keys=keys, 

1573 for_executemany=for_executemany, 

1574 schema_translate_map=schema_translate_map, 

1575 linting=self.dialect.compiler_linting | compiler.WARN_LINTING, 

1576 ) 

1577 ret = self._execute_context( 

1578 dialect, 

1579 dialect.execution_ctx_cls._init_compiled, 

1580 compiled_sql, 

1581 distilled_params, 

1582 execution_options, 

1583 compiled_sql, 

1584 distilled_params, 

1585 elem, 

1586 extracted_params, 

1587 cache_hit=cache_hit, 

1588 ) 

1589 if has_events: 

1590 self.dispatch.after_execute( 

1591 self, 

1592 elem, 

1593 event_multiparams, 

1594 event_params, 

1595 execution_options, 

1596 ret, 

1597 ) 

1598 return ret 

1599 

1600 def _execute_compiled( 

1601 self, 

1602 compiled, 

1603 multiparams, 

1604 params, 

1605 execution_options=_EMPTY_EXECUTION_OPTS, 

1606 ): 

1607 """Execute a sql.Compiled object. 

1608 

1609 TODO: why do we have this? likely deprecate or remove 

1610 

1611 """ 

1612 

1613 execution_options = compiled.execution_options.merge_with( 

1614 self._execution_options, execution_options 

1615 ) 

1616 distilled_parameters = _distill_params(self, multiparams, params) 

1617 

1618 if self._has_events or self.engine._has_events: 

1619 ( 

1620 compiled, 

1621 distilled_params, 

1622 event_multiparams, 

1623 event_params, 

1624 ) = self._invoke_before_exec_event( 

1625 compiled, distilled_parameters, execution_options 

1626 ) 

1627 

1628 dialect = self.dialect 

1629 

1630 ret = self._execute_context( 

1631 dialect, 

1632 dialect.execution_ctx_cls._init_compiled, 

1633 compiled, 

1634 distilled_parameters, 

1635 execution_options, 

1636 compiled, 

1637 distilled_parameters, 

1638 None, 

1639 None, 

1640 ) 

1641 if self._has_events or self.engine._has_events: 

1642 self.dispatch.after_execute( 

1643 self, 

1644 compiled, 

1645 event_multiparams, 

1646 event_params, 

1647 execution_options, 

1648 ret, 

1649 ) 

1650 return ret 

1651 

1652 def _exec_driver_sql( 

1653 self, statement, multiparams, params, execution_options, future 

1654 ): 

1655 

1656 execution_options = self._execution_options.merge_with( 

1657 execution_options 

1658 ) 

1659 

1660 distilled_parameters = _distill_params(self, multiparams, params) 

1661 

1662 if not future: 

1663 if self._has_events or self.engine._has_events: 

1664 ( 

1665 statement, 

1666 distilled_params, 

1667 event_multiparams, 

1668 event_params, 

1669 ) = self._invoke_before_exec_event( 

1670 statement, distilled_parameters, execution_options 

1671 ) 

1672 

1673 dialect = self.dialect 

1674 ret = self._execute_context( 

1675 dialect, 

1676 dialect.execution_ctx_cls._init_statement, 

1677 statement, 

1678 distilled_parameters, 

1679 execution_options, 

1680 statement, 

1681 distilled_parameters, 

1682 ) 

1683 

1684 if not future: 

1685 if self._has_events or self.engine._has_events: 

1686 self.dispatch.after_execute( 

1687 self, 

1688 statement, 

1689 event_multiparams, 

1690 event_params, 

1691 execution_options, 

1692 ret, 

1693 ) 

1694 return ret 

1695 

1696 def _execute_20( 

1697 self, 

1698 statement, 

1699 parameters=None, 

1700 execution_options=_EMPTY_EXECUTION_OPTS, 

1701 ): 

1702 args_10style, kwargs_10style = _distill_params_20(parameters) 

1703 try: 

1704 meth = statement._execute_on_connection 

1705 except AttributeError as err: 

1706 util.raise_( 

1707 exc.ObjectNotExecutableError(statement), replace_context=err 

1708 ) 

1709 else: 

1710 return meth(self, args_10style, kwargs_10style, execution_options) 

1711 

1712 def exec_driver_sql( 

1713 self, statement, parameters=None, execution_options=None 

1714 ): 

1715 r"""Executes a SQL statement construct and returns a 

1716 :class:`_engine.CursorResult`. 

1717 

1718 :param statement: The statement str to be executed. Bound parameters 

1719 must use the underlying DBAPI's paramstyle, such as "qmark", 

1720 "pyformat", "format", etc. 

1721 

1722 :param parameters: represent bound parameter values to be used in the 

1723 execution. The format is one of: a dictionary of named parameters, 

1724 a tuple of positional parameters, or a list containing either 

1725 dictionaries or tuples for multiple-execute support. 

1726 

1727 E.g. multiple dictionaries:: 

1728 

1729 

1730 conn.exec_driver_sql( 

1731 "INSERT INTO table (id, value) VALUES (%(id)s, %(value)s)", 

1732 [{"id":1, "value":"v1"}, {"id":2, "value":"v2"}] 

1733 ) 

1734 

1735 Single dictionary:: 

1736 

1737 conn.exec_driver_sql( 

1738 "INSERT INTO table (id, value) VALUES (%(id)s, %(value)s)", 

1739 dict(id=1, value="v1") 

1740 ) 

1741 

1742 Single tuple:: 

1743 

1744 conn.exec_driver_sql( 

1745 "INSERT INTO table (id, value) VALUES (?, ?)", 

1746 (1, 'v1') 

1747 ) 

1748 

1749 .. note:: The :meth:`_engine.Connection.exec_driver_sql` method does 

1750 not participate in the 

1751 :meth:`_events.ConnectionEvents.before_execute` and 

1752 :meth:`_events.ConnectionEvents.after_execute` events. To 

1753 intercept calls to :meth:`_engine.Connection.exec_driver_sql`, use 

1754 :meth:`_events.ConnectionEvents.before_cursor_execute` and 

1755 :meth:`_events.ConnectionEvents.after_cursor_execute`. 

1756 

1757 .. seealso:: 

1758 

1759 :pep:`249` 

1760 

1761 """ 

1762 

1763 args_10style, kwargs_10style = _distill_params_20(parameters) 

1764 

1765 return self._exec_driver_sql( 

1766 statement, 

1767 args_10style, 

1768 kwargs_10style, 

1769 execution_options, 

1770 future=True, 

1771 ) 

1772 

1773 def _execute_context( 

1774 self, 

1775 dialect, 

1776 constructor, 

1777 statement, 

1778 parameters, 

1779 execution_options, 

1780 *args, 

1781 **kw 

1782 ): 

1783 """Create an :class:`.ExecutionContext` and execute, returning 

1784 a :class:`_engine.CursorResult`.""" 

1785 

1786 branched = self 

1787 if self.__branch_from: 

1788 # if this is a "branched" connection, do everything in terms 

1789 # of the "root" connection, *except* for .close(), which is 

1790 # the only feature that branching provides 

1791 self = self.__branch_from 

1792 

1793 if execution_options: 

1794 yp = execution_options.get("yield_per", None) 

1795 if yp: 

1796 execution_options = execution_options.union( 

1797 {"stream_results": True, "max_row_buffer": yp} 

1798 ) 

1799 

1800 try: 

1801 conn = self._dbapi_connection 

1802 if conn is None: 

1803 conn = self._revalidate_connection() 

1804 

1805 context = constructor( 

1806 dialect, self, conn, execution_options, *args, **kw 

1807 ) 

1808 except (exc.PendingRollbackError, exc.ResourceClosedError): 

1809 raise 

1810 except BaseException as e: 

1811 self._handle_dbapi_exception( 

1812 e, util.text_type(statement), parameters, None, None 

1813 ) 

1814 

1815 if ( 

1816 self._transaction 

1817 and not self._transaction.is_active 

1818 or ( 

1819 self._nested_transaction 

1820 and not self._nested_transaction.is_active 

1821 ) 

1822 ): 

1823 self._invalid_transaction() 

1824 

1825 elif self._trans_context_manager: 

1826 TransactionalContext._trans_ctx_check(self) 

1827 

1828 if self._is_future and self._transaction is None: 

1829 self._autobegin() 

1830 

1831 context.pre_exec() 

1832 

1833 if dialect.use_setinputsizes: 

1834 context._set_input_sizes() 

1835 

1836 cursor, statement, parameters = ( 

1837 context.cursor, 

1838 context.statement, 

1839 context.parameters, 

1840 ) 

1841 

1842 if not context.executemany: 

1843 parameters = parameters[0] 

1844 

1845 if self._has_events or self.engine._has_events: 

1846 for fn in self.dispatch.before_cursor_execute: 

1847 statement, parameters = fn( 

1848 self, 

1849 cursor, 

1850 statement, 

1851 parameters, 

1852 context, 

1853 context.executemany, 

1854 ) 

1855 

1856 if self._echo: 

1857 

1858 self._log_info(statement) 

1859 

1860 stats = context._get_cache_stats() 

1861 

1862 if not self.engine.hide_parameters: 

1863 self._log_info( 

1864 "[%s] %r", 

1865 stats, 

1866 sql_util._repr_params( 

1867 parameters, batches=10, ismulti=context.executemany 

1868 ), 

1869 ) 

1870 else: 

1871 self._log_info( 

1872 "[%s] [SQL parameters hidden due to hide_parameters=True]" 

1873 % (stats,) 

1874 ) 

1875 

1876 evt_handled = False 

1877 try: 

1878 if context.executemany: 

1879 if self.dialect._has_events: 

1880 for fn in self.dialect.dispatch.do_executemany: 

1881 if fn(cursor, statement, parameters, context): 

1882 evt_handled = True 

1883 break 

1884 if not evt_handled: 

1885 self.dialect.do_executemany( 

1886 cursor, statement, parameters, context 

1887 ) 

1888 elif not parameters and context.no_parameters: 

1889 if self.dialect._has_events: 

1890 for fn in self.dialect.dispatch.do_execute_no_params: 

1891 if fn(cursor, statement, context): 

1892 evt_handled = True 

1893 break 

1894 if not evt_handled: 

1895 self.dialect.do_execute_no_params( 

1896 cursor, statement, context 

1897 ) 

1898 else: 

1899 if self.dialect._has_events: 

1900 for fn in self.dialect.dispatch.do_execute: 

1901 if fn(cursor, statement, parameters, context): 

1902 evt_handled = True 

1903 break 

1904 if not evt_handled: 

1905 self.dialect.do_execute( 

1906 cursor, statement, parameters, context 

1907 ) 

1908 

1909 if self._has_events or self.engine._has_events: 

1910 self.dispatch.after_cursor_execute( 

1911 self, 

1912 cursor, 

1913 statement, 

1914 parameters, 

1915 context, 

1916 context.executemany, 

1917 ) 

1918 

1919 context.post_exec() 

1920 

1921 result = context._setup_result_proxy() 

1922 

1923 if not self._is_future: 

1924 should_close_with_result = branched.should_close_with_result 

1925 

1926 if not result._soft_closed and should_close_with_result: 

1927 result._autoclose_connection = True 

1928 

1929 if ( 

1930 # usually we're in a transaction so avoid relatively 

1931 # expensive / legacy should_autocommit call 

1932 self._transaction is None 

1933 and context.should_autocommit 

1934 ): 

1935 self._commit_impl(autocommit=True) 

1936 

1937 # for "connectionless" execution, we have to close this 

1938 # Connection after the statement is complete. 

1939 # legacy stuff. 

1940 if should_close_with_result and context._soft_closed: 

1941 assert not self._is_future 

1942 

1943 # CursorResult already exhausted rows / has no rows. 

1944 # close us now 

1945 branched.close() 

1946 

1947 except BaseException as e: 

1948 self._handle_dbapi_exception( 

1949 e, statement, parameters, cursor, context 

1950 ) 

1951 

1952 return result 

1953 

1954 def _cursor_execute(self, cursor, statement, parameters, context=None): 

1955 """Execute a statement + params on the given cursor. 

1956 

1957 Adds appropriate logging and exception handling. 

1958 

1959 This method is used by DefaultDialect for special-case 

1960 executions, such as for sequences and column defaults. 

1961 The path of statement execution in the majority of cases 

1962 terminates at _execute_context(). 

1963 

1964 """ 

1965 if self._has_events or self.engine._has_events: 

1966 for fn in self.dispatch.before_cursor_execute: 

1967 statement, parameters = fn( 

1968 self, cursor, statement, parameters, context, False 

1969 ) 

1970 

1971 if self._echo: 

1972 self._log_info(statement) 

1973 self._log_info("[raw sql] %r", parameters) 

1974 try: 

1975 for fn in ( 

1976 () 

1977 if not self.dialect._has_events 

1978 else self.dialect.dispatch.do_execute 

1979 ): 

1980 if fn(cursor, statement, parameters, context): 

1981 break 

1982 else: 

1983 self.dialect.do_execute(cursor, statement, parameters, context) 

1984 except BaseException as e: 

1985 self._handle_dbapi_exception( 

1986 e, statement, parameters, cursor, context 

1987 ) 

1988 

1989 if self._has_events or self.engine._has_events: 

1990 self.dispatch.after_cursor_execute( 

1991 self, cursor, statement, parameters, context, False 

1992 ) 

1993 

1994 def _safe_close_cursor(self, cursor): 

1995 """Close the given cursor, catching exceptions 

1996 and turning into log warnings. 

1997 

1998 """ 

1999 try: 

2000 cursor.close() 

2001 except Exception: 

2002 # log the error through the connection pool's logger. 

2003 self.engine.pool.logger.error( 

2004 "Error closing cursor", exc_info=True 

2005 ) 

2006 

2007 _reentrant_error = False 

2008 _is_disconnect = False 

2009 

2010 def _handle_dbapi_exception( 

2011 self, e, statement, parameters, cursor, context 

2012 ): 

2013 exc_info = sys.exc_info() 

2014 

2015 is_exit_exception = util.is_exit_exception(e) 

2016 

2017 if not self._is_disconnect: 

2018 self._is_disconnect = ( 

2019 isinstance(e, self.dialect.dbapi.Error) 

2020 and not self.closed 

2021 and self.dialect.is_disconnect( 

2022 e, 

2023 self._dbapi_connection if not self.invalidated else None, 

2024 cursor, 

2025 ) 

2026 ) or (is_exit_exception and not self.closed) 

2027 

2028 invalidate_pool_on_disconnect = not is_exit_exception 

2029 

2030 if self._reentrant_error: 

2031 util.raise_( 

2032 exc.DBAPIError.instance( 

2033 statement, 

2034 parameters, 

2035 e, 

2036 self.dialect.dbapi.Error, 

2037 hide_parameters=self.engine.hide_parameters, 

2038 dialect=self.dialect, 

2039 ismulti=context.executemany 

2040 if context is not None 

2041 else None, 

2042 ), 

2043 with_traceback=exc_info[2], 

2044 from_=e, 

2045 ) 

2046 self._reentrant_error = True 

2047 try: 

2048 # non-DBAPI error - if we already got a context, 

2049 # or there's no string statement, don't wrap it 

2050 should_wrap = isinstance(e, self.dialect.dbapi.Error) or ( 

2051 statement is not None 

2052 and context is None 

2053 and not is_exit_exception 

2054 ) 

2055 

2056 if should_wrap: 

2057 sqlalchemy_exception = exc.DBAPIError.instance( 

2058 statement, 

2059 parameters, 

2060 e, 

2061 self.dialect.dbapi.Error, 

2062 hide_parameters=self.engine.hide_parameters, 

2063 connection_invalidated=self._is_disconnect, 

2064 dialect=self.dialect, 

2065 ismulti=context.executemany 

2066 if context is not None 

2067 else None, 

2068 ) 

2069 else: 

2070 sqlalchemy_exception = None 

2071 

2072 newraise = None 

2073 

2074 if ( 

2075 self._has_events or self.engine._has_events 

2076 ) and not self._execution_options.get( 

2077 "skip_user_error_events", False 

2078 ): 

2079 ctx = ExceptionContextImpl( 

2080 e, 

2081 sqlalchemy_exception, 

2082 self.engine, 

2083 self, 

2084 cursor, 

2085 statement, 

2086 parameters, 

2087 context, 

2088 self._is_disconnect, 

2089 invalidate_pool_on_disconnect, 

2090 ) 

2091 

2092 for fn in self.dispatch.handle_error: 

2093 try: 

2094 # handler returns an exception; 

2095 # call next handler in a chain 

2096 per_fn = fn(ctx) 

2097 if per_fn is not None: 

2098 ctx.chained_exception = newraise = per_fn 

2099 except Exception as _raised: 

2100 # handler raises an exception - stop processing 

2101 newraise = _raised 

2102 break 

2103 

2104 if self._is_disconnect != ctx.is_disconnect: 

2105 self._is_disconnect = ctx.is_disconnect 

2106 if sqlalchemy_exception: 

2107 sqlalchemy_exception.connection_invalidated = ( 

2108 ctx.is_disconnect 

2109 ) 

2110 

2111 # set up potentially user-defined value for 

2112 # invalidate pool. 

2113 invalidate_pool_on_disconnect = ( 

2114 ctx.invalidate_pool_on_disconnect 

2115 ) 

2116 

2117 if should_wrap and context: 

2118 context.handle_dbapi_exception(e) 

2119 

2120 if not self._is_disconnect: 

2121 if cursor: 

2122 self._safe_close_cursor(cursor) 

2123 with util.safe_reraise(warn_only=True): 

2124 self._autorollback() 

2125 

2126 if newraise: 

2127 util.raise_(newraise, with_traceback=exc_info[2], from_=e) 

2128 elif should_wrap: 

2129 util.raise_( 

2130 sqlalchemy_exception, with_traceback=exc_info[2], from_=e 

2131 ) 

2132 else: 

2133 util.raise_(exc_info[1], with_traceback=exc_info[2]) 

2134 

2135 finally: 

2136 del self._reentrant_error 

2137 if self._is_disconnect: 

2138 del self._is_disconnect 

2139 if not self.invalidated: 

2140 dbapi_conn_wrapper = self._dbapi_connection 

2141 if invalidate_pool_on_disconnect: 

2142 self.engine.pool._invalidate(dbapi_conn_wrapper, e) 

2143 self.invalidate(e) 

2144 if self.should_close_with_result: 

2145 assert not self._is_future 

2146 self.close() 

2147 

2148 @classmethod 

2149 def _handle_dbapi_exception_noconnection(cls, e, dialect, engine): 

2150 exc_info = sys.exc_info() 

2151 

2152 is_disconnect = dialect.is_disconnect(e, None, None) 

2153 

2154 should_wrap = isinstance(e, dialect.dbapi.Error) 

2155 

2156 if should_wrap: 

2157 sqlalchemy_exception = exc.DBAPIError.instance( 

2158 None, 

2159 None, 

2160 e, 

2161 dialect.dbapi.Error, 

2162 hide_parameters=engine.hide_parameters, 

2163 connection_invalidated=is_disconnect, 

2164 ) 

2165 else: 

2166 sqlalchemy_exception = None 

2167 

2168 newraise = None 

2169 

2170 if engine._has_events: 

2171 ctx = ExceptionContextImpl( 

2172 e, 

2173 sqlalchemy_exception, 

2174 engine, 

2175 None, 

2176 None, 

2177 None, 

2178 None, 

2179 None, 

2180 is_disconnect, 

2181 True, 

2182 ) 

2183 for fn in engine.dispatch.handle_error: 

2184 try: 

2185 # handler returns an exception; 

2186 # call next handler in a chain 

2187 per_fn = fn(ctx) 

2188 if per_fn is not None: 

2189 ctx.chained_exception = newraise = per_fn 

2190 except Exception as _raised: 

2191 # handler raises an exception - stop processing 

2192 newraise = _raised 

2193 break 

2194 

2195 if sqlalchemy_exception and is_disconnect != ctx.is_disconnect: 

2196 sqlalchemy_exception.connection_invalidated = ( 

2197 is_disconnect 

2198 ) = ctx.is_disconnect 

2199 

2200 if newraise: 

2201 util.raise_(newraise, with_traceback=exc_info[2], from_=e) 

2202 elif should_wrap: 

2203 util.raise_( 

2204 sqlalchemy_exception, with_traceback=exc_info[2], from_=e 

2205 ) 

2206 else: 

2207 util.raise_(exc_info[1], with_traceback=exc_info[2]) 

2208 

2209 def _run_ddl_visitor(self, visitorcallable, element, **kwargs): 

2210 """run a DDL visitor. 

2211 

2212 This method is only here so that the MockConnection can change the 

2213 options given to the visitor so that "checkfirst" is skipped. 

2214 

2215 """ 

2216 visitorcallable(self.dialect, self, **kwargs).traverse_single(element) 

2217 

2218 @util.deprecated( 

2219 "1.4", 

2220 "The :meth:`_engine.Connection.transaction` " 

2221 "method is deprecated and will be " 

2222 "removed in a future release. Use the :meth:`_engine.Engine.begin` " 

2223 "context manager instead.", 

2224 ) 

2225 def transaction(self, callable_, *args, **kwargs): 

2226 r"""Execute the given function within a transaction boundary. 

2227 

2228 The function is passed this :class:`_engine.Connection` 

2229 as the first argument, followed by the given \*args and \**kwargs, 

2230 e.g.:: 

2231 

2232 def do_something(conn, x, y): 

2233 conn.execute(text("some statement"), {'x':x, 'y':y}) 

2234 

2235 conn.transaction(do_something, 5, 10) 

2236 

2237 The operations inside the function are all invoked within the 

2238 context of a single :class:`.Transaction`. 

2239 Upon success, the transaction is committed. If an 

2240 exception is raised, the transaction is rolled back 

2241 before propagating the exception. 

2242 

2243 .. note:: 

2244 

2245 The :meth:`.transaction` method is superseded by 

2246 the usage of the Python ``with:`` statement, which can 

2247 be used with :meth:`_engine.Connection.begin`:: 

2248 

2249 with conn.begin(): 

2250 conn.execute(text("some statement"), {'x':5, 'y':10}) 

2251 

2252 As well as with :meth:`_engine.Engine.begin`:: 

2253 

2254 with engine.begin() as conn: 

2255 conn.execute(text("some statement"), {'x':5, 'y':10}) 

2256 

2257 .. seealso:: 

2258 

2259 :meth:`_engine.Engine.begin` - engine-level transactional 

2260 context 

2261 

2262 :meth:`_engine.Engine.transaction` - engine-level version of 

2263 :meth:`_engine.Connection.transaction` 

2264 

2265 """ 

2266 

2267 kwargs["_sa_skip_warning"] = True 

2268 trans = self.begin() 

2269 try: 

2270 ret = self.run_callable(callable_, *args, **kwargs) 

2271 trans.commit() 

2272 return ret 

2273 except: 

2274 with util.safe_reraise(): 

2275 trans.rollback() 

2276 

2277 @util.deprecated( 

2278 "1.4", 

2279 "The :meth:`_engine.Connection.run_callable` " 

2280 "method is deprecated and will " 

2281 "be removed in a future release. Invoke the callable function " 

2282 "directly, passing the Connection.", 

2283 ) 

2284 def run_callable(self, callable_, *args, **kwargs): 

2285 r"""Given a callable object or function, execute it, passing 

2286 a :class:`_engine.Connection` as the first argument. 

2287 

2288 The given \*args and \**kwargs are passed subsequent 

2289 to the :class:`_engine.Connection` argument. 

2290 

2291 This function, along with :meth:`_engine.Engine.run_callable`, 

2292 allows a function to be run with a :class:`_engine.Connection` 

2293 or :class:`_engine.Engine` object without the need to know 

2294 which one is being dealt with. 

2295 

2296 """ 

2297 return callable_(self, *args, **kwargs) 

2298 

2299 

2300class ExceptionContextImpl(ExceptionContext): 

2301 """Implement the :class:`.ExceptionContext` interface.""" 

2302 

2303 def __init__( 

2304 self, 

2305 exception, 

2306 sqlalchemy_exception, 

2307 engine, 

2308 connection, 

2309 cursor, 

2310 statement, 

2311 parameters, 

2312 context, 

2313 is_disconnect, 

2314 invalidate_pool_on_disconnect, 

2315 ): 

2316 self.engine = engine 

2317 self.connection = connection 

2318 self.sqlalchemy_exception = sqlalchemy_exception 

2319 self.original_exception = exception 

2320 self.execution_context = context 

2321 self.statement = statement 

2322 self.parameters = parameters 

2323 self.is_disconnect = is_disconnect 

2324 self.invalidate_pool_on_disconnect = invalidate_pool_on_disconnect 

2325 

2326 

2327class Transaction(TransactionalContext): 

2328 """Represent a database transaction in progress. 

2329 

2330 The :class:`.Transaction` object is procured by 

2331 calling the :meth:`_engine.Connection.begin` method of 

2332 :class:`_engine.Connection`:: 

2333 

2334 from sqlalchemy import create_engine 

2335 engine = create_engine("postgresql://scott:tiger@localhost/test") 

2336 connection = engine.connect() 

2337 trans = connection.begin() 

2338 connection.execute(text("insert into x (a, b) values (1, 2)")) 

2339 trans.commit() 

2340 

2341 The object provides :meth:`.rollback` and :meth:`.commit` 

2342 methods in order to control transaction boundaries. It 

2343 also implements a context manager interface so that 

2344 the Python ``with`` statement can be used with the 

2345 :meth:`_engine.Connection.begin` method:: 

2346 

2347 with connection.begin(): 

2348 connection.execute(text("insert into x (a, b) values (1, 2)")) 

2349 

2350 The Transaction object is **not** threadsafe. 

2351 

2352 .. seealso:: 

2353 

2354 :meth:`_engine.Connection.begin` 

2355 

2356 :meth:`_engine.Connection.begin_twophase` 

2357 

2358 :meth:`_engine.Connection.begin_nested` 

2359 

2360 .. index:: 

2361 single: thread safety; Transaction 

2362 """ 

2363 

2364 __slots__ = () 

2365 

2366 _is_root = False 

2367 

2368 def __init__(self, connection): 

2369 raise NotImplementedError() 

2370 

2371 def _do_deactivate(self): 

2372 """do whatever steps are necessary to set this transaction as 

2373 "deactive", however leave this transaction object in place as far 

2374 as the connection's state. 

2375 

2376 for a "real" transaction this should roll back the transaction 

2377 and ensure this transaction is no longer a reset agent. 

2378 

2379 this is used for nesting of marker transactions where the marker 

2380 can set the "real" transaction as rolled back, however it stays 

2381 in place. 

2382 

2383 for 2.0 we hope to remove this nesting feature. 

2384 

2385 """ 

2386 raise NotImplementedError() 

2387 

2388 @property 

2389 def _deactivated_from_connection(self): 

2390 """True if this transaction is totally deactivated from the connection 

2391 and therefore can no longer affect its state. 

2392 

2393 """ 

2394 raise NotImplementedError() 

2395 

2396 def _do_close(self): 

2397 raise NotImplementedError() 

2398 

2399 def _do_rollback(self): 

2400 raise NotImplementedError() 

2401 

2402 def _do_commit(self): 

2403 raise NotImplementedError() 

2404 

2405 @property 

2406 def is_valid(self): 

2407 return self.is_active and not self.connection.invalidated 

2408 

2409 def close(self): 

2410 """Close this :class:`.Transaction`. 

2411 

2412 If this transaction is the base transaction in a begin/commit 

2413 nesting, the transaction will rollback(). Otherwise, the 

2414 method returns. 

2415 

2416 This is used to cancel a Transaction without affecting the scope of 

2417 an enclosing transaction. 

2418 

2419 """ 

2420 try: 

2421 self._do_close() 

2422 finally: 

2423 assert not self.is_active 

2424 

2425 def rollback(self): 

2426 """Roll back this :class:`.Transaction`. 

2427 

2428 The implementation of this may vary based on the type of transaction in 

2429 use: 

2430 

2431 * For a simple database transaction (e.g. :class:`.RootTransaction`), 

2432 it corresponds to a ROLLBACK. 

2433 

2434 * For a :class:`.NestedTransaction`, it corresponds to a 

2435 "ROLLBACK TO SAVEPOINT" operation. 

2436 

2437 * For a :class:`.TwoPhaseTransaction`, DBAPI-specific methods for two 

2438 phase transactions may be used. 

2439 

2440 

2441 """ 

2442 try: 

2443 self._do_rollback() 

2444 finally: 

2445 assert not self.is_active 

2446 

2447 def commit(self): 

2448 """Commit this :class:`.Transaction`. 

2449 

2450 The implementation of this may vary based on the type of transaction in 

2451 use: 

2452 

2453 * For a simple database transaction (e.g. :class:`.RootTransaction`), 

2454 it corresponds to a COMMIT. 

2455 

2456 * For a :class:`.NestedTransaction`, it corresponds to a 

2457 "RELEASE SAVEPOINT" operation. 

2458 

2459 * For a :class:`.TwoPhaseTransaction`, DBAPI-specific methods for two 

2460 phase transactions may be used. 

2461 

2462 """ 

2463 try: 

2464 self._do_commit() 

2465 finally: 

2466 assert not self.is_active 

2467 

2468 def _get_subject(self): 

2469 return self.connection 

2470 

2471 def _transaction_is_active(self): 

2472 return self.is_active 

2473 

2474 def _transaction_is_closed(self): 

2475 return not self._deactivated_from_connection 

2476 

2477 def _rollback_can_be_called(self): 

2478 # for RootTransaction / NestedTransaction, it's safe to call 

2479 # rollback() even if the transaction is deactive and no warnings 

2480 # will be emitted. tested in 

2481 # test_transaction.py -> test_no_rollback_in_deactive(?:_savepoint)? 

2482 return True 

2483 

2484 

2485class MarkerTransaction(Transaction): 

2486 """A 'marker' transaction that is used for nested begin() calls. 

2487 

2488 .. deprecated:: 1.4 future connection for 2.0 won't support this pattern. 

2489 

2490 """ 

2491 

2492 __slots__ = ("connection", "_is_active", "_transaction") 

2493 

2494 def __init__(self, connection): 

2495 assert connection._transaction is not None 

2496 if not connection._transaction.is_active: 

2497 raise exc.InvalidRequestError( 

2498 "the current transaction on this connection is inactive. " 

2499 "Please issue a rollback first." 

2500 ) 

2501 

2502 assert not connection._is_future 

2503 util.warn_deprecated_20( 

2504 "Calling .begin() when a transaction is already begun, creating " 

2505 "a 'sub' transaction, is deprecated " 

2506 "and will be removed in 2.0. See the documentation section " 

2507 "'Migrating from the nesting pattern' for background on how " 

2508 "to migrate from this pattern." 

2509 ) 

2510 

2511 self.connection = connection 

2512 

2513 if connection._trans_context_manager: 

2514 TransactionalContext._trans_ctx_check(connection) 

2515 

2516 if connection._nested_transaction is not None: 

2517 self._transaction = connection._nested_transaction 

2518 else: 

2519 self._transaction = connection._transaction 

2520 self._is_active = True 

2521 

2522 @property 

2523 def _deactivated_from_connection(self): 

2524 return not self.is_active 

2525 

2526 @property 

2527 def is_active(self): 

2528 return self._is_active and self._transaction.is_active 

2529 

2530 def _deactivate(self): 

2531 self._is_active = False 

2532 

2533 def _do_close(self): 

2534 # does not actually roll back the root 

2535 self._deactivate() 

2536 

2537 def _do_rollback(self): 

2538 # does roll back the root 

2539 if self._is_active: 

2540 try: 

2541 self._transaction._do_deactivate() 

2542 finally: 

2543 self._deactivate() 

2544 

2545 def _do_commit(self): 

2546 self._deactivate() 

2547 

2548 

2549class RootTransaction(Transaction): 

2550 """Represent the "root" transaction on a :class:`_engine.Connection`. 

2551 

2552 This corresponds to the current "BEGIN/COMMIT/ROLLBACK" that's occurring 

2553 for the :class:`_engine.Connection`. The :class:`_engine.RootTransaction` 

2554 is created by calling upon the :meth:`_engine.Connection.begin` method, and 

2555 remains associated with the :class:`_engine.Connection` throughout its 

2556 active span. The current :class:`_engine.RootTransaction` in use is 

2557 accessible via the :attr:`_engine.Connection.get_transaction` method of 

2558 :class:`_engine.Connection`. 

2559 

2560 In :term:`2.0 style` use, the :class:`_future.Connection` also employs 

2561 "autobegin" behavior that will create a new 

2562 :class:`_engine.RootTransaction` whenever a connection in a 

2563 non-transactional state is used to emit commands on the DBAPI connection. 

2564 The scope of the :class:`_engine.RootTransaction` in 2.0 style 

2565 use can be controlled using the :meth:`_future.Connection.commit` and 

2566 :meth:`_future.Connection.rollback` methods. 

2567 

2568 

2569 """ 

2570 

2571 _is_root = True 

2572 

2573 __slots__ = ("connection", "is_active") 

2574 

2575 def __init__(self, connection): 

2576 assert connection._transaction is None 

2577 if connection._trans_context_manager: 

2578 TransactionalContext._trans_ctx_check(connection) 

2579 self.connection = connection 

2580 self._connection_begin_impl() 

2581 connection._transaction = self 

2582 

2583 self.is_active = True 

2584 

2585 def _deactivate_from_connection(self): 

2586 if self.is_active: 

2587 assert self.connection._transaction is self 

2588 self.is_active = False 

2589 

2590 elif self.connection._transaction is not self: 

2591 util.warn("transaction already deassociated from connection") 

2592 

2593 @property 

2594 def _deactivated_from_connection(self): 

2595 return self.connection._transaction is not self 

2596 

2597 def _do_deactivate(self): 

2598 # called from a MarkerTransaction to cancel this root transaction. 

2599 # the transaction stays in place as connection._transaction, but 

2600 # is no longer active and is no longer the reset agent for the 

2601 # pooled connection. the connection won't support a new begin() 

2602 # until this transaction is explicitly closed, rolled back, 

2603 # or committed. 

2604 

2605 assert self.connection._transaction is self 

2606 

2607 if self.is_active: 

2608 self._connection_rollback_impl() 

2609 

2610 # handle case where a savepoint was created inside of a marker 

2611 # transaction that refers to a root. nested has to be cancelled 

2612 # also. 

2613 if self.connection._nested_transaction: 

2614 self.connection._nested_transaction._cancel() 

2615 

2616 self._deactivate_from_connection() 

2617 

2618 def _connection_begin_impl(self): 

2619 self.connection._begin_impl(self) 

2620 

2621 def _connection_rollback_impl(self): 

2622 self.connection._rollback_impl() 

2623 

2624 def _connection_commit_impl(self): 

2625 self.connection._commit_impl() 

2626 

2627 def _close_impl(self, try_deactivate=False): 

2628 try: 

2629 if self.is_active: 

2630 self._connection_rollback_impl() 

2631 

2632 if self.connection._nested_transaction: 

2633 self.connection._nested_transaction._cancel() 

2634 finally: 

2635 if self.is_active or try_deactivate: 

2636 self._deactivate_from_connection() 

2637 if self.connection._transaction is self: 

2638 self.connection._transaction = None 

2639 

2640 assert not self.is_active 

2641 assert self.connection._transaction is not self 

2642 

2643 def _do_close(self): 

2644 self._close_impl() 

2645 

2646 def _do_rollback(self): 

2647 self._close_impl(try_deactivate=True) 

2648 

2649 def _do_commit(self): 

2650 if self.is_active: 

2651 assert self.connection._transaction is self 

2652 

2653 try: 

2654 self._connection_commit_impl() 

2655 finally: 

2656 # whether or not commit succeeds, cancel any 

2657 # nested transactions, make this transaction "inactive" 

2658 # and remove it as a reset agent 

2659 if self.connection._nested_transaction: 

2660 self.connection._nested_transaction._cancel() 

2661 

2662 self._deactivate_from_connection() 

2663 

2664 # ...however only remove as the connection's current transaction 

2665 # if commit succeeded. otherwise it stays on so that a rollback 

2666 # needs to occur. 

2667 self.connection._transaction = None 

2668 else: 

2669 if self.connection._transaction is self: 

2670 self.connection._invalid_transaction() 

2671 else: 

2672 raise exc.InvalidRequestError("This transaction is inactive") 

2673 

2674 assert not self.is_active 

2675 assert self.connection._transaction is not self 

2676 

2677 

2678class NestedTransaction(Transaction): 

2679 """Represent a 'nested', or SAVEPOINT transaction. 

2680 

2681 The :class:`.NestedTransaction` object is created by calling the 

2682 :meth:`_engine.Connection.begin_nested` method of 

2683 :class:`_engine.Connection`. 

2684 

2685 When using :class:`.NestedTransaction`, the semantics of "begin" / 

2686 "commit" / "rollback" are as follows: 

2687 

2688 * the "begin" operation corresponds to the "BEGIN SAVEPOINT" command, where 

2689 the savepoint is given an explicit name that is part of the state 

2690 of this object. 

2691 

2692 * The :meth:`.NestedTransaction.commit` method corresponds to a 

2693 "RELEASE SAVEPOINT" operation, using the savepoint identifier associated 

2694 with this :class:`.NestedTransaction`. 

2695 

2696 * The :meth:`.NestedTransaction.rollback` method corresponds to a 

2697 "ROLLBACK TO SAVEPOINT" operation, using the savepoint identifier 

2698 associated with this :class:`.NestedTransaction`. 

2699 

2700 The rationale for mimicking the semantics of an outer transaction in 

2701 terms of savepoints so that code may deal with a "savepoint" transaction 

2702 and an "outer" transaction in an agnostic way. 

2703 

2704 .. seealso:: 

2705 

2706 :ref:`session_begin_nested` - ORM version of the SAVEPOINT API. 

2707 

2708 """ 

2709 

2710 __slots__ = ("connection", "is_active", "_savepoint", "_previous_nested") 

2711 

2712 def __init__(self, connection): 

2713 assert connection._transaction is not None 

2714 if connection._trans_context_manager: 

2715 TransactionalContext._trans_ctx_check(connection) 

2716 self.connection = connection 

2717 self._savepoint = self.connection._savepoint_impl() 

2718 self.is_active = True 

2719 self._previous_nested = connection._nested_transaction 

2720 connection._nested_transaction = self 

2721 

2722 def _deactivate_from_connection(self, warn=True): 

2723 if self.connection._nested_transaction is self: 

2724 self.connection._nested_transaction = self._previous_nested 

2725 elif warn: 

2726 util.warn( 

2727 "nested transaction already deassociated from connection" 

2728 ) 

2729 

2730 @property 

2731 def _deactivated_from_connection(self): 

2732 return self.connection._nested_transaction is not self 

2733 

2734 def _cancel(self): 

2735 # called by RootTransaction when the outer transaction is 

2736 # committed, rolled back, or closed to cancel all savepoints 

2737 # without any action being taken 

2738 self.is_active = False 

2739 self._deactivate_from_connection() 

2740 if self._previous_nested: 

2741 self._previous_nested._cancel() 

2742 

2743 def _close_impl(self, deactivate_from_connection, warn_already_deactive): 

2744 try: 

2745 if self.is_active and self.connection._transaction.is_active: 

2746 self.connection._rollback_to_savepoint_impl(self._savepoint) 

2747 finally: 

2748 self.is_active = False 

2749 

2750 if deactivate_from_connection: 

2751 self._deactivate_from_connection(warn=warn_already_deactive) 

2752 

2753 assert not self.is_active 

2754 if deactivate_from_connection: 

2755 assert self.connection._nested_transaction is not self 

2756 

2757 def _do_deactivate(self): 

2758 self._close_impl(False, False) 

2759 

2760 def _do_close(self): 

2761 self._close_impl(True, False) 

2762 

2763 def _do_rollback(self): 

2764 self._close_impl(True, True) 

2765 

2766 def _do_commit(self): 

2767 if self.is_active: 

2768 try: 

2769 self.connection._release_savepoint_impl(self._savepoint) 

2770 finally: 

2771 # nested trans becomes inactive on failed release 

2772 # unconditionally. this prevents it from trying to 

2773 # emit SQL when it rolls back. 

2774 self.is_active = False 

2775 

2776 # but only de-associate from connection if it succeeded 

2777 self._deactivate_from_connection() 

2778 else: 

2779 if self.connection._nested_transaction is self: 

2780 self.connection._invalid_transaction() 

2781 else: 

2782 raise exc.InvalidRequestError( 

2783 "This nested transaction is inactive" 

2784 ) 

2785 

2786 

2787class TwoPhaseTransaction(RootTransaction): 

2788 """Represent a two-phase transaction. 

2789 

2790 A new :class:`.TwoPhaseTransaction` object may be procured 

2791 using the :meth:`_engine.Connection.begin_twophase` method. 

2792 

2793 The interface is the same as that of :class:`.Transaction` 

2794 with the addition of the :meth:`prepare` method. 

2795 

2796 """ 

2797 

2798 __slots__ = ("connection", "is_active", "xid", "_is_prepared") 

2799 

2800 def __init__(self, connection, xid): 

2801 self._is_prepared = False 

2802 self.xid = xid 

2803 super(TwoPhaseTransaction, self).__init__(connection) 

2804 

2805 def prepare(self): 

2806 """Prepare this :class:`.TwoPhaseTransaction`. 

2807 

2808 After a PREPARE, the transaction can be committed. 

2809 

2810 """ 

2811 if not self.is_active: 

2812 raise exc.InvalidRequestError("This transaction is inactive") 

2813 self.connection._prepare_twophase_impl(self.xid) 

2814 self._is_prepared = True 

2815 

2816 def _connection_begin_impl(self): 

2817 self.connection._begin_twophase_impl(self) 

2818 

2819 def _connection_rollback_impl(self): 

2820 self.connection._rollback_twophase_impl(self.xid, self._is_prepared) 

2821 

2822 def _connection_commit_impl(self): 

2823 self.connection._commit_twophase_impl(self.xid, self._is_prepared) 

2824 

2825 

2826class Engine(Connectable, log.Identified): 

2827 """ 

2828 Connects a :class:`~sqlalchemy.pool.Pool` and 

2829 :class:`~sqlalchemy.engine.interfaces.Dialect` together to provide a 

2830 source of database connectivity and behavior. 

2831 

2832 This is the **SQLAlchemy 1.x version** of :class:`_engine.Engine`. For 

2833 the :term:`2.0 style` version, which includes some API differences, 

2834 see :class:`_future.Engine`. 

2835 

2836 An :class:`_engine.Engine` object is instantiated publicly using the 

2837 :func:`~sqlalchemy.create_engine` function. 

2838 

2839 .. seealso:: 

2840 

2841 :doc:`/core/engines` 

2842 

2843 :ref:`connections_toplevel` 

2844 

2845 """ 

2846 

2847 _execution_options = _EMPTY_EXECUTION_OPTS 

2848 _has_events = False 

2849 _connection_cls = Connection 

2850 _sqla_logger_namespace = "sqlalchemy.engine.Engine" 

2851 _is_future = False 

2852 

2853 _schema_translate_map = None 

2854 

2855 def __init__( 

2856 self, 

2857 pool, 

2858 dialect, 

2859 url, 

2860 logging_name=None, 

2861 echo=None, 

2862 query_cache_size=500, 

2863 execution_options=None, 

2864 hide_parameters=False, 

2865 ): 

2866 self.pool = pool 

2867 self.url = url 

2868 self.dialect = dialect 

2869 if logging_name: 

2870 self.logging_name = logging_name 

2871 self.echo = echo 

2872 self.hide_parameters = hide_parameters 

2873 if query_cache_size != 0: 

2874 self._compiled_cache = util.LRUCache( 

2875 query_cache_size, size_alert=self._lru_size_alert 

2876 ) 

2877 else: 

2878 self._compiled_cache = None 

2879 log.instance_logger(self, echoflag=echo) 

2880 if execution_options: 

2881 self.update_execution_options(**execution_options) 

2882 

2883 def _lru_size_alert(self, cache): 

2884 if self._should_log_info: 

2885 self.logger.info( 

2886 "Compiled cache size pruning from %d items to %d. " 

2887 "Increase cache size to reduce the frequency of pruning.", 

2888 len(cache), 

2889 cache.capacity, 

2890 ) 

2891 

2892 @property 

2893 def engine(self): 

2894 return self 

2895 

2896 def clear_compiled_cache(self): 

2897 """Clear the compiled cache associated with the dialect. 

2898 

2899 This applies **only** to the built-in cache that is established 

2900 via the :paramref:`_engine.create_engine.query_cache_size` parameter. 

2901 It will not impact any dictionary caches that were passed via the 

2902 :paramref:`.Connection.execution_options.query_cache` parameter. 

2903 

2904 .. versionadded:: 1.4 

2905 

2906 """ 

2907 if self._compiled_cache: 

2908 self._compiled_cache.clear() 

2909 

2910 def update_execution_options(self, **opt): 

2911 r"""Update the default execution_options dictionary 

2912 of this :class:`_engine.Engine`. 

2913 

2914 The given keys/values in \**opt are added to the 

2915 default execution options that will be used for 

2916 all connections. The initial contents of this dictionary 

2917 can be sent via the ``execution_options`` parameter 

2918 to :func:`_sa.create_engine`. 

2919 

2920 .. seealso:: 

2921 

2922 :meth:`_engine.Connection.execution_options` 

2923 

2924 :meth:`_engine.Engine.execution_options` 

2925 

2926 """ 

2927 self._execution_options = self._execution_options.union(opt) 

2928 self.dispatch.set_engine_execution_options(self, opt) 

2929 self.dialect.set_engine_execution_options(self, opt) 

2930 

2931 def execution_options(self, **opt): 

2932 """Return a new :class:`_engine.Engine` that will provide 

2933 :class:`_engine.Connection` objects with the given execution options. 

2934 

2935 The returned :class:`_engine.Engine` remains related to the original 

2936 :class:`_engine.Engine` in that it shares the same connection pool and 

2937 other state: 

2938 

2939 * The :class:`_pool.Pool` used by the new :class:`_engine.Engine` 

2940 is the 

2941 same instance. The :meth:`_engine.Engine.dispose` 

2942 method will replace 

2943 the connection pool instance for the parent engine as well 

2944 as this one. 

2945 * Event listeners are "cascaded" - meaning, the new 

2946 :class:`_engine.Engine` 

2947 inherits the events of the parent, and new events can be associated 

2948 with the new :class:`_engine.Engine` individually. 

2949 * The logging configuration and logging_name is copied from the parent 

2950 :class:`_engine.Engine`. 

2951 

2952 The intent of the :meth:`_engine.Engine.execution_options` method is 

2953 to implement "sharding" schemes where multiple :class:`_engine.Engine` 

2954 objects refer to the same connection pool, but are differentiated 

2955 by options that would be consumed by a custom event:: 

2956 

2957 primary_engine = create_engine("mysql://") 

2958 shard1 = primary_engine.execution_options(shard_id="shard1") 

2959 shard2 = primary_engine.execution_options(shard_id="shard2") 

2960 

2961 Above, the ``shard1`` engine serves as a factory for 

2962 :class:`_engine.Connection` 

2963 objects that will contain the execution option 

2964 ``shard_id=shard1``, and ``shard2`` will produce 

2965 :class:`_engine.Connection` 

2966 objects that contain the execution option ``shard_id=shard2``. 

2967 

2968 An event handler can consume the above execution option to perform 

2969 a schema switch or other operation, given a connection. Below 

2970 we emit a MySQL ``use`` statement to switch databases, at the same 

2971 time keeping track of which database we've established using the 

2972 :attr:`_engine.Connection.info` dictionary, 

2973 which gives us a persistent 

2974 storage space that follows the DBAPI connection:: 

2975 

2976 from sqlalchemy import event 

2977 from sqlalchemy.engine import Engine 

2978 

2979 shards = {"default": "base", shard_1: "db1", "shard_2": "db2"} 

2980 

2981 @event.listens_for(Engine, "before_cursor_execute") 

2982 def _switch_shard(conn, cursor, stmt, 

2983 params, context, executemany): 

2984 shard_id = conn._execution_options.get('shard_id', "default") 

2985 current_shard = conn.info.get("current_shard", None) 

2986 

2987 if current_shard != shard_id: 

2988 cursor.execute("use %s" % shards[shard_id]) 

2989 conn.info["current_shard"] = shard_id 

2990 

2991 .. seealso:: 

2992 

2993 :meth:`_engine.Connection.execution_options` 

2994 - update execution options 

2995 on a :class:`_engine.Connection` object. 

2996 

2997 :meth:`_engine.Engine.update_execution_options` 

2998 - update the execution 

2999 options for a given :class:`_engine.Engine` in place. 

3000 

3001 :meth:`_engine.Engine.get_execution_options` 

3002 

3003 

3004 """ 

3005 return self._option_cls(self, opt) 

3006 

3007 def get_execution_options(self): 

3008 """Get the non-SQL options which will take effect during execution. 

3009 

3010 .. versionadded: 1.3 

3011 

3012 .. seealso:: 

3013 

3014 :meth:`_engine.Engine.execution_options` 

3015 """ 

3016 return self._execution_options 

3017 

3018 @property 

3019 def name(self): 

3020 """String name of the :class:`~sqlalchemy.engine.interfaces.Dialect` 

3021 in use by this :class:`Engine`.""" 

3022 

3023 return self.dialect.name 

3024 

3025 @property 

3026 def driver(self): 

3027 """Driver name of the :class:`~sqlalchemy.engine.interfaces.Dialect` 

3028 in use by this :class:`Engine`.""" 

3029 

3030 return self.dialect.driver 

3031 

3032 echo = log.echo_property() 

3033 

3034 def __repr__(self): 

3035 return "Engine(%r)" % (self.url,) 

3036 

3037 def dispose(self, close=True): 

3038 """Dispose of the connection pool used by this 

3039 :class:`_engine.Engine`. 

3040 

3041 A new connection pool is created immediately after the old one has been 

3042 disposed. The previous connection pool is disposed either actively, by 

3043 closing out all currently checked-in connections in that pool, or 

3044 passively, by losing references to it but otherwise not closing any 

3045 connections. The latter strategy is more appropriate for an initializer 

3046 in a forked Python process. 

3047 

3048 :param close: if left at its default of ``True``, has the 

3049 effect of fully closing all **currently checked in** 

3050 database connections. Connections that are still checked out 

3051 will **not** be closed, however they will no longer be associated 

3052 with this :class:`_engine.Engine`, 

3053 so when they are closed individually, eventually the 

3054 :class:`_pool.Pool` which they are associated with will 

3055 be garbage collected and they will be closed out fully, if 

3056 not already closed on checkin. 

3057 

3058 If set to ``False``, the previous connection pool is de-referenced, 

3059 and otherwise not touched in any way. 

3060 

3061 .. versionadded:: 1.4.33 Added the :paramref:`.Engine.dispose.close` 

3062 parameter to allow the replacement of a connection pool in a child 

3063 process without interfering with the connections used by the parent 

3064 process. 

3065 

3066 

3067 .. seealso:: 

3068 

3069 :ref:`engine_disposal` 

3070 

3071 :ref:`pooling_multiprocessing` 

3072 

3073 """ 

3074 if close: 

3075 self.pool.dispose() 

3076 self.pool = self.pool.recreate() 

3077 self.dispatch.engine_disposed(self) 

3078 

3079 def _execute_default( 

3080 self, default, multiparams=(), params=util.EMPTY_DICT 

3081 ): 

3082 with self.connect() as conn: 

3083 return conn._execute_default(default, multiparams, params) 

3084 

3085 @contextlib.contextmanager 

3086 def _optional_conn_ctx_manager(self, connection=None): 

3087 if connection is None: 

3088 with self.connect() as conn: 

3089 yield conn 

3090 else: 

3091 yield connection 

3092 

3093 class _trans_ctx(object): 

3094 def __init__(self, conn, transaction, close_with_result): 

3095 self.conn = conn 

3096 self.transaction = transaction 

3097 self.close_with_result = close_with_result 

3098 

3099 def __enter__(self): 

3100 self.transaction.__enter__() 

3101 return self.conn 

3102 

3103 def __exit__(self, type_, value, traceback): 

3104 try: 

3105 self.transaction.__exit__(type_, value, traceback) 

3106 finally: 

3107 if not self.close_with_result: 

3108 self.conn.close() 

3109 

3110 def begin(self, close_with_result=False): 

3111 """Return a context manager delivering a :class:`_engine.Connection` 

3112 with a :class:`.Transaction` established. 

3113 

3114 E.g.:: 

3115 

3116 with engine.begin() as conn: 

3117 conn.execute( 

3118 text("insert into table (x, y, z) values (1, 2, 3)") 

3119 ) 

3120 conn.execute(text("my_special_procedure(5)")) 

3121 

3122 Upon successful operation, the :class:`.Transaction` 

3123 is committed. If an error is raised, the :class:`.Transaction` 

3124 is rolled back. 

3125 

3126 Legacy use only: the ``close_with_result`` flag is normally ``False``, 

3127 and indicates that the :class:`_engine.Connection` will be closed when 

3128 the operation is complete. When set to ``True``, it indicates the 

3129 :class:`_engine.Connection` is in "single use" mode, where the 

3130 :class:`_engine.CursorResult` returned by the first call to 

3131 :meth:`_engine.Connection.execute` will close the 

3132 :class:`_engine.Connection` when that :class:`_engine.CursorResult` has 

3133 exhausted all result rows. 

3134 

3135 .. seealso:: 

3136 

3137 :meth:`_engine.Engine.connect` - procure a 

3138 :class:`_engine.Connection` from 

3139 an :class:`_engine.Engine`. 

3140 

3141 :meth:`_engine.Connection.begin` - start a :class:`.Transaction` 

3142 for a particular :class:`_engine.Connection`. 

3143 

3144 """ 

3145 if self._connection_cls._is_future: 

3146 conn = self.connect() 

3147 else: 

3148 conn = self.connect(close_with_result=close_with_result) 

3149 try: 

3150 trans = conn.begin() 

3151 except: 

3152 with util.safe_reraise(): 

3153 conn.close() 

3154 return Engine._trans_ctx(conn, trans, close_with_result) 

3155 

3156 @util.deprecated( 

3157 "1.4", 

3158 "The :meth:`_engine.Engine.transaction` " 

3159 "method is deprecated and will be " 

3160 "removed in a future release. Use the :meth:`_engine.Engine.begin` " 

3161 "context " 

3162 "manager instead.", 

3163 ) 

3164 def transaction(self, callable_, *args, **kwargs): 

3165 r"""Execute the given function within a transaction boundary. 

3166 

3167 The function is passed a :class:`_engine.Connection` newly procured 

3168 from :meth:`_engine.Engine.connect` as the first argument, 

3169 followed by the given \*args and \**kwargs. 

3170 

3171 e.g.:: 

3172 

3173 def do_something(conn, x, y): 

3174 conn.execute(text("some statement"), {'x':x, 'y':y}) 

3175 

3176 engine.transaction(do_something, 5, 10) 

3177 

3178 The operations inside the function are all invoked within the 

3179 context of a single :class:`.Transaction`. 

3180 Upon success, the transaction is committed. If an 

3181 exception is raised, the transaction is rolled back 

3182 before propagating the exception. 

3183 

3184 .. note:: 

3185 

3186 The :meth:`.transaction` method is superseded by 

3187 the usage of the Python ``with:`` statement, which can 

3188 be used with :meth:`_engine.Engine.begin`:: 

3189 

3190 with engine.begin() as conn: 

3191 conn.execute(text("some statement"), {'x':5, 'y':10}) 

3192 

3193 .. seealso:: 

3194 

3195 :meth:`_engine.Engine.begin` - engine-level transactional 

3196 context 

3197 

3198 :meth:`_engine.Connection.transaction` 

3199 - connection-level version of 

3200 :meth:`_engine.Engine.transaction` 

3201 

3202 """ 

3203 kwargs["_sa_skip_warning"] = True 

3204 with self.connect() as conn: 

3205 return conn.transaction(callable_, *args, **kwargs) 

3206 

3207 @util.deprecated( 

3208 "1.4", 

3209 "The :meth:`_engine.Engine.run_callable` " 

3210 "method is deprecated and will be " 

3211 "removed in a future release. Use the :meth:`_engine.Engine.begin` " 

3212 "context manager instead.", 

3213 ) 

3214 def run_callable(self, callable_, *args, **kwargs): 

3215 r"""Given a callable object or function, execute it, passing 

3216 a :class:`_engine.Connection` as the first argument. 

3217 

3218 The given \*args and \**kwargs are passed subsequent 

3219 to the :class:`_engine.Connection` argument. 

3220 

3221 This function, along with :meth:`_engine.Connection.run_callable`, 

3222 allows a function to be run with a :class:`_engine.Connection` 

3223 or :class:`_engine.Engine` object without the need to know 

3224 which one is being dealt with. 

3225 

3226 """ 

3227 kwargs["_sa_skip_warning"] = True 

3228 with self.connect() as conn: 

3229 return conn.run_callable(callable_, *args, **kwargs) 

3230 

3231 def _run_ddl_visitor(self, visitorcallable, element, **kwargs): 

3232 with self.begin() as conn: 

3233 conn._run_ddl_visitor(visitorcallable, element, **kwargs) 

3234 

3235 @util.deprecated_20( 

3236 ":meth:`_engine.Engine.execute`", 

3237 alternative="All statement execution in SQLAlchemy 2.0 is performed " 

3238 "by the :meth:`_engine.Connection.execute` method of " 

3239 ":class:`_engine.Connection`, " 

3240 "or in the ORM by the :meth:`.Session.execute` method of " 

3241 ":class:`.Session`.", 

3242 ) 

3243 def execute(self, statement, *multiparams, **params): 

3244 """Executes the given construct and returns a 

3245 :class:`_engine.CursorResult`. 

3246 

3247 The arguments are the same as those used by 

3248 :meth:`_engine.Connection.execute`. 

3249 

3250 Here, a :class:`_engine.Connection` is acquired using the 

3251 :meth:`_engine.Engine.connect` method, and the statement executed 

3252 with that connection. The returned :class:`_engine.CursorResult` 

3253 is flagged 

3254 such that when the :class:`_engine.CursorResult` is exhausted and its 

3255 underlying cursor is closed, the :class:`_engine.Connection` 

3256 created here 

3257 will also be closed, which allows its associated DBAPI connection 

3258 resource to be returned to the connection pool. 

3259 

3260 """ 

3261 connection = self.connect(close_with_result=True) 

3262 return connection.execute(statement, *multiparams, **params) 

3263 

3264 @util.deprecated_20( 

3265 ":meth:`_engine.Engine.scalar`", 

3266 alternative="All statement execution in SQLAlchemy 2.0 is performed " 

3267 "by the :meth:`_engine.Connection.execute` method of " 

3268 ":class:`_engine.Connection`, " 

3269 "or in the ORM by the :meth:`.Session.execute` method of " 

3270 ":class:`.Session`; the :meth:`_future.Result.scalar` " 

3271 "method can then be " 

3272 "used to return a scalar result.", 

3273 ) 

3274 def scalar(self, statement, *multiparams, **params): 

3275 """Executes and returns the first column of the first row. 

3276 

3277 The underlying result/cursor is closed after execution. 

3278 """ 

3279 return self.execute(statement, *multiparams, **params).scalar() 

3280 

3281 def _execute_clauseelement( 

3282 self, 

3283 elem, 

3284 multiparams=None, 

3285 params=None, 

3286 execution_options=_EMPTY_EXECUTION_OPTS, 

3287 ): 

3288 connection = self.connect(close_with_result=True) 

3289 return connection._execute_clauseelement( 

3290 elem, multiparams, params, execution_options 

3291 ) 

3292 

3293 def _execute_compiled( 

3294 self, 

3295 compiled, 

3296 multiparams, 

3297 params, 

3298 execution_options=_EMPTY_EXECUTION_OPTS, 

3299 ): 

3300 connection = self.connect(close_with_result=True) 

3301 return connection._execute_compiled( 

3302 compiled, multiparams, params, execution_options 

3303 ) 

3304 

3305 def connect(self, close_with_result=False): 

3306 """Return a new :class:`_engine.Connection` object. 

3307 

3308 The :class:`_engine.Connection` object is a facade that uses a DBAPI 

3309 connection internally in order to communicate with the database. This 

3310 connection is procured from the connection-holding :class:`_pool.Pool` 

3311 referenced by this :class:`_engine.Engine`. When the 

3312 :meth:`_engine.Connection.close` method of the 

3313 :class:`_engine.Connection` object 

3314 is called, the underlying DBAPI connection is then returned to the 

3315 connection pool, where it may be used again in a subsequent call to 

3316 :meth:`_engine.Engine.connect`. 

3317 

3318 """ 

3319 

3320 return self._connection_cls(self, close_with_result=close_with_result) 

3321 

3322 @util.deprecated( 

3323 "1.4", 

3324 "The :meth:`_engine.Engine.table_names` " 

3325 "method is deprecated and will be " 

3326 "removed in a future release. Please refer to " 

3327 ":meth:`_reflection.Inspector.get_table_names`.", 

3328 ) 

3329 def table_names(self, schema=None, connection=None): 

3330 """Return a list of all table names available in the database. 

3331 

3332 :param schema: Optional, retrieve names from a non-default schema. 

3333 

3334 :param connection: Optional, use a specified connection. 

3335 """ 

3336 with self._optional_conn_ctx_manager(connection) as conn: 

3337 insp = inspection.inspect(conn) 

3338 return insp.get_table_names(schema) 

3339 

3340 @util.deprecated( 

3341 "1.4", 

3342 "The :meth:`_engine.Engine.has_table` " 

3343 "method is deprecated and will be " 

3344 "removed in a future release. Please refer to " 

3345 ":meth:`_reflection.Inspector.has_table`.", 

3346 ) 

3347 def has_table(self, table_name, schema=None): 

3348 """Return True if the given backend has a table of the given name. 

3349 

3350 .. seealso:: 

3351 

3352 :ref:`metadata_reflection_inspector` - detailed schema inspection 

3353 using the :class:`_reflection.Inspector` interface. 

3354 

3355 :class:`.quoted_name` - used to pass quoting information along 

3356 with a schema identifier. 

3357 

3358 """ 

3359 with self._optional_conn_ctx_manager(None) as conn: 

3360 insp = inspection.inspect(conn) 

3361 return insp.has_table(table_name, schema=schema) 

3362 

3363 def _wrap_pool_connect(self, fn, connection): 

3364 dialect = self.dialect 

3365 try: 

3366 return fn() 

3367 except dialect.dbapi.Error as e: 

3368 if connection is None: 

3369 Connection._handle_dbapi_exception_noconnection( 

3370 e, dialect, self 

3371 ) 

3372 else: 

3373 util.raise_( 

3374 sys.exc_info()[1], with_traceback=sys.exc_info()[2] 

3375 ) 

3376 

3377 def raw_connection(self, _connection=None): 

3378 """Return a "raw" DBAPI connection from the connection pool. 

3379 

3380 The returned object is a proxied version of the DBAPI 

3381 connection object used by the underlying driver in use. 

3382 The object will have all the same behavior as the real DBAPI 

3383 connection, except that its ``close()`` method will result in the 

3384 connection being returned to the pool, rather than being closed 

3385 for real. 

3386 

3387 This method provides direct DBAPI connection access for 

3388 special situations when the API provided by 

3389 :class:`_engine.Connection` 

3390 is not needed. When a :class:`_engine.Connection` object is already 

3391 present, the DBAPI connection is available using 

3392 the :attr:`_engine.Connection.connection` accessor. 

3393 

3394 .. seealso:: 

3395 

3396 :ref:`dbapi_connections` 

3397 

3398 """ 

3399 return self._wrap_pool_connect(self.pool.connect, _connection) 

3400 

3401 

3402class OptionEngineMixin(object): 

3403 _sa_propagate_class_events = False 

3404 

3405 def __init__(self, proxied, execution_options): 

3406 self._proxied = proxied 

3407 self.url = proxied.url 

3408 self.dialect = proxied.dialect 

3409 self.logging_name = proxied.logging_name 

3410 self.echo = proxied.echo 

3411 self._compiled_cache = proxied._compiled_cache 

3412 self.hide_parameters = proxied.hide_parameters 

3413 log.instance_logger(self, echoflag=self.echo) 

3414 

3415 # note: this will propagate events that are assigned to the parent 

3416 # engine after this OptionEngine is created. Since we share 

3417 # the events of the parent we also disallow class-level events 

3418 # to apply to the OptionEngine class directly. 

3419 # 

3420 # the other way this can work would be to transfer existing 

3421 # events only, using: 

3422 # self.dispatch._update(proxied.dispatch) 

3423 # 

3424 # that might be more appropriate however it would be a behavioral 

3425 # change for logic that assigns events to the parent engine and 

3426 # would like it to take effect for the already-created sub-engine. 

3427 self.dispatch = self.dispatch._join(proxied.dispatch) 

3428 

3429 self._execution_options = proxied._execution_options 

3430 self.update_execution_options(**execution_options) 

3431 

3432 def _get_pool(self): 

3433 return self._proxied.pool 

3434 

3435 def _set_pool(self, pool): 

3436 self._proxied.pool = pool 

3437 

3438 pool = property(_get_pool, _set_pool) 

3439 

3440 def _get_has_events(self): 

3441 return self._proxied._has_events or self.__dict__.get( 

3442 "_has_events", False 

3443 ) 

3444 

3445 def _set_has_events(self, value): 

3446 self.__dict__["_has_events"] = value 

3447 

3448 _has_events = property(_get_has_events, _set_has_events) 

3449 

3450 

3451class OptionEngine(OptionEngineMixin, Engine): 

3452 pass 

3453 

3454 

3455Engine._option_cls = OptionEngine