Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc1010e2

Browse files
author
Nikita Glukhov
committed
Add JSON_SCALAR()
1 parentd58ca1c commitc1010e2

File tree

21 files changed

+432
-60
lines changed

21 files changed

+432
-60
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16901,11 +16901,16 @@ $ ? (@ like_regex "^\\d+$")
1690116901
<para>
1690216902
<productname>PostgreSQL</productname> provides several functions
1690316903
that generate JSON data. Taking values of SQL types as input, these
16904-
functions construct JSON objectsor JSONarrays represented as
16905-
SQL character or binary strings.
16904+
functions construct JSON objects, JSON arraysor JSONscalars represented
16905+
as <type>json</type> or <type>jsonb</type> types,SQL character or binary strings.
1690616906
</para>
1690716907

1690816908
<itemizedlist>
16909+
<listitem>
16910+
<para>
16911+
<xref linkend="functions-jsonscalar"/>
16912+
</para>
16913+
</listitem>
1690916914
<listitem>
1691016915
<para>
1691116916
<link linkend="functions-jsonobject"><literal>JSON_OBJECT</literal></link>
@@ -16928,6 +16933,102 @@ $ ? (@ like_regex "^\\d+$")
1692816933
</listitem>
1692916934
</itemizedlist>
1693016935

16936+
<refentry id="functions-jsonscalar">
16937+
<refnamediv>
16938+
<refname>JSON_SCALAR</refname>
16939+
<refpurpose>create a JSON scalar</refpurpose>
16940+
</refnamediv>
16941+
16942+
<refsynopsisdiv>
16943+
<synopsis>
16944+
JSON_SCALAR (
16945+
<replaceable class="parameter">expression</replaceable>
16946+
[ RETURNING <replaceable class="parameter">json_data_type</replaceable> ]
16947+
)
16948+
</synopsis>
16949+
</refsynopsisdiv>
16950+
16951+
<refsect1>
16952+
<title>Description</title>
16953+
16954+
<para>
16955+
<function>JSON_SCALAR</function> function generates a scalar
16956+
<acronym>JSON</acronym> from a <acronym>SQL</acronym> data.
16957+
</para>
16958+
</refsect1>
16959+
16960+
<refsect1>
16961+
<title>Parameters</title>
16962+
<variablelist>
16963+
<varlistentry>
16964+
<term>
16965+
<literal><replaceable class="parameter">expression</replaceable></literal>
16966+
</term>
16967+
<listitem>
16968+
<para>
16969+
Expression that provides the data for constructing a
16970+
<acronym>JSON</acronym>.
16971+
For null input, <acronym>SQL</acronym> null
16972+
(not a <acronym>JSON</acronym> null) value is returned.
16973+
For any scalar other than a number, a Boolean, the text representation
16974+
will be used, with escaping as necessary to make it a valid
16975+
<acronym>JSON</acronym> string value.
16976+
For details, see
16977+
<function>to_json()</function>/<function>to_jsonb()</function>
16978+
in <xref linkend="functions-json-creation-table"/>.
16979+
</para>
16980+
</listitem>
16981+
</varlistentry>
16982+
<varlistentry>
16983+
<term>
16984+
<literal>RETURNING <replaceable class="parameter">json_data_type</replaceable></literal>
16985+
</term>
16986+
<listitem>
16987+
<para>
16988+
The output clause that specifies the type (<type>json</type> or
16989+
<type>jsonb</type>) of the generated <acronym>JSON</acronym> scalar.
16990+
</para>
16991+
</listitem>
16992+
</varlistentry>
16993+
</variablelist>
16994+
</refsect1>
16995+
16996+
<refsect1>
16997+
<title>Notes</title>
16998+
<para>
16999+
Alternatively, you can construct <acronym>JSON</acronym> objects by
17000+
using <productname>PostgreSQL</productname>-specific
17001+
<function>to_json()</function>/<function>to_jsonb()</function> functions.
17002+
See <xref linkend="functions-json-creation-table"/> for details.
17003+
</para>
17004+
</refsect1>
17005+
<refsect1>
17006+
<title>Examples</title>
17007+
<para>
17008+
Construct a JSON from the provided values various types:
17009+
</para>
17010+
<screen>
17011+
SELECT JSON_SCALAR(123.45);
17012+
json_scalar
17013+
-------------
17014+
123.45
17015+
(1 row)
17016+
17017+
SELECT JSON_SCALAR('123');
17018+
json_scalar
17019+
-------------
17020+
"123"
17021+
(1 row)
17022+
17023+
SELECT JSON_SCALAR(true);
17024+
json_scalar
17025+
-------------
17026+
true
17027+
(1 row)
17028+
</screen>
17029+
</refsect1>
17030+
</refentry>
17031+
1693117032
<sect4 id="functions-jsonobject">
1693217033
<title><literal>JSON_OBJECT</literal></title>
1693317034
<indexterm><primary>json_object</primary></indexterm>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ JSON_EXISTS
162162
JSON_OBJECT
163163
JSON_OBJECTAGG
164164
JSON_QUERY
165+
JSON_SCALAR
165166
JSON_TABLE
166167
JSON_TABLE_PRIMITIVE
167168
JSON_VALUE

‎src/backend/executor/execExpr.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
#include"utils/array.h"
4747
#include"utils/builtins.h"
4848
#include"utils/datum.h"
49+
#include"utils/json.h"
50+
#include"utils/jsonb.h"
4951
#include"utils/jsonpath.h"
5052
#include"utils/lsyscache.h"
5153
#include"utils/typcache.h"
@@ -2172,6 +2174,43 @@ ExecInitExprRec(Expr *node, ExprState *state,
21722174
argno++;
21732175
}
21742176

2177+
/* prepare type cache for datum_to_json[b]() */
2178+
if (ctor->type==JSCTOR_JSON_SCALAR)
2179+
{
2180+
boolis_jsonb=
2181+
ctor->returning->format->format==JS_FORMAT_JSONB;
2182+
2183+
scratch.d.json_ctor.arg_type_cache=
2184+
palloc(sizeof(*scratch.d.json_ctor.arg_type_cache)*nargs);
2185+
2186+
for (inti=0;i<nargs;i++)
2187+
{
2188+
intcategory;
2189+
Oidoutfuncid;
2190+
Oidtypid=scratch.d.json_ctor.arg_types[i];
2191+
2192+
if (is_jsonb)
2193+
{
2194+
JsonbTypeCategoryjbcat;
2195+
2196+
jsonb_categorize_type(typid,&jbcat,&outfuncid);
2197+
2198+
category= (int)jbcat;
2199+
}
2200+
else
2201+
{
2202+
JsonTypeCategoryjscat;
2203+
2204+
json_categorize_type(typid,&jscat,&outfuncid);
2205+
2206+
category= (int)jscat;
2207+
}
2208+
2209+
scratch.d.json_ctor.arg_type_cache[i].outfuncid=outfuncid;
2210+
scratch.d.json_ctor.arg_type_cache[i].category=category;
2211+
}
2212+
}
2213+
21752214
ExprEvalPushStep(state,&scratch);
21762215
}
21772216

‎src/backend/executor/execExprInterp.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,25 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
15801580
op->d.json_constructor.arg_types,
15811581
op->d.json_constructor.constructor->absent_on_null,
15821582
op->d.json_constructor.constructor->unique);
1583+
elseif (ctor->type==JSCTOR_JSON_SCALAR)
1584+
{
1585+
if (op->d.json_ctor.arg_nulls[0])
1586+
{
1587+
res= (Datum)0;
1588+
isnull= true;
1589+
}
1590+
else
1591+
{
1592+
Datumvalue=op->d.json_constructor.arg_values[0];
1593+
intcategory=op->d.json_constructor.arg_type_cache[0].category;
1594+
Oidoutfuncid=op->d.json_constructor.arg_type_cache[0].outfuncid;
1595+
1596+
if (is_jsonb)
1597+
res=to_jsonb_worker(value,category,outfuncid);
1598+
else
1599+
res=to_json_worker(value,category,outfuncid);
1600+
}
1601+
}
15831602
else
15841603
{
15851604
res= (Datum)0;

‎src/backend/nodes/copyfuncs.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,6 +2294,20 @@ _copyJsonValueExpr(const JsonValueExpr *from)
22942294
returnnewnode;
22952295
}
22962296

2297+
/*
2298+
* _copyJsonScalarExpr
2299+
*/
2300+
staticJsonScalarExpr*
2301+
_copyJsonScalarExpr(constJsonScalarExpr*from)
2302+
{
2303+
JsonScalarExpr*newnode=makeNode(JsonScalarExpr);
2304+
2305+
COPY_NODE_FIELD(expr);
2306+
COPY_LOCATION_FIELD(location);
2307+
2308+
returnnewnode;
2309+
}
2310+
22972311
/*
22982312
* _copyJsonConstructorExpr
22992313
*/
@@ -5492,6 +5506,9 @@ copyObjectImpl(const void *from)
54925506
caseT_JsonValueExpr:
54935507
retval=_copyJsonValueExpr(from);
54945508
break;
5509+
caseT_JsonScalarExpr:
5510+
retval=_copyJsonScalarExpr(from);
5511+
break;
54955512
caseT_JsonKeyValue:
54965513
retval=_copyJsonKeyValue(from);
54975514
break;

‎src/backend/nodes/equalfuncs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,15 @@ _equalJsonValueExpr(const JsonValueExpr *a, const JsonValueExpr *b)
848848
return true;
849849
}
850850

851+
staticbool
852+
_equalJsonScalarExpr(constJsonScalarExpr*a,constJsonScalarExpr*b)
853+
{
854+
COMPARE_NODE_FIELD(expr);
855+
COMPARE_LOCATION_FIELD(location);
856+
857+
return true;
858+
}
859+
851860
staticbool
852861
_equalJsonConstructorExpr(constJsonConstructorExpr*a,constJsonConstructorExpr*b)
853862
{
@@ -3436,6 +3445,9 @@ equal(const void *a, const void *b)
34363445
caseT_JsonValueExpr:
34373446
retval=_equalJsonValueExpr(a,b);
34383447
break;
3448+
caseT_JsonScalarExpr:
3449+
retval=_equalJsonScalarExpr(a,b);
3450+
break;
34393451
caseT_JsonConstructorExpr:
34403452
retval=_equalJsonConstructorExpr(a,b);
34413453
break;

‎src/backend/parser/gram.y

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
613613
json_value_func_expr
614614
json_query_expr
615615
json_exists_predicate
616+
json_scalar_expr
616617
json_api_common_syntax
617618
json_context_item
618619
json_argument
@@ -733,7 +734,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
733734
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
734735

735736
JOIN JSON JSON_ARRAY JSON_ARRAYAGG JSON_EXISTS JSON_OBJECT JSON_OBJECTAGG
736-
JSON_QUERY JSON_VALUE
737+
JSON_QUERYJSON_SCALARJSON_VALUE
737738

738739
KEY KEYS KEEP
739740

@@ -14791,6 +14792,17 @@ json_func_expr:
1479114792
| json_value_func_expr
1479214793
| json_query_expr
1479314794
| json_exists_predicate
14795+
| json_scalar_expr
14796+
;
14797+
14798+
json_scalar_expr:
14799+
JSON_SCALAR'(' a_expr')'
14800+
{
14801+
JsonScalarExpr *n =makeNode(JsonScalarExpr);
14802+
n->expr = (Expr *) $3;
14803+
n->location = @1;
14804+
$$ = (Node *) n;
14805+
}
1479414806
;
1479514807

1479614808

@@ -16007,6 +16019,7 @@ col_name_keyword:
1600716019
| JSON_OBJECT
1600816020
| JSON_OBJECTAGG
1600916021
| JSON_QUERY
16022+
| JSON_SCALAR
1601016023
| JSON_VALUE
1601116024
| LEAST
1601216025
| NATIONAL

‎src/backend/parser/parse_expr.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ static Node *transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg);
134134
staticNode*transformJsonIsPredicate(ParseState*pstate,JsonIsPredicate*p);
135135
staticNode*transformJsonFuncExpr(ParseState*pstate,JsonFuncExpr*p);
136136
staticNode*transformJsonValueExpr(ParseState*pstate,JsonValueExpr*jve);
137+
staticNode*transformJsonScalarExpr(ParseState*pstate,JsonScalarExpr*expr);
137138
staticNode*make_row_comparison_op(ParseState*pstate,List*opname,
138139
List*largs,List*rargs,intlocation);
139140
staticNode*make_row_distinct_op(ParseState*pstate,List*opname,
@@ -414,6 +415,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
414415
result=transformJsonValueExpr(pstate, (JsonValueExpr*)expr);
415416
break;
416417

418+
caseT_JsonScalarExpr:
419+
result=transformJsonScalarExpr(pstate, (JsonScalarExpr*)expr);
420+
break;
421+
417422
default:
418423
/* should not reach here */
419424
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
@@ -4886,3 +4891,23 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
48864891

48874892
return (Node*)jsexpr;
48884893
}
4894+
4895+
/*
4896+
* Transform a JSON_SCALAR() expression.
4897+
*/
4898+
staticNode*
4899+
transformJsonScalarExpr(ParseState*pstate,JsonScalarExpr*jsexpr)
4900+
{
4901+
JsonReturning*returning=makeNode(JsonReturning);
4902+
Node*arg=transformExprRecurse(pstate, (Node*)jsexpr->expr);
4903+
4904+
returning->format=makeJsonFormat(JS_FORMAT_JSON,JS_ENC_DEFAULT,-1);
4905+
returning->typid=JSONOID;
4906+
returning->typmod=-1;
4907+
4908+
if (exprType(arg)==UNKNOWNOID)
4909+
arg=coerce_to_specific_type(pstate,arg,TEXTOID,"JSON_SCALAR");
4910+
4911+
returnmakeJsonCtorExpr(pstate,JSCTOR_JSON_SCALAR,list_make1(arg),NULL,
4912+
returning, false, false,jsexpr->location);
4913+
}

‎src/backend/parser/parse_target.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,6 +1931,9 @@ FigureColnameInternal(Node *node, char **name)
19311931
caseT_XmlSerialize:
19321932
*name="xmlserialize";
19331933
return2;
1934+
caseT_JsonScalarExpr:
1935+
*name="json_scalar";
1936+
return2;
19341937
caseT_JsonObjectConstructor:
19351938
*name="json_object";
19361939
return2;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp