From: Mike Bayer Date: Tue, 1 May 2012 15:19:54 +0000 (-0400) Subject: - [bug] Added "type" argument to op.drop_constraint(), X-Git-Tag: rel_0_3_3~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=494ac8d84a4e827fcf7dc117b84ba76f442d60a2;p=thirdparty%2Fsqlalchemy%2Falembic.git - [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 --- diff --git a/CHANGES b/CHANGES index 40a57654..4a20a5e3 100644 --- a/CHANGES +++ b/CHANGES @@ -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 259782c9..d75fb222 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 00cf7ab5..f5afc22d 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 7787f77a..9d4b7ef0 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 499dec7c..4c4a357d 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