Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/sql/events.py: 71%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

24 statements  

1# sql/events.py 

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

3# <see AUTHORS file> 

4# 

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

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

7 

8from __future__ import annotations 

9 

10from typing import Any 

11from typing import TYPE_CHECKING 

12 

13from .base import SchemaEventTarget 

14from .. import event 

15 

16if TYPE_CHECKING: 

17 from .schema import Column 

18 from .schema import Constraint 

19 from .schema import SchemaItem 

20 from .schema import Table 

21 from ..engine.base import Connection 

22 from ..engine.interfaces import ReflectedColumn 

23 from ..engine.reflection import Inspector 

24 

25 

26class DDLEvents(event.Events[SchemaEventTarget]): 

27 """ 

28 Define event listeners for schema objects, 

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

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

31 :class:`_schema.Column`, etc. 

32 

33 **Create / Drop Events** 

34 

35 Events emitted when CREATE and DROP commands are emitted to the database. 

36 The event hooks in this category include :meth:`.DDLEvents.before_create`, 

37 :meth:`.DDLEvents.after_create`, :meth:`.DDLEvents.before_drop`, and 

38 :meth:`.DDLEvents.after_drop`. 

39 

40 These events are emitted when using schema-level methods such as 

41 :meth:`.MetaData.create_all` and :meth:`.MetaData.drop_all`. Per-object 

42 create/drop methods such as :meth:`.Table.create`, :meth:`.Table.drop`, 

43 :meth:`.Index.create` are also included, as well as dialect-specific 

44 methods such as :meth:`_postgresql.ENUM.create`. 

45 

46 .. versionadded:: 2.0 :class:`.DDLEvents` event hooks now take place 

47 for non-table objects including constraints, indexes, and 

48 dialect-specific schema types. 

49 

50 Event hooks may be attached directly to a :class:`_schema.Table` object or 

51 to a :class:`_schema.MetaData` collection, as well as to any 

52 :class:`.SchemaItem` class or object that can be individually created and 

53 dropped using a distinct SQL command. Such classes include :class:`.Index`, 

54 :class:`.Sequence`, and dialect-specific classes such as 

55 :class:`_postgresql.ENUM`. 

56 

57 Example using the :meth:`.DDLEvents.after_create` event, where a custom 

58 event hook will emit an ``ALTER TABLE`` command on the current connection, 

59 after ``CREATE TABLE`` is emitted:: 

60 

61 from sqlalchemy import create_engine 

62 from sqlalchemy import event 

63 from sqlalchemy import Table, Column, Metadata, Integer 

64 

65 m = MetaData() 

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

67 

68 @event.listens_for(some_table, "after_create") 

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

70 connection.execute(text( 

71 "ALTER TABLE %s SET name=foo_%s" % (target.name, target.name) 

72 )) 

73 

74 

75 some_engine = create_engine("postgresql://scott:tiger@host/test") 

76 

77 # will emit "CREATE TABLE some_table" as well as the above 

78 # "ALTER TABLE" statement afterwards 

79 m.create_all(some_engine) 

80 

81 Constraint objects such as :class:`.ForeignKeyConstraint`, 

82 :class:`.UniqueConstraint`, :class:`.CheckConstraint` may also be 

83 subscribed to these events, however they will **not** normally produce 

84 events as these objects are usually rendered inline within an 

85 enclosing ``CREATE TABLE`` statement and implicitly dropped from a 

86 ``DROP TABLE`` statement. 

87 

88 For the :class:`.Index` construct, the event hook will be emitted 

89 for ``CREATE INDEX``, however SQLAlchemy does not normally emit 

90 ``DROP INDEX`` when dropping tables as this is again implicit within the 

91 ``DROP TABLE`` statement. 

92 

93 .. versionadded:: 2.0 Support for :class:`.SchemaItem` objects 

94 for create/drop events was expanded from its previous support for 

95 :class:`.MetaData` and :class:`.Table` to also include 

96 :class:`.Constraint` and all subclasses, :class:`.Index`, 

97 :class:`.Sequence` and some type-related constructs such as 

98 :class:`_postgresql.ENUM`. 

99 

100 .. note:: These event hooks are only emitted within the scope of 

101 SQLAlchemy's create/drop methods; they are not necessarily supported 

102 by tools such as `alembic <https://alembic.sqlalchemy.org>`_. 

103 

104 

105 **Attachment Events** 

106 

107 Attachment events are provided to customize 

108 behavior whenever a child schema element is associated 

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

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

111 :class:`_schema.ForeignKeyConstraint` 

112 is associated with a :class:`_schema.Table`, etc. These events include 

113 :meth:`.DDLEvents.before_parent_attach` and 

114 :meth:`.DDLEvents.after_parent_attach`. 

115 

116 **Reflection Events** 

117 

118 The :meth:`.DDLEvents.column_reflect` event is used to intercept 

119 and modify the in-Python definition of database columns when 

120 :term:`reflection` of database tables proceeds. 

121 

122 **Use with Generic DDL** 

123 

124 DDL events integrate closely with the 

125 :class:`.DDL` class and the :class:`.ExecutableDDLElement` hierarchy 

126 of DDL clause constructs, which are themselves appropriate 

127 as listener callables:: 

128 

129 from sqlalchemy import DDL 

130 event.listen( 

131 some_table, 

132 "after_create", 

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

134 ) 

135 

136 **Event Propagation to MetaData Copies** 

137 

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

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

140 object, which are made when using the :meth:`_schema.Table.to_metadata` 

141 method:: 

142 

143 from sqlalchemy import DDL 

144 

145 metadata = MetaData() 

146 some_table = Table("some_table", metadata, Column("data", Integer)) 

147 

148 event.listen( 

149 some_table, 

150 "after_create", 

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

152 propagate=True 

153 ) 

154 

155 new_metadata = MetaData() 

156 new_table = some_table.to_metadata(new_metadata) 

157 

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

159 :meth:`.DDLEvents.after_create` event for both the ``some_table`` and 

160 the ``new_table`` :class:`.Table` objects. 

161 

162 .. seealso:: 

163 

164 :ref:`event_toplevel` 

165 

166 :class:`.ExecutableDDLElement` 

167 

168 :class:`.DDL` 

169 

170 :ref:`schema_ddl_sequences` 

171 

172 """ 

173 

174 _target_class_doc = "SomeSchemaClassOrObject" 

175 _dispatch_target = SchemaEventTarget 

176 

177 def before_create( 

178 self, target: SchemaEventTarget, connection: Connection, **kw: Any 

179 ) -> None: 

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

181 

182 :param target: the :class:`.SchemaObject`, such as a 

183 :class:`_schema.MetaData` or :class:`_schema.Table` 

184 but also including all create/drop objects such as 

185 :class:`.Index`, :class:`.Sequence`, etc., 

186 object which is the target of the event. 

187 

188 .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects 

189 was added. 

190 

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

192 CREATE statement or statements will be emitted. 

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

194 to the event. The contents of this dictionary 

195 may vary across releases, and include the 

196 list of tables being generated for a metadata-level 

197 event, the checkfirst flag, and other 

198 elements used by internal events. 

199 

200 :func:`.event.listen` accepts the ``propagate=True`` 

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

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

203 i.e. those copies that are generated when 

204 :meth:`_schema.Table.to_metadata` is used. 

205 

206 :func:`.event.listen` accepts the ``insert=True`` 

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

208 be prepended to the internal list of events upon discovery, and execute 

209 before registered listener functions that do not pass this argument. 

210 

211 """ 

212 

213 def after_create( 

214 self, target: SchemaEventTarget, connection: Connection, **kw: Any 

215 ) -> None: 

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

217 

218 :param target: the :class:`.SchemaObject`, such as a 

219 :class:`_schema.MetaData` or :class:`_schema.Table` 

220 but also including all create/drop objects such as 

221 :class:`.Index`, :class:`.Sequence`, etc., 

222 object which is the target of the event. 

223 

224 .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects 

225 was added. 

226 

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

228 CREATE statement or statements have been emitted. 

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

230 to the event. The contents of this dictionary 

231 may vary across releases, and include the 

232 list of tables being generated for a metadata-level 

233 event, the checkfirst flag, and other 

234 elements used by internal events. 

235 

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

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

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

239 i.e. those copies that are generated when 

240 :meth:`_schema.Table.to_metadata` is used. 

241 

242 """ 

243 

244 def before_drop( 

245 self, target: SchemaEventTarget, connection: Connection, **kw: Any 

246 ) -> None: 

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

248 

249 :param target: the :class:`.SchemaObject`, such as a 

250 :class:`_schema.MetaData` or :class:`_schema.Table` 

251 but also including all create/drop objects such as 

252 :class:`.Index`, :class:`.Sequence`, etc., 

253 object which is the target of the event. 

254 

255 .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects 

256 was added. 

257 

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

259 DROP statement or statements will be emitted. 

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

261 to the event. The contents of this dictionary 

262 may vary across releases, and include the 

263 list of tables being generated for a metadata-level 

264 event, the checkfirst flag, and other 

265 elements used by internal events. 

266 

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

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

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

270 i.e. those copies that are generated when 

271 :meth:`_schema.Table.to_metadata` is used. 

272 

273 """ 

274 

275 def after_drop( 

276 self, target: SchemaEventTarget, connection: Connection, **kw: Any 

277 ) -> None: 

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

279 

280 :param target: the :class:`.SchemaObject`, such as a 

281 :class:`_schema.MetaData` or :class:`_schema.Table` 

282 but also including all create/drop objects such as 

283 :class:`.Index`, :class:`.Sequence`, etc., 

284 object which is the target of the event. 

285 

286 .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects 

287 was added. 

288 

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

290 DROP statement or statements have been emitted. 

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

292 to the event. The contents of this dictionary 

293 may vary across releases, and include the 

294 list of tables being generated for a metadata-level 

295 event, the checkfirst flag, and other 

296 elements used by internal events. 

297 

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

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

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

301 i.e. those copies that are generated when 

302 :meth:`_schema.Table.to_metadata` is used. 

303 

304 """ 

305 

306 def before_parent_attach( 

307 self, target: SchemaEventTarget, parent: SchemaItem 

308 ) -> None: 

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

310 a parent :class:`.SchemaItem`. 

311 

312 :param target: the target object 

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

314 

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

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

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

318 i.e. those copies that are generated when 

319 :meth:`_schema.Table.to_metadata` is used. 

320 

321 """ 

322 

323 def after_parent_attach( 

324 self, target: SchemaEventTarget, parent: SchemaItem 

325 ) -> None: 

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

327 a parent :class:`.SchemaItem`. 

328 

329 :param target: the target object 

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

331 

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

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

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

335 i.e. those copies that are generated when 

336 :meth:`_schema.Table.to_metadata` is used. 

337 

338 """ 

339 

340 def _sa_event_column_added_to_pk_constraint( 

341 self, const: Constraint, col: Column[Any] 

342 ) -> None: 

343 """internal event hook used for primary key naming convention 

344 updates. 

345 

346 """ 

347 

348 def column_reflect( 

349 self, inspector: Inspector, table: Table, column_info: ReflectedColumn 

350 ) -> None: 

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

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

353 

354 This event is most easily used by applying it to a specific 

355 :class:`_schema.MetaData` instance, where it will take effect for 

356 all :class:`_schema.Table` objects within that 

357 :class:`_schema.MetaData` that undergo reflection:: 

358 

359 metadata = MetaData() 

360 

361 @event.listens_for(metadata, 'column_reflect') 

362 def receive_column_reflect(inspector, table, column_info): 

363 # receives for all Table objects that are reflected 

364 # under this MetaData 

365 

366 

367 # will use the above event hook 

368 my_table = Table("my_table", metadata, autoload_with=some_engine) 

369 

370 

371 .. versionadded:: 1.4.0b2 The :meth:`_events.DDLEvents.column_reflect` 

372 hook may now be applied to a :class:`_schema.MetaData` object as 

373 well as the :class:`_schema.MetaData` class itself where it will 

374 take place for all :class:`_schema.Table` objects associated with 

375 the targeted :class:`_schema.MetaData`. 

376 

377 It may also be applied to the :class:`_schema.Table` class across 

378 the board:: 

379 

380 from sqlalchemy import Table 

381 

382 @event.listens_for(Table, 'column_reflect') 

383 def receive_column_reflect(inspector, table, column_info): 

384 # receives for all Table objects that are reflected 

385 

386 It can also be applied to a specific :class:`_schema.Table` at the 

387 point that one is being reflected using the 

388 :paramref:`_schema.Table.listeners` parameter:: 

389 

390 t1 = Table( 

391 "my_table", 

392 autoload_with=some_engine, 

393 listeners=[ 

394 ('column_reflect', receive_column_reflect) 

395 ] 

396 ) 

397 

398 The dictionary of column information as returned by the 

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

400 is that returned in each element of the list returned 

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

402 

403 * ``name`` - the column's name, is applied to the 

404 :paramref:`_schema.Column.name` parameter 

405 

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

407 of :class:`~sqlalchemy.types.TypeEngine`, is applied to the 

408 :paramref:`_schema.Column.type` parameter 

409 

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

411 is applied to the :paramref:`_schema.Column.nullable` parameter 

412 

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

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

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

416 or :func:`_expression.text` object as well. Is applied to the 

417 :paramref:`_schema.Column.server_default` parameter 

418 

419 The event is called before any action is taken against 

420 this dictionary, and the contents can be modified; the following 

421 additional keys may be added to the dictionary to further modify 

422 how the :class:`_schema.Column` is constructed: 

423 

424 

425 * ``key`` - the string key that will be used to access this 

426 :class:`_schema.Column` in the ``.c`` collection; will be applied 

427 to the :paramref:`_schema.Column.key` parameter. Is also used 

428 for ORM mapping. See the section 

429 :ref:`mapper_automated_reflection_schemes` for an example. 

430 

431 * ``quote`` - force or un-force quoting on the column name; 

432 is applied to the :paramref:`_schema.Column.quote` parameter. 

433 

434 * ``info`` - a dictionary of arbitrary data to follow along with 

435 the :class:`_schema.Column`, is applied to the 

436 :paramref:`_schema.Column.info` parameter. 

437 

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

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

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

441 i.e. those copies that are generated when 

442 :meth:`_schema.Table.to_metadata` is used. 

443 

444 .. seealso:: 

445 

446 :ref:`mapper_automated_reflection_schemes` - 

447 in the ORM mapping documentation 

448 

449 :ref:`automap_intercepting_columns` - 

450 in the :ref:`automap_toplevel` documentation 

451 

452 :ref:`metadata_reflection_dbagnostic_types` - in 

453 the :ref:`metadata_reflection_toplevel` documentation 

454 

455 """