diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index f6780bbf52c..2c62b0c9c84 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -139,7 +139,6 @@ ExecInitExpr(Expr *node, PlanState *parent) state->expr = node; state->parent = parent; state->ext_params = NULL; - state->escontext = NULL; /* Insert setup steps as needed */ ExecCreateExprSetupSteps(state, (Node *) node); @@ -177,7 +176,6 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params) state->expr = node; state->parent = NULL; state->ext_params = ext_params; - state->escontext = NULL; /* Insert setup steps as needed */ ExecCreateExprSetupSteps(state, (Node *) node); @@ -230,7 +228,6 @@ ExecInitQual(List *qual, PlanState *parent) state->expr = (Expr *) qual; state->parent = parent; state->ext_params = NULL; - state->escontext = NULL; /* mark expression as to be used with ExecQual() */ state->flags = EEO_FLAG_IS_QUAL; @@ -376,7 +373,6 @@ ExecBuildProjectionInfo(List *targetList, state->expr = (Expr *) targetList; state->parent = parent; state->ext_params = NULL; - state->escontext = NULL; state->resultslot = slot; @@ -548,7 +544,6 @@ ExecBuildUpdateProjection(List *targetList, state->expr = NULL; /* not used */ state->parent = parent; state->ext_params = NULL; - state->escontext = NULL; state->resultslot = slot; @@ -1554,6 +1549,8 @@ ExecInitExprRec(Expr *node, ExprState *state, CoerceViaIO *iocoerce = (CoerceViaIO *) node; Oid iofunc; bool typisvarlena; + Oid typioparam; + FunctionCallInfo fcinfo_in; /* evaluate argument into step's result area */ ExecInitExprRec(iocoerce->arg, state, resv, resnull); @@ -1582,13 +1579,25 @@ ExecInitExprRec(Expr *node, ExprState *state, /* lookup the result type's input function */ scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo)); + scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3)); + getTypeInputInfo(iocoerce->resulttype, - &iofunc, &scratch.d.iocoerce.typioparam); + &iofunc, &typioparam); fmgr_info(iofunc, scratch.d.iocoerce.finfo_in); fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in); + InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in, + scratch.d.iocoerce.finfo_in, + 3, InvalidOid, NULL, NULL); - /* Set ErrorSaveContext if passed by the caller. */ - scratch.d.iocoerce.escontext = state->escontext; + /* + * We can preload the second and third arguments for the input + * function, since they're constants. + */ + fcinfo_in = scratch.d.iocoerce.fcinfo_data_in; + fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam); + fcinfo_in->args[1].isnull = false; + fcinfo_in->args[2].value = Int32GetDatum(-1); + fcinfo_in->args[2].isnull = false; ExprEvalPushStep(state, &scratch); break; @@ -1619,7 +1628,6 @@ ExecInitExprRec(Expr *node, ExprState *state, elemstate->expr = acoerce->elemexpr; elemstate->parent = state->parent; elemstate->ext_params = state->ext_params; - state->escontext = NULL; elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum)); elemstate->innermost_casenull = (bool *) palloc(sizeof(bool)); @@ -3298,8 +3306,6 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, /* we'll allocate workspace only if needed */ scratch->d.domaincheck.checkvalue = NULL; scratch->d.domaincheck.checknull = NULL; - /* Set ErrorSaveContext if passed by the caller. */ - scratch->d.domaincheck.escontext = state->escontext; /* * Evaluate argument - it's fine to directly store it into resv/resnull, diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index e55fd10e3b8..24c2b60c62a 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -1177,27 +1177,29 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* call input function (similar to InputFunctionCall) */ if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL) { - bool error; + FunctionCallInfo fcinfo_in; + Datum d; - /* - * InputFunctionCallSafe() writes directly into *op->resvalue. - * Return NULL if an error is reported. - */ - error = !InputFunctionCallSafe(op->d.iocoerce.finfo_in, str, - op->d.iocoerce.typioparam, -1, - (Node *) op->d.iocoerce.escontext, - op->resvalue); - if (error) - *op->resnull = true; + fcinfo_in = op->d.iocoerce.fcinfo_data_in; + fcinfo_in->args[0].value = PointerGetDatum(str); + fcinfo_in->args[0].isnull = *op->resnull; + /* second and third arguments are already set up */ - /* - * Should get null result if and only if str is NULL or if we - * got an error above. - */ - if (str == NULL || error) + fcinfo_in->isnull = false; + d = FunctionCallInvoke(fcinfo_in); + *op->resvalue = d; + + /* Should get null result if and only if str is NULL */ + if (str == NULL) + { Assert(*op->resnull); + Assert(fcinfo_in->isnull); + } else + { Assert(!*op->resnull); + Assert(!fcinfo_in->isnull); + } } EEO_NEXT(); @@ -3743,7 +3745,7 @@ ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op) { if (!*op->d.domaincheck.checknull && !DatumGetBool(*op->d.domaincheck.checkvalue)) - errsave((Node *) op->d.domaincheck.escontext, + ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("value for domain %s violates check constraint \"%s\"", format_type_be(op->d.domaincheck.resulttype), diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index 125e1e73ae6..4dfaf797432 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -70,14 +70,12 @@ LLVMTypeRef StructHeapTupleTableSlot; LLVMTypeRef StructMinimalTupleTableSlot; LLVMTypeRef StructMemoryContextData; LLVMTypeRef StructFunctionCallInfoData; -LLVMTypeRef StructFmgrInfo; LLVMTypeRef StructExprContext; LLVMTypeRef StructExprEvalStep; LLVMTypeRef StructExprState; LLVMTypeRef StructAggState; LLVMTypeRef StructAggStatePerGroupData; LLVMTypeRef StructAggStatePerTransData; -LLVMTypeRef StructErrorSaveContext; LLVMValueRef AttributeTemplate; @@ -1120,7 +1118,6 @@ llvm_create_types(void) StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep"); StructExprState = llvm_pg_var_type("StructExprState"); StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData"); - StructFmgrInfo = llvm_pg_var_type("StructFmgrInfo"); StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData"); StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot"); StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot"); @@ -1130,7 +1127,6 @@ llvm_create_types(void) StructAggState = llvm_pg_var_type("StructAggState"); StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData"); StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData"); - StructErrorSaveContext = llvm_pg_var_type("StructErrorSaveContext"); AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate"); } diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index 7d44a4c9f4e..4b51aa1ce07 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -1251,9 +1251,14 @@ llvm_compile_expr(ExprState *state) case EEOP_IOCOERCE: { - FunctionCallInfo fcinfo_out; - LLVMValueRef v_fn_out; - LLVMValueRef v_fcinfo_out; + FunctionCallInfo fcinfo_out, + fcinfo_in; + LLVMValueRef v_fn_out, + v_fn_in; + LLVMValueRef v_fcinfo_out, + v_fcinfo_in; + LLVMValueRef v_fcinfo_in_isnullp; + LLVMValueRef v_retval; LLVMValueRef v_resvalue; LLVMValueRef v_resnull; @@ -1266,6 +1271,7 @@ llvm_compile_expr(ExprState *state) LLVMBasicBlockRef b_inputcall; fcinfo_out = op->d.iocoerce.fcinfo_data_out; + fcinfo_in = op->d.iocoerce.fcinfo_data_in; b_skipoutput = l_bb_before_v(opblocks[opno + 1], "op.%d.skipoutputnull", opno); @@ -1277,7 +1283,14 @@ llvm_compile_expr(ExprState *state) "op.%d.inputcall", opno); v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out); + v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in); v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData)); + v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData)); + + v_fcinfo_in_isnullp = + LLVMBuildStructGEP(b, v_fcinfo_in, + FIELDNO_FUNCTIONCALLINFODATA_ISNULL, + "v_fcinfo_in_isnull"); /* output functions are not called on nulls */ v_resnull = LLVMBuildLoad(b, v_resnullp, ""); @@ -1343,44 +1356,24 @@ llvm_compile_expr(ExprState *state) LLVMBuildBr(b, b_inputcall); } - /* - * Call the input function. - * - * If op->d.iocoerce.escontext references an - * ErrorSaveContext, InputFunctionCallSafe() would return - * false upon encountering an error. - */ LLVMPositionBuilderAtEnd(b, b_inputcall); - { - Oid ioparam = op->d.iocoerce.typioparam; - LLVMValueRef v_params[6]; - LLVMValueRef v_success; + /* set arguments */ + /* arg0: output */ + LLVMBuildStore(b, v_output, + l_funcvaluep(b, v_fcinfo_in, 0)); + LLVMBuildStore(b, v_resnull, + l_funcnullp(b, v_fcinfo_in, 0)); - v_params[0] = l_ptr_const(op->d.iocoerce.finfo_in, - l_ptr(StructFmgrInfo)); - v_params[1] = v_output; - v_params[2] = l_oid_const(lc, ioparam); - v_params[3] = l_int32_const(lc, -1); - v_params[4] = l_ptr_const(op->d.iocoerce.escontext, - l_ptr(StructErrorSaveContext)); + /* arg1: ioparam: preset in execExpr.c */ + /* arg2: typmod: preset in execExpr.c */ - /* - * InputFunctionCallSafe() will write directly into - * *op->resvalue. - */ - v_params[5] = v_resvaluep; + /* reset fcinfo_in->isnull */ + LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp); + /* and call function */ + v_retval = LLVMBuildCall(b, v_fn_in, &v_fcinfo_in, 1, + "funccall_iocoerce_in"); - v_success = LLVMBuildCall(b, llvm_pg_func(mod, "InputFunctionCallSafe"), - v_params, lengthof(v_params), - "funccall_iocoerce_in_safe"); - - /* - * Return null if InputFunctionCallSafe() encountered - * an error. - */ - v_resnullp = LLVMBuildICmp(b, LLVMIntEQ, v_success, - l_sbool_const(0), ""); - } + LLVMBuildStore(b, v_retval, v_resvaluep); LLVMBuildBr(b, opblocks[opno + 1]); break; diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index e1e96250389..41ac4c6f45c 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -59,7 +59,6 @@ AggStatePerTransData StructAggStatePerTransData; ExprContext StructExprContext; ExprEvalStep StructExprEvalStep; ExprState StructExprState; -FmgrInfo StructFmgrInfo; FunctionCallInfoBaseData StructFunctionCallInfoData; HeapTupleData StructHeapTupleData; MemoryContextData StructMemoryContextData; @@ -67,7 +66,6 @@ TupleTableSlot StructTupleTableSlot; HeapTupleTableSlot StructHeapTupleTableSlot; MinimalTupleTableSlot StructMinimalTupleTableSlot; TupleDescData StructTupleDescData; -ErrorSaveContext StructErrorSaveContext; /* @@ -138,7 +136,6 @@ void *referenced_functions[] = ExecEvalJsonConstructor, ExecEvalJsonIsPredicate, MakeExpandedObjectReadOnlyInternal, - InputFunctionCallSafe, slot_getmissingattrs, slot_getsomeattrs_int, strlen, diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index 59f3b043c6b..048573c2bcb 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -16,7 +16,6 @@ #include "executor/nodeAgg.h" #include "nodes/execnodes.h" -#include "nodes/miscnodes.h" /* forward references to avoid circularity */ struct ExprEvalStep; @@ -417,8 +416,7 @@ typedef struct ExprEvalStep FunctionCallInfo fcinfo_data_out; /* lookup and call info for result type's input function */ FmgrInfo *finfo_in; - Oid typioparam; - ErrorSaveContext *escontext; + FunctionCallInfo fcinfo_data_in; } iocoerce; /* for EEOP_SQLVALUEFUNCTION */ @@ -549,7 +547,6 @@ typedef struct ExprEvalStep bool *checknull; /* OID of domain type */ Oid resulttype; - ErrorSaveContext *escontext; } domaincheck; /* for EEOP_CONVERT_ROWTYPE */ diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h index 5b7681eba90..6d90a16f792 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -75,7 +75,6 @@ extern PGDLLIMPORT LLVMTypeRef StructTupleTableSlot; extern PGDLLIMPORT LLVMTypeRef StructHeapTupleTableSlot; extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleTableSlot; extern PGDLLIMPORT LLVMTypeRef StructMemoryContextData; -extern PGDLLIMPORT LLVMTypeRef StructFmgrInfo; extern PGDLLIMPORT LLVMTypeRef StructFunctionCallInfoData; extern PGDLLIMPORT LLVMTypeRef StructExprContext; extern PGDLLIMPORT LLVMTypeRef StructExprEvalStep; @@ -83,7 +82,6 @@ extern PGDLLIMPORT LLVMTypeRef StructExprState; extern PGDLLIMPORT LLVMTypeRef StructAggState; extern PGDLLIMPORT LLVMTypeRef StructAggStatePerTransData; extern PGDLLIMPORT LLVMTypeRef StructAggStatePerGroupData; -extern PGDLLIMPORT LLVMTypeRef StructErrorSaveContext; extern PGDLLIMPORT LLVMValueRef AttributeTemplate; diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h index ead46a64ae2..5e74543be47 100644 --- a/src/include/jit/llvmjit_emit.h +++ b/src/include/jit/llvmjit_emit.h @@ -85,15 +85,6 @@ l_sizet_const(size_t i) return LLVMConstInt(TypeSizeT, i, false); } -/* - * Emit constant oid. - */ -static inline LLVMValueRef -l_oid_const(LLVMContextRef lc, Oid i) -{ - return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false); -} - /* * Emit constant boolean, as used for storage (e.g. global vars, structs). */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index b9b08f0f62b..869465d6f80 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -34,7 +34,6 @@ #include "fmgr.h" #include "lib/ilist.h" #include "lib/pairingheap.h" -#include "nodes/miscnodes.h" #include "nodes/params.h" #include "nodes/plannodes.h" #include "nodes/tidbitmap.h" @@ -130,12 +129,6 @@ typedef struct ExprState Datum *innermost_domainval; bool *innermost_domainnull; - - /* - * For expression nodes that support soft errors. Should be set to NULL - * before calling ExecInitExprRec() if the caller wants errors thrown. - */ - ErrorSaveContext *escontext; } ExprState;