#32858 closed Bug (fixed)
Syntax error when using an index transform on an ArrayField in an ExclusionConstraint
Reported by: | Lucidiot | Owned by: | Lucidiot |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.2 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
I am trying to create a GIST exclusion constraint on a PostgreSQL 12 database. One of the fields is an ArrayField, and I want to apply the constraint on its first item using my_array__0
. When doing so, I get a syntax error from Postgres.
from django.db import models from django.contrib.postgres.constraints import ExclusionConstraint from django.contrib.postgres.fields import ArrayField, RangeOperators class MyModel(models.Model): my_array = ArrayField() class Meta: constraints = ( ExclusionConstraint( name='foo', expressions=[ ('my_array__0', RangeOperators.EQUAL), ] ) )
django.db.utils.ProgrammingError: syntax error at or near "WITH" LINE 1: ..." ADD CONSTRAINT "foo" EXCLUDE USING GIST ("my_array"[1] WITH =) ^
It seems a similar issue had occurred with casts (#32392). The docs for ALTER TABLE mention this syntax for expressions in an EXCLUDE constraint:
exclude_element in an EXCLUDE constraint is: { column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]
This implies that parentheses around anything that is not a column name are mandatory. Maybe a more generic fix could be made to detect if something is only a column name, or just to add parentheses all the time? EXCLUDE USING GIST (("my_array"[1]) WITH =)
works without any trouble.
Change History (7)
comment:1 by , 3 years ago
Description: | modified (diff) |
---|
comment:2 by , 3 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 3 years ago
Has patch: | set |
---|---|
Owner: | changed from | to
Status: | new → assigned |
I managed to make a PR! I did not however look into reverting the previous fix.
comment:4 by , 3 years ago
That's looking great thanks! Lets leave the decision of reverting the previous fix to the mergers.
comment:5 by , 3 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
The proposed solution makes sense to me, looks like #32392 was just a workaround in the end.
It should be easy enough to add the conditional
f'({sql})'
wrapping ifisinstance(expression, Col)
as you've mentioned (Col
isdjango.db.models.expressions.Col
).https://github.com/django/django/blob/225d96533a8e05debd402a2bfe566487cc27d95f/django/contrib/postgres/constraints.py#L72-L83
Would you be able to provide a patch/PR?
I also wonder if we should just revert the non-test bits of fdfbc66331292def201c9344e3cd29fbcbcd076a since it might just be hiding other instances of this problem.