Fix index introspection on PostgreSQL 18.

Review Request #14923 — Created March 17, 2026 and updated — Latest diff uploaded

Information

Django Evolution
master

Reviewers

PostgreSQL 18 stores NOT NULL constraints in pg_constraint (with
contype='n'). Django's get_constraints() includes these in its
results, but with all type flags (index, unique, primary_key, check,
foreign_key) set to False. get_constraints_for_table() was passing
through all constraint entries unconditionally, causing these NOT NULL
constraints to be tracked as regular non-unique indexes in
DatabaseState (e.g., "tests_testmodel_int_field1_not_null").

This caused two categories of failures:

  1. ChangeField operations that modified db_index or unique would
    find unexpected NOT NULL indexes in the database state, causing
    assertion failures.

  2. ChangeMeta(indexes) operations would see NOT NULL constraint
    entries instead of the actual Django-managed indexes, generating
    incorrect DROP/CREATE INDEX SQL.

The fix filters get_constraints_for_table() to only include entries
where index, unique, or primary_key is True. This excludes NOT NULL
constraints, check constraints, and foreign key constraint entries --
none of which should be tracked as indexes in DatabaseState. (Foreign
key fields still have their actual indexes captured via separate
index=True entries, and check constraints are handled through Django's
Meta.constraints system.)

Ran dbtests-minmax

Commits

Files