Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# engine/base.py 

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

3# <see AUTHORS file> 

4# 

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

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

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 .. import exc 

16from .. import interfaces 

17from .. import log 

18from .. import util 

19from ..sql import schema 

20from ..sql import util as sql_util 

21 

22 

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

24 

25""" 

26 

27 

28class Connection(Connectable): 

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

30 

31 Provides execution support for string-based SQL statements as well as 

32 :class:`_expression.ClauseElement`, :class:`.Compiled` and 

33 :class:`.DefaultGenerator` 

34 objects. Provides a :meth:`begin` method to return :class:`.Transaction` 

35 objects. 

36 

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

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

39 possible that the underlying DBAPI connection may not support shared 

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

41 

42 The Connection object represents a single dbapi connection checked out 

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

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

45 connection pool to properly manage connections, connections should be 

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

47 connection is not in use. 

48 

49 .. index:: 

50 single: thread safety; Connection 

51 

52 """ 

53 

54 schema_for_object = schema._schema_getter(None) 

55 """Return the ".schema" attribute for an object. 

56 

57 Used for :class:`_schema.Table`, :class:`.Sequence` and similar objects, 

58 and takes into account 

59 the :paramref:`.Connection.execution_options.schema_translate_map` 

60 parameter. 

61 

62 .. versionadded:: 1.1 

63 

64 .. seealso:: 

65 

66 :ref:`schema_translating` 

67 

68 """ 

69 

70 def __init__( 

71 self, 

72 engine, 

73 connection=None, 

74 close_with_result=False, 

75 _branch_from=None, 

76 _execution_options=None, 

77 _dispatch=None, 

78 _has_events=None, 

79 ): 

80 """Construct a new Connection. 

81 

82 The constructor here is not public and is only called only by an 

83 :class:`_engine.Engine`. See :meth:`_engine.Engine.connect` and 

84 :meth:`_engine.Engine.contextual_connect` methods. 

85 

86 """ 

87 self.engine = engine 

88 self.dialect = engine.dialect 

89 self.__branch_from = _branch_from 

90 self.__branch = _branch_from is not None 

91 

92 if _branch_from: 

93 self.__connection = connection 

94 self._execution_options = _execution_options 

95 self._echo = _branch_from._echo 

96 self.should_close_with_result = False 

97 self.dispatch = _dispatch 

98 self._has_events = _branch_from._has_events 

99 self.schema_for_object = _branch_from.schema_for_object 

100 else: 

101 self.__connection = ( 

102 connection 

103 if connection is not None 

104 else engine.raw_connection() 

105 ) 

106 self.__transaction = None 

107 self.__savepoint_seq = 0 

108 self.should_close_with_result = close_with_result 

109 self.__invalid = False 

110 self.__can_reconnect = True 

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

112 

113 if _has_events is None: 

114 # if _has_events is sent explicitly as False, 

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

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

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

118 self._has_events = _has_events or ( 

119 _has_events is None and engine._has_events 

120 ) 

121 

122 assert not _execution_options 

123 self._execution_options = engine._execution_options 

124 

125 if self._has_events or self.engine._has_events: 

126 self.dispatch.engine_connect(self, self.__branch) 

127 

128 def _branch(self): 

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

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

131 and also whose close() method does nothing. 

132 

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

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

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

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

137 

138 Userland code accesses _branch() when the connect() or 

139 contextual_connect() methods are called. The branched connection 

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

141 connected when a close() event occurs. 

142 

143 """ 

144 if self.__branch_from: 

145 return self.__branch_from._branch() 

146 else: 

147 return self.engine._connection_cls( 

148 self.engine, 

149 self.__connection, 

150 _branch_from=self, 

151 _execution_options=self._execution_options, 

152 _has_events=self._has_events, 

153 _dispatch=self.dispatch, 

154 ) 

155 

156 @property 

157 def _root(self): 

158 """return the 'root' connection. 

159 

160 Returns 'self' if this connection is not a branch, else 

161 returns the root connection from which we ultimately branched. 

162 

163 """ 

164 

165 if self.__branch_from: 

166 return self.__branch_from 

167 else: 

168 return self 

169 

170 def _clone(self): 

171 """Create a shallow copy of this Connection. 

172 

173 """ 

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

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

176 return c 

177 

178 def __enter__(self): 

179 return self 

180 

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

182 self.close() 

183 

184 def execution_options(self, **opt): 

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

186 during execution. 

187 

188 The method returns a copy of this :class:`_engine.Connection` 

189 which references 

190 the same underlying DBAPI connection, but also defines the given 

191 execution options which will take effect for a call to 

192 :meth:`execute`. As the new :class:`_engine.Connection` 

193 references the same 

194 underlying resource, it's usually a good idea to ensure that the copies 

195 will be discarded immediately, which is implicit if used as in:: 

196 

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

198 execute(stmt) 

199 

200 Note that any key/value can be passed to 

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

202 and it will be stored in the 

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

204 It 

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

206 event listeners, for example. 

207 

208 The keywords that are currently recognized by SQLAlchemy itself 

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

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

211 

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

213 When True, a COMMIT will be invoked after execution 

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

215 transaction is not begun on the connection. Note that DBAPI 

216 connections by default are always in a transaction - SQLAlchemy uses 

217 rules applied to different kinds of statements to determine if 

218 COMMIT will be invoked in order to provide its "autocommit" feature. 

219 Typically, all INSERT/UPDATE/DELETE statements as well as 

220 CREATE/DROP statements have autocommit behavior enabled; SELECT 

221 constructs do not. Use this option when invoking a SELECT or other 

222 specific SQL construct where COMMIT is desired (typically when 

223 calling stored procedures and such), and an explicit 

224 transaction is not in progress. 

225 

226 :param compiled_cache: Available on: Connection. 

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

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

229 compiles a clause 

230 expression into a :class:`.Compiled` object. 

231 It is the user's responsibility to 

232 manage the size of this dictionary, which will have keys 

233 corresponding to the dialect, clause element, the column 

234 names within the VALUES or SET clause of an INSERT or UPDATE, 

235 as well as the "batch" mode for an INSERT or UPDATE statement. 

236 The format of this dictionary is not guaranteed to stay the 

237 same in future releases. 

238 

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

240 some operations, including flush operations. The caching 

241 used by the ORM internally supersedes a cache dictionary 

242 specified here. 

243 

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

245 

246 Set the transaction isolation level for the lifespan of this 

247 :class:`_engine.Connection` object. 

248 Valid values include those string 

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

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

251 semi-database specific; see individual dialect documentation for 

252 valid levels. 

253 

254 The isolation level option applies the isolation level by emitting 

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

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

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

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

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

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

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

262 where an event handler will emit 

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

264 isolation level change. 

265 

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

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

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

269 method or similar has been 

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

271 transaction in progress, and different DBAPIs and/or 

272 SQLAlchemy dialects may implicitly roll back or commit 

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

274 

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

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

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

278 disconnection error occurs. The new connection produced after 

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

280 to it automatically. 

281 

282 .. seealso:: 

283 

284 :paramref:`_sa.create_engine.isolation_level` 

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

286 

287 :meth:`_engine.Connection.get_isolation_level` 

288 - view current level 

289 

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

291 

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

293 

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

295 

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

297 

298 :ref:`session_transaction_isolation` - for the ORM 

299 

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

301 list or dictionary is totally empty, will invoke the 

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

303 not passing the parameter collection at all. 

304 Some DBAPIs such as psycopg2 and mysql-python consider 

305 percent signs as significant only when parameters are 

306 present; this option allows code to generate SQL 

307 containing percent signs (and possibly other characters) 

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

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

310 command line tools. 

311 

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

313 Indicate to the dialect that results should be 

314 "streamed" and not pre-buffered, if possible. This is a limitation 

315 of many DBAPIs. The flag is currently understood only by the 

316 psycopg2, mysqldb and pymysql dialects. 

317 

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

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

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

321 :class:`_schema.Table` 

322 encountered when SQL or DDL expression elements 

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

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

325 

326 .. versionadded:: 1.1 

327 

328 .. seealso:: 

329 

330 :ref:`schema_translating` 

331 

332 .. seealso:: 

333 

334 :meth:`_engine.Engine.execution_options` 

335 

336 :meth:`.Executable.execution_options` 

337 

338 :meth:`_engine.Connection.get_execution_options` 

339 

340 

341 """ # noqa 

342 c = self._clone() 

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

344 if self._has_events or self.engine._has_events: 

345 self.dispatch.set_connection_execution_options(c, opt) 

346 self.dialect.set_connection_execution_options(c, opt) 

347 return c 

348 

349 def get_execution_options(self): 

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

351 

352 .. versionadded:: 1.3 

353 

354 .. seealso:: 

355 

356 :meth:`_engine.Connection.execution_options` 

357 """ 

358 return self._execution_options 

359 

360 @property 

361 def closed(self): 

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

363 

364 return ( 

365 "_Connection__connection" not in self.__dict__ 

366 and not self.__can_reconnect 

367 ) 

368 

369 @property 

370 def invalidated(self): 

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

372 

373 return self._root.__invalid 

374 

375 @property 

376 def connection(self): 

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

378 

379 .. seealso:: 

380 

381 

382 :ref:`dbapi_connections` 

383 

384 """ 

385 

386 try: 

387 return self.__connection 

388 except AttributeError: 

389 # escape "except AttributeError" before revalidating 

390 # to prevent misleading stacktraces in Py3K 

391 pass 

392 try: 

393 return self._revalidate_connection() 

394 except BaseException as e: 

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

396 

397 def get_isolation_level(self): 

398 """Return the current isolation level assigned to this 

399 :class:`_engine.Connection`. 

400 

401 This will typically be the default isolation level as determined 

402 by the dialect, unless if the 

403 :paramref:`.Connection.execution_options.isolation_level` 

404 feature has been used to alter the isolation level on a 

405 per-:class:`_engine.Connection` basis. 

406 

407 This attribute will typically perform a live SQL operation in order 

408 to procure the current isolation level, so the value returned is the 

409 actual level on the underlying DBAPI connection regardless of how 

410 this state was set. Compare to the 

411 :attr:`_engine.Connection.default_isolation_level` accessor 

412 which returns the dialect-level setting without performing a SQL 

413 query. 

414 

415 .. versionadded:: 0.9.9 

416 

417 .. seealso:: 

418 

419 :attr:`_engine.Connection.default_isolation_level` 

420 - view default level 

421 

422 :paramref:`_sa.create_engine.isolation_level` 

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

424 

425 :paramref:`.Connection.execution_options.isolation_level` 

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

427 

428 """ 

429 try: 

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

431 except BaseException as e: 

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

433 

434 @property 

435 def default_isolation_level(self): 

436 """The default isolation level assigned to this 

437 :class:`_engine.Connection`. 

438 

439 This is the isolation level setting that the 

440 :class:`_engine.Connection` 

441 has when first procured via the :meth:`_engine.Engine.connect` method. 

442 This level stays in place until the 

443 :paramref:`.Connection.execution_options.isolation_level` is used 

444 to change the setting on a per-:class:`_engine.Connection` basis. 

445 

446 Unlike :meth:`_engine.Connection.get_isolation_level`, 

447 this attribute is set 

448 ahead of time from the first connection procured by the dialect, 

449 so SQL query is not invoked when this accessor is called. 

450 

451 .. versionadded:: 0.9.9 

452 

453 .. seealso:: 

454 

455 :meth:`_engine.Connection.get_isolation_level` 

456 - view current level 

457 

458 :paramref:`_sa.create_engine.isolation_level` 

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

460 

461 :paramref:`.Connection.execution_options.isolation_level` 

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

463 

464 """ 

465 return self.dialect.default_isolation_level 

466 

467 def _revalidate_connection(self): 

468 if self.__branch_from: 

469 return self.__branch_from._revalidate_connection() 

470 if self.__can_reconnect and self.__invalid: 

471 if self.__transaction is not None: 

472 raise exc.InvalidRequestError( 

473 "Can't reconnect until invalid " 

474 "transaction is rolled back" 

475 ) 

476 self.__connection = self.engine.raw_connection(_connection=self) 

477 self.__invalid = False 

478 return self.__connection 

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

480 

481 @property 

482 def _connection_is_valid(self): 

483 # use getattr() for is_valid to support exceptions raised in 

484 # dialect initializer, where the connection is not wrapped in 

485 # _ConnectionFairy 

486 

487 return getattr(self.__connection, "is_valid", False) 

488 

489 @property 

490 def _still_open_and_connection_is_valid(self): 

491 return ( 

492 not self.closed 

493 and not self.invalidated 

494 and getattr(self.__connection, "is_valid", False) 

495 ) 

496 

497 @property 

498 def info(self): 

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

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

501 data to be associated with the connection. 

502 

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

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

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

506 

507 """ 

508 

509 return self.connection.info 

510 

511 def connect(self): 

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

513 

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

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

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

517 

518 This method provides usage symmetry with 

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

520 with context managers. 

521 

522 """ 

523 

524 return self._branch() 

525 

526 def _contextual_connect(self, **kwargs): 

527 return self._branch() 

528 

529 def invalidate(self, exception=None): 

530 """Invalidate the underlying DBAPI connection associated with 

531 this :class:`_engine.Connection`. 

532 

533 The underlying DBAPI connection is literally closed (if 

534 possible), and is discarded. Its source connection pool will 

535 typically lazily create a new connection to replace it. 

536 

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

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

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

540 procure a new DBAPI connection using the services of the 

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

542 a "reconnection"). 

543 

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

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

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

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

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

549 will not allow a reconnection to proceed until the 

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

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

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

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

554 This is to prevent applications from accidentally 

555 continuing an ongoing transactional operations despite the 

556 fact that the transaction has been lost due to an 

557 invalidation. 

558 

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

560 just like auto-invalidation, 

561 will at the connection pool level invoke the 

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

563 

564 .. seealso:: 

565 

566 :ref:`pool_connection_invalidation` 

567 

568 """ 

569 

570 if self.invalidated: 

571 return 

572 

573 if self.closed: 

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

575 

576 if self._root._connection_is_valid: 

577 self._root.__connection.invalidate(exception) 

578 del self._root.__connection 

579 self._root.__invalid = True 

580 

581 def detach(self): 

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

583 

584 E.g.:: 

585 

586 with engine.connect() as conn: 

587 conn.detach() 

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

589 

590 # work with connection 

591 

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

593 # also call .close()) 

594 

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

596 When closed 

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

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

599 returned to its originating pool. 

600 

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

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

603 isolation level or similar). 

604 

605 """ 

606 

607 self.__connection.detach() 

608 

609 def begin(self): 

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

611 

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

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

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

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

616 

617 Nested calls to :meth:`.begin` on the same :class:`_engine.Connection` 

618 will return new :class:`.Transaction` objects that represent 

619 an emulated transaction within the scope of the enclosing 

620 transaction, that is:: 

621 

622 trans = conn.begin() # outermost transaction 

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

624 trans2.commit() # does nothing 

625 trans.commit() # actually commits 

626 

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

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

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

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

631 transaction. 

632 

633 .. seealso:: 

634 

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

636 

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

638 use a two phase /XID transaction 

639 

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

641 :class:`_engine.Engine` 

642 

643 """ 

644 if self.__branch_from: 

645 return self.__branch_from.begin() 

646 

647 if self.__transaction is None: 

648 self.__transaction = RootTransaction(self) 

649 return self.__transaction 

650 else: 

651 return Transaction(self, self.__transaction) 

652 

653 def begin_nested(self): 

654 """Begin a nested transaction and return a transaction handle. 

655 

656 The returned object is an instance of :class:`.NestedTransaction`. 

657 

658 Nested transactions require SAVEPOINT support in the 

659 underlying database. Any transaction in the hierarchy may 

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

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

662 transaction of a whole. 

663 

664 .. seealso:: 

665 

666 :meth:`_engine.Connection.begin` 

667 

668 :meth:`_engine.Connection.begin_twophase` 

669 

670 """ 

671 if self.__branch_from: 

672 return self.__branch_from.begin_nested() 

673 

674 if self.__transaction is None: 

675 self.__transaction = RootTransaction(self) 

676 else: 

677 self.__transaction = NestedTransaction(self, self.__transaction) 

678 return self.__transaction 

679 

680 def begin_twophase(self, xid=None): 

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

682 handle. 

683 

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

685 which in addition to the methods provided by 

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

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

688 

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

690 random id will be generated. 

691 

692 .. seealso:: 

693 

694 :meth:`_engine.Connection.begin` 

695 

696 :meth:`_engine.Connection.begin_twophase` 

697 

698 """ 

699 

700 if self.__branch_from: 

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

702 

703 if self.__transaction is not None: 

704 raise exc.InvalidRequestError( 

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

706 "is already in progress." 

707 ) 

708 if xid is None: 

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

710 self.__transaction = TwoPhaseTransaction(self, xid) 

711 return self.__transaction 

712 

713 def recover_twophase(self): 

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

715 

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

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

718 

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

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

721 

722 def in_transaction(self): 

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

724 return self._root.__transaction is not None 

725 

726 def _begin_impl(self, transaction): 

727 assert not self.__branch_from 

728 

729 if self._echo: 

730 self.engine.logger.info("BEGIN (implicit)") 

731 

732 if self._has_events or self.engine._has_events: 

733 self.dispatch.begin(self) 

734 

735 try: 

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

737 if self.connection._reset_agent is None: 

738 self.connection._reset_agent = transaction 

739 except BaseException as e: 

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

741 

742 def _rollback_impl(self): 

743 assert not self.__branch_from 

744 

745 if self._has_events or self.engine._has_events: 

746 self.dispatch.rollback(self) 

747 

748 if self._still_open_and_connection_is_valid: 

749 if self._echo: 

750 self.engine.logger.info("ROLLBACK") 

751 try: 

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

753 except BaseException as e: 

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

755 finally: 

756 if ( 

757 not self.__invalid 

758 and self.connection._reset_agent is self.__transaction 

759 ): 

760 self.connection._reset_agent = None 

761 self.__transaction = None 

762 else: 

763 self.__transaction = None 

764 

765 def _commit_impl(self, autocommit=False): 

766 assert not self.__branch_from 

767 

768 if self._has_events or self.engine._has_events: 

769 self.dispatch.commit(self) 

770 

771 if self._echo: 

772 self.engine.logger.info("COMMIT") 

773 try: 

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

775 except BaseException as e: 

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

777 finally: 

778 if ( 

779 not self.__invalid 

780 and self.connection._reset_agent is self.__transaction 

781 ): 

782 self.connection._reset_agent = None 

783 self.__transaction = None 

784 

785 def _savepoint_impl(self, name=None): 

786 assert not self.__branch_from 

787 

788 if self._has_events or self.engine._has_events: 

789 self.dispatch.savepoint(self, name) 

790 

791 if name is None: 

792 self.__savepoint_seq += 1 

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

794 if self._still_open_and_connection_is_valid: 

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

796 return name 

797 

798 def _discard_transaction(self, trans): 

799 if trans is self.__transaction: 

800 if trans._parent is trans: 

801 self.__transaction = None 

802 else: 

803 self.__transaction = trans._parent 

804 

805 if self._still_open_and_connection_is_valid: 

806 if self.__connection._reset_agent is trans: 

807 self.__connection._reset_agent = None 

808 

809 def _rollback_to_savepoint_impl(self, name, context): 

810 assert not self.__branch_from 

811 

812 if self._has_events or self.engine._has_events: 

813 self.dispatch.rollback_savepoint(self, name, context) 

814 

815 if self._still_open_and_connection_is_valid: 

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

817 self.__transaction = context 

818 

819 def _release_savepoint_impl(self, name, context): 

820 assert not self.__branch_from 

821 

822 if self._has_events or self.engine._has_events: 

823 self.dispatch.release_savepoint(self, name, context) 

824 

825 if self._still_open_and_connection_is_valid: 

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

827 self.__transaction = context 

828 

829 def _begin_twophase_impl(self, transaction): 

830 assert not self.__branch_from 

831 

832 if self._echo: 

833 self.engine.logger.info("BEGIN TWOPHASE (implicit)") 

834 if self._has_events or self.engine._has_events: 

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

836 

837 if self._still_open_and_connection_is_valid: 

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

839 

840 if self.connection._reset_agent is None: 

841 self.connection._reset_agent = transaction 

842 

843 def _prepare_twophase_impl(self, xid): 

844 assert not self.__branch_from 

845 

846 if self._has_events or self.engine._has_events: 

847 self.dispatch.prepare_twophase(self, xid) 

848 

849 if self._still_open_and_connection_is_valid: 

850 assert isinstance(self.__transaction, TwoPhaseTransaction) 

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

852 

853 def _rollback_twophase_impl(self, xid, is_prepared): 

854 assert not self.__branch_from 

855 

856 if self._has_events or self.engine._has_events: 

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

858 

859 if self._still_open_and_connection_is_valid: 

860 assert isinstance(self.__transaction, TwoPhaseTransaction) 

861 try: 

862 self.engine.dialect.do_rollback_twophase( 

863 self, xid, is_prepared 

864 ) 

865 finally: 

866 if self.connection._reset_agent is self.__transaction: 

867 self.connection._reset_agent = None 

868 self.__transaction = None 

869 else: 

870 self.__transaction = None 

871 

872 def _commit_twophase_impl(self, xid, is_prepared): 

873 assert not self.__branch_from 

874 

875 if self._has_events or self.engine._has_events: 

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

877 

878 if self._still_open_and_connection_is_valid: 

879 assert isinstance(self.__transaction, TwoPhaseTransaction) 

880 try: 

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

882 finally: 

883 if self.connection._reset_agent is self.__transaction: 

884 self.connection._reset_agent = None 

885 self.__transaction = None 

886 else: 

887 self.__transaction = None 

888 

889 def _autorollback(self): 

890 if not self._root.in_transaction(): 

891 self._root._rollback_impl() 

892 

893 def close(self): 

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

895 

896 This results in a release of the underlying database 

897 resources, that is, the DBAPI connection referenced 

898 internally. The DBAPI connection is typically restored 

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

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

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

902 the DBAPI connection is also unconditionally released via 

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

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

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

906 

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

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

909 and will allow no further operations. 

910 

911 """ 

912 if self.__branch_from: 

913 try: 

914 del self.__connection 

915 except AttributeError: 

916 pass 

917 finally: 

918 self.__can_reconnect = False 

919 return 

920 try: 

921 conn = self.__connection 

922 except AttributeError: 

923 pass 

924 else: 

925 

926 conn.close() 

927 if conn._reset_agent is self.__transaction: 

928 conn._reset_agent = None 

929 

930 # the close() process can end up invalidating us, 

931 # as the pool will call our transaction as the "reset_agent" 

932 # for rollback(), which can then cause an invalidation 

933 if not self.__invalid: 

934 del self.__connection 

935 self.__can_reconnect = False 

936 self.__transaction = None 

937 

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

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

940 

941 The underlying result/cursor is closed after execution. 

942 """ 

943 

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

945 

946 def execute(self, object_, *multiparams, **params): 

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

948 :class:`_engine.ResultProxy`. 

949 

950 :param object: The statement to be executed. May be 

951 one of: 

952 

953 * a plain string 

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

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

956 :func:`_expression.select` construct 

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

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

959 a SELECT statement, which is then executed. 

960 * a :class:`.DDLElement` object 

961 * a :class:`.DefaultGenerator` object 

962 * a :class:`.Compiled` object 

963 

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

965 values to be used in the execution. Typically, 

966 the format is either a collection of one or more 

967 dictionaries passed to \*multiparams:: 

968 

969 conn.execute( 

970 table.insert(), 

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

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

973 ) 

974 

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

976 

977 conn.execute( 

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

979 ) 

980 

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

982 DBAPI accepts positional bind parameters, a collection of tuples 

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

984 

985 conn.execute( 

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

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

988 ) 

989 

990 conn.execute( 

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

992 1, "v1" 

993 ) 

994 

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

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

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

998 "numeric". See `pep-249 <http://www.python.org/dev/peps/pep-0249/>`_ 

999 for details on paramstyle. 

1000 

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

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

1003 

1004 """ 

1005 if isinstance(object_, util.string_types[0]): 

1006 return self._execute_text(object_, multiparams, params) 

1007 try: 

1008 meth = object_._execute_on_connection 

1009 except AttributeError as err: 

1010 util.raise_( 

1011 exc.ObjectNotExecutableError(object_), replace_context=err 

1012 ) 

1013 else: 

1014 return meth(self, multiparams, params) 

1015 

1016 def _execute_function(self, func, multiparams, params): 

1017 """Execute a sql.FunctionElement object.""" 

1018 

1019 return self._execute_clauseelement(func.select(), multiparams, params) 

1020 

1021 def _execute_default(self, default, multiparams, params): 

1022 """Execute a schema.ColumnDefault object.""" 

1023 

1024 if self._has_events or self.engine._has_events: 

1025 for fn in self.dispatch.before_execute: 

1026 default, multiparams, params = fn( 

1027 self, default, multiparams, params 

1028 ) 

1029 

1030 try: 

1031 try: 

1032 conn = self.__connection 

1033 except AttributeError: 

1034 # escape "except AttributeError" before revalidating 

1035 # to prevent misleading stacktraces in Py3K 

1036 conn = None 

1037 if conn is None: 

1038 conn = self._revalidate_connection() 

1039 

1040 dialect = self.dialect 

1041 ctx = dialect.execution_ctx_cls._init_default(dialect, self, conn) 

1042 except BaseException as e: 

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

1044 

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

1046 if self.should_close_with_result: 

1047 self.close() 

1048 

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

1050 self.dispatch.after_execute( 

1051 self, default, multiparams, params, ret 

1052 ) 

1053 

1054 return ret 

1055 

1056 def _execute_ddl(self, ddl, multiparams, params): 

1057 """Execute a schema.DDL object.""" 

1058 

1059 if self._has_events or self.engine._has_events: 

1060 for fn in self.dispatch.before_execute: 

1061 ddl, multiparams, params = fn(self, ddl, multiparams, params) 

1062 

1063 dialect = self.dialect 

1064 

1065 compiled = ddl.compile( 

1066 dialect=dialect, 

1067 schema_translate_map=self.schema_for_object 

1068 if not self.schema_for_object.is_default 

1069 else None, 

1070 ) 

1071 ret = self._execute_context( 

1072 dialect, 

1073 dialect.execution_ctx_cls._init_ddl, 

1074 compiled, 

1075 None, 

1076 compiled, 

1077 ) 

1078 if self._has_events or self.engine._has_events: 

1079 self.dispatch.after_execute(self, ddl, multiparams, params, ret) 

1080 return ret 

1081 

1082 def _execute_clauseelement(self, elem, multiparams, params): 

1083 """Execute a sql.ClauseElement object.""" 

1084 

1085 if self._has_events or self.engine._has_events: 

1086 for fn in self.dispatch.before_execute: 

1087 elem, multiparams, params = fn(self, elem, multiparams, params) 

1088 

1089 distilled_params = _distill_params(multiparams, params) 

1090 if distilled_params: 

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

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

1093 keys = list(distilled_params[0].keys()) 

1094 else: 

1095 keys = [] 

1096 

1097 dialect = self.dialect 

1098 if "compiled_cache" in self._execution_options: 

1099 key = ( 

1100 dialect, 

1101 elem, 

1102 tuple(sorted(keys)), 

1103 self.schema_for_object.hash_key, 

1104 len(distilled_params) > 1, 

1105 ) 

1106 compiled_sql = self._execution_options["compiled_cache"].get(key) 

1107 if compiled_sql is None: 

1108 compiled_sql = elem.compile( 

1109 dialect=dialect, 

1110 column_keys=keys, 

1111 inline=len(distilled_params) > 1, 

1112 schema_translate_map=self.schema_for_object 

1113 if not self.schema_for_object.is_default 

1114 else None, 

1115 ) 

1116 self._execution_options["compiled_cache"][key] = compiled_sql 

1117 else: 

1118 compiled_sql = elem.compile( 

1119 dialect=dialect, 

1120 column_keys=keys, 

1121 inline=len(distilled_params) > 1, 

1122 schema_translate_map=self.schema_for_object 

1123 if not self.schema_for_object.is_default 

1124 else None, 

1125 ) 

1126 

1127 ret = self._execute_context( 

1128 dialect, 

1129 dialect.execution_ctx_cls._init_compiled, 

1130 compiled_sql, 

1131 distilled_params, 

1132 compiled_sql, 

1133 distilled_params, 

1134 ) 

1135 if self._has_events or self.engine._has_events: 

1136 self.dispatch.after_execute(self, elem, multiparams, params, ret) 

1137 return ret 

1138 

1139 def _execute_compiled(self, compiled, multiparams, params): 

1140 """Execute a sql.Compiled object.""" 

1141 

1142 if self._has_events or self.engine._has_events: 

1143 for fn in self.dispatch.before_execute: 

1144 compiled, multiparams, params = fn( 

1145 self, compiled, multiparams, params 

1146 ) 

1147 

1148 dialect = self.dialect 

1149 parameters = _distill_params(multiparams, params) 

1150 ret = self._execute_context( 

1151 dialect, 

1152 dialect.execution_ctx_cls._init_compiled, 

1153 compiled, 

1154 parameters, 

1155 compiled, 

1156 parameters, 

1157 ) 

1158 if self._has_events or self.engine._has_events: 

1159 self.dispatch.after_execute( 

1160 self, compiled, multiparams, params, ret 

1161 ) 

1162 return ret 

1163 

1164 def _execute_text(self, statement, multiparams, params): 

1165 """Execute a string SQL statement.""" 

1166 

1167 if self._has_events or self.engine._has_events: 

1168 for fn in self.dispatch.before_execute: 

1169 statement, multiparams, params = fn( 

1170 self, statement, multiparams, params 

1171 ) 

1172 

1173 dialect = self.dialect 

1174 parameters = _distill_params(multiparams, params) 

1175 ret = self._execute_context( 

1176 dialect, 

1177 dialect.execution_ctx_cls._init_statement, 

1178 statement, 

1179 parameters, 

1180 statement, 

1181 parameters, 

1182 ) 

1183 if self._has_events or self.engine._has_events: 

1184 self.dispatch.after_execute( 

1185 self, statement, multiparams, params, ret 

1186 ) 

1187 return ret 

1188 

1189 def _execute_context( 

1190 self, dialect, constructor, statement, parameters, *args 

1191 ): 

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

1193 a :class:`_engine.ResultProxy`.""" 

1194 

1195 try: 

1196 try: 

1197 conn = self.__connection 

1198 except AttributeError: 

1199 # escape "except AttributeError" before revalidating 

1200 # to prevent misleading stacktraces in Py3K 

1201 conn = None 

1202 if conn is None: 

1203 conn = self._revalidate_connection() 

1204 

1205 context = constructor(dialect, self, conn, *args) 

1206 except BaseException as e: 

1207 self._handle_dbapi_exception( 

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

1209 ) 

1210 

1211 if context.compiled: 

1212 context.pre_exec() 

1213 

1214 cursor, statement, parameters = ( 

1215 context.cursor, 

1216 context.statement, 

1217 context.parameters, 

1218 ) 

1219 

1220 if not context.executemany: 

1221 parameters = parameters[0] 

1222 

1223 if self._has_events or self.engine._has_events: 

1224 for fn in self.dispatch.before_cursor_execute: 

1225 statement, parameters = fn( 

1226 self, 

1227 cursor, 

1228 statement, 

1229 parameters, 

1230 context, 

1231 context.executemany, 

1232 ) 

1233 

1234 if self._echo: 

1235 self.engine.logger.info(statement) 

1236 if not self.engine.hide_parameters: 

1237 self.engine.logger.info( 

1238 "%r", 

1239 sql_util._repr_params( 

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

1241 ), 

1242 ) 

1243 else: 

1244 self.engine.logger.info( 

1245 "[SQL parameters hidden due to hide_parameters=True]" 

1246 ) 

1247 

1248 evt_handled = False 

1249 try: 

1250 if context.executemany: 

1251 if self.dialect._has_events: 

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

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

1254 evt_handled = True 

1255 break 

1256 if not evt_handled: 

1257 self.dialect.do_executemany( 

1258 cursor, statement, parameters, context 

1259 ) 

1260 elif not parameters and context.no_parameters: 

1261 if self.dialect._has_events: 

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

1263 if fn(cursor, statement, context): 

1264 evt_handled = True 

1265 break 

1266 if not evt_handled: 

1267 self.dialect.do_execute_no_params( 

1268 cursor, statement, context 

1269 ) 

1270 else: 

1271 if self.dialect._has_events: 

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

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

1274 evt_handled = True 

1275 break 

1276 if not evt_handled: 

1277 self.dialect.do_execute( 

1278 cursor, statement, parameters, context 

1279 ) 

1280 

1281 if self._has_events or self.engine._has_events: 

1282 self.dispatch.after_cursor_execute( 

1283 self, 

1284 cursor, 

1285 statement, 

1286 parameters, 

1287 context, 

1288 context.executemany, 

1289 ) 

1290 

1291 if context.compiled: 

1292 context.post_exec() 

1293 

1294 if context.is_crud or context.is_text: 

1295 result = context._setup_crud_result_proxy() 

1296 else: 

1297 result = context.get_result_proxy() 

1298 if result._metadata is None: 

1299 result._soft_close() 

1300 

1301 if context.should_autocommit and self._root.__transaction is None: 

1302 self._root._commit_impl(autocommit=True) 

1303 

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

1305 # Connection after the statement is complete. 

1306 if self.should_close_with_result: 

1307 # ResultProxy already exhausted rows / has no rows. 

1308 # close us now 

1309 if result._soft_closed: 

1310 self.close() 

1311 else: 

1312 # ResultProxy will close this Connection when no more 

1313 # rows to fetch. 

1314 result._autoclose_connection = True 

1315 

1316 except BaseException as e: 

1317 self._handle_dbapi_exception( 

1318 e, statement, parameters, cursor, context 

1319 ) 

1320 

1321 return result 

1322 

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

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

1325 

1326 Adds appropriate logging and exception handling. 

1327 

1328 This method is used by DefaultDialect for special-case 

1329 executions, such as for sequences and column defaults. 

1330 The path of statement execution in the majority of cases 

1331 terminates at _execute_context(). 

1332 

1333 """ 

1334 if self._has_events or self.engine._has_events: 

1335 for fn in self.dispatch.before_cursor_execute: 

1336 statement, parameters = fn( 

1337 self, cursor, statement, parameters, context, False 

1338 ) 

1339 

1340 if self._echo: 

1341 self.engine.logger.info(statement) 

1342 self.engine.logger.info("%r", parameters) 

1343 try: 

1344 for fn in ( 

1345 () 

1346 if not self.dialect._has_events 

1347 else self.dialect.dispatch.do_execute 

1348 ): 

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

1350 break 

1351 else: 

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

1353 except BaseException as e: 

1354 self._handle_dbapi_exception( 

1355 e, statement, parameters, cursor, context 

1356 ) 

1357 

1358 if self._has_events or self.engine._has_events: 

1359 self.dispatch.after_cursor_execute( 

1360 self, cursor, statement, parameters, context, False 

1361 ) 

1362 

1363 def _safe_close_cursor(self, cursor): 

1364 """Close the given cursor, catching exceptions 

1365 and turning into log warnings. 

1366 

1367 """ 

1368 try: 

1369 cursor.close() 

1370 except Exception: 

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

1372 self.engine.pool.logger.error( 

1373 "Error closing cursor", exc_info=True 

1374 ) 

1375 

1376 _reentrant_error = False 

1377 _is_disconnect = False 

1378 

1379 def _handle_dbapi_exception( 

1380 self, e, statement, parameters, cursor, context 

1381 ): 

1382 exc_info = sys.exc_info() 

1383 

1384 if context and context.exception is None: 

1385 context.exception = e 

1386 

1387 is_exit_exception = not isinstance(e, Exception) 

1388 

1389 if not self._is_disconnect: 

1390 self._is_disconnect = ( 

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

1392 and not self.closed 

1393 and self.dialect.is_disconnect( 

1394 e, 

1395 self.__connection if not self.invalidated else None, 

1396 cursor, 

1397 ) 

1398 ) or (is_exit_exception and not self.closed) 

1399 

1400 if context: 

1401 context.is_disconnect = self._is_disconnect 

1402 

1403 invalidate_pool_on_disconnect = not is_exit_exception 

1404 

1405 if self._reentrant_error: 

1406 util.raise_( 

1407 exc.DBAPIError.instance( 

1408 statement, 

1409 parameters, 

1410 e, 

1411 self.dialect.dbapi.Error, 

1412 hide_parameters=self.engine.hide_parameters, 

1413 dialect=self.dialect, 

1414 ismulti=context.executemany 

1415 if context is not None 

1416 else None, 

1417 ), 

1418 with_traceback=exc_info[2], 

1419 from_=e, 

1420 ) 

1421 self._reentrant_error = True 

1422 try: 

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

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

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

1426 statement is not None 

1427 and context is None 

1428 and not is_exit_exception 

1429 ) 

1430 

1431 if should_wrap: 

1432 sqlalchemy_exception = exc.DBAPIError.instance( 

1433 statement, 

1434 parameters, 

1435 e, 

1436 self.dialect.dbapi.Error, 

1437 hide_parameters=self.engine.hide_parameters, 

1438 connection_invalidated=self._is_disconnect, 

1439 dialect=self.dialect, 

1440 ismulti=context.executemany 

1441 if context is not None 

1442 else None, 

1443 ) 

1444 else: 

1445 sqlalchemy_exception = None 

1446 

1447 newraise = None 

1448 

1449 if ( 

1450 self._has_events or self.engine._has_events 

1451 ) and not self._execution_options.get( 

1452 "skip_user_error_events", False 

1453 ): 

1454 # legacy dbapi_error event 

1455 if should_wrap and context: 

1456 self.dispatch.dbapi_error( 

1457 self, cursor, statement, parameters, context, e 

1458 ) 

1459 

1460 # new handle_error event 

1461 ctx = ExceptionContextImpl( 

1462 e, 

1463 sqlalchemy_exception, 

1464 self.engine, 

1465 self, 

1466 cursor, 

1467 statement, 

1468 parameters, 

1469 context, 

1470 self._is_disconnect, 

1471 invalidate_pool_on_disconnect, 

1472 ) 

1473 

1474 for fn in self.dispatch.handle_error: 

1475 try: 

1476 # handler returns an exception; 

1477 # call next handler in a chain 

1478 per_fn = fn(ctx) 

1479 if per_fn is not None: 

1480 ctx.chained_exception = newraise = per_fn 

1481 except Exception as _raised: 

1482 # handler raises an exception - stop processing 

1483 newraise = _raised 

1484 break 

1485 

1486 if self._is_disconnect != ctx.is_disconnect: 

1487 self._is_disconnect = ctx.is_disconnect 

1488 if sqlalchemy_exception: 

1489 sqlalchemy_exception.connection_invalidated = ( 

1490 ctx.is_disconnect 

1491 ) 

1492 

1493 # set up potentially user-defined value for 

1494 # invalidate pool. 

1495 invalidate_pool_on_disconnect = ( 

1496 ctx.invalidate_pool_on_disconnect 

1497 ) 

1498 

1499 if should_wrap and context: 

1500 context.handle_dbapi_exception(e) 

1501 

1502 if not self._is_disconnect: 

1503 if cursor: 

1504 self._safe_close_cursor(cursor) 

1505 with util.safe_reraise(warn_only=True): 

1506 self._autorollback() 

1507 

1508 if newraise: 

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

1510 elif should_wrap: 

1511 util.raise_( 

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

1513 ) 

1514 else: 

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

1516 

1517 finally: 

1518 del self._reentrant_error 

1519 if self._is_disconnect: 

1520 del self._is_disconnect 

1521 if not self.invalidated: 

1522 dbapi_conn_wrapper = self.__connection 

1523 if invalidate_pool_on_disconnect: 

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

1525 self.invalidate(e) 

1526 if self.should_close_with_result: 

1527 self.close() 

1528 

1529 @classmethod 

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

1531 exc_info = sys.exc_info() 

1532 

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

1534 

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

1536 

1537 if should_wrap: 

1538 sqlalchemy_exception = exc.DBAPIError.instance( 

1539 None, 

1540 None, 

1541 e, 

1542 dialect.dbapi.Error, 

1543 hide_parameters=engine.hide_parameters, 

1544 connection_invalidated=is_disconnect, 

1545 ) 

1546 else: 

1547 sqlalchemy_exception = None 

1548 

1549 newraise = None 

1550 

1551 if engine._has_events: 

1552 ctx = ExceptionContextImpl( 

1553 e, 

1554 sqlalchemy_exception, 

1555 engine, 

1556 None, 

1557 None, 

1558 None, 

1559 None, 

1560 None, 

1561 is_disconnect, 

1562 True, 

1563 ) 

1564 for fn in engine.dispatch.handle_error: 

1565 try: 

1566 # handler returns an exception; 

1567 # call next handler in a chain 

1568 per_fn = fn(ctx) 

1569 if per_fn is not None: 

1570 ctx.chained_exception = newraise = per_fn 

1571 except Exception as _raised: 

1572 # handler raises an exception - stop processing 

1573 newraise = _raised 

1574 break 

1575 

1576 if sqlalchemy_exception and is_disconnect != ctx.is_disconnect: 

1577 sqlalchemy_exception.connection_invalidated = ( 

1578 is_disconnect 

1579 ) = ctx.is_disconnect 

1580 

1581 if newraise: 

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

1583 elif should_wrap: 

1584 util.raise_( 

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

1586 ) 

1587 else: 

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

1589 

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

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

1592 

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

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

1595 e.g.:: 

1596 

1597 def do_something(conn, x, y): 

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

1599 

1600 conn.transaction(do_something, 5, 10) 

1601 

1602 The operations inside the function are all invoked within the 

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

1604 Upon success, the transaction is committed. If an 

1605 exception is raised, the transaction is rolled back 

1606 before propagating the exception. 

1607 

1608 .. note:: 

1609 

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

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

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

1613 

1614 with conn.begin(): 

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

1616 

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

1618 

1619 with engine.begin() as conn: 

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

1621 

1622 .. seealso:: 

1623 

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

1625 context 

1626 

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

1628 :meth:`_engine.Connection.transaction` 

1629 

1630 """ 

1631 

1632 trans = self.begin() 

1633 try: 

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

1635 trans.commit() 

1636 return ret 

1637 except: 

1638 with util.safe_reraise(): 

1639 trans.rollback() 

1640 

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

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

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

1644 

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

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

1647 

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

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

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

1651 which one is being dealt with. 

1652 

1653 """ 

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

1655 

1656 def _run_visitor(self, visitorcallable, element, **kwargs): 

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

1658 

1659 

1660class ExceptionContextImpl(ExceptionContext): 

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

1662 

1663 def __init__( 

1664 self, 

1665 exception, 

1666 sqlalchemy_exception, 

1667 engine, 

1668 connection, 

1669 cursor, 

1670 statement, 

1671 parameters, 

1672 context, 

1673 is_disconnect, 

1674 invalidate_pool_on_disconnect, 

1675 ): 

1676 self.engine = engine 

1677 self.connection = connection 

1678 self.sqlalchemy_exception = sqlalchemy_exception 

1679 self.original_exception = exception 

1680 self.execution_context = context 

1681 self.statement = statement 

1682 self.parameters = parameters 

1683 self.is_disconnect = is_disconnect 

1684 self.invalidate_pool_on_disconnect = invalidate_pool_on_disconnect 

1685 

1686 

1687class Transaction(object): 

1688 """Represent a database transaction in progress. 

1689 

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

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

1692 :class:`_engine.Connection`:: 

1693 

1694 from sqlalchemy import create_engine 

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

1696 connection = engine.connect() 

1697 trans = connection.begin() 

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

1699 trans.commit() 

1700 

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

1702 methods in order to control transaction boundaries. It 

1703 also implements a context manager interface so that 

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

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

1706 

1707 with connection.begin(): 

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

1709 

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

1711 

1712 .. seealso:: 

1713 

1714 :meth:`_engine.Connection.begin` 

1715 

1716 :meth:`_engine.Connection.begin_twophase` 

1717 

1718 :meth:`_engine.Connection.begin_nested` 

1719 

1720 .. index:: 

1721 single: thread safety; Transaction 

1722 """ 

1723 

1724 def __init__(self, connection, parent): 

1725 self.connection = connection 

1726 self._actual_parent = parent 

1727 self.is_active = True 

1728 

1729 @property 

1730 def _parent(self): 

1731 return self._actual_parent or self 

1732 

1733 def close(self): 

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

1735 

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

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

1738 method returns. 

1739 

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

1741 an enclosing transaction. 

1742 

1743 """ 

1744 

1745 if self._parent.is_active and self._parent is self: 

1746 self.rollback() 

1747 self.connection._discard_transaction(self) 

1748 

1749 def rollback(self): 

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

1751 

1752 """ 

1753 if self._parent.is_active: 

1754 self._do_rollback() 

1755 self.is_active = False 

1756 

1757 def _do_rollback(self): 

1758 self._parent.rollback() 

1759 

1760 def commit(self): 

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

1762 

1763 if not self._parent.is_active: 

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

1765 self._do_commit() 

1766 self.is_active = False 

1767 

1768 def _do_commit(self): 

1769 pass 

1770 

1771 def __enter__(self): 

1772 return self 

1773 

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

1775 if type_ is None and self.is_active: 

1776 try: 

1777 self.commit() 

1778 except: 

1779 with util.safe_reraise(): 

1780 self.rollback() 

1781 else: 

1782 self.rollback() 

1783 

1784 

1785class RootTransaction(Transaction): 

1786 def __init__(self, connection): 

1787 super(RootTransaction, self).__init__(connection, None) 

1788 self.connection._begin_impl(self) 

1789 

1790 def _do_rollback(self): 

1791 if self.is_active: 

1792 self.connection._rollback_impl() 

1793 

1794 def _do_commit(self): 

1795 if self.is_active: 

1796 self.connection._commit_impl() 

1797 

1798 

1799class NestedTransaction(Transaction): 

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

1801 

1802 A new :class:`.NestedTransaction` object may be procured 

1803 using the :meth:`_engine.Connection.begin_nested` method. 

1804 

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

1806 

1807 """ 

1808 

1809 def __init__(self, connection, parent): 

1810 super(NestedTransaction, self).__init__(connection, parent) 

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

1812 

1813 def _do_rollback(self): 

1814 if self.is_active: 

1815 self.connection._rollback_to_savepoint_impl( 

1816 self._savepoint, self._parent 

1817 ) 

1818 

1819 def _do_commit(self): 

1820 if self.is_active: 

1821 self.connection._release_savepoint_impl( 

1822 self._savepoint, self._parent 

1823 ) 

1824 

1825 

1826class TwoPhaseTransaction(Transaction): 

1827 """Represent a two-phase transaction. 

1828 

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

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

1831 

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

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

1834 

1835 """ 

1836 

1837 def __init__(self, connection, xid): 

1838 super(TwoPhaseTransaction, self).__init__(connection, None) 

1839 self._is_prepared = False 

1840 self.xid = xid 

1841 self.connection._begin_twophase_impl(self) 

1842 

1843 def prepare(self): 

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

1845 

1846 After a PREPARE, the transaction can be committed. 

1847 

1848 """ 

1849 if not self._parent.is_active: 

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

1851 self.connection._prepare_twophase_impl(self.xid) 

1852 self._is_prepared = True 

1853 

1854 def _do_rollback(self): 

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

1856 

1857 def _do_commit(self): 

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

1859 

1860 

1861class Engine(Connectable, log.Identified): 

1862 """ 

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

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

1865 source of database connectivity and behavior. 

1866 

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

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

1869 

1870 .. seealso:: 

1871 

1872 :doc:`/core/engines` 

1873 

1874 :ref:`connections_toplevel` 

1875 

1876 """ 

1877 

1878 _execution_options = util.immutabledict() 

1879 _has_events = False 

1880 _connection_cls = Connection 

1881 

1882 schema_for_object = schema._schema_getter(None) 

1883 """Return the ".schema" attribute for an object. 

1884 

1885 Used for :class:`_schema.Table`, :class:`.Sequence` and similar objects, 

1886 and takes into account 

1887 the :paramref:`.Connection.execution_options.schema_translate_map` 

1888 parameter. 

1889 

1890 .. versionadded:: 1.1 

1891 

1892 .. seealso:: 

1893 

1894 :ref:`schema_translating` 

1895 

1896 """ 

1897 

1898 def __init__( 

1899 self, 

1900 pool, 

1901 dialect, 

1902 url, 

1903 logging_name=None, 

1904 echo=None, 

1905 proxy=None, 

1906 execution_options=None, 

1907 hide_parameters=False, 

1908 ): 

1909 self.pool = pool 

1910 self.url = url 

1911 self.dialect = dialect 

1912 if logging_name: 

1913 self.logging_name = logging_name 

1914 self.echo = echo 

1915 self.hide_parameters = hide_parameters 

1916 log.instance_logger(self, echoflag=echo) 

1917 if proxy: 

1918 interfaces.ConnectionProxy._adapt_listener(self, proxy) 

1919 if execution_options: 

1920 self.update_execution_options(**execution_options) 

1921 

1922 @property 

1923 def engine(self): 

1924 return self 

1925 

1926 def update_execution_options(self, **opt): 

1927 r"""Update the default execution_options dictionary 

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

1929 

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

1931 default execution options that will be used for 

1932 all connections. The initial contents of this dictionary 

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

1934 to :func:`_sa.create_engine`. 

1935 

1936 .. seealso:: 

1937 

1938 :meth:`_engine.Connection.execution_options` 

1939 

1940 :meth:`_engine.Engine.execution_options` 

1941 

1942 """ 

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

1944 self.dispatch.set_engine_execution_options(self, opt) 

1945 self.dialect.set_engine_execution_options(self, opt) 

1946 

1947 def execution_options(self, **opt): 

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

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

1950 

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

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

1953 other state: 

1954 

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

1956 is the 

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

1958 method will replace 

1959 the connection pool instance for the parent engine as well 

1960 as this one. 

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

1962 :class:`_engine.Engine` 

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

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

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

1966 :class:`_engine.Engine`. 

1967 

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

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

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

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

1972 

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

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

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

1976 

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

1978 :class:`_engine.Connection` 

1979 objects that will contain the execution option 

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

1981 :class:`_engine.Connection` 

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

1983 

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

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

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

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

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

1989 which gives us a persistent 

1990 storage space that follows the DBAPI connection:: 

1991 

1992 from sqlalchemy import event 

1993 from sqlalchemy.engine import Engine 

1994 

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

1996 

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

1998 def _switch_shard(conn, cursor, stmt, 

1999 params, context, executemany): 

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

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

2002 

2003 if current_shard != shard_id: 

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

2005 conn.info["current_shard"] = shard_id 

2006 

2007 .. seealso:: 

2008 

2009 :meth:`_engine.Connection.execution_options` 

2010 - update execution options 

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

2012 

2013 :meth:`_engine.Engine.update_execution_options` 

2014 - update the execution 

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

2016 

2017 :meth:`_engine.Engine.get_execution_options` 

2018 

2019 

2020 """ 

2021 return OptionEngine(self, opt) 

2022 

2023 def get_execution_options(self): 

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

2025 

2026 .. versionadded: 1.3 

2027 

2028 .. seealso:: 

2029 

2030 :meth:`_engine.Engine.execution_options` 

2031 """ 

2032 return self._execution_options 

2033 

2034 @property 

2035 def name(self): 

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

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

2038 

2039 return self.dialect.name 

2040 

2041 @property 

2042 def driver(self): 

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

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

2045 

2046 return self.dialect.driver 

2047 

2048 echo = log.echo_property() 

2049 

2050 def __repr__(self): 

2051 return "Engine(%r)" % self.url 

2052 

2053 def dispose(self): 

2054 """Dispose of the connection pool used by this :class:`_engine.Engine` 

2055 . 

2056 

2057 This has the effect of fully closing all **currently checked in** 

2058 database connections. Connections that are still checked out 

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

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

2061 so when they are closed individually, 

2062 eventually the :class:`_pool.Pool` which they are associated with will 

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

2064 not already closed on checkin. 

2065 

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

2067 been disposed. This new pool, like all SQLAlchemy connection pools, 

2068 does not make any actual connections to the database until one is 

2069 first requested, so as long as the :class:`_engine.Engine` 

2070 isn't used again, 

2071 no new connections will be made. 

2072 

2073 .. seealso:: 

2074 

2075 :ref:`engine_disposal` 

2076 

2077 """ 

2078 self.pool.dispose() 

2079 self.pool = self.pool.recreate() 

2080 self.dispatch.engine_disposed(self) 

2081 

2082 def _execute_default(self, default): 

2083 with self._contextual_connect() as conn: 

2084 return conn._execute_default(default, (), {}) 

2085 

2086 @contextlib.contextmanager 

2087 def _optional_conn_ctx_manager(self, connection=None): 

2088 if connection is None: 

2089 with self._contextual_connect() as conn: 

2090 yield conn 

2091 else: 

2092 yield connection 

2093 

2094 def _run_visitor( 

2095 self, visitorcallable, element, connection=None, **kwargs 

2096 ): 

2097 with self._optional_conn_ctx_manager(connection) as conn: 

2098 conn._run_visitor(visitorcallable, element, **kwargs) 

2099 

2100 class _trans_ctx(object): 

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

2102 self.conn = conn 

2103 self.transaction = transaction 

2104 self.close_with_result = close_with_result 

2105 

2106 def __enter__(self): 

2107 return self.conn 

2108 

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

2110 if type_ is not None: 

2111 self.transaction.rollback() 

2112 else: 

2113 self.transaction.commit() 

2114 if not self.close_with_result: 

2115 self.conn.close() 

2116 

2117 def begin(self, close_with_result=False): 

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

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

2120 

2121 E.g.:: 

2122 

2123 with engine.begin() as conn: 

2124 conn.execute("insert into table (x, y, z) values (1, 2, 3)") 

2125 conn.execute("my_special_procedure(5)") 

2126 

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

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

2129 is rolled back. 

2130 

2131 The ``close_with_result`` flag is normally ``False``, and indicates 

2132 that the :class:`_engine.Connection` will be closed when the operation 

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

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

2135 :class:`_engine.ResultProxy` returned by the first call to 

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

2137 :class:`_engine.Connection` when 

2138 that :class:`_engine.ResultProxy` has exhausted all result rows. 

2139 

2140 .. seealso:: 

2141 

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

2143 :class:`_engine.Connection` from 

2144 an :class:`_engine.Engine`. 

2145 

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

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

2148 

2149 """ 

2150 conn = self._contextual_connect(close_with_result=close_with_result) 

2151 try: 

2152 trans = conn.begin() 

2153 except: 

2154 with util.safe_reraise(): 

2155 conn.close() 

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

2157 

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

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

2160 

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

2162 from :meth:`_engine.Engine.contextual_connect` as the first argument, 

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

2164 

2165 e.g.:: 

2166 

2167 def do_something(conn, x, y): 

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

2169 

2170 engine.transaction(do_something, 5, 10) 

2171 

2172 The operations inside the function are all invoked within the 

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

2174 Upon success, the transaction is committed. If an 

2175 exception is raised, the transaction is rolled back 

2176 before propagating the exception. 

2177 

2178 .. note:: 

2179 

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

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

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

2183 

2184 with engine.begin() as conn: 

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

2186 

2187 .. seealso:: 

2188 

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

2190 context 

2191 

2192 :meth:`_engine.Connection.transaction` 

2193 - connection-level version of 

2194 :meth:`_engine.Engine.transaction` 

2195 

2196 """ 

2197 

2198 with self._contextual_connect() as conn: 

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

2200 

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

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

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

2204 

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

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

2207 

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

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

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

2211 which one is being dealt with. 

2212 

2213 """ 

2214 with self._contextual_connect() as conn: 

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

2216 

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

2218 """Executes the given construct and returns a 

2219 :class:`_engine.ResultProxy`. 

2220 

2221 The arguments are the same as those used by 

2222 :meth:`_engine.Connection.execute`. 

2223 

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

2225 :meth:`_engine.Engine.contextual_connect` method, 

2226 and the statement executed 

2227 with that connection. The returned :class:`_engine.ResultProxy` 

2228 is flagged 

2229 such that when the :class:`_engine.ResultProxy` is exhausted and its 

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

2231 created here 

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

2233 resource to be returned to the connection pool. 

2234 

2235 """ 

2236 

2237 connection = self._contextual_connect(close_with_result=True) 

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

2239 

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

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

2242 

2243 def _execute_clauseelement(self, elem, multiparams=None, params=None): 

2244 connection = self._contextual_connect(close_with_result=True) 

2245 return connection._execute_clauseelement(elem, multiparams, params) 

2246 

2247 def _execute_compiled(self, compiled, multiparams, params): 

2248 connection = self._contextual_connect(close_with_result=True) 

2249 return connection._execute_compiled(compiled, multiparams, params) 

2250 

2251 def connect(self, **kwargs): 

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

2253 

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

2255 connection internally in order to communicate with the database. This 

2256 connection is procured from the connection-holding :class:`_pool.Pool` 

2257 referenced by this :class:`_engine.Engine`. When the 

2258 :meth:`_engine.Connection.close` method of the 

2259 :class:`_engine.Connection` object 

2260 is called, the underlying DBAPI connection is then returned to the 

2261 connection pool, where it may be used again in a subsequent call to 

2262 :meth:`_engine.Engine.connect`. 

2263 

2264 """ 

2265 

2266 return self._connection_cls(self, **kwargs) 

2267 

2268 @util.deprecated( 

2269 "1.3", 

2270 "The :meth:`_engine.Engine.contextual_connect` method is deprecated. " 

2271 "This " 

2272 "method is an artifact of the threadlocal engine strategy which is " 

2273 "also to be deprecated. For explicit connections from an " 

2274 ":class:`_engine.Engine`, use the :meth:`_engine.Engine.connect` " 

2275 "method.", 

2276 ) 

2277 def contextual_connect(self, close_with_result=False, **kwargs): 

2278 """Return a :class:`_engine.Connection` 

2279 object which may be part of some 

2280 ongoing context. 

2281 

2282 By default, this method does the same thing as 

2283 :meth:`_engine.Engine.connect`. 

2284 Subclasses of :class:`_engine.Engine` may override this method 

2285 to provide contextual behavior. 

2286 

2287 :param close_with_result: When True, the first 

2288 :class:`_engine.ResultProxy` 

2289 created by the :class:`_engine.Connection` will call the 

2290 :meth:`_engine.Connection.close` 

2291 method of that connection as soon as any 

2292 pending result rows are exhausted. This is used to supply the 

2293 "connectionless execution" behavior provided by the 

2294 :meth:`_engine.Engine.execute` method. 

2295 

2296 """ 

2297 

2298 return self._contextual_connect( 

2299 close_with_result=close_with_result, **kwargs 

2300 ) 

2301 

2302 def _contextual_connect(self, close_with_result=False, **kwargs): 

2303 return self._connection_cls( 

2304 self, 

2305 self._wrap_pool_connect(self.pool.connect, None), 

2306 close_with_result=close_with_result, 

2307 **kwargs 

2308 ) 

2309 

2310 def table_names(self, schema=None, connection=None): 

2311 """Return a list of all table names available in the database. 

2312 

2313 :param schema: Optional, retrieve names from a non-default schema. 

2314 

2315 :param connection: Optional, use a specified connection. Default is 

2316 the ``contextual_connect`` for this ``Engine``. 

2317 """ 

2318 

2319 with self._optional_conn_ctx_manager(connection) as conn: 

2320 return self.dialect.get_table_names(conn, schema) 

2321 

2322 def has_table(self, table_name, schema=None): 

2323 """Return True if the given backend has a table of the given name. 

2324 

2325 .. seealso:: 

2326 

2327 :ref:`metadata_reflection_inspector` - detailed schema inspection 

2328 using the :class:`_reflection.Inspector` interface. 

2329 

2330 :class:`.quoted_name` - used to pass quoting information along 

2331 with a schema identifier. 

2332 

2333 """ 

2334 return self.run_callable(self.dialect.has_table, table_name, schema) 

2335 

2336 def _wrap_pool_connect(self, fn, connection): 

2337 dialect = self.dialect 

2338 try: 

2339 return fn() 

2340 except dialect.dbapi.Error as e: 

2341 if connection is None: 

2342 Connection._handle_dbapi_exception_noconnection( 

2343 e, dialect, self 

2344 ) 

2345 else: 

2346 util.raise_( 

2347 sys.exc_info()[1], with_traceback=sys.exc_info()[2] 

2348 ) 

2349 

2350 def raw_connection(self, _connection=None): 

2351 """Return a "raw" DBAPI connection from the connection pool. 

2352 

2353 The returned object is a proxied version of the DBAPI 

2354 connection object used by the underlying driver in use. 

2355 The object will have all the same behavior as the real DBAPI 

2356 connection, except that its ``close()`` method will result in the 

2357 connection being returned to the pool, rather than being closed 

2358 for real. 

2359 

2360 This method provides direct DBAPI connection access for 

2361 special situations when the API provided by 

2362 :class:`_engine.Connection` 

2363 is not needed. When a :class:`_engine.Connection` object is already 

2364 present, the DBAPI connection is available using 

2365 the :attr:`_engine.Connection.connection` accessor. 

2366 

2367 .. seealso:: 

2368 

2369 :ref:`dbapi_connections` 

2370 

2371 """ 

2372 return self._wrap_pool_connect( 

2373 self.pool.unique_connection, _connection 

2374 ) 

2375 

2376 

2377class OptionEngine(Engine): 

2378 _sa_propagate_class_events = False 

2379 

2380 def __init__(self, proxied, execution_options): 

2381 self._proxied = proxied 

2382 self.url = proxied.url 

2383 self.dialect = proxied.dialect 

2384 self.logging_name = proxied.logging_name 

2385 self.echo = proxied.echo 

2386 self.hide_parameters = proxied.hide_parameters 

2387 log.instance_logger(self, echoflag=self.echo) 

2388 

2389 # note: this will propagate events that are assigned to the parent 

2390 # engine after this OptionEngine is created. Since we share 

2391 # the events of the parent we also disallow class-level events 

2392 # to apply to the OptionEngine class directly. 

2393 # 

2394 # the other way this can work would be to transfer existing 

2395 # events only, using: 

2396 # self.dispatch._update(proxied.dispatch) 

2397 # 

2398 # that might be more appropriate however it would be a behavioral 

2399 # change for logic that assigns events to the parent engine and 

2400 # would like it to take effect for the already-created sub-engine. 

2401 self.dispatch = self.dispatch._join(proxied.dispatch) 

2402 

2403 self._execution_options = proxied._execution_options 

2404 self.update_execution_options(**execution_options) 

2405 

2406 def _get_pool(self): 

2407 return self._proxied.pool 

2408 

2409 def _set_pool(self, pool): 

2410 self._proxied.pool = pool 

2411 

2412 pool = property(_get_pool, _set_pool) 

2413 

2414 def _get_has_events(self): 

2415 return self._proxied._has_events or self.__dict__.get( 

2416 "_has_events", False 

2417 ) 

2418 

2419 def _set_has_events(self, value): 

2420 self.__dict__["_has_events"] = value 

2421 

2422 _has_events = property(_get_has_events, _set_has_events)