diff options
author | Andres Freund | 2019-01-26 22:17:52 +0000 |
---|---|---|
committer | Andres Freund | 2019-01-26 22:17:52 +0000 |
commit | a9c35cf85ca1ff72f16f0f10d7ddee6e582b62b8 (patch) | |
tree | 4f34f2c902977a7ce0be7b1e32a12adf0cb223b7 /src/backend/utils | |
parent | 6d3ede5f1c654f923b2767b0b0c3b09569adaa18 (diff) |
Change function call information to be variable length.
Before this change FunctionCallInfoData, the struct arguments etc for
V1 function calls are stored in, always had space for
FUNC_MAX_ARGS/100 arguments, storing datums and their nullness in two
arrays. For nearly every function call 100 arguments is far more than
needed, therefore wasting memory. Arg and argnull being two separate
arrays also guarantees that to access a single argument, two
cachelines have to be touched.
Change the layout so there's a single variable-length array with pairs
of value / isnull. That drastically reduces memory consumption for
most function calls (on x86-64 a two argument function now uses
64bytes, previously 936 bytes), and makes it very likely that argument
value and its nullness are on the same cacheline.
Arguments are stored in a new NullableDatum struct, which, due to
padding, needs more memory per argument than before. But as usually
far fewer arguments are stored, and individual arguments are cheaper
to access, that's still a clear win. It's likely that there's other
places where conversion to NullableDatum arrays would make sense,
e.g. TupleTableSlots, but that's for another commit.
Because the function call information is now variable-length
allocations have to take the number of arguments into account. For
heap allocations that can be done with SizeForFunctionCallInfoData(),
for on-stack allocations there's a new LOCAL_FCINFO(name, nargs) macro
that helps to allocate an appropriately sized and aligned variable.
Some places with stack allocation function call information don't know
the number of arguments at compile time, and currently variably sized
stack allocations aren't allowed in postgres. Therefore allow for
FUNC_MAX_ARGS space in these cases. They're not that common, so for
now that seems acceptable.
Because of the need to allocate FunctionCallInfo of the appropriate
size, older extensions may need to update their code. To avoid subtle
breakages, the FunctionCallInfoData struct has been renamed to
FunctionCallInfoBaseData. Most code only references FunctionCallInfo,
so that shouldn't cause much collateral damage.
This change is also a prerequisite for more efficient expression JIT
compilation (by allocating the function call information on the stack,
allowing LLVM to optimize it away); previously the size of the call
information caused problems inside LLVM's optimizer.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/[email protected]
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 122 | ||||
-rw-r--r-- | src/backend/utils/adt/int.c | 20 | ||||
-rw-r--r-- | src/backend/utils/adt/oid.c | 20 | ||||
-rw-r--r-- | src/backend/utils/adt/rowtypes.c | 32 | ||||
-rw-r--r-- | src/backend/utils/fmgr/README | 23 | ||||
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 866 | ||||
-rw-r--r-- | src/backend/utils/sort/sortsupport.c | 15 |
7 files changed, 459 insertions, 639 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index e457d81f23c..a785361fd07 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3571,6 +3571,7 @@ array_contains_nulls(ArrayType *array) Datum array_eq(PG_FUNCTION_ARGS) { + LOCAL_FCINFO(locfcinfo, 2); AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0); AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1); Oid collation = PG_GET_COLLATION(); @@ -3590,7 +3591,6 @@ array_eq(PG_FUNCTION_ARGS) array_iter it1; array_iter it2; int i; - FunctionCallInfoData locfcinfo; if (element_type != AARR_ELEMTYPE(array2)) ereport(ERROR, @@ -3630,7 +3630,7 @@ array_eq(PG_FUNCTION_ARGS) /* * apply the operator to each pair of array elements. */ - InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2, collation, NULL, NULL); /* Loop over source data */ @@ -3666,12 +3666,12 @@ array_eq(PG_FUNCTION_ARGS) /* * Apply the operator to the element pair */ - locfcinfo.arg[0] = elt1; - locfcinfo.arg[1] = elt2; - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; - oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = elt1; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = elt2; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); if (!oprresult) { result = false; @@ -3742,6 +3742,7 @@ btarraycmp(PG_FUNCTION_ARGS) static int array_cmp(FunctionCallInfo fcinfo) { + LOCAL_FCINFO(locfcinfo, 2); AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0); AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1); Oid collation = PG_GET_COLLATION(); @@ -3761,7 +3762,6 @@ array_cmp(FunctionCallInfo fcinfo) array_iter it1; array_iter it2; int i; - FunctionCallInfoData locfcinfo; if (element_type != AARR_ELEMTYPE(array2)) ereport(ERROR, @@ -3794,7 +3794,7 @@ array_cmp(FunctionCallInfo fcinfo) /* * apply the operator to each pair of array elements. */ - InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2, collation, NULL, NULL); /* Loop over source data */ @@ -3833,12 +3833,12 @@ array_cmp(FunctionCallInfo fcinfo) } /* Compare the pair of elements */ - locfcinfo.arg[0] = elt1; - locfcinfo.arg[1] = elt2; - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; - cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = elt1; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = elt2; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); if (cmpresult == 0) continue; /* equal */ @@ -3913,6 +3913,7 @@ array_cmp(FunctionCallInfo fcinfo) Datum hash_array(PG_FUNCTION_ARGS) { + LOCAL_FCINFO(locfcinfo, 1); AnyArrayType *array = PG_GETARG_ANY_ARRAY_P(0); int ndims = AARR_NDIM(array); int *dims = AARR_DIMS(array); @@ -3925,7 +3926,6 @@ hash_array(PG_FUNCTION_ARGS) char typalign; int i; array_iter iter; - FunctionCallInfoData locfcinfo; /* * We arrange to look up the hash function only once per series of calls, @@ -3953,7 +3953,7 @@ hash_array(PG_FUNCTION_ARGS) /* * apply the hash function to each array element. */ - InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1, + InitFunctionCallInfoData(*locfcinfo, &typentry->hash_proc_finfo, 1, InvalidOid, NULL, NULL); /* Loop over source data */ @@ -3977,10 +3977,10 @@ hash_array(PG_FUNCTION_ARGS) else { /* Apply the hash function */ - locfcinfo.arg[0] = elt; - locfcinfo.argnull[0] = false; - locfcinfo.isnull = false; - elthash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = elt; + locfcinfo->args[0].isnull = false; + locfcinfo->isnull = false; + elthash = DatumGetUInt32(FunctionCallInvoke(locfcinfo)); } /* @@ -4010,6 +4010,7 @@ hash_array(PG_FUNCTION_ARGS) Datum hash_array_extended(PG_FUNCTION_ARGS) { + LOCAL_FCINFO(locfcinfo, 2); AnyArrayType *array = PG_GETARG_ANY_ARRAY_P(0); uint64 seed = PG_GETARG_INT64(1); int ndims = AARR_NDIM(array); @@ -4023,7 +4024,6 @@ hash_array_extended(PG_FUNCTION_ARGS) char typalign; int i; array_iter iter; - FunctionCallInfoData locfcinfo; typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra; if (typentry == NULL || @@ -4042,7 +4042,7 @@ hash_array_extended(PG_FUNCTION_ARGS) typbyval = typentry->typbyval; typalign = typentry->typalign; - InitFunctionCallInfoData(locfcinfo, &typentry->hash_extended_proc_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->hash_extended_proc_finfo, 2, InvalidOid, NULL, NULL); /* Loop over source data */ @@ -4065,12 +4065,11 @@ hash_array_extended(PG_FUNCTION_ARGS) else { /* Apply the hash function */ - locfcinfo.arg[0] = elt; - locfcinfo.arg[1] = Int64GetDatum(seed); - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; - elthash = DatumGetUInt64(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = elt; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = Int64GetDatum(seed); + locfcinfo->args[1].isnull = false; + elthash = DatumGetUInt64(FunctionCallInvoke(locfcinfo)); } result = (result << 5) - result + elthash; @@ -4100,6 +4099,7 @@ static bool array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, bool matchall, void **fn_extra) { + LOCAL_FCINFO(locfcinfo, 2); bool result = matchall; Oid element_type = AARR_ELEMTYPE(array1); TypeCacheEntry *typentry; @@ -4113,7 +4113,6 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, int i; int j; array_iter it1; - FunctionCallInfoData locfcinfo; if (element_type != AARR_ELEMTYPE(array2)) ereport(ERROR, @@ -4164,7 +4163,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, /* * Apply the comparison operator to each pair of array elements. */ - InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2, collation, NULL, NULL); /* Loop over source data */ @@ -4206,12 +4205,12 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, /* * Apply the operator to the element pair */ - locfcinfo.arg[0] = elt1; - locfcinfo.arg[1] = elt2; - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; - oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = elt1; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = elt2; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); if (oprresult) break; } @@ -6042,6 +6041,7 @@ array_replace_internal(ArrayType *array, bool remove, Oid collation, FunctionCallInfo fcinfo) { + LOCAL_FCINFO(locfcinfo, 2); ArrayType *result; Oid element_type; Datum *values; @@ -6062,7 +6062,6 @@ array_replace_internal(ArrayType *array, int bitmask; bool changed = false; TypeCacheEntry *typentry; - FunctionCallInfoData locfcinfo; element_type = ARR_ELEMTYPE(array); ndim = ARR_NDIM(array); @@ -6117,7 +6116,7 @@ array_replace_internal(ArrayType *array, } /* Prepare to apply the comparison operator */ - InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2, collation, NULL, NULL); /* Allocate temporary arrays for new values */ @@ -6175,12 +6174,12 @@ array_replace_internal(ArrayType *array, /* * Apply the operator to the element pair */ - locfcinfo.arg[0] = elt; - locfcinfo.arg[1] = search; - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; - oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = elt; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = search; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); if (!oprresult) { /* no match, keep element */ @@ -6457,10 +6456,10 @@ width_bucket_array_fixed(Datum operand, Oid collation, TypeCacheEntry *typentry) { + LOCAL_FCINFO(locfcinfo, 2); char *thresholds_data; int typlen = typentry->typlen; bool typbyval = typentry->typbyval; - FunctionCallInfoData locfcinfo; int left; int right; @@ -6470,7 +6469,7 @@ width_bucket_array_fixed(Datum operand, */ thresholds_data = (char *) ARR_DATA_PTR(thresholds); - InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2, collation, NULL, NULL); /* Find the bucket */ @@ -6484,13 +6483,13 @@ width_bucket_array_fixed(Datum operand, ptr = thresholds_data + mid * typlen; - locfcinfo.arg[0] = operand; - locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen); - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; + locfcinfo->args[0].value = 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)); + cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); if (cmpresult < 0) right = mid; @@ -6510,17 +6509,17 @@ width_bucket_array_variable(Datum operand, Oid collation, TypeCacheEntry *typentry) { + LOCAL_FCINFO(locfcinfo, 2); char *thresholds_data; int typlen = typentry->typlen; bool typbyval = typentry->typbyval; char typalign = typentry->typalign; - FunctionCallInfoData locfcinfo; int left; int right; thresholds_data = (char *) ARR_DATA_PTR(thresholds); - InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2, collation, NULL, NULL); /* Find the bucket */ @@ -6541,13 +6540,12 @@ width_bucket_array_variable(Datum operand, ptr = (char *) att_align_nominal(ptr, typalign); } - locfcinfo.arg[0] = operand; - locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen); - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; + locfcinfo->args[0].value = operand; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = fetch_att(ptr, typbyval, typlen); + locfcinfo->args[1].isnull = false; - cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo)); + cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); if (cmpresult < 0) right = mid; diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index fd82a83c47c..ad8e6d02ee4 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -201,8 +201,8 @@ int2vectorout(PG_FUNCTION_ARGS) Datum int2vectorrecv(PG_FUNCTION_ARGS) { + LOCAL_FCINFO(locfcinfo, 3); StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - FunctionCallInfoData locfcinfo; int2vector *result; /* @@ -211,19 +211,19 @@ int2vectorrecv(PG_FUNCTION_ARGS) * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo * parameter. */ - InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, + InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3, InvalidOid, NULL, NULL); - locfcinfo.arg[0] = PointerGetDatum(buf); - locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID); - locfcinfo.arg[2] = Int32GetDatum(-1); - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.argnull[2] = false; + locfcinfo->args[0].value = PointerGetDatum(buf); + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID); + locfcinfo->args[1].isnull = false; + locfcinfo->args[2].value = Int32GetDatum(-1); + locfcinfo->args[2].isnull = false; - result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo)); + result = (int2vector *) DatumGetPointer(array_recv(locfcinfo)); - Assert(!locfcinfo.isnull); + Assert(!locfcinfo->isnull); /* sanity checks: int2vector must be 1-D, 0-based, no nulls */ if (ARR_NDIM(result) != 1 || diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index eb21b078f40..bb67e014996 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -256,8 +256,8 @@ oidvectorout(PG_FUNCTION_ARGS) Datum oidvectorrecv(PG_FUNCTION_ARGS) { + LOCAL_FCINFO(locfcinfo, 3); StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - FunctionCallInfoData locfcinfo; oidvector *result; /* @@ -266,19 +266,19 @@ oidvectorrecv(PG_FUNCTION_ARGS) * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo * parameter. */ - InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, + InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3, InvalidOid, NULL, NULL); - locfcinfo.arg[0] = PointerGetDatum(buf); - locfcinfo.arg[1] = ObjectIdGetDatum(OIDOID); - locfcinfo.arg[2] = Int32GetDatum(-1); - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.argnull[2] = false; + locfcinfo->args[0].value = PointerGetDatum(buf); + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = ObjectIdGetDatum(OIDOID); + locfcinfo->args[1].isnull = false; + locfcinfo->args[2].value = Int32GetDatum(-1); + locfcinfo->args[2].isnull = false; - result = (oidvector *) DatumGetPointer(array_recv(&locfcinfo)); + result = (oidvector *) DatumGetPointer(array_recv(locfcinfo)); - Assert(!locfcinfo.isnull); + Assert(!locfcinfo->isnull); /* sanity checks: oidvector must be 1-D, 0-based, no nulls */ if (ARR_NDIM(result) != 1 || diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 0467f97dc3f..5bbf5686103 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -942,7 +942,7 @@ record_cmp(FunctionCallInfo fcinfo) */ if (!nulls1[i1] || !nulls2[i2]) { - FunctionCallInfoData locfcinfo; + LOCAL_FCINFO(locfcinfo, 2); int32 cmpresult; if (nulls1[i1]) @@ -959,14 +959,14 @@ record_cmp(FunctionCallInfo fcinfo) } /* Compare the pair of elements */ - InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2, collation, NULL, NULL); - locfcinfo.arg[0] = values1[i1]; - locfcinfo.arg[1] = values2[i2]; - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; - cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = values1[i1]; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].value = values2[i2]; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); if (cmpresult < 0) { @@ -1119,11 +1119,11 @@ record_eq(PG_FUNCTION_ARGS) i1 = i2 = j = 0; while (i1 < ncolumns1 || i2 < ncolumns2) { + LOCAL_FCINFO(locfcinfo, 2); Form_pg_attribute att1; Form_pg_attribute att2; TypeCacheEntry *typentry; Oid collation; - FunctionCallInfoData locfcinfo; bool oprresult; /* @@ -1193,14 +1193,14 @@ record_eq(PG_FUNCTION_ARGS) } /* Compare the pair of elements */ - InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, + InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2, collation, NULL, NULL); - locfcinfo.arg[0] = values1[i1]; - locfcinfo.arg[1] = values2[i2]; - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.isnull = false; - oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].value = values1[i1]; + 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) { result = false; diff --git a/src/backend/utils/fmgr/README b/src/backend/utils/fmgr/README index 5a2331ff159..a4d6a07bddc 100644 --- a/src/backend/utils/fmgr/README +++ b/src/backend/utils/fmgr/README @@ -53,7 +53,7 @@ point to the expression parse tree for the function call; this can be used to extract parse-time knowledge about the actual arguments. Note that this field really is information about the arguments rather than information about the function, but it's proven to be more convenient to keep it in -FmgrInfo than in FunctionCallInfoData where it might more logically go. +FmgrInfo than in FunctionCallInfoBaseData where it might more logically go. During a call of a function, the following data structure is created @@ -67,10 +67,9 @@ typedef struct Oid fncollation; /* collation for function to use */ bool isnull; /* function must set true if result is NULL */ short nargs; /* # arguments actually passed */ - Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */ - bool argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */ -} FunctionCallInfoData; -typedef FunctionCallInfoData* FunctionCallInfo; + NullableDatum args[]; /* Arguments passed to function */ +} FunctionCallInfoBaseData; +typedef FunctionCallInfoBaseData* FunctionCallInfo; flinfo points to the lookup info used to make the call. Ordinary functions will probably ignore this field, but function class handlers will need it @@ -97,24 +96,24 @@ when there are no inputs of collatable types or they don't share a common collation. This is effectively a hidden additional argument, which collation-sensitive functions can use to determine their behavior. -nargs, arg[], and argnull[] hold the arguments being passed to the function. +nargs and args[] hold the arguments being passed to the function. Notice that all the arguments passed to a function (as well as its result value) will now uniformly be of type Datum. As discussed below, callers and callees should apply the standard Datum-to-and-from-whatever macros to convert to the actual argument types of a particular function. The -value in arg[i] is unspecified when argnull[i] is true. +value in args[i].value is unspecified when args[i].isnull is true. It is generally the responsibility of the caller to ensure that the number of arguments passed matches what the callee is expecting; except for callees that take a variable number of arguments, the callee will -typically ignore the nargs field and just grab values from arg[]. +typically ignore the nargs field and just grab values from args[]. The isnull field will be initialized to "false" before the call. On return from the function, isnull is the null flag for the function result: if it is true the function's result is NULL, regardless of the actual function return value. Note that simple "strict" functions can ignore -both isnull and argnull[], since they won't even get called when there -are any TRUE values in argnull[]. +both isnull and args[i].isnull, since they won't even get called when there +are any TRUE values in args[].isnull. FunctionCallInfo replaces FmgrValues plus a bunch of ad-hoc parameter conventions, global variables (fmgr_pl_finfo and CurrentTriggerData at @@ -157,7 +156,7 @@ again, it might come in handy to have this macro in place. A nonstrict function is responsible for checking whether each individual argument is null or not, which it can do with PG_ARGISNULL(n) (which is -just "fcinfo->argnull[n]"). It should avoid trying to fetch the value +just "fcinfo->args[n].isnull"). It should avoid trying to fetch the value of any argument that is null. Both strict and nonstrict functions can return NULL, if needed, with @@ -171,7 +170,7 @@ Argument values are ordinarily fetched using code like For float4, float8, and int8, the PG_GETARG macros will hide whether the types are pass-by-value or pass-by-reference. For example, if float8 is pass-by-reference then PG_GETARG_FLOAT8 expands to - (* (float8 *) DatumGetPointer(fcinfo->arg[number])) + (* (float8 *) DatumGetPointer(fcinfo->args[number].value)) and would typically be called like this: float8 arg = PG_GETARG_FLOAT8(0); For what are now historical reasons, the float-related typedefs and macros diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 506eeef01c3..ead8b371a73 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -792,18 +792,18 @@ fmgr_security_definer(PG_FUNCTION_ARGS) Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 1); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 1, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, NULL, 1, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.argnull[0] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -812,20 +812,20 @@ DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1) Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 2); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 2, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, NULL, 2, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -835,22 +835,22 @@ Datum DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 3); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 3, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, NULL, 3, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -860,24 +860,24 @@ Datum DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 4); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 4, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, NULL, 4, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -887,26 +887,26 @@ Datum DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 5); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 5, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, NULL, 5, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -917,28 +917,28 @@ DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 6); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 6, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, NULL, 6, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -949,30 +949,30 @@ DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 7); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 7, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - - result = (*func) (&fcinfo); + InitFunctionCallInfoData(*fcinfo, NULL, 7, collation, NULL, NULL); + + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].value = arg7; + fcinfo->args[6].isnull = false; + + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -983,32 +983,32 @@ DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 8); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 8, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.arg[7] = arg8; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - fcinfo.argnull[7] = false; - - result = (*func) (&fcinfo); + InitFunctionCallInfoData(*fcinfo, NULL, 8, collation, NULL, NULL); + + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].value = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].value = arg8; + fcinfo->args[7].isnull = false; + + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -1020,34 +1020,34 @@ DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg6, Datum arg7, Datum arg8, Datum arg9) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 9); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 9, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.arg[7] = arg8; - fcinfo.arg[8] = arg9; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - fcinfo.argnull[7] = false; - fcinfo.argnull[8] = false; - - result = (*func) (&fcinfo); + InitFunctionCallInfoData(*fcinfo, NULL, 9, collation, NULL, NULL); + + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].value = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].value = arg8; + fcinfo->args[7].isnull = false; + fcinfo->args[8].value = arg9; + fcinfo->args[8].isnull = false; + + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -1065,18 +1065,18 @@ DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 1); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.argnull[0] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -1085,20 +1085,20 @@ CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 2); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; - result = (*func) (&fcinfo); + result = (*func) (fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result; @@ -1110,21 +1110,38 @@ CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum * are allowed to be NULL. */ Datum +FunctionCall0Coll(FmgrInfo *flinfo, Oid collation) +{ + LOCAL_FCINFO(fcinfo, 0); + Datum result; + + InitFunctionCallInfoData(*fcinfo, flinfo, 0, collation, NULL, NULL); + + result = FunctionCallInvoke(fcinfo); + + /* Check for null result, since caller is clearly not expecting one */ + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); + + return result; +} + +Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 1); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.argnull[0] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1132,21 +1149,21 @@ FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1) Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 2); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1155,23 +1172,23 @@ Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 3); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 3, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 3, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1180,25 +1197,25 @@ Datum FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 4); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 4, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 4, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1207,27 +1224,27 @@ Datum FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 5); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 5, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 5, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1237,29 +1254,29 @@ FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 6); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 6, collation, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 6, collation, NULL, NULL); - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1269,31 +1286,31 @@ FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 7); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 7, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - - result = FunctionCallInvoke(&fcinfo); + InitFunctionCallInfoData(*fcinfo, flinfo, 7, collation, NULL, NULL); + + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].value = arg7; + fcinfo->args[6].isnull = false; + + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1303,33 +1320,33 @@ FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 8); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 8, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.arg[7] = arg8; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - fcinfo.argnull[7] = false; - - result = FunctionCallInvoke(&fcinfo); + InitFunctionCallInfoData(*fcinfo, flinfo, 8, collation, NULL, NULL); + + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].value = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].value = arg8; + fcinfo->args[7].isnull = false; + + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1340,35 +1357,35 @@ FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg6, Datum arg7, Datum arg8, Datum arg9) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 9); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 9, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.arg[7] = arg8; - fcinfo.arg[8] = arg9; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - fcinfo.argnull[7] = false; - fcinfo.argnull[8] = false; - - result = FunctionCallInvoke(&fcinfo); + InitFunctionCallInfoData(*fcinfo, flinfo, 9, collation, NULL, NULL); + + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].value = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].value = arg8; + fcinfo->args[7].isnull = false; + fcinfo->args[8].value = arg9; + fcinfo->args[8].isnull = false; + + result = FunctionCallInvoke(fcinfo); /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", flinfo->fn_oid); return result; } @@ -1385,68 +1402,30 @@ Datum OidFunctionCall0Coll(Oid functionId, Oid collation) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 0, collation, NULL, NULL); - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall0Coll(&flinfo, collation); } Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 1, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.argnull[0] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall1Coll(&flinfo, collation, arg1); } Datum OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 2, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall2Coll(&flinfo, collation, arg1, arg2); } Datum @@ -1454,27 +1433,10 @@ OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 3, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall3Coll(&flinfo, collation, arg1, arg2, arg3); } Datum @@ -1482,29 +1444,10 @@ OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 4, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall4Coll(&flinfo, collation, arg1, arg2, arg3, arg4); } Datum @@ -1512,31 +1455,10 @@ OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 5, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall5Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5); } Datum @@ -1545,33 +1467,11 @@ OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg6) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 6, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall6Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5, + arg6); } Datum @@ -1580,35 +1480,11 @@ OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg6, Datum arg7) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 7, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall7Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5, + arg6, arg7); } Datum @@ -1617,37 +1493,11 @@ OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg6, Datum arg7, Datum arg8) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 8, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.arg[7] = arg8; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - fcinfo.argnull[7] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall8Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5, + arg6, arg7, arg8); } Datum @@ -1657,39 +1507,11 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg9) { FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum result; fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 9, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.arg[2] = arg3; - fcinfo.arg[3] = arg4; - fcinfo.arg[4] = arg5; - fcinfo.arg[5] = arg6; - fcinfo.arg[6] = arg7; - fcinfo.arg[7] = arg8; - fcinfo.arg[8] = arg9; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; - fcinfo.argnull[3] = false; - fcinfo.argnull[4] = false; - fcinfo.argnull[5] = false; - fcinfo.argnull[6] = false; - fcinfo.argnull[7] = false; - fcinfo.argnull[8] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", flinfo.fn_oid); - - return result; + return FunctionCall9Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5, + arg6, arg7, arg8, arg9); } @@ -1708,35 +1530,35 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 3); Datum result; if (str == NULL && flinfo->fn_strict) return (Datum) 0; /* just return null result */ - InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL); - fcinfo.arg[0] = CStringGetDatum(str); - fcinfo.arg[1] = ObjectIdGetDatum(typioparam); - fcinfo.arg[2] = Int32GetDatum(typmod); - fcinfo.argnull[0] = (str == NULL); - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; + fcinfo->args[0].value = CStringGetDatum(str); + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = ObjectIdGetDatum(typioparam); + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = Int32GetDatum(typmod); + fcinfo->args[2].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Should get null result if and only if str is NULL */ if (str == NULL) { - if (!fcinfo.isnull) + if (!fcinfo->isnull) elog(ERROR, "input function %u returned non-NULL", - fcinfo.flinfo->fn_oid); + flinfo->fn_oid); } else { - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "input function %u returned NULL", - fcinfo.flinfo->fn_oid); + flinfo->fn_oid); } return result; @@ -1767,35 +1589,35 @@ Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod) { - FunctionCallInfoData fcinfo; + LOCAL_FCINFO(fcinfo, 3); Datum result; if (buf == NULL && flinfo->fn_strict) return (Datum) 0; /* just return null result */ - InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL); - fcinfo.arg[0] = PointerGetDatum(buf); - fcinfo.arg[1] = ObjectIdGetDatum(typioparam); - fcinfo.arg[2] = Int32GetDatum(typmod); - fcinfo.argnull[0] = (buf == NULL); - fcinfo.argnull[1] = false; - fcinfo.argnull[2] = false; + fcinfo->args[0].value = PointerGetDatum(buf); + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = ObjectIdGetDatum(typioparam); + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = Int32GetDatum(typmod); + fcinfo->args[2].isnull = false; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); /* Should get null result if and only if buf is NULL */ if (buf == NULL) { - if (!fcinfo.isnull) + if (!fcinfo->isnull) elog(ERROR, "receive function %u returned non-NULL", - fcinfo.flinfo->fn_oid); + flinfo->fn_oid); } else { - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "receive function %u returned NULL", - fcinfo.flinfo->fn_oid); + flinfo->fn_oid); } return result; diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c index e2100da266a..9a771214dc2 100644 --- a/src/backend/utils/sort/sortsupport.c +++ b/src/backend/utils/sort/sortsupport.c @@ -26,16 +26,17 @@ /* Info needed to use an old-style comparison function as a sort comparator */ typedef struct { - FunctionCallInfoData fcinfo; /* reusable callinfo structure */ FmgrInfo flinfo; /* lookup data for comparison function */ + FunctionCallInfoBaseData fcinfo; /* reusable callinfo structure */ } SortShimExtra; +#define SizeForSortShimExtra(nargs) (offsetof(SortShimExtra, fcinfo) + SizeForFunctionCallInfo(nargs)) /* * Shim function for calling an old-style comparator * * This is essentially an inlined version of FunctionCall2Coll(), except - * we assume that the FunctionCallInfoData was already mostly set up by + * we assume that the FunctionCallInfoBaseData was already mostly set up by * PrepareSortSupportComparisonShim. */ static int @@ -44,8 +45,8 @@ comparison_shim(Datum x, Datum y, SortSupport ssup) SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra; Datum result; - extra->fcinfo.arg[0] = x; - extra->fcinfo.arg[1] = y; + extra->fcinfo.args[0].value = x; + extra->fcinfo.args[1].value = y; /* just for paranoia's sake, we reset isnull each time */ extra->fcinfo.isnull = false; @@ -69,7 +70,7 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup) SortShimExtra *extra; extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt, - sizeof(SortShimExtra)); + SizeForSortShimExtra(2)); /* Lookup the comparison function */ fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt); @@ -77,8 +78,8 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup) /* We can initialize the callinfo just once and re-use it */ InitFunctionCallInfoData(extra->fcinfo, &extra->flinfo, 2, ssup->ssup_collation, NULL, NULL); - extra->fcinfo.argnull[0] = false; - extra->fcinfo.argnull[1] = false; + extra->fcinfo.args[0].isnull = false; + extra->fcinfo.args[1].isnull = false; ssup->ssup_extra = extra; ssup->comparator = comparison_shim; |