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

Commitedcf87d

Browse files
author
Nikita Glukhov
committed
Add JsonValueExpr transformation
1 parentceb864a commitedcf87d

File tree

9 files changed

+319
-0
lines changed

9 files changed

+319
-0
lines changed

‎contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,6 +3086,15 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
30863086
JumbleExpr(jstate, (Node*)conf->exclRelTlist);
30873087
}
30883088
break;
3089+
caseT_JsonValueExpr:
3090+
{
3091+
JsonValueExpr*expr= (JsonValueExpr*)node;
3092+
3093+
JumbleExpr(jstate, (Node*)expr->expr);
3094+
APP_JUMB(expr->format.type);
3095+
APP_JUMB(expr->format.encoding);
3096+
}
3097+
break;
30893098
caseT_List:
30903099
foreach(temp, (List*)node)
30913100
{

‎src/backend/executor/execExpr.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,6 +2108,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
21082108
break;
21092109
}
21102110

2111+
caseT_JsonValueExpr:
2112+
ExecInitExprRec(((JsonValueExpr*)node)->expr,state,resv,
2113+
resnull);
2114+
break;
2115+
21112116
default:
21122117
elog(ERROR,"unrecognized node type: %d",
21132118
(int)nodeTag(node));

‎src/backend/nodes/copyfuncs.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,6 +2248,20 @@ _copyOnConflictExpr(const OnConflictExpr *from)
22482248
returnnewnode;
22492249
}
22502250

2251+
/*
2252+
* _copyJsonValueExpr
2253+
*/
2254+
staticJsonValueExpr*
2255+
_copyJsonValueExpr(constJsonValueExpr*from)
2256+
{
2257+
JsonValueExpr*newnode=makeNode(JsonValueExpr);
2258+
2259+
COPY_NODE_FIELD(expr);
2260+
COPY_SCALAR_FIELD(format);
2261+
2262+
returnnewnode;
2263+
}
2264+
22512265
/* ****************************************************************
22522266
*pathnodes.h copy functions
22532267
*
@@ -5145,6 +5159,9 @@ copyObjectImpl(const void *from)
51455159
caseT_OnConflictExpr:
51465160
retval=_copyOnConflictExpr(from);
51475161
break;
5162+
caseT_JsonValueExpr:
5163+
retval=_copyJsonValueExpr(from);
5164+
break;
51485165

51495166
/*
51505167
* RELATION NODES

‎src/backend/nodes/equalfuncs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,17 @@ _equalOnConflictExpr(const OnConflictExpr *a, const OnConflictExpr *b)
818818
return true;
819819
}
820820

821+
staticbool
822+
_equalJsonValueExpr(constJsonValueExpr*a,constJsonValueExpr*b)
823+
{
824+
COMPARE_NODE_FIELD(expr);
825+
COMPARE_SCALAR_FIELD(format.type);
826+
COMPARE_SCALAR_FIELD(format.encoding);
827+
COMPARE_LOCATION_FIELD(format.location);
828+
829+
return true;
830+
}
831+
821832
/*
822833
* Stuff from pathnodes.h
823834
*/
@@ -3210,6 +3221,9 @@ equal(const void *a, const void *b)
32103221
caseT_JoinExpr:
32113222
retval=_equalJoinExpr(a,b);
32123223
break;
3224+
caseT_JsonValueExpr:
3225+
retval=_equalJsonValueExpr(a,b);
3226+
break;
32133227

32143228
/*
32153229
* RELATION NODES

‎src/backend/nodes/nodeFuncs.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ exprType(const Node *expr)
258258
caseT_PlaceHolderVar:
259259
type=exprType((Node*) ((constPlaceHolderVar*)expr)->phexpr);
260260
break;
261+
caseT_JsonValueExpr:
262+
type=exprType((Node*) ((constJsonValueExpr*)expr)->expr);
263+
break;
261264
default:
262265
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
263266
type=InvalidOid;/* keep compiler quiet */
@@ -491,6 +494,8 @@ exprTypmod(const Node *expr)
491494
return ((constSetToDefault*)expr)->typeMod;
492495
caseT_PlaceHolderVar:
493496
returnexprTypmod((Node*) ((constPlaceHolderVar*)expr)->phexpr);
497+
caseT_JsonValueExpr:
498+
returnexprTypmod((Node*) ((constJsonValueExpr*)expr)->expr);
494499
default:
495500
break;
496501
}
@@ -906,6 +911,9 @@ exprCollation(const Node *expr)
906911
caseT_PlaceHolderVar:
907912
coll=exprCollation((Node*) ((constPlaceHolderVar*)expr)->phexpr);
908913
break;
914+
caseT_JsonValueExpr:
915+
coll=exprCollation((Node*) ((constJsonValueExpr*)expr)->expr);
916+
break;
909917
default:
910918
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
911919
coll=InvalidOid;/* keep compiler quiet */
@@ -1109,6 +1117,10 @@ exprSetCollation(Node *expr, Oid collation)
11091117
Assert(!OidIsValid(collation));/* result is always an integer
11101118
* type */
11111119
break;
1120+
caseT_JsonValueExpr:
1121+
exprSetCollation((Node*) ((constJsonValueExpr*)expr)->expr,
1122+
collation);
1123+
break;
11121124
default:
11131125
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
11141126
break;
@@ -1549,6 +1561,9 @@ exprLocation(const Node *expr)
15491561
caseT_PartitionRangeDatum:
15501562
loc= ((constPartitionRangeDatum*)expr)->location;
15511563
break;
1564+
caseT_JsonValueExpr:
1565+
loc=exprLocation((Node*) ((constJsonValueExpr*)expr)->expr);
1566+
break;
15521567
default:
15531568
/* for any other node type it's just unknown... */
15541569
loc=-1;
@@ -2246,6 +2261,8 @@ expression_tree_walker(Node *node,
22462261
return true;
22472262
}
22482263
break;
2264+
caseT_JsonValueExpr:
2265+
returnwalker(((JsonValueExpr*)node)->expr,context);
22492266
default:
22502267
elog(ERROR,"unrecognized node type: %d",
22512268
(int)nodeTag(node));
@@ -3169,6 +3186,16 @@ expression_tree_mutator(Node *node,
31693186
return (Node*)newnode;
31703187
}
31713188
break;
3189+
caseT_JsonValueExpr:
3190+
{
3191+
JsonValueExpr*jve= (JsonValueExpr*)node;
3192+
JsonValueExpr*newnode;
3193+
3194+
FLATCOPY(newnode,jve,JsonValueExpr);
3195+
MUTATE(newnode->expr,jve->expr,Expr*);
3196+
3197+
return (Node*)newnode;
3198+
}
31723199
default:
31733200
elog(ERROR,"unrecognized node type: %d",
31743201
(int)nodeTag(node));
@@ -3864,6 +3891,8 @@ raw_expression_tree_walker(Node *node,
38643891
break;
38653892
caseT_CommonTableExpr:
38663893
returnwalker(((CommonTableExpr*)node)->ctequery,context);
3894+
caseT_JsonValueExpr:
3895+
returnwalker(((JsonValueExpr*)node)->expr,context);
38673896
default:
38683897
elog(ERROR,"unrecognized node type: %d",
38693898
(int)nodeTag(node));

‎src/backend/nodes/outfuncs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,17 @@ _outOnConflictExpr(StringInfo str, const OnConflictExpr *node)
17091709
WRITE_NODE_FIELD(exclRelTlist);
17101710
}
17111711

1712+
staticvoid
1713+
_outJsonValueExpr(StringInfostr,constJsonValueExpr*node)
1714+
{
1715+
WRITE_NODE_TYPE("JSONVALUEEXPR");
1716+
1717+
WRITE_NODE_FIELD(expr);
1718+
WRITE_ENUM_FIELD(format.type,JsonFormatType);
1719+
WRITE_ENUM_FIELD(format.encoding,JsonEncoding);
1720+
WRITE_LOCATION_FIELD(format.location);
1721+
}
1722+
17121723
/*****************************************************************************
17131724
*
17141725
*Stuff from pathnodes.h.
@@ -4337,6 +4348,9 @@ outNode(StringInfo str, const void *obj)
43374348
caseT_PartitionRangeDatum:
43384349
_outPartitionRangeDatum(str,obj);
43394350
break;
4351+
caseT_JsonValueExpr:
4352+
_outJsonValueExpr(str,obj);
4353+
break;
43404354

43414355
default:
43424356

‎src/backend/nodes/readfuncs.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,22 @@ _readOnConflictExpr(void)
13431343
READ_DONE();
13441344
}
13451345

1346+
/*
1347+
* _readJsonValueExpr
1348+
*/
1349+
staticJsonValueExpr*
1350+
_readJsonValueExpr(void)
1351+
{
1352+
READ_LOCALS(JsonValueExpr);
1353+
1354+
READ_NODE_FIELD(expr);
1355+
READ_ENUM_FIELD(format.type,JsonFormatType);
1356+
READ_ENUM_FIELD(format.encoding,JsonEncoding);
1357+
READ_LOCATION_FIELD(format.location);
1358+
1359+
READ_DONE();
1360+
}
1361+
13461362
/*
13471363
*Stuff from pathnodes.h.
13481364
*
@@ -2880,6 +2896,8 @@ parseNodeString(void)
28802896
return_value=_readPartitionBoundSpec();
28812897
elseif (MATCH("PARTITIONRANGEDATUM",19))
28822898
return_value=_readPartitionRangeDatum();
2899+
elseif (MATCH("JSONVALUEEXPR",13))
2900+
return_value=_readJsonValueExpr();
28832901
else
28842902
{
28852903
elog(ERROR,"badly formatted node string \"%.32s\"...",token);

‎src/backend/parser/parse_expr.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include"parser/parse_type.h"
3535
#include"utils/builtins.h"
3636
#include"utils/date.h"
37+
#include"utils/fmgroids.h"
3738
#include"utils/lsyscache.h"
3839
#include"utils/timestamp.h"
3940
#include"utils/xml.h"
@@ -3569,3 +3570,159 @@ ParseExprKindName(ParseExprKind exprKind)
35693570
}
35703571
return"unrecognized expression kind";
35713572
}
3573+
3574+
/*
3575+
* Make string Const node from JSON encoding name.
3576+
*
3577+
* UTF8 is default encoding.
3578+
*/
3579+
staticConst*
3580+
getJsonEncodingConst(JsonFormat*format)
3581+
{
3582+
JsonEncodingencoding;
3583+
constchar*enc;
3584+
Nameencname=palloc(sizeof(NameData));
3585+
3586+
if (!format||
3587+
format->type==JS_FORMAT_DEFAULT||
3588+
format->encoding==JS_ENC_DEFAULT)
3589+
encoding=JS_ENC_UTF8;
3590+
else
3591+
encoding=format->encoding;
3592+
3593+
switch (encoding)
3594+
{
3595+
caseJS_ENC_UTF16:
3596+
enc="UTF16";
3597+
break;
3598+
caseJS_ENC_UTF32:
3599+
enc="UTF32";
3600+
break;
3601+
caseJS_ENC_UTF8:
3602+
default:
3603+
enc="UTF8";
3604+
break;
3605+
}
3606+
3607+
namestrcpy(encname,enc);
3608+
3609+
returnmakeConst(NAMEOID,-1,InvalidOid,NAMEDATALEN,
3610+
NameGetDatum(encname), false, false);
3611+
}
3612+
3613+
/*
3614+
* Make bytea => text conversion using specified JSON format encoding.
3615+
*/
3616+
staticNode*
3617+
makeJsonByteaToTextConversion(Node*expr,JsonFormat*format,intlocation)
3618+
{
3619+
Const*encoding=getJsonEncodingConst(format);
3620+
FuncExpr*fexpr=makeFuncExpr(F_PG_CONVERT_FROM,TEXTOID,
3621+
list_make2(expr,encoding),
3622+
InvalidOid,InvalidOid,
3623+
COERCE_INTERNAL_CAST);
3624+
3625+
fexpr->location=location;
3626+
3627+
return (Node*)fexpr;
3628+
}
3629+
3630+
/*
3631+
* Transform JSON value expression using specified input JSON format or
3632+
* default format otherwise.
3633+
*/
3634+
staticNode*
3635+
transformJsonValueExpr(ParseState*pstate,JsonValueExpr*ve,
3636+
JsonFormatTypedefault_format)
3637+
{
3638+
Node*expr=transformExprRecurse(pstate, (Node*)ve->expr);
3639+
JsonFormatTypeformat;
3640+
Oidexprtype;
3641+
intlocation;
3642+
chartypcategory;
3643+
booltypispreferred;
3644+
3645+
if (exprType(expr)==UNKNOWNOID)
3646+
expr=coerce_to_specific_type(pstate,expr,TEXTOID,"JSON_VALUE_EXPR");
3647+
3648+
exprtype=exprType(expr);
3649+
location=exprLocation(expr);
3650+
3651+
get_type_category_preferred(exprtype,&typcategory,&typispreferred);
3652+
3653+
if (ve->format.type!=JS_FORMAT_DEFAULT)
3654+
{
3655+
if (ve->format.encoding!=JS_ENC_DEFAULT&&exprtype!=BYTEAOID)
3656+
ereport(ERROR,
3657+
(errcode(ERRCODE_DATATYPE_MISMATCH),
3658+
errmsg("JSON ENCODING clause is only allowed for bytea input type"),
3659+
parser_errposition(pstate,ve->format.location)));
3660+
3661+
if (exprtype==JSONOID||exprtype==JSONBOID)
3662+
{
3663+
format=JS_FORMAT_DEFAULT;/* do not format json[b] types */
3664+
ereport(WARNING,
3665+
(errmsg("FORMAT JSON has no effect for json and jsonb types"),
3666+
parser_errposition(pstate,ve->format->location)));
3667+
}
3668+
else
3669+
format=ve->format.type;
3670+
}
3671+
elseif (exprtype==JSONOID||exprtype==JSONBOID)
3672+
format=JS_FORMAT_DEFAULT;/* do not format json[b] types */
3673+
else
3674+
format=default_format;
3675+
3676+
if (format!=JS_FORMAT_DEFAULT)
3677+
{
3678+
Oidtargettype=format==JS_FORMAT_JSONB ?JSONBOID :JSONOID;
3679+
Node*coerced;
3680+
FuncExpr*fexpr;
3681+
3682+
if (exprtype!=BYTEAOID&&typcategory!=TYPCATEGORY_STRING)
3683+
ereport(ERROR,
3684+
(errcode(ERRCODE_DATATYPE_MISMATCH),
3685+
errmsg(ve->format.type==JS_FORMAT_DEFAULT ?
3686+
"cannot use non-string types with implicit FORMAT JSON clause" :
3687+
"cannot use non-string types with explicit FORMAT JSON clause"),
3688+
parser_errposition(pstate,ve->format.location >=0 ?
3689+
ve->format.location :location)));
3690+
3691+
/* Convert encoded JSON text from bytea. */
3692+
if (format==JS_FORMAT_JSON&&exprtype==BYTEAOID)
3693+
{
3694+
expr=makeJsonByteaToTextConversion(expr,&ve->format,location);
3695+
exprtype=TEXTOID;
3696+
}
3697+
3698+
/* Try to coerce to the target type. */
3699+
coerced=coerce_to_target_type(pstate,expr,exprtype,
3700+
targettype,-1,
3701+
COERCION_EXPLICIT,
3702+
COERCE_INTERNAL_CAST,
3703+
location);
3704+
3705+
if (coerced)
3706+
expr=coerced;
3707+
else
3708+
{
3709+
/* If coercion failed, use to_json()/to_jsonb() functions. */
3710+
Oidfnoid=targettype==JSONOID ?F_TO_JSON :F_TO_JSONB;
3711+
3712+
fexpr=makeFuncExpr(fnoid,targettype,list_make1(expr),
3713+
InvalidOid,InvalidOid,
3714+
COERCE_INTERNAL_CAST);
3715+
fexpr->location=location;
3716+
3717+
expr= (Node*)fexpr;
3718+
}
3719+
3720+
ve=copyObject(ve);
3721+
ve->expr= (Expr*)expr;
3722+
3723+
expr= (Node*)ve;
3724+
}
3725+
3726+
returnexpr;
3727+
}
3728+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp