1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-04 20:11:56 +03:00

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
This commit is contained in:
Amit Langote
2024-09-12 09:36:31 +09:00
parent 77761ee5dd
commit e6c45d85dc
3 changed files with 48 additions and 38 deletions

View File

@@ -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);