Skip to content

Commit a4800a8

Browse files
author
Nikita Glukhov
committed
Remove json[b]_build_object_ext()
1 parent 76b4760 commit a4800a8

File tree

17 files changed

+142
-108
lines changed

17 files changed

+142
-108
lines changed

src/backend/executor/execExpr.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,8 +2131,45 @@ ExecInitExprRec(Expr *node, ExprState *state,
21312131
}
21322132

21332133
case T_JsonCtorExpr:
2134-
ExecInitExprRec(&((JsonCtorExpr *) node)->func->xpr, state, resv,
2135-
resnull);
2134+
{
2135+
JsonCtorExpr *ctor = (JsonCtorExpr *) node;
2136+
List *args = ctor->args;
2137+
ListCell *lc;
2138+
int nargs = list_length(args);
2139+
int argno = 0;
2140+
2141+
scratch.opcode = EEOP_JSON_CTOR;
2142+
scratch.d.json_ctor.ctor = ctor;
2143+
scratch.d.json_ctor.arg_values = palloc(sizeof(Datum) * nargs);
2144+
scratch.d.json_ctor.arg_nulls = palloc(sizeof(bool) * nargs);
2145+
scratch.d.json_ctor.arg_types = palloc(sizeof(Oid) * nargs);
2146+
scratch.d.json_ctor.nargs = nargs;
2147+
2148+
foreach(lc, args)
2149+
{
2150+
Expr *arg = (Expr *) lfirst(lc);
2151+
2152+
scratch.d.json_ctor.arg_types[argno] = exprType((Node *) arg);
2153+
2154+
if (IsA(arg, Const))
2155+
{
2156+
/* Don't evaluate const arguments every round */
2157+
Const *con = (Const *) arg;
2158+
2159+
scratch.d.json_ctor.arg_values[argno] = con->constvalue;
2160+
scratch.d.json_ctor.arg_nulls[argno] = con->constisnull;
2161+
}
2162+
else
2163+
{
2164+
ExecInitExprRec(arg, state,
2165+
&scratch.d.json_ctor.arg_values[argno],
2166+
&scratch.d.json_ctor.arg_nulls[argno]);
2167+
}
2168+
argno++;
2169+
}
2170+
2171+
ExprEvalPushStep(state, &scratch);
2172+
}
21362173
break;
21372174

21382175
default:

src/backend/executor/execExprInterp.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
#include "utils/date.h"
7272
#include "utils/datum.h"
7373
#include "utils/expandedrecord.h"
74+
#include "utils/json.h"
75+
#include "utils/jsonb.h"
7476
#include "utils/lsyscache.h"
7577
#include "utils/memutils.h"
7678
#include "utils/timestamp.h"
@@ -432,6 +434,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
432434
&&CASE_EEOP_WINDOW_FUNC,
433435
&&CASE_EEOP_SUBPLAN,
434436
&&CASE_EEOP_ALTERNATIVE_SUBPLAN,
437+
&&CASE_EEOP_JSON_CTOR,
435438
&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
436439
&&CASE_EEOP_AGG_DESERIALIZE,
437440
&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
@@ -1544,6 +1547,26 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
15441547
EEO_NEXT();
15451548
}
15461549

1550+
EEO_CASE(EEOP_JSON_CTOR)
1551+
{
1552+
Datum res;
1553+
bool is_jsonb = op->d.json_ctor.ctor->returning->format->format == JS_FORMAT_JSONB;
1554+
1555+
res = (is_jsonb ?
1556+
jsonb_build_object_worker :
1557+
json_build_object_worker)(op->d.json_ctor.nargs,
1558+
op->d.json_ctor.arg_values,
1559+
op->d.json_ctor.arg_nulls,
1560+
op->d.json_ctor.arg_types,
1561+
op->d.json_ctor.ctor->absent_on_null,
1562+
op->d.json_ctor.ctor->unique);
1563+
1564+
*op->resvalue = res;
1565+
*op->resnull = false;
1566+
1567+
EEO_NEXT();
1568+
}
1569+
15471570
/* evaluate a strict aggregate deserialization function */
15481571
EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE)
15491572
{

src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,11 +2302,13 @@ _copyJsonCtorExpr(const JsonCtorExpr *from)
23022302
{
23032303
JsonCtorExpr *newnode = makeNode(JsonCtorExpr);
23042304

2305+
COPY_NODE_FIELD(args);
23052306
COPY_NODE_FIELD(func);
23062307
COPY_SCALAR_FIELD(type);
23072308
COPY_NODE_FIELD(returning);
23082309
COPY_SCALAR_FIELD(absent_on_null);
23092310
COPY_SCALAR_FIELD(unique);
2311+
COPY_LOCATION_FIELD(location);
23102312

23112313
return newnode;
23122314
}

src/backend/nodes/equalfuncs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,11 +851,13 @@ _equalJsonValueExpr(const JsonValueExpr *a, const JsonValueExpr *b)
851851
static bool
852852
_equalJsonCtorExpr(const JsonCtorExpr *a, const JsonCtorExpr *b)
853853
{
854+
COMPARE_NODE_FIELD(args);
854855
COMPARE_NODE_FIELD(func);
855856
COMPARE_SCALAR_FIELD(type);
856857
COMPARE_NODE_FIELD(returning);
857858
COMPARE_SCALAR_FIELD(absent_on_null);
858859
COMPARE_SCALAR_FIELD(unique);
860+
COMPARE_LOCATION_FIELD(location);
859861

860862
return true;
861863
}

src/backend/nodes/nodeFuncs.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ exprType(const Node *expr)
266266
}
267267
break;
268268
case T_JsonCtorExpr:
269-
type = exprType((Node *) ((const JsonCtorExpr *) expr)->func);
269+
type = ((const JsonCtorExpr *) expr)->returning->format->format == JS_FORMAT_JSONB ? JSONBOID : JSONOID;
270270
break;
271271
default:
272272
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -504,7 +504,7 @@ exprTypmod(const Node *expr)
504504
case T_JsonValueExpr:
505505
return exprTypmod((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
506506
case T_JsonCtorExpr:
507-
return exprTypmod((Node *) ((const JsonCtorExpr *) expr)->func);
507+
return -1; /* ((const JsonCtorExpr *) expr)->returning->typmod; */
508508
default:
509509
break;
510510
}
@@ -924,7 +924,8 @@ exprCollation(const Node *expr)
924924
coll = exprCollation((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
925925
break;
926926
case T_JsonCtorExpr:
927-
coll = exprCollation((Node *) ((const JsonCtorExpr *) expr)->func);
927+
/* coll = exprCollation((Node *) ((const JsonCtorExpr *) expr)->func); */
928+
coll = InvalidOid; /* keep compiler quiet */
928929
break;
929930
default:
930931
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -1134,8 +1135,8 @@ exprSetCollation(Node *expr, Oid collation)
11341135
collation);
11351136
break;
11361137
case T_JsonCtorExpr:
1137-
exprSetCollation((Node *) ((const JsonCtorExpr *) expr)->func,
1138-
collation);
1138+
/* exprSetCollation((Node *) ((const JsonCtorExpr *) expr)->func, collation); */
1139+
Assert(!OidIsValid(collation)); /* result is always an json[b] type */
11391140
break;
11401141
default:
11411142
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -1581,7 +1582,7 @@ exprLocation(const Node *expr)
15811582
loc = exprLocation((Node *) ((const JsonValueExpr *) expr)->raw_expr);
15821583
break;
15831584
case T_JsonCtorExpr:
1584-
loc = exprLocation((Node *) ((const JsonCtorExpr *) expr)->func);
1585+
loc = ((const JsonCtorExpr *) expr)->location;
15851586
break;
15861587
default:
15871588
/* for any other node type it's just unknown... */
@@ -2293,7 +2294,9 @@ expression_tree_walker(Node *node,
22932294
case T_JsonCtorExpr:
22942295
{
22952296
JsonCtorExpr *ctor = (JsonCtorExpr *) node;
2296-
2297+
2298+
if (walker(ctor->args, context))
2299+
return true;
22972300
if (walker(ctor->func, context))
22982301
return true;
22992302
}
@@ -3250,6 +3253,7 @@ expression_tree_mutator(Node *node,
32503253
JsonCtorExpr *newnode;
32513254

32523255
FLATCOPY(newnode, jve, JsonCtorExpr);
3256+
MUTATE(newnode->args, jve->args, List *);
32533257
MUTATE(newnode->func, jve->func, FuncExpr *);
32543258
MUTATE(newnode->returning, jve->returning, JsonReturning *);
32553259

@@ -3968,6 +3972,8 @@ raw_expression_tree_walker(Node *node,
39683972
{
39693973
JsonCtorExpr *ctor = (JsonCtorExpr *) node;
39703974

3975+
if (walker(ctor->args, context))
3976+
return true;
39713977
if (walker(ctor->func, context))
39723978
return true;
39733979
if (walker(ctor->returning, context))

src/backend/nodes/outfuncs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,11 +1744,13 @@ _outJsonCtorExpr(StringInfo str, const JsonCtorExpr *node)
17441744
{
17451745
WRITE_NODE_TYPE("JSONCTOREXPR");
17461746

1747+
WRITE_NODE_FIELD(args);
17471748
WRITE_NODE_FIELD(func);
17481749
WRITE_INT_FIELD(type);
17491750
WRITE_NODE_FIELD(returning);
17501751
WRITE_BOOL_FIELD(unique);
17511752
WRITE_BOOL_FIELD(absent_on_null);
1753+
WRITE_LOCATION_FIELD(location);
17521754
}
17531755

17541756
/*****************************************************************************

src/backend/nodes/readfuncs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,11 +1396,13 @@ _readJsonCtorExpr(void)
13961396
{
13971397
READ_LOCALS(JsonCtorExpr);
13981398

1399+
READ_NODE_FIELD(args);
13991400
READ_NODE_FIELD(func);
14001401
READ_INT_FIELD(type);
14011402
READ_NODE_FIELD(returning);
14021403
READ_BOOL_FIELD(unique);
14031404
READ_BOOL_FIELD(absent_on_null);
1405+
READ_LOCATION_FIELD(location);
14041406

14051407
READ_DONE();
14061408
}

src/backend/parser/parse_expr.c

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3963,22 +3963,14 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr,
39633963
static Node *
39643964
transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39653965
{
3966-
JsonReturning *returning;
39673966
JsonCtorExpr *jsctor;
3968-
FuncExpr *fexpr;
39693967
List *args = NIL;
3970-
Oid funcid;
3971-
Oid funcrettype;
39723968

39733969
/* transform key-value pairs, if any */
39743970
if (ctor->exprs)
39753971
{
39763972
ListCell *lc;
39773973

3978-
/* append the first two arguments */
3979-
args = lappend(args, makeBoolConst(ctor->absent_on_null, false));
3980-
args = lappend(args, makeBoolConst(ctor->unique, false));
3981-
39823974
/* transform and append key-value arguments */
39833975
foreach(lc, ctor->exprs)
39843976
{
@@ -3992,29 +3984,14 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39923984
}
39933985
}
39943986

3995-
returning = transformJsonCtorOutput(pstate, ctor->output, args);
3996-
3997-
if (returning->format->format == JS_FORMAT_JSONB)
3998-
{
3999-
funcid = args ? F_JSONB_BUILD_OBJECT_EXT : F_JSONB_BUILD_OBJECT_NOARGS;
4000-
funcrettype = JSONBOID;
4001-
}
4002-
else
4003-
{
4004-
funcid = args ? F_JSON_BUILD_OBJECT_EXT : F_JSON_BUILD_OBJECT_NOARGS;
4005-
funcrettype = JSONOID;
4006-
}
4007-
4008-
fexpr = makeFuncExpr(funcid, funcrettype, args,
4009-
InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL);
4010-
fexpr->location = ctor->location;
4011-
40123987
jsctor = makeNode(JsonCtorExpr);
4013-
jsctor->func = fexpr;
3988+
jsctor->args = args;
3989+
jsctor->func = NULL;
40143990
jsctor->type = JSCTOR_JSON_OBJECT;
4015-
jsctor->returning = returning;
3991+
jsctor->returning = transformJsonCtorOutput(pstate, ctor->output, args);
40163992
jsctor->unique = ctor->unique;
40173993
jsctor->absent_on_null = ctor->absent_on_null;
3994+
jsctor->location = ctor->location;
40183995

4019-
return coerceJsonFuncExpr(pstate, (Node *) jsctor, returning, true);
3996+
return coerceJsonFuncExpr(pstate, (Node *) jsctor, jsctor->returning, true);
40203997
}

src/backend/utils/adt/json.c

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,26 +1121,15 @@ catenate_stringinfo_string(StringInfo buffer, const char *addon)
11211121
return result;
11221122
}
11231123

1124-
static Datum
1125-
json_build_object_worker(FunctionCallInfo fcinfo, int first_vararg,
1124+
Datum
1125+
json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
11261126
bool absent_on_null, bool unique_keys)
11271127
{
1128-
int nargs = PG_NARGS();
11291128
int i;
11301129
const char *sep = "";
11311130
StringInfo result;
1132-
Datum *args;
1133-
bool *nulls;
1134-
Oid *types;
11351131
JsonUniqueBuilderState unique_check;
11361132

1137-
/* fetch argument values to build the object */
1138-
nargs = extract_variadic_args(fcinfo, first_vararg, false,
1139-
&args, &types, &nulls);
1140-
1141-
if (nargs < 0)
1142-
PG_RETURN_NULL();
1143-
11441133
if (nargs % 2 != 0)
11451134
ereport(ERROR,
11461135
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1184,7 +1173,7 @@ json_build_object_worker(FunctionCallInfo fcinfo, int first_vararg,
11841173
if (nulls[i])
11851174
ereport(ERROR,
11861175
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1187-
errmsg("argument %d cannot be null", first_vararg + i + 1),
1176+
errmsg("argument %d cannot be null", i + 1),
11881177
errhint("Object keys should be text.")));
11891178

11901179
/* save key offset before key appending */
@@ -1217,7 +1206,7 @@ json_build_object_worker(FunctionCallInfo fcinfo, int first_vararg,
12171206
if (unique_keys)
12181207
json_unique_builder_free(&unique_check);
12191208

1220-
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
1209+
return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
12211210
}
12221211

12231212
/*
@@ -1226,17 +1215,17 @@ json_build_object_worker(FunctionCallInfo fcinfo, int first_vararg,
12261215
Datum
12271216
json_build_object(PG_FUNCTION_ARGS)
12281217
{
1229-
return json_build_object_worker(fcinfo, 0, false, false);
1230-
}
1218+
Datum *args;
1219+
bool *nulls;
1220+
Oid *types;
1221+
/* build argument values to build the object */
1222+
int nargs = extract_variadic_args(fcinfo, 0, true,
1223+
&args, &types, &nulls);
12311224

1232-
/*
1233-
* SQL function json_build_object_ext(absent_on_null bool, unique bool, variadic "any")
1234-
*/
1235-
Datum
1236-
json_build_object_ext(PG_FUNCTION_ARGS)
1237-
{
1238-
return json_build_object_worker(fcinfo, 2,
1239-
PG_GETARG_BOOL(0), PG_GETARG_BOOL(1));
1225+
if (nargs < 0)
1226+
PG_RETURN_NULL();
1227+
1228+
PG_RETURN_DATUM(json_build_object_worker(nargs, args, nulls, types, false, false));
12401229
}
12411230

12421231
/*

0 commit comments

Comments
 (0)