Opened 8 years ago
Closed 8 years ago
#27693 closed Bug (fixed)
Case insensitive lookups on JSONField nested values
Reported by: | Harris Lapiroff | Owned by: | |
---|---|---|---|
Component: | contrib.postgres | Version: | dev |
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
Currently JSONField
doesn't support case-insensitive lookups such as iexact
. This is not documented as working, so I'm marking this as a new feature, but it's something I think Django can and should support.
Attempting to use an iexact
lookup (e.g., OrganizationPerson.objects.filter(data__field2__iexact='Ethelfort')
) results in a SQL error:
django.db.utils.ProgrammingError: function upper(jsonb) does not exist LINE 1: ...st" FROM "organizations_organizationperson" WHERE UPPER("org... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.
I believe this is just a case of misplaced parens and quotes. Similar functionality (though still not documented) does work on HStoreField
s. Here's an example of the successful SQL Django generates for an iexact
lookup on an HStoreField
.
SELECT "organizations_organizationperson"."id", "organizations_organizationperson"."organization_id", "organizations_organizationperson"."person_id", "organizations_organizationperson"."data", "organizations_organizationperson"."test" FROM "organizations_organizationperson" WHERE UPPER(("organizations_organizationperson"."test" -> 'foo')::text) = UPPER('Bar') LIMIT 21
And here's the unsuccessful SQL Django generates for an iexact
lookup on a JSONField
, which generates the error above:
SELECT "organizations_organizationperson"."id", "organizations_organizationperson"."organization_id", "organizations_organizationperson"."person_id", "organizations_organizationperson"."data", "organizations_organizationperson"."test" FROM "organizations_organizationperson" WHERE UPPER("organizations_organizationperson"."data" -> 'field2'::text) = UPPER('Ethelfort') LIMIT 21
I don't have an ORM-level fix for correcting the query, but a proper query that works as expected just includes a couple more parens and quotes in the WHERE
clause:
SELECT "organizations_organizationperson"."id", "organizations_organizationperson"."organization_id", "organizations_organizationperson"."person_id", "organizations_organizationperson"."data", "organizations_organizationperson"."test" FROM "organizations_organizationperson" WHERE UPPER(("organizations_organizationperson"."data" -> 'field2')::text) = UPPER('"Ethelfort"') LIMIT 21
Change History (6)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
Just tested this on master, and I can confirm that the iexact lookup works - except that you need to add the quotes for the query in yourself. i.e.
>>> x = OrganizationPerson.objects.first() >>> x.data {'field2': 'Ethelfort'} >>> OrganizationPerson.objects.filter(data__field2__iexact='Ethelfort') <QuerySet []> >>> OrganizationPerson.objects.filter(data__field2__iexact='"Ethelfort"') <QuerySet [<OrganizationPerson: OrganizationPerson object>]>
Knowing how the SQL ends up looking, this sort of makes sense to me - but if I didn't know that from this ticket I would be completely lost.
comment:3 by , 8 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | New feature → Bug |
Version: | 1.10 → master |
It looks like the iexact case was overlooked by #27257. It believe it would be a simple matter of defining a KeyTransformIExact(KeyTransformTextLookupMixin, builtin_lookups.IExact)
subclass and registering it as a KeyTransform
lookup. See cecef94275118dc49a1b0d89d3ca9734e2ec9776.
comment:5 by , 8 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Did you reproduce this on master? I thought it might be fixed by #27257 -- Fixed builtin text lookups on JSONField keys.