summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alembic/autogenerate/render.py67
-rw-r--r--alembic/batch.py22
-rw-r--r--alembic/operations.py30
-rw-r--r--tests/test_autogenerate.py4
-rw-r--r--tests/test_batch.py55
5 files changed, 129 insertions, 49 deletions
diff --git a/alembic/autogenerate/render.py b/alembic/autogenerate/render.py
index d14842e..3bfa9c0 100644
--- a/alembic/autogenerate/render.py
+++ b/alembic/autogenerate/render.py
@@ -137,24 +137,32 @@ def _add_index(index, autogen_context):
:class:`~sqlalchemy.schema.Index` instance.
"""
- text = "%(prefix)screate_index(%(name)r, %(table)r, [%(columns)s], "\
- "unique=%(unique)r%(schema)s%(kwargs)s)" % {
- 'prefix': _alembic_autogenerate_prefix(autogen_context),
- 'name': _render_gen_name(autogen_context, index.name),
- 'table': _ident(index.table.name),
- 'columns': ", ".join(
- _get_index_rendered_expressions(index, autogen_context)),
- 'unique': index.unique or False,
- 'schema': (", schema=%r" % _ident(index.table.schema))
- if index.table.schema else '',
- 'kwargs': (
- ', ' +
- ', '.join(
- ["%s=%s" %
- (key, _render_potential_expr(val, autogen_context))
- for key, val in index.kwargs.items()]))
- if len(index.kwargs) else ''
- }
+ has_batch = 'batch_prefix' in autogen_context
+
+ if has_batch:
+ tmpl = "%(prefix)screate_index(%(name)r, [%(columns)s], "\
+ "unique=%(unique)r%(kwargs)s)"
+ else:
+ tmpl = "%(prefix)screate_index(%(name)r, %(table)r, [%(columns)s], "\
+ "unique=%(unique)r%(schema)s%(kwargs)s)"
+
+ text = tmpl % {
+ 'prefix': _alembic_autogenerate_prefix(autogen_context),
+ 'name': _render_gen_name(autogen_context, index.name),
+ 'table': _ident(index.table.name),
+ 'columns': ", ".join(
+ _get_index_rendered_expressions(index, autogen_context)),
+ 'unique': index.unique or False,
+ 'schema': (", schema=%r" % _ident(index.table.schema))
+ if index.table.schema else '',
+ 'kwargs': (
+ ', ' +
+ ', '.join(
+ ["%s=%s" %
+ (key, _render_potential_expr(val, autogen_context))
+ for key, val in index.kwargs.items()]))
+ if len(index.kwargs) else ''
+ }
return text
@@ -163,14 +171,21 @@ def _drop_index(index, autogen_context):
Generate Alembic operations for the DROP INDEX of an
:class:`~sqlalchemy.schema.Index` instance.
"""
- text = "%(prefix)sdrop_index(%(name)r, "\
- "table_name=%(table_name)r%(schema)s)" % {
- 'prefix': _alembic_autogenerate_prefix(autogen_context),
- 'name': _render_gen_name(autogen_context, index.name),
- 'table_name': _ident(index.table.name),
- 'schema': ((", schema=%r" % _ident(index.table.schema))
- if index.table.schema else '')
- }
+ has_batch = 'batch_prefix' in autogen_context
+
+ if has_batch:
+ tmpl = "%(prefix)sdrop_index(%(name)r)"
+ else:
+ tmpl = "%(prefix)sdrop_index(%(name)r, "\
+ "table_name=%(table_name)r%(schema)s)"
+
+ text = tmpl % {
+ 'prefix': _alembic_autogenerate_prefix(autogen_context),
+ 'name': _render_gen_name(autogen_context, index.name),
+ 'table_name': _ident(index.table.name),
+ 'schema': ((", schema=%r" % _ident(index.table.schema))
+ if index.table.schema else '')
+ }
return text
diff --git a/alembic/batch.py b/alembic/batch.py
index 7bfcf22..f5957ca 100644
--- a/alembic/batch.py
+++ b/alembic/batch.py
@@ -78,18 +78,18 @@ class BatchOperationsImpl(object):
def rename_table(self, *arg, **kw):
self.batch.append(("rename_table", arg, kw))
+ def create_index(self, idx):
+ self.batch.append(("create_index", (idx,), {}))
+
+ def drop_index(self, idx):
+ self.batch.append(("drop_index", (idx,), {}))
+
def create_table(self, table):
raise NotImplementedError("Can't create table in batch mode")
def drop_table(self, table):
raise NotImplementedError("Can't drop table in batch mode")
- def create_index(self, index):
- raise NotImplementedError("Can't create index in batch mode")
-
- def drop_index(self, index):
- raise NotImplementedError("Can't drop index in batch mode")
-
class ApplyBatchImpl(object):
def __init__(self, table, table_args, table_kwargs):
@@ -117,6 +117,7 @@ class ApplyBatchImpl(object):
self.named_constraints[const.name] = const
else:
self.unnamed_constraints.append(const)
+
for idx in self.table.indexes:
self.indexes[idx.name] = idx
@@ -251,5 +252,14 @@ class ApplyBatchImpl(object):
except KeyError:
raise ValueError("No such constraint: '%s'" % const.name)
+ def add_index(self, idx):
+ self.indexes[idx.name] = idx
+
+ def drop_index(self, idx):
+ try:
+ del self.indexes[idx.name]
+ except KeyError:
+ raise ValueError("No such index: '%s'" % idx.name)
+
def rename_table(self, *arg, **kw):
raise NotImplementedError("TODO")
diff --git a/alembic/operations.py b/alembic/operations.py
index 4665505..fc52e03 100644
--- a/alembic/operations.py
+++ b/alembic/operations.py
@@ -1309,6 +1309,7 @@ class BatchOperations(Operations):
:meth:`.Operations.create_primary_key`
"""
+ raise NotImplementedError("not yet implemented")
def create_foreign_key(
self, name, referent, local_cols, remote_cols, **kw):
@@ -1331,7 +1332,8 @@ class BatchOperations(Operations):
"""
return super(BatchOperations, self).create_foreign_key(
- name, self.impl.table_name, referent, local_cols, remote_cols,)
+ name, self.impl.table_name, referent, local_cols, remote_cols,
+ schema=self.impl.schema)
def create_unique_constraint(self, name, local_cols, **kw):
"""Issue a "create unique constraint" instruction using the
@@ -1345,6 +1347,7 @@ class BatchOperations(Operations):
:meth:`.Operations.create_unique_constraint`
"""
+ kw['schema'] = self.impl.schema
return super(BatchOperations, self).create_unique_constraint(
name, self.impl.table_name, local_cols, **kw)
@@ -1360,6 +1363,7 @@ class BatchOperations(Operations):
:meth:`.Operations.create_check_constraint`
"""
+ raise NotImplementedError("not yet implemented")
def drop_constraint(self, name, type_=None):
"""Issue a "drop constraint" instruction using the
@@ -1374,13 +1378,23 @@ class BatchOperations(Operations):
"""
return super(BatchOperations, self).drop_constraint(
- name, self.impl.table_name, type_=type_)
+ name, self.impl.table_name, type_=type_,
+ schema=self.impl.schema)
+
+ def create_index(self, name, columns, **kw):
+ """Issue a "create index" instruction using the
+ current batch migration context."""
+
+ kw['schema'] = self.impl.schema
+
+ return super(BatchOperations, self).create_index(
+ name, self.impl.table_name, columns, **kw)
- def create_index(self, *arg, **kw):
- """Not implemented for batch table operations."""
- self._noop("create_index")
+ def drop_index(self, name, **kw):
+ """Issue a "drop index" instruction using the
+ current batch migration context."""
- def drop_index(self, name):
- """Not implemented for batch table operations."""
- self._noop("drop_index")
+ kw['schema'] = self.impl.schema
+ return super(BatchOperations, self).drop_index(
+ name, self.impl.table_name, **kw)
diff --git a/tests/test_autogenerate.py b/tests/test_autogenerate.py
index 60b3a3e..51cae27 100644
--- a/tests/test_autogenerate.py
+++ b/tests/test_autogenerate.py
@@ -594,7 +594,7 @@ nullable=True))
batch_op.alter_column('name',
existing_type=sa.VARCHAR(length=50),
nullable=False)
- batch_op.drop_index('pw_idx', table_name='user')
+ batch_op.drop_index('pw_idx')
batch_op.drop_column('pw')
### end Alembic commands ###""")
@@ -603,7 +603,7 @@ nullable=True))
"""### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('pw', sa.VARCHAR(length=50), nullable=True))
- batch_op.create_index('pw_idx', 'user', ['pw'], unique=False)
+ batch_op.create_index('pw_idx', ['pw'], unique=False)
batch_op.alter_column('name',
existing_type=sa.VARCHAR(length=50),
nullable=True)
diff --git a/tests/test_batch.py b/tests/test_batch.py
index a387792..3892951 100644
--- a/tests/test_batch.py
+++ b/tests/test_batch.py
@@ -10,9 +10,9 @@ from alembic.batch import ApplyBatchImpl
from alembic.migration import MigrationContext
from sqlalchemy import Integer, Table, Column, String, MetaData, ForeignKey, \
- UniqueConstraint, ForeignKeyConstraint
+ UniqueConstraint, ForeignKeyConstraint, Index
from sqlalchemy.sql import column
-from sqlalchemy.schema import CreateTable
+from sqlalchemy.schema import CreateTable, CreateIndex
class BatchApplyTest(TestBase):
@@ -42,6 +42,17 @@ class BatchApplyTest(TestBase):
)
return ApplyBatchImpl(t, table_args, table_kwargs)
+ def _ix_fixture(self, table_args=(), table_kwargs={}):
+ m = MetaData()
+ t = Table(
+ 'tname', m,
+ Column('id', Integer, primary_key=True),
+ Column('x', String()),
+ Column('y', Integer),
+ Index('ix1', 'y')
+ )
+ return ApplyBatchImpl(t, table_args, table_kwargs)
+
def _fk_fixture(self, table_args=(), table_kwargs={}):
m = MetaData()
t = Table(
@@ -90,13 +101,23 @@ class BatchApplyTest(TestBase):
CreateTable(impl.new_table).compile(dialect=context.dialect))
create_stmt = re.sub(r'[\n\t]', '', create_stmt)
+ idx_stmt = ""
+ for idx in impl.new_table.indexes:
+ idx_stmt += str(CreateIndex(idx).compile(dialect=context.dialect))
+ idx_stmt = re.sub(r'[\n\t]', '', idx_stmt)
+
if ddl_contains:
- assert ddl_contains in create_stmt
+ assert ddl_contains in create_stmt + idx_stmt
if ddl_not_contains:
- assert ddl_not_contains not in create_stmt
+ assert ddl_not_contains not in create_stmt + idx_stmt
- context.assert_(
+ expected = [
create_stmt,
+ ]
+ if impl.new_table.indexes:
+ expected.append(idx_stmt)
+
+ expected.extend([
'INSERT INTO _alembic_batch_temp (%(colnames)s) '
'SELECT %(tname_colnames)s FROM tname' % {
"colnames": ", ".join([
@@ -116,7 +137,8 @@ class BatchApplyTest(TestBase):
},
'DROP TABLE tname',
'ALTER TABLE _alembic_batch_temp RENAME TO tname'
- )
+ ])
+ context.assert_(*expected)
return impl.new_table
def test_change_type(self):
@@ -250,6 +272,24 @@ class BatchApplyTest(TestBase):
impl, colnames=['id', 'x', 'y'],
ddl_not_contains="CONSTRAINT uq1 UNIQUE")
+ def test_add_index(self):
+ impl = self._simple_fixture()
+ ix = self.op._index('ix1', 'tname', ['y'])
+
+ impl.add_index(ix)
+ self._assert_impl(
+ impl, colnames=['id', 'x', 'y'],
+ ddl_contains="CREATE INDEX ix1")
+
+ def test_drop_index(self):
+ impl = self._ix_fixture()
+
+ ix = self.op._index('ix1', 'tname', ['y'])
+ impl.drop_index(ix)
+ self._assert_impl(
+ impl, colnames=['id', 'x', 'y'],
+ ddl_not_contains="CONSTRAINT uq1 UNIQUE")
+
def test_add_table_opts(self):
impl = self._simple_fixture(table_kwargs={'mysql_engine': 'InnoDB'})
self._assert_impl(
@@ -304,7 +344,8 @@ class BatchAPITest(TestBase):
mock.call(
['x'], ['user.y'],
onupdate=None, ondelete=None, name='myfk',
- initially=None, deferrable=None, match=None)
+ initially=None, deferrable=None, match=None,
+ schema=None)
]
)
eq_(