JSONField __in operator breaks when given a values_list()
Prerequisites
- Create a model MyModel1 with the field
resource = JSONField().
- Create another model MyModel2 with a field
id = CharField(max_length=255)
Reproduce by doing MyModel1.objects.filter(resource__foo__id__in=MyModel2.objects.all().values_list("id"))
Expected result: Should look at MyModel1 for objects with resource matching {"foo": {"id": <id>}}.
Actual result:
ERROR: operator does not exist: jsonb = character varying
LINE 1: ...AND ("resource" #> '{foo,id}') IN (SELECT...
The actual issue is that when passing a values_list() to __in, the values list is not cast to jsonb (unlike when passing a text type). In the resulting sql, we can see IN (SELECT U0."id" AS Col1 FROM mymodel2 U0 ...). Wrapping to_json(U0."id") solves the issue.
Change History
(11)
| Description: |
modified (diff)
|
| Description: |
modified (diff)
|
| Triage Stage: |
Unreviewed → Accepted
|
| Owner: |
set to VCAMP
|
| Status: |
new → assigned
|
| Cc: |
VCAMP added
|
| Has patch: |
set
|
| Patch needs improvement: |
set
|
| Component: |
contrib.postgres → Database layer (models, ORM)
|
| Owner: |
VCAMP removed
|
| Status: |
assigned → new
|
| Owner: |
set to JaeHyuckSa
|
| Patch needs improvement: |
unset
|
| Status: |
new → assigned
|
| Patch needs improvement: |
set
|
| Patch needs improvement: |
unset
|
https://github.com/django/django/pull/10597