From 47bea76c6cf108e0fe7445d97f4398bc920ca48d Mon Sep 17 00:00:00 2001 From: naisila Date: Mon, 12 Sep 2022 11:29:07 +0300 Subject: [PATCH] Revert "Support JSON_TABLE on PG 15 (#6241)" This reverts commit 1f4fe35512dafbba89e6fe89606c5639f10e69b1. --- .../planner/multi_logical_planner.c | 3 +- .../planner/query_pushdown_planning.c | 63 +- .../distributed/query_pushdown_planning.h | 2 +- .../expected/json_table_select_only.out | 1583 ----------------- .../expected/json_table_select_only_0.out | 9 - src/test/regress/expected/pg15_json.out | 488 ----- src/test/regress/expected/pg15_json_0.out | 9 - src/test/regress/json_table_select_only.out | 1572 ---------------- src/test/regress/json_table_select_only_0.out | 9 - src/test/regress/multi_schedule | 2 +- .../regress/sql/json_table_select_only.sql | 330 ---- src/test/regress/sql/pg15_json.sql | 326 ---- 12 files changed, 7 insertions(+), 4389 deletions(-) delete mode 100644 src/test/regress/expected/json_table_select_only.out delete mode 100644 src/test/regress/expected/json_table_select_only_0.out delete mode 100644 src/test/regress/expected/pg15_json.out delete mode 100644 src/test/regress/expected/pg15_json_0.out delete mode 100644 src/test/regress/json_table_select_only.out delete mode 100644 src/test/regress/json_table_select_only_0.out delete mode 100644 src/test/regress/sql/json_table_select_only.sql delete mode 100644 src/test/regress/sql/pg15_json.sql diff --git a/src/backend/distributed/planner/multi_logical_planner.c b/src/backend/distributed/planner/multi_logical_planner.c index 14dfa924f..7e665b567 100644 --- a/src/backend/distributed/planner/multi_logical_planner.c +++ b/src/backend/distributed/planner/multi_logical_planner.c @@ -1154,8 +1154,7 @@ HasComplexRangeTableType(Query *queryTree) if (rangeTableEntry->rtekind != RTE_RELATION && rangeTableEntry->rtekind != RTE_SUBQUERY && rangeTableEntry->rtekind != RTE_FUNCTION && - rangeTableEntry->rtekind != RTE_VALUES && - !IsJsonTableRTE(rangeTableEntry)) + rangeTableEntry->rtekind != RTE_VALUES) { hasComplexRangeTableType = true; } diff --git a/src/backend/distributed/planner/query_pushdown_planning.c b/src/backend/distributed/planner/query_pushdown_planning.c index 964acfff4..5ad7887e9 100644 --- a/src/backend/distributed/planner/query_pushdown_planning.c +++ b/src/backend/distributed/planner/query_pushdown_planning.c @@ -60,8 +60,7 @@ typedef enum RecurringTuplesType RECURRING_TUPLES_FUNCTION, RECURRING_TUPLES_EMPTY_JOIN_TREE, RECURRING_TUPLES_RESULT_FUNCTION, - RECURRING_TUPLES_VALUES, - RECURRING_TUPLES_JSON_TABLE + RECURRING_TUPLES_VALUES } RecurringTuplesType; /* @@ -346,8 +345,7 @@ IsFunctionOrValuesRTE(Node *node) RangeTblEntry *rangeTblEntry = (RangeTblEntry *) node; if (rangeTblEntry->rtekind == RTE_FUNCTION || - rangeTblEntry->rtekind == RTE_VALUES || - IsJsonTableRTE(rangeTblEntry)) + rangeTblEntry->rtekind == RTE_VALUES) { return true; } @@ -720,13 +718,6 @@ DeferErrorIfFromClauseRecurs(Query *queryTree) "the FROM clause contains VALUES", NULL, NULL); } - else if (recurType == RECURRING_TUPLES_JSON_TABLE) - { - return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, - "correlated subqueries are not supported when " - "the FROM clause contains JSON_TABLE", NULL, - NULL); - } /* @@ -954,13 +945,6 @@ DeferredErrorIfUnsupportedRecurringTuplesJoin( "There exist a VALUES clause in the outer " "part of the outer join", NULL); } - else if (recurType == RECURRING_TUPLES_JSON_TABLE) - { - return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, - "cannot pushdown the subquery", - "There exist a JSON_TABLE clause in the outer " - "part of the outer join", NULL); - } return NULL; } @@ -1251,8 +1235,7 @@ DeferErrorIfUnsupportedTableCombination(Query *queryTree) */ if (rangeTableEntry->rtekind == RTE_RELATION || rangeTableEntry->rtekind == RTE_SUBQUERY || - rangeTableEntry->rtekind == RTE_RESULT || - IsJsonTableRTE(rangeTableEntry)) /* TODO: can we have volatile???*/ + rangeTableEntry->rtekind == RTE_RESULT) { /* accepted */ } @@ -1420,13 +1403,6 @@ DeferErrorIfUnsupportedUnionQuery(Query *subqueryTree) "VALUES is not supported within a " "UNION", NULL); } - else if (recurType == RECURRING_TUPLES_JSON_TABLE) - { - return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, - "cannot push down this subquery", - "JSON_TABLE is not supported within a " - "UNION", NULL); - } return NULL; } @@ -1526,11 +1502,6 @@ RecurringTypeDescription(RecurringTuplesType recurType) return "a VALUES clause"; } - case RECURRING_TUPLES_JSON_TABLE: - { - return "a JSON_TABLE"; - } - case RECURRING_TUPLES_INVALID: { /* @@ -1727,8 +1698,7 @@ DeferredErrorIfUnsupportedLateralSubquery(PlannerInfo *plannerInfo, * strings anyway. */ if (recurType != RECURRING_TUPLES_VALUES && - recurType != RECURRING_TUPLES_RESULT_FUNCTION && - recurType != RECURRING_TUPLES_JSON_TABLE) + recurType != RECURRING_TUPLES_RESULT_FUNCTION) { recurTypeDescription = psprintf("%s (%s)", recurTypeDescription, recurringRangeTableEntry->eref-> @@ -1805,26 +1775,6 @@ ContainsRecurringRangeTable(List *rangeTable, RecurringTuplesType *recurType) } -/* - * IsJsonTableRTE checks whether the RTE refers to a JSON_TABLE - * table function, which was introduced in PostgreSQL 15. - */ -bool -IsJsonTableRTE(RangeTblEntry *rte) -{ -#if PG_VERSION_NUM >= PG_VERSION_15 - if (rte == NULL) - { - return false; - } - return (rte->rtekind == RTE_TABLEFUNC && - rte->tablefunc->functype == TFT_JSON_TABLE); -#endif - - return false; -} - - /* * HasRecurringTuples returns whether any part of the expression will generate * the same set of tuples in every query on shards when executing a distributed @@ -1886,11 +1836,6 @@ HasRecurringTuples(Node *node, RecurringTuplesType *recurType) *recurType = RECURRING_TUPLES_VALUES; return true; } - else if (IsJsonTableRTE(rangeTableEntry)) - { - *recurType = RECURRING_TUPLES_JSON_TABLE; - return true; - } return false; } diff --git a/src/include/distributed/query_pushdown_planning.h b/src/include/distributed/query_pushdown_planning.h index 3c30b7814..061a4a730 100644 --- a/src/include/distributed/query_pushdown_planning.h +++ b/src/include/distributed/query_pushdown_planning.h @@ -46,6 +46,6 @@ extern DeferredErrorMessage * DeferErrorIfCannotPushdownSubquery(Query *subquery bool outerMostQueryHasLimit); extern DeferredErrorMessage * DeferErrorIfUnsupportedUnionQuery(Query *queryTree); -extern bool IsJsonTableRTE(RangeTblEntry *rte); + #endif /* QUERY_PUSHDOWN_PLANNING_H */ diff --git a/src/test/regress/expected/json_table_select_only.out b/src/test/regress/expected/json_table_select_only.out deleted file mode 100644 index 0ce4edc68..000000000 --- a/src/test/regress/expected/json_table_select_only.out +++ /dev/null @@ -1,1583 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q -\endif -SET search_path TO "json table"; -CREATE SCHEMA "json table"; -SET search_path TO "json table"; -CREATE TABLE jsonb_table_test (id bigserial, js jsonb); -SELECT create_distributed_table('jsonb_table_test', 'id'); - create_distributed_table ---------------------------------------------------------------------- - -(1 row) - --- insert some data -INSERT INTO jsonb_table_test (js) -VALUES ( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "d": [], "c": []}, - {"a": 2, "d": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "d": [1, 2], "c": []}, - {"x": "4", "d": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [100, 200, 300], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": [null]}, - {"x": "4", "b": [1, 2], "c": 2} - ]' -), -( - '[ - {"y": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "t": [1, 2], "c": []}, - {"x": "4", "b": [1, 200], "c": 96} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "100", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"t": 1, "b": [], "c": []}, - {"t": 2, "b": [1, 2, 3], "x": [10, null, 20]}, - {"t": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"U": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1000, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "T": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"ffa": 1, "b": [], "c": []}, - {"ffb": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"fffc": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -); --- unspecified plan (outer, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- default plan (outer, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (outer, union) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- specific plan (p outer (pb union pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pb union pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- specific plan (p outer (pc union pb)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pc union pb)) - ) jt ORDER BY 1,2,3,4; - n | a | c | b ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 10 | - 2 | -1 | 20 | - 2 | -1 | | 1 - 2 | -1 | | 1 - 2 | -1 | | 2 - 2 | -1 | | 2 - 2 | -1 | | 3 - 2 | -1 | | 3 - 2 | -1 | | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 100 - 2 | 2 | | 200 - 2 | 2 | | 300 - 2 | 2 | | 1000 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | | 1 - 3 | -1 | | 1 - 3 | -1 | | 2 - 3 | -1 | | 2 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 200 - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- default plan (inner, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (inner) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | -(107 rows) - --- specific plan (p inner (pb union pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p inner (pb union pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | -(107 rows) - --- default plan (inner, cross) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (cross, inner) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 3 | 3 | 1 | - 3 | 3 | 2 | -(92 rows) - --- specific plan (p inner (pb cross pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p inner (pb cross pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 3 | 3 | 1 | - 3 | 3 | 2 | -(92 rows) - --- default plan (outer, cross) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (outer, cross) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | -1 | | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 2 | 2 | | - 3 | -1 | | - 3 | -1 | | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | -(129 rows) - --- specific plan (p outer (pb cross pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pb cross pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | -1 | | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 2 | 2 | | - 3 | -1 | | - 3 | -1 | | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | -(129 rows) - -select - jt.*, b1 + 100 as b -from - json_table (jsonb - '[ - {"a": 1, "b": [[1, 10], [2], [3, 30, 300]], "c": [1, null, 2]}, - {"a": 2, "b": [10, 20], "c": [1, null, 2]}, - {"x": "3", "b": [11, 22, 33, 44]} - ]', - '$[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on error, - nested path 'strict $.b[*]' as pb columns ( - b text format json path '$', - nested path 'strict $[*]' as pb1 columns ( - b1 int path '$' - ) - ), - nested path 'strict $.c[*]' as pc columns ( - c text format json path '$', - nested path 'strict $[*]' as pc1 columns ( - c1 int path '$' - ) - ) - ) - --plan default(outer, cross) - plan(p outer ((pb inner pb1) cross (pc outer pc1))) - ) jt ORDER BY 1,2,3,4,5; - n | a | b | b1 | c | c1 | b ---------------------------------------------------------------------- - 1 | 1 | [1, 10] | 1 | 1 | | 101 - 1 | 1 | [1, 10] | 1 | 2 | | 101 - 1 | 1 | [1, 10] | 1 | null | | 101 - 1 | 1 | [1, 10] | 10 | 1 | | 110 - 1 | 1 | [1, 10] | 10 | 2 | | 110 - 1 | 1 | [1, 10] | 10 | null | | 110 - 1 | 1 | [2] | 2 | 1 | | 102 - 1 | 1 | [2] | 2 | 2 | | 102 - 1 | 1 | [2] | 2 | null | | 102 - 1 | 1 | [3, 30, 300] | 3 | 1 | | 103 - 1 | 1 | [3, 30, 300] | 3 | 2 | | 103 - 1 | 1 | [3, 30, 300] | 3 | null | | 103 - 1 | 1 | [3, 30, 300] | 30 | 1 | | 130 - 1 | 1 | [3, 30, 300] | 30 | 2 | | 130 - 1 | 1 | [3, 30, 300] | 30 | null | | 130 - 1 | 1 | [3, 30, 300] | 300 | 1 | | 400 - 1 | 1 | [3, 30, 300] | 300 | 2 | | 400 - 1 | 1 | [3, 30, 300] | 300 | null | | 400 - 2 | 2 | | | | | - 3 | | | | | | -(20 rows) - --- Should succeed (JSON arguments are passed to root and nested paths) -SELECT * -FROM - generate_series(1, 4) x, - generate_series(1, 3) y, - JSON_TABLE(jsonb - '[[1,2,3],[2,3,4,5],[3,4,5,6]]', - 'strict $[*] ? (@[*] < $x)' - PASSING x AS x, y AS y - COLUMNS ( - y text FORMAT JSON PATH '$', - NESTED PATH 'strict $[*] ? (@ >= $y)' - COLUMNS ( - z int PATH '$' - ) - ) - ) jt ORDER BY 4,1,2,3; - x | y | y | z ---------------------------------------------------------------------- - 2 | 1 | [1, 2, 3] | 1 - 3 | 1 | [1, 2, 3] | 1 - 4 | 1 | [1, 2, 3] | 1 - 2 | 1 | [1, 2, 3] | 2 - 2 | 2 | [1, 2, 3] | 2 - 3 | 1 | [1, 2, 3] | 2 - 3 | 1 | [2, 3, 4, 5] | 2 - 3 | 2 | [1, 2, 3] | 2 - 3 | 2 | [2, 3, 4, 5] | 2 - 4 | 1 | [1, 2, 3] | 2 - 4 | 1 | [2, 3, 4, 5] | 2 - 4 | 2 | [1, 2, 3] | 2 - 4 | 2 | [2, 3, 4, 5] | 2 - 2 | 1 | [1, 2, 3] | 3 - 2 | 2 | [1, 2, 3] | 3 - 2 | 3 | [1, 2, 3] | 3 - 3 | 1 | [1, 2, 3] | 3 - 3 | 1 | [2, 3, 4, 5] | 3 - 3 | 2 | [1, 2, 3] | 3 - 3 | 2 | [2, 3, 4, 5] | 3 - 3 | 3 | [1, 2, 3] | 3 - 3 | 3 | [2, 3, 4, 5] | 3 - 4 | 1 | [1, 2, 3] | 3 - 4 | 1 | [2, 3, 4, 5] | 3 - 4 | 1 | [3, 4, 5, 6] | 3 - 4 | 2 | [1, 2, 3] | 3 - 4 | 2 | [2, 3, 4, 5] | 3 - 4 | 2 | [3, 4, 5, 6] | 3 - 4 | 3 | [1, 2, 3] | 3 - 4 | 3 | [2, 3, 4, 5] | 3 - 4 | 3 | [3, 4, 5, 6] | 3 - 3 | 1 | [2, 3, 4, 5] | 4 - 3 | 2 | [2, 3, 4, 5] | 4 - 3 | 3 | [2, 3, 4, 5] | 4 - 4 | 1 | [2, 3, 4, 5] | 4 - 4 | 1 | [3, 4, 5, 6] | 4 - 4 | 2 | [2, 3, 4, 5] | 4 - 4 | 2 | [3, 4, 5, 6] | 4 - 4 | 3 | [2, 3, 4, 5] | 4 - 4 | 3 | [3, 4, 5, 6] | 4 - 3 | 1 | [2, 3, 4, 5] | 5 - 3 | 2 | [2, 3, 4, 5] | 5 - 3 | 3 | [2, 3, 4, 5] | 5 - 4 | 1 | [2, 3, 4, 5] | 5 - 4 | 1 | [3, 4, 5, 6] | 5 - 4 | 2 | [2, 3, 4, 5] | 5 - 4 | 2 | [3, 4, 5, 6] | 5 - 4 | 3 | [2, 3, 4, 5] | 5 - 4 | 3 | [3, 4, 5, 6] | 5 - 4 | 1 | [3, 4, 5, 6] | 6 - 4 | 2 | [3, 4, 5, 6] | 6 - 4 | 3 | [3, 4, 5, 6] | 6 -(52 rows) - -SET client_min_messages TO ERROR; -DROP SCHEMA "json table" CASCADE; diff --git a/src/test/regress/expected/json_table_select_only_0.out b/src/test/regress/expected/json_table_select_only_0.out deleted file mode 100644 index c04e76814..000000000 --- a/src/test/regress/expected/json_table_select_only_0.out +++ /dev/null @@ -1,9 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q diff --git a/src/test/regress/expected/pg15_json.out b/src/test/regress/expected/pg15_json.out deleted file mode 100644 index be263337a..000000000 --- a/src/test/regress/expected/pg15_json.out +++ /dev/null @@ -1,488 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q -\endif -CREATE SCHEMA pg15_json; -SET search_path TO pg15_json; -SET citus.next_shard_id TO 1687000; -CREATE TABLE test_table(id bigserial, value text); -SELECT create_distributed_table('test_table', 'id'); - create_distributed_table ---------------------------------------------------------------------- - -(1 row) - -INSERT INTO test_table (value) SELECT i::text FROM generate_series(0,100)i; -CREATE TABLE my_films(id bigserial, js jsonb); -SELECT create_distributed_table('my_films', 'id'); - create_distributed_table ---------------------------------------------------------------------- - -(1 row) - -INSERT INTO my_films(js) VALUES ( -'{ "favorites" : [ - { "kind" : "comedy", "films" : [ { "title" : "Bananas", "director" : "Woody Allen"}, - { "title" : "The Dinner Game", "director" : "Francis Veber" } ] }, - { "kind" : "horror", "films" : [{ "title" : "Psycho", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "thriller", "films" : [{ "title" : "Vertigo", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "drama", "films" : [{ "title" : "Yojimbo", "director" : "Akira Kurosawa" } ] } - ] }'); -INSERT INTO my_films(js) VALUES ( -'{ "favorites" : [ - { "kind" : "comedy", "films" : [ { "title" : "Bananas2", "director" : "Woody Allen"}, - { "title" : "The Dinner Game2", "director" : "Francis Veber" } ] }, - { "kind" : "horror", "films" : [{ "title" : "Psycho2", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "thriller", "films" : [{ "title" : "Vertigo2", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "drama", "films" : [{ "title" : "Yojimbo2", "director" : "Akira Kurosawa" } ] } - ] }'); --- a router query -SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt - WHERE my_films.id = 1 - ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 1 | comedy | Bananas | Woody Allen - 1 | comedy | The Dinner Game | Francis Veber - 2 | horror | Psycho | Alfred Hitchcock - 3 | thriller | Vertigo | Alfred Hitchcock - 4 | drama | Yojimbo | Akira Kurosawa -(5 rows) - --- router query with an explicit LATEREL SUBQUERY -SELECT sub.* -FROM my_films, - lateral(SELECT * FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt) as sub -WHERE my_films.id = 1 ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 1 | comedy | Bananas | Woody Allen - 1 | comedy | The Dinner Game | Francis Veber - 2 | horror | Psycho | Alfred Hitchcock - 3 | thriller | Vertigo | Alfred Hitchcock - 4 | drama | Yojimbo | Akira Kurosawa -(5 rows) - --- router query with an explicit LATEREL SUBQUERY and LIMIT -SELECT sub.* -FROM my_films, - lateral(SELECT * FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt ORDER BY id DESC LIMIT 1) as sub -WHERE my_films.id = 1 ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 4 | drama | Yojimbo | Akira Kurosawa -(1 row) - --- set it DEBUG1 in case the plan changes --- we can see details -SET client_min_messages TO DEBUG1; --- a mult-shard query -SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt - ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 1 | comedy | Bananas | Woody Allen - 1 | comedy | Bananas2 | Woody Allen - 1 | comedy | The Dinner Game | Francis Veber - 1 | comedy | The Dinner Game2 | Francis Veber - 2 | horror | Psycho | Alfred Hitchcock - 2 | horror | Psycho2 | Alfred Hitchcock - 3 | thriller | Vertigo | Alfred Hitchcock - 3 | thriller | Vertigo2 | Alfred Hitchcock - 4 | drama | Yojimbo | Akira Kurosawa - 4 | drama | Yojimbo2 | Akira Kurosawa -(10 rows) - --- recursively plan subqueries that has JSON_TABLE -SELECT count(*) FROM -( - SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt - LIMIT 1) as sub_with_json, test_table -WHERE test_table.id = sub_with_json.id; -DEBUG: push down of limit count: 1 -DEBUG: generating subplan XXX_1 for subquery SELECT jt.id, jt.kind, jt.title, jt.director FROM pg15_json.my_films, LATERAL JSON_TABLE(my_films.js, '$."favorites"[*]' AS json_table_path_1 COLUMNS (id FOR ORDINALITY, kind text PATH '$."kind"', NESTED PATH '$."films"[*]' AS json_table_path_2 COLUMNS (title text PATH '$."title"', director text PATH '$."director"')) PLAN (json_table_path_1 OUTER json_table_path_2)) jt LIMIT 1 -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.id, intermediate_result.kind, intermediate_result.title, intermediate_result.director FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer, kind text, title text, director text)) sub_with_json, pg15_json.test_table WHERE (test_table.id OPERATOR(pg_catalog.=) sub_with_json.id) - count ---------------------------------------------------------------------- - 1 -(1 row) - --- multi-shard query with an explicit LATEREL SUBQUERY -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) - ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 1 | comedy | Bananas | Woody Allen - 1 | comedy | Bananas2 | Woody Allen - 1 | comedy | The Dinner Game | Francis Veber - 1 | comedy | The Dinner Game2 | Francis Veber - 2 | horror | Psycho | Alfred Hitchcock - 2 | horror | Psycho2 | Alfred Hitchcock - 3 | thriller | Vertigo | Alfred Hitchcock - 3 | thriller | Vertigo2 | Alfred Hitchcock - 4 | drama | Yojimbo | Akira Kurosawa - 4 | drama | Yojimbo2 | Akira Kurosawa -(10 rows) - --- JSON_TABLE can be on the inner part of an outer joion -SELECT sub.* -FROM my_films LEFT JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) - ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 1 | comedy | Bananas | Woody Allen - 1 | comedy | Bananas2 | Woody Allen - 1 | comedy | The Dinner Game | Francis Veber - 1 | comedy | The Dinner Game2 | Francis Veber - 2 | horror | Psycho | Alfred Hitchcock - 2 | horror | Psycho2 | Alfred Hitchcock - 3 | thriller | Vertigo | Alfred Hitchcock - 3 | thriller | Vertigo2 | Alfred Hitchcock - 4 | drama | Yojimbo | Akira Kurosawa - 4 | drama | Yojimbo2 | Akira Kurosawa -(10 rows) - --- we can pushdown this correlated subquery in WHERE clause -SELECT count(*) -FROM my_films WHERE - (SELECT count(*) > 0 - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000); - count ---------------------------------------------------------------------- - 2 -(1 row) - --- we can pushdown this correlated subquery in SELECT clause - SELECT (SELECT count(*) > 0 - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt) -FROM my_films; - ?column? ---------------------------------------------------------------------- - t - t -(2 rows) - --- multi-shard query with an explicit LATEREL SUBQUERY --- along with other tables -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) JOIN test_table ON(my_films.id = test_table.id) - ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 1 | comedy | Bananas | Woody Allen - 1 | comedy | Bananas2 | Woody Allen - 1 | comedy | The Dinner Game | Francis Veber - 1 | comedy | The Dinner Game2 | Francis Veber - 2 | horror | Psycho | Alfred Hitchcock - 2 | horror | Psycho2 | Alfred Hitchcock - 3 | thriller | Vertigo | Alfred Hitchcock - 3 | thriller | Vertigo2 | Alfred Hitchcock - 4 | drama | Yojimbo | Akira Kurosawa - 4 | drama | Yojimbo2 | Akira Kurosawa -(10 rows) - --- non-colocated join fails -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) JOIN test_table ON(my_films.id != test_table.id) - ORDER BY 1,2,3,4; -ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns --- JSON_TABLE can be in the outer part of the join --- as long as there is a distributed table -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) LEFT JOIN test_table ON(my_films.id = test_table.id) - ORDER BY 1,2,3,4; - id | kind | title | director ---------------------------------------------------------------------- - 1 | comedy | Bananas | Woody Allen - 1 | comedy | Bananas2 | Woody Allen - 1 | comedy | The Dinner Game | Francis Veber - 1 | comedy | The Dinner Game2 | Francis Veber - 2 | horror | Psycho | Alfred Hitchcock - 2 | horror | Psycho2 | Alfred Hitchcock - 3 | thriller | Vertigo | Alfred Hitchcock - 3 | thriller | Vertigo2 | Alfred Hitchcock - 4 | drama | Yojimbo | Akira Kurosawa - 4 | drama | Yojimbo2 | Akira Kurosawa -(10 rows) - --- JSON_TABLE cannot be on the outer side of the join -SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY, column_a int4 PATH '$.a', column_b int4 PATH '$.b', a int4, b int4, c text)) -LEFT JOIN LATERAL - (SELECT * - FROM my_films) AS foo on(foo.id = a); -ERROR: cannot pushdown the subquery -DETAIL: There exist a JSON_TABLE clause in the outer part of the outer join --- JSON_TABLE cannot be on the FROM clause alone -SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY, column_a int4 PATH '$.a', column_b int4 PATH '$.b', a int4, b int4, c text)) as foo -WHERE b > - (SELECT count(*) - FROM my_films WHERE id = foo.a); -ERROR: correlated subqueries are not supported when the FROM clause contains JSON_TABLE --- we can recursively plan json_tables on set operations -(SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY)) ORDER BY id ASC LIMIT 1) -UNION -(SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY)) ORDER BY id ASC LIMIT 1) -UNION -(SELECT id FROM test_table ORDER BY id ASC LIMIT 1); -DEBUG: generating subplan XXX_1 for subquery SELECT id FROM JSON_TABLE('[{"a": 10, "b": 20}, {"a": 30, "b": 40}]'::jsonb, '$[*]' AS json_table_path_1 COLUMNS (id FOR ORDINALITY) PLAN (json_table_path_1)) ORDER BY id LIMIT 1 -DEBUG: generating subplan XXX_2 for subquery SELECT id FROM JSON_TABLE('[{"a": 10, "b": 20}, {"a": 30, "b": 40}]'::jsonb, '$[*]' AS json_table_path_1 COLUMNS (id FOR ORDINALITY) PLAN (json_table_path_1)) ORDER BY id LIMIT 1 -DEBUG: push down of limit count: 1 -DEBUG: generating subplan XXX_3 for subquery SELECT id FROM pg15_json.test_table ORDER BY id LIMIT 1 -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT intermediate_result.id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer) UNION SELECT intermediate_result.id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(id integer) UNION SELECT intermediate_result.id FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(id bigint) - id ---------------------------------------------------------------------- - 1 -(1 row) - --- LIMIT in subquery not supported when json_table exists -SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY, column_a int4 PATH '$.a', column_b int4 PATH '$.b', a int4, b int4, c text)) -JOIN LATERAL - (SELECT * - FROM my_films WHERE json_table.id = a LIMIT 1) as foo ON (true); -ERROR: cannot push down this subquery -DETAIL: Limit clause is currently unsupported when a lateral subquery references a column from a JSON_TABLE --- a little more complex query with multiple json_table -SELECT - director1 AS director, title1, kind1, title2, kind2 -FROM - my_films, - JSON_TABLE ( js, '$.favorites' AS favs COLUMNS ( - NESTED PATH '$[*]' AS films1 COLUMNS ( - kind1 text PATH '$.kind', - NESTED PATH '$.films[*]' AS film1 COLUMNS ( - title1 text PATH '$.title', - director1 text PATH '$.director') - ), - NESTED PATH '$[*]' AS films2 COLUMNS ( - kind2 text PATH '$.kind', - NESTED PATH '$.films[*]' AS film2 COLUMNS ( - title2 text PATH '$.title', - director2 text PATH '$.director' - ) - ) - ) - PLAN (favs INNER ((films1 INNER film1) CROSS (films2 INNER film2))) - ) AS jt - WHERE kind1 > kind2 AND director1 = director2 - ORDER BY 1,2,3,4; - director | title1 | kind1 | title2 | kind2 ---------------------------------------------------------------------- - Alfred Hitchcock | Vertigo | thriller | Psycho | horror - Alfred Hitchcock | Vertigo2 | thriller | Psycho2 | horror -(2 rows) - -RESET client_min_messages; --- test some utility functions on the target list & where clause -select jsonb_path_exists(js, '$.favorites') from my_films; - jsonb_path_exists ---------------------------------------------------------------------- - t - t -(2 rows) - -select bool_and(JSON_EXISTS(js, '$.favorites.films.title')) from my_films; - bool_and ---------------------------------------------------------------------- - t -(1 row) - -SELECT count(*) FROM my_films WHERE jsonb_path_exists(js, '$.favorites'); - count ---------------------------------------------------------------------- - 2 -(1 row) - -SELECT count(*) FROM my_films WHERE jsonb_path_exists(js, '$.favorites'); - count ---------------------------------------------------------------------- - 2 -(1 row) - -SELECT count(*) FROM my_films WHERE JSON_EXISTS(js, '$.favorites.films.title'); - count ---------------------------------------------------------------------- - 2 -(1 row) - --- check constraint with json_exists -create table user_profiles ( - id bigserial, - addresses jsonb, - anyjson jsonb, - check (json_exists( addresses, '$.main' )) -); -select create_distributed_table('user_profiles', 'id'); - create_distributed_table ---------------------------------------------------------------------- - -(1 row) - -insert into user_profiles (addresses) VALUES (JSON_SCALAR('1')); -ERROR: new row for relation "user_profiles_1687008" violates check constraint "user_profiles_addresses_check" -DETAIL: Failing row contains (1, "1", null). -CONTEXT: while executing command on localhost:xxxxx -insert into user_profiles (addresses) VALUES ('{"main":"value"}'); --- we cannot insert because WITH UNIQUE KEYS -insert into user_profiles (addresses) VALUES (JSON ('{"main":"value", "main":"value"}' WITH UNIQUE KEYS)); -ERROR: duplicate JSON object key value --- we can insert with -insert into user_profiles (addresses) VALUES (JSON ('{"main":"value", "main":"value"}' WITHOUT UNIQUE KEYS)) RETURNING *; - id | addresses | anyjson ---------------------------------------------------------------------- - 4 | {"main": "value"} | -(1 row) - -TRUNCATE user_profiles; -INSERT INTO user_profiles (anyjson) VALUES ('12'), ('"abc"'), ('[1,2,3]'), ('{"a":12}'); -select anyjson, anyjson is json array as json_array, anyjson is json object as json_object, anyjson is json scalar as json_scalar, -anyjson is json with UNIQUE keys -from user_profiles WHERE anyjson IS NOT NULL ORDER BY 1; - anyjson | json_array | json_object | json_scalar | ?column? ---------------------------------------------------------------------- - "abc" | f | f | t | t - 12 | f | f | t | t - [1, 2, 3] | t | f | f | t - {"a": 12} | f | t | f | t -(4 rows) - --- use json_query -SELECT i, - json_query('[{"x": "aaa"},{"x": "bbb"},{"x": "ccc"}]'::JSONB, '$[$i].x' passing id AS i RETURNING text omit quotes) -FROM generate_series(0, 3) i -JOIN my_films ON(id = i) ORDER BY 1; - i | json_query ---------------------------------------------------------------------- - 1 | bbb - 2 | ccc -(2 rows) - --- we can use JSON_TABLE in modification queries as well --- use log level such that we can see trace changes -SET client_min_messages TO DEBUG1; ---the JSON_TABLE subquery is recursively planned -UPDATE test_table SET VALUE = 'XXX' FROM( -SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt) as foo WHERE foo.id = test_table.id; -DEBUG: generating subplan XXX_1 for subquery SELECT jt.id, jt.kind, jt.title, jt.director FROM pg15_json.my_films, LATERAL JSON_TABLE(my_films.js, '$."favorites"[*]' AS json_table_path_1 COLUMNS (id FOR ORDINALITY, kind text PATH '$."kind"', NESTED PATH '$."films"[*]' AS json_table_path_2 COLUMNS (title text PATH '$."title"', director text PATH '$."director"')) PLAN (json_table_path_1 OUTER json_table_path_2)) jt -DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE pg15_json.test_table SET value = 'XXX'::text FROM (SELECT intermediate_result.id, intermediate_result.kind, intermediate_result.title, intermediate_result.director FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer, kind text, title text, director text)) foo WHERE (foo.id OPERATOR(pg_catalog.=) test_table.id) --- Subquery with JSON table can be pushed down because two distributed tables --- in the query are joined on distribution column -UPDATE test_table SET VALUE = 'XXX' FROM ( -SELECT my_films.id, jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt) as foo WHERE foo.id = test_table.id; --- we can pushdown with CTEs as well -WITH json_cte AS -(SELECT my_films.id, jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt) -UPDATE test_table SET VALUE = 'XYZ' FROM json_cte - WHERE json_cte.id = test_table.id; - -- we can recursively with CTEs as well -WITH json_cte AS -(SELECT my_films.id as film_id, jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - id FOR ORDINALITY, - title text PATH '$.title', - director text PATH '$.director'))) AS jt ORDER BY jt.id LIMIT 1) -UPDATE test_table SET VALUE = 'XYZ' FROM json_cte - WHERE json_cte.film_id = test_table.id; -DEBUG: generating subplan XXX_1 for CTE json_cte: SELECT my_films.id AS film_id, jt.kind, jt.id, jt.title, jt.director FROM pg15_json.my_films, LATERAL JSON_TABLE(my_films.js, '$."favorites"[*]' AS json_table_path_1 COLUMNS (kind text PATH '$."kind"', NESTED PATH '$."films"[*]' AS json_table_path_2 COLUMNS (id FOR ORDINALITY, title text PATH '$."title"', director text PATH '$."director"')) PLAN (json_table_path_1 OUTER json_table_path_2)) jt ORDER BY jt.id LIMIT 1 -DEBUG: push down of limit count: 1 -DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE pg15_json.test_table SET value = 'XYZ'::text FROM (SELECT intermediate_result.film_id, intermediate_result.kind, intermediate_result.id, intermediate_result.title, intermediate_result.director FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(film_id bigint, kind text, id integer, title text, director text)) json_cte WHERE (json_cte.film_id OPERATOR(pg_catalog.=) test_table.id) -SET client_min_messages TO ERROR; -DROP SCHEMA pg15_json CASCADE; diff --git a/src/test/regress/expected/pg15_json_0.out b/src/test/regress/expected/pg15_json_0.out deleted file mode 100644 index c04e76814..000000000 --- a/src/test/regress/expected/pg15_json_0.out +++ /dev/null @@ -1,9 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q diff --git a/src/test/regress/json_table_select_only.out b/src/test/regress/json_table_select_only.out deleted file mode 100644 index 61a120202..000000000 --- a/src/test/regress/json_table_select_only.out +++ /dev/null @@ -1,1572 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q -\endif -SET search_path TO "json table"; --- insert some data -INSERT INTO jsonb_table_test (js) -VALUES ( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "d": [], "c": []}, - {"a": 2, "d": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "d": [1, 2], "c": []}, - {"x": "4", "d": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [100, 200, 300], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": [null]}, - {"x": "4", "b": [1, 2], "c": 2} - ]' -), -( - '[ - {"y": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "t": [1, 2], "c": []}, - {"x": "4", "b": [1, 200], "c": 96} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "100", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"t": 1, "b": [], "c": []}, - {"t": 2, "b": [1, 2, 3], "x": [10, null, 20]}, - {"t": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"U": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1000, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "T": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"ffa": 1, "b": [], "c": []}, - {"ffb": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"fffc": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -); --- unspecified plan (outer, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- default plan (outer, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (outer, union) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- specific plan (p outer (pb union pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pb union pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- specific plan (p outer (pc union pb)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pc union pb)) - ) jt ORDER BY 1,2,3,4; - n | a | c | b ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 10 | - 2 | -1 | 20 | - 2 | -1 | | 1 - 2 | -1 | | 1 - 2 | -1 | | 2 - 2 | -1 | | 2 - 2 | -1 | | 3 - 2 | -1 | | 3 - 2 | -1 | | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 10 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | 20 | - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 1 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 2 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 3 - 2 | 2 | | 100 - 2 | 2 | | 200 - 2 | 2 | | 300 - 2 | 2 | | 1000 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | | 1 - 3 | -1 | | 1 - 3 | -1 | | 2 - 3 | -1 | | 2 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 1 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | 2 - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 1 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 2 - 4 | -1 | | 200 - 4 | -1 | | - 4 | -1 | | -(123 rows) - --- default plan (inner, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (inner) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | -(107 rows) - --- specific plan (p inner (pb union pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p inner (pb union pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | - 2 | -1 | 1 | - 2 | -1 | 2 | - 2 | -1 | 2 | - 2 | -1 | 3 | - 2 | -1 | 3 | - 2 | -1 | | 10 - 2 | -1 | | 20 - 2 | -1 | | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | - 2 | 2 | 200 | - 2 | 2 | 300 | - 2 | 2 | 1000 | - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 10 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | 20 - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 2 | 2 | | - 3 | -1 | 1 | - 3 | -1 | 1 | - 3 | -1 | 2 | - 3 | -1 | 2 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | 2 | - 3 | 3 | | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 1 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 2 | - 4 | -1 | 200 | -(107 rows) - --- default plan (inner, cross) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (cross, inner) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 3 | 3 | 1 | - 3 | 3 | 2 | -(92 rows) - --- specific plan (p inner (pb cross pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p inner (pb cross pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 3 | 3 | 1 | - 3 | 3 | 2 | -(92 rows) - --- default plan (outer, cross) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (outer, cross) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | -1 | | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 2 | 2 | | - 3 | -1 | | - 3 | -1 | | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | -(129 rows) - --- specific plan (p outer (pb cross pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pb cross pc)) - ) jt ORDER BY 1,2,3,4; - n | a | b | c ---------------------------------------------------------------------- - 1 | -1 | | - 1 | -1 | | - 1 | -1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 1 | 1 | | - 2 | -1 | 1 | 10 - 2 | -1 | 1 | 20 - 2 | -1 | 1 | - 2 | -1 | 2 | 10 - 2 | -1 | 2 | 20 - 2 | -1 | 2 | - 2 | -1 | 3 | 10 - 2 | -1 | 3 | 20 - 2 | -1 | 3 | - 2 | -1 | | - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 10 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | 20 - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 1 | - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 10 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | 20 - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 2 | - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 10 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | 20 - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 3 | - 2 | 2 | 100 | 10 - 2 | 2 | 100 | 20 - 2 | 2 | 100 | - 2 | 2 | 200 | 10 - 2 | 2 | 200 | 20 - 2 | 2 | 200 | - 2 | 2 | 300 | 10 - 2 | 2 | 300 | 20 - 2 | 2 | 300 | - 2 | 2 | 1000 | 10 - 2 | 2 | 1000 | 20 - 2 | 2 | 1000 | - 2 | 2 | | - 3 | -1 | | - 3 | -1 | | - 3 | 3 | 1 | - 3 | 3 | 2 | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 3 | 3 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | - 4 | -1 | | -(129 rows) - -select - jt.*, b1 + 100 as b -from - json_table (jsonb - '[ - {"a": 1, "b": [[1, 10], [2], [3, 30, 300]], "c": [1, null, 2]}, - {"a": 2, "b": [10, 20], "c": [1, null, 2]}, - {"x": "3", "b": [11, 22, 33, 44]} - ]', - '$[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on error, - nested path 'strict $.b[*]' as pb columns ( - b text format json path '$', - nested path 'strict $[*]' as pb1 columns ( - b1 int path '$' - ) - ), - nested path 'strict $.c[*]' as pc columns ( - c text format json path '$', - nested path 'strict $[*]' as pc1 columns ( - c1 int path '$' - ) - ) - ) - --plan default(outer, cross) - plan(p outer ((pb inner pb1) cross (pc outer pc1))) - ) jt ORDER BY 1,2,3,4,5; - n | a | b | b1 | c | c1 | b ---------------------------------------------------------------------- - 1 | 1 | [1, 10] | 1 | 1 | | 101 - 1 | 1 | [1, 10] | 1 | 2 | | 101 - 1 | 1 | [1, 10] | 1 | null | | 101 - 1 | 1 | [1, 10] | 10 | 1 | | 110 - 1 | 1 | [1, 10] | 10 | 2 | | 110 - 1 | 1 | [1, 10] | 10 | null | | 110 - 1 | 1 | [2] | 2 | 1 | | 102 - 1 | 1 | [2] | 2 | 2 | | 102 - 1 | 1 | [2] | 2 | null | | 102 - 1 | 1 | [3, 30, 300] | 3 | 1 | | 103 - 1 | 1 | [3, 30, 300] | 3 | 2 | | 103 - 1 | 1 | [3, 30, 300] | 3 | null | | 103 - 1 | 1 | [3, 30, 300] | 30 | 1 | | 130 - 1 | 1 | [3, 30, 300] | 30 | 2 | | 130 - 1 | 1 | [3, 30, 300] | 30 | null | | 130 - 1 | 1 | [3, 30, 300] | 300 | 1 | | 400 - 1 | 1 | [3, 30, 300] | 300 | 2 | | 400 - 1 | 1 | [3, 30, 300] | 300 | null | | 400 - 2 | 2 | | | | | - 3 | | | | | | -(20 rows) - --- Should succeed (JSON arguments are passed to root and nested paths) -SELECT * -FROM - generate_series(1, 4) x, - generate_series(1, 3) y, - JSON_TABLE(jsonb - '[[1,2,3],[2,3,4,5],[3,4,5,6]]', - 'strict $[*] ? (@[*] < $x)' - PASSING x AS x, y AS y - COLUMNS ( - y text FORMAT JSON PATH '$', - NESTED PATH 'strict $[*] ? (@ >= $y)' - COLUMNS ( - z int PATH '$' - ) - ) - ) jt ORDER BY 4,1,2,3; - x | y | y | z ---------------------------------------------------------------------- - 2 | 1 | [1, 2, 3] | 1 - 3 | 1 | [1, 2, 3] | 1 - 4 | 1 | [1, 2, 3] | 1 - 2 | 1 | [1, 2, 3] | 2 - 2 | 2 | [1, 2, 3] | 2 - 3 | 1 | [1, 2, 3] | 2 - 3 | 1 | [2, 3, 4, 5] | 2 - 3 | 2 | [1, 2, 3] | 2 - 3 | 2 | [2, 3, 4, 5] | 2 - 4 | 1 | [1, 2, 3] | 2 - 4 | 1 | [2, 3, 4, 5] | 2 - 4 | 2 | [1, 2, 3] | 2 - 4 | 2 | [2, 3, 4, 5] | 2 - 2 | 1 | [1, 2, 3] | 3 - 2 | 2 | [1, 2, 3] | 3 - 2 | 3 | [1, 2, 3] | 3 - 3 | 1 | [1, 2, 3] | 3 - 3 | 1 | [2, 3, 4, 5] | 3 - 3 | 2 | [1, 2, 3] | 3 - 3 | 2 | [2, 3, 4, 5] | 3 - 3 | 3 | [1, 2, 3] | 3 - 3 | 3 | [2, 3, 4, 5] | 3 - 4 | 1 | [1, 2, 3] | 3 - 4 | 1 | [2, 3, 4, 5] | 3 - 4 | 1 | [3, 4, 5, 6] | 3 - 4 | 2 | [1, 2, 3] | 3 - 4 | 2 | [2, 3, 4, 5] | 3 - 4 | 2 | [3, 4, 5, 6] | 3 - 4 | 3 | [1, 2, 3] | 3 - 4 | 3 | [2, 3, 4, 5] | 3 - 4 | 3 | [3, 4, 5, 6] | 3 - 3 | 1 | [2, 3, 4, 5] | 4 - 3 | 2 | [2, 3, 4, 5] | 4 - 3 | 3 | [2, 3, 4, 5] | 4 - 4 | 1 | [2, 3, 4, 5] | 4 - 4 | 1 | [3, 4, 5, 6] | 4 - 4 | 2 | [2, 3, 4, 5] | 4 - 4 | 2 | [3, 4, 5, 6] | 4 - 4 | 3 | [2, 3, 4, 5] | 4 - 4 | 3 | [3, 4, 5, 6] | 4 - 3 | 1 | [2, 3, 4, 5] | 5 - 3 | 2 | [2, 3, 4, 5] | 5 - 3 | 3 | [2, 3, 4, 5] | 5 - 4 | 1 | [2, 3, 4, 5] | 5 - 4 | 1 | [3, 4, 5, 6] | 5 - 4 | 2 | [2, 3, 4, 5] | 5 - 4 | 2 | [3, 4, 5, 6] | 5 - 4 | 3 | [2, 3, 4, 5] | 5 - 4 | 3 | [3, 4, 5, 6] | 5 - 4 | 1 | [3, 4, 5, 6] | 6 - 4 | 2 | [3, 4, 5, 6] | 6 - 4 | 3 | [3, 4, 5, 6] | 6 -(52 rows) - diff --git a/src/test/regress/json_table_select_only_0.out b/src/test/regress/json_table_select_only_0.out deleted file mode 100644 index c04e76814..000000000 --- a/src/test/regress/json_table_select_only_0.out +++ /dev/null @@ -1,9 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index c7b804f85..c8ad97d5a 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -55,7 +55,7 @@ test: subquery_in_targetlist subquery_in_where subquery_complex_target_list subq test: subquery_prepared_statements test: non_colocated_leaf_subquery_joins non_colocated_subquery_joins test: cte_inline recursive_view_local_table values sequences_with_different_types -test: pg13 pg12 pg15_json json_table_select_only +test: pg13 pg12 # run pg14 sequentially as it syncs metadata test: pg14 test: pg15 diff --git a/src/test/regress/sql/json_table_select_only.sql b/src/test/regress/sql/json_table_select_only.sql deleted file mode 100644 index 250315a25..000000000 --- a/src/test/regress/sql/json_table_select_only.sql +++ /dev/null @@ -1,330 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q -\endif - -SET search_path TO "json table"; - -CREATE SCHEMA "json table"; -SET search_path TO "json table"; -CREATE TABLE jsonb_table_test (id bigserial, js jsonb); -SELECT create_distributed_table('jsonb_table_test', 'id'); - --- insert some data -INSERT INTO jsonb_table_test (js) -VALUES ( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "d": [], "c": []}, - {"a": 2, "d": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "d": [1, 2], "c": []}, - {"x": "4", "d": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [100, 200, 300], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": [null]}, - {"x": "4", "b": [1, 2], "c": 2} - ]' -), -( - '[ - {"y": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "t": [1, 2], "c": []}, - {"x": "4", "b": [1, 200], "c": 96} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "100", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"t": 1, "b": [], "c": []}, - {"t": 2, "b": [1, 2, 3], "x": [10, null, 20]}, - {"t": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"U": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1000, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "T": [1, 2], "c": 123} - ]' -), -( - '[ - {"a": 1, "b": [], "c": []}, - {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"a": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -), -( - '[ - {"ffa": 1, "b": [], "c": []}, - {"ffb": 2, "b": [1, 2, 3], "c": [10, null, 20]}, - {"fffc": 3, "b": [1, 2], "c": []}, - {"x": "4", "b": [1, 2], "c": 123} - ]' -); - --- unspecified plan (outer, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - ) jt ORDER BY 1,2,3,4; - - - --- default plan (outer, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (outer, union) - ) jt ORDER BY 1,2,3,4; - --- specific plan (p outer (pb union pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pb union pc)) - ) jt ORDER BY 1,2,3,4; - --- specific plan (p outer (pc union pb)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pc union pb)) - ) jt ORDER BY 1,2,3,4; - --- default plan (inner, union) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (inner) - ) jt ORDER BY 1,2,3,4; - --- specific plan (p inner (pb union pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p inner (pb union pc)) - ) jt ORDER BY 1,2,3,4; - --- default plan (inner, cross) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (cross, inner) - ) jt ORDER BY 1,2,3,4; - --- specific plan (p inner (pb cross pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p inner (pb cross pc)) - ) jt ORDER BY 1,2,3,4; - --- default plan (outer, cross) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan default (outer, cross) - ) jt ORDER BY 1,2,3,4; - --- specific plan (p outer (pb cross pc)) -select - jt.* -from - jsonb_table_test jtt, - json_table ( - jtt.js,'strict $[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on empty, - nested path 'strict $.b[*]' as pb columns ( b int path '$' ), - nested path 'strict $.c[*]' as pc columns ( c int path '$' ) - ) - plan (p outer (pb cross pc)) - ) jt ORDER BY 1,2,3,4; - - -select - jt.*, b1 + 100 as b -from - json_table (jsonb - '[ - {"a": 1, "b": [[1, 10], [2], [3, 30, 300]], "c": [1, null, 2]}, - {"a": 2, "b": [10, 20], "c": [1, null, 2]}, - {"x": "3", "b": [11, 22, 33, 44]} - ]', - '$[*]' as p - columns ( - n for ordinality, - a int path 'lax $.a' default -1 on error, - nested path 'strict $.b[*]' as pb columns ( - b text format json path '$', - nested path 'strict $[*]' as pb1 columns ( - b1 int path '$' - ) - ), - nested path 'strict $.c[*]' as pc columns ( - c text format json path '$', - nested path 'strict $[*]' as pc1 columns ( - c1 int path '$' - ) - ) - ) - --plan default(outer, cross) - plan(p outer ((pb inner pb1) cross (pc outer pc1))) - ) jt ORDER BY 1,2,3,4,5; - --- Should succeed (JSON arguments are passed to root and nested paths) -SELECT * -FROM - generate_series(1, 4) x, - generate_series(1, 3) y, - JSON_TABLE(jsonb - '[[1,2,3],[2,3,4,5],[3,4,5,6]]', - 'strict $[*] ? (@[*] < $x)' - PASSING x AS x, y AS y - COLUMNS ( - y text FORMAT JSON PATH '$', - NESTED PATH 'strict $[*] ? (@ >= $y)' - COLUMNS ( - z int PATH '$' - ) - ) - ) jt ORDER BY 4,1,2,3; - -SET client_min_messages TO ERROR; -DROP SCHEMA "json table" CASCADE; - diff --git a/src/test/regress/sql/pg15_json.sql b/src/test/regress/sql/pg15_json.sql deleted file mode 100644 index 640953ac7..000000000 --- a/src/test/regress/sql/pg15_json.sql +++ /dev/null @@ -1,326 +0,0 @@ --- --- PG15+ test --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15 -\gset -\if :server_version_ge_15 -\else -\q -\endif - -CREATE SCHEMA pg15_json; -SET search_path TO pg15_json; - -SET citus.next_shard_id TO 1687000; - -CREATE TABLE test_table(id bigserial, value text); -SELECT create_distributed_table('test_table', 'id'); -INSERT INTO test_table (value) SELECT i::text FROM generate_series(0,100)i; - - -CREATE TABLE my_films(id bigserial, js jsonb); -SELECT create_distributed_table('my_films', 'id'); - -INSERT INTO my_films(js) VALUES ( -'{ "favorites" : [ - { "kind" : "comedy", "films" : [ { "title" : "Bananas", "director" : "Woody Allen"}, - { "title" : "The Dinner Game", "director" : "Francis Veber" } ] }, - { "kind" : "horror", "films" : [{ "title" : "Psycho", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "thriller", "films" : [{ "title" : "Vertigo", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "drama", "films" : [{ "title" : "Yojimbo", "director" : "Akira Kurosawa" } ] } - ] }'); - -INSERT INTO my_films(js) VALUES ( -'{ "favorites" : [ - { "kind" : "comedy", "films" : [ { "title" : "Bananas2", "director" : "Woody Allen"}, - { "title" : "The Dinner Game2", "director" : "Francis Veber" } ] }, - { "kind" : "horror", "films" : [{ "title" : "Psycho2", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "thriller", "films" : [{ "title" : "Vertigo2", "director" : "Alfred Hitchcock" } ] }, - { "kind" : "drama", "films" : [{ "title" : "Yojimbo2", "director" : "Akira Kurosawa" } ] } - ] }'); - --- a router query -SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt - WHERE my_films.id = 1 - ORDER BY 1,2,3,4; - --- router query with an explicit LATEREL SUBQUERY -SELECT sub.* -FROM my_films, - lateral(SELECT * FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt) as sub -WHERE my_films.id = 1 ORDER BY 1,2,3,4; - --- router query with an explicit LATEREL SUBQUERY and LIMIT -SELECT sub.* -FROM my_films, - lateral(SELECT * FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt ORDER BY id DESC LIMIT 1) as sub -WHERE my_films.id = 1 ORDER BY 1,2,3,4; - --- set it DEBUG1 in case the plan changes --- we can see details -SET client_min_messages TO DEBUG1; - --- a mult-shard query -SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt - ORDER BY 1,2,3,4; - --- recursively plan subqueries that has JSON_TABLE -SELECT count(*) FROM -( - SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt - LIMIT 1) as sub_with_json, test_table -WHERE test_table.id = sub_with_json.id; - - --- multi-shard query with an explicit LATEREL SUBQUERY -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) - ORDER BY 1,2,3,4; - --- JSON_TABLE can be on the inner part of an outer joion -SELECT sub.* -FROM my_films LEFT JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) - ORDER BY 1,2,3,4; - --- we can pushdown this correlated subquery in WHERE clause -SELECT count(*) -FROM my_films WHERE - (SELECT count(*) > 0 - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000); - --- we can pushdown this correlated subquery in SELECT clause - SELECT (SELECT count(*) > 0 - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt) -FROM my_films; - --- multi-shard query with an explicit LATEREL SUBQUERY --- along with other tables -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) JOIN test_table ON(my_films.id = test_table.id) - ORDER BY 1,2,3,4; - --- non-colocated join fails -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) JOIN test_table ON(my_films.id != test_table.id) - ORDER BY 1,2,3,4; - --- JSON_TABLE can be in the outer part of the join --- as long as there is a distributed table -SELECT sub.* -FROM my_films JOIN - lateral - (SELECT * - FROM JSON_TABLE (js, '$.favorites[*]' COLUMNS (id FOR ORDINALITY, - kind text PATH '$.kind', NESTED PATH '$.films[*]' - COLUMNS (title text PATH '$.title', director text PATH '$.director'))) AS jt - LIMIT 1000) AS sub ON (true) LEFT JOIN test_table ON(my_films.id = test_table.id) - ORDER BY 1,2,3,4; - --- JSON_TABLE cannot be on the outer side of the join -SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY, column_a int4 PATH '$.a', column_b int4 PATH '$.b', a int4, b int4, c text)) -LEFT JOIN LATERAL - (SELECT * - FROM my_films) AS foo on(foo.id = a); - - --- JSON_TABLE cannot be on the FROM clause alone -SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY, column_a int4 PATH '$.a', column_b int4 PATH '$.b', a int4, b int4, c text)) as foo -WHERE b > - (SELECT count(*) - FROM my_films WHERE id = foo.a); - --- we can recursively plan json_tables on set operations -(SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY)) ORDER BY id ASC LIMIT 1) -UNION -(SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY)) ORDER BY id ASC LIMIT 1) -UNION -(SELECT id FROM test_table ORDER BY id ASC LIMIT 1); - --- LIMIT in subquery not supported when json_table exists -SELECT * -FROM json_table('[{"a":10,"b":20},{"a":30,"b":40}]'::JSONB, '$[*]' - COLUMNS (id FOR ORDINALITY, column_a int4 PATH '$.a', column_b int4 PATH '$.b', a int4, b int4, c text)) -JOIN LATERAL - (SELECT * - FROM my_films WHERE json_table.id = a LIMIT 1) as foo ON (true); - --- a little more complex query with multiple json_table -SELECT - director1 AS director, title1, kind1, title2, kind2 -FROM - my_films, - JSON_TABLE ( js, '$.favorites' AS favs COLUMNS ( - NESTED PATH '$[*]' AS films1 COLUMNS ( - kind1 text PATH '$.kind', - NESTED PATH '$.films[*]' AS film1 COLUMNS ( - title1 text PATH '$.title', - director1 text PATH '$.director') - ), - NESTED PATH '$[*]' AS films2 COLUMNS ( - kind2 text PATH '$.kind', - NESTED PATH '$.films[*]' AS film2 COLUMNS ( - title2 text PATH '$.title', - director2 text PATH '$.director' - ) - ) - ) - PLAN (favs INNER ((films1 INNER film1) CROSS (films2 INNER film2))) - ) AS jt - WHERE kind1 > kind2 AND director1 = director2 - ORDER BY 1,2,3,4; - -RESET client_min_messages; - --- test some utility functions on the target list & where clause -select jsonb_path_exists(js, '$.favorites') from my_films; -select bool_and(JSON_EXISTS(js, '$.favorites.films.title')) from my_films; -SELECT count(*) FROM my_films WHERE jsonb_path_exists(js, '$.favorites'); -SELECT count(*) FROM my_films WHERE jsonb_path_exists(js, '$.favorites'); -SELECT count(*) FROM my_films WHERE JSON_EXISTS(js, '$.favorites.films.title'); - --- check constraint with json_exists -create table user_profiles ( - id bigserial, - addresses jsonb, - anyjson jsonb, - check (json_exists( addresses, '$.main' )) -); -select create_distributed_table('user_profiles', 'id'); -insert into user_profiles (addresses) VALUES (JSON_SCALAR('1')); -insert into user_profiles (addresses) VALUES ('{"main":"value"}'); - --- we cannot insert because WITH UNIQUE KEYS -insert into user_profiles (addresses) VALUES (JSON ('{"main":"value", "main":"value"}' WITH UNIQUE KEYS)); - --- we can insert with -insert into user_profiles (addresses) VALUES (JSON ('{"main":"value", "main":"value"}' WITHOUT UNIQUE KEYS)) RETURNING *; - -TRUNCATE user_profiles; -INSERT INTO user_profiles (anyjson) VALUES ('12'), ('"abc"'), ('[1,2,3]'), ('{"a":12}'); -select anyjson, anyjson is json array as json_array, anyjson is json object as json_object, anyjson is json scalar as json_scalar, -anyjson is json with UNIQUE keys -from user_profiles WHERE anyjson IS NOT NULL ORDER BY 1; - --- use json_query -SELECT i, - json_query('[{"x": "aaa"},{"x": "bbb"},{"x": "ccc"}]'::JSONB, '$[$i].x' passing id AS i RETURNING text omit quotes) -FROM generate_series(0, 3) i -JOIN my_films ON(id = i) ORDER BY 1; - --- we can use JSON_TABLE in modification queries as well - --- use log level such that we can see trace changes -SET client_min_messages TO DEBUG1; - ---the JSON_TABLE subquery is recursively planned -UPDATE test_table SET VALUE = 'XXX' FROM( -SELECT jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - id FOR ORDINALITY, - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt) as foo WHERE foo.id = test_table.id; - --- Subquery with JSON table can be pushed down because two distributed tables --- in the query are joined on distribution column -UPDATE test_table SET VALUE = 'XXX' FROM ( -SELECT my_films.id, jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt) as foo WHERE foo.id = test_table.id; - --- we can pushdown with CTEs as well -WITH json_cte AS -(SELECT my_films.id, jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - title text PATH '$.title', - director text PATH '$.director'))) AS jt) -UPDATE test_table SET VALUE = 'XYZ' FROM json_cte - WHERE json_cte.id = test_table.id; - - -- we can recursively with CTEs as well -WITH json_cte AS -(SELECT my_films.id as film_id, jt.* FROM - my_films, - JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( - kind text PATH '$.kind', - NESTED PATH '$.films[*]' COLUMNS ( - id FOR ORDINALITY, - title text PATH '$.title', - director text PATH '$.director'))) AS jt ORDER BY jt.id LIMIT 1) -UPDATE test_table SET VALUE = 'XYZ' FROM json_cte - WHERE json_cte.film_id = test_table.id; - -SET client_min_messages TO ERROR; -DROP SCHEMA pg15_json CASCADE;