diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 44587a84bae..9f4229de600 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -1172,6 +1172,7 @@ finalize_partialaggregate(AggState *aggstate, pergroupstate->transValueIsNull, pertrans->transtypeLen); fcinfo->args[0].isnull = pergroupstate->transValueIsNull; + fcinfo->isnull = false; *resultVal = FunctionCallInvoke(fcinfo); *resultIsNull = fcinfo->isnull; diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 11987c8f3ba..800107d4e72 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3668,7 +3668,7 @@ array_eq(PG_FUNCTION_ARGS) } /* - * Apply the operator to the element pair + * Apply the operator to the element pair; treat NULL as false */ locfcinfo->args[0].value = elt1; locfcinfo->args[0].isnull = false; @@ -3676,7 +3676,7 @@ array_eq(PG_FUNCTION_ARGS) locfcinfo->args[1].isnull = false; locfcinfo->isnull = false; oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); - if (!oprresult) + if (locfcinfo->isnull || !oprresult) { result = false; break; @@ -3841,9 +3841,11 @@ array_cmp(FunctionCallInfo fcinfo) locfcinfo->args[0].isnull = false; locfcinfo->args[1].value = elt2; locfcinfo->args[1].isnull = false; - locfcinfo->isnull = false; cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); + /* We don't expect comparison support functions to return null */ + Assert(!locfcinfo->isnull); + if (cmpresult == 0) continue; /* equal */ @@ -3983,8 +3985,9 @@ hash_array(PG_FUNCTION_ARGS) /* Apply the hash function */ locfcinfo->args[0].value = elt; locfcinfo->args[0].isnull = false; - locfcinfo->isnull = false; elthash = DatumGetUInt32(FunctionCallInvoke(locfcinfo)); + /* We don't expect hash functions to return null */ + Assert(!locfcinfo->isnull); } /* @@ -4074,6 +4077,8 @@ hash_array_extended(PG_FUNCTION_ARGS) locfcinfo->args[1].value = Int64GetDatum(seed); locfcinfo->args[1].isnull = false; elthash = DatumGetUInt64(FunctionCallInvoke(locfcinfo)); + /* We don't expect hash functions to return null */ + Assert(!locfcinfo->isnull); } result = (result << 5) - result + elthash; @@ -4207,7 +4212,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, continue; /* can't match */ /* - * Apply the operator to the element pair + * Apply the operator to the element pair; treat NULL as false */ locfcinfo->args[0].value = elt1; locfcinfo->args[0].isnull = false; @@ -4215,7 +4220,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, locfcinfo->args[1].isnull = false; locfcinfo->isnull = false; oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); - if (oprresult) + if (!locfcinfo->isnull && oprresult) break; } @@ -6202,7 +6207,7 @@ array_replace_internal(ArrayType *array, else { /* - * Apply the operator to the element pair + * Apply the operator to the element pair; treat NULL as false */ locfcinfo->args[0].value = elt; locfcinfo->args[0].isnull = false; @@ -6210,7 +6215,7 @@ array_replace_internal(ArrayType *array, locfcinfo->args[1].isnull = false; locfcinfo->isnull = false; oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); - if (!oprresult) + if (locfcinfo->isnull || !oprresult) { /* no match, keep element */ values[nresult] = elt; @@ -6517,10 +6522,12 @@ width_bucket_array_fixed(Datum operand, locfcinfo->args[0].isnull = false; locfcinfo->args[1].value = fetch_att(ptr, typbyval, typlen); locfcinfo->args[1].isnull = false; - locfcinfo->isnull = false; cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); + /* We don't expect comparison support functions to return null */ + Assert(!locfcinfo->isnull); + if (cmpresult < 0) right = mid; else @@ -6577,6 +6584,9 @@ width_bucket_array_variable(Datum operand, cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); + /* We don't expect comparison support functions to return null */ + Assert(!locfcinfo->isnull); + if (cmpresult < 0) right = mid; else diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 06ad83d7cae..80cba2f4c26 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -966,9 +966,11 @@ record_cmp(FunctionCallInfo fcinfo) locfcinfo->args[0].isnull = false; locfcinfo->args[1].value = values2[i2]; locfcinfo->args[1].isnull = false; - locfcinfo->isnull = false; cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); + /* We don't expect comparison support functions to return null */ + Assert(!locfcinfo->isnull); + if (cmpresult < 0) { /* arg1 is less than arg2 */ @@ -1200,9 +1202,8 @@ record_eq(PG_FUNCTION_ARGS) locfcinfo->args[0].isnull = false; locfcinfo->args[1].value = values2[i2]; locfcinfo->args[1].isnull = false; - locfcinfo->isnull = false; oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); - if (!oprresult) + if (locfcinfo->isnull || !oprresult) { result = false; break; diff --git a/src/include/fmgr.h b/src/include/fmgr.h index a4249994b92..d349510b7c7 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -163,6 +163,11 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn); * caller must still check fcinfo->isnull! Also, if function is strict, * it is caller's responsibility to verify that no null arguments are present * before calling. + * + * Some code performs multiple calls without redoing InitFunctionCallInfoData, + * possibly altering the argument values. This is okay, but be sure to reset + * the fcinfo->isnull flag before each call, since callees are permitted to + * assume that starts out false. */ #define FunctionCallInvoke(fcinfo) ((* (fcinfo)->flinfo->fn_addr) (fcinfo))