Skip to content

Commit 59f8c5c

Browse files
author
Nikita Glukhov
committed
Add parsing of common SQL/JSON clauses
1 parent b5310e4 commit 59f8c5c

File tree

7 files changed

+181
-3
lines changed

7 files changed

+181
-3
lines changed

src/backend/nodes/makefuncs.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "catalog/pg_type.h"
2020
#include "nodes/makefuncs.h"
2121
#include "nodes/nodeFuncs.h"
22+
#include "utils/errcodes.h"
2223
#include "utils/lsyscache.h"
2324

2425

@@ -814,3 +815,39 @@ makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
814815
v->va_cols = va_cols;
815816
return v;
816817
}
818+
819+
/*
820+
* makeJsonValueExpr -
821+
* creates a JsonValueExpr node
822+
*/
823+
JsonValueExpr *
824+
makeJsonValueExpr(Expr *expr, JsonFormat format)
825+
{
826+
JsonValueExpr *jve = makeNode(JsonValueExpr);
827+
828+
jve->expr = expr;
829+
jve->format = format;
830+
831+
return jve;
832+
}
833+
834+
/*
835+
* makeJsonEncoding -
836+
* converts JSON encoding name to enum JsonEncoding
837+
*/
838+
JsonEncoding
839+
makeJsonEncoding(char *name)
840+
{
841+
if (!pg_strcasecmp(name, "utf8"))
842+
return JS_ENC_UTF8;
843+
if (!pg_strcasecmp(name, "utf16"))
844+
return JS_ENC_UTF16;
845+
if (!pg_strcasecmp(name, "utf32"))
846+
return JS_ENC_UTF32;
847+
848+
ereport(ERROR,
849+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
850+
errmsg("unrecognized JSON encoding: %s", name)));
851+
852+
return JS_ENC_DEFAULT;
853+
}

src/backend/parser/gram.y

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
220220
JoinType jtype;
221221
DropBehavior dbehavior;
222222
OnCommitAction oncommit;
223+
JsonFormat jsformat;
223224
List *list;
224225
Node *node;
225226
Value *value;
@@ -599,6 +600,15 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
599600
%type <list> hash_partbound
600601
%type <defelt> hash_partbound_elem
601602

603+
%type <node> json_value_expr
604+
json_output_clause_opt
605+
606+
%type <ival> json_encoding
607+
json_encoding_clause_opt
608+
609+
%type <jsformat> json_format_clause_opt
610+
json_representation
611+
602612
/*
603613
* Non-keyword token types. These are hard-wired into the "flex" lexer.
604614
* They must be listed first so that their numeric codes do not depend on
@@ -650,7 +660,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
650660
EXTENSION EXTERNAL EXTRACT
651661

652662
FALSE_P FAMILY FETCH FILTER FIRST_P FLOAT_P FOLLOWING FOR
653-
FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS
663+
FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS
654664

655665
GENERATED GLOBAL GRANT GRANTED GREATEST GROUP_P GROUPING GROUPS
656666

@@ -661,7 +671,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
661671
INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
662672
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
663673

664-
JOIN
674+
JOIN JSON
665675

666676
KEY
667677

@@ -729,9 +739,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
729739
*/
730740
%token NOT_LA NULLS_LA WITH_LA
731741

732-
733742
/* Precedence: lowest to highest */
734743
%nonassoc SET /* see relation_expr_opt_alias */
744+
%right FORMAT
735745
%left UNION EXCEPT
736746
%left INTERSECT
737747
%left OR
@@ -14635,6 +14645,58 @@ opt_asymmetric: ASYMMETRIC
1463514645
| /*EMPTY*/
1463614646
;
1463714647

14648+
/* SQL/JSON support */
14649+
14650+
json_value_expr:
14651+
a_expr json_format_clause_opt
14652+
{
14653+
$$ = (Node *) makeJsonValueExpr((Expr *) $1, $2);
14654+
}
14655+
;
14656+
14657+
json_format_clause_opt:
14658+
FORMAT json_representation
14659+
{
14660+
$$ = $2;
14661+
$$.location = @1;
14662+
}
14663+
| /* EMPTY */
14664+
{
14665+
$$.type = JS_FORMAT_DEFAULT;
14666+
$$.encoding = JS_ENC_DEFAULT;
14667+
$$.location = -1;
14668+
}
14669+
;
14670+
14671+
json_representation:
14672+
JSON json_encoding_clause_opt
14673+
{
14674+
$$.type = JS_FORMAT_JSON;
14675+
$$.encoding = $2;
14676+
$$.location = @1;
14677+
}
14678+
/* | implementation_defined_JSON_representation_option (BSON, AVRO etc) */
14679+
;
14680+
14681+
json_encoding_clause_opt:
14682+
ENCODING json_encoding { $$ = $2; }
14683+
| /* EMPTY */ { $$ = JS_ENC_DEFAULT; }
14684+
;
14685+
14686+
json_encoding:
14687+
name { $$ = makeJsonEncoding($1); }
14688+
;
14689+
14690+
json_output_clause_opt:
14691+
RETURNING Typename json_format_clause_opt
14692+
{
14693+
JsonOutput *n = makeNode(JsonOutput);
14694+
n->typeName = $2;
14695+
n->returning.format = $3;
14696+
$$ = (Node *) n;
14697+
}
14698+
| /* EMPTY */ { $$ = NULL; }
14699+
;
1463814700

1463914701
/*****************************************************************************
1464014702
*
@@ -15113,6 +15175,7 @@ unreserved_keyword:
1511315175
| FIRST_P
1511415176
| FOLLOWING
1511515177
| FORCE
15178+
| FORMAT
1511615179
| FORWARD
1511715180
| FUNCTION
1511815181
| FUNCTIONS
@@ -15144,6 +15207,7 @@ unreserved_keyword:
1514415207
| INSTEAD
1514515208
| INVOKER
1514615209
| ISOLATION
15210+
| JSON
1514715211
| KEY
1514815212
| LABEL
1514915213
| LANGUAGE

src/include/nodes/makefuncs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,7 @@ extern GroupingSet *makeGroupingSet(GroupingSetKind kind, List *content, int loc
105105

106106
extern VacuumRelation *makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols);
107107

108+
extern JsonValueExpr *makeJsonValueExpr(Expr *expr, JsonFormat format);
109+
extern JsonEncoding makeJsonEncoding(char *name);
110+
108111
#endif /* MAKEFUNC_H */

src/include/nodes/nodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,8 @@ typedef enum NodeTag
481481
T_PartitionRangeDatum,
482482
T_PartitionCmd,
483483
T_VacuumRelation,
484+
T_JsonValueExpr,
485+
T_JsonOutput,
484486

485487
/*
486488
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)

src/include/nodes/parsenodes.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,31 @@ typedef struct TriggerTransition
14861486
bool isTable;
14871487
} TriggerTransition;
14881488

1489+
/* Nodes for SQL/JSON support */
1490+
1491+
/*
1492+
* JsonOutput -
1493+
* representation of JSON output clause (RETURNING type [FORMAT format])
1494+
*/
1495+
typedef struct JsonOutput
1496+
{
1497+
NodeTag type;
1498+
TypeName *typeName; /* RETURNING type name, if specified */
1499+
JsonReturning returning; /* RETURNING FORMAT clause and type Oids */
1500+
} JsonOutput;
1501+
1502+
/*
1503+
* JsonValueExpr -
1504+
* representation of JSON value expression (expr [FORMAT json_format])
1505+
*/
1506+
typedef struct JsonValueExpr
1507+
{
1508+
NodeTag type;
1509+
Expr *expr; /* raw expression */
1510+
JsonFormat format; /* FORMAT clause, if specified */
1511+
} JsonValueExpr;
1512+
1513+
14891514
/*****************************************************************************
14901515
* Raw Grammar Output Statements
14911516
*****************************************************************************/

src/include/nodes/primnodes.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,51 @@ typedef struct XmlExpr
11891189
int location; /* token location, or -1 if unknown */
11901190
} XmlExpr;
11911191

1192+
/*
1193+
* JsonEncoding -
1194+
* representation of JSON ENCODING clause
1195+
*/
1196+
typedef enum JsonEncoding
1197+
{
1198+
JS_ENC_DEFAULT, /* unspecified */
1199+
JS_ENC_UTF8,
1200+
JS_ENC_UTF16,
1201+
JS_ENC_UTF32,
1202+
} JsonEncoding;
1203+
1204+
/*
1205+
* JsonFormatType -
1206+
* enumeration of JSON formats used in JSON FORMAT clause
1207+
*/
1208+
typedef enum JsonFormatType
1209+
{
1210+
JS_FORMAT_DEFAULT, /* unspecified */
1211+
JS_FORMAT_JSON, /* FORMAT JSON [ENCODING ...] */
1212+
JS_FORMAT_JSONB /* implicit internal format for RETURNING jsonb */
1213+
} JsonFormatType;
1214+
1215+
/*
1216+
* JsonFormat -
1217+
* representation of JSON FORMAT clause
1218+
*/
1219+
typedef struct JsonFormat
1220+
{
1221+
JsonFormatType type; /* format type */
1222+
JsonEncoding encoding; /* JSON encoding */
1223+
int location; /* token location, or -1 if unknown */
1224+
} JsonFormat;
1225+
1226+
/*
1227+
* JsonReturning -
1228+
* transformed representation of JSON RETURNING clause
1229+
*/
1230+
typedef struct JsonReturning
1231+
{
1232+
JsonFormat format; /* output JSON format */
1233+
Oid typid; /* target type Oid */
1234+
int32 typmod; /* target type modifier */
1235+
} JsonReturning;
1236+
11921237
/* ----------------
11931238
* NullTest
11941239
*

src/include/parser/kwlist.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ PG_KEYWORD("following", FOLLOWING, UNRESERVED_KEYWORD)
169169
PG_KEYWORD("for", FOR, RESERVED_KEYWORD)
170170
PG_KEYWORD("force", FORCE, UNRESERVED_KEYWORD)
171171
PG_KEYWORD("foreign", FOREIGN, RESERVED_KEYWORD)
172+
PG_KEYWORD("format", FORMAT, UNRESERVED_KEYWORD)
172173
PG_KEYWORD("forward", FORWARD, UNRESERVED_KEYWORD)
173174
PG_KEYWORD("freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD)
174175
PG_KEYWORD("from", FROM, RESERVED_KEYWORD)
@@ -221,6 +222,7 @@ PG_KEYWORD("is", IS, TYPE_FUNC_NAME_KEYWORD)
221222
PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD)
222223
PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD)
223224
PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD)
225+
PG_KEYWORD("json", JSON, UNRESERVED_KEYWORD)
224226
PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)
225227
PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD)
226228
PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)

0 commit comments

Comments
 (0)