From 26204e454877601a7fe4993dcc6e7790126ad7d2 Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Fri, 30 Aug 2024 12:55:04 +0900 Subject: [PATCH v2 3/4] SQL/JSON: Fix JSON_TABLE() column deparsing The deparsing code in get_json_expr_options() unnecessarily emitted the default column-specific ON ERROR / EMPTY behavior when the top-level ON ERROR behavior in JSON_TABLE was set to ERROR. Fix that by not overriding the column-specific default, determined based on the column's JsonExprOp in get_json_table_columns(), with JSON_BEHAVIOR_ERROR when that is the top-level ON ERROR behavior. Note that this only removes redundancy; the current deparsing output is not incorrect, just redundant. Discussion: https://postgr.es/m/CACJufxEo4sUjKCYtda0_qt9tazqqKPmF1cqhW9KBOUeJFqQd2g@mail.gmail.com --- src/backend/utils/adt/ruleutils.c | 8 +++---- .../regress/expected/sqljson_jsontable.out | 24 ++++++++++++++++--- src/test/regress/sql/sqljson_jsontable.sql | 5 ++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 0aa090be20..cd9c3eddd1 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -11719,7 +11719,6 @@ get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan, bool showimplicit) { StringInfo buf = context->buf; - JsonExpr *jexpr = castNode(JsonExpr, tf->docexpr); ListCell *lc_colname; ListCell *lc_coltype; ListCell *lc_coltypmod; @@ -11772,6 +11771,10 @@ get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan, if (ordinality) continue; + /* + * Set default_behavior to guide get_json_expr_options() on whether to + * to emit the ON ERROR / EMPTY clauses. + */ if (colexpr->op == JSON_EXISTS_OP) { appendStringInfoString(buf, " EXISTS"); @@ -11795,9 +11798,6 @@ get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan, default_behavior = JSON_BEHAVIOR_NULL; } - if (jexpr->on_error->btype == JSON_BEHAVIOR_ERROR) - default_behavior = JSON_BEHAVIOR_ERROR; - appendStringInfoString(buf, " PATH "); get_json_path_spec(colexpr->path_spec, context, showimplicit); diff --git a/src/test/regress/expected/sqljson_jsontable.out b/src/test/regress/expected/sqljson_jsontable.out index f25d03bc77..1a24e478eb 100644 --- a/src/test/regress/expected/sqljson_jsontable.out +++ b/src/test/regress/expected/sqljson_jsontable.out @@ -1158,10 +1158,28 @@ EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EM (3 rows) EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') ERROR ON ERROR); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- Table Function Scan on "json_table" (cost=0.01..1.00 rows=100 width=32) Output: a - Table Function Call: JSON_TABLE('"a"'::jsonb, '$' AS json_table_path_0 COLUMNS (a text PATH '$' NULL ON EMPTY NULL ON ERROR) ERROR ON ERROR) + Table Function Call: JSON_TABLE('"a"'::jsonb, '$' AS json_table_path_0 COLUMNS (a text PATH '$') ERROR ON ERROR) +(3 rows) + +-- Test JSON_TABLE() column deparsing -- don't emit default ON ERROR / EMPTY +-- behavior +EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$')); + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Table Function Scan on "json_table" (cost=0.01..1.00 rows=100 width=32) + Output: a + Table Function Call: JSON_TABLE('"a"'::jsonb, '$' AS json_table_path_0 COLUMNS (a text PATH '$')) +(3 rows) + +EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') ERROR ON ERROR); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Table Function Scan on "json_table" (cost=0.01..1.00 rows=100 width=32) + Output: a + Table Function Call: JSON_TABLE('"a"'::jsonb, '$' AS json_table_path_0 COLUMNS (a text PATH '$') ERROR ON ERROR) (3 rows) diff --git a/src/test/regress/sql/sqljson_jsontable.sql b/src/test/regress/sql/sqljson_jsontable.sql index 932a3ecf59..6d2b5be027 100644 --- a/src/test/regress/sql/sqljson_jsontable.sql +++ b/src/test/regress/sql/sqljson_jsontable.sql @@ -548,3 +548,8 @@ EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$')); EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ON ERROR); EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ARRAY ON ERROR); EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') ERROR ON ERROR); + +-- Test JSON_TABLE() column deparsing -- don't emit default ON ERROR / EMPTY +-- behavior +EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$')); +EXPLAIN VERBOSE SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') ERROR ON ERROR); -- 2.43.0