Details
-
Bug
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.0
-
None
Description
JSON_EXISTS is documented to determine whether a document has an element
at a path. Asked for the root path, it answers 1 whatever the argument
is - including bytes that are not a document at all, and including the
empty string.
SELECT JSON_EXISTS('', '$') AS v; |
v
|
1
|
No warning is raised. Every sibling function refuses the same bytes in
the same statement:
SELECT JSON_EXISTS('', '$') AS ex, |
JSON_CONTAINS('', '1') AS co, |
JSON_CONTAINS_PATH('','one','$') AS cp, |
JSON_VALID('') AS va, |
JSON_LENGTH('') AS le; |
ex co cp va le
|
1 NULL NULL 0 NULL |
Warnings:
|
Warning 4037 Unexpected end of JSON text in argument 1 |
to function 'json_contains' |
Warning 4037 Unexpected end of JSON text in argument 1 |
to function 'json_contains_path' |
Note 4037 Unexpected end of JSON text in argument 1 |
to function 'json_valid' |
Warning 4037 Unexpected end of JSON text in argument 1 |
to function 'json_length' |
How to repeat
SELECT JSON_EXISTS('', '$') AS empty_string; |
SELECT JSON_EXISTS(' ', '$') AS spaces; |
SELECT JSON_EXISTS('rubbish', '$') AS not_json; |
SELECT JSON_EXISTS('{', '$') AS truncated; |
-- all four answer 1, silently
|
 |
-- and the same documents with any other path answer NULL and say why
|
SELECT JSON_EXISTS('', '$.a') AS with_a_step; |
SELECT JSON_EXISTS('', '$[0]') AS with_a_subscript; |
-- NULL + Warning 4037
|
So the answer 1 for the root path is given without the document having
been read at all.
Root cause
The root path needs no search, so the function answers before the
argument is scanned. Any other path drives a scan, which is why the
same document is diagnosed there and not here.
The contract is *"Determines whether json_doc has an element pointed to
by path json_path. Returns 1 if the element exists, 0 if not, or NULL
if any of the inputs were NULL"* (`scripts/fill_help_tables.sql:440`).
Of the three documented answers, 1 is the only one that cannot be right
for a document that does not exist.
Why it matters
JSON_EXISTS(col, '$') is the natural way to ask whether a column holds
anything at all, and written that way it cannot fail: a column of
rubbish and a column of documents give the same answer, and nothing
downstream can tell them apart.
Affected versions
JSON_EXISTS was added in 10.2.3 and the early return for the root
path has been there throughout.
Verified on 10.11 only (10.11.19-MariaDB-debug, commit 1dab253482d).
Other branches were not tested.
Note
Found while auditing the JSON functions against their documented
contracts. No test in mysql-test/ calls JSON_EXISTS on an
empty or malformed document.
Attachments
Issue Links
- split from
-
MDEV-40642 Project "JSON Phoenix" (placeholder)
-
- Open
-