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

Commit c35370f

Browse files
author
Nikita Glukhov
committed
Refactor jsonpath variables execution
1 parent 99c01d3 commit c35370f

File tree

1 file changed

+69
-40
lines changed

1 file changed

+69
-40
lines changed

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,16 @@ typedef struct JsonBaseObjectInfo
8686
int id;
8787
} JsonBaseObjectInfo;
8888

89+
typedef int (*JsonPathVarCallback) (void *vars, char *varName, int varNameLen,
90+
JsonbValue *val, JsonbValue *baseObject);
91+
8992
/*
9093
* Context of jsonpath execution.
9194
*/
9295
typedef struct JsonPathExecContext
9396
{
94-
Jsonb *vars; /* variables to substitute into jsonpath */
97+
void *vars; /* variables to substitute into jsonpath */
98+
JsonPathVarCallback getVar;
9599
JsonbValue *root; /* for $ evaluation */
96100
JsonbValue *current; /* for @ evaluation */
97101
JsonBaseObjectInfo baseObject; /* "base object" for .keyvalue()
@@ -173,7 +177,8 @@ typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
173177
void *param);
174178
typedef Numeric (*BinaryArithmFunc) (Numeric num1, Numeric num2, bool *error);
175179

176-
static JsonPathExecResult executeJsonPath(JsonPath *path, Jsonb *vars,
180+
static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars,
181+
JsonPathVarCallback getVar,
177182
Jsonb *json, bool throwErrors,
178183
JsonValueList *result, bool useTz);
179184
static JsonPathExecResult executeItem(JsonPathExecContext *cxt,
@@ -225,7 +230,10 @@ static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt,
225230
static void getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
226231
JsonbValue *value);
227232
static void getJsonPathVariable(JsonPathExecContext *cxt,
228-
JsonPathItem *variable, Jsonb *vars, JsonbValue *value);
233+
JsonPathItem *variable, JsonbValue *value);
234+
static int getJsonPathVariableFromJsonb(void *varsJsonb, char *varName,
235+
int varNameLen, JsonbValue *val,
236+
JsonbValue *baseObject);
229237
static int JsonbArraySize(JsonbValue *jb);
230238
static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv,
231239
JsonbValue *rv, void *p);
@@ -283,7 +291,8 @@ jsonb_path_exists_internal(FunctionCallInfo fcinfo, bool tz)
283291
silent = PG_GETARG_BOOL(3);
284292
}
285293

286-
res = executeJsonPath(jp, vars, jb, !silent, NULL, tz);
294+
res = executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
295+
jb, !silent, NULL, tz);
287296

288297
PG_FREE_IF_COPY(jb, 0);
289298
PG_FREE_IF_COPY(jp, 1);
@@ -338,7 +347,8 @@ jsonb_path_match_internal(FunctionCallInfo fcinfo, bool tz)
338347
silent = PG_GETARG_BOOL(3);
339348
}
340349

341-
(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
350+
(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
351+
jb, !silent, &found, tz);
342352

343353
PG_FREE_IF_COPY(jb, 0);
344354
PG_FREE_IF_COPY(jp, 1);
@@ -416,7 +426,8 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz)
416426
vars = PG_GETARG_JSONB_P_COPY(2);
417427
silent = PG_GETARG_BOOL(3);
418428

419-
(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
429+
(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
430+
jb, !silent, &found, tz);
420431

421432
funcctx->user_fctx = JsonValueListGetList(&found);
422433

@@ -463,7 +474,8 @@ jsonb_path_query_array_internal(FunctionCallInfo fcinfo, bool tz)
463474
Jsonb *vars = PG_GETARG_JSONB_P(2);
464475
bool silent = PG_GETARG_BOOL(3);
465476

466-
(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
477+
(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
478+
jb, !silent, &found, tz);
467479

468480
PG_RETURN_JSONB_P(JsonbValueToJsonb(wrapItemsInArray(&found)));
469481
}
@@ -494,7 +506,8 @@ jsonb_path_query_first_internal(FunctionCallInfo fcinfo, bool tz)
494506
Jsonb *vars = PG_GETARG_JSONB_P(2);
495507
bool silent = PG_GETARG_BOOL(3);
496508

497-
(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
509+
(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
510+
jb, !silent, &found, tz);
498511

499512
if (JsonValueListLength(&found) >= 1)
500513
PG_RETURN_JSONB_P(JsonbValueToJsonb(JsonValueListHead(&found)));
@@ -536,8 +549,9 @@ jsonb_path_query_first_tz(PG_FUNCTION_ARGS)
536549
* In other case it tries to find all the satisfied result items.
537550
*/
538551
static JsonPathExecResult
539-
executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors,
540-
JsonValueList *result, bool useTz)
552+
executeJsonPath(JsonPath *path, void *vars, JsonPathVarCallback getVar,
553+
Jsonb *json, bool throwErrors, JsonValueList *result,
554+
bool useTz)
541555
{
542556
JsonPathExecContext cxt;
543557
JsonPathExecResult res;
@@ -549,22 +563,16 @@ executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors,
549563
if (!JsonbExtractScalar(&json->root, &jbv))
550564
JsonbInitBinary(&jbv, json);
551565

552-
if (vars && !JsonContainerIsObject(&vars->root))
553-
{
554-
ereport(ERROR,
555-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
556-
errmsg("\"vars\" argument is not an object"),
557-
errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object.")));
558-
}
559-
560566
cxt.vars = vars;
567+
cxt.getVar = getVar;
561568
cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
562569
cxt.ignoreStructuralErrors = cxt.laxMode;
563570
cxt.root = &jbv;
564571
cxt.current = &jbv;
565572
cxt.baseObject.jbc = NULL;
566573
cxt.baseObject.id = 0;
567-
cxt.lastGeneratedObjectId = vars ? 2 : 1;
574+
/* 1 + number of base objects in vars */
575+
cxt.lastGeneratedObjectId = 1 + getVar(vars, NULL, 0, NULL, NULL);
568576
cxt.innermostArraySize = -1;
569577
cxt.throwErrors = throwErrors;
570578
cxt.useTz = useTz;
@@ -2092,7 +2100,7 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
20922100
&value->val.string.len);
20932101
break;
20942102
case jpiVariable:
2095-
getJsonPathVariable(cxt, item, cxt->vars, value);
2103+
getJsonPathVariable(cxt, item, value);
20962104
return;
20972105
default:
20982106
elog(ERROR, "unexpected jsonpath item type");
@@ -2104,42 +2112,63 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
21042112
*/
21052113
static void
21062114
getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable,
2107-
Jsonb *vars, JsonbValue *value)
2115+
JsonbValue *value)
21082116
{
21092117
char *varName;
21102118
int varNameLength;
2119+
JsonbValue baseObject;
2120+
int baseObjectId;
2121+
2122+
Assert(variable->type == jpiVariable);
2123+
varName = jspGetString(variable, &varNameLength);
2124+
2125+
if (!cxt->vars ||
2126+
(baseObjectId = cxt->getVar(cxt->vars, varName, varNameLength, value,
2127+
&baseObject)) < 0)
2128+
ereport(ERROR,
2129+
(errcode(ERRCODE_UNDEFINED_OBJECT),
2130+
errmsg("could not find jsonpath variable \"%s\"",
2131+
pnstrdup(varName, varNameLength))));
2132+
2133+
if (baseObjectId > 0)
2134+
setBaseObject(cxt, &baseObject, baseObjectId);
2135+
}
2136+
2137+
static int
2138+
getJsonPathVariableFromJsonb(void *varsJsonb, char *varName, int varNameLength,
2139+
JsonbValue *value, JsonbValue *baseObject)
2140+
{
2141+
Jsonb *vars = varsJsonb;
21112142
JsonbValue tmp;
21122143
JsonbValue *v;
21132144

2114-
if (!vars)
2145+
if (!varName)
21152146
{
2116-
value->type = jbvNull;
2117-
return;
2147+
if (vars && !JsonContainerIsObject(&vars->root))
2148+
{
2149+
ereport(ERROR,
2150+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2151+
errmsg("\"vars\" argument is not an object"),
2152+
errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object.")));
2153+
}
2154+
2155+
return vars ? 1 : 0; /* count of base objects */
21182156
}
21192157

2120-
Assert(variable->type == jpiVariable);
2121-
varName = jspGetString(variable, &varNameLength);
21222158
tmp.type = jbvString;
21232159
tmp.val.string.val = varName;
21242160
tmp.val.string.len = varNameLength;
21252161

21262162
v = findJsonbValueFromContainer(&vars->root, JB_FOBJECT, &tmp);
21272163

2128-
if (v)
2129-
{
2130-
*value = *v;
2131-
pfree(v);
2132-
}
2133-
else
2134-
{
2135-
ereport(ERROR,
2136-
(errcode(ERRCODE_UNDEFINED_OBJECT),
2137-
errmsg("could not find jsonpath variable \"%s\"",
2138-
pnstrdup(varName, varNameLength))));
2139-
}
2164+
if (!v)
2165+
return -1;
2166+
2167+
*value = *v;
2168+
pfree(v);
21402169

2141-
JsonbInitBinary(&tmp, vars);
2142-
setBaseObject(cxt, &tmp, 1);
2170+
JsonbInitBinary(baseObject, vars);
2171+
return 1;
21432172
}
21442173

21452174
/**************** Support functions for JsonPath execution *****************/

0 commit comments

Comments
 (0)