Search code examples
pythonsqlalchemyalembicsqlmodel

Alembic doesn't detect unique constraints


I'm using tiangolo sqlmodel and in my database-model I wanted to add unique-constraints, so one is kind of a business-key and the other is for mapping tables - both aren't recognized by alembic.

The one for the business-key is in a base-table (because all non-mapping-tables inherit from this class) and looks like this:

class BusinessKeyModel(PydanticBase):
    businessKey: Optional[str] = Field(
        alias="businessKey",
        max_length=255,
        description=DescriptionConstants.BUSINESS_KEY,
        nullable=True,
        unique=True  # <-- added this before generating new migration
    )

class BaseTableModel(SQLModel, BusinessKeyModel):
    ...

class User(GUIDModel, BaseTableModel):
    guid: Optional[UUID] = Field(
        ...,
        primary_key=True,
        description=DescriptionConstants.GUID,
        sa_column=Column(
            "guid",
            UNIQUEIDENTIFIER,
            nullable=False,
            primary_key=True,
            server_default=text("newsequentialid()"),
        ),
    )

so when I now add unique=True to the BusinessKeyModel.businessKey and try to generate a new migration with alembic, (with autogenerate) it doesn't detect the changes.

Same goes for my mapping-tables, after I added UniqueConstraint into my __table_args__ I think it should detect the changes:

class UserRoleMappingBase(BaseMappingModel, GUIDModel):

    userId: UUID
    roleId: UUID


class UserRoleMapping(UserRoleMappingBase, table=True):
    __table_args__ = (
        UniqueConstraint("userId", "roleId"), # <-- added this before generating new migration
        {"schema": "dbx_v2"}
    )

Solution

  • Turns out, Alembic is not able to detect changes of unique-constraints, at least for SQL Server. Neither adding them, nor deleting them. To define an answer anyway, the solution was to create a new migration and add them manually with in the upgrade():

    op.create_unique_constraint('uq_user_businessKey', 'user', ['businessKey'], schema='dbx_v2')
    

    and in the downgrade():

    op.drop_constraint('uq_user_businessKey', 'user', schema='dbx_v2')