1# sqlalchemy/sql/events.py
2# Copyright (C) 2005-2021 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 .base import SchemaEventTarget
9from .. import event
10
11
12class DDLEvents(event.Events):
13    """
14    Define event listeners for schema objects,
15    that is, :class:`.SchemaItem` and other :class:`.SchemaEventTarget`
16    subclasses, including :class:`_schema.MetaData`, :class:`_schema.Table`,
17    :class:`_schema.Column`.
18
19    :class:`_schema.MetaData` and :class:`_schema.Table` support events
20    specifically regarding when CREATE and DROP
21    DDL is emitted to the database.
22
23    Attachment events are also provided to customize
24    behavior whenever a child schema element is associated
25    with a parent, such as, when a :class:`_schema.Column` is associated
26    with its :class:`_schema.Table`, when a
27    :class:`_schema.ForeignKeyConstraint`
28    is associated with a :class:`_schema.Table`, etc.
29
30    Example using the ``after_create`` event::
31
32        from sqlalchemy import event
33        from sqlalchemy import Table, Column, Metadata, Integer
34
35        m = MetaData()
36        some_table = Table('some_table', m, Column('data', Integer))
37
38        def after_create(target, connection, **kw):
39            connection.execute(text(
40                "ALTER TABLE %s SET name=foo_%s" % (target.name, target.name)
41            ))
42
43        event.listen(some_table, "after_create", after_create)
44
45    DDL events integrate closely with the
46    :class:`.DDL` class and the :class:`.DDLElement` hierarchy
47    of DDL clause constructs, which are themselves appropriate
48    as listener callables::
49
50        from sqlalchemy import DDL
51        event.listen(
52            some_table,
53            "after_create",
54            DDL("ALTER TABLE %(table)s SET name=foo_%(table)s")
55        )
56
57    The methods here define the name of an event as well
58    as the names of members that are passed to listener
59    functions.
60
61    For all :class:`.DDLEvent` events, the ``propagate=True`` keyword argument
62    will ensure that a given event handler is propagated to copies of the
63    object, which are made when using the :meth:`_schema.Table.to_metadata`
64    method::
65
66        from sqlalchemy import DDL
67        event.listen(
68            some_table,
69            "after_create",
70            DDL("ALTER TABLE %(table)s SET name=foo_%(table)s"),
71            propagate=True
72        )
73
74        new_table = some_table.to_metadata(new_metadata)
75
76    The above :class:`.DDL` object will also be associated with the
77    :class:`_schema.Table` object represented by ``new_table``.
78
79    .. seealso::
80
81        :ref:`event_toplevel`
82
83        :class:`.DDLElement`
84
85        :class:`.DDL`
86
87        :ref:`schema_ddl_sequences`
88
89    """
90
91    _target_class_doc = "SomeSchemaClassOrObject"
92    _dispatch_target = SchemaEventTarget
93
94    def before_create(self, target, connection, **kw):
95        r"""Called before CREATE statements are emitted.
96
97        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table`
98         object which is the target of the event.
99        :param connection: the :class:`_engine.Connection` where the
100         CREATE statement or statements will be emitted.
101        :param \**kw: additional keyword arguments relevant
102         to the event.  The contents of this dictionary
103         may vary across releases, and include the
104         list of tables being generated for a metadata-level
105         event, the checkfirst flag, and other
106         elements used by internal events.
107
108        :func:`.event.listen` accepts the ``propagate=True``
109        modifier for this event; when True, the listener function will
110        be established for any copies made of the target object,
111        i.e. those copies that are generated when
112        :meth:`_schema.Table.to_metadata` is used.
113
114        :func:`.event.listen` accepts the ``insert=True``
115        modifier for this event; when True, the listener function will
116        be prepended to the internal list of events upon discovery, and execute
117        before registered listener functions that do not pass this argument.
118
119        """
120
121    def after_create(self, target, connection, **kw):
122        r"""Called after CREATE statements are emitted.
123
124        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table`
125         object which is the target of the event.
126        :param connection: the :class:`_engine.Connection` where the
127         CREATE statement or statements have been emitted.
128        :param \**kw: additional keyword arguments relevant
129         to the event.  The contents of this dictionary
130         may vary across releases, and include the
131         list of tables being generated for a metadata-level
132         event, the checkfirst flag, and other
133         elements used by internal events.
134
135        :func:`.event.listen` also accepts the ``propagate=True``
136        modifier for this event; when True, the listener function will
137        be established for any copies made of the target object,
138        i.e. those copies that are generated when
139        :meth:`_schema.Table.to_metadata` is used.
140
141        """
142
143    def before_drop(self, target, connection, **kw):
144        r"""Called before DROP statements are emitted.
145
146        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table`
147         object which is the target of the event.
148        :param connection: the :class:`_engine.Connection` where the
149         DROP statement or statements will be emitted.
150        :param \**kw: additional keyword arguments relevant
151         to the event.  The contents of this dictionary
152         may vary across releases, and include the
153         list of tables being generated for a metadata-level
154         event, the checkfirst flag, and other
155         elements used by internal events.
156
157        :func:`.event.listen` also accepts the ``propagate=True``
158        modifier for this event; when True, the listener function will
159        be established for any copies made of the target object,
160        i.e. those copies that are generated when
161        :meth:`_schema.Table.to_metadata` is used.
162
163        """
164
165    def after_drop(self, target, connection, **kw):
166        r"""Called after DROP statements are emitted.
167
168        :param target: the :class:`_schema.MetaData` or :class:`_schema.Table`
169         object which is the target of the event.
170        :param connection: the :class:`_engine.Connection` where the
171         DROP statement or statements have been emitted.
172        :param \**kw: additional keyword arguments relevant
173         to the event.  The contents of this dictionary
174         may vary across releases, and include the
175         list of tables being generated for a metadata-level
176         event, the checkfirst flag, and other
177         elements used by internal events.
178
179        :func:`.event.listen` also accepts the ``propagate=True``
180        modifier for this event; when True, the listener function will
181        be established for any copies made of the target object,
182        i.e. those copies that are generated when
183        :meth:`_schema.Table.to_metadata` is used.
184
185        """
186
187    def before_parent_attach(self, target, parent):
188        """Called before a :class:`.SchemaItem` is associated with
189        a parent :class:`.SchemaItem`.
190
191        :param target: the target object
192        :param parent: the parent to which the target is being attached.
193
194        :func:`.event.listen` also accepts the ``propagate=True``
195        modifier for this event; when True, the listener function will
196        be established for any copies made of the target object,
197        i.e. those copies that are generated when
198        :meth:`_schema.Table.to_metadata` is used.
199
200        """
201
202    def after_parent_attach(self, target, parent):
203        """Called after a :class:`.SchemaItem` is associated with
204        a parent :class:`.SchemaItem`.
205
206        :param target: the target object
207        :param parent: the parent to which the target is being attached.
208
209        :func:`.event.listen` also accepts the ``propagate=True``
210        modifier for this event; when True, the listener function will
211        be established for any copies made of the target object,
212        i.e. those copies that are generated when
213        :meth:`_schema.Table.to_metadata` is used.
214
215        """
216
217    def _sa_event_column_added_to_pk_constraint(self, const, col):
218        """internal event hook used for primary key naming convention
219        updates.
220
221        """
222
223    def column_reflect(self, inspector, table, column_info):
224        """Called for each unit of 'column info' retrieved when
225        a :class:`_schema.Table` is being reflected.
226
227        This event is most easily used by applying it to a specific
228        :class:`_schema.MetaData` instance, where it will take effect for
229        all :class:`_schema.Table` objects within that
230        :class:`_schema.MetaData` that undergo reflection::
231
232            metadata = MetaData()
233
234            @event.listens_for(metadata, 'column_reflect')
235            def receive_column_reflect(inspector, table, column_info):
236                # receives for all Table objects that are reflected
237                # under this MetaData
238
239
240            # will use the above event hook
241            my_table = Table("my_table", metadata, autoload_with=some_engine)
242
243
244        .. versionadded:: 1.4.0b2 The :meth:`_events.DDLEvents.column_reflect`
245           hook may now be applied to a :class:`_schema.MetaData` object as
246           well as the :class:`_schema.MetaData` class itself where it will
247           take place for all :class:`_schema.Table` objects associated with
248           the targeted :class:`_schema.MetaData`.
249
250        It may also be applied to the :class:`_schema.Table` class across
251        the board::
252
253            from sqlalchemy import Table
254
255            @event.listens_for(Table, 'column_reflect')
256            def receive_column_reflect(inspector, table, column_info):
257                # receives for all Table objects that are reflected
258
259        It can also be applied to a specific :class:`_schema.Table` at the
260        point that one is being reflected using the
261        :paramref:`_schema.Table.listeners` parameter::
262
263            t1 = Table(
264                "my_table",
265                autoload_with=some_engine,
266                listeners=[
267                    ('column_reflect', receive_column_reflect)
268                ]
269            )
270
271        A future release will allow it to be associated with a specific
272        :class:`_schema.MetaData` object as well.
273
274        The dictionary of column information as returned by the
275        dialect is passed, and can be modified.  The dictionary
276        is that returned in each element of the list returned
277        by :meth:`.reflection.Inspector.get_columns`:
278
279            * ``name`` - the column's name, is applied to the
280              :paramref:`_schema.Column.name` parameter
281
282            * ``type`` - the type of this column, which should be an instance
283              of :class:`~sqlalchemy.types.TypeEngine`, is applied to the
284              :paramref:`_schema.Column.type` parameter
285
286            * ``nullable`` - boolean flag if the column is NULL or NOT NULL,
287              is applied to the :paramref:`_schema.Column.nullable` parameter
288
289            * ``default`` - the column's server default value.  This is
290              normally specified as a plain string SQL expression, however the
291              event can pass a :class:`.FetchedValue`, :class:`.DefaultClause`,
292              or :func:`_expression.text` object as well.  Is applied to the
293              :paramref:`_schema.Column.server_default` parameter
294
295        The event is called before any action is taken against
296        this dictionary, and the contents can be modified; the following
297        additional keys may be added to the dictionary to further modify
298        how the :class:`_schema.Column` is constructed:
299
300
301            * ``key`` - the string key that will be used to access this
302              :class:`_schema.Column` in the ``.c`` collection; will be applied
303              to the :paramref:`_schema.Column.key` parameter. Is also used
304              for ORM mapping.  See the section
305              :ref:`mapper_automated_reflection_schemes` for an example.
306
307            * ``quote`` - force or un-force quoting on the column name;
308              is applied to the :paramref:`_schema.Column.quote` parameter.
309
310            * ``info`` - a dictionary of arbitrary data to follow along with
311              the :class:`_schema.Column`, is applied to the
312              :paramref:`_schema.Column.info` parameter.
313
314        :func:`.event.listen` also accepts the ``propagate=True``
315        modifier for this event; when True, the listener function will
316        be established for any copies made of the target object,
317        i.e. those copies that are generated when
318        :meth:`_schema.Table.to_metadata` is used.
319
320        .. seealso::
321
322            :ref:`mapper_automated_reflection_schemes` -
323            in the ORM mapping documentation
324
325            :ref:`automap_intercepting_columns` -
326            in the :ref:`automap_toplevel` documentation
327
328            :ref:`metadata_reflection_dbagnostic_types` - in
329            the :ref:`metadata_reflection_toplevel` documentation
330
331        """
332