You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JSON path equality against a non-string value: silently empty on MySQL, raises on PostgreSQL #1564
Table & {"json_attr.field": value} only behaves correctly when value is a string. A Python bool returns the wrong answer on MySQL and raises on PostgreSQL; a Python int raises on PostgreSQL.
Sibling of #1563 — same root (JSON extraction yields text), different side: that one is the :type annotation on projection, this one is the Python value on restriction.
UndefinedFunction: operator does not exist: text = integer
& {"s.ch": "64"}
['a']
['a']
& {"s.cal": True}
[]
UndefinedFunction: operator does not exist: text = boolean
& {"s.cal": "true"}
['a']
['a']
The MySQL boolean row is the serious one: no error, no rows, and the natural reading of an empty result is "nothing is calibrated."
Cause
adapter.json_path_expr yields json_value(...) / jsonb_extract_path_text(...), both of which return text. prep_value (condition.py:336) then renders the Python value by its own type, so the comparison becomes text = <non-text>:
PostgreSQL refuses the comparison outright.
MySQL coerces for numerics, which is why 64 happens to work, but compares the extracted true against 1 for a bool and matches nothing.
The asymmetry is invisible to a user: the same expression is correct, wrong, or an error depending on the value's Python type and the backend.
Suggested fix
On the JSON-path branch of prep_value, render the comparison value as text — or cast the extraction to the value's type — so that True, 64 and "Acme" all behave the same way on both backends.
Whichever way, a bool must not silently match nothing. If a given comparison cannot be made portable, raising is acceptable; returning the wrong rows is not.
Documentation
This is almost certainly why tutorials/advanced/json-type.ipynb teaches "Filtering on JSON Content — fetch then filter in Python" and lists "Filter in Python" as an inherent property of JSON in its Design Guidelines. Server-side filtering does work, with the value passed as a string; the tutorial's advice reads as a limitation of the type rather than of this behavior. Worth revisiting together.
Activity