diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index 8d83b2edb35..145a5e75f6b 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -224,8 +224,9 @@ static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonValueList *found, JsonPathBool res); static void getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, JsonbValue *value); -static void getJsonPathVariable(JsonPathExecContext *cxt, - JsonPathItem *variable, Jsonb *vars, JsonbValue *value); +static JsonPathExecResult getJsonPathVariable(JsonPathExecContext *cxt, + JsonPathItem *variable, + JsonbValue *value); static int JsonbArraySize(JsonbValue *jb); static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv, JsonbValue *rv, void *p); @@ -952,7 +953,6 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, case jpiBool: case jpiNumeric: case jpiString: - case jpiVariable: { JsonbValue vbuf; JsonbValue *v; @@ -975,6 +975,28 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, } break; + case jpiVariable: + { + JsonbValue vbuf; + JsonbValue *v; + bool hasNext = jspGetNext(jsp, &elem); + + v = hasNext ? &vbuf : palloc(sizeof(*v)); + + baseObject = cxt->baseObject; + res = getJsonPathVariable(cxt, jsp, v); + + if (res == jperOk) + { + res = executeNextItem(cxt, jsp, &elem, + v, found, hasNext); + if (jspHasNext(jsp) || !found) + pfree(v); + } + cxt->baseObject = baseObject; + } + break; + case jpiType: { JsonbValue *jbv = palloc(sizeof(*jbv)); @@ -2092,9 +2114,6 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, value->val.string.val = jspGetString(item, &value->val.string.len); break; - case jpiVariable: - getJsonPathVariable(cxt, item, cxt->vars, value); - return; default: elog(ERROR, "unexpected jsonpath item type"); } @@ -2103,19 +2122,20 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, /* * Get the value of variable passed to jsonpath executor */ -static void +static JsonPathExecResult getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable, - Jsonb *vars, JsonbValue *value) + JsonbValue *value) { char *varName; int varNameLength; JsonbValue tmp; JsonbValue *v; + Jsonb *vars = cxt->vars; + JsonPathExecResult res; if (!vars) { - value->type = jbvNull; - return; + return jperNotFound; } Assert(variable->type == jpiVariable); @@ -2130,17 +2150,26 @@ getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable, { *value = *v; pfree(v); + res = jperOk; } - else + else if (!jspIgnoreStructuralErrors(cxt)) { + if (!jspThrowErrors(cxt)) + res = jperError; ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find jsonpath variable \"%s\"", pnstrdup(varName, varNameLength)))); } + else + { + res = jperNotFound; + } JsonbInitBinary(&tmp, vars); setBaseObject(cxt, &tmp, 1); + + return res; } /**************** Support functions for JsonPath execution *****************/