mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Add soft error handling to some expression nodes
This adjusts the expression evaluation code for CoerceViaIO and CoerceToDomain to handle errors softly if needed. For CoerceViaIo, this means using InputFunctionCallSafe(), which provides the option to handle errors softly, instead of calling the type input function directly. For CoerceToDomain, this simply entails replacing the ereport() in ExecEvalConstraintCheck() by errsave(). In both cases, the ErrorSaveContext to be used when evaluating the expression is stored by ExecInitExprRec() in the expression's struct in the expression's ExprEvalStep. The ErrorSaveContext is passed by setting ExprState.escontext to point to it when calling ExecInitExprRec() on the expression whose errors are to be handled softly. Note that no call site of ExecInitExprRec() has been changed in this commit, so there's no functional change. This is intended for implementing new SQL/JSON expression nodes in future commits that will use to it suppress errors that may occur during type coercions. Reviewed-by: Álvaro Herrera Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
This commit is contained in:
@ -139,6 +139,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
|||||||
state->expr = node;
|
state->expr = node;
|
||||||
state->parent = parent;
|
state->parent = parent;
|
||||||
state->ext_params = NULL;
|
state->ext_params = NULL;
|
||||||
|
state->escontext = NULL;
|
||||||
|
|
||||||
/* Insert setup steps as needed */
|
/* Insert setup steps as needed */
|
||||||
ExecCreateExprSetupSteps(state, (Node *) node);
|
ExecCreateExprSetupSteps(state, (Node *) node);
|
||||||
@ -176,6 +177,7 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
|
|||||||
state->expr = node;
|
state->expr = node;
|
||||||
state->parent = NULL;
|
state->parent = NULL;
|
||||||
state->ext_params = ext_params;
|
state->ext_params = ext_params;
|
||||||
|
state->escontext = NULL;
|
||||||
|
|
||||||
/* Insert setup steps as needed */
|
/* Insert setup steps as needed */
|
||||||
ExecCreateExprSetupSteps(state, (Node *) node);
|
ExecCreateExprSetupSteps(state, (Node *) node);
|
||||||
@ -228,6 +230,7 @@ ExecInitQual(List *qual, PlanState *parent)
|
|||||||
state->expr = (Expr *) qual;
|
state->expr = (Expr *) qual;
|
||||||
state->parent = parent;
|
state->parent = parent;
|
||||||
state->ext_params = NULL;
|
state->ext_params = NULL;
|
||||||
|
state->escontext = NULL;
|
||||||
|
|
||||||
/* mark expression as to be used with ExecQual() */
|
/* mark expression as to be used with ExecQual() */
|
||||||
state->flags = EEO_FLAG_IS_QUAL;
|
state->flags = EEO_FLAG_IS_QUAL;
|
||||||
@ -373,6 +376,7 @@ ExecBuildProjectionInfo(List *targetList,
|
|||||||
state->expr = (Expr *) targetList;
|
state->expr = (Expr *) targetList;
|
||||||
state->parent = parent;
|
state->parent = parent;
|
||||||
state->ext_params = NULL;
|
state->ext_params = NULL;
|
||||||
|
state->escontext = NULL;
|
||||||
|
|
||||||
state->resultslot = slot;
|
state->resultslot = slot;
|
||||||
|
|
||||||
@ -544,6 +548,7 @@ ExecBuildUpdateProjection(List *targetList,
|
|||||||
state->expr = NULL; /* not used */
|
state->expr = NULL; /* not used */
|
||||||
state->parent = parent;
|
state->parent = parent;
|
||||||
state->ext_params = NULL;
|
state->ext_params = NULL;
|
||||||
|
state->escontext = NULL;
|
||||||
|
|
||||||
state->resultslot = slot;
|
state->resultslot = slot;
|
||||||
|
|
||||||
@ -1549,8 +1554,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
|
|||||||
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
|
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
|
||||||
Oid iofunc;
|
Oid iofunc;
|
||||||
bool typisvarlena;
|
bool typisvarlena;
|
||||||
Oid typioparam;
|
|
||||||
FunctionCallInfo fcinfo_in;
|
|
||||||
|
|
||||||
/* evaluate argument into step's result area */
|
/* evaluate argument into step's result area */
|
||||||
ExecInitExprRec(iocoerce->arg, state, resv, resnull);
|
ExecInitExprRec(iocoerce->arg, state, resv, resnull);
|
||||||
@ -1579,25 +1582,13 @@ ExecInitExprRec(Expr *node, ExprState *state,
|
|||||||
|
|
||||||
/* lookup the result type's input function */
|
/* lookup the result type's input function */
|
||||||
scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
|
scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
|
||||||
scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
|
|
||||||
|
|
||||||
getTypeInputInfo(iocoerce->resulttype,
|
getTypeInputInfo(iocoerce->resulttype,
|
||||||
&iofunc, &typioparam);
|
&iofunc, &scratch.d.iocoerce.typioparam);
|
||||||
fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
|
fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
|
||||||
fmgr_info_set_expr((Node *) node, 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. */
|
||||||
* We can preload the second and third arguments for the input
|
scratch.d.iocoerce.escontext = state->escontext;
|
||||||
* 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);
|
ExprEvalPushStep(state, &scratch);
|
||||||
break;
|
break;
|
||||||
@ -1628,6 +1619,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
|
|||||||
elemstate->expr = acoerce->elemexpr;
|
elemstate->expr = acoerce->elemexpr;
|
||||||
elemstate->parent = state->parent;
|
elemstate->parent = state->parent;
|
||||||
elemstate->ext_params = state->ext_params;
|
elemstate->ext_params = state->ext_params;
|
||||||
|
state->escontext = NULL;
|
||||||
|
|
||||||
elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
|
elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
|
||||||
elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
|
elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
|
||||||
@ -3306,6 +3298,8 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
|
|||||||
/* we'll allocate workspace only if needed */
|
/* we'll allocate workspace only if needed */
|
||||||
scratch->d.domaincheck.checkvalue = NULL;
|
scratch->d.domaincheck.checkvalue = NULL;
|
||||||
scratch->d.domaincheck.checknull = 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,
|
* Evaluate argument - it's fine to directly store it into resv/resnull,
|
||||||
|
@ -1177,29 +1177,27 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
|
|||||||
/* call input function (similar to InputFunctionCall) */
|
/* call input function (similar to InputFunctionCall) */
|
||||||
if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
|
if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
|
||||||
{
|
{
|
||||||
FunctionCallInfo fcinfo_in;
|
bool error;
|
||||||
Datum d;
|
|
||||||
|
|
||||||
fcinfo_in = op->d.iocoerce.fcinfo_data_in;
|
/*
|
||||||
fcinfo_in->args[0].value = PointerGetDatum(str);
|
* InputFunctionCallSafe() writes directly into *op->resvalue.
|
||||||
fcinfo_in->args[0].isnull = *op->resnull;
|
* Return NULL if an error is reported.
|
||||||
/* second and third arguments are already set up */
|
*/
|
||||||
|
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->isnull = false;
|
/*
|
||||||
d = FunctionCallInvoke(fcinfo_in);
|
* Should get null result if and only if str is NULL or if we
|
||||||
*op->resvalue = d;
|
* got an error above.
|
||||||
|
*/
|
||||||
/* Should get null result if and only if str is NULL */
|
if (str == NULL || error)
|
||||||
if (str == NULL)
|
|
||||||
{
|
|
||||||
Assert(*op->resnull);
|
Assert(*op->resnull);
|
||||||
Assert(fcinfo_in->isnull);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Assert(!*op->resnull);
|
Assert(!*op->resnull);
|
||||||
Assert(!fcinfo_in->isnull);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EEO_NEXT();
|
EEO_NEXT();
|
||||||
@ -3745,7 +3743,7 @@ ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op)
|
|||||||
{
|
{
|
||||||
if (!*op->d.domaincheck.checknull &&
|
if (!*op->d.domaincheck.checknull &&
|
||||||
!DatumGetBool(*op->d.domaincheck.checkvalue))
|
!DatumGetBool(*op->d.domaincheck.checkvalue))
|
||||||
ereport(ERROR,
|
errsave((Node *) op->d.domaincheck.escontext,
|
||||||
(errcode(ERRCODE_CHECK_VIOLATION),
|
(errcode(ERRCODE_CHECK_VIOLATION),
|
||||||
errmsg("value for domain %s violates check constraint \"%s\"",
|
errmsg("value for domain %s violates check constraint \"%s\"",
|
||||||
format_type_be(op->d.domaincheck.resulttype),
|
format_type_be(op->d.domaincheck.resulttype),
|
||||||
|
@ -70,12 +70,14 @@ LLVMTypeRef StructHeapTupleTableSlot;
|
|||||||
LLVMTypeRef StructMinimalTupleTableSlot;
|
LLVMTypeRef StructMinimalTupleTableSlot;
|
||||||
LLVMTypeRef StructMemoryContextData;
|
LLVMTypeRef StructMemoryContextData;
|
||||||
LLVMTypeRef StructFunctionCallInfoData;
|
LLVMTypeRef StructFunctionCallInfoData;
|
||||||
|
LLVMTypeRef StructFmgrInfo;
|
||||||
LLVMTypeRef StructExprContext;
|
LLVMTypeRef StructExprContext;
|
||||||
LLVMTypeRef StructExprEvalStep;
|
LLVMTypeRef StructExprEvalStep;
|
||||||
LLVMTypeRef StructExprState;
|
LLVMTypeRef StructExprState;
|
||||||
LLVMTypeRef StructAggState;
|
LLVMTypeRef StructAggState;
|
||||||
LLVMTypeRef StructAggStatePerGroupData;
|
LLVMTypeRef StructAggStatePerGroupData;
|
||||||
LLVMTypeRef StructAggStatePerTransData;
|
LLVMTypeRef StructAggStatePerTransData;
|
||||||
|
LLVMTypeRef StructErrorSaveContext;
|
||||||
|
|
||||||
LLVMValueRef AttributeTemplate;
|
LLVMValueRef AttributeTemplate;
|
||||||
|
|
||||||
@ -1118,6 +1120,7 @@ llvm_create_types(void)
|
|||||||
StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
|
StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
|
||||||
StructExprState = llvm_pg_var_type("StructExprState");
|
StructExprState = llvm_pg_var_type("StructExprState");
|
||||||
StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
|
StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
|
||||||
|
StructFmgrInfo = llvm_pg_var_type("StructFmgrInfo");
|
||||||
StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
|
StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
|
||||||
StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
|
StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
|
||||||
StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
|
StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
|
||||||
@ -1127,6 +1130,7 @@ llvm_create_types(void)
|
|||||||
StructAggState = llvm_pg_var_type("StructAggState");
|
StructAggState = llvm_pg_var_type("StructAggState");
|
||||||
StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
|
StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
|
||||||
StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
|
StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
|
||||||
|
StructErrorSaveContext = llvm_pg_var_type("StructErrorSaveContext");
|
||||||
|
|
||||||
AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
|
AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
|
||||||
}
|
}
|
||||||
|
@ -1251,14 +1251,9 @@ llvm_compile_expr(ExprState *state)
|
|||||||
|
|
||||||
case EEOP_IOCOERCE:
|
case EEOP_IOCOERCE:
|
||||||
{
|
{
|
||||||
FunctionCallInfo fcinfo_out,
|
FunctionCallInfo fcinfo_out;
|
||||||
fcinfo_in;
|
LLVMValueRef v_fn_out;
|
||||||
LLVMValueRef v_fn_out,
|
LLVMValueRef v_fcinfo_out;
|
||||||
v_fn_in;
|
|
||||||
LLVMValueRef v_fcinfo_out,
|
|
||||||
v_fcinfo_in;
|
|
||||||
LLVMValueRef v_fcinfo_in_isnullp;
|
|
||||||
LLVMValueRef v_retval;
|
|
||||||
LLVMValueRef v_resvalue;
|
LLVMValueRef v_resvalue;
|
||||||
LLVMValueRef v_resnull;
|
LLVMValueRef v_resnull;
|
||||||
|
|
||||||
@ -1271,7 +1266,6 @@ llvm_compile_expr(ExprState *state)
|
|||||||
LLVMBasicBlockRef b_inputcall;
|
LLVMBasicBlockRef b_inputcall;
|
||||||
|
|
||||||
fcinfo_out = op->d.iocoerce.fcinfo_data_out;
|
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],
|
b_skipoutput = l_bb_before_v(opblocks[opno + 1],
|
||||||
"op.%d.skipoutputnull", opno);
|
"op.%d.skipoutputnull", opno);
|
||||||
@ -1283,14 +1277,7 @@ llvm_compile_expr(ExprState *state)
|
|||||||
"op.%d.inputcall", opno);
|
"op.%d.inputcall", opno);
|
||||||
|
|
||||||
v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out);
|
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_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 */
|
/* output functions are not called on nulls */
|
||||||
v_resnull = LLVMBuildLoad(b, v_resnullp, "");
|
v_resnull = LLVMBuildLoad(b, v_resnullp, "");
|
||||||
@ -1356,24 +1343,44 @@ llvm_compile_expr(ExprState *state)
|
|||||||
LLVMBuildBr(b, b_inputcall);
|
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);
|
LLVMPositionBuilderAtEnd(b, b_inputcall);
|
||||||
/* set arguments */
|
{
|
||||||
/* arg0: output */
|
Oid ioparam = op->d.iocoerce.typioparam;
|
||||||
LLVMBuildStore(b, v_output,
|
LLVMValueRef v_params[6];
|
||||||
l_funcvaluep(b, v_fcinfo_in, 0));
|
LLVMValueRef v_success;
|
||||||
LLVMBuildStore(b, v_resnull,
|
|
||||||
l_funcnullp(b, v_fcinfo_in, 0));
|
|
||||||
|
|
||||||
/* arg1: ioparam: preset in execExpr.c */
|
v_params[0] = l_ptr_const(op->d.iocoerce.finfo_in,
|
||||||
/* arg2: typmod: preset in execExpr.c */
|
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));
|
||||||
|
|
||||||
/* reset fcinfo_in->isnull */
|
/*
|
||||||
LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
|
* InputFunctionCallSafe() will write directly into
|
||||||
/* and call function */
|
* *op->resvalue.
|
||||||
v_retval = LLVMBuildCall(b, v_fn_in, &v_fcinfo_in, 1,
|
*/
|
||||||
"funccall_iocoerce_in");
|
v_params[5] = v_resvaluep;
|
||||||
|
|
||||||
LLVMBuildStore(b, v_retval, v_resvaluep);
|
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), "");
|
||||||
|
}
|
||||||
|
|
||||||
LLVMBuildBr(b, opblocks[opno + 1]);
|
LLVMBuildBr(b, opblocks[opno + 1]);
|
||||||
break;
|
break;
|
||||||
|
@ -59,6 +59,7 @@ AggStatePerTransData StructAggStatePerTransData;
|
|||||||
ExprContext StructExprContext;
|
ExprContext StructExprContext;
|
||||||
ExprEvalStep StructExprEvalStep;
|
ExprEvalStep StructExprEvalStep;
|
||||||
ExprState StructExprState;
|
ExprState StructExprState;
|
||||||
|
FmgrInfo StructFmgrInfo;
|
||||||
FunctionCallInfoBaseData StructFunctionCallInfoData;
|
FunctionCallInfoBaseData StructFunctionCallInfoData;
|
||||||
HeapTupleData StructHeapTupleData;
|
HeapTupleData StructHeapTupleData;
|
||||||
MemoryContextData StructMemoryContextData;
|
MemoryContextData StructMemoryContextData;
|
||||||
@ -66,6 +67,7 @@ TupleTableSlot StructTupleTableSlot;
|
|||||||
HeapTupleTableSlot StructHeapTupleTableSlot;
|
HeapTupleTableSlot StructHeapTupleTableSlot;
|
||||||
MinimalTupleTableSlot StructMinimalTupleTableSlot;
|
MinimalTupleTableSlot StructMinimalTupleTableSlot;
|
||||||
TupleDescData StructTupleDescData;
|
TupleDescData StructTupleDescData;
|
||||||
|
ErrorSaveContext StructErrorSaveContext;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -136,6 +138,7 @@ void *referenced_functions[] =
|
|||||||
ExecEvalJsonConstructor,
|
ExecEvalJsonConstructor,
|
||||||
ExecEvalJsonIsPredicate,
|
ExecEvalJsonIsPredicate,
|
||||||
MakeExpandedObjectReadOnlyInternal,
|
MakeExpandedObjectReadOnlyInternal,
|
||||||
|
InputFunctionCallSafe,
|
||||||
slot_getmissingattrs,
|
slot_getmissingattrs,
|
||||||
slot_getsomeattrs_int,
|
slot_getsomeattrs_int,
|
||||||
strlen,
|
strlen,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "executor/nodeAgg.h"
|
#include "executor/nodeAgg.h"
|
||||||
#include "nodes/execnodes.h"
|
#include "nodes/execnodes.h"
|
||||||
|
#include "nodes/miscnodes.h"
|
||||||
|
|
||||||
/* forward references to avoid circularity */
|
/* forward references to avoid circularity */
|
||||||
struct ExprEvalStep;
|
struct ExprEvalStep;
|
||||||
@ -416,7 +417,8 @@ typedef struct ExprEvalStep
|
|||||||
FunctionCallInfo fcinfo_data_out;
|
FunctionCallInfo fcinfo_data_out;
|
||||||
/* lookup and call info for result type's input function */
|
/* lookup and call info for result type's input function */
|
||||||
FmgrInfo *finfo_in;
|
FmgrInfo *finfo_in;
|
||||||
FunctionCallInfo fcinfo_data_in;
|
Oid typioparam;
|
||||||
|
ErrorSaveContext *escontext;
|
||||||
} iocoerce;
|
} iocoerce;
|
||||||
|
|
||||||
/* for EEOP_SQLVALUEFUNCTION */
|
/* for EEOP_SQLVALUEFUNCTION */
|
||||||
@ -547,6 +549,7 @@ typedef struct ExprEvalStep
|
|||||||
bool *checknull;
|
bool *checknull;
|
||||||
/* OID of domain type */
|
/* OID of domain type */
|
||||||
Oid resulttype;
|
Oid resulttype;
|
||||||
|
ErrorSaveContext *escontext;
|
||||||
} domaincheck;
|
} domaincheck;
|
||||||
|
|
||||||
/* for EEOP_CONVERT_ROWTYPE */
|
/* for EEOP_CONVERT_ROWTYPE */
|
||||||
|
@ -75,6 +75,7 @@ extern PGDLLIMPORT LLVMTypeRef StructTupleTableSlot;
|
|||||||
extern PGDLLIMPORT LLVMTypeRef StructHeapTupleTableSlot;
|
extern PGDLLIMPORT LLVMTypeRef StructHeapTupleTableSlot;
|
||||||
extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleTableSlot;
|
extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleTableSlot;
|
||||||
extern PGDLLIMPORT LLVMTypeRef StructMemoryContextData;
|
extern PGDLLIMPORT LLVMTypeRef StructMemoryContextData;
|
||||||
|
extern PGDLLIMPORT LLVMTypeRef StructFmgrInfo;
|
||||||
extern PGDLLIMPORT LLVMTypeRef StructFunctionCallInfoData;
|
extern PGDLLIMPORT LLVMTypeRef StructFunctionCallInfoData;
|
||||||
extern PGDLLIMPORT LLVMTypeRef StructExprContext;
|
extern PGDLLIMPORT LLVMTypeRef StructExprContext;
|
||||||
extern PGDLLIMPORT LLVMTypeRef StructExprEvalStep;
|
extern PGDLLIMPORT LLVMTypeRef StructExprEvalStep;
|
||||||
@ -82,6 +83,7 @@ extern PGDLLIMPORT LLVMTypeRef StructExprState;
|
|||||||
extern PGDLLIMPORT LLVMTypeRef StructAggState;
|
extern PGDLLIMPORT LLVMTypeRef StructAggState;
|
||||||
extern PGDLLIMPORT LLVMTypeRef StructAggStatePerTransData;
|
extern PGDLLIMPORT LLVMTypeRef StructAggStatePerTransData;
|
||||||
extern PGDLLIMPORT LLVMTypeRef StructAggStatePerGroupData;
|
extern PGDLLIMPORT LLVMTypeRef StructAggStatePerGroupData;
|
||||||
|
extern PGDLLIMPORT LLVMTypeRef StructErrorSaveContext;
|
||||||
|
|
||||||
extern PGDLLIMPORT LLVMValueRef AttributeTemplate;
|
extern PGDLLIMPORT LLVMValueRef AttributeTemplate;
|
||||||
|
|
||||||
|
@ -85,6 +85,15 @@ l_sizet_const(size_t i)
|
|||||||
return LLVMConstInt(TypeSizeT, i, false);
|
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).
|
* Emit constant boolean, as used for storage (e.g. global vars, structs).
|
||||||
*/
|
*/
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
#include "lib/ilist.h"
|
#include "lib/ilist.h"
|
||||||
#include "lib/pairingheap.h"
|
#include "lib/pairingheap.h"
|
||||||
|
#include "nodes/miscnodes.h"
|
||||||
#include "nodes/params.h"
|
#include "nodes/params.h"
|
||||||
#include "nodes/plannodes.h"
|
#include "nodes/plannodes.h"
|
||||||
#include "nodes/tidbitmap.h"
|
#include "nodes/tidbitmap.h"
|
||||||
@ -129,6 +130,12 @@ typedef struct ExprState
|
|||||||
|
|
||||||
Datum *innermost_domainval;
|
Datum *innermost_domainval;
|
||||||
bool *innermost_domainnull;
|
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;
|
} ExprState;
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user