Skip to content

Commit d82d015

Browse files
Nikita MalakhovCommitfest Bot
authored andcommitted
Add the PLAN clauses for JSON_TABLE Revisited part 1
This patch adds the PLAN clauses for JSON_TABLE, which allow the user to specify how data from nested paths are joined, allowing considerable freedom in shaping the tabular output of JSON_TABLE. PLAN DEFAULT allows the user to specify the global strategies when dealing with sibling or child nested paths. The is often sufficient to achieve the necessary goal, and is considerably simpler than the full PLAN clause, which allows the user to specify the strategy to be used for each named nested path. Code was taken from v45-0001-JSON_TABLE.patch from https://www.postgresql.org/message-id/CA%2BHiwqE1gcPkQhBko%2BUbvVvAtRBaLfOpmHbFrK79pW_5F51Oww%40mail.gmail.com Original patch was modified according to recent changes in SQL/JSON JSON_TABLE, and invalid PLAN test results found while adapting original patch to these changes. Author: Nikita Glukhov Author: Teodor Sigaev Author: Oleg Bartunov Author: Alexander Korotkov Author: Andrew Dunstan Author: Amit Langote Author: Anton A. Melnikov Author: Nikita Malakhov Reviewers have included (in no particular order) Andres Freund, Alexander Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu, Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby, Álvaro Herrera, Jian He Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/[email protected] Discussion: https://postgr.es/m/abd9b83b-aa66-f230-3d6d-734817f0995d%40postgresql.org Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
1 parent 257ee78 commit d82d015

File tree

9 files changed

+713
-112
lines changed

9 files changed

+713
-112
lines changed

src/backend/nodes/makefuncs.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,60 @@ makeJsonBehavior(JsonBehaviorType btype, Node *expr, int location)
963963
return behavior;
964964
}
965965

966+
/*
967+
* makeJsonTableDefaultPlan -
968+
* creates a JsonTablePlanSpec node to represent a "default" JSON_TABLE plan
969+
* with given join strategy
970+
*/
971+
Node *
972+
makeJsonTableDefaultPlan(JsonTablePlanJoinType join_type, int location)
973+
{
974+
JsonTablePlanSpec *n = makeNode(JsonTablePlanSpec);
975+
976+
n->plan_type = JSTP_DEFAULT;
977+
n->join_type = join_type;
978+
n->location = location;
979+
980+
return (Node *) n;
981+
}
982+
983+
/*
984+
* makeJsonTableSimplePlan -
985+
* creates a JsonTablePlanSpec node to represent a "simple" JSON_TABLE plan
986+
* for given PATH
987+
*/
988+
Node *
989+
makeJsonTableSimplePlan(char *pathname, int location)
990+
{
991+
JsonTablePlanSpec *n = makeNode(JsonTablePlanSpec);
992+
993+
n->plan_type = JSTP_SIMPLE;
994+
n->pathname = pathname;
995+
n->location = location;
996+
997+
return (Node *) n;
998+
}
999+
1000+
/*
1001+
* makeJsonTableJoinedPlan -
1002+
* creates a JsonTablePlanSpec node to represent join between the given
1003+
* pair of plans
1004+
*/
1005+
Node *
1006+
makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2,
1007+
int location)
1008+
{
1009+
JsonTablePlanSpec *n = makeNode(JsonTablePlanSpec);
1010+
1011+
n->plan_type = JSTP_JOINED;
1012+
n->join_type = type;
1013+
n->plan1 = castNode(JsonTablePlanSpec, plan1);
1014+
n->plan2 = castNode(JsonTablePlanSpec, plan2);
1015+
n->location = location;
1016+
1017+
return (Node *) n;
1018+
}
1019+
9661020
/*
9671021
* makeJsonKeyValue -
9681022
* creates a JsonKeyValue node

src/backend/parser/gram.y

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,14 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
662662
json_table
663663
json_table_column_definition
664664
json_table_column_path_clause_opt
665+
json_table_plan_clause_opt
666+
json_table_plan
667+
json_table_plan_simple
668+
json_table_plan_outer
669+
json_table_plan_inner
670+
json_table_plan_union
671+
json_table_plan_cross
672+
json_table_plan_primary
665673
%type <list> json_name_and_value_list
666674
json_value_expr_list
667675
json_array_aggregate_order_by_clause_opt
@@ -673,6 +681,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
673681
%type <ival> json_behavior_type
674682
json_predicate_type_constraint
675683
json_quotes_clause_opt
684+
json_table_default_plan_choices
685+
json_table_default_plan_inner_outer
686+
json_table_default_plan_union_cross
676687
json_wrapper_behavior
677688
%type <boolean> json_key_uniqueness_constraint_opt
678689
json_object_constructor_null_clause_opt
@@ -14411,6 +14422,7 @@ json_table:
1441114422
json_value_expr ',' a_expr json_table_path_name_opt
1441214423
json_passing_clause_opt
1441314424
COLUMNS '(' json_table_column_definition_list ')'
14425+
json_table_plan_clause_opt
1441414426
json_on_error_clause_opt
1441514427
')'
1441614428
{
@@ -14422,13 +14434,15 @@ json_table:
1442214434
castNode(A_Const, $5)->val.node.type != T_String)
1442314435
ereport(ERROR,
1442414436
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
14425-
errmsg("only string constants are supported in JSON_TABLE path specification"),
14437+
errmsg("only string constants are supported in"
14438+
" JSON_TABLE path specification"),
1442614439
parser_errposition(@5));
1442714440
pathstring = castNode(A_Const, $5)->val.sval.sval;
1442814441
n->pathspec = makeJsonTablePathSpec(pathstring, $6, @5, @6);
1442914442
n->passing = $7;
1443014443
n->columns = $10;
14431-
n->on_error = (JsonBehavior *) $12;
14444+
n->planspec = (JsonTablePlanSpec *) $12;
14445+
n->on_error = (JsonBehavior *) $13;
1443214446
n->location = @1;
1443314447
$$ = (Node *) n;
1443414448
}
@@ -14520,8 +14534,7 @@ json_table_column_definition:
1452014534
JsonTableColumn *n = makeNode(JsonTableColumn);
1452114535

1452214536
n->coltype = JTC_NESTED;
14523-
n->pathspec = (JsonTablePathSpec *)
14524-
makeJsonTablePathSpec($3, NULL, @3, -1);
14537+
n->pathspec = makeJsonTablePathSpec($3, NULL, @3, -1);
1452514538
n->columns = $6;
1452614539
n->location = @1;
1452714540
$$ = (Node *) n;
@@ -14532,8 +14545,7 @@ json_table_column_definition:
1453214545
JsonTableColumn *n = makeNode(JsonTableColumn);
1453314546

1453414547
n->coltype = JTC_NESTED;
14535-
n->pathspec = (JsonTablePathSpec *)
14536-
makeJsonTablePathSpec($3, $5, @3, @5);
14548+
n->pathspec = makeJsonTablePathSpec($3, $5, @3, @5);
1453714549
n->columns = $8;
1453814550
n->location = @1;
1453914551
$$ = (Node *) n;
@@ -14552,6 +14564,83 @@ json_table_column_path_clause_opt:
1455214564
{ $$ = NULL; }
1455314565
;
1455414566

14567+
json_table_plan_clause_opt:
14568+
PLAN '(' json_table_plan ')'
14569+
{ $$ = $3; }
14570+
| PLAN DEFAULT '(' json_table_default_plan_choices ')'
14571+
{ $$ = makeJsonTableDefaultPlan($4, @1); }
14572+
| /* EMPTY */
14573+
{ $$ = NULL; }
14574+
;
14575+
14576+
json_table_plan:
14577+
json_table_plan_simple
14578+
| json_table_plan_outer
14579+
| json_table_plan_inner
14580+
| json_table_plan_union
14581+
| json_table_plan_cross
14582+
;
14583+
14584+
json_table_plan_simple:
14585+
name
14586+
{ $$ = makeJsonTableSimplePlan($1, @1); }
14587+
;
14588+
14589+
json_table_plan_outer:
14590+
json_table_plan_simple OUTER_P json_table_plan_primary
14591+
{ $$ = makeJsonTableJoinedPlan(JSTP_JOIN_OUTER, $1, $3, @1); }
14592+
;
14593+
14594+
json_table_plan_inner:
14595+
json_table_plan_simple INNER_P json_table_plan_primary
14596+
{ $$ = makeJsonTableJoinedPlan(JSTP_JOIN_INNER, $1, $3, @1); }
14597+
;
14598+
14599+
json_table_plan_union:
14600+
json_table_plan_primary UNION json_table_plan_primary
14601+
{ $$ = makeJsonTableJoinedPlan(JSTP_JOIN_UNION, $1, $3, @1); }
14602+
| json_table_plan_union UNION json_table_plan_primary
14603+
{ $$ = makeJsonTableJoinedPlan(JSTP_JOIN_UNION, $1, $3, @1); }
14604+
;
14605+
14606+
json_table_plan_cross:
14607+
json_table_plan_primary CROSS json_table_plan_primary
14608+
{ $$ = makeJsonTableJoinedPlan(JSTP_JOIN_CROSS, $1, $3, @1); }
14609+
| json_table_plan_cross CROSS json_table_plan_primary
14610+
{ $$ = makeJsonTableJoinedPlan(JSTP_JOIN_CROSS, $1, $3, @1); }
14611+
;
14612+
14613+
json_table_plan_primary:
14614+
json_table_plan_simple
14615+
{ $$ = $1; }
14616+
| '(' json_table_plan ')'
14617+
{
14618+
castNode(JsonTablePlanSpec, $2)->location = @1;
14619+
$$ = $2;
14620+
}
14621+
;
14622+
14623+
json_table_default_plan_choices:
14624+
json_table_default_plan_inner_outer
14625+
{ $$ = $1 | JSTP_JOIN_UNION; }
14626+
| json_table_default_plan_union_cross
14627+
{ $$ = $1 | JSTP_JOIN_OUTER; }
14628+
| json_table_default_plan_inner_outer ',' json_table_default_plan_union_cross
14629+
{ $$ = $1 | $3; }
14630+
| json_table_default_plan_union_cross ',' json_table_default_plan_inner_outer
14631+
{ $$ = $1 | $3; }
14632+
;
14633+
14634+
json_table_default_plan_inner_outer:
14635+
INNER_P { $$ = JSTP_JOIN_INNER; }
14636+
| OUTER_P { $$ = JSTP_JOIN_OUTER; }
14637+
;
14638+
14639+
json_table_default_plan_union_cross:
14640+
UNION { $$ = JSTP_JOIN_UNION; }
14641+
| CROSS { $$ = JSTP_JOIN_CROSS; }
14642+
;
14643+
1455514644
/*****************************************************************************
1455614645
*
1455714646
* Type syntax

0 commit comments

Comments
 (0)