summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-03-03 10:12:09 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2020-03-03 10:12:45 -0500
commit94ac796772b25ae3aafb83a846158fe8c3729c90 (patch)
treed6706c17da388a8a73f0279f49e44c91f58e4548 /docs
parentdfb82e2cc13f6c508543a3ac47d18ec7ae54887a (diff)
downloadalembic-94ac796772b25ae3aafb83a846158fe8c3729c90.tar.gz
Add custom table column sorting example
Change-Id: Ie953ba34ed8e6cbf90e3070494279174ebca5d1a
Diffstat (limited to 'docs')
-rw-r--r--docs/build/api/autogenerate.rst10
-rw-r--r--docs/build/cookbook.rst96
2 files changed, 106 insertions, 0 deletions
diff --git a/docs/build/api/autogenerate.rst b/docs/build/api/autogenerate.rst
index c4678e1..230d42d 100644
--- a/docs/build/api/autogenerate.rst
+++ b/docs/build/api/autogenerate.rst
@@ -203,6 +203,16 @@ structure consisting of zero or more :class:`.MigrationScript` directives.
The :func:`.command.revision` command will then produce scripts corresponding
to whatever is in this list.
+.. seealso::
+
+ More examples of using :paramref:`.EnvironmentContext.configure.process_revision_directives`
+
+ :ref:`cookbook_no_empty_migrations`
+
+ :ref:`cookbook_dont_emit_drop_index`
+
+ :ref:`cookbook_custom_sorting_create_table`
+
.. autofunction:: alembic.autogenerate.render_python_code
.. _autogen_rewriter:
diff --git a/docs/build/cookbook.rst b/docs/build/cookbook.rst
index 0d034af..83cabdb 100644
--- a/docs/build/cookbook.rst
+++ b/docs/build/cookbook.rst
@@ -774,6 +774,8 @@ recreated again within the downgrade for this migration::
INFO [sqlalchemy.engine.base.Engine] {}
INFO [sqlalchemy.engine.base.Engine] COMMIT
+.. _cookbook_no_empty_migrations:
+
Don't Generate Empty Migrations with Autogenerate
=================================================
@@ -809,6 +811,8 @@ any operations::
with context.begin_transaction():
context.run_migrations()
+.. _cookbook_dont_emit_drop_index:
+
Don't emit DROP INDEX when the table is to be dropped as well
=============================================================
@@ -934,6 +938,98 @@ the local :class:`.MetaData` collection::
include_object = include_object
)
+.. _cookbook_custom_sorting_create_table:
+
+Apply Custom Sorting to Table Columns within CREATE TABLE
+==========================================================
+
+This example illustrates use of the :class:`.Rewriter` object introduced
+at :ref:`autogen_rewriter`. While the rewriter grants access to the
+individual :class:`.ops.MigrateOperation` objects, there are sometimes some
+special techniques required to get around some structural limitations that
+are present.
+
+One is when trying to reorganize the order of columns in a
+table within a :class:`.ops.CreateTableOp` directive. This directive, when
+generated by autogenerate, actually holds onto the original :class:`.Table`
+object as the source of its information, so attempting to reorder the
+:attr:`.ops.CreateTableOp.columns` collection will usually have no effect.
+Instead, a new :class:`.ops.CreateTableOp` object may be constructed with the
+new ordering. However, a second issue is that the :class:`.Column` objects
+inside will already be associated with the :class:`.Table` that is from the
+model being autogenerated, meaning they can't be reassigned directly to a new
+:class:`.Table`. To get around this, we can copy all the columns and constraints
+using methods like :meth:`.Column.copy`.
+
+Below we use :class:`.Rewriter` to create a new :class:`.ops.CreateTableOp`
+directive and to copy the :class:`.Column` objects from one into another,
+copying each column or constraint object and applying a new sorting scheme::
+
+ # in env.py
+
+ from alembic.operations import ops
+ from alembic.autogenerate import rewriter
+
+ writer = rewriter.Rewriter()
+
+ @writer.rewrites(ops.CreateTableOp)
+ def order_columns(context, revision, op):
+
+ special_names = {"id": -100, "created_at": 1001, "updated_at": 1002}
+
+ cols_by_key = [
+ (
+ special_names.get(col.key, index)
+ if isinstance(col, Column)
+ else 2000,
+ col.copy(),
+ )
+ for index, col in enumerate(op.columns)
+ ]
+
+ columns = [
+ col for idx, col in sorted(cols_by_key, key=lambda entry: entry[0])
+ ]
+ return ops.CreateTableOp(
+ op.table_name, columns, schema=op.schema, **op.kw)
+
+
+ # ...
+
+ context.configure(
+ # ...
+ process_revision_directives=writer
+ )
+
+
+Above, when we apply the ``writer`` to a table such as::
+
+ Table(
+ "my_table",
+ m,
+ Column("data", String(50)),
+ Column("created_at", DateTime),
+ Column("id", Integer, primary_key=True),
+ Column("updated_at", DateTime),
+ UniqueConstraint("data", name="uq_data")
+ )
+
+
+This will render in the autogenerated file as::
+
+ def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.create_table(
+ "my_table",
+ sa.Column("id", sa.Integer(), nullable=False),
+ sa.Column("data", sa.String(length=50), nullable=True),
+ sa.Column("created_at", sa.DateTime(), nullable=True),
+ sa.Column("updated_at", sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint("id"),
+ sa.UniqueConstraint("data", name="uq_data"),
+ )
+ # ### end Alembic commands ###
+
Don't emit CREATE TABLE statements for Views
============================================