summaryrefslogtreecommitdiff
path: root/docs/build/api/operations.rst
blob: 773cf6e0793e7e8edff48f1f4d3b97ea85ca7e8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
=====================
The Operations Object
=====================

Within migration scripts, actual database migration operations are handled
via an instance of :class:`.Operations`.   The :class:`.Operations` class
lists out available migration operations that are linked to a
:class:`.MigrationContext`, which communicates instructions originated
by the :class:`.Operations` object into SQL that is sent to a database or SQL
output stream.

Most methods on the :class:`.Operations` class are generated dynamically
using a "plugin" system, described in the next section
:ref:`operation_plugins`.   Additionally, when Alembic migration scripts
actually run, the methods on the current :class:`.Operations` object are
proxied out to the :mod:`alembic.op` module, so that they are available
using module-style access.

For an overview of how to use an :class:`.Operations` object directly
in programs, as well as for reference to the standard operation methods
as well as "batch" methods, see :ref:`ops`.

.. _operation_plugins:

Operation Plugins
=====================

The Operations object is extensible using a plugin system.   This system
allows one to add new ``op.<some_operation>`` methods at runtime.  The
steps to use this system are to first create a subclass of
:class:`.MigrateOperation`, register it using the :meth:`.Operations.register_operation`
class decorator, then build a default "implementation" function which is
established using the :meth:`.Operations.implementation_for` decorator.

.. versionadded:: 0.8.0 - the :class:`.Operations` class is now an
   open namespace that is extensible via the creation of new
   :class:`.MigrateOperation` subclasses.

Below we illustrate a very simple operation ``CreateSequenceOp`` which
will implement a new method ``op.create_sequence()`` for use in
migration scripts::

    from alembic.operations import Operations, MigrateOperation

    @Operations.register_operation("create_sequence")
    class CreateSequenceOp(MigrateOperation):
        """Create a SEQUENCE."""

        def __init__(self, sequence_name, **kw):
            self.sequence_name = sequence_name
            self.kw = kw

        @classmethod
        def create_sequence(cls, operations, sequence_name, **kw):
            """Issue a "CREATE SEQUENCE" instruction."""

            op = CreateSequenceOp(sequence_name, **kw)
            return operations.invoke(op)

Above, the ``CreateSequenceOp`` class represents a new operation that will
be available as ``op.create_sequence()``.   The reason the operation
is represented as a stateful class is so that an operation and a specific
set of arguments can be represented generically; the state can then correspond
to different kinds of operations, such as invoking the instruction against
a database, or autogenerating Python code for the operation into a
script.

In order to establish the migrate-script behavior of the new operation,
we use the :meth:`.Operations.implementation_for` decorator::

    @Operations.implementation_for(CreateSequenceOp)
    def create_sequence(operations, operation):
        operations.execute("CREATE SEQUENCE %s" % operation.sequence_name)

Above, we use the simplest possible technique of invoking our DDL, which
is just to call :meth:`.Operations.execute` with literal SQL.  If this is
all a custom operation needs, then this is fine.  However, options for
more comprehensive support include building out a custom SQL construct,
as documented at :ref:`sqlalchemy.ext.compiles`.

With the above two steps, a migration script can now use a new method
``op.create_sequence()`` that will proxy to our object as a classmethod::

    def upgrade():
        op.create_sequence("my_sequence")

The registration of new operations only needs to occur in time for the
``env.py`` script to invoke :meth:`.MigrationContext.run_migrations`;
within the module level of the ``env.py`` script is sufficient.


.. versionadded:: 0.8 - the migration operations available via the
   :class:`.Operations` class as well as the :mod:`alembic.op` namespace
   is now extensible using a plugin system.


.. _operation_objects:

Built-in Operation Objects
==============================

The migration operations present on :class:`.Operations` are themselves
delivered via operation objects that represent an operation and its
arguments.   All operations descend from the :class:`.MigrateOperation`
class, and are registered with the :class:`.Operations` class using
the :meth:`.Operations.register_operation` class decorator.  The
:class:`.MigrateOperation` objects also serve as the basis for how the
autogenerate system renders new migration scripts.

.. seealso::

    :ref:`operation_plugins`

    :ref:`customizing_revision`

The built-in operation objects are listed below.

.. automodule:: alembic.operations.ops
    :members: