diff options
Diffstat (limited to 'src/backend/executor/execExprInterp.c')
-rw-r--r-- | src/backend/executor/execExprInterp.c | 139 |
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; |