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# sqlalchemy/events.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 

7 

8"""Core event interfaces.""" 

9 

10from . import event 

11from . import exc 

12from . import util 

13from .engine import Connectable 

14from .engine import Dialect 

15from .engine import Engine 

16from .pool import Pool 

17from .sql.base import SchemaEventTarget 

18 

19 

20class DDLEvents(event.Events): 

21 """ 

22 Define event listeners for schema objects, 

23 that is, :class:`.SchemaItem` and other :class:`.SchemaEventTarget` 

24 subclasses, including :class:`_schema.MetaData`, :class:`_schema.Table`, 

25 :class:`_schema.Column`. 

26 

27 :class:`_schema.MetaData` and :class:`_schema.Table` support events 

28 specifically regarding when CREATE and DROP 

29 DDL is emitted to the database. 

30 

31 Attachment events are also provided to customize 

32 behavior whenever a child schema element is associated 

33 with a parent, such as, when a :class:`_schema.Column` is associated 

34 with its :class:`_schema.Table`, when a 

35 :class:`_schema.ForeignKeyConstraint` 

36 is associated with a :class:`_schema.Table`, etc. 

37 

38 Example using the ``after_create`` event:: 

39 

40 from sqlalchemy import event 

41 from sqlalchemy import Table, Column, Metadata, Integer 

42 

43 m = MetaData() 

44 some_table = Table('some_table', m, Column('data', Integer)) 

45 

46 def after_create(target, connection, **kw): 

47 connection.execute("ALTER TABLE %s SET name=foo_%s" % 

48 (target.name, target.name)) 

49 

50 event.listen(some_table, "after_create", after_create) 

51 

52 DDL events integrate closely with the 

53 :class:`.DDL` class and the :class:`.DDLElement` hierarchy 

54 of DDL clause constructs, which are themselves appropriate 

55 as listener callables:: 

56 

57 from sqlalchemy import DDL 

58 event.listen( 

59 some_table, 

60 "after_create", 

61 DDL("ALTER TABLE %(table)s SET name=foo_%(table)s") 

62 ) 

63 

64 The methods here define the name of an event as well 

65 as the names of members that are passed to listener 

66 functions. 

67 

68 For all :class:`.DDLEvent` events, the ``propagate=True`` keyword argument 

69 will ensure that a given event handler is propagated to copies of the 

70 object, which are made when using the :meth:`_schema.Table.tometadata` 

71 method:: 

72 

73 from sqlalchemy import DDL 

74 event.listen( 

75 some_table, 

76 "after_create", 

77 DDL("ALTER TABLE %(table)s SET name=foo_%(table)s"), 

78 propagate=True 

79 ) 

80 

81 new_table = some_table.tometadata(new_metadata) 

82 

83 The above :class:`.DDL` object will also be associated with the 

84 :class:`_schema.Table` object represented by ``new_table``. 

85 

86 .. seealso:: 

87 

88 :ref:`event_toplevel` 

89 

90 :class:`.DDLElement` 

91 

92 :class:`.DDL` 

93 

94 :ref:`schema_ddl_sequences` 

95 

96 """ 

97 

98 _target_class_doc = "SomeSchemaClassOrObject" 

99 _dispatch_target = SchemaEventTarget 

100 

101 def before_create(self, target, connection, **kw): 

102 r"""Called before CREATE statements are emitted. 

103 

104 :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 

105 object which is the target of the event. 

106 :param connection: the :class:`_engine.Connection` where the 

107 CREATE statement or statements will be emitted. 

108 :param \**kw: additional keyword arguments relevant 

109 to the event. The contents of this dictionary 

110 may vary across releases, and include the 

111 list of tables being generated for a metadata-level 

112 event, the checkfirst flag, and other 

113 elements used by internal events. 

114 

115 :func:`.event.listen` also accepts the ``propagate=True`` 

116 modifier for this event; when True, the listener function will 

117 be established for any copies made of the target object, 

118 i.e. those copies that are generated when 

119 :meth:`_schema.Table.tometadata` is used. 

120 

121 """ 

122 

123 def after_create(self, target, connection, **kw): 

124 r"""Called after CREATE statements are emitted. 

125 

126 :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 

127 object which is the target of the event. 

128 :param connection: the :class:`_engine.Connection` where the 

129 CREATE statement or statements have been emitted. 

130 :param \**kw: additional keyword arguments relevant 

131 to the event. The contents of this dictionary 

132 may vary across releases, and include the 

133 list of tables being generated for a metadata-level 

134 event, the checkfirst flag, and other 

135 elements used by internal events. 

136 

137 :func:`.event.listen` also accepts the ``propagate=True`` 

138 modifier for this event; when True, the listener function will 

139 be established for any copies made of the target object, 

140 i.e. those copies that are generated when 

141 :meth:`_schema.Table.tometadata` is used. 

142 

143 """ 

144 

145 def before_drop(self, target, connection, **kw): 

146 r"""Called before DROP statements are emitted. 

147 

148 :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 

149 object which is the target of the event. 

150 :param connection: the :class:`_engine.Connection` where the 

151 DROP statement or statements will be emitted. 

152 :param \**kw: additional keyword arguments relevant 

153 to the event. The contents of this dictionary 

154 may vary across releases, and include the 

155 list of tables being generated for a metadata-level 

156 event, the checkfirst flag, and other 

157 elements used by internal events. 

158 

159 :func:`.event.listen` also accepts the ``propagate=True`` 

160 modifier for this event; when True, the listener function will 

161 be established for any copies made of the target object, 

162 i.e. those copies that are generated when 

163 :meth:`_schema.Table.tometadata` is used. 

164 

165 """ 

166 

167 def after_drop(self, target, connection, **kw): 

168 r"""Called after DROP statements are emitted. 

169 

170 :param target: the :class:`_schema.MetaData` or :class:`_schema.Table` 

171 object which is the target of the event. 

172 :param connection: the :class:`_engine.Connection` where the 

173 DROP statement or statements have been emitted. 

174 :param \**kw: additional keyword arguments relevant 

175 to the event. The contents of this dictionary 

176 may vary across releases, and include the 

177 list of tables being generated for a metadata-level 

178 event, the checkfirst flag, and other 

179 elements used by internal events. 

180 

181 :func:`.event.listen` also accepts the ``propagate=True`` 

182 modifier for this event; when True, the listener function will 

183 be established for any copies made of the target object, 

184 i.e. those copies that are generated when 

185 :meth:`_schema.Table.tometadata` is used. 

186 

187 """ 

188 

189 def before_parent_attach(self, target, parent): 

190 """Called before a :class:`.SchemaItem` is associated with 

191 a parent :class:`.SchemaItem`. 

192 

193 :param target: the target object 

194 :param parent: the parent to which the target is being attached. 

195 

196 :func:`.event.listen` also accepts the ``propagate=True`` 

197 modifier for this event; when True, the listener function will 

198 be established for any copies made of the target object, 

199 i.e. those copies that are generated when 

200 :meth:`_schema.Table.tometadata` is used. 

201 

202 """ 

203 

204 def after_parent_attach(self, target, parent): 

205 """Called after a :class:`.SchemaItem` is associated with 

206 a parent :class:`.SchemaItem`. 

207 

208 :param target: the target object 

209 :param parent: the parent to which the target is being attached. 

210 

211 :func:`.event.listen` also accepts the ``propagate=True`` 

212 modifier for this event; when True, the listener function will 

213 be established for any copies made of the target object, 

214 i.e. those copies that are generated when 

215 :meth:`_schema.Table.tometadata` is used. 

216 

217 """ 

218 

219 def column_reflect(self, inspector, table, column_info): 

220 """Called for each unit of 'column info' retrieved when 

221 a :class:`_schema.Table` is being reflected. 

222 

223 The dictionary of column information as returned by the 

224 dialect is passed, and can be modified. The dictionary 

225 is that returned in each element of the list returned 

226 by :meth:`.reflection.Inspector.get_columns`: 

227 

228 * ``name`` - the column's name 

229 

230 * ``type`` - the type of this column, which should be an instance 

231 of :class:`~sqlalchemy.types.TypeEngine` 

232 

233 * ``nullable`` - boolean flag if the column is NULL or NOT NULL 

234 

235 * ``default`` - the column's server default value. This is 

236 normally specified as a plain string SQL expression, however the 

237 event can pass a :class:`.FetchedValue`, :class:`.DefaultClause`, 

238 or :func:`_expression.text` object as well. 

239 

240 .. versionchanged:: 1.1.6 

241 

242 The :meth:`.DDLEvents.column_reflect` event allows a non 

243 string :class:`.FetchedValue`, 

244 :func:`_expression.text`, or derived object to be 

245 specified as the value of ``default`` in the column 

246 dictionary. 

247 

248 * ``attrs`` - dict containing optional column attributes 

249 

250 The event is called before any action is taken against 

251 this dictionary, and the contents can be modified. 

252 The :class:`_schema.Column` specific arguments ``info``, ``key``, 

253 and ``quote`` can also be added to the dictionary and 

254 will be passed to the constructor of :class:`_schema.Column`. 

255 

256 Note that this event is only meaningful if either 

257 associated with the :class:`_schema.Table` class across the 

258 board, e.g.:: 

259 

260 from sqlalchemy.schema import Table 

261 from sqlalchemy import event 

262 

263 def listen_for_reflect(inspector, table, column_info): 

264 "receive a column_reflect event" 

265 # ... 

266 

267 event.listen( 

268 Table, 

269 'column_reflect', 

270 listen_for_reflect) 

271 

272 ...or with a specific :class:`_schema.Table` instance using 

273 the ``listeners`` argument:: 

274 

275 def listen_for_reflect(inspector, table, column_info): 

276 "receive a column_reflect event" 

277 # ... 

278 

279 t = Table( 

280 'sometable', 

281 autoload=True, 

282 listeners=[ 

283 ('column_reflect', listen_for_reflect) 

284 ]) 

285 

286 This because the reflection process initiated by ``autoload=True`` 

287 completes within the scope of the constructor for 

288 :class:`_schema.Table`. 

289 

290 :func:`.event.listen` also accepts the ``propagate=True`` 

291 modifier for this event; when True, the listener function will 

292 be established for any copies made of the target object, 

293 i.e. those copies that are generated when 

294 :meth:`_schema.Table.tometadata` is used. 

295 

296 """ 

297 

298 

299class PoolEvents(event.Events): 

300 """Available events for :class:`_pool.Pool`. 

301 

302 The methods here define the name of an event as well 

303 as the names of members that are passed to listener 

304 functions. 

305 

306 e.g.:: 

307 

308 from sqlalchemy import event 

309 

310 def my_on_checkout(dbapi_conn, connection_rec, connection_proxy): 

311 "handle an on checkout event" 

312 

313 event.listen(Pool, 'checkout', my_on_checkout) 

314 

315 In addition to accepting the :class:`_pool.Pool` class and 

316 :class:`_pool.Pool` instances, :class:`_events.PoolEvents` also accepts 

317 :class:`_engine.Engine` objects and the :class:`_engine.Engine` class as 

318 targets, which will be resolved to the ``.pool`` attribute of the 

319 given engine or the :class:`_pool.Pool` class:: 

320 

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

322 

323 # will associate with engine.pool 

324 event.listen(engine, 'checkout', my_on_checkout) 

325 

326 """ 

327 

328 _target_class_doc = "SomeEngineOrPool" 

329 _dispatch_target = Pool 

330 

331 @classmethod 

332 def _accept_with(cls, target): 

333 if isinstance(target, type): 

334 if issubclass(target, Engine): 

335 return Pool 

336 elif issubclass(target, Pool): 

337 return target 

338 elif isinstance(target, Engine): 

339 return target.pool 

340 else: 

341 return target 

342 

343 def connect(self, dbapi_connection, connection_record): 

344 """Called at the moment a particular DBAPI connection is first 

345 created for a given :class:`_pool.Pool`. 

346 

347 This event allows one to capture the point directly after which 

348 the DBAPI module-level ``.connect()`` method has been used in order 

349 to produce a new DBAPI connection. 

350 

351 :param dbapi_connection: a DBAPI connection. 

352 

353 :param connection_record: the :class:`._ConnectionRecord` managing the 

354 DBAPI connection. 

355 

356 """ 

357 

358 def first_connect(self, dbapi_connection, connection_record): 

359 """Called exactly once for the first time a DBAPI connection is 

360 checked out from a particular :class:`_pool.Pool`. 

361 

362 The rationale for :meth:`_events.PoolEvents.first_connect` 

363 is to determine 

364 information about a particular series of database connections based 

365 on the settings used for all connections. Since a particular 

366 :class:`_pool.Pool` 

367 refers to a single "creator" function (which in terms 

368 of a :class:`_engine.Engine` 

369 refers to the URL and connection options used), 

370 it is typically valid to make observations about a single connection 

371 that can be safely assumed to be valid about all subsequent 

372 connections, such as the database version, the server and client 

373 encoding settings, collation settings, and many others. 

374 

375 :param dbapi_connection: a DBAPI connection. 

376 

377 :param connection_record: the :class:`._ConnectionRecord` managing the 

378 DBAPI connection. 

379 

380 """ 

381 

382 def checkout(self, dbapi_connection, connection_record, connection_proxy): 

383 """Called when a connection is retrieved from the Pool. 

384 

385 :param dbapi_connection: a DBAPI connection. 

386 

387 :param connection_record: the :class:`._ConnectionRecord` managing the 

388 DBAPI connection. 

389 

390 :param connection_proxy: the :class:`._ConnectionFairy` object which 

391 will proxy the public interface of the DBAPI connection for the 

392 lifespan of the checkout. 

393 

394 If you raise a :class:`~sqlalchemy.exc.DisconnectionError`, the current 

395 connection will be disposed and a fresh connection retrieved. 

396 Processing of all checkout listeners will abort and restart 

397 using the new connection. 

398 

399 .. seealso:: :meth:`_events.ConnectionEvents.engine_connect` 

400 - a similar event 

401 which occurs upon creation of a new :class:`_engine.Connection`. 

402 

403 """ 

404 

405 def checkin(self, dbapi_connection, connection_record): 

406 """Called when a connection returns to the pool. 

407 

408 Note that the connection may be closed, and may be None if the 

409 connection has been invalidated. ``checkin`` will not be called 

410 for detached connections. (They do not return to the pool.) 

411 

412 :param dbapi_connection: a DBAPI connection. 

413 

414 :param connection_record: the :class:`._ConnectionRecord` managing the 

415 DBAPI connection. 

416 

417 """ 

418 

419 def reset(self, dbapi_connection, connection_record): 

420 """Called before the "reset" action occurs for a pooled connection. 

421 

422 This event represents 

423 when the ``rollback()`` method is called on the DBAPI connection 

424 before it is returned to the pool. The behavior of "reset" can 

425 be controlled, including disabled, using the ``reset_on_return`` 

426 pool argument. 

427 

428 

429 The :meth:`_events.PoolEvents.reset` event is usually followed by the 

430 :meth:`_events.PoolEvents.checkin` event is called, except in those 

431 cases where the connection is discarded immediately after reset. 

432 

433 :param dbapi_connection: a DBAPI connection. 

434 

435 :param connection_record: the :class:`._ConnectionRecord` managing the 

436 DBAPI connection. 

437 

438 .. seealso:: 

439 

440 :meth:`_events.ConnectionEvents.rollback` 

441 

442 :meth:`_events.ConnectionEvents.commit` 

443 

444 """ 

445 

446 def invalidate(self, dbapi_connection, connection_record, exception): 

447 """Called when a DBAPI connection is to be "invalidated". 

448 

449 This event is called any time the :meth:`._ConnectionRecord.invalidate` 

450 method is invoked, either from API usage or via "auto-invalidation", 

451 without the ``soft`` flag. 

452 

453 The event occurs before a final attempt to call ``.close()`` on the 

454 connection occurs. 

455 

456 :param dbapi_connection: a DBAPI connection. 

457 

458 :param connection_record: the :class:`._ConnectionRecord` managing the 

459 DBAPI connection. 

460 

461 :param exception: the exception object corresponding to the reason 

462 for this invalidation, if any. May be ``None``. 

463 

464 .. versionadded:: 0.9.2 Added support for connection invalidation 

465 listening. 

466 

467 .. seealso:: 

468 

469 :ref:`pool_connection_invalidation` 

470 

471 """ 

472 

473 def soft_invalidate(self, dbapi_connection, connection_record, exception): 

474 """Called when a DBAPI connection is to be "soft invalidated". 

475 

476 This event is called any time the :meth:`._ConnectionRecord.invalidate` 

477 method is invoked with the ``soft`` flag. 

478 

479 Soft invalidation refers to when the connection record that tracks 

480 this connection will force a reconnect after the current connection 

481 is checked in. It does not actively close the dbapi_connection 

482 at the point at which it is called. 

483 

484 .. versionadded:: 1.0.3 

485 

486 """ 

487 

488 def close(self, dbapi_connection, connection_record): 

489 """Called when a DBAPI connection is closed. 

490 

491 The event is emitted before the close occurs. 

492 

493 The close of a connection can fail; typically this is because 

494 the connection is already closed. If the close operation fails, 

495 the connection is discarded. 

496 

497 The :meth:`.close` event corresponds to a connection that's still 

498 associated with the pool. To intercept close events for detached 

499 connections use :meth:`.close_detached`. 

500 

501 .. versionadded:: 1.1 

502 

503 """ 

504 

505 def detach(self, dbapi_connection, connection_record): 

506 """Called when a DBAPI connection is "detached" from a pool. 

507 

508 This event is emitted after the detach occurs. The connection 

509 is no longer associated with the given connection record. 

510 

511 .. versionadded:: 1.1 

512 

513 """ 

514 

515 def close_detached(self, dbapi_connection): 

516 """Called when a detached DBAPI connection is closed. 

517 

518 The event is emitted before the close occurs. 

519 

520 The close of a connection can fail; typically this is because 

521 the connection is already closed. If the close operation fails, 

522 the connection is discarded. 

523 

524 .. versionadded:: 1.1 

525 

526 """ 

527 

528 

529class ConnectionEvents(event.Events): 

530 """Available events for :class:`.Connectable`, which includes 

531 :class:`_engine.Connection` and :class:`_engine.Engine`. 

532 

533 The methods here define the name of an event as well as the names of 

534 members that are passed to listener functions. 

535 

536 An event listener can be associated with any :class:`.Connectable` 

537 class or instance, such as an :class:`_engine.Engine`, e.g.:: 

538 

539 from sqlalchemy import event, create_engine 

540 

541 def before_cursor_execute(conn, cursor, statement, parameters, context, 

542 executemany): 

543 log.info("Received statement: %s", statement) 

544 

545 engine = create_engine('postgresql://scott:tiger@localhost/test') 

546 event.listen(engine, "before_cursor_execute", before_cursor_execute) 

547 

548 or with a specific :class:`_engine.Connection`:: 

549 

550 with engine.begin() as conn: 

551 @event.listens_for(conn, 'before_cursor_execute') 

552 def before_cursor_execute(conn, cursor, statement, parameters, 

553 context, executemany): 

554 log.info("Received statement: %s", statement) 

555 

556 When the methods are called with a `statement` parameter, such as in 

557 :meth:`.after_cursor_execute`, :meth:`.before_cursor_execute` and 

558 :meth:`.dbapi_error`, the statement is the exact SQL string that was 

559 prepared for transmission to the DBAPI ``cursor`` in the connection's 

560 :class:`.Dialect`. 

561 

562 The :meth:`.before_execute` and :meth:`.before_cursor_execute` 

563 events can also be established with the ``retval=True`` flag, which 

564 allows modification of the statement and parameters to be sent 

565 to the database. The :meth:`.before_cursor_execute` event is 

566 particularly useful here to add ad-hoc string transformations, such 

567 as comments, to all executions:: 

568 

569 from sqlalchemy.engine import Engine 

570 from sqlalchemy import event 

571 

572 @event.listens_for(Engine, "before_cursor_execute", retval=True) 

573 def comment_sql_calls(conn, cursor, statement, parameters, 

574 context, executemany): 

575 statement = statement + " -- some comment" 

576 return statement, parameters 

577 

578 .. note:: :class:`_events.ConnectionEvents` can be established on any 

579 combination of :class:`_engine.Engine`, :class:`_engine.Connection`, 

580 as well 

581 as instances of each of those classes. Events across all 

582 four scopes will fire off for a given instance of 

583 :class:`_engine.Connection`. However, for performance reasons, the 

584 :class:`_engine.Connection` object determines at instantiation time 

585 whether or not its parent :class:`_engine.Engine` has event listeners 

586 established. Event listeners added to the :class:`_engine.Engine` 

587 class or to an instance of :class:`_engine.Engine` 

588 *after* the instantiation 

589 of a dependent :class:`_engine.Connection` instance will usually 

590 *not* be available on that :class:`_engine.Connection` instance. 

591 The newly 

592 added listeners will instead take effect for 

593 :class:`_engine.Connection` 

594 instances created subsequent to those event listeners being 

595 established on the parent :class:`_engine.Engine` class or instance. 

596 

597 :param retval=False: Applies to the :meth:`.before_execute` and 

598 :meth:`.before_cursor_execute` events only. When True, the 

599 user-defined event function must have a return value, which 

600 is a tuple of parameters that replace the given statement 

601 and parameters. See those methods for a description of 

602 specific return arguments. 

603 

604 """ 

605 

606 _target_class_doc = "SomeEngine" 

607 _dispatch_target = Connectable 

608 

609 @classmethod 

610 def _listen(cls, event_key, retval=False): 

611 target, identifier, fn = ( 

612 event_key.dispatch_target, 

613 event_key.identifier, 

614 event_key._listen_fn, 

615 ) 

616 

617 target._has_events = True 

618 

619 if not retval: 

620 if identifier == "before_execute": 

621 orig_fn = fn 

622 

623 def wrap_before_execute( 

624 conn, clauseelement, multiparams, params 

625 ): 

626 orig_fn(conn, clauseelement, multiparams, params) 

627 return clauseelement, multiparams, params 

628 

629 fn = wrap_before_execute 

630 elif identifier == "before_cursor_execute": 

631 orig_fn = fn 

632 

633 def wrap_before_cursor_execute( 

634 conn, cursor, statement, parameters, context, executemany 

635 ): 

636 orig_fn( 

637 conn, 

638 cursor, 

639 statement, 

640 parameters, 

641 context, 

642 executemany, 

643 ) 

644 return statement, parameters 

645 

646 fn = wrap_before_cursor_execute 

647 elif retval and identifier not in ( 

648 "before_execute", 

649 "before_cursor_execute", 

650 "handle_error", 

651 ): 

652 raise exc.ArgumentError( 

653 "Only the 'before_execute', " 

654 "'before_cursor_execute' and 'handle_error' engine " 

655 "event listeners accept the 'retval=True' " 

656 "argument." 

657 ) 

658 event_key.with_wrapper(fn).base_listen() 

659 

660 def before_execute(self, conn, clauseelement, multiparams, params): 

661 """Intercept high level execute() events, receiving uncompiled 

662 SQL constructs and other objects prior to rendering into SQL. 

663 

664 This event is good for debugging SQL compilation issues as well 

665 as early manipulation of the parameters being sent to the database, 

666 as the parameter lists will be in a consistent format here. 

667 

668 This event can be optionally established with the ``retval=True`` 

669 flag. The ``clauseelement``, ``multiparams``, and ``params`` 

670 arguments should be returned as a three-tuple in this case:: 

671 

672 @event.listens_for(Engine, "before_execute", retval=True) 

673 def before_execute(conn, clauseelement, multiparams, params): 

674 # do something with clauseelement, multiparams, params 

675 return clauseelement, multiparams, params 

676 

677 :param conn: :class:`_engine.Connection` object 

678 :param clauseelement: SQL expression construct, :class:`.Compiled` 

679 instance, or string statement passed to 

680 :meth:`_engine.Connection.execute`. 

681 :param multiparams: Multiple parameter sets, a list of dictionaries. 

682 :param params: Single parameter set, a single dictionary. 

683 

684 .. seealso:: 

685 

686 :meth:`.before_cursor_execute` 

687 

688 """ 

689 

690 def after_execute(self, conn, clauseelement, multiparams, params, result): 

691 """Intercept high level execute() events after execute. 

692 

693 

694 :param conn: :class:`_engine.Connection` object 

695 :param clauseelement: SQL expression construct, :class:`.Compiled` 

696 instance, or string statement passed to 

697 :meth:`_engine.Connection.execute`. 

698 :param multiparams: Multiple parameter sets, a list of dictionaries. 

699 :param params: Single parameter set, a single dictionary. 

700 :param result: :class:`_engine.ResultProxy` generated by the execution 

701 . 

702 

703 """ 

704 

705 def before_cursor_execute( 

706 self, conn, cursor, statement, parameters, context, executemany 

707 ): 

708 """Intercept low-level cursor execute() events before execution, 

709 receiving the string SQL statement and DBAPI-specific parameter list to 

710 be invoked against a cursor. 

711 

712 This event is a good choice for logging as well as late modifications 

713 to the SQL string. It's less ideal for parameter modifications except 

714 for those which are specific to a target backend. 

715 

716 This event can be optionally established with the ``retval=True`` 

717 flag. The ``statement`` and ``parameters`` arguments should be 

718 returned as a two-tuple in this case:: 

719 

720 @event.listens_for(Engine, "before_cursor_execute", retval=True) 

721 def before_cursor_execute(conn, cursor, statement, 

722 parameters, context, executemany): 

723 # do something with statement, parameters 

724 return statement, parameters 

725 

726 See the example at :class:`_events.ConnectionEvents`. 

727 

728 :param conn: :class:`_engine.Connection` object 

729 :param cursor: DBAPI cursor object 

730 :param statement: string SQL statement, as to be passed to the DBAPI 

731 :param parameters: Dictionary, tuple, or list of parameters being 

732 passed to the ``execute()`` or ``executemany()`` method of the 

733 DBAPI ``cursor``. In some cases may be ``None``. 

734 :param context: :class:`.ExecutionContext` object in use. May 

735 be ``None``. 

736 :param executemany: boolean, if ``True``, this is an ``executemany()`` 

737 call, if ``False``, this is an ``execute()`` call. 

738 

739 .. seealso:: 

740 

741 :meth:`.before_execute` 

742 

743 :meth:`.after_cursor_execute` 

744 

745 """ 

746 

747 def after_cursor_execute( 

748 self, conn, cursor, statement, parameters, context, executemany 

749 ): 

750 """Intercept low-level cursor execute() events after execution. 

751 

752 :param conn: :class:`_engine.Connection` object 

753 :param cursor: DBAPI cursor object. Will have results pending 

754 if the statement was a SELECT, but these should not be consumed 

755 as they will be needed by the :class:`_engine.ResultProxy`. 

756 :param statement: string SQL statement, as passed to the DBAPI 

757 :param parameters: Dictionary, tuple, or list of parameters being 

758 passed to the ``execute()`` or ``executemany()`` method of the 

759 DBAPI ``cursor``. In some cases may be ``None``. 

760 :param context: :class:`.ExecutionContext` object in use. May 

761 be ``None``. 

762 :param executemany: boolean, if ``True``, this is an ``executemany()`` 

763 call, if ``False``, this is an ``execute()`` call. 

764 

765 """ 

766 

767 @util.deprecated( 

768 "0.9", 

769 "The :meth:`_events.ConnectionEvents.dbapi_error` " 

770 "event is deprecated and will be removed in a future release. " 

771 "Please refer to the :meth:`_events.ConnectionEvents.handle_error` " 

772 "event.", 

773 ) 

774 def dbapi_error( 

775 self, conn, cursor, statement, parameters, context, exception 

776 ): 

777 """Intercept a raw DBAPI error. 

778 

779 This event is called with the DBAPI exception instance 

780 received from the DBAPI itself, *before* SQLAlchemy wraps the 

781 exception with it's own exception wrappers, and before any 

782 other operations are performed on the DBAPI cursor; the 

783 existing transaction remains in effect as well as any state 

784 on the cursor. 

785 

786 The use case here is to inject low-level exception handling 

787 into an :class:`_engine.Engine`, typically for logging and 

788 debugging purposes. 

789 

790 .. warning:: 

791 

792 Code should **not** modify 

793 any state or throw any exceptions here as this will 

794 interfere with SQLAlchemy's cleanup and error handling 

795 routines. For exception modification, please refer to the 

796 new :meth:`_events.ConnectionEvents.handle_error` event. 

797 

798 Subsequent to this hook, SQLAlchemy may attempt any 

799 number of operations on the connection/cursor, including 

800 closing the cursor, rolling back of the transaction in the 

801 case of connectionless execution, and disposing of the entire 

802 connection pool if a "disconnect" was detected. The 

803 exception is then wrapped in a SQLAlchemy DBAPI exception 

804 wrapper and re-thrown. 

805 

806 :param conn: :class:`_engine.Connection` object 

807 :param cursor: DBAPI cursor object 

808 :param statement: string SQL statement, as passed to the DBAPI 

809 :param parameters: Dictionary, tuple, or list of parameters being 

810 passed to the ``execute()`` or ``executemany()`` method of the 

811 DBAPI ``cursor``. In some cases may be ``None``. 

812 :param context: :class:`.ExecutionContext` object in use. May 

813 be ``None``. 

814 :param exception: The **unwrapped** exception emitted directly from the 

815 DBAPI. The class here is specific to the DBAPI module in use. 

816 

817 """ 

818 

819 def handle_error(self, exception_context): 

820 r"""Intercept all exceptions processed by the 

821 :class:`_engine.Connection`. 

822 

823 This includes all exceptions emitted by the DBAPI as well as 

824 within SQLAlchemy's statement invocation process, including 

825 encoding errors and other statement validation errors. Other areas 

826 in which the event is invoked include transaction begin and end, 

827 result row fetching, cursor creation. 

828 

829 Note that :meth:`.handle_error` may support new kinds of exceptions 

830 and new calling scenarios at *any time*. Code which uses this 

831 event must expect new calling patterns to be present in minor 

832 releases. 

833 

834 To support the wide variety of members that correspond to an exception, 

835 as well as to allow extensibility of the event without backwards 

836 incompatibility, the sole argument received is an instance of 

837 :class:`.ExceptionContext`. This object contains data members 

838 representing detail about the exception. 

839 

840 Use cases supported by this hook include: 

841 

842 * read-only, low-level exception handling for logging and 

843 debugging purposes 

844 * exception re-writing 

845 * Establishing or disabling whether a connection or the owning 

846 connection pool is invalidated or expired in response to a 

847 specific exception. 

848 

849 The hook is called while the cursor from the failed operation 

850 (if any) is still open and accessible. Special cleanup operations 

851 can be called on this cursor; SQLAlchemy will attempt to close 

852 this cursor subsequent to this hook being invoked. If the connection 

853 is in "autocommit" mode, the transaction also remains open within 

854 the scope of this hook; the rollback of the per-statement transaction 

855 also occurs after the hook is called. 

856 

857 For the common case of detecting a "disconnect" situation which 

858 is not currently handled by the SQLAlchemy dialect, the 

859 :attr:`.ExceptionContext.is_disconnect` flag can be set to True which 

860 will cause the exception to be considered as a disconnect situation, 

861 which typically results in the connection pool being invalidated:: 

862 

863 @event.listens_for(Engine, "handle_error") 

864 def handle_exception(context): 

865 if isinstance(context.original_exception, pyodbc.Error): 

866 for code in ( 

867 '08S01', '01002', '08003', 

868 '08007', '08S02', '08001', 'HYT00', 'HY010'): 

869 

870 if code in str(context.original_exception): 

871 context.is_disconnect = True 

872 

873 A handler function has two options for replacing 

874 the SQLAlchemy-constructed exception into one that is user 

875 defined. It can either raise this new exception directly, in 

876 which case all further event listeners are bypassed and the 

877 exception will be raised, after appropriate cleanup as taken 

878 place:: 

879 

880 @event.listens_for(Engine, "handle_error") 

881 def handle_exception(context): 

882 if isinstance(context.original_exception, 

883 psycopg2.OperationalError) and \ 

884 "failed" in str(context.original_exception): 

885 raise MySpecialException("failed operation") 

886 

887 .. warning:: Because the 

888 :meth:`_events.ConnectionEvents.handle_error` 

889 event specifically provides for exceptions to be re-thrown as 

890 the ultimate exception raised by the failed statement, 

891 **stack traces will be misleading** if the user-defined event 

892 handler itself fails and throws an unexpected exception; 

893 the stack trace may not illustrate the actual code line that 

894 failed! It is advised to code carefully here and use 

895 logging and/or inline debugging if unexpected exceptions are 

896 occurring. 

897 

898 Alternatively, a "chained" style of event handling can be 

899 used, by configuring the handler with the ``retval=True`` 

900 modifier and returning the new exception instance from the 

901 function. In this case, event handling will continue onto the 

902 next handler. The "chained" exception is available using 

903 :attr:`.ExceptionContext.chained_exception`:: 

904 

905 @event.listens_for(Engine, "handle_error", retval=True) 

906 def handle_exception(context): 

907 if context.chained_exception is not None and \ 

908 "special" in context.chained_exception.message: 

909 return MySpecialException("failed", 

910 cause=context.chained_exception) 

911 

912 Handlers that return ``None`` may be used within the chain; when 

913 a handler returns ``None``, the previous exception instance, 

914 if any, is maintained as the current exception that is passed onto the 

915 next handler. 

916 

917 When a custom exception is raised or returned, SQLAlchemy raises 

918 this new exception as-is, it is not wrapped by any SQLAlchemy 

919 object. If the exception is not a subclass of 

920 :class:`sqlalchemy.exc.StatementError`, 

921 certain features may not be available; currently this includes 

922 the ORM's feature of adding a detail hint about "autoflush" to 

923 exceptions raised within the autoflush process. 

924 

925 :param context: an :class:`.ExceptionContext` object. See this 

926 class for details on all available members. 

927 

928 .. versionadded:: 0.9.7 Added the 

929 :meth:`_events.ConnectionEvents.handle_error` hook. 

930 

931 .. versionchanged:: 1.1 The :meth:`.handle_error` event will now 

932 receive all exceptions that inherit from ``BaseException``, 

933 including ``SystemExit`` and ``KeyboardInterrupt``. The setting for 

934 :attr:`.ExceptionContext.is_disconnect` is ``True`` in this case and 

935 the default for 

936 :attr:`.ExceptionContext.invalidate_pool_on_disconnect` is 

937 ``False``. 

938 

939 .. versionchanged:: 1.0.0 The :meth:`.handle_error` event is now 

940 invoked when an :class:`_engine.Engine` fails during the initial 

941 call to :meth:`_engine.Engine.connect`, as well as when a 

942 :class:`_engine.Connection` object encounters an error during a 

943 reconnect operation. 

944 

945 .. versionchanged:: 1.0.0 The :meth:`.handle_error` event is 

946 not fired off when a dialect makes use of the 

947 ``skip_user_error_events`` execution option. This is used 

948 by dialects which intend to catch SQLAlchemy-specific exceptions 

949 within specific operations, such as when the MySQL dialect detects 

950 a table not present within the ``has_table()`` dialect method. 

951 Prior to 1.0.0, code which implements :meth:`.handle_error` needs 

952 to ensure that exceptions thrown in these scenarios are re-raised 

953 without modification. 

954 

955 """ 

956 

957 def engine_connect(self, conn, branch): 

958 """Intercept the creation of a new :class:`_engine.Connection`. 

959 

960 This event is called typically as the direct result of calling 

961 the :meth:`_engine.Engine.connect` method. 

962 

963 It differs from the :meth:`_events.PoolEvents.connect` method, which 

964 refers to the actual connection to a database at the DBAPI level; 

965 a DBAPI connection may be pooled and reused for many operations. 

966 In contrast, this event refers only to the production of a higher level 

967 :class:`_engine.Connection` wrapper around such a DBAPI connection. 

968 

969 It also differs from the :meth:`_events.PoolEvents.checkout` event 

970 in that it is specific to the :class:`_engine.Connection` object, 

971 not the 

972 DBAPI connection that :meth:`_events.PoolEvents.checkout` deals with, 

973 although 

974 this DBAPI connection is available here via the 

975 :attr:`_engine.Connection.connection` attribute. 

976 But note there can in fact 

977 be multiple :meth:`_events.PoolEvents.checkout` 

978 events within the lifespan 

979 of a single :class:`_engine.Connection` object, if that 

980 :class:`_engine.Connection` 

981 is invalidated and re-established. There can also be multiple 

982 :class:`_engine.Connection` 

983 objects generated for the same already-checked-out 

984 DBAPI connection, in the case that a "branch" of a 

985 :class:`_engine.Connection` 

986 is produced. 

987 

988 :param conn: :class:`_engine.Connection` object. 

989 :param branch: if True, this is a "branch" of an existing 

990 :class:`_engine.Connection`. A branch is generated within the course 

991 of a statement execution to invoke supplemental statements, most 

992 typically to pre-execute a SELECT of a default value for the purposes 

993 of an INSERT statement. 

994 

995 .. versionadded:: 0.9.0 

996 

997 .. seealso:: 

998 

999 :ref:`pool_disconnects_pessimistic` - illustrates how to use 

1000 :meth:`_events.ConnectionEvents.engine_connect` 

1001 to transparently ensure pooled connections are connected to the 

1002 database. 

1003 

1004 :meth:`_events.PoolEvents.checkout` 

1005 the lower-level pool checkout event 

1006 for an individual DBAPI connection 

1007 

1008 :meth:`_events.ConnectionEvents.set_connection_execution_options` 

1009 - a copy 

1010 of a :class:`_engine.Connection` is also made when the 

1011 :meth:`_engine.Connection.execution_options` method is called. 

1012 

1013 """ 

1014 

1015 def set_connection_execution_options(self, conn, opts): 

1016 """Intercept when the :meth:`_engine.Connection.execution_options` 

1017 method is called. 

1018 

1019 This method is called after the new :class:`_engine.Connection` 

1020 has been 

1021 produced, with the newly updated execution options collection, but 

1022 before the :class:`.Dialect` has acted upon any of those new options. 

1023 

1024 Note that this method is not called when a new 

1025 :class:`_engine.Connection` 

1026 is produced which is inheriting execution options from its parent 

1027 :class:`_engine.Engine`; to intercept this condition, use the 

1028 :meth:`_events.ConnectionEvents.engine_connect` event. 

1029 

1030 :param conn: The newly copied :class:`_engine.Connection` object 

1031 

1032 :param opts: dictionary of options that were passed to the 

1033 :meth:`_engine.Connection.execution_options` method. 

1034 

1035 .. versionadded:: 0.9.0 

1036 

1037 .. seealso:: 

1038 

1039 :meth:`_events.ConnectionEvents.set_engine_execution_options` 

1040 - event 

1041 which is called when :meth:`_engine.Engine.execution_options` 

1042 is called. 

1043 

1044 

1045 """ 

1046 

1047 def set_engine_execution_options(self, engine, opts): 

1048 """Intercept when the :meth:`_engine.Engine.execution_options` 

1049 method is called. 

1050 

1051 The :meth:`_engine.Engine.execution_options` method produces a shallow 

1052 copy of the :class:`_engine.Engine` which stores the new options. 

1053 That new 

1054 :class:`_engine.Engine` is passed here. 

1055 A particular application of this 

1056 method is to add a :meth:`_events.ConnectionEvents.engine_connect` 

1057 event 

1058 handler to the given :class:`_engine.Engine` 

1059 which will perform some per- 

1060 :class:`_engine.Connection` task specific to these execution options. 

1061 

1062 :param conn: The newly copied :class:`_engine.Engine` object 

1063 

1064 :param opts: dictionary of options that were passed to the 

1065 :meth:`_engine.Connection.execution_options` method. 

1066 

1067 .. versionadded:: 0.9.0 

1068 

1069 .. seealso:: 

1070 

1071 :meth:`_events.ConnectionEvents.set_connection_execution_options` 

1072 - event 

1073 which is called when :meth:`_engine.Connection.execution_options` 

1074 is 

1075 called. 

1076 

1077 """ 

1078 

1079 def engine_disposed(self, engine): 

1080 """Intercept when the :meth:`_engine.Engine.dispose` method is called. 

1081 

1082 The :meth:`_engine.Engine.dispose` method instructs the engine to 

1083 "dispose" of it's connection pool (e.g. :class:`_pool.Pool`), and 

1084 replaces it with a new one. Disposing of the old pool has the 

1085 effect that existing checked-in connections are closed. The new 

1086 pool does not establish any new connections until it is first used. 

1087 

1088 This event can be used to indicate that resources related to the 

1089 :class:`_engine.Engine` should also be cleaned up, 

1090 keeping in mind that the 

1091 :class:`_engine.Engine` 

1092 can still be used for new requests in which case 

1093 it re-acquires connection resources. 

1094 

1095 .. versionadded:: 1.0.5 

1096 

1097 """ 

1098 

1099 def begin(self, conn): 

1100 """Intercept begin() events. 

1101 

1102 :param conn: :class:`_engine.Connection` object 

1103 

1104 """ 

1105 

1106 def rollback(self, conn): 

1107 """Intercept rollback() events, as initiated by a 

1108 :class:`.Transaction`. 

1109 

1110 Note that the :class:`_pool.Pool` also "auto-rolls back" 

1111 a DBAPI connection upon checkin, if the ``reset_on_return`` 

1112 flag is set to its default value of ``'rollback'``. 

1113 To intercept this 

1114 rollback, use the :meth:`_events.PoolEvents.reset` hook. 

1115 

1116 :param conn: :class:`_engine.Connection` object 

1117 

1118 .. seealso:: 

1119 

1120 :meth:`_events.PoolEvents.reset` 

1121 

1122 """ 

1123 

1124 def commit(self, conn): 

1125 """Intercept commit() events, as initiated by a 

1126 :class:`.Transaction`. 

1127 

1128 Note that the :class:`_pool.Pool` may also "auto-commit" 

1129 a DBAPI connection upon checkin, if the ``reset_on_return`` 

1130 flag is set to the value ``'commit'``. To intercept this 

1131 commit, use the :meth:`_events.PoolEvents.reset` hook. 

1132 

1133 :param conn: :class:`_engine.Connection` object 

1134 """ 

1135 

1136 def savepoint(self, conn, name): 

1137 """Intercept savepoint() events. 

1138 

1139 :param conn: :class:`_engine.Connection` object 

1140 :param name: specified name used for the savepoint. 

1141 

1142 """ 

1143 

1144 def rollback_savepoint(self, conn, name, context): 

1145 """Intercept rollback_savepoint() events. 

1146 

1147 :param conn: :class:`_engine.Connection` object 

1148 :param name: specified name used for the savepoint. 

1149 :param context: :class:`.ExecutionContext` in use. May be ``None``. 

1150 

1151 """ 

1152 

1153 def release_savepoint(self, conn, name, context): 

1154 """Intercept release_savepoint() events. 

1155 

1156 :param conn: :class:`_engine.Connection` object 

1157 :param name: specified name used for the savepoint. 

1158 :param context: :class:`.ExecutionContext` in use. May be ``None``. 

1159 

1160 """ 

1161 

1162 def begin_twophase(self, conn, xid): 

1163 """Intercept begin_twophase() events. 

1164 

1165 :param conn: :class:`_engine.Connection` object 

1166 :param xid: two-phase XID identifier 

1167 

1168 """ 

1169 

1170 def prepare_twophase(self, conn, xid): 

1171 """Intercept prepare_twophase() events. 

1172 

1173 :param conn: :class:`_engine.Connection` object 

1174 :param xid: two-phase XID identifier 

1175 """ 

1176 

1177 def rollback_twophase(self, conn, xid, is_prepared): 

1178 """Intercept rollback_twophase() events. 

1179 

1180 :param conn: :class:`_engine.Connection` object 

1181 :param xid: two-phase XID identifier 

1182 :param is_prepared: boolean, indicates if 

1183 :meth:`.TwoPhaseTransaction.prepare` was called. 

1184 

1185 """ 

1186 

1187 def commit_twophase(self, conn, xid, is_prepared): 

1188 """Intercept commit_twophase() events. 

1189 

1190 :param conn: :class:`_engine.Connection` object 

1191 :param xid: two-phase XID identifier 

1192 :param is_prepared: boolean, indicates if 

1193 :meth:`.TwoPhaseTransaction.prepare` was called. 

1194 

1195 """ 

1196 

1197 

1198class DialectEvents(event.Events): 

1199 """event interface for execution-replacement functions. 

1200 

1201 These events allow direct instrumentation and replacement 

1202 of key dialect functions which interact with the DBAPI. 

1203 

1204 .. note:: 

1205 

1206 :class:`.DialectEvents` hooks should be considered **semi-public** 

1207 and experimental. 

1208 These hooks are not for general use and are only for those situations 

1209 where intricate re-statement of DBAPI mechanics must be injected onto 

1210 an existing dialect. For general-use statement-interception events, 

1211 please use the :class:`_events.ConnectionEvents` interface. 

1212 

1213 .. seealso:: 

1214 

1215 :meth:`_events.ConnectionEvents.before_cursor_execute` 

1216 

1217 :meth:`_events.ConnectionEvents.before_execute` 

1218 

1219 :meth:`_events.ConnectionEvents.after_cursor_execute` 

1220 

1221 :meth:`_events.ConnectionEvents.after_execute` 

1222 

1223 

1224 .. versionadded:: 0.9.4 

1225 

1226 """ 

1227 

1228 _target_class_doc = "SomeEngine" 

1229 _dispatch_target = Dialect 

1230 

1231 @classmethod 

1232 def _listen(cls, event_key, retval=False): 

1233 target = event_key.dispatch_target 

1234 

1235 target._has_events = True 

1236 event_key.base_listen() 

1237 

1238 @classmethod 

1239 def _accept_with(cls, target): 

1240 if isinstance(target, type): 

1241 if issubclass(target, Engine): 

1242 return Dialect 

1243 elif issubclass(target, Dialect): 

1244 return target 

1245 elif isinstance(target, Engine): 

1246 return target.dialect 

1247 else: 

1248 return target 

1249 

1250 def do_connect(self, dialect, conn_rec, cargs, cparams): 

1251 """Receive connection arguments before a connection is made. 

1252 

1253 Return a DBAPI connection to halt further events from invoking; 

1254 the returned connection will be used. 

1255 

1256 Alternatively, the event can manipulate the cargs and/or cparams 

1257 collections; cargs will always be a Python list that can be mutated 

1258 in-place and cparams a Python dictionary. Return None to 

1259 allow control to pass to the next event handler and ultimately 

1260 to allow the dialect to connect normally, given the updated 

1261 arguments. 

1262 

1263 .. versionadded:: 1.0.3 

1264 

1265 .. seealso:: 

1266 

1267 :ref:`custom_dbapi_args` 

1268 

1269 """ 

1270 

1271 def do_executemany(self, cursor, statement, parameters, context): 

1272 """Receive a cursor to have executemany() called. 

1273 

1274 Return the value True to halt further events from invoking, 

1275 and to indicate that the cursor execution has already taken 

1276 place within the event handler. 

1277 

1278 """ 

1279 

1280 def do_execute_no_params(self, cursor, statement, context): 

1281 """Receive a cursor to have execute() with no parameters called. 

1282 

1283 Return the value True to halt further events from invoking, 

1284 and to indicate that the cursor execution has already taken 

1285 place within the event handler. 

1286 

1287 """ 

1288 

1289 def do_execute(self, cursor, statement, parameters, context): 

1290 """Receive a cursor to have execute() called. 

1291 

1292 Return the value True to halt further events from invoking, 

1293 and to indicate that the cursor execution has already taken 

1294 place within the event handler. 

1295 

1296 """ 

1297 

1298 def do_setinputsizes( 

1299 self, inputsizes, cursor, statement, parameters, context 

1300 ): 

1301 """Receive the setinputsizes dictionary for possible modification. 

1302 

1303 This event is emitted in the case where the dialect makes use of the 

1304 DBAPI ``cursor.setinputsizes()`` method which passes information about 

1305 parameter binding for a particular statement. The given 

1306 ``inputsizes`` dictionary will contain :class:`.BindParameter` objects 

1307 as keys, linked to DBAPI-specific type objects as values; for 

1308 parameters that are not bound, they are added to the dictionary with 

1309 ``None`` as the value, which means the parameter will not be included 

1310 in the ultimate setinputsizes call. The event may be used to inspect 

1311 and/or log the datatypes that are being bound, as well as to modify the 

1312 dictionary in place. Parameters can be added, modified, or removed 

1313 from this dictionary. Callers will typically want to inspect the 

1314 :attr:`.BindParameter.type` attribute of the given bind objects in 

1315 order to make decisions about the DBAPI object. 

1316 

1317 After the event, the ``inputsizes`` dictionary is converted into 

1318 an appropriate datastructure to be passed to ``cursor.setinputsizes``; 

1319 either a list for a positional bound parameter execution style, 

1320 or a dictionary of string parameter keys to DBAPI type objects for 

1321 a named bound parameter execution style. 

1322 

1323 Most dialects **do not use** this method at all; the only built-in 

1324 dialect which uses this hook is the cx_Oracle dialect. The hook here 

1325 is made available so as to allow customization of how datatypes are set 

1326 up with the cx_Oracle DBAPI. 

1327 

1328 .. versionadded:: 1.2.9 

1329 

1330 .. seealso:: 

1331 

1332 :ref:`cx_oracle_setinputsizes` 

1333 

1334 """ 

1335 pass