else:
run_migrations_online()
+.. _batch:
+
+Running SQLite "Batch" Migrations
+=================================
+
+The SQLite database presents an inconvenient challenge to migration tools,
+in that it has almost no support for the ALTER statement upon which
+relational schema migrations rely upon. The rationale for this stems from
+philosophical and architecural concerns within SQLite, and they are unlikely
+to be changed.
+
+Migration tools are instead expected to produce copies of SQLite tables that
+correspond to the new structure, to transfer the data from the existing
+table to the new one, then drop the old table. In order to accommodate this
+workflow in a way that is reasonably predictable, while remaining compatible
+with other databases, Alembic provides the "batch" operations context.
+This context provides the table recreate plus data copy operation for SQLite,
+and can also be instructed to use this flow for other databases as well,
+providing an alternative scheme in some cases where the blocking behavior of
+some ALTER statements is to be avoided.
+
+Within this context, a relational table is named, and then a series of
+any number of mutation operations to that table then proceed within the
+block. When the context is complete, the above mentioned table-recreate
+and data copy operation proceeds, but *only* if appropriate for the target
+database; for other databases, the batch context proceeds using traditional
+ALTER statements, unless the context is set to "always".
+
+TODO: "recreate" doesn't work very well for Postgresql due to constraint naming
+TODO: caveats, beta status
+
+
+
.. _tutorial_constraint_names:
The Importance of Naming Constraints
from contextlib import contextmanager
import re
+from alembic.testing import exclusions
from alembic.testing import TestBase, eq_, config
from alembic.testing.fixtures import op_fixture
from alembic.testing import mock
{"id": 4, "data": "9.46", "x": 8, 'data2': 'hi'},
{"id": 5, "data": "d5", "x": 9, 'data2': 'hi'}
])
+
+
+class BatchRoundTripMySQLTest(BatchRoundTripTest):
+ __only_on__ = "mysql"
+
+ @exclusions.fails()
+ def test_rename_column_pk(self):
+ super(BatchRoundTripMySQLTest, self).test_rename_column_pk()
+
+ @exclusions.fails()
+ def test_rename_column(self):
+ super(BatchRoundTripMySQLTest, self).test_rename_column()
+
+ @exclusions.fails()
+ def test_change_type(self):
+ super(BatchRoundTripMySQLTest, self).test_change_type()
+
+
+class BatchRoundTripPostgresqlTest(BatchRoundTripTest):
+ __only_on__ = "postgresql"
+
+ @exclusions.fails()
+ def test_change_type(self):
+ super(BatchRoundTripPostgresqlTest, self).test_change_type()
+
+ @exclusions.fails()
+ def test_add_column_recreate(self):
+ super(BatchRoundTripPostgresqlTest, self).test_add_column_recreate()