Describe the bug
I have a migration file which basically creates a Check Constraint in upgrade() and drops it in downgrade(). When I define the constraint in the column, the downgrade throws ValueError: No such constraint: 'ck_Tasks_name'. When I define it in __table_args__, the downgrade works fine. upgrade() works in both definitions.
Expected behavior
I think Alembic should detect the per-column Check Constraints.
To Reproduce
# Model that throws an error during the downgrade sqlite_naming_convention = { "ix": "ix_%(column_0_label)s", "uq": "uq_%(table_name)s_%(column_0_name)s", "ck": "ck_%(table_name)s_%(column_0_name)s", "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", "pk": "pk_%(table_name)s", } Metadata = MetaData(naming_convention=sqlite_naming_convention) BaseSpatiaLite = declarative_base(metadata=Metadata) class Task(BaseSpatiaLite): __tablename__ = "Tasks" task_id = Column(Integer, primary_key=True) # per-column constraint is below name = Column(String(150), CheckConstraint("name <> ''", name="ck_Tasks_name"), nullable=False)
# Model that works in both upgrade and downgrade sqlite_naming_convention = { "ix": "ix_%(column_0_label)s", "uq": "uq_%(table_name)s_%(column_0_name)s", "ck": "ck_%(table_name)s_%(column_0_name)s", "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", "pk": "pk_%(table_name)s", } Metadata = MetaData(naming_convention=sqlite_naming_convention) BaseSpatiaLite = declarative_base(metadata=Metadata) class Task(BaseSpatiaLite): __tablename__ = "Tasks" task_id = Column(Integer, primary_key=True) # per-column constraint moved to __table_args name = Column(String(150), nullable=False) __table_args__ = (CheckConstraint("name <> ''", name="ck_Tasks_name"), )
# migration file """Add CheckConstraints for non-nullable string cols Revision ID: b7fc1ab24c92 Revises: d5d740c76aa3 Create Date: 2020-07-10 13:24:56.007611 """ from models import Task # revision identifiers, used by Alembic. revision = "b7fc1ab24c92" down_revision = "d5d740c76aa3" branch_labels = None depends_on = None def upgrade(): with op.batch_alter_table("Tasks", schema=None, copy_from=Task.__table__) as batch_op: batch_op.create_check_constraint("ck_Tasks_name", condition="name <> ''") def downgrade(): with op.batch_alter_table("Tasks", schema=None, copy_from=Task.__table__) as batch_op: batch_op.drop_constraint("ck_Tasks_name", type_="check")
Error
INFO [alembic.runtime.migration] Running downgrade b7fc1ab24c92 -> d5d740c76aa3, Add CheckConstraints for non-nullable string cols
-- Running downgrade b7fc1ab24c92 -> d5d740c76aa3
Traceback (most recent call last):
File .../lib/python3.8/site-packages/alembic/operations/batch.py", line 508, in drop_constraint
const = self.named_constraints.pop(const.name)
KeyError: 'ck_Tasks_name'
...
File ".../migrations/sqlite_versions/2020-07-10_b7fc1ab24c92_add_checkconstraints_for_non_nullable_.py", line 451, in downgrade
batch_op.drop_constraint("ck_Tasks_name", type_="check")
File "/Users/baris/.pyenv/versions/3.8.1/lib/python3.8/contextlib.py", line 120, in __exit__
next(self.gen)
File ".../lib/python3.8/site-packages/alembic/operations/base.py", line 354, in batch_alter_table
impl.flush()
File ".../lib/python3.8/site-packages/alembic/operations/batch.py", line 114, in flush
fn(*arg, **kw)
File ".../lib/python3.8/site-packages/alembic/operations/batch.py", line 516, in drop_constraint
raise ValueError("No such constraint: '%s'" % const.name)
ValueError: No such constraint: 'ck_Tasks_name'
Versions.
- OS: Mac OS 10.15
- Python: 3.8.1
- Alembic: 1.4.2
- SQLAlchemy: 1.3.10
- Database: SQLite
- DBAPI:
Additional context
If this is reported before or is explained in the Alembic's documentation, I'm sorry that I couldn't find any information.
Have a nice day!