diff options
Diffstat (limited to 'src/include/fmgr.h')
-rw-r--r-- | src/include/fmgr.h | 60 |
1 files changed, 43 insertions, 17 deletions
diff --git a/src/include/fmgr.h b/src/include/fmgr.h index ead17f0e442..ce652845253 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -35,7 +35,7 @@ typedef struct StringInfoData *fmStringInfo; * signature.) */ -typedef struct FunctionCallInfoData *FunctionCallInfo; +typedef struct FunctionCallInfoBaseData *FunctionCallInfo; typedef Datum (*PGFunction) (FunctionCallInfo fcinfo); @@ -46,8 +46,8 @@ typedef Datum (*PGFunction) (FunctionCallInfo fcinfo); * info struct saved for re-use. * * Note that fn_expr really is parse-time-determined information about the - * arguments, rather than about the function itself. But it's convenient - * to store it here rather than in FunctionCallInfoData, where it might more + * arguments, rather than about the function itself. But it's convenient to + * store it here rather than in FunctionCallInfoBaseData, where it might more * logically belong. * * fn_extra is available for use by the called function; all other fields @@ -73,8 +73,16 @@ typedef struct FmgrInfo * fields in whatever resultinfo points to. It should not change any other * fields. (In particular, scribbling on the argument arrays is a bad idea, * since some callers assume they can re-call with the same arguments.) + * + * Note that enough space for arguments needs to be provided, either by using + * SizeForFunctionCallInfo() in dynamic allocations, or by using + * LOCAL_FCINFO() for on-stack allocations. + * + * This struct is named *BaseData, rather than *Data, to break pre v12 code + * that allocated FunctionCallInfoData itself, as it'd often silently break + * old code due to no space for arguments being provided. */ -typedef struct FunctionCallInfoData +typedef struct FunctionCallInfoBaseData { FmgrInfo *flinfo; /* ptr to lookup info used for this call */ fmNodePtr context; /* pass info about context of call */ @@ -83,11 +91,31 @@ typedef struct FunctionCallInfoData #define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4 bool isnull; /* function must set true if result is NULL */ short nargs; /* # arguments actually passed */ -#define FIELDNO_FUNCTIONCALLINFODATA_ARG 6 - Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */ -#define FIELDNO_FUNCTIONCALLINFODATA_ARGNULL 7 - bool argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */ -} FunctionCallInfoData; +#define FIELDNO_FUNCTIONCALLINFODATA_ARGS 6 + NullableDatum args[FLEXIBLE_ARRAY_MEMBER]; +} FunctionCallInfoBaseData; + +/* + * Space needed for for a FunctionCallInfoBaseData struct with sufficient space + * for `nargs` arguments. + */ +#define SizeForFunctionCallInfo(nargs) \ + (offsetof(FunctionCallInfoBaseData, args) + \ + sizeof(NullableDatum) * (nargs)) + +/* + * This macro ensures that `name` points to a stack-allocated + * FunctionCallInfoBaseData struct with sufficient space for `nargs` arguments. + */ +#define LOCAL_FCINFO(name, nargs) \ + /* use union with FunctionCallInfoBaseData to guarantee alignment */ \ + union \ + { \ + FunctionCallInfoBaseData fcinfo; \ + /* ensure enough space for nargs args is available */ \ + char fcinfo_data[SizeForFunctionCallInfo(nargs)]; \ + } name##data; \ + FunctionCallInfo name = &name##data.fcinfo /* * This routine fills a FmgrInfo struct, given the OID @@ -116,11 +144,8 @@ extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, extern void fmgr_symbol(Oid functionId, char **mod, char **fn); /* - * This macro initializes all the fields of a FunctionCallInfoData except - * for the arg[] and argnull[] arrays. Performance testing has shown that - * the fastest way to set up argnull[] for small numbers of arguments is to - * explicitly set each required element to false, so we don't try to zero - * out the argnull[] array in the macro. + * This macro initializes all the fields of a FunctionCallInfoBaseData except + * for the args[] array. */ #define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo) \ do { \ @@ -133,7 +158,7 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn); } while (0) /* - * This macro invokes a function given a filled-in FunctionCallInfoData + * This macro invokes a function given a filled-in FunctionCallInfoBaseData * struct. The macro result is the returned Datum --- but note that * caller must still check fcinfo->isnull! Also, if function is strict, * it is caller's responsibility to verify that no null arguments are present @@ -176,7 +201,7 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn); * If function is not marked "proisstrict" in pg_proc, it must check for * null arguments using this macro. Do not try to GETARG a null argument! */ -#define PG_ARGISNULL(n) (fcinfo->argnull[n]) +#define PG_ARGISNULL(n) (fcinfo->args[n].isnull) /* * Support for fetching detoasted copies of toastable datatypes (all of @@ -235,7 +260,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum); /* Macros for fetching arguments of standard types */ -#define PG_GETARG_DATUM(n) (fcinfo->arg[n]) +#define PG_GETARG_DATUM(n) (fcinfo->args[n].value) #define PG_GETARG_INT32(n) DatumGetInt32(PG_GETARG_DATUM(n)) #define PG_GETARG_UINT32(n) DatumGetUInt32(PG_GETARG_DATUM(n)) #define PG_GETARG_INT16(n) DatumGetInt16(PG_GETARG_DATUM(n)) @@ -514,6 +539,7 @@ extern Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, * directly-computed parameter list. Note that neither arguments nor result * are allowed to be NULL. */ +extern Datum FunctionCall0Coll(FmgrInfo *flinfo, Oid collation); extern Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1); extern Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, |