Skip to content

Commit cb80df9

Browse files
author
Nikita Glukhov
committed
Add SQL/JSON constructors parsing
1 parent 80424b5 commit cb80df9

File tree

9 files changed

+393
-5
lines changed

9 files changed

+393
-5
lines changed

src/backend/nodes/makefuncs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,3 +868,18 @@ makeJsonEncoding(char *name)
868868

869869
return JS_ENC_DEFAULT;
870870
}
871+
872+
/*
873+
* makeJsonKeyValue -
874+
* creates a JsonKeyValue node
875+
*/
876+
Node *
877+
makeJsonKeyValue(Node *key, Node *value)
878+
{
879+
JsonKeyValue *n = makeNode(JsonKeyValue);
880+
881+
n->key = (Expr *) key;
882+
n->value = castNode(JsonValueExpr, value);
883+
884+
return (Node *) n;
885+
}

src/backend/parser/gram.y

Lines changed: 241 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -602,11 +602,31 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
602602
%type <node> json_format_clause_opt
603603
json_representation
604604
json_value_expr
605+
json_func_expr
605606
json_output_clause_opt
607+
json_value_constructor
608+
json_object_constructor
609+
json_object_constructor_args_opt
610+
json_object_args
611+
json_object_ctor_args_opt
612+
json_object_func_args
613+
json_array_constructor
614+
json_name_and_value
615+
json_aggregate_func
616+
json_object_aggregate_constructor
617+
json_array_aggregate_constructor
618+
619+
%type <list> json_name_and_value_list
620+
json_value_expr_list
621+
json_array_aggregate_order_by_clause_opt
606622

607623
%type <ival> json_encoding
608624
json_encoding_clause_opt
609625

626+
%type <boolean> json_key_uniqueness_constraint_opt
627+
json_object_constructor_null_clause_opt
628+
json_array_constructor_null_clause_opt
629+
610630
/*
611631
* Non-keyword token types. These are hard-wired into the "flex" lexer.
612632
* They must be listed first so that their numeric codes do not depend on
@@ -632,7 +652,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
632652
*/
633653

634654
/* ordinary key words in alphabetical order */
635-
%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
655+
%token <keyword> ABORT_P ABSENT ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
636656
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
637657
ASSERTION ASSIGNMENT ASYMMETRIC AT ATTACH ATTRIBUTE AUTHORIZATION
638658

@@ -669,9 +689,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
669689
INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
670690
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
671691

672-
JOIN JSON
692+
JOIN JSON JSON_ARRAY JSON_ARRAYAGG JSON_OBJECT JSON_OBJECTAGG
673693

674-
KEY
694+
KEY KEYS
675695

676696
LABEL LANGUAGE LARGE_P LAST_P LATERAL_P
677697
LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
@@ -735,7 +755,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
735755
* as NOT, at least with respect to their left-hand subexpression.
736756
* NULLS_LA and WITH_LA are needed to make the grammar LALR(1).
737757
*/
738-
%token NOT_LA NULLS_LA WITH_LA
758+
%token NOT_LA NULLS_LA WITH_LA WITH_LA_UNIQUE WITHOUT_LA
739759

740760
/* Precedence: lowest to highest */
741761
%nonassoc SET /* see relation_expr_opt_alias */
@@ -778,6 +798,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
778798
* blame any funny behavior of UNBOUNDED on the SQL standard, though.
779799
*/
780800
%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */
801+
%nonassoc ABSENT
781802
%nonassoc IDENT GENERATED NULL_P PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP
782803
%left Op OPERATOR /* multi-character ops and user-defined operators */
783804
%left '+' '-'
@@ -802,6 +823,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
802823
/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */
803824
%right PRESERVE STRIP_P
804825

826+
%nonassoc empty_json_unique
827+
%left WITHOUT WITH_LA_UNIQUE
828+
805829
%%
806830

807831
/*
@@ -12834,7 +12858,7 @@ ConstInterval:
1283412858

1283512859
opt_timezone:
1283612860
WITH_LA TIME ZONE { $$ = true; }
12837-
| WITHOUT TIME ZONE { $$ = false; }
12861+
| WITHOUT_LA TIME ZONE { $$ = false; }
1283812862
| /*EMPTY*/ { $$ = false; }
1283912863
;
1284012864

@@ -13443,6 +13467,17 @@ b_expr: c_expr
1344313467
}
1344413468
;
1344513469

13470+
json_key_uniqueness_constraint_opt:
13471+
WITH_LA_UNIQUE UNIQUE opt_keys { $$ = true; }
13472+
| WITHOUT UNIQUE opt_keys { $$ = false; }
13473+
| /* EMPTY */ %prec empty_json_unique { $$ = false; }
13474+
;
13475+
13476+
opt_keys:
13477+
KEYS { }
13478+
| /* EMPTY */ { }
13479+
;
13480+
1344613481
/*
1344713482
* Productions that can be used in both a_expr and b_expr.
1344813483
*
@@ -13703,6 +13738,13 @@ func_expr: func_application within_group_clause filter_clause over_clause
1370313738
n->over = $4;
1370413739
$$ = (Node *) n;
1370513740
}
13741+
| json_aggregate_func filter_clause over_clause
13742+
{
13743+
JsonAggCtor *n = (JsonAggCtor *) $1;
13744+
n->agg_filter = $2;
13745+
n->over = $3;
13746+
$$ = (Node *) $1;
13747+
}
1370613748
| func_expr_common_subexpr
1370713749
{ $$ = $1; }
1370813750
;
@@ -13716,6 +13758,7 @@ func_expr: func_application within_group_clause filter_clause over_clause
1371613758
func_expr_windowless:
1371713759
func_application { $$ = $1; }
1371813760
| func_expr_common_subexpr { $$ = $1; }
13761+
| json_aggregate_func { $$ = $1; }
1371913762
;
1372013763

1372113764
/*
@@ -13940,6 +13983,8 @@ func_expr_common_subexpr:
1394013983
n->location = @1;
1394113984
$$ = (Node *)n;
1394213985
}
13986+
| json_func_expr
13987+
{ $$ = $1; }
1394313988
;
1394413989

1394513990
/*
@@ -14644,6 +14689,9 @@ opt_asymmetric: ASYMMETRIC
1464414689
;
1464514690

1464614691
/* SQL/JSON support */
14692+
json_func_expr:
14693+
json_value_constructor
14694+
;
1464714695

1464814696
json_value_expr:
1464914697
a_expr json_format_clause_opt
@@ -14690,6 +14738,188 @@ json_output_clause_opt:
1469014738
$$ = (Node *) n;
1469114739
}
1469214740
| /* EMPTY */ { $$ = NULL; }
14741+
;
14742+
14743+
json_value_constructor:
14744+
json_object_constructor
14745+
| json_array_constructor
14746+
;
14747+
14748+
json_object_constructor:
14749+
JSON_OBJECT '(' json_object_args ')'
14750+
{
14751+
$$ = $3;
14752+
}
14753+
;
14754+
14755+
json_object_args:
14756+
json_object_ctor_args_opt
14757+
| json_object_func_args
14758+
;
14759+
14760+
json_object_func_args:
14761+
func_arg_list
14762+
{
14763+
List *func = list_make1(makeString("json_object"));
14764+
$$ = (Node *) makeFuncCall(func, $1, @1);
14765+
}
14766+
;
14767+
14768+
json_object_ctor_args_opt:
14769+
json_object_constructor_args_opt json_output_clause_opt
14770+
{
14771+
JsonObjectCtor *n = (JsonObjectCtor *) $1;
14772+
n->output = (JsonOutput *) $2;
14773+
n->location = @1;
14774+
$$ = (Node *) n;
14775+
}
14776+
;
14777+
14778+
json_object_constructor_args_opt:
14779+
json_name_and_value_list
14780+
json_object_constructor_null_clause_opt
14781+
json_key_uniqueness_constraint_opt
14782+
{
14783+
JsonObjectCtor *n = makeNode(JsonObjectCtor);
14784+
n->exprs = $1;
14785+
n->absent_on_null = $2;
14786+
n->unique = $3;
14787+
$$ = (Node *) n;
14788+
}
14789+
| /* EMPTY */
14790+
{
14791+
JsonObjectCtor *n = makeNode(JsonObjectCtor);
14792+
n->exprs = NULL;
14793+
n->absent_on_null = false;
14794+
n->unique = false;
14795+
$$ = (Node *) n;
14796+
}
14797+
;
14798+
14799+
json_name_and_value_list:
14800+
json_name_and_value
14801+
{ $$ = list_make1($1); }
14802+
| json_name_and_value_list ',' json_name_and_value
14803+
{ $$ = lappend($1, $3); }
14804+
;
14805+
14806+
json_name_and_value:
14807+
/* TODO This is not supported due to conflicts
14808+
KEY c_expr VALUE_P json_value_expr %prec POSTFIXOP
14809+
{ $$ = makeJsonKeyValue($2, $4); }
14810+
|
14811+
*/
14812+
c_expr VALUE_P json_value_expr
14813+
{ $$ = makeJsonKeyValue($1, $3); }
14814+
|
14815+
a_expr ':' json_value_expr
14816+
{ $$ = makeJsonKeyValue($1, $3); }
14817+
;
14818+
14819+
json_object_constructor_null_clause_opt:
14820+
NULL_P ON NULL_P { $$ = false; }
14821+
| ABSENT ON NULL_P { $$ = true; }
14822+
| /* EMPTY */ { $$ = false; }
14823+
;
14824+
14825+
json_array_constructor:
14826+
JSON_ARRAY '('
14827+
json_value_expr_list
14828+
json_array_constructor_null_clause_opt
14829+
json_output_clause_opt
14830+
')'
14831+
{
14832+
JsonArrayCtor *n = makeNode(JsonArrayCtor);
14833+
n->exprs = $3;
14834+
n->absent_on_null = $4;
14835+
n->output = (JsonOutput *) $5;
14836+
n->location = @1;
14837+
$$ = (Node *) n;
14838+
}
14839+
| JSON_ARRAY '('
14840+
select_no_parens
14841+
/* json_format_clause_opt */
14842+
/* json_array_constructor_null_clause_opt */
14843+
json_output_clause_opt
14844+
')'
14845+
{
14846+
JsonArrayQueryCtor *n = makeNode(JsonArrayQueryCtor);
14847+
n->query = $3;
14848+
/* n->format = $4; */
14849+
n->absent_on_null = true /* $5 */;
14850+
n->output = (JsonOutput *) $4;
14851+
n->location = @1;
14852+
$$ = (Node *) n;
14853+
}
14854+
| JSON_ARRAY '('
14855+
json_output_clause_opt
14856+
')'
14857+
{
14858+
JsonArrayCtor *n = makeNode(JsonArrayCtor);
14859+
n->exprs = NIL;
14860+
n->absent_on_null = true;
14861+
n->output = (JsonOutput *) $3;
14862+
n->location = @1;
14863+
$$ = (Node *) n;
14864+
}
14865+
;
14866+
14867+
json_value_expr_list:
14868+
json_value_expr { $$ = list_make1($1); }
14869+
| json_value_expr_list ',' json_value_expr { $$ = lappend($1, $3);}
14870+
;
14871+
14872+
json_array_constructor_null_clause_opt:
14873+
NULL_P ON NULL_P { $$ = false; }
14874+
| ABSENT ON NULL_P { $$ = true; }
14875+
| /* EMPTY */ { $$ = true; }
14876+
;
14877+
14878+
json_aggregate_func:
14879+
json_object_aggregate_constructor
14880+
| json_array_aggregate_constructor
14881+
;
14882+
14883+
json_object_aggregate_constructor:
14884+
JSON_OBJECTAGG '('
14885+
json_name_and_value
14886+
json_object_constructor_null_clause_opt
14887+
json_key_uniqueness_constraint_opt
14888+
json_output_clause_opt
14889+
')'
14890+
{
14891+
JsonObjectAgg *n = makeNode(JsonObjectAgg);
14892+
n->arg = (JsonKeyValue *) $3;
14893+
n->absent_on_null = $4;
14894+
n->unique = $5;
14895+
n->ctor.output = (JsonOutput *) $6;
14896+
n->ctor.agg_order = NULL;
14897+
n->ctor.location = @1;
14898+
$$ = (Node *) n;
14899+
}
14900+
;
14901+
14902+
json_array_aggregate_constructor:
14903+
JSON_ARRAYAGG '('
14904+
json_value_expr
14905+
json_array_aggregate_order_by_clause_opt
14906+
json_array_constructor_null_clause_opt
14907+
json_output_clause_opt
14908+
')'
14909+
{
14910+
JsonArrayAgg *n = makeNode(JsonArrayAgg);
14911+
n->arg = (JsonValueExpr *) $3;
14912+
n->ctor.agg_order = $4;
14913+
n->absent_on_null = $5;
14914+
n->ctor.output = (JsonOutput *) $6;
14915+
n->ctor.location = @1;
14916+
$$ = (Node *) n;
14917+
}
14918+
;
14919+
14920+
json_array_aggregate_order_by_clause_opt:
14921+
ORDER BY sortby_list { $$ = $3; }
14922+
| /* EMPTY */ { $$ = NIL; }
1469314923
;
1469414924

1469514925
/*****************************************************************************
@@ -15079,6 +15309,7 @@ ColLabel: IDENT { $$ = $1; }
1507915309
*/
1508015310
unreserved_keyword:
1508115311
ABORT_P
15312+
| ABSENT
1508215313
| ABSOLUTE_P
1508315314
| ACCESS
1508415315
| ACTION
@@ -15203,6 +15434,7 @@ unreserved_keyword:
1520315434
| ISOLATION
1520415435
| JSON
1520515436
| KEY
15437+
| KEYS
1520615438
| LABEL
1520715439
| LANGUAGE
1520815440
| LARGE_P
@@ -15410,6 +15642,10 @@ col_name_keyword:
1541015642
| INT_P
1541115643
| INTEGER
1541215644
| INTERVAL
15645+
| JSON_ARRAY
15646+
| JSON_ARRAYAGG
15647+
| JSON_OBJECT
15648+
| JSON_OBJECTAGG
1541315649
| LEAST
1541415650
| NATIONAL
1541515651
| NCHAR

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy