Fix index introspection on PostgreSQL 18.
Review Request #14923 — Created March 17, 2026 and submitted
PostgreSQL 18 stores
NOT NULLconstraints inpg_constraint(with
contype='n'). Django'sget_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:
ChangeFieldoperations that modifieddb_indexoruniquewould
find unexpectedNOT NULLindexes in the database state, causing
assertion failures.
ChangeMeta(indexes)operations would seeNOT NULLconstraint
entries instead of the actual Django-managed indexes, generating
incorrectDROP/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=Trueentries, and check constraints are handled through Django's
Meta.constraintssystem.)
Ran dbtests-minmax
| Summary | ID |
|---|---|
| wyzwxmuzpkxnwrpzokqqzpoosrtoznnm |
-
-
We're ultimately going to want to look up other details on constraints, so I think this method is most helpful as an unfiltered wrapper around
introspection.get_constraints()(even once the legacy DB implementation is removed, this takes care of cursor setup and normalization).I think the approach I'd prefer here is to include the other fields we need in the results, and then filter at the call site that handles indexing. That keeps the filtering where it's needed and frees us up to perform lookups for things like Check Constraints and primary key lookup later.
-
This will need unit tests for
DatabaseState.rescan_tableswith the different types of checks, and theChangeFieldandChangeMetafailures.