Opened 85 minutes ago
Last modified 16 minutes ago
#36880 new Bug
Postgres hash exclusion constraints are not considered totally unique
| Reported by: | Tilman Koschnick | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Tilman Koschnick | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description
Hi,
with Postgres, a hash index can be used as an exclusion constraint, functioning the same way a unique btree based constrained. Support for this has recently been merged to Django: https://code.djangoproject.com/ticket/36827
Using this on a USERNAME_FIELD can be good for index size and performance. Currently, the auth system checks doesn't detect a hash exclusion constraint as a viable option though:
account.User: (auth.E003) 'User.email' must be unique because it is named as the 'USERNAME_FIELD'.
The attached patch enhances the check to consider hash constraints as well.
Cheers, Til
Attachments (1)
Change History (2)
by , 85 minutes ago
| Attachment: | checks.diff added |
|---|
comment:1 by , 19 minutes ago
| Patch needs improvement: | set |
|---|---|
| Summary: | using hash index as exclusion constraint on USERNAME_FIELD triggers SystemCheckError → Postgres hash exclusion constraints are not considered totally unique |
| Triage Stage: | Unreviewed → Accepted |
Accepting on the basis that the check logic should be able to consider all type of unique constraints but the proposed patch is inadequate.
What should be done instead is find a way to have
django.db.models.options.Options.total_unique_constraintsinclude such constraint in a way that doesn't couplecontrib.postgreswith core.A potential solution could be to introduce a
Constraint.totally_unique_for_fields: set[tuple[str]] | Noneproperty which is implemented byUniqueConstraintandExclusionConstraintover the introspection logic that currently exists.That might call for a
Options.unique_together_fields: set[tuple[str]]that combineField.unique,Options.unique_togetherandConstraint.totally_unique_for_fieldsso interested parties don't have to check of them every time.