aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execExprInterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execExprInterp.c')
-rw-r--r--src/backend/executor/execExprInterp.c139
1 files changed, 76 insertions, 63 deletions
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 5a7206f5882..5c5f655645d 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -387,7 +387,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
&&CASE_EEOP_ALTERNATIVE_SUBPLAN,
&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
&&CASE_EEOP_AGG_DESERIALIZE,
- &&CASE_EEOP_AGG_STRICT_INPUT_CHECK,
+ &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
+ &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
&&CASE_EEOP_AGG_INIT_TRANS,
&&CASE_EEOP_AGG_STRICT_TRANS_CHECK,
&&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
@@ -631,14 +632,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_FUNCEXPR_STRICT)
{
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
- bool *argnull = fcinfo->argnull;
+ NullableDatum *args = fcinfo->args;
int argno;
Datum d;
/* strict function, so check for NULL args */
for (argno = 0; argno < op->d.func.nargs; argno++)
{
- if (argnull[argno])
+ if (args[argno].isnull)
{
*op->resnull = true;
goto strictfail;
@@ -1054,8 +1055,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
FunctionCallInfo fcinfo_out;
fcinfo_out = op->d.iocoerce.fcinfo_data_out;
- fcinfo_out->arg[0] = *op->resvalue;
- fcinfo_out->argnull[0] = false;
+ fcinfo_out->args[0].value = *op->resvalue;
+ fcinfo_out->args[0].isnull = false;
fcinfo_out->isnull = false;
str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
@@ -1071,8 +1072,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
Datum d;
fcinfo_in = op->d.iocoerce.fcinfo_data_in;
- fcinfo_in->arg[0] = PointerGetDatum(str);
- fcinfo_in->argnull[0] = *op->resnull;
+ fcinfo_in->args[0].value = PointerGetDatum(str);
+ fcinfo_in->args[0].isnull = *op->resnull;
/* second and third arguments are already set up */
fcinfo_in->isnull = false;
@@ -1099,23 +1100,23 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
/*
* IS DISTINCT FROM must evaluate arguments (already done into
- * fcinfo->arg/argnull) to determine whether they are NULL; if
- * either is NULL then the result is determined. If neither is
- * NULL, then proceed to evaluate the comparison function, which
- * is just the type's standard equality operator. We need not
- * care whether that function is strict. Because the handling of
- * nulls is different, we can't just reuse EEOP_FUNCEXPR.
+ * fcinfo->args) to determine whether they are NULL; if either is
+ * NULL then the result is determined. If neither is NULL, then
+ * proceed to evaluate the comparison function, which is just the
+ * type's standard equality operator. We need not care whether
+ * that function is strict. Because the handling of nulls is
+ * different, we can't just reuse EEOP_FUNCEXPR.
*/
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
/* check function arguments for NULLness */
- if (fcinfo->argnull[0] && fcinfo->argnull[1])
+ if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
{
/* Both NULL? Then is not distinct... */
*op->resvalue = BoolGetDatum(false);
*op->resnull = false;
}
- else if (fcinfo->argnull[0] || fcinfo->argnull[1])
+ else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
{
/* Only one is NULL? Then is distinct... */
*op->resvalue = BoolGetDatum(true);
@@ -1141,12 +1142,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
- if (fcinfo->argnull[0] && fcinfo->argnull[1])
+ if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
{
*op->resvalue = BoolGetDatum(true);
*op->resnull = false;
}
- else if (fcinfo->argnull[0] || fcinfo->argnull[1])
+ else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
{
*op->resvalue = BoolGetDatum(false);
*op->resnull = false;
@@ -1167,12 +1168,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_NULLIF)
{
/*
- * The arguments are already evaluated into fcinfo->arg/argnull.
+ * The arguments are already evaluated into fcinfo->args.
*/
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
/* if either argument is NULL they can't be equal */
- if (!fcinfo->argnull[0] && !fcinfo->argnull[1])
+ if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull)
{
Datum result;
@@ -1190,8 +1191,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
}
/* Arguments aren't equal, so return the first one */
- *op->resvalue = fcinfo->arg[0];
- *op->resnull = fcinfo->argnull[0];
+ *op->resvalue = fcinfo->args[0].value;
+ *op->resnull = fcinfo->args[0].isnull;
EEO_NEXT();
}
@@ -1257,7 +1258,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* force NULL result if strict fn and NULL input */
if (op->d.rowcompare_step.finfo->fn_strict &&
- (fcinfo->argnull[0] || fcinfo->argnull[1]))
+ (fcinfo->args[0].isnull || fcinfo->args[1].isnull))
{
*op->resnull = true;
EEO_JUMP(op->d.rowcompare_step.jumpnull);
@@ -1496,10 +1497,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* evaluate a strict aggregate deserialization function */
EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE)
{
- bool *argnull = op->d.agg_deserialize.fcinfo_data->argnull;
-
/* Don't call a strict deserialization function with NULL input */
- if (argnull[0])
+ if (op->d.agg_deserialize.fcinfo_data->args[0].isnull)
EEO_JUMP(op->d.agg_deserialize.jumpnull);
/* fallthrough */
@@ -1529,7 +1528,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
* Check that a strict aggregate transition / combination function's
* input is not NULL.
*/
- EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK)
+ EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
{
int argno;
bool *nulls = op->d.agg_strict_input_check.nulls;
@@ -1543,6 +1542,20 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_NEXT();
}
+ EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS)
+ {
+ int argno;
+ NullableDatum *args = op->d.agg_strict_input_check.args;
+ int nargs = op->d.agg_strict_input_check.nargs;
+
+ for (argno = 0; argno < nargs; argno++)
+ {
+ if (args[argno].isnull)
+ EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
+ }
+ EEO_NEXT();
+ }
+
/*
* Initialize an aggregate's first value if necessary.
*/
@@ -1613,7 +1626,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
Assert(pertrans->transtypeByVal);
- fcinfo = &pertrans->transfn_fcinfo;
+ fcinfo = pertrans->transfn_fcinfo;
/* cf. select_current_set() */
aggstate->curaggcontext = op->d.agg_trans.aggcontext;
@@ -1625,8 +1638,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* invoke transition function in per-tuple context */
oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
- fcinfo->arg[0] = pergroup->transValue;
- fcinfo->argnull[0] = pergroup->transValueIsNull;
+ fcinfo->args[0].value = pergroup->transValue;
+ fcinfo->args[0].isnull = pergroup->transValueIsNull;
fcinfo->isnull = false; /* just in case transfn doesn't set it */
newVal = FunctionCallInvoke(fcinfo);
@@ -1664,7 +1677,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
Assert(!pertrans->transtypeByVal);
- fcinfo = &pertrans->transfn_fcinfo;
+ fcinfo = pertrans->transfn_fcinfo;
/* cf. select_current_set() */
aggstate->curaggcontext = op->d.agg_trans.aggcontext;
@@ -1676,8 +1689,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* invoke transition function in per-tuple context */
oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
- fcinfo->arg[0] = pergroup->transValue;
- fcinfo->argnull[0] = pergroup->transValueIsNull;
+ fcinfo->args[0].value = pergroup->transValue;
+ fcinfo->args[0].isnull = pergroup->transValueIsNull;
fcinfo->isnull = false; /* just in case transfn doesn't set it */
newVal = FunctionCallInvoke(fcinfo);
@@ -2075,7 +2088,7 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
{
ExprEvalStep *op = &state->steps[0];
FunctionCallInfo fcinfo;
- bool *argnull;
+ NullableDatum *args;
int argno;
Datum d;
@@ -2089,12 +2102,12 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
op++;
fcinfo = op->d.func.fcinfo_data;
- argnull = fcinfo->argnull;
+ args = fcinfo->args;
/* strict function, so check for NULL args */
for (argno = 0; argno < op->d.func.nargs; argno++)
{
- if (argnull[argno])
+ if (args[argno].isnull)
{
*isnull = true;
return (Datum) 0;
@@ -2220,14 +2233,14 @@ ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
PgStat_FunctionCallUsage fcusage;
- bool *argnull = fcinfo->argnull;
+ NullableDatum *args = fcinfo->args;
int argno;
Datum d;
/* strict function, so check for NULL args */
for (argno = 0; argno < op->d.func.nargs; argno++)
{
- if (argnull[argno])
+ if (args[argno].isnull)
{
*op->resnull = true;
return;
@@ -2317,8 +2330,8 @@ ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void
ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
{
+ LOCAL_FCINFO(fcinfo, 0);
SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
- FunctionCallInfoData fcinfo;
*op->resnull = false;
@@ -2350,24 +2363,24 @@ ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
case SVFOP_CURRENT_ROLE:
case SVFOP_CURRENT_USER:
case SVFOP_USER:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = current_user(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_user(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
case SVFOP_SESSION_USER:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = session_user(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = session_user(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
case SVFOP_CURRENT_CATALOG:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = current_database(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_database(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
case SVFOP_CURRENT_SCHEMA:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = current_schema(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_schema(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
}
}
@@ -2800,8 +2813,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
int off;
/* set at initialization */
- Assert(fcinfo->argnull[0] == false);
- Assert(fcinfo->argnull[1] == false);
+ Assert(fcinfo->args[0].isnull == false);
+ Assert(fcinfo->args[1].isnull == false);
/* default to null result */
*op->resnull = true;
@@ -2823,8 +2836,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
int cmpresult;
/* apply comparison function */
- fcinfo->arg[0] = *op->resvalue;
- fcinfo->arg[1] = values[off];
+ fcinfo->args[0].value = *op->resvalue;
+ fcinfo->args[1].value = values[off];
fcinfo->isnull = false;
cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
@@ -3324,7 +3337,7 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext
* Evaluate "scalar op ANY/ALL (array)".
*
* Source array is in our result area, scalar arg is already evaluated into
- * fcinfo->arg[0]/argnull[0].
+ * fcinfo->args[0].
*
* The operator always yields boolean, and we combine the results across all
* array elements using OR and AND (for ANY and ALL respectively). Of course
@@ -3376,7 +3389,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
* If the scalar is NULL, and the function is strict, return NULL; no
* point in iterating the loop.
*/
- if (fcinfo->argnull[0] && strictfunc)
+ if (fcinfo->args[0].isnull && strictfunc)
{
*op->resnull = true;
return;
@@ -3416,20 +3429,20 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
/* Get array element, checking for NULL */
if (bitmap && (*bitmap & bitmask) == 0)
{
- fcinfo->arg[1] = (Datum) 0;
- fcinfo->argnull[1] = true;
+ fcinfo->args[1].value = (Datum) 0;
+ fcinfo->args[1].isnull = true;
}
else
{
elt = fetch_att(s, typbyval, typlen);
s = att_addlength_pointer(s, typlen, s);
s = (char *) att_align_nominal(s, typalign);
- fcinfo->arg[1] = elt;
- fcinfo->argnull[1] = false;
+ fcinfo->args[1].value = elt;
+ fcinfo->args[1].isnull = false;
}
/* Call comparison function */
- if (fcinfo->argnull[1] && strictfunc)
+ if (fcinfo->args[1].isnull && strictfunc)
{
fcinfo->isnull = true;
thisresult = (Datum) 0;
@@ -4044,7 +4057,7 @@ ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
void
ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup)
{
- FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
MemoryContext oldContext;
/*
@@ -4055,7 +4068,7 @@ ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup
*/
oldContext = MemoryContextSwitchTo(
aggstate->curaggcontext->ecxt_per_tuple_memory);
- pergroup->transValue = datumCopy(fcinfo->arg[1],
+ pergroup->transValue = datumCopy(fcinfo->args[1].value,
pertrans->transtypeByVal,
pertrans->transtypeLen);
pergroup->transValueIsNull = false;