Commit
8d829f5a0 introduced the JSCTOR_JSON_ARRAY_QUERY constructor
type so that ruleutils.c could deparse JSON_ARRAY(subquery) using its
original syntax, storing the transformed subquery in a new orig_query
field. However, the input FORMAT clause of JSON_ARRAY(subquery FORMAT
...) was not preserved for deparsing. The format was recorded only in
the executable expression kept in the func field, which ruleutils.c
does not inspect, so it is silently dropped.
This is more than cosmetic, because FORMAT JSON changes the result:
without it a text value is treated as a string to be quoted, while
with it the value is treated as already-formatted JSON.
To fix, record the input FORMAT in a new deparse-only field of
JsonConstructorExpr, alongside orig_query, and emit it in ruleutils.c.
Bump catalog version.
Author: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/
4C89B193-7D54-4705-9CF9-
F0D484B9E099@gmail.com
Backpatch-through: 19
* - orig_query: the transformed Query of the user's original subquery, so
* that ruleutils.c can deparse the original JSON_ARRAY(SELECT ...) syntax
* for view definitions.
+ *
+ * - format: the input FORMAT clause, so that ruleutils.c can deparse it.
*/
static Node *
transformJsonArrayQueryConstructor(ParseState *pstate,
false, ctor->absent_on_null,
ctor->location);
((JsonConstructorExpr *) result)->orig_query = (Node *) query;
+ ((JsonConstructorExpr *) result)->format = ctor->format;
return result;
}
context->prettyFlags, context->wrapColumn,
context->indentLevel);
+ get_json_format(ctor->format, buf);
get_json_constructor_options(ctor, buf);
appendStringInfoChar(buf, ')');
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202607201
+#define CATALOG_VERSION_NO 202607271
#endif
* orig_query holds the user's original subquery for JSON_ARRAY(query), used
* only by ruleutils.c for deparsing; it is not walked because func is
* authoritative for all other purposes.
+ *
+ * format likewise holds the input FORMAT clause of JSON_ARRAY(query), which
+ * is otherwise only represented inside func; it is used only by ruleutils.c
+ * for deparsing.
*/
typedef struct JsonConstructorExpr
{
Expr *coercion; /* coercion to RETURNING type */
JsonReturning *returning; /* RETURNING clause */
Node *orig_query; /* original subquery for deparsing */
+ JsonFormat *format; /* input FORMAT for JSON_ARRAY(query) */
bool absent_on_null; /* ABSENT ON NULL? */
bool unique; /* WITH UNIQUE KEYS? (JSON_OBJECT[AGG] only) */
ParseLoc location;
SELECT JSON_ARRAY( SELECT foo.i
FROM ( VALUES (1), (2), (NULL::integer), (4)) foo(i) RETURNING text) AS "json_array"
DROP VIEW json_array_subquery_view;
+-- JSON_ARRAY(subquery) with an input FORMAT clause
+CREATE VIEW json_array_subquery_view AS
+SELECT JSON_ARRAY(SELECT '{"a": 1}'::text FORMAT JSON);
+\sv json_array_subquery_view
+CREATE OR REPLACE VIEW public.json_array_subquery_view AS
+ SELECT JSON_ARRAY( SELECT '{"a": 1}'::text AS text FORMAT JSON RETURNING json) AS "json_array"
+DROP VIEW json_array_subquery_view;
-- Test mutability of JSON_OBJECTAGG, JSON_ARRAYAGG, JSON_ARRAY, JSON_OBJECT
create type comp1 as (a int, b date);
create domain d_comp1 as comp1;
DROP VIEW json_array_subquery_view;
+-- JSON_ARRAY(subquery) with an input FORMAT clause
+CREATE VIEW json_array_subquery_view AS
+SELECT JSON_ARRAY(SELECT '{"a": 1}'::text FORMAT JSON);
+
+\sv json_array_subquery_view
+
+DROP VIEW json_array_subquery_view;
+
-- Test mutability of JSON_OBJECTAGG, JSON_ARRAYAGG, JSON_ARRAY, JSON_OBJECT
create type comp1 as (a int, b date);
create domain d_comp1 as comp1;