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

Commit39d0a43

Browse files
author
Nikita Glukhov
committed
Refactor output coercion in SQL/JSON constructors
1 parent7548800 commit39d0a43

File tree

9 files changed

+122
-61
lines changed

9 files changed

+122
-61
lines changed

‎contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3117,6 +3117,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
31173117
JsonCtorExpr*ctor= (JsonCtorExpr*)node;
31183118

31193119
JumbleExpr(jstate, (Node*)ctor->func);
3120+
JumbleExpr(jstate, (Node*)ctor->coercion);
31203121
JumbleExpr(jstate, (Node*)ctor->returning);
31213122
APP_JUMB(ctor->type);
31223123
APP_JUMB(ctor->unique);

‎src/backend/executor/execExpr.c

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,40 +2141,55 @@ ExecInitExprRec(Expr *node, ExprState *state,
21412141
if (ctor->func)
21422142
{
21432143
ExecInitExprRec(ctor->func,state,resv,resnull);
2144-
break;
21452144
}
2146-
2147-
scratch.opcode=EEOP_JSON_CTOR;
2148-
scratch.d.json_ctor.ctor=ctor;
2149-
scratch.d.json_ctor.arg_values=palloc(sizeof(Datum)*nargs);
2150-
scratch.d.json_ctor.arg_nulls=palloc(sizeof(bool)*nargs);
2151-
scratch.d.json_ctor.arg_types=palloc(sizeof(Oid)*nargs);
2152-
scratch.d.json_ctor.nargs=nargs;
2153-
2154-
foreach(lc,args)
2145+
else
21552146
{
2156-
Expr*arg= (Expr*)lfirst(lc);
2147+
scratch.opcode=EEOP_JSON_CTOR;
2148+
scratch.d.json_ctor.ctor=ctor;
2149+
scratch.d.json_ctor.arg_values=palloc(sizeof(Datum)*nargs);
2150+
scratch.d.json_ctor.arg_nulls=palloc(sizeof(bool)*nargs);
2151+
scratch.d.json_ctor.arg_types=palloc(sizeof(Oid)*nargs);
2152+
scratch.d.json_ctor.nargs=nargs;
2153+
2154+
foreach(lc,args)
2155+
{
2156+
Expr*arg= (Expr*)lfirst(lc);
21572157

2158-
scratch.d.json_ctor.arg_types[argno]=exprType((Node*)arg);
2158+
scratch.d.json_ctor.arg_types[argno]=exprType((Node*)arg);
21592159

2160-
if (IsA(arg,Const))
2161-
{
2162-
/* Don't evaluate const arguments every round */
2163-
Const*con= (Const*)arg;
2160+
if (IsA(arg,Const))
2161+
{
2162+
/* Don't evaluate const arguments every round */
2163+
Const*con= (Const*)arg;
21642164

2165-
scratch.d.json_ctor.arg_values[argno]=con->constvalue;
2166-
scratch.d.json_ctor.arg_nulls[argno]=con->constisnull;
2167-
}
2168-
else
2169-
{
2170-
ExecInitExprRec(arg,state,
2171-
&scratch.d.json_ctor.arg_values[argno],
2172-
&scratch.d.json_ctor.arg_nulls[argno]);
2165+
scratch.d.json_ctor.arg_values[argno]=con->constvalue;
2166+
scratch.d.json_ctor.arg_nulls[argno]=con->constisnull;
2167+
}
2168+
else
2169+
{
2170+
ExecInitExprRec(arg,state,
2171+
&scratch.d.json_ctor.arg_values[argno],
2172+
&scratch.d.json_ctor.arg_nulls[argno]);
2173+
}
2174+
argno++;
21732175
}
2174-
argno++;
2176+
2177+
ExprEvalPushStep(state,&scratch);
21752178
}
21762179

2177-
ExprEvalPushStep(state,&scratch);
2180+
if (ctor->coercion)
2181+
{
2182+
Datum*innermost_caseval=state->innermost_caseval;
2183+
bool*innermost_isnull=state->innermost_casenull;
2184+
2185+
state->innermost_caseval=resv;
2186+
state->innermost_casenull=resnull;
2187+
2188+
ExecInitExprRec(ctor->coercion,state,resv,resnull);
2189+
2190+
state->innermost_caseval=innermost_caseval;
2191+
state->innermost_casenull=innermost_isnull;
2192+
}
21782193
}
21792194
break;
21802195

‎src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2302,9 +2302,10 @@ _copyJsonCtorExpr(const JsonCtorExpr *from)
23022302
{
23032303
JsonCtorExpr*newnode=makeNode(JsonCtorExpr);
23042304

2305+
COPY_SCALAR_FIELD(type);
23052306
COPY_NODE_FIELD(args);
23062307
COPY_NODE_FIELD(func);
2307-
COPY_SCALAR_FIELD(type);
2308+
COPY_NODE_FIELD(coercion);
23082309
COPY_NODE_FIELD(returning);
23092310
COPY_SCALAR_FIELD(absent_on_null);
23102311
COPY_SCALAR_FIELD(unique);

‎src/backend/nodes/equalfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,9 +851,10 @@ _equalJsonValueExpr(const JsonValueExpr *a, const JsonValueExpr *b)
851851
staticbool
852852
_equalJsonCtorExpr(constJsonCtorExpr*a,constJsonCtorExpr*b)
853853
{
854+
COMPARE_SCALAR_FIELD(type);
854855
COMPARE_NODE_FIELD(args);
855856
COMPARE_NODE_FIELD(func);
856-
COMPARE_SCALAR_FIELD(type);
857+
COMPARE_NODE_FIELD(coercion);
857858
COMPARE_NODE_FIELD(returning);
858859
COMPARE_SCALAR_FIELD(absent_on_null);
859860
COMPARE_SCALAR_FIELD(unique);

‎src/backend/nodes/nodeFuncs.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ exprType(const Node *expr)
266266
}
267267
break;
268268
caseT_JsonCtorExpr:
269-
type= ((constJsonCtorExpr*)expr)->returning->format->format==JS_FORMAT_JSONB ?JSONBOID :JSONOID;
269+
type= ((constJsonCtorExpr*)expr)->returning->typid;
270270
break;
271271
default:
272272
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
@@ -924,8 +924,14 @@ exprCollation(const Node *expr)
924924
coll=exprCollation((Node*) ((constJsonValueExpr*)expr)->formatted_expr);
925925
break;
926926
caseT_JsonCtorExpr:
927-
/* coll = exprCollation((Node *) ((const JsonCtorExpr *) expr)->func); */
928-
coll=InvalidOid;/* keep compiler quiet */
927+
{
928+
constJsonCtorExpr*ctor= (constJsonCtorExpr*)expr;
929+
930+
if (ctor->coercion)
931+
coll=exprCollation((Node*)ctor->coercion);
932+
else
933+
coll=InvalidOid;
934+
}
929935
break;
930936
default:
931937
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
@@ -1135,8 +1141,14 @@ exprSetCollation(Node *expr, Oid collation)
11351141
collation);
11361142
break;
11371143
caseT_JsonCtorExpr:
1138-
/* exprSetCollation((Node *) ((const JsonCtorExpr *) expr)->func, collation); */
1139-
Assert(!OidIsValid(collation));/* result is always an json[b] type */
1144+
{
1145+
JsonCtorExpr*ctor= (JsonCtorExpr*)expr;
1146+
1147+
if (ctor->coercion)
1148+
exprSetCollation((Node*)ctor->coercion,collation);
1149+
else
1150+
Assert(!OidIsValid(collation));/* result is always an json[b] type */
1151+
}
11401152
break;
11411153
default:
11421154
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
@@ -2299,6 +2311,8 @@ expression_tree_walker(Node *node,
22992311
return true;
23002312
if (walker(ctor->func,context))
23012313
return true;
2314+
if (walker(ctor->coercion,context))
2315+
return true;
23022316
}
23032317
break;
23042318
default:
@@ -3255,6 +3269,7 @@ expression_tree_mutator(Node *node,
32553269
FLATCOPY(newnode,jve,JsonCtorExpr);
32563270
MUTATE(newnode->args,jve->args,List*);
32573271
MUTATE(newnode->func,jve->func,Expr*);
3272+
MUTATE(newnode->coercion,jve->coercion,Expr*);
32583273
MUTATE(newnode->returning,jve->returning,JsonReturning*);
32593274

32603275
return (Node*)newnode;
@@ -3976,6 +3991,8 @@ raw_expression_tree_walker(Node *node,
39763991
return true;
39773992
if (walker(ctor->func,context))
39783993
return true;
3994+
if (walker(ctor->coercion,context))
3995+
return true;
39793996
if (walker(ctor->returning,context))
39803997
return true;
39813998
}

‎src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,7 @@ _outJsonCtorExpr(StringInfo str, const JsonCtorExpr *node)
17461746

17471747
WRITE_NODE_FIELD(args);
17481748
WRITE_NODE_FIELD(func);
1749+
WRITE_NODE_FIELD(coercion);
17491750
WRITE_INT_FIELD(type);
17501751
WRITE_NODE_FIELD(returning);
17511752
WRITE_BOOL_FIELD(unique);

‎src/backend/nodes/readfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ _readJsonCtorExpr(void)
13981398

13991399
READ_NODE_FIELD(args);
14001400
READ_NODE_FIELD(func);
1401+
READ_NODE_FIELD(coercion);
14011402
READ_INT_FIELD(type);
14021403
READ_NODE_FIELD(returning);
14031404
READ_BOOL_FIELD(unique);

‎src/backend/parser/parse_expr.c

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3974,6 +3974,46 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr,
39743974
returnres;
39753975
}
39763976

3977+
staticNode*
3978+
makeJsonCtorExpr(ParseState*pstate,JsonCtorTypetype,List*args,Expr*fexpr,
3979+
JsonReturning*returning,boolunique,boolabsent_on_null,
3980+
intlocation)
3981+
{
3982+
Node*placeholder;
3983+
Node*coercion;
3984+
JsonCtorExpr*jsctor=makeNode(JsonCtorExpr);
3985+
Oidintermediate_typid=
3986+
returning->format->format==JS_FORMAT_JSONB ?JSONBOID :JSONOID;
3987+
3988+
jsctor->args=args;
3989+
jsctor->func=fexpr;
3990+
jsctor->type=type;
3991+
jsctor->returning=returning;
3992+
jsctor->unique=unique;
3993+
jsctor->absent_on_null=absent_on_null;
3994+
jsctor->location=location;
3995+
3996+
if (fexpr)
3997+
placeholder=makeCaseTestExpr((Node*)fexpr);
3998+
else
3999+
{
4000+
CaseTestExpr*cte=makeNode(CaseTestExpr);
4001+
4002+
cte->typeId=intermediate_typid;
4003+
cte->typeMod=-1;
4004+
cte->collation=InvalidOid;
4005+
4006+
placeholder= (Node*)cte;
4007+
}
4008+
4009+
coercion=coerceJsonFuncExpr(pstate,placeholder,returning, true);
4010+
4011+
if (coercion!=placeholder)
4012+
jsctor->coercion= (Expr*)coercion;
4013+
4014+
return (Node*)jsctor;
4015+
}
4016+
39774017
/*
39784018
* Transform JSON_OBJECT() constructor.
39794019
*
@@ -3986,7 +4026,7 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr,
39864026
staticNode*
39874027
transformJsonObjectCtor(ParseState*pstate,JsonObjectCtor*ctor)
39884028
{
3989-
JsonCtorExpr*jsctor;
4029+
JsonReturning*returning;
39904030
List*args=NIL;
39914031

39924032
/* transform key-value pairs, if any */
@@ -4007,15 +4047,11 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
40074047
}
40084048
}
40094049

4010-
jsctor=makeNode(JsonCtorExpr);
4011-
jsctor->args=args;
4012-
jsctor->type=JSCTOR_JSON_OBJECT;
4013-
jsctor->returning=transformJsonCtorOutput(pstate,ctor->output,args);
4014-
jsctor->unique=ctor->unique;
4015-
jsctor->absent_on_null=ctor->absent_on_null;
4016-
jsctor->location=ctor->location;
4050+
returning=transformJsonCtorOutput(pstate,ctor->output,args);
40174051

4018-
returncoerceJsonFuncExpr(pstate, (Node*)jsctor,jsctor->returning, true);
4052+
returnmakeJsonCtorExpr(pstate,JSCTOR_JSON_OBJECT,args,NULL,
4053+
returning,ctor->unique,ctor->absent_on_null,
4054+
ctor->location);
40194055
}
40204056

40214057
/*
@@ -4093,7 +4129,6 @@ transformJsonAggCtor(ParseState *pstate, JsonAggCtor *agg_ctor,
40934129
boolunique,boolabsent_on_null)
40944130
{
40954131
Oidaggfnoid;
4096-
JsonCtorExpr*jsctor;
40974132
Node*node;
40984133
Expr*aggfilter=agg_ctor->agg_filter ? (Expr*)
40994134
transformWhereClause(pstate,agg_ctor->agg_filter,
@@ -4156,15 +4191,8 @@ transformJsonAggCtor(ParseState *pstate, JsonAggCtor *agg_ctor,
41564191
node= (Node*)aggref;
41574192
}
41584193

4159-
jsctor=makeNode(JsonCtorExpr);
4160-
jsctor->func= (Expr*)node;
4161-
jsctor->type=ctor_type;
4162-
jsctor->returning=returning;
4163-
jsctor->unique=unique;
4164-
jsctor->absent_on_null=absent_on_null;
4165-
jsctor->location=agg_ctor->location;
4166-
4167-
returncoerceJsonFuncExpr(pstate, (Node*)jsctor,returning, true);
4194+
returnmakeJsonCtorExpr(pstate,ctor_type,NIL, (Expr*)node,returning,
4195+
unique,absent_on_null,agg_ctor->location);
41684196
}
41694197

41704198
/*
@@ -4277,7 +4305,7 @@ transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg)
42774305
staticNode*
42784306
transformJsonArrayCtor(ParseState*pstate,JsonArrayCtor*ctor)
42794307
{
4280-
JsonCtorExpr*jsctor;
4308+
JsonReturning*returning;
42814309
List*args=NIL;
42824310

42834311
/* transform element expressions, if any */
@@ -4296,13 +4324,8 @@ transformJsonArrayCtor(ParseState *pstate, JsonArrayCtor *ctor)
42964324
}
42974325
}
42984326

4299-
jsctor=makeNode(JsonCtorExpr);
4300-
jsctor->args=args;
4301-
jsctor->type=JSCTOR_JSON_ARRAY;
4302-
jsctor->returning=transformJsonCtorOutput(pstate,ctor->output,args);
4303-
jsctor->unique= false;
4304-
jsctor->absent_on_null=ctor->absent_on_null;
4305-
jsctor->location=ctor->location;
4327+
returning=transformJsonCtorOutput(pstate,ctor->output,args);
43064328

4307-
returncoerceJsonFuncExpr(pstate, (Node*)jsctor,jsctor->returning, true);
4329+
returnmakeJsonCtorExpr(pstate,JSCTOR_JSON_ARRAY,args,NULL,returning,
4330+
false,ctor->absent_on_null,ctor->location);
43084331
}

‎src/include/nodes/primnodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,7 @@ typedef struct JsonCtorExpr
12661266
JsonCtorTypetype;/* constructor type */
12671267
List*args;
12681268
Expr*func;/* underlying json[b]_xxx() function call */
1269+
Expr*coercion;/* coercion to RETURNING type */
12691270
JsonReturning*returning;/* RETURNING clause */
12701271
boolabsent_on_null;/* ABSENT ON NULL? */
12711272
boolunique;/* WITH UNIQUE KEYS? (JSON_OBJECT[AGG] only) */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp