#33820 closed Bug (fixed)
Querying "null" on key transforms for JSONField returns wrong results on SQLite.
Reported by: | Johnny Metz | Owned by: | Mariusz Felisiak |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 4.0 |
Severity: | Release blocker | Keywords: | JSONField |
Cc: | Matthew Cornell, Sage Abdullah | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Let's say I have a Django model with a JSONField
:
class Event(models.Model): data = models.JSONField()
And I create the following objects:
event1 = Event.objects.create(data={"key": None}) event2 = Event.objects.create(data={"key": "null"})
In Django 3.2.13, the following queries return some results:
Event.objects.filter(data__key=Value("null")) # [event1] Event.objects.filter(data__key="null") # [event2]
In Django 4.0.5, the same queries return different results:
Event.objects.filter(data__key=Value("null")) # [event1, event2] Event.objects.filter(data__key="null") # [event1, event2]
The Django docs aren't clear which results are correct. I would lean towards the v3 results.
I'm happy to work on a patch if people think this is a bug in v4.
Attachments (1)
Change History (12)
comment:1 by , 2 years ago
Cc: | added |
---|---|
Severity: | Normal → Release blocker |
Summary: | Querying null in JSONField is different between 3.2 and 4.0 → Querying "null" on key transforms for JSONField returns wrong results on SQLite. |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 2 years ago
Seems like a type-juggling routine introduced in 4.0.0
I am totally into type-juggling but this case, and actually blocking issue is a great example of the general confusion that a seemingly *simplification* - may lead to hold back on tech dev.
TL;DR:
- consider removing type juggling
- keep principles up, regarding data type comparison
by , 2 years ago
Attachment: | regression-tests-33820.diff added |
---|
comment:3 by , 2 years ago
I tried to fix this few times in the last two weeks, unfortunately, I don't see a proper way to distinguish between {"x": "null"}
and {"x": NULL}
extracted from the JSON field (the same for boolean values). Mainly due to the lack of proper database types in SQLite. In 71ec102b01fcc85acae3819426a4e02ef423b0fa we tried to use
CASE WHEN JSON_TYPE("model"."json_field", $."key") IN ('null', 'false', 'true') THEN JSON_TYPE("model"."json_field", $."key") ELSE JSON_EXTRACT("model"."json_field", $."key") END
which fixed #32483 but also introduced this regression because for both NULL
and "null"
it returns 'null'
.
Quo vadis? 🤷 We have two options:
- document this as a SQLite caveat,
- revert 71ec102b01fcc85acae3819426a4e02ef423b0fa and reintroduce another SQLite caveat.
follow-up: 5 comment:4 by , 2 years ago
document this as a SQLite caveat,
I'd go with this. I think storing "null"
is quite niche, and easily worked around.
comment:5 by , 2 years ago
Replying to Carlton Gibson:
I'd go with this. I think storing
"null"
is quite niche, and easily worked around.
Just to be clear, this issue is for all three "true"
, "false"
, and "null"
.
comment:6 by , 2 years ago
Sure, yes. My feeling is that it's better to resolve #32483, which was 71ec102b01fcc85acae3819426a4e02ef423b0fa. Most times I want True
/False
/None
, and I can serialise those if I need to. (That's just a +1 towards option 1 in response to the What to do?)
comment:7 by , 2 years ago
Cc: | added |
---|
Thanks for the report. Regression in 71ec102b01fcc85acae3819426a4e02ef423b0fa. This is also inconsistent with other backends.