Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5976663

Browse files
author
Nikita Glukhov
committed
Add JSON_SERIALIZE()
1 parent f61823c commit 5976663

File tree

15 files changed

+278
-1
lines changed

15 files changed

+278
-1
lines changed

doc/src/sgml/func.sgml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18457,6 +18457,108 @@ FROM
1845718457
</sect4>
1845818458

1845918459

18460+
</sect3>
18461+
18462+
<sect3 id="functions-sqljson-serializing">
18463+
<title>Serializing JSON data</title>
18464+
<itemizedlist>
18465+
<listitem>
18466+
<para>
18467+
<xref linkend="functions-jsonserialize"/>
18468+
</para>
18469+
</listitem>
18470+
</itemizedlist>
18471+
18472+
<refentry id="functions-jsonserialize">
18473+
<refnamediv>
18474+
<refname>JSON_SERIALIZE</refname>
18475+
<refpurpose>serialize a JSON data as a string</refpurpose>
18476+
</refnamediv>
18477+
18478+
<refsynopsisdiv>
18479+
<synopsis>
18480+
JSON_SERIALIZE (
18481+
<replaceable class="parameter">expression</replaceable> [ FORMAT JSON [ ENCODING UTF8 ] ]
18482+
[ RETURNING <replaceable class="parameter">data_type</replaceable> [ FORMAT JSON [ ENCODING UTF8 ] ] ]
18483+
)
18484+
</synopsis>
18485+
</refsynopsisdiv>
18486+
18487+
<refsect1>
18488+
<title>Description</title>
18489+
18490+
<para>
18491+
<function>JSON_SERIALIZE</function> function transforms a SQL/JSON value
18492+
into a character or binary string.
18493+
</para>
18494+
</refsect1>
18495+
18496+
<refsect1>
18497+
<title>Parameters</title>
18498+
<variablelist>
18499+
<varlistentry>
18500+
<term>
18501+
<literal><replaceable class="parameter">expression</replaceable> [ FORMAT JSON [ ENCODING UTF8 ] ]</literal>
18502+
</term>
18503+
<listitem>
18504+
<para>
18505+
<acronym>JSON</acronym> typed expression that provides a data for
18506+
serialization. Accepted JSON types (<type>json</type> and
18507+
<type>jsonb</type>), any character string types (<type>text</type>,
18508+
<type>char</type>, etc.), binary strings (<type>bytea</type>) in
18509+
UTF8 encoding.
18510+
For null input, null value is returned.
18511+
</para>
18512+
<para>
18513+
The optional <literal>FORMAT</literal> clause is provided to conform
18514+
to the SQL/JSON standard.
18515+
</para>
18516+
</listitem>
18517+
</varlistentry>
18518+
<varlistentry>
18519+
<term>
18520+
<literal>RETURNING <replaceable class="parameter">data_type</replaceable> [ FORMAT JSON [ ENCODING UTF8 ] ] </literal>
18521+
</term>
18522+
<listitem>
18523+
<para>
18524+
The output clause that specifies the target character or binary string
18525+
type (<type>text</type>, <type>char</type>, <type>bytea</type>, etc.).
18526+
</para>
18527+
</listitem>
18528+
</varlistentry>
18529+
</variablelist>
18530+
</refsect1>
18531+
18532+
<refsect1>
18533+
<title>Notes</title>
18534+
<para>
18535+
Alternatively, you can construct <acronym>JSON</acronym> values simply
18536+
using <productname>PostgreSQL</productname>-specific casts to
18537+
<type>json</type> and <type>jsonb</type> types.
18538+
</para>
18539+
</refsect1>
18540+
<refsect1>
18541+
<title>Examples</title>
18542+
<para>
18543+
Construct a JSON the provided strings:
18544+
</para>
18545+
<screen>
18546+
SELECT JSON_SERIALIZE(JSON_SCALAR('foo'));
18547+
json_serialize
18548+
----------------
18549+
"foo"
18550+
(1 row)
18551+
18552+
SELECT JSON_SERIALIZE('{"foo": "bar", "baz": [1, 2, 3]}' RETURNING bytea);
18553+
json_serialize
18554+
--------------------------------------------------------------------
18555+
\x7b22666f6f223a2022626172222c202262617a223a205b312c20322c20335d7d
18556+
(1 row)
18557+
18558+
</screen>
18559+
</refsect1>
18560+
</refentry>
18561+
1846018562
</sect3>
1846118563

1846218564
<sect3 id="sqljson-common-clauses">

doc/src/sgml/keywords/sql2016-02-reserved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ JSON_OBJECT
163163
JSON_OBJECTAGG
164164
JSON_QUERY
165165
JSON_SCALAR
166+
JSON_SERIALIZE
166167
JSON_TABLE
167168
JSON_TABLE_PRIMITIVE
168169
JSON_VALUE

src/backend/executor/execExpr.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,6 +2142,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
21422142
{
21432143
ExecInitExprRec(ctor->func, state, resv, resnull);
21442144
}
2145+
else if (ctor->type == JSCTOR_JSON_SERIALIZE)
2146+
{
2147+
/* Use the value of the first argument as a result */
2148+
ExecInitExprRec(linitial(args), state, resv, resnull);
2149+
}
21452150
else
21462151
{
21472152
scratch.opcode = EEOP_JSON_CONSTRUCTOR;

src/backend/nodes/copyfuncs.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,6 +2308,21 @@ _copyJsonScalarExpr(const JsonScalarExpr *from)
23082308
return newnode;
23092309
}
23102310

2311+
/*
2312+
* _copyJsonSerializeExpr
2313+
*/
2314+
static JsonSerializeExpr *
2315+
_copyJsonSerializeExpr(const JsonSerializeExpr *from)
2316+
{
2317+
JsonSerializeExpr *newnode = makeNode(JsonSerializeExpr);
2318+
2319+
COPY_NODE_FIELD(expr);
2320+
COPY_NODE_FIELD(output);
2321+
COPY_LOCATION_FIELD(location);
2322+
2323+
return newnode;
2324+
}
2325+
23112326
/*
23122327
* _copyJsonConstructorExpr
23132328
*/
@@ -5509,6 +5524,9 @@ copyObjectImpl(const void *from)
55095524
case T_JsonScalarExpr:
55105525
retval = _copyJsonScalarExpr(from);
55115526
break;
5527+
case T_JsonSerializeExpr:
5528+
retval = _copyJsonSerializeExpr(from);
5529+
break;
55125530
case T_JsonKeyValue:
55135531
retval = _copyJsonKeyValue(from);
55145532
break;

src/backend/nodes/equalfuncs.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,16 @@ _equalJsonScalarExpr(const JsonScalarExpr *a, const JsonScalarExpr *b)
857857
return true;
858858
}
859859

860+
static bool
861+
_equalJsonSerializeExpr(const JsonSerializeExpr *a, const JsonSerializeExpr *b)
862+
{
863+
COMPARE_NODE_FIELD(expr);
864+
COMPARE_NODE_FIELD(output);
865+
COMPARE_LOCATION_FIELD(location);
866+
867+
return true;
868+
}
869+
860870
static bool
861871
_equalJsonConstructorExpr(const JsonConstructorExpr *a, const JsonConstructorExpr *b)
862872
{
@@ -3448,6 +3458,9 @@ equal(const void *a, const void *b)
34483458
case T_JsonScalarExpr:
34493459
retval = _equalJsonScalarExpr(a, b);
34503460
break;
3461+
case T_JsonSerializeExpr:
3462+
retval = _equalJsonSerializeExpr(a, b);
3463+
break;
34513464
case T_JsonConstructorExpr:
34523465
retval = _equalJsonConstructorExpr(a, b);
34533466
break;

src/backend/parser/gram.y

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
614614
json_query_expr
615615
json_exists_predicate
616616
json_scalar_expr
617+
json_serialize_expr
617618
json_api_common_syntax
618619
json_context_item
619620
json_argument
@@ -734,7 +735,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
734735
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
735736

736737
JOIN JSON JSON_ARRAY JSON_ARRAYAGG JSON_EXISTS JSON_OBJECT JSON_OBJECTAGG
737-
JSON_QUERY JSON_SCALAR JSON_VALUE
738+
JSON_QUERY JSON_SCALAR JSON_SERIALIZE JSON_VALUE
738739

739740
KEY KEYS KEEP
740741

@@ -14793,6 +14794,7 @@ json_func_expr:
1479314794
| json_query_expr
1479414795
| json_exists_predicate
1479514796
| json_scalar_expr
14797+
| json_serialize_expr
1479614798
;
1479714799

1479814800
json_scalar_expr:
@@ -14805,6 +14807,16 @@ json_scalar_expr:
1480514807
}
1480614808
;
1480714809

14810+
json_serialize_expr:
14811+
JSON_SERIALIZE '(' json_value_expr json_output_clause_opt ')'
14812+
{
14813+
JsonSerializeExpr *n = makeNode(JsonSerializeExpr);
14814+
n->expr = (JsonValueExpr *) $3;
14815+
n->output = (JsonOutput *) $4;
14816+
n->location = @1;
14817+
$$ = (Node *) n;
14818+
}
14819+
;
1480814820

1480914821
json_value_func_expr:
1481014822
JSON_VALUE '('
@@ -16020,6 +16032,7 @@ col_name_keyword:
1602016032
| JSON_OBJECTAGG
1602116033
| JSON_QUERY
1602216034
| JSON_SCALAR
16035+
| JSON_SERIALIZE
1602316036
| JSON_VALUE
1602416037
| LEAST
1602516038
| NATIONAL

src/backend/parser/parse_expr.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ static Node *transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *p);
135135
static Node *transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *p);
136136
static Node *transformJsonValueExpr(ParseState *pstate, JsonValueExpr *jve);
137137
static Node *transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *expr);
138+
static Node *transformJsonSerializeExpr(ParseState *pstate,
139+
JsonSerializeExpr *expr);
138140
static Node *make_row_comparison_op(ParseState *pstate, List *opname,
139141
List *largs, List *rargs, int location);
140142
static Node *make_row_distinct_op(ParseState *pstate, List *opname,
@@ -419,6 +421,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
419421
result = transformJsonScalarExpr(pstate, (JsonScalarExpr *) expr);
420422
break;
421423

424+
case T_JsonSerializeExpr:
425+
result = transformJsonSerializeExpr(pstate, (JsonSerializeExpr *) expr);
426+
break;
427+
422428
default:
423429
/* should not reach here */
424430
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -4911,3 +4917,27 @@ transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *jsexpr)
49114917
return makeJsonConstructorExpr(pstate, JSCTOR_JSON_SCALAR, list_make1(arg), NULL,
49124918
returning, false, false, jsexpr->location);
49134919
}
4920+
4921+
/*
4922+
* Transform a JSON_SERIALIZE() expression.
4923+
*/
4924+
static Node *
4925+
transformJsonSerializeExpr(ParseState *pstate, JsonSerializeExpr *expr)
4926+
{
4927+
Node *arg = transformJsonValueExpr(pstate, expr->expr);
4928+
JsonReturning *returning;
4929+
4930+
if (expr->output)
4931+
returning = transformJsonOutput(pstate, expr->output, true);
4932+
else
4933+
{
4934+
/* RETURNING TEXT FORMAT JSON is by default */
4935+
returning = makeNode(JsonReturning);
4936+
returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1);
4937+
returning->typid = TEXTOID;
4938+
returning->typmod = -1;
4939+
}
4940+
4941+
return makeJsonCtorExpr(pstate, JSCTOR_JSON_SERIALIZE, list_make1(arg),
4942+
NULL, returning, false, false, expr->location);
4943+
}

src/backend/parser/parse_target.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,6 +1934,9 @@ FigureColnameInternal(Node *node, char **name)
19341934
case T_JsonScalarExpr:
19351935
*name = "json_scalar";
19361936
return 2;
1937+
case T_JsonSerializeExpr:
1938+
*name = "json_serialize";
1939+
return 2;
19371940
case T_JsonObjectConstructor:
19381941
*name = "json_object";
19391942
return 2;

src/backend/utils/adt/ruleutils.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9608,6 +9608,9 @@ get_json_constructor(JsonConstructorExpr *ctor, deparse_context *context,
96089608
case JSCTOR_JSON_SCALAR:
96099609
funcname = "JSON_SCALAR";
96109610
break;
9611+
case JSCTOR_JSON_SERIALIZE:
9612+
funcname = "JSON_SERIALIZE";
9613+
break;
96119614
case JSCTOR_JSON_OBJECT:
96129615
funcname = "JSON_OBJECT";
96139616
break;

src/include/nodes/nodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ typedef enum NodeTag
202202
T_JsonReturning,
203203
T_JsonValueExpr,
204204
T_JsonScalarExpr,
205+
T_JsonSerializeExpr,
205206
T_JsonConstructorExpr,
206207
T_JsonExpr,
207208
T_JsonCoercion,

src/include/nodes/parsenodes.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,18 @@ typedef struct JsonScalarExpr
15811581
int location; /* token location, or -1 if unknown */
15821582
} JsonScalarExpr;
15831583

1584+
/*
1585+
* JsonSerializeExpr -
1586+
* untransformed representation of JSON_SERIALIZE() function
1587+
*/
1588+
typedef struct JsonSerializeExpr
1589+
{
1590+
NodeTag type;
1591+
JsonValueExpr *expr; /* json value expression */
1592+
JsonOutput *output; /* RETURNING clause, if specified */
1593+
int location; /* token location, or -1 if unknown */
1594+
} JsonSerializeExpr;
1595+
15841596
/*
15851597
* JsonObjectConstructor -
15861598
* untransformed representation of JSON_OBJECT() constructor

src/include/nodes/primnodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,7 @@ typedef enum JsonConstructorType
12941294
JSCTOR_JSON_OBJECTAGG = 3,
12951295
JSCTOR_JSON_ARRAYAGG = 4,
12961296
JSCTOR_JSON_SCALAR = 5,
1297+
JSCTOR_JSON_SERIALIZE = 6
12971298
} JsonConstructorType;
12981299

12991300
/*

src/include/parser/kwlist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ PG_KEYWORD("json_object", JSON_OBJECT, COL_NAME_KEYWORD)
234234
PG_KEYWORD("json_objectagg", JSON_OBJECTAGG, COL_NAME_KEYWORD)
235235
PG_KEYWORD("json_query", JSON_QUERY, COL_NAME_KEYWORD)
236236
PG_KEYWORD("json_scalar", JSON_SCALAR, COL_NAME_KEYWORD)
237+
PG_KEYWORD("json_serialize", JSON_SERIALIZE, COL_NAME_KEYWORD)
237238
PG_KEYWORD("json_value", JSON_VALUE, COL_NAME_KEYWORD)
238239
PG_KEYWORD("keep", KEEP, UNRESERVED_KEYWORD)
239240
PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)

0 commit comments

Comments
 (0)