summaryrefslogtreecommitdiff
path: root/src/include/fmgr.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/fmgr.h')
-rw-r--r--src/include/fmgr.h60
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,