diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-05-01 11:19:54 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-05-01 11:19:54 -0400 |
commit | 494ac8d84a4e827fcf7dc117b84ba76f442d60a2 (patch) | |
tree | 57b5ae7a873ea5eab423aa0642dff3aa1c9d9f1b | |
parent | 7835a323a7e41558989afcb2eeaa73b968dd9e34 (diff) | |
download | alembic-494ac8d84a4e827fcf7dc117b84ba76f442d60a2.tar.gz |
- [bug] Added "type" argument to op.drop_constraint(),
and implemented full constraint drop support for
MySQL. CHECK and undefined raise an error.
MySQL needs the constraint type
in order to emit a DROP CONSTRAINT. #44
-rw-r--r-- | CHANGES | 8 | ||||
-rw-r--r-- | alembic/__init__.py | 2 | ||||
-rw-r--r-- | alembic/ddl/mysql.py | 19 | ||||
-rw-r--r-- | alembic/operations.py | 26 | ||||
-rw-r--r-- | tests/test_mysql.py | 39 |
5 files changed, 90 insertions, 4 deletions
@@ -1,3 +1,11 @@ +0.3.3 +===== +- [bug] Added "type" argument to op.drop_constraint(), + and implemented full constraint drop support for + MySQL. CHECK and undefined raise an error. + MySQL needs the constraint type + in order to emit a DROP CONSTRAINT. #44 + 0.3.2 ===== - [feature] Basic support for Oracle added, diff --git a/alembic/__init__.py b/alembic/__init__.py index 259782c..d75fb22 100644 --- a/alembic/__init__.py +++ b/alembic/__init__.py @@ -1,6 +1,6 @@ from os import path -__version__ = '0.3.2' +__version__ = '0.3.3' package_dir = path.abspath(path.dirname(__file__)) diff --git a/alembic/ddl/mysql.py b/alembic/ddl/mysql.py index 00cf7ab..f5afc22 100644 --- a/alembic/ddl/mysql.py +++ b/alembic/ddl/mysql.py @@ -4,6 +4,7 @@ from sqlalchemy.ext.compiler import compiles from alembic.ddl.base import alter_table from alembic import util from sqlalchemy import types as sqltypes +from sqlalchemy import schema class MySQLImpl(DefaultImpl): __dialect__ = 'mysql' @@ -85,4 +86,22 @@ def _mysql_colspec(compiler, name, nullable, server_default, type_): return spec +@compiles(schema.DropConstraint, "mysql") +def _mysql_drop_constraint(element, compiler, **kw): + """Redefine SQLAlchemy's drop constraint to + raise errors for invalid constraint type.""" + + constraint = element.element + if isinstance(constraint, (schema.ForeignKeyConstraint, + schema.PrimaryKeyConstraint, + schema.UniqueConstraint) + ): + return compiler.visit_drop_constraint(element, **kw) + elif isinstance(constraint, schema.CheckConstraint): + raise NotImplementedError( + "MySQL does not support CHECK constraints.") + else: + raise NotImplementedError( + "No generic 'DROP CONSTRAINT' in MySQL - " + "please specify constraint type") diff --git a/alembic/operations.py b/alembic/operations.py index 7787f77..9d4b7ef 100644 --- a/alembic/operations.py +++ b/alembic/operations.py @@ -529,10 +529,30 @@ class Operations(object): # 0.7.6 and further raises on Index with no columns self.impl.drop_index(self._index(name, tablename, ['x'])) - def drop_constraint(self, name, tablename): - """Drop a constraint of the given name""" + def drop_constraint(self, name, tablename, type=None): + """Drop a constraint of the given name, typically via DROP CONSTRAINT. + + :param name: name of the constraint. + :param tablename: tablename. + :param type: optional, required on MySQL. can be + 'foreignkey', 'unique', or 'check' + + """ t = self._table(tablename) - const = schema.Constraint(name=name) + types = { + 'foreignkey':lambda name:schema.ForeignKeyConstraint( + [], [], name=name), + 'unique':schema.UniqueConstraint, + 'check':lambda name:schema.CheckConstraint("", name=name), + None:schema.Constraint + } + try: + const = types[type] + except KeyError: + raise TypeError("'type' can be one of %s" % + ", ".join(sorted(repr(x) for x in types))) + + const = const(name=name) t.append_constraint(const) self.impl.drop_constraint(const) diff --git a/tests/test_mysql.py b/tests/test_mysql.py index 499dec7..4c4a357 100644 --- a/tests/test_mysql.py +++ b/tests/test_mysql.py @@ -40,3 +40,42 @@ def test_col_alter_type_required(): "All MySQL ALTER COLUMN operations require the existing type.", op.alter_column, 't1', 'c1', nullable=False, server_default="q" ) + +def test_drop_fk(): + context = op_fixture('mysql') + op.drop_constraint("f1", "t1", "foreignkey") + context.assert_( + "ALTER TABLE t1 DROP FOREIGN KEY f1" + ) + +def test_drop_unique(): + context = op_fixture('mysql') + op.drop_constraint("f1", "t1", "unique") + context.assert_( + "ALTER TABLE t1 DROP INDEX f1" + ) + +def test_drop_check(): + context = op_fixture('mysql') + assert_raises_message( + NotImplementedError, + "MySQL does not support CHECK constraints.", + op.drop_constraint, "f1", "t1", "check" + ) + +def test_drop_unknown(): + context = op_fixture('mysql') + assert_raises_message( + TypeError, + "'type' can be one of 'check', 'foreignkey', 'unique', None", + op.drop_constraint, "f1", "t1", "typo" + ) + +def test_drop_generic_constraint(): + context = op_fixture('mysql') + assert_raises_message( + NotImplementedError, + "No generic 'DROP CONSTRAINT' in MySQL - please " + "specify constraint type", + op.drop_constraint, "f1", "t1" + )
\ No newline at end of file |