From 003bfccffc69824e0fb947d11f3f75a7b70fefb4 Mon Sep 17 00:00:00 2001 From: Nikita Glukhov Date: Mon, 29 Aug 2022 22:41:08 +0300 Subject: [PATCH v9 8/9] Remove subsidary ExprStates in SQL/JSON execution --- src/backend/executor/execExpr.c | 88 ++++++++--- src/backend/executor/execExprInterp.c | 206 ++++++++++++-------------- src/backend/jit/llvm/llvmjit_expr.c | 70 ++++++++- src/backend/jit/llvm/llvmjit_types.c | 1 + src/backend/utils/adt/jsonpath_exec.c | 79 +++++++++- src/include/executor/execExpr.h | 20 ++- src/include/utils/jsonpath.h | 4 - 7 files changed, 317 insertions(+), 151 deletions(-) diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index f50e0d703f8..68227ebee21 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -4159,9 +4159,16 @@ static void ExecInitJsonExpr(JsonExpr *jexpr, ExprState *state, ExprEvalStep *scratch, Datum *resv, bool *resnull) { + ExprEvalStep *step; JsonExprState *jsestate; ListCell *argexprlc; ListCell *argnamelc; + int skip_step_off; + int execpath_step_off; + int done_step_off; + int default_on_empty_step_off = -1; + int default_on_error_step_off = -1; + int default_on_empty_jump_off = -1; /* JSON_TABLE preudo-function returns context item as a result */ if (jexpr->op == JSON_TABLE_OP) @@ -4174,9 +4181,6 @@ ExecInitJsonExpr(JsonExpr *jexpr, ExprState *state, ExprEvalStep *scratch, jsestate = palloc0(sizeof(JsonExprState)); jsestate->jsexpr = jexpr; - scratch->opcode = EEOP_JSONEXPR; - scratch->d.jsonexpr.jsestate = jsestate; - ExecInitExprRec((Expr *) jexpr->formatted_expr, state, &jsestate->formatted_expr.value, &jsestate->formatted_expr.isnull); @@ -4185,15 +4189,12 @@ ExecInitJsonExpr(JsonExpr *jexpr, ExprState *state, ExprEvalStep *scratch, &jsestate->pathspec.value, &jsestate->pathspec.isnull); - if (jexpr->on_empty) - jsestate->default_on_empty = - ExecInitExpr((Expr *) jexpr->on_empty->default_expr, - state->parent); - - jsestate->default_on_error = - ExecInitExpr((Expr *) jexpr->on_error->default_expr, - state->parent); + scratch->opcode = EEOP_JSONEXPR_SKIP; + scratch->d.jsonexpr_skip.jsestate = jsestate; + skip_step_off = state->steps_len; + ExprEvalPushStep(state, scratch); + /* PASSING args. */ jsestate->args = NIL; forboth(argexprlc, jexpr->passing_values, @@ -4206,16 +4207,69 @@ ExecInitJsonExpr(JsonExpr *jexpr, ExprState *state, ExprEvalStep *scratch, var->name = pstrdup(argname->sval); var->typid = exprType((Node *) argexpr); var->typmod = exprTypmod((Node *) argexpr); - var->estate = ExecInitExpr(argexpr, state->parent); + + /* + * A separate ExprState is not necessary for these expressions + * when being evaluated for a JsonExpr, like in this case, + * because they will evaluated as the steps of the JsonExpr. + */ + var->estate = NULL; var->econtext = NULL; var->mcxt = NULL; - var->evaluated = false; - var->value = (Datum) 0; - var->isnull = true; - jsestate->args = - lappend(jsestate->args, var); + /* + * Mark these as always evaluated because they must have been + * evaluated before JSON path evaluation begins, because we + * haven't pushed the step for the latter yet. + */ + var->evaluated = true; + + ExecInitExprRec((Expr *) argexpr, state, &var->value, &var->isnull); + + jsestate->args = lappend(jsestate->args, var); } + /* Step for the actual JSON path evaluation. */ + scratch->opcode = EEOP_JSONEXPR_PATH; + scratch->d.jsonexpr.jsestate = jsestate; + execpath_step_off = state->steps_len; ExprEvalPushStep(state, scratch); + + if (jexpr->on_empty && jexpr->on_empty->default_expr) + { + default_on_empty_step_off = state->steps_len; + ExecInitExprRec((Expr *) jexpr->on_empty->default_expr, state, resv, resnull); + + scratch->opcode = EEOP_JUMP; + default_on_empty_jump_off = state->steps_len; + ExprEvalPushStep(state, scratch); + } + + if (jexpr->on_error->default_expr) + { + default_on_error_step_off = state->steps_len; + ExecInitExprRec((Expr *) jexpr->on_error->default_expr, state, resv, resnull); + } + + /* Adjust jump locations */ + done_step_off = state->steps_len; + + /* EEOP_JSONEXPR_SKIP */ + step = &state->steps[skip_step_off]; + step->d.jsonexpr_skip.jump_done = done_step_off; + + /* EEOP_JSONEXPR_PATH */ + step = &state->steps[execpath_step_off]; + step->d.jsonexpr.jump_done = done_step_off; + step->d.jsonexpr.jump_default_on_empty = + default_on_empty_step_off > 0 ? default_on_empty_step_off : done_step_off; + step->d.jsonexpr.jump_default_on_error = + default_on_error_step_off > 0 ? default_on_error_step_off : done_step_off; + + /* EEOP_JUMP */ + if (default_on_empty_jump_off > 0) + { + step = &state->steps[default_on_empty_jump_off]; + step->d.jump.jumpdone = done_step_off; + } } diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 45c648817ba..d39223e0d15 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -491,7 +491,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_SUBPLAN, &&CASE_EEOP_JSON_CONSTRUCTOR, &&CASE_EEOP_IS_JSON, - &&CASE_EEOP_JSONEXPR, + &&CASE_EEOP_JSONEXPR_SKIP, + &&CASE_EEOP_JSONEXPR_PATH, &&CASE_EEOP_AGG_STRICT_DESERIALIZE, &&CASE_EEOP_AGG_DESERIALIZE, &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS, @@ -1842,11 +1843,26 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } - EEO_CASE(EEOP_JSONEXPR) + EEO_CASE(EEOP_JSONEXPR_SKIP) { /* too complex for an inline implementation */ - ExecEvalJsonExpr(state, op, econtext); - EEO_NEXT(); + if (ExecEvalJsonExprSkip(state, op)) + EEO_JUMP(op->d.jsonexpr_skip.jump_done); + else + EEO_NEXT(); + } + + EEO_CASE(EEOP_JSONEXPR_PATH) + { + /* too complex for an inline implementation */ + int res = ExecEvalJsonExpr(state, op); + + if (res == 0) + EEO_JUMP(op->d.jsonexpr.jump_default_on_empty); + else if (res == -1) + EEO_JUMP(op->d.jsonexpr.jump_default_on_error); + else + EEO_JUMP(op->d.jsonexpr.jump_done); } EEO_CASE(EEOP_LAST) @@ -4701,59 +4717,6 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op, *op->resnull = isnull; } -/* - * Evaluate a JSON path variable caching computed value. - */ -int -EvalJsonPathVar(void *cxt, char *varName, int varNameLen, - JsonbValue *val, JsonbValue *baseObject) -{ - JsonPathVariableEvalContext *var = NULL; - List *vars = cxt; - ListCell *lc; - int id = 1; - - if (!varName) - return list_length(vars); - - foreach(lc, vars) - { - var = lfirst(lc); - - if (!strncmp(var->name, varName, varNameLen)) - break; - - var = NULL; - id++; - } - - if (!var) - return -1; - - if (!var->evaluated) - { - MemoryContext oldcxt = var->mcxt ? - MemoryContextSwitchTo(var->mcxt) : NULL; - - var->value = ExecEvalExpr(var->estate, var->econtext, &var->isnull); - var->evaluated = true; - - if (oldcxt) - MemoryContextSwitchTo(oldcxt); - } - - if (var->isnull) - { - val->type = jbvNull; - return 0; - } - - JsonItemFromDatum(var->value, var->typid, var->typmod, val); - - *baseObject = *val; - return id; -} - /* * Check whether we need to override default coercion in * JSON_QUERY(OMIT QUOTES) case. @@ -5210,9 +5173,8 @@ ExecJsonValueCoercion(JsonbValue *item, Oid typid, int32 typmod, * type. */ static Datum -ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior, - ExprState *default_estate, - Oid ret_typid, int32 ret_typmod, bool *is_null) +ExecEvalJsonBehavior(JsonBehavior *behavior, Oid ret_typid, + int32 ret_typmod, bool *is_null) { *is_null = false; @@ -5262,12 +5224,8 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior, return (Datum) 0; case JSON_BEHAVIOR_DEFAULT: - /* - * Execute DEFAULT expression. - * Coercion is not needed here, because expression is - * already coerced to the target type by the parser. - */ - return ExecEvalExpr(default_estate, econtext, is_null); + Assert(0); + return (Datum) 0; /* must be handled by caller */ default: elog(ERROR, "unrecognized SQL/JSON behavior %d", behavior->btype); @@ -5276,28 +5234,27 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior, } static Datum -ExecEvalJsonExprInternal(ExprState *state, - JsonExprState *jsestate, ExprContext *econtext, +ExecEvalJsonExprInternal(ExprState *state, JsonExprState *jsestate, JsonPath *path, Datum item, bool *resnull, - bool *error) + bool *empty, bool *error) { JsonExpr *jexpr = jsestate->jsexpr; - bool empty = false; Datum res = (Datum) 0; Oid ret_typid = jexpr->returning->typid; int32 ret_typmod = jexpr->returning->typmod; *resnull = true; + *empty = false; switch (jexpr->op) { case JSON_QUERY_OP: - res = JsonPathQuery(item, path, jexpr->wrapper, &empty, error, + res = JsonPathQuery(item, path, jexpr->wrapper, empty, error, jsestate->args); if (error && *error) return (Datum) 0; - if (empty) + if (*empty) break; *resnull = !DatumGetPointer(res); @@ -5364,13 +5321,13 @@ ExecEvalJsonExprInternal(ExprState *state, case JSON_VALUE_OP: { - JsonbValue *jbv = JsonPathValue(item, path, &empty, error, + JsonbValue *jbv = JsonPathValue(item, path, empty, error, jsestate->args); if (error && *error) return (Datum) 0; - if (empty) + if (*empty) break; if (!jbv) @@ -5408,78 +5365,101 @@ ExecEvalJsonExprInternal(ExprState *state, return (Datum) 0; } - Assert(empty); - Assert(jexpr->on_empty); /* it is not JSON_EXISTS */ + Assert(*empty); - if (jexpr->on_empty->btype == JSON_BEHAVIOR_ERROR) - { - if (error) - { - *error = true; - return (Datum) 0; - } + return (Datum) 0; +} - ereport(ERROR, - (errcode(ERRCODE_NO_SQL_JSON_ITEM), - errmsg("no SQL/JSON item"))); +bool +ExecEvalJsonExprSkip(ExprState *state, ExprEvalStep *op) +{ + JsonExprState *jsestate = op->d.jsonexpr_skip.jsestate; + + /* + * Skip if either of the input expressions has turned out to be + * NULL, though do execute domain checks for NULLs, which are + * handled by the coercion step. + */ + if (jsestate->formatted_expr.isnull || + jsestate->pathspec.isnull) + { + *op->resvalue = (Datum) 0; + *op->resnull = true; + return true; } - /* Execute ON EMPTY behavior */ - return ExecEvalJsonBehavior(econtext, jexpr->on_empty, - jsestate->default_on_empty, - ret_typid, ret_typmod, resnull); + /* + * Go evaluate the PASSING args if any and subsequently JSON path + * itself. + */ + return false; } /* ---------------------------------------------------------------- * ExecEvalJsonExpr * ---------------------------------------------------------------- + * + * Return value: + * 1 - Ok, jump to the end of JsonExpr + * 0 - empty result, need to execute DEFAULT ON EMPTY expression + * -1 - error occured, need to execute DEFAULT ON ERROR expression */ -void -ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext) +int +ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op) { JsonExprState *jsestate = op->d.jsonexpr.jsestate; JsonExpr *jexpr = jsestate->jsexpr; Datum item; Datum res; JsonPath *path; - ListCell *lc; + bool empty = false; bool error = false; - bool throwErrors = jexpr->on_error->btype == JSON_BEHAVIOR_ERROR; - - if (jsestate->formatted_expr.isnull || jsestate->pathspec.isnull) - { - *op->resnull = true; - *op->resvalue = (Datum) 0; - return; - } + bool throw_errors = jexpr->on_error->btype == JSON_BEHAVIOR_ERROR; item = jsestate->formatted_expr.value; path = DatumGetJsonPathP(jsestate->pathspec.value); - /* reset JSON path variable contexts */ - foreach(lc, jsestate->args) + res = ExecEvalJsonExprInternal(state, jsestate, path, item, + op->resnull, &empty, + throw_errors ? NULL : &error); + + if (empty && !error) { - JsonPathVariableEvalContext *var = lfirst(lc); + Assert(jexpr->on_empty); /* it is not JSON_EXISTS */ - var->econtext = econtext; - var->evaluated = false; - } + if (jexpr->on_empty->btype == JSON_BEHAVIOR_ERROR) + { + if (throw_errors) + ereport(ERROR, + (errcode(ERRCODE_NO_SQL_JSON_ITEM), + errmsg("no SQL/JSON item"))); - res = ExecEvalJsonExprInternal(state, jsestate, econtext, - path, item, op->resnull, - throwErrors ? NULL : &error); + error = true; /* fallback to error behavior */ + } + else if (jexpr->on_empty->btype == JSON_BEHAVIOR_DEFAULT) + return 0; /* jump to ON EMPTY expression */ + else + /* Execute ON EMPTY behavior */ + res = ExecEvalJsonBehavior(jexpr->on_empty, + jexpr->returning->typid, + jexpr->returning->typmod, + op->resnull); + } if (error) { - Assert(!throwErrors); + Assert(!throw_errors); + + if (jexpr->on_error->btype == JSON_BEHAVIOR_DEFAULT) + return -1; /* jump to ON ERROR expression */ /* Execute ON ERROR behavior */ - res = ExecEvalJsonBehavior(econtext, jexpr->on_error, - jsestate->default_on_error, + res = ExecEvalJsonBehavior(jexpr->on_error, jexpr->returning->typid, jexpr->returning->typmod, op->resnull); } *op->resvalue = res; + return 1; /* jump to the end of expression */ } diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index fd72630f5e6..7681a77cd63 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -2407,11 +2407,71 @@ llvm_compile_expr(ExprState *state) LLVMBuildBr(b, opblocks[opno + 1]); break; - case EEOP_JSONEXPR: - build_EvalXFunc(b, mod, "ExecEvalJsonExpr", - v_state, op, v_econtext); - LLVMBuildBr(b, opblocks[opno + 1]); - break; + case EEOP_JSONEXPR_SKIP: + { + LLVMValueRef v_ret; + + /* + * Call ExecEvalJsonExprSkip() to decide if JSON + * path evaluation can be skipped. This returns + * boolean "skip" flag. + */ + v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExprSkip", + v_state, op); + v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, ""); + + /* + * Jump to coercion step if true was returned, + * which signifies skipping of JSON path evaluation, + * else to the next step which must point to the + * steps to evaluate PASSING args, if any, or to + * the JSON path evaluation. + */ + LLVMBuildCondBr(b, + LLVMBuildICmp(b, + LLVMIntEQ, + v_ret, + l_sbool_const(0), + ""), + opblocks[opno + 1], + opblocks[op->d.jsonexpr_skip.jump_done]); + break; + } + + case EEOP_JSONEXPR_PATH: + { + LLVMValueRef v_ret; + LLVMValueRef v_switch; + int n_jumps = 0; + + v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExpr", + v_state, op); + + if (op->d.jsonexpr.jump_default_on_empty != op->d.jsonexpr.jump_done) + n_jumps++; + + if (op->d.jsonexpr.jump_default_on_error != op->d.jsonexpr.jump_done) + n_jumps++; + + if (!n_jumps) + LLVMBuildBr(b, opblocks[op->d.jsonexpr.jump_done]); + else + { + v_switch = LLVMBuildSwitch(b, v_ret, + opblocks[op->d.jsonexpr.jump_done], + n_jumps); + + if (op->d.jsonexpr.jump_default_on_empty != op->d.jsonexpr.jump_done) + LLVMAddCase(v_switch, l_int32_const(0), + opblocks[op->d.jsonexpr.jump_default_on_empty]); + + if (op->d.jsonexpr.jump_default_on_error != op->d.jsonexpr.jump_done) + LLVMAddCase(v_switch, l_int32_const(-1), + opblocks[op->d.jsonexpr.jump_default_on_error]); + } + + break; + } case EEOP_LAST: Assert(false); diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index 37fe64654b6..b9148ce515c 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -136,6 +136,7 @@ void *referenced_functions[] = ExecEvalJsonConstructor, ExecEvalJsonIsPredicate, ExecEvalJsonExpr, + ExecEvalJsonExprSkip, MakeExpandedObjectReadOnlyInternal, slot_getmissingattrs, slot_getsomeattrs_int, diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index 5b6a4805721..b8949789710 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -286,6 +286,8 @@ static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonValueList *found, JsonPathBool res); static void getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, JsonbValue *value); +static int evalJsonPathVariable(void *cxt, char *varName, int varNameLen, + JsonbValue *val, JsonbValue *baseObject); static void getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable, JsonbValue *value); static int getJsonPathVariableFromJsonb(void *varsJsonb, char *varName, @@ -2172,6 +2174,71 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, } } +/* + * Evaluate a JSON path variable caching computed value. + */ +static int +evalJsonPathVariable(void *cxt, char *varName, int varNameLen, + JsonbValue *val, JsonbValue *baseObject) +{ + JsonPathVariableEvalContext *var = NULL; + List *vars = cxt; + ListCell *lc; + int id = 1; + + if (!varName) + return list_length(vars); + + foreach(lc, vars) + { + var = lfirst(lc); + + if (!strncmp(var->name, varName, varNameLen)) + break; + + var = NULL; + id++; + } + + if (!var) + return -1; + + /* + * When belonging to a JsonExpr, path variables are computed with the + * JsonExpr's ExprState (var->estate is NULL), so don't need to be computed + * here. In some other cases, such as when the path variables belonging + * to a JsonTable instead, those variables must be evaluated on their own, + * without the enclosing JsonExpr itself needing to be evaluated, so must + * be handled here. + */ + if (!var->estate) + { + Assert(var->evaluated); + } + else if (!var->evaluated) + { + MemoryContext oldcxt = var->mcxt ? MemoryContextSwitchTo(var->mcxt) : NULL; + + Assert(var->econtext); + var->value = ExecEvalExpr(var->estate, var->econtext, &var->isnull); + var->evaluated = true; + + if (oldcxt) + MemoryContextSwitchTo(oldcxt); + } + + if (var->isnull) + { + val->type = jbvNull; + return 0; + } + + JsonItemFromDatum(var->value, var->typid, var->typmod, val); + + *baseObject = *val; + return id; +} + /* * Get the value of variable passed to jsonpath executor */ @@ -2903,7 +2970,7 @@ compareDatetime(Datum val1, Oid typid1, Datum val2, Oid typid2, bool JsonPathExists(Datum jb, JsonPath *jp, List *vars, bool *error) { - JsonPathExecResult res = executeJsonPath(jp, vars, EvalJsonPathVar, + JsonPathExecResult res = executeJsonPath(jp, vars, evalJsonPathVariable, DatumGetJsonbP(jb), !error, NULL, true); @@ -2925,8 +2992,8 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, JsonPathExecResult res PG_USED_FOR_ASSERTS_ONLY; int count; - res = executeJsonPath(jp, vars, EvalJsonPathVar, DatumGetJsonbP(jb), !error, - &found, true); + res = executeJsonPath(jp, vars, evalJsonPathVariable, + DatumGetJsonbP(jb), !error, &found, true); Assert(error || !jperIsError(res)); @@ -2992,8 +3059,8 @@ JsonPathValue(Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars) JsonPathExecResult jper PG_USED_FOR_ASSERTS_ONLY; int count; - jper = executeJsonPath(jp, vars, EvalJsonPathVar, DatumGetJsonbP(jb), !error, - &found, true); + jper = executeJsonPath(jp, vars, evalJsonPathVariable, + DatumGetJsonbP(jb), !error, &found, true); Assert(error || !jperIsError(jper)); @@ -3306,7 +3373,7 @@ JsonTableResetContextItem(JsonTableScanState *scan, Datum item) oldcxt = MemoryContextSwitchTo(scan->mcxt); - res = executeJsonPath(scan->path, scan->args, EvalJsonPathVar, js, + res = executeJsonPath(scan->path, scan->args, evalJsonPathVariable, js, scan->errorOnError, &scan->found, false /* FIXME */ ); MemoryContextSwitchTo(oldcxt); diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index adabf57c97b..b005bf440dd 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -244,7 +244,8 @@ typedef enum ExprEvalOp EEOP_SUBPLAN, EEOP_JSON_CONSTRUCTOR, EEOP_IS_JSON, - EEOP_JSONEXPR, + EEOP_JSONEXPR_SKIP, + EEOP_JSONEXPR_PATH, /* aggregation related nodes */ EEOP_AGG_STRICT_DESERIALIZE, @@ -696,8 +697,18 @@ typedef struct ExprEvalStep struct { struct JsonExprState *jsestate; + int jump_done; + int jump_default_on_empty; /* ON EMPTY DEFAULT expression */ + int jump_default_on_error; /* ON ERROR DEFAULT expression */ } jsonexpr; + /* for EEOP_JSONEXPR_SKIP */ + struct + { + struct JsonExprState *jsestate; + int jump_done; + } jsonexpr_skip; + } d; } ExprEvalStep; @@ -764,11 +775,8 @@ typedef struct JsonExprState NullableDatum formatted_expr, /* formatted context item value */ - coercion_expr, /* input for JSON item coercion */ pathspec; /* path specification value */ - ExprState *default_on_empty; /* ON EMPTY DEFAULT expression */ - ExprState *default_on_error; /* ON ERROR DEFAULT expression */ List *args; /* passing arguments */ } JsonExprState; @@ -831,8 +839,8 @@ extern void ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext, TupleTableSlot *slot); extern void ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op, ExprContext *econtext); -extern void ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, - ExprContext *econtext); +extern int ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op); +extern bool ExecEvalJsonExprSkip(ExprState *state, ExprEvalStep *op); extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext); diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h index e9134b7eab4..a33a770f7aa 100644 --- a/src/include/utils/jsonpath.h +++ b/src/include/utils/jsonpath.h @@ -280,10 +280,6 @@ extern Datum JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, bool *error, List *vars); extern JsonbValue *JsonPathValue(Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars); - -extern int EvalJsonPathVar(void *vars, char *varName, int varNameLen, - JsonbValue *val, JsonbValue *baseObject); - extern PGDLLIMPORT const TableFuncRoutine JsonbTableRoutine; #endif -- 2.17.1