diff options
author | Amit Langote <amitlan@postgresql.org> | 2024-09-12 09:36:31 +0900 |
---|---|---|
committer | Amit Langote <amitlan@postgresql.org> | 2024-09-12 09:39:56 +0900 |
commit | e6c45d85dc168fb05b5ee5596a4de5167c9fe01f (patch) | |
tree | acf249d689ab6800d4a23939b6d3b473f821fa8d /src/backend/utils/adt/jsonpath_exec.c | |
parent | 77761ee5dddc0518235a51c533893e81e5f375b9 (diff) | |
download | postgresql-e6c45d85dc168fb05b5ee5596a4de5167c9fe01f.tar.gz postgresql-e6c45d85dc168fb05b5ee5596a4de5167c9fe01f.zip |
SQL/JSON: Fix JSON_QUERY(... WITH CONDITIONAL WRAPPER)
Currently, when WITH CONDITIONAL WRAPPER is specified, array wrappers
are applied even to a single SQL/JSON item if it is a scalar JSON
value, but this behavior does not comply with the standard.
To fix, apply wrappers only when there are multiple SQL/JSON items
in the result.
Reported-by: Peter Eisentraut <peter@eisentraut.org>
Author: Peter Eisentraut <peter@eisentraut.org>
Author: Amit Langote <amitlangote09@gmail.com>
Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Discussion: https://postgr.es/m/8022e067-818b-45d3-8fab-6e0d94d03626%40eisentraut.org
Backpatch-through: 17
Diffstat (limited to 'src/backend/utils/adt/jsonpath_exec.c')
-rw-r--r-- | src/backend/utils/adt/jsonpath_exec.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index e3ee0093d4d..e569c7efb83 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -3947,7 +3947,24 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, return (Datum) 0; } - /* WRAP or not? */ + /* + * Determine whether to wrap the result in a JSON array or not. + * + * First, count the number of SQL/JSON items in the returned + * JsonValueList. If the list is empty (singleton == NULL), no wrapping is + * necessary. + * + * If the wrapper mode is JSW_NONE or JSW_UNSPEC, wrapping is explicitly + * disabled. This enforces a WITHOUT WRAPPER clause, which is also the + * default when no WRAPPER clause is specified. + * + * If the mode is JSW_UNCONDITIONAL, wrapping is enforced regardless of + * the number of SQL/JSON items, enforcing a WITH WRAPPER or WITH + * UNCONDITIONAL WRAPPER clause. + * + * For JSW_CONDITIONAL, wrapping occurs only if there is more than one + * SQL/JSON item in the list, enforcing a WITH CONDITIONAL WRAPPER clause. + */ count = JsonValueListLength(&found); singleton = count > 0 ? JsonValueListHead(&found) : NULL; if (singleton == NULL) @@ -3957,10 +3974,7 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, else if (wrapper == JSW_UNCONDITIONAL) wrap = true; else if (wrapper == JSW_CONDITIONAL) - wrap = count > 1 || - IsAJsonbScalar(singleton) || - (singleton->type == jbvBinary && - JsonContainerIsScalar(singleton->val.binary.data)); + wrap = count > 1; else { elog(ERROR, "unrecognized json wrapper %d", (int) wrapper); |