forked from huawei/openGauss-server
940 lines
44 KiB
C++
Executable File
940 lines
44 KiB
C++
Executable File
/* -------------------------------------------------------------------------
|
|
*
|
|
* fmgr.h
|
|
* Definitions for the Postgres function manager and function-call
|
|
* interface.
|
|
*
|
|
* This file must be included by all Postgres modules that either define
|
|
* or call fmgr-callable functions.
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/fmgr.h
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
#ifndef FMGR_H
|
|
#define FMGR_H
|
|
|
|
#include "postgres.h"
|
|
#include "lib/stringinfo.h"
|
|
|
|
/* We don't want to include primnodes.h here, so make a stub reference */
|
|
typedef struct Node* fmNodePtr;
|
|
class ScalarVector;
|
|
|
|
/* Likewise, avoid including stringinfo.h here */
|
|
typedef struct StringInfoData* fmStringInfo;
|
|
|
|
struct FunctionCallInfoData;
|
|
|
|
struct Cursor_Data;
|
|
|
|
typedef Datum (*UDFArgsFuncType)(FunctionCallInfoData* fcinfo, int idx, Datum val);
|
|
|
|
/*
|
|
* All functions that can be called directly by fmgr must have this signature.
|
|
* (Other functions can be called by using a handler that does have this
|
|
* signature.)
|
|
*/
|
|
|
|
typedef struct FunctionCallInfoData* FunctionCallInfo;
|
|
|
|
typedef Datum (*PGFunction)(FunctionCallInfo fcinfo);
|
|
|
|
typedef ScalarVector* (*VectorFunction)(FunctionCallInfo fcinfo);
|
|
typedef Datum (*GenericArgExtract)(Datum* data);
|
|
|
|
extern void InitFuncCallUDFInfo(FunctionCallInfoData* fcinfo, int argN, bool setFuncPtr);
|
|
extern void InitFunctionCallUDFArgs(FunctionCallInfoData* fcinfo, int argN, int batchRows);
|
|
extern void FreeFuncCallUDFInfo(FunctionCallInfoData* Fcinfo);
|
|
|
|
#define VECTOR_GENERIC_FUNCTION_PREALLOCED_ARGS 32
|
|
#define VECTOR_GENERIC_FUNCTION_INCREMENTAL_ARGS 10
|
|
|
|
struct GenericFunRuntimeArg {
|
|
ScalarVector** arg;
|
|
Oid argType;
|
|
GenericArgExtract getArgFun;
|
|
};
|
|
|
|
struct GenericFunRuntime {
|
|
/* maxium number of the arguements can be stored */
|
|
uint16 compacity;
|
|
|
|
/* pointer to the address of the real arg */
|
|
GenericFunRuntimeArg* args;
|
|
Datum* inputargs;
|
|
bool* nulls;
|
|
|
|
bool restrictFlag[BatchMaxSize];
|
|
FunctionCallInfoData* internalFinfo;
|
|
};
|
|
/*
|
|
* This struct holds the system-catalog information that must be looked up
|
|
* before a function can be called through fmgr. If the same function is
|
|
* to be called multiple times, the lookup need be done only once and the
|
|
* 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
|
|
* logically belong.
|
|
*/
|
|
typedef struct FmgrInfo {
|
|
PGFunction fn_addr; /* pointer to function or handler to be called */
|
|
Oid fn_oid; /* OID of function (NOT of handler, if any) */
|
|
short fn_nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable arg
|
|
* count */
|
|
bool fn_strict; /* function is "strict" (NULL in => NULL out) */
|
|
bool fn_retset; /* function returns a set */
|
|
unsigned char fn_stats; /* collect stats if track_functions > this */
|
|
void* fn_extra; /* extra space for use by handler */
|
|
MemoryContext fn_mcxt; /* memory context to store fn_extra in */
|
|
fmNodePtr fn_expr; /* expression parse tree for call, or NULL */
|
|
Oid fn_rettype; // Oid of function return type
|
|
char fnName[NAMEDATALEN]; /* function name */
|
|
char* fnLibPath; /* library path for c-udf
|
|
* package.class.method(args) for java-udf */
|
|
bool fn_fenced;
|
|
Oid fn_languageId; /* function language id*/
|
|
char fn_volatile; /* procvolatile */
|
|
// Vector Function
|
|
VectorFunction vec_fn_addr;
|
|
VectorFunction* vec_fn_cache;
|
|
GenericFunRuntime* genericRuntime;
|
|
} FmgrInfo;
|
|
|
|
/* number of prealloced arguments to a function. */
|
|
#define FUNC_PREALLOCED_ARGS 10
|
|
|
|
typedef struct UDFInfoType {
|
|
UDFArgsFuncType* UDFArgsHandlerPtr; /* UDF send/recv argument function */
|
|
UDFArgsFuncType UDFResultHandlerPtr;
|
|
StringInfo udfMsgBuf;
|
|
char* msgReadPtr;
|
|
int argBatchRows;
|
|
int allocRows;
|
|
Datum** arg;
|
|
bool** null;
|
|
Datum* result;
|
|
bool* resultIsNull;
|
|
bool valid_UDFArgsHandlerPtr; /* True if funcUDFArgs are filled ok */
|
|
|
|
UDFInfoType()
|
|
{
|
|
udfMsgBuf = NULL;
|
|
msgReadPtr = NULL;
|
|
arg = NULL;
|
|
null = NULL;
|
|
result = NULL;
|
|
resultIsNull = NULL;
|
|
UDFArgsHandlerPtr = NULL;
|
|
valid_UDFArgsHandlerPtr = false;
|
|
allocRows = 0;
|
|
argBatchRows = 0;
|
|
}
|
|
} UDFInfoType;
|
|
|
|
typedef struct RefcusorInfoData {
|
|
Cursor_Data* argCursor;
|
|
Cursor_Data* returnCursor;
|
|
int return_number;
|
|
} RefcusorInfoData;
|
|
|
|
/*
|
|
* This struct is the data actually passed to an fmgr-called function.
|
|
*/
|
|
typedef struct FunctionCallInfoData {
|
|
FmgrInfo* flinfo; /* ptr to lookup info used for this call */
|
|
fmNodePtr context; /* pass info about context of call */
|
|
fmNodePtr resultinfo; /* pass or return extra info about result */
|
|
Oid fncollation; /* collation for function to use */
|
|
bool isnull; /* function must set true if result is NULL */
|
|
short nargs; /* # arguments actually passed */
|
|
Datum* arg; /* Arguments passed to function */
|
|
bool* argnull; /* T if arg[i] is actually NULL */
|
|
Oid* argTypes; /* Argument type */
|
|
Datum prealloc_arg[FUNC_PREALLOCED_ARGS]; /* prealloced arguments.*/
|
|
bool prealloc_argnull[FUNC_PREALLOCED_ARGS]; /* prealloced argument null flags.*/
|
|
Oid prealloc_argTypes[FUNC_PREALLOCED_ARGS]; /* prealloced argument type */
|
|
ScalarVector* argVector; /*Scalar Vector */
|
|
RefcusorInfoData refcursor_data;
|
|
UDFInfoType udfInfo;
|
|
|
|
FunctionCallInfoData()
|
|
{
|
|
flinfo = NULL;
|
|
arg = NULL;
|
|
argnull = NULL;
|
|
argTypes = NULL;
|
|
argVector = NULL;
|
|
}
|
|
} FunctionCallInfoData;
|
|
|
|
/*
|
|
* List of dynamically loaded files (kept in malloc'd memory).
|
|
*/
|
|
|
|
typedef struct df_files {
|
|
struct df_files* next; /* List link */
|
|
dev_t device; /* Device file is on */
|
|
#ifndef WIN32 /* ensures we never again depend on this under \
|
|
* win32 */
|
|
ino_t inode; /* Inode number of file */
|
|
#endif
|
|
void* handle; /* a handle for pg_dl* functions */
|
|
char filename[FLEXIBLE_ARRAY_MEMBER]; /* Full pathname of file */
|
|
|
|
/*
|
|
* we allocate the block big enough for actual length of pathname.
|
|
* filename[] must be last item in struct!
|
|
*/
|
|
} DynamicFileList;
|
|
|
|
/*Introduced to judge whether PG_init has done or not*/
|
|
typedef struct df_files_init {
|
|
struct df_files_init* next; /*List Link*/
|
|
DynamicFileList* file_list; /*restore file_list in the linked list*/
|
|
} FileListInit;
|
|
|
|
extern DynamicFileList* file_list;
|
|
extern DynamicFileList* file_tail;
|
|
|
|
#define EXTRA_NARGS 3
|
|
|
|
extern bool file_exists(const char* name);
|
|
/*
|
|
* This routine fills a FmgrInfo struct, given the OID
|
|
* of the function to be called.
|
|
*/
|
|
extern void fmgr_info(Oid functionId, FmgrInfo* finfo);
|
|
|
|
/*
|
|
* Same, when the FmgrInfo struct is in a memory context longer-lived than
|
|
* CurrentMemoryContext. The specified context will be set as fn_mcxt
|
|
* and used to hold all subsidiary data of finfo.
|
|
*/
|
|
extern void fmgr_info_cxt(Oid functionId, FmgrInfo* finfo, MemoryContext mcxt);
|
|
|
|
extern void InitVecFunctionCallInfoData(
|
|
FunctionCallInfoData* Fcinfo, FmgrInfo* Flinfo, int Nargs, Oid Collation, fmNodePtr Context, fmNodePtr Resultinfo);
|
|
|
|
/* Convenience macro for setting the fn_expr field */
|
|
#define fmgr_info_set_expr(expr, finfo) ((finfo)->fn_expr = (expr))
|
|
|
|
/*
|
|
* Copy an FmgrInfo struct
|
|
*/
|
|
extern void fmgr_info_copy(FmgrInfo* dstinfo, FmgrInfo* srcinfo, MemoryContext destcxt);
|
|
|
|
/*
|
|
* This macro initializes all the fields of a GenericFunRuntime except
|
|
* for the all the prealloc arrays. Performance testing has shown that
|
|
* the fastest way to set up static arrays for small numbers of arguments is to
|
|
* explicitly set each required element to false, so we don't try to zero
|
|
* out the static prealloc array in the macro.
|
|
*/
|
|
|
|
#define InitGenericFunRuntimeInfo(GenericRuntime, Nargs) \
|
|
do { \
|
|
(GenericRuntime).compacity = VECTOR_GENERIC_FUNCTION_PREALLOCED_ARGS; \
|
|
if (unlikely((Nargs) > VECTOR_GENERIC_FUNCTION_PREALLOCED_ARGS)) { \
|
|
(GenericRuntime).compacity += \
|
|
(((Nargs)-VECTOR_GENERIC_FUNCTION_PREALLOCED_ARGS - 1) / VECTOR_GENERIC_FUNCTION_INCREMENTAL_ARGS + \
|
|
1) * \
|
|
VECTOR_GENERIC_FUNCTION_INCREMENTAL_ARGS; \
|
|
} \
|
|
(GenericRuntime).args = \
|
|
(GenericFunRuntimeArg*)palloc0(sizeof(GenericFunRuntimeArg) * (GenericRuntime).compacity); \
|
|
(GenericRuntime).inputargs = (Datum*)palloc0(sizeof(Datum) * (GenericRuntime).compacity); \
|
|
(GenericRuntime).nulls = (bool*)palloc0(sizeof(bool) * (GenericRuntime).compacity); \
|
|
} while (0)
|
|
|
|
#define FreeGenericFunRuntimeInfo(GenericRuntime) \
|
|
do { \
|
|
pfree_ext((GenericRuntime).args); \
|
|
pfree_ext((GenericRuntime).inputargs); \
|
|
pfree_ext((GenericRuntime).nulls); \
|
|
if (unlikely((GenericRuntime).internalFinfo != NULL)) \
|
|
FreeFunctionCallInfoData(*((GenericRuntime).internalFinfo)); \
|
|
(GenericRuntime).compacity = 0; \
|
|
} while (0)
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
#define InitFunctionCallInfoArgs(Fcinfo, Nargs, batchRow) \
|
|
do { \
|
|
(Fcinfo).nargs = (Nargs); \
|
|
if ((Nargs) > FUNC_PREALLOCED_ARGS) { \
|
|
(Fcinfo).arg = (Datum*)palloc0((Nargs) * sizeof(Datum)); \
|
|
(Fcinfo).argnull = (bool*)palloc0(Nargs * sizeof(bool)); \
|
|
(Fcinfo).argTypes = (Oid*)palloc0((Nargs) * sizeof(Oid)); \
|
|
} else { \
|
|
(Fcinfo).arg = (Fcinfo).prealloc_arg; \
|
|
(Fcinfo).argnull = (Fcinfo).prealloc_argnull; \
|
|
(Fcinfo).argTypes = (Fcinfo).prealloc_argTypes; \
|
|
} \
|
|
if (unlikely((Fcinfo).flinfo && (Fcinfo).flinfo->fn_fenced)) \
|
|
InitFunctionCallUDFArgs(&(Fcinfo), (Nargs), (batchRow)); \
|
|
} while (0)
|
|
|
|
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo) \
|
|
do { \
|
|
(Fcinfo).flinfo = (Flinfo); \
|
|
(Fcinfo).context = (Context); \
|
|
(Fcinfo).resultinfo = (Resultinfo); \
|
|
(Fcinfo).fncollation = (Collation); \
|
|
(Fcinfo).isnull = false; \
|
|
(Fcinfo).nargs = (Nargs); \
|
|
if ((Nargs) > FUNC_PREALLOCED_ARGS) { \
|
|
(Fcinfo).arg = (Datum*)palloc0((Nargs) * sizeof(Datum)); \
|
|
(Fcinfo).argnull = (bool*)palloc0((Nargs) * sizeof(bool)); \
|
|
(Fcinfo).argTypes = (Oid*)palloc0((Nargs) * sizeof(Oid)); \
|
|
} else { \
|
|
(Fcinfo).arg = (Fcinfo).prealloc_arg; \
|
|
(Fcinfo).argnull = (Fcinfo).prealloc_argnull; \
|
|
(Fcinfo).argTypes = (Fcinfo).prealloc_argTypes; \
|
|
} \
|
|
if (unlikely((Flinfo) != NULL && (Fcinfo).flinfo->fn_fenced)) \
|
|
InitFuncCallUDFInfo(&(Fcinfo), (Nargs), false); \
|
|
(Fcinfo).refcursor_data.argCursor = NULL; \
|
|
(Fcinfo).refcursor_data.returnCursor = NULL; \
|
|
(Fcinfo).refcursor_data.return_number = 0; \
|
|
} while (0)
|
|
|
|
#define FreeFunctionCallInfoData(Fcinfo) \
|
|
do { \
|
|
if ((Fcinfo).nargs > FUNC_PREALLOCED_ARGS) { \
|
|
pfree((Fcinfo).arg); \
|
|
pfree((Fcinfo).argnull); \
|
|
pfree((Fcinfo).argTypes); \
|
|
(Fcinfo).argTypes = NULL; \
|
|
(Fcinfo).arg = NULL; \
|
|
(Fcinfo).argnull = NULL; \
|
|
} \
|
|
FreeFuncCallUDFInfo(&(Fcinfo)); \
|
|
} while (0)
|
|
/*
|
|
* This macro invokes a function given a filled-in FunctionCallInfoData
|
|
* 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
|
|
* before calling.
|
|
*/
|
|
#define FunctionCallInvoke(fcinfo) ((*(fcinfo)->flinfo->fn_addr)(fcinfo))
|
|
|
|
#define VecFunctionCallInvoke(fcinfo) ((*(fcinfo)->flinfo->vec_fn_addr)(fcinfo))
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Support macros to ease writing fmgr-compatible functions
|
|
*
|
|
* A C-coded fmgr-compatible function should be declared as
|
|
*
|
|
* Datum
|
|
* function_name(PG_FUNCTION_ARGS)
|
|
* {
|
|
* ...
|
|
* }
|
|
*
|
|
* It should access its arguments using appropriate PG_GETARG_xxx macros
|
|
* and should return its result using PG_RETURN_xxx.
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* Standard parameter list for fmgr-compatible functions */
|
|
#define PG_FUNCTION_ARGS FunctionCallInfo fcinfo
|
|
|
|
/*
|
|
* Get collation function should use.
|
|
*/
|
|
#define PG_GET_COLLATION() (fcinfo->fncollation)
|
|
|
|
/*
|
|
* Get number of arguments passed to function.
|
|
*/
|
|
#define PG_NARGS() (fcinfo->nargs)
|
|
|
|
/*
|
|
* 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])
|
|
|
|
/*
|
|
* Support for fetching detoasted copies of toastable datatypes (all of
|
|
* which are varlena types). pg_detoast_datum() gives you either the input
|
|
* datum (if not toasted) or a detoasted copy allocated with palloc().
|
|
* pg_detoast_datum_copy() always gives you a palloc'd copy --- use it
|
|
* if you need a modifiable copy of the input. Caller is expected to have
|
|
* checked for null inputs first, if necessary.
|
|
*
|
|
* pg_detoast_datum_packed() will return packed (1-byte header) datums
|
|
* unmodified. It will still expand an externally toasted or compressed datum.
|
|
* The resulting datum can be accessed using VARSIZE_ANY() and VARDATA_ANY()
|
|
* (beware of multiple evaluations in those macros!)
|
|
*
|
|
* WARNING: It is only safe to use pg_detoast_datum_packed() and
|
|
* VARDATA_ANY() if you really don't care about the alignment. Either because
|
|
* you're working with something like text where the alignment doesn't matter
|
|
* or because you're not going to access its constituent parts and just use
|
|
* things like memcpy on it anyways.
|
|
*
|
|
* Note: it'd be nice if these could be macros, but I see no way to do that
|
|
* without evaluating the arguments multiple times, which is NOT acceptable.
|
|
*/
|
|
extern struct varlena* pg_detoast_datum(struct varlena* datum);
|
|
extern struct varlena* pg_detoast_datum_copy(struct varlena* datum);
|
|
extern struct varlena* pg_detoast_datum_slice(struct varlena* datum, int32 first, int32 count);
|
|
extern struct varlena* pg_detoast_datum_packed(struct varlena* datum);
|
|
|
|
#define PG_DETOAST_DATUM(datum) pg_detoast_datum((struct varlena*)DatumGetPointer(datum))
|
|
#define PG_DETOAST_DATUM_COPY(datum) pg_detoast_datum_copy((struct varlena*)DatumGetPointer(datum))
|
|
#define PG_DETOAST_DATUM_SLICE(datum, f, c) \
|
|
pg_detoast_datum_slice((struct varlena*)DatumGetPointer(datum), (int32)(f), (int32)(c))
|
|
/* WARNING -- unaligned pointer */
|
|
#define PG_DETOAST_DATUM_PACKED(datum) pg_detoast_datum_packed((struct varlena*)DatumGetPointer(datum))
|
|
|
|
/*
|
|
* Support for cleaning up detoasted copies of inputs. This must only
|
|
* be used for pass-by-ref datatypes, and normally would only be used
|
|
* for toastable types. If the given pointer is different from the
|
|
* original argument, assume it's a palloc'd detoasted copy, and pfree it.
|
|
* NOTE: most functions on toastable types do not have to worry about this,
|
|
* but we currently require that support functions for indexes not leak
|
|
* memory.
|
|
*/
|
|
#define PG_FREE_IF_COPY(ptr, n) \
|
|
do { \
|
|
if ((Pointer)(ptr) != PG_GETARG_POINTER(n)) \
|
|
pfree(ptr); \
|
|
} while (0)
|
|
|
|
/* Macros for fetching arguments of standard types */
|
|
|
|
#define PG_GETARG_DATUM(n) (fcinfo->arg[n])
|
|
#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))
|
|
#define PG_GETARG_UINT16(n) DatumGetUInt16(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_INT8(n) DatumGetInt8(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_UINT8(n) DatumGetUInt8(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_CHAR(n) DatumGetChar(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_BOOL(n) DatumGetBool(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_OID(n) DatumGetObjectId(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_POINTER(n) DatumGetPointer(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_CSTRING(n) DatumGetCString(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_NAME(n) DatumGetName(PG_GETARG_DATUM(n))
|
|
/* these macros hide the pass-by-reference-ness of the datatype: */
|
|
#define PG_GETARG_FLOAT4(n) DatumGetFloat4(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_FLOAT8(n) DatumGetFloat8(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_INT64(n) DatumGetInt64(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_TRANSACTIONID(n) DatumGetTransactionId(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_SHORTTRANSACTIONID(n) DatumGetShortTransactionId(PG_GETARG_DATUM(n))
|
|
/* use this if you want the raw, possibly-toasted input datum: */
|
|
#define PG_GETARG_RAW_VARLENA_P(n) ((struct varlena*)PG_GETARG_POINTER(n))
|
|
/* use this if you want the input datum de-toasted: */
|
|
#define PG_GETARG_VARLENA_P(n) PG_DETOAST_DATUM(PG_GETARG_DATUM(n))
|
|
/* and this if you can handle 1-byte-header datums: */
|
|
#define PG_GETARG_VARLENA_PP(n) PG_DETOAST_DATUM_PACKED(PG_GETARG_DATUM(n))
|
|
/* DatumGetFoo macros for varlena types will typically look like this: */
|
|
#define DatumGetByteaP(X) ((bytea*)PG_DETOAST_DATUM(X))
|
|
#define DatumGetByteaPP(X) ((bytea*)PG_DETOAST_DATUM_PACKED(X))
|
|
#define DatumGetTextP(X) ((text*)PG_DETOAST_DATUM(X))
|
|
#define DatumGetTextPP(X) ((text*)PG_DETOAST_DATUM_PACKED(X))
|
|
#define DatumGetBpCharP(X) ((BpChar*)PG_DETOAST_DATUM(X))
|
|
#define DatumGetBpCharPP(X) ((BpChar*)PG_DETOAST_DATUM_PACKED(X))
|
|
#define DatumGetVarCharP(X) ((VarChar*)PG_DETOAST_DATUM(X))
|
|
#define DatumGetVarCharPP(X) ((VarChar*)PG_DETOAST_DATUM_PACKED(X))
|
|
#define DatumGetNVarChar2PP(X) ((NVarChar2*)PG_DETOAST_DATUM_PACKED(X))
|
|
#define DatumGetHeapTupleHeader(X) ((HeapTupleHeader)PG_DETOAST_DATUM(X))
|
|
/* And we also offer variants that return an OK-to-write copy */
|
|
#define DatumGetByteaPCopy(X) ((bytea*)PG_DETOAST_DATUM_COPY(X))
|
|
#define DatumGetTextPCopy(X) ((text*)PG_DETOAST_DATUM_COPY(X))
|
|
#define DatumGetBpCharPCopy(X) ((BpChar*)PG_DETOAST_DATUM_COPY(X))
|
|
#define DatumGetVarCharPCopy(X) ((VarChar*)PG_DETOAST_DATUM_COPY(X))
|
|
#define DatumGetHeapTupleHeaderCopy(X) ((HeapTupleHeader)PG_DETOAST_DATUM_COPY(X))
|
|
/* Variants which return n bytes starting at pos. m */
|
|
#define DatumGetByteaPSlice(X, m, n) ((bytea*)PG_DETOAST_DATUM_SLICE(X, m, n))
|
|
#define DatumGetTextPSlice(X, m, n) ((text*)PG_DETOAST_DATUM_SLICE(X, m, n))
|
|
#define DatumGetBpCharPSlice(X, m, n) ((BpChar*)PG_DETOAST_DATUM_SLICE(X, m, n))
|
|
#define DatumGetVarCharPSlice(X, m, n) ((VarChar*)PG_DETOAST_DATUM_SLICE(X, m, n))
|
|
/* GETARG macros for varlena types will typically look like this: */
|
|
#define PG_GETARG_BYTEA_P(n) DatumGetByteaP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_BYTEA_PP(n) DatumGetByteaPP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_TEXT_P(n) DatumGetTextP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_TEXT_PP(n) DatumGetTextPP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_BPCHAR_P(n) DatumGetBpCharP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_BPCHAR_PP(n) DatumGetBpCharPP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_VARCHAR_P(n) DatumGetVarCharP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_VARCHAR_PP(n) DatumGetVarCharPP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_NVARCHAR2_PP(n) DatumGetNVarChar2PP(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_HEAPTUPLEHEADER(n) DatumGetHeapTupleHeader(PG_GETARG_DATUM(n))
|
|
/* And we also offer variants that return an OK-to-write copy */
|
|
#define PG_GETARG_BYTEA_P_COPY(n) DatumGetByteaPCopy(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_TEXT_P_COPY(n) DatumGetTextPCopy(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_BPCHAR_P_COPY(n) DatumGetBpCharPCopy(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_VARCHAR_P_COPY(n) DatumGetVarCharPCopy(PG_GETARG_DATUM(n))
|
|
#define PG_GETARG_HEAPTUPLEHEADER_COPY(n) DatumGetHeapTupleHeaderCopy(PG_GETARG_DATUM(n))
|
|
/* And a b-byte slice from position a -also OK to write */
|
|
#define PG_GETARG_BYTEA_P_SLICE(n, a, b) DatumGetByteaPSlice(PG_GETARG_DATUM(n), a, b)
|
|
#define PG_GETARG_TEXT_P_SLICE(n, a, b) DatumGetTextPSlice(PG_GETARG_DATUM(n), a, b)
|
|
#define PG_GETARG_BPCHAR_P_SLICE(n, a, b) DatumGetBpCharPSlice(PG_GETARG_DATUM(n), a, b)
|
|
#define PG_GETARG_VARCHAR_P_SLICE(n, a, b) DatumGetVarCharPSlice(PG_GETARG_DATUM(n), a, b)
|
|
|
|
// Vectorized getters
|
|
//
|
|
#define PG_GETARG_VECTOR(n) ((ScalarVector*)(PG_GETARG_DATUM(n)))
|
|
#define PG_GETARG_SELECTION(n) ((bool*)(PG_GETARG_DATUM(n)))
|
|
#define PG_GETARG_VECVAL(n) ((ScalarValue*)(PG_GETARG_VECTOR(n)->m_vals))
|
|
|
|
/* To return a NULL do this: */
|
|
#define PG_RETURN_NULL() \
|
|
do { \
|
|
fcinfo->isnull = true; \
|
|
return (Datum)0; \
|
|
} while (0)
|
|
|
|
/* A few internal functions return void (which is not the same as NULL!) */
|
|
#define PG_RETURN_VOID() return (Datum)0
|
|
|
|
/* Macros for returning results of standard types */
|
|
|
|
#define PG_RETURN_DATUM(x) return (x)
|
|
#define PG_RETURN_INT32(x) return Int32GetDatum(x)
|
|
#define PG_RETURN_UINT32(x) return UInt32GetDatum(x)
|
|
#define PG_RETURN_INT16(x) return Int16GetDatum(x)
|
|
#define PG_RETURN_UINT16(x) return UInt16GetDatum(x)
|
|
#define PG_RETURN_UINT8(x) return UInt8GetDatum(x)
|
|
#define PG_RETURN_CHAR(x) return CharGetDatum(x)
|
|
#define PG_RETURN_BOOL(x) return BoolGetDatum(x)
|
|
#define PG_RETURN_OID(x) return ObjectIdGetDatum(x)
|
|
#define PG_RETURN_POINTER(x) return PointerGetDatum(x)
|
|
#define PG_RETURN_CSTRING(x) return CStringGetDatum(x)
|
|
#define PG_RETURN_NAME(x) return NameGetDatum(x)
|
|
/* these macros hide the pass-by-reference-ness of the datatype: */
|
|
#define PG_RETURN_FLOAT4(x) return Float4GetDatum(x)
|
|
#define PG_RETURN_FLOAT8(x) return Float8GetDatum(x)
|
|
#define PG_RETURN_INT64(x) return Int64GetDatum(x)
|
|
#define PG_RETURN_TRANSACTIONID(x) return TransactionIdGetDatum(x)
|
|
#define PG_RETURN_SHORTTRANSACTIONID(x) return ShortTransactionIdGetDatum(x)
|
|
/* RETURN macros for other pass-by-ref types will typically look like this: */
|
|
#define PG_RETURN_BYTEA_P(x) PG_RETURN_POINTER(x)
|
|
#define PG_RETURN_TEXT_P(x) PG_RETURN_POINTER(x)
|
|
#define PG_RETURN_BPCHAR_P(x) PG_RETURN_POINTER(x)
|
|
#define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x)
|
|
#define PG_RETURN_HEAPTUPLEHEADER(x) PG_RETURN_POINTER(x)
|
|
#define PG_RETURN_NVARCHAR2_P(x) PG_RETURN_POINTER(x)
|
|
|
|
typedef enum COMM_ARG_IDX {
|
|
ARG_0,
|
|
ARG_1,
|
|
ARG_2,
|
|
ARG_3,
|
|
ARG_4,
|
|
ARG_5,
|
|
ARG_6,
|
|
ARG_7,
|
|
ARG_8,
|
|
ARG_9,
|
|
ARG_10,
|
|
ARG_11,
|
|
ARG_12,
|
|
ARG_13,
|
|
ARG_14,
|
|
ARG_15,
|
|
ARG_16,
|
|
ARG_17,
|
|
ARG_18,
|
|
ARG_19,
|
|
ARG_20,
|
|
ARG_END
|
|
} COMM_ARG_IDX;
|
|
|
|
typedef enum COMM_ARR_IDX {
|
|
ARR_0,
|
|
ARR_1,
|
|
ARR_2,
|
|
ARR_3,
|
|
ARR_4,
|
|
ARR_5,
|
|
ARR_6,
|
|
ARR_7,
|
|
ARR_8,
|
|
ARR_9,
|
|
ARR_10,
|
|
ARR_11,
|
|
ARR_12,
|
|
ARR_13,
|
|
ARR_14,
|
|
ARR_15,
|
|
ARR_16,
|
|
ARR_17,
|
|
ARR_18,
|
|
ARR_19,
|
|
ARR_20,
|
|
ARR_END
|
|
} COMM_ARR_IDX;
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Support for detecting call convention of dynamically-loaded functions
|
|
*
|
|
* Dynamically loaded functions may use either the version-1 ("new style")
|
|
* or version-0 ("old style") calling convention. Version 1 is the call
|
|
* convention defined in this header file; version 0 is the old "plain C"
|
|
* convention. A version-1 function must be accompanied by the macro call
|
|
*
|
|
* PG_FUNCTION_INFO_V1(function_name);
|
|
*
|
|
* Note that internal functions do not need this decoration since they are
|
|
* assumed to be version-1.
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
typedef struct {
|
|
int api_version; /* specifies call convention version number */
|
|
/* More fields may be added later, for version numbers > 1. */
|
|
} Pg_finfo_record;
|
|
|
|
/* Expected signature of an info function */
|
|
typedef const Pg_finfo_record* (*PGFInfoFunction)(void);
|
|
|
|
/*
|
|
* Macro to build an info function associated with the given function name.
|
|
* Win32 loadable functions usually link with 'dlltool --export-all', but it
|
|
* doesn't hurt to add PGDLLIMPORT in case they don't.
|
|
*/
|
|
#define PG_FUNCTION_INFO_V1(funcname) \
|
|
extern "C" PGDLLEXPORT const Pg_finfo_record* CppConcat(pg_finfo_, funcname)(void); \
|
|
const Pg_finfo_record* CppConcat(pg_finfo_, funcname)(void) \
|
|
{ \
|
|
static const Pg_finfo_record my_finfo = {1}; \
|
|
return &my_finfo; \
|
|
} \
|
|
extern int no_such_variable
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Support for verifying backend compatibility of loaded modules
|
|
*
|
|
* We require dynamically-loaded modules to include the macro call
|
|
* PG_MODULE_MAGIC;
|
|
* so that we can check for obvious incompatibility, such as being compiled
|
|
* for a different major PostgreSQL version.
|
|
*
|
|
* To compile with versions of PostgreSQL that do not support this,
|
|
* you may put an #ifdef/#endif test around it. Note that in a multiple-
|
|
* source-file module, the macro call should only appear once.
|
|
*
|
|
* The specific items included in the magic block are intended to be ones that
|
|
* are custom-configurable and especially likely to break dynamically loaded
|
|
* modules if they were compiled with other values. Also, the length field
|
|
* can be used to detect definition changes.
|
|
*
|
|
* Note: we compare magic blocks with memcmp(), so there had better not be
|
|
* any alignment pad bytes in them.
|
|
*
|
|
* Note: when changing the contents of magic blocks, be sure to adjust the
|
|
* incompatible_module_error() function in dfmgr.c.
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* Definition of the magic block structure */
|
|
typedef struct {
|
|
int len; /* sizeof(this struct) */
|
|
int version; /* PostgreSQL major version */
|
|
int funcmaxargs; /* FUNC_MAX_ARGS */
|
|
int indexmaxkeys; /* INDEX_MAX_KEYS */
|
|
int namedatalen; /* NAMEDATALEN */
|
|
int float4byval; /* FLOAT4PASSBYVAL */
|
|
int float8byval; /* FLOAT8PASSBYVAL */
|
|
} Pg_magic_struct;
|
|
|
|
/* The actual data block contents */
|
|
#define PG_MODULE_MAGIC_DATA \
|
|
{ \
|
|
sizeof(Pg_magic_struct), PG_VERSION_NUM / 100, FUNC_MAX_ARGS, INDEX_MAX_KEYS, NAMEDATALEN, FLOAT4PASSBYVAL, \
|
|
FLOAT8PASSBYVAL \
|
|
}
|
|
|
|
/*
|
|
* Declare the module magic function. It needs to be a function as the dlsym
|
|
* in the backend is only guaranteed to work on functions, not data
|
|
*/
|
|
typedef const Pg_magic_struct* (*PGModuleMagicFunction)(void);
|
|
|
|
#define PG_MAGIC_FUNCTION_NAME Pg_magic_func
|
|
#define PG_MAGIC_FUNCTION_NAME_STRING "Pg_magic_func"
|
|
|
|
#define PG_MODULE_MAGIC \
|
|
extern "C" PGDLLEXPORT const Pg_magic_struct* PG_MAGIC_FUNCTION_NAME(void); \
|
|
const Pg_magic_struct* PG_MAGIC_FUNCTION_NAME(void) \
|
|
{ \
|
|
static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA; \
|
|
return &Pg_magic_data; \
|
|
} \
|
|
extern int no_such_variable
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Support routines and macros for callers of fmgr-compatible functions
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* These are for invocation of a specifically named function with a
|
|
* directly-computed parameter list. Note that neither arguments nor result
|
|
* are allowed to be NULL.
|
|
*/
|
|
extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1);
|
|
extern Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2);
|
|
extern Datum DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3);
|
|
extern Datum DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4);
|
|
extern Datum DirectFunctionCall5Coll(
|
|
PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5);
|
|
extern Datum DirectFunctionCall6Coll(
|
|
PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6);
|
|
extern Datum DirectFunctionCall7Coll(
|
|
PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7);
|
|
extern Datum DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4,
|
|
Datum arg5, Datum arg6, Datum arg7, Datum arg8);
|
|
extern Datum DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4,
|
|
Datum arg5, Datum arg6, Datum arg7, Datum arg8, Datum arg9);
|
|
|
|
/* These are for invocation of a previously-looked-up function with a
|
|
* directly-computed parameter list. Note that neither arguments nor result
|
|
* are allowed to be NULL.
|
|
*/
|
|
extern Datum FunctionCall1Coll(FmgrInfo* flinfo, Oid collation, Datum arg1);
|
|
extern Datum FunctionCall2Coll(FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2);
|
|
extern Datum FunctionCall3Coll(FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3);
|
|
extern Datum FunctionCall4Coll(FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4);
|
|
extern Datum FunctionCall5Coll(
|
|
FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5);
|
|
extern Datum FunctionCall6Coll(
|
|
FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6);
|
|
extern Datum FunctionCall7Coll(FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4,
|
|
Datum arg5, Datum arg6, Datum arg7);
|
|
extern Datum FunctionCall8Coll(FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4,
|
|
Datum arg5, Datum arg6, Datum arg7, Datum arg8);
|
|
extern Datum FunctionCall9Coll(FmgrInfo* flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4,
|
|
Datum arg5, Datum arg6, Datum arg7, Datum arg8, Datum arg9);
|
|
|
|
/* These are for invocation of a function identified by OID with a
|
|
* directly-computed parameter list. Note that neither arguments nor result
|
|
* are allowed to be NULL. These are essentially FunctionLookup() followed
|
|
* by FunctionCallN(). If the same function is to be invoked repeatedly,
|
|
* do the FunctionLookup() once and then use FunctionCallN().
|
|
*/
|
|
extern Datum OidFunctionCall0Coll(Oid functionId, Oid collation);
|
|
extern Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1);
|
|
extern Datum OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2);
|
|
extern Datum OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3);
|
|
extern Datum OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4);
|
|
extern Datum OidFunctionCall5Coll(
|
|
Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5);
|
|
extern Datum OidFunctionCall6Coll(
|
|
Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6);
|
|
extern Datum OidFunctionCall7Coll(
|
|
Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7);
|
|
extern Datum OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4,
|
|
Datum arg5, Datum arg6, Datum arg7, Datum arg8);
|
|
extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4,
|
|
Datum arg5, Datum arg6, Datum arg7, Datum arg8, Datum arg9);
|
|
|
|
/* These macros allow the collation argument to be omitted (with a default of
|
|
* InvalidOid, ie, no collation). They exist mostly for backwards
|
|
* compatibility of source code.
|
|
*/
|
|
#define DirectFunctionCall1(func, arg1) DirectFunctionCall1Coll(func, InvalidOid, arg1)
|
|
#define DirectFunctionCall2(func, arg1, arg2) DirectFunctionCall2Coll(func, InvalidOid, arg1, arg2)
|
|
#define DirectFunctionCall3(func, arg1, arg2, arg3) DirectFunctionCall3Coll(func, InvalidOid, arg1, arg2, arg3)
|
|
#define DirectFunctionCall4(func, arg1, arg2, arg3, arg4) \
|
|
DirectFunctionCall4Coll(func, InvalidOid, arg1, arg2, arg3, arg4)
|
|
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5) \
|
|
DirectFunctionCall5Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5)
|
|
#define DirectFunctionCall6(func, arg1, arg2, arg3, arg4, arg5, arg6) \
|
|
DirectFunctionCall6Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
|
|
#define DirectFunctionCall7(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
|
|
DirectFunctionCall7Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
|
#define DirectFunctionCall8(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
|
|
DirectFunctionCall8Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
|
#define DirectFunctionCall9(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
|
|
DirectFunctionCall9Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
|
#define FunctionCall1(flinfo, arg1) FunctionCall1Coll(flinfo, InvalidOid, arg1)
|
|
#define FunctionCall2(flinfo, arg1, arg2) FunctionCall2Coll(flinfo, InvalidOid, arg1, arg2)
|
|
#define FunctionCall3(flinfo, arg1, arg2, arg3) FunctionCall3Coll(flinfo, InvalidOid, arg1, arg2, arg3)
|
|
#define FunctionCall4(flinfo, arg1, arg2, arg3, arg4) FunctionCall4Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4)
|
|
#define FunctionCall5(flinfo, arg1, arg2, arg3, arg4, arg5) \
|
|
FunctionCall5Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5)
|
|
#define FunctionCall6(flinfo, arg1, arg2, arg3, arg4, arg5, arg6) \
|
|
FunctionCall6Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
|
|
#define FunctionCall7(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
|
|
FunctionCall7Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
|
#define FunctionCall8(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
|
|
FunctionCall8Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
|
#define FunctionCall9(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
|
|
FunctionCall9Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
|
#define OidFunctionCall0(functionId) OidFunctionCall0Coll(functionId, InvalidOid)
|
|
#define OidFunctionCall1(functionId, arg1) OidFunctionCall1Coll(functionId, InvalidOid, arg1)
|
|
#define OidFunctionCall2(functionId, arg1, arg2) OidFunctionCall2Coll(functionId, InvalidOid, arg1, arg2)
|
|
#define OidFunctionCall3(functionId, arg1, arg2, arg3) OidFunctionCall3Coll(functionId, InvalidOid, arg1, arg2, arg3)
|
|
#define OidFunctionCall4(functionId, arg1, arg2, arg3, arg4) \
|
|
OidFunctionCall4Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4)
|
|
#define OidFunctionCall5(functionId, arg1, arg2, arg3, arg4, arg5) \
|
|
OidFunctionCall5Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5)
|
|
#define OidFunctionCall6(functionId, arg1, arg2, arg3, arg4, arg5, arg6) \
|
|
OidFunctionCall6Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
|
|
#define OidFunctionCall7(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
|
|
OidFunctionCall7Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
|
#define OidFunctionCall8(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
|
|
OidFunctionCall8Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
|
#define OidFunctionCall9(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
|
|
OidFunctionCall9Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
|
|
|
typedef struct {
|
|
PGFunction user_fn; /* the function's address */
|
|
const Pg_finfo_record* inforec; /* address of its info record */
|
|
} CFunInfo;
|
|
|
|
/* Special cases for convenient invocation of datatype I/O functions. */
|
|
extern Datum InputFunctionCall(FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod);
|
|
extern Datum InputFunctionCallForDateType(
|
|
FmgrInfo* flinfo, char* str, Oid typioparam, int32 typmod, char* date_time_fmt);
|
|
extern Datum OidInputFunctionCall(Oid functionId, char* str, Oid typioparam, int32 typmod);
|
|
extern char* OutputFunctionCall(FmgrInfo* flinfo, Datum val);
|
|
extern char* OidOutputFunctionCall(Oid functionId, Datum val);
|
|
extern Datum ReceiveFunctionCall(FmgrInfo* flinfo, fmStringInfo buf, Oid typioparam, int32 typmod);
|
|
extern Datum OidReceiveFunctionCall(Oid functionId, fmStringInfo buf, Oid typioparam, int32 typmod);
|
|
extern bytea* SendFunctionCall(FmgrInfo* flinfo, Datum val);
|
|
extern bytea* OidSendFunctionCall(Oid functionId, Datum val);
|
|
|
|
/*
|
|
* Routines in fmgr.c
|
|
*/
|
|
extern const Pg_finfo_record* fetch_finfo_record(void* filehandle, char* funcname, bool isValidate);
|
|
extern void clear_external_function_hash(void* filehandle);
|
|
extern Oid fmgr_internal_function(const char* proname);
|
|
extern Oid get_fn_expr_rettype(FmgrInfo* flinfo);
|
|
extern Oid get_fn_expr_argtype(FmgrInfo* flinfo, int argnum);
|
|
extern Oid get_call_expr_argtype(fmNodePtr expr, int argnum);
|
|
extern bool get_fn_expr_arg_stable(FmgrInfo* flinfo, int argnum);
|
|
extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum);
|
|
extern bool get_fn_expr_variadic(FmgrInfo* flinfo);
|
|
extern bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid);
|
|
|
|
extern CFunInfo load_external_function(const char* filename, char* funcname, bool signalNotFound, bool isValidate);
|
|
extern char* expand_dynamic_library_name(const char* name);
|
|
extern PGFunction lookup_external_function(void* filehandle, const char* funcname);
|
|
extern void load_file(const char* filename, bool restricted);
|
|
extern void** find_rendezvous_variable(const char* varName);
|
|
|
|
/*
|
|
* Support for aggregate functions
|
|
*
|
|
* This is actually in executor/nodeAgg.c, but we declare it here since the
|
|
* whole point is for callers of it to not be overly friendly with nodeAgg.
|
|
*/
|
|
|
|
/* AggCheckCallContext can return one of the following codes, or 0: */
|
|
#define AGG_CONTEXT_AGGREGATE 1 /* regular aggregate */
|
|
#define AGG_CONTEXT_WINDOW 2 /* window function */
|
|
|
|
extern int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext* aggcontext);
|
|
|
|
/*
|
|
* We allow plugin modules to hook function entry/exit. This is intended
|
|
* as support for loadable security policy modules, which may want to
|
|
* perform additional privilege checks on function entry or exit, or to do
|
|
* other internal bookkeeping. To make this possible, such modules must be
|
|
* able not only to support normal function entry and exit, but also to trap
|
|
* the case where we bail out due to an error; and they must also be able to
|
|
* prevent inlining.
|
|
*/
|
|
typedef enum FmgrHookEventType { FHET_START, FHET_END, FHET_ABORT } FmgrHookEventType;
|
|
|
|
typedef bool (*needs_fmgr_hook_type)(Oid fn_oid);
|
|
|
|
typedef void (*fmgr_hook_type)(FmgrHookEventType event, FmgrInfo* flinfo, Datum* arg);
|
|
|
|
extern THR_LOCAL PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook;
|
|
extern THR_LOCAL PGDLLIMPORT fmgr_hook_type fmgr_hook;
|
|
|
|
#define FmgrHookIsNeeded(fn_oid) (!needs_fmgr_hook ? false : (*needs_fmgr_hook)(fn_oid))
|
|
|
|
// Define common stuff for vectorized expression //
|
|
typedef enum SimpleOp {
|
|
SOP_EQ, // =
|
|
SOP_NEQ, // !=
|
|
SOP_LE, // <=
|
|
SOP_LT, // <
|
|
SOP_GE, // >=
|
|
SOP_GT, // >
|
|
} SimpleOp;
|
|
|
|
template <SimpleOp sop, typename Datatype>
|
|
inline bool eval_simple_op(Datatype dataVal1, Datatype dataVal2)
|
|
{
|
|
if (sop == SOP_EQ)
|
|
return ((dataVal1) == (dataVal2));
|
|
if (sop == SOP_NEQ)
|
|
return ((dataVal1) != (dataVal2));
|
|
if (sop == SOP_LE)
|
|
return ((dataVal1) <= (dataVal2));
|
|
if (sop == SOP_LT)
|
|
return ((dataVal1) < (dataVal2));
|
|
if (sop == SOP_GE)
|
|
return ((dataVal1) >= (dataVal2));
|
|
if (sop == SOP_GT)
|
|
return ((dataVal1) > (dataVal2));
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* !!! OLD INTERFACE !!!
|
|
*
|
|
* fmgr() is the only remaining vestige of the old-style caller support
|
|
* functions. It's no longer used anywhere in the Postgres distribution,
|
|
* but we should leave it around for a release or two to ease the transition
|
|
* for user-supplied C functions. OidFunctionCallN() replaces it for new
|
|
* code.
|
|
*/
|
|
|
|
/*
|
|
* DEPRECATED, DO NOT USE IN NEW CODE
|
|
*/
|
|
extern char* fmgr(Oid procedureId, ...);
|
|
|
|
extern Datum DirectCall0(bool* isRetNull, PGFunction func, Oid collation);
|
|
extern Datum DirectCall1(bool* isRetNull, PGFunction func, Oid collation, Datum arg1);
|
|
extern Datum DirectCall2(bool* isRetNull, PGFunction func, Oid collation, Datum arg1, Datum arg2);
|
|
extern Datum DirectCall3(bool* isRetNull, PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3);
|
|
extern Datum interval_in(PG_FUNCTION_ARGS);
|
|
|
|
#define CHECK_RETNULL_RETURN_DATUM(x) \
|
|
do { \
|
|
_datum = (x); \
|
|
if (_isRetNull) \
|
|
PG_RETURN_NULL(); \
|
|
else \
|
|
return _datum; \
|
|
} while (0)
|
|
#define CHECK_RETNULL_CALL0(func, collation) DirectCall0(&_isRetNull, func, collation)
|
|
#define CHECK_RETNULL_CALL1(func, collation, arg1) DirectCall1(&_isRetNull, func, collation, arg1)
|
|
#define CHECK_RETNULL_CALL2(func, collation, arg1, arg2) DirectCall2(&_isRetNull, func, collation, arg1, arg2)
|
|
#define CHECK_RETNULL_CALL3(func, collation, arg1, arg2, arg3) \
|
|
DirectCall3(&_isRetNull, func, collation, arg1, arg2, arg3)
|
|
#define CHECK_RETNULL_INIT() \
|
|
Datum _datum; \
|
|
bool _isRetNull = false
|
|
|
|
extern void CopyCursorInfoData(Cursor_Data* target_data, Cursor_Data* source_data);
|
|
|
|
#endif /* FMGR_H */
|