Skip to content

fix(migrations): emit Meta.constraints in CREATE TABLE (#2272) - #2275

Open
jagadeepmamidi wants to merge 3 commits into
tortoise:developfrom
jagadeepmamidi:fix/2272-meta-constraints-create-table
Open

jagadeepmamidi wants to merge 3 commits into
tortoise:developfrom
jagadeepmamidi:fix/2272-meta-constraints-create-table

Conversation

@jagadeepmamidi

Copy link
Copy Markdown

Named UniqueConstraint and CheckConstraint were stored on CreateModel but never applied when creating tables, and MySQL add_constraint ignored custom names.

Description

Meta.constraints (UniqueConstraint / CheckConstraint) are now emitted in CREATE TABLE for both tortoise migrate and generate_schemas.

Previously makemigrations stored them on CreateModel, but table creation only applied unique_together, so a new model never got AddConstraint and named uniques like unique_like never appeared. MySQL add_constraint also ignored name and generated uidx_* instead.

  • Named unique and check constraints are inlined in CREATE TABLE
  • Partial unique constraints (condition) become CREATE UNIQUE INDEX ... WHERE on PostgreSQL
  • A UniqueConstraint whose resolved columns already match unique_together is skipped
  • MySQL add_constraint honors constraint.name when set

Motivation and Context

Fixes #2272

Reporter used tortoise makemigrations / tortoise migrate on MySQL 8.4 with:

class Meta:
    constraints = [
        UniqueConstraint(fields=("types", "user_id", "art_id"), name="unique_like"),
    ]

Expected a unique index named unique_like; nothing was created, with no error.

How Has This Been Tested?

Added regression tests in tests/migrations/test_schema_editor_sql.py and tests/migrations/test_schema_editor_constraints.py covering:

  • CreateModel SQL for named unique + check constraints (ANSI and MySQL)
  • skip when UniqueConstraint duplicates unique_together (including FK field vs organization_id columns)
  • PostgreSQL partial unique index on create
  • generate_schemas including Meta.constraints
  • MySQL add_constraint using the custom name

Ran:

uv run pytest tests/migrations/test_schema_editor_sql.py tests/migrations/test_schema_editor_constraints.py

(52 passed)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added the changelog accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Named UniqueConstraint and CheckConstraint were stored on CreateModel but never applied when creating tables, and MySQL add_constraint ignored custom names.
@seejah

seejah commented Sep 8, 2026

Copy link
Copy Markdown

Great efficient work 🏅

@jagadeepmamidi

Copy link
Copy Markdown
Author

@seejah please let me know if I can check any other issues too (happy to help)

@codspeed

codspeed Bot commented Sep 13, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing jagadeepmamidi:fix/2272-meta-constraints-create-table (2045bec) with develop (ffc946e)

Open in CodSpeed

@waketzheng waketzheng left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For _partial_unique_index_sqls(): the base class could just return [], and the
actual logic should move to an override in
tortoise/backends/base_postgres/schema_generator.py. Keeping self.DIALECT != "postgres"
in the base generator couples it to a specific dialect — new dialects should extend via
override, not by adding string checks here.

With that change, the MySQL override of _partial_unique_index_sqls() also becomes
unnecessary, since it would inherit the base return [] and correctly produce nothing.

@jagadeepmamidi

Copy link
Copy Markdown
Author

Thanks for the feedback. I moved partial unique-index generation out of the base schema classes and into the PostgreSQL-specific implementations. The base classes now
return an empty list, so dialect-specific behavior is handled through backend overrides instead of checking for postgres in the base implementation.

I also added regression coverage for PostgreSQL generate_schemas() partial unique indexes. The branch was updated with the latest develop, and the targeted migration

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Constraints defined within Meta are not applied when performing data migrations.

3 participants