1.. _alembic.operations.toplevel:
2
3=====================
4Operation Directives
5=====================
6
7.. note:: this section discusses the **internal API of Alembic** as regards
8   the internal system of defining migration operation directives.
9   This section is only useful for developers who wish to extend the
10   capabilities of Alembic.  For end-user guidance on Alembic migration
11   operations, please see :ref:`ops`.
12
13Within migration scripts, actual database migration operations are handled
14via an instance of :class:`.Operations`.   The :class:`.Operations` class
15lists out available migration operations that are linked to a
16:class:`.MigrationContext`, which communicates instructions originated
17by the :class:`.Operations` object into SQL that is sent to a database or SQL
18output stream.
19
20Most methods on the :class:`.Operations` class are generated dynamically
21using a "plugin" system, described in the next section
22:ref:`operation_plugins`.   Additionally, when Alembic migration scripts
23actually run, the methods on the current :class:`.Operations` object are
24proxied out to the ``alembic.op`` module, so that they are available
25using module-style access.
26
27For an overview of how to use an :class:`.Operations` object directly
28in programs, as well as for reference to the standard operation methods
29as well as "batch" methods, see :ref:`ops`.
30
31.. _operation_plugins:
32
33Operation Plugins
34=====================
35
36The Operations object is extensible using a plugin system.   This system
37allows one to add new ``op.<some_operation>`` methods at runtime.  The
38steps to use this system are to first create a subclass of
39:class:`.MigrateOperation`, register it using the :meth:`.Operations.register_operation`
40class decorator, then build a default "implementation" function which is
41established using the :meth:`.Operations.implementation_for` decorator.
42
43.. versionadded:: 0.8.0 - the :class:`.Operations` class is now an
44   open namespace that is extensible via the creation of new
45   :class:`.MigrateOperation` subclasses.
46
47Below we illustrate a very simple operation ``CreateSequenceOp`` which
48will implement a new method ``op.create_sequence()`` for use in
49migration scripts::
50
51    from alembic.operations import Operations, MigrateOperation
52
53    @Operations.register_operation("create_sequence")
54    class CreateSequenceOp(MigrateOperation):
55        """Create a SEQUENCE."""
56
57        def __init__(self, sequence_name, schema=None):
58            self.sequence_name = sequence_name
59            self.schema = schema
60
61        @classmethod
62        def create_sequence(cls, operations, sequence_name, **kw):
63            """Issue a "CREATE SEQUENCE" instruction."""
64
65            op = CreateSequenceOp(sequence_name, **kw)
66            return operations.invoke(op)
67
68        def reverse(self):
69            # only needed to support autogenerate
70            return DropSequenceOp(self.sequence_name, schema=self.schema)
71
72    @Operations.register_operation("drop_sequence")
73    class DropSequenceOp(MigrateOperation):
74        """Drop a SEQUENCE."""
75
76        def __init__(self, sequence_name, schema=None):
77            self.sequence_name = sequence_name
78            self.schema = schema
79
80        @classmethod
81        def drop_sequence(cls, operations, sequence_name, **kw):
82            """Issue a "DROP SEQUENCE" instruction."""
83
84            op = DropSequenceOp(sequence_name, **kw)
85            return operations.invoke(op)
86
87        def reverse(self):
88            # only needed to support autogenerate
89            return CreateSequenceOp(self.sequence_name, schema=self.schema)
90
91Above, the ``CreateSequenceOp`` and ``DropSequenceOp`` classes represent
92new operations that will
93be available as ``op.create_sequence()`` and ``op.drop_sequence()``.
94The reason the operations
95are represented as stateful classes is so that an operation and a specific
96set of arguments can be represented generically; the state can then correspond
97to different kinds of operations, such as invoking the instruction against
98a database, or autogenerating Python code for the operation into a
99script.
100
101In order to establish the migrate-script behavior of the new operations,
102we use the :meth:`.Operations.implementation_for` decorator::
103
104    @Operations.implementation_for(CreateSequenceOp)
105    def create_sequence(operations, operation):
106        if operation.schema is not None:
107            name = "%s.%s" % (operation.schema, operation.sequence_name)
108        else:
109            name = operation.sequence_name
110        operations.execute("CREATE SEQUENCE %s" % name)
111
112
113    @Operations.implementation_for(DropSequenceOp)
114    def drop_sequence(operations, operation):
115        if operation.schema is not None:
116            name = "%s.%s" % (operation.schema, operation.sequence_name)
117        else:
118            name = operation.sequence_name
119        operations.execute("DROP SEQUENCE %s" % name)
120
121Above, we use the simplest possible technique of invoking our DDL, which
122is just to call :meth:`.Operations.execute` with literal SQL.  If this is
123all a custom operation needs, then this is fine.  However, options for
124more comprehensive support include building out a custom SQL construct,
125as documented at :ref:`sqlalchemy.ext.compiler_toplevel`.
126
127With the above two steps, a migration script can now use new methods
128``op.create_sequence()`` and ``op.drop_sequence()`` that will proxy to
129our object as a classmethod::
130
131    def upgrade():
132        op.create_sequence("my_sequence")
133
134    def downgrade():
135        op.drop_sequence("my_sequence")
136
137The registration of new operations only needs to occur in time for the
138``env.py`` script to invoke :meth:`.MigrationContext.run_migrations`;
139within the module level of the ``env.py`` script is sufficient.
140
141.. seealso::
142
143    :ref:`autogen_custom_ops` - how to add autogenerate support to
144    custom operations.
145
146.. versionadded:: 0.8 - the migration operations available via the
147   :class:`.Operations` class as well as the ``alembic.op`` namespace
148   is now extensible using a plugin system.
149
150
151.. _operation_objects:
152.. _alembic.operations.ops.toplevel:
153
154Built-in Operation Objects
155==============================
156
157The migration operations present on :class:`.Operations` are themselves
158delivered via operation objects that represent an operation and its
159arguments.   All operations descend from the :class:`.MigrateOperation`
160class, and are registered with the :class:`.Operations` class using
161the :meth:`.Operations.register_operation` class decorator.  The
162:class:`.MigrateOperation` objects also serve as the basis for how the
163autogenerate system renders new migration scripts.
164
165.. seealso::
166
167    :ref:`operation_plugins`
168
169    :ref:`customizing_revision`
170
171The built-in operation objects are listed below.
172
173.. automodule:: alembic.operations.ops
174    :members:
175