summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-05-01 11:19:54 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-05-01 11:19:54 -0400
commit494ac8d84a4e827fcf7dc117b84ba76f442d60a2 (patch)
tree57b5ae7a873ea5eab423aa0642dff3aa1c9d9f1b
parent7835a323a7e41558989afcb2eeaa73b968dd9e34 (diff)
downloadalembic-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--CHANGES8
-rw-r--r--alembic/__init__.py2
-rw-r--r--alembic/ddl/mysql.py19
-rw-r--r--alembic/operations.py26
-rw-r--r--tests/test_mysql.py39
5 files changed, 90 insertions, 4 deletions
diff --git a/CHANGES b/CHANGES
index 40a5765..4a20a5e 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 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