aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/Gen_fmgrtab.sh.in196
-rw-r--r--src/backend/utils/Makefile17
-rw-r--r--src/backend/utils/adt/int8.c11
-rw-r--r--src/backend/utils/adt/regproc.c3
-rw-r--r--src/backend/utils/adt/selfuncs.c10
-rw-r--r--src/backend/utils/adt/sets.c5
-rw-r--r--src/backend/utils/cache/catcache.c3
-rw-r--r--src/backend/utils/cache/fcache.c56
-rw-r--r--src/backend/utils/cache/relcache.c3
-rw-r--r--src/backend/utils/fmgr/dfmgr.c306
-rw-r--r--src/backend/utils/fmgr/fmgr.c1765
-rw-r--r--src/backend/utils/init/postinit.c3
12 files changed, 1383 insertions, 995 deletions
diff --git a/src/backend/utils/Gen_fmgrtab.sh.in b/src/backend/utils/Gen_fmgrtab.sh.in
index 975e2a0f9a2..f075ac28376 100644
--- a/src/backend/utils/Gen_fmgrtab.sh.in
+++ b/src/backend/utils/Gen_fmgrtab.sh.in
@@ -1,14 +1,15 @@
#!/bin/sh
#-------------------------------------------------------------------------
#
-# Gen_fmgrtab.sh--
-# shell script to generate fmgr.h and fmgrtab.c from pg_proc.h
+# Gen_fmgrtab.sh
+# shell script to generate fmgroids.h and fmgrtab.c from pg_proc.h
#
-# Copyright (c) 1994, Regents of the University of California
+# Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+# Portions Copyright (c) 1994, Regents of the University of California
#
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.21 2000/05/22 02:34:21 momjian Exp $
+# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.22 2000/05/28 17:56:05 tgl Exp $
#
# NOTES
# Passes any -D options on to cpp prior to generating the list
@@ -16,12 +17,6 @@
#
#-------------------------------------------------------------------------
-if [ $? != 0 ]
-then
- echo `basename $0`: Bad option
- exit 1
-fi
-
BKIOPTS=''
#
@@ -32,7 +27,7 @@ for opt in $*
do
case $opt in
-D) BKIOPTS="$BKIOPTS -D$2"; shift; shift;;
- -D*) BKIOPTS="$BKIOPTS $1";shift;;
+ -D*) BKIOPTS="$BKIOPTS $1"; shift;;
--) shift; break;;
-*) shift;;
esac
@@ -41,8 +36,8 @@ done
INFILE=$1
RAWFILE=fmgr.raw
CPPTMPFILE=fmgrtmp.c
-HFILE=fmgr.h
-TABCFILE=fmgrtab.c
+OIDSFILE=fmgroids.h
+TABLEFILE=fmgrtab.c
#
# Generate the file containing raw pg_proc tuple data
@@ -63,7 +58,8 @@ sed -e 's/^.*OID[^=]*=[^0-9]*//' \
-e 's/[ ]*).*$//' | \
awk '
/^#/ { print; next; }
-$4 == "11" { print; next; }' > $CPPTMPFILE
+$4 == "11" { print; next; }
+$4 == "12" { print; next; }' > $CPPTMPFILE
@CPP@ $BKIOPTS $CPPTMPFILE | \
egrep '^[0-9]' | \
@@ -72,18 +68,21 @@ sort -n > $RAWFILE
rm -f $CPPTMPFILE
#
-# Generate fmgr.h
+# Generate fmgroids.h
#
-cat > $HFILE <<FuNkYfMgRsTuFf
+cat > $OIDSFILE <<FuNkYfMgRsTuFf
/*-------------------------------------------------------------------------
*
- * $HFILE--
- * Definitions for using internal procedures.
+ * $OIDSFILE
+ * Macros that define the OIDs of built-in functions.
*
+ * These macros can be used to avoid a catalog lookup when a specific
+ * fmgr-callable function needs to be referenced.
*
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: Gen_fmgrtab.sh.in,v 1.21 2000/05/22 02:34:21 momjian Exp $
+ * $Id: Gen_fmgrtab.sh.in,v 1.22 2000/05/28 17:56:05 tgl Exp $
*
* NOTES
* ******************************
@@ -91,77 +90,12 @@ cat > $HFILE <<FuNkYfMgRsTuFf
* ******************************
*
* It has been GENERATED by $0
- * from $1
+ * from $INFILE
*
*-------------------------------------------------------------------------
*/
-#ifndef FMGR_H
-#define FMGR_H
-
-#include "postgres.h"
-
-typedef struct {
- char *data[FUNC_MAX_ARGS];
-} FmgrValues;
-
-typedef struct {
- func_ptr fn_addr;
- func_ptr fn_plhandler;
- Oid fn_oid;
- int fn_nargs;
-} FmgrInfo;
-
-/*
- * defined in fmgr.c
- */
-extern char *fmgr_c(FmgrInfo *finfo, FmgrValues *values, bool *isNull);
-extern void fmgr_info(Oid procedureId, FmgrInfo *finfo);
-extern char *fmgr(Oid procedureId, ... );
-extern char *fmgr_ptr(FmgrInfo *finfo, ... );
-extern char *fmgr_array_args(Oid procedureId, int nargs,
- char *args[], bool *isNull);
-
-/*
- * defined in dfmgr.c
- */
-extern func_ptr fmgr_dynamic(Oid procedureId, int *pronargs);
-extern void load_file(char *filename);
-
-/*
- * For performance reasons, we often want to simply jump through a
- * a function pointer (if it's valid, that is). These calls have
- * been macroized so we can run them through a routine that does
- * sanity-checking (and so we can track them down more easily when
- * we must).
- */
-
-/* We don't make this static so fmgr_faddr() macros can access it */
-extern FmgrInfo *fmgr_pl_finfo;
-
-#define fmgr_faddr(finfo) \
-( \
- fmgr_pl_finfo = (finfo), \
- (func_ptr)(finfo)->fn_addr \
-)
-
-#ifdef TRACE_FMGR_PTR
-#define FMGR_PTR2(FINFO, ARG1, ARG2) \
- fmgr_ptr(FINFO, 2, ARG1, ARG2)
-#else
-#define FMGR_PTR2(FINFO, ARG1, ARG2) \
-( \
- ((FINFO)->fn_addr) ? \
- (*(fmgr_faddr(FINFO)))(ARG1, ARG2) \
- : \
- fmgr((FINFO)->fn_oid, ARG1, ARG2) \
-)
-#endif
-
-/*
- * Flags for the builtin oprrest selectivity routines.
- */
-#define SEL_CONSTANT 1 /* constant does not vary (not a parameter) */
-#define SEL_RIGHT 2 /* constant appears to right of operator */
+#ifndef FMGROIDS_H
+#define FMGROIDS_H
/*
* Constant macros for the OIDs of entries in pg_proc.
@@ -174,30 +108,33 @@ FuNkYfMgRsTuFf
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $RAWFILE | \
awk '
BEGIN { OFS = ""; }
- { if (seenit[$2]++ == 0) print "#define F_", $2, " ", $1; }' >> $HFILE
+ { if (seenit[$2]++ == 0) print "#define F_", $2, " ", $1; }' >> $OIDSFILE
-cat >> $HFILE <<FuNkYfMgRsTuFf
+cat >> $OIDSFILE <<FuNkYfMgRsTuFf
-#endif /* FMGR_H */
+#endif /* FMGROIDS_H */
FuNkYfMgRsTuFf
#
-# Generate fmgr function table file.
+# Generate fmgr's built-in-function table.
#
-# Print out the bogus function declarations, then the table that
-# refers to them.
+# Print out the function declarations, then the table that refers to them.
+# NB: the function declarations are bogus in the case of old-style functions,
+# although they should be correct for new-style. Therefore we need to compile
+# this table definition as a separate C file that won't need to include any
+# "real" declarations for those functions!
#
-cat > $TABCFILE <<FuNkYfMgRtAbStUfF
+cat > $TABLEFILE <<FuNkYfMgRtAbStUfF
/*-------------------------------------------------------------------------
*
- * $TABCFILE--
+ * $TABLEFILE
* The function manager's table of internal functions.
*
- * Copyright (c) 1994, Regents of the University of California
- *
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.21 2000/05/22 02:34:21 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh.in,v 1.22 2000/05/28 17:56:05 tgl Exp $
*
* NOTES
*
@@ -206,72 +143,41 @@ cat > $TABCFILE <<FuNkYfMgRtAbStUfF
* ******************************
*
* It has been GENERATED by $0
- * from $1
+ * from $INFILE
*
- * We lie here to cc about the return type and arguments of the
+ * We lie here to cc about the return type and arguments of old-style
* builtin functions; all ld cares about is the fact that it
* will need to resolve an external function reference.
*
*-------------------------------------------------------------------------
*/
-#include <string.h>
#include "postgres.h"
+
#include "utils/fmgrtab.h"
FuNkYfMgRtAbStUfF
-awk '{ print "extern char *", $(NF-1), "();"; }' $RAWFILE >> $TABCFILE
+awk '{ print "extern Datum", $(NF-1), "(PG_FUNCTION_ARGS);"; }' $RAWFILE >> $TABLEFILE
-cat >> $TABCFILE <<FuNkYfMgRtAbStUfF
+cat >> $TABLEFILE <<FuNkYfMgRtAbStUfF
-static FmgrCall fmgr_builtins[] = {
+const FmgrBuiltin fmgr_builtins[] = {
FuNkYfMgRtAbStUfF
-awk '{ printf (" {%d, %d, %s, \"%s\" },\n"), $1, $8, $(NF-1), $(NF-1) }' $RAWFILE >> $TABCFILE
+awk '{ printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \
+ $1, $(NF-1), $9, \
+ ($8 == "t") ? "true" : "false", \
+ ($4 == "11") ? "true" : "false", \
+ $(NF-1) }' $RAWFILE >> $TABLEFILE
-cat >> $TABCFILE <<FuNkYfMgRtAbStUfF
+cat >> $TABLEFILE <<FuNkYfMgRtAbStUfF
/* dummy entry is easier than getting rid of comma after last real one */
- { 0, 0, (func_ptr) NULL, NULL }
+ { 0, NULL, 0, false, false, (PGFunction) NULL }
};
-/* Note FMGR_NBUILTINS excludes the dummy entry */
-#define FMGR_NBUILTINS ((sizeof(fmgr_builtins) / sizeof(FmgrCall)) - 1)
-
-FmgrCall *fmgr_isbuiltin(Oid id)
-{
- int low = 0;
- int high = FMGR_NBUILTINS - 1;
-
- /* Loop invariant: low is the first index that could contain target
- * entry, and high is the last index that could contain it.
- */
- while (low <= high) {
- int i = (high + low) / 2;
- FmgrCall * ptr = &fmgr_builtins[i];
- if (id == ptr->proid)
- return ptr;
- else if (id > ptr->proid)
- low = i + 1;
- else
- high = i - 1;
- }
- return (FmgrCall *) NULL;
-}
-
-func_ptr fmgr_lookupByName(char *name)
-{
- /* Lookup a builtin by name. Note there can be more than one entry in
- * the array matching this name, but they should all point to the same
- * routine.
- */
- int i;
- for (i=0; i<FMGR_NBUILTINS; i++) {
- if (strcmp(name, fmgr_builtins[i].funcName) == 0)
- return fmgr_builtins[i].func;
- }
- return (func_ptr) NULL;
-}
+/* Note fmgr_nbuiltins excludes the dummy entry */
+const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;
FuNkYfMgRtAbStUfF
diff --git a/src/backend/utils/Makefile b/src/backend/utils/Makefile
index e37c85761e6..eba9b13af29 100644
--- a/src/backend/utils/Makefile
+++ b/src/backend/utils/Makefile
@@ -4,12 +4,12 @@
# Makefile for utils
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/backend/utils/Makefile,v 1.10 1999/12/13 22:34:28 momjian Exp $
+# $Header: /cvsroot/pgsql/src/backend/utils/Makefile,v 1.11 2000/05/28 17:56:05 tgl Exp $
#
#-------------------------------------------------------------------------
SRCDIR = ../..
-include ../../Makefile.global
+include $(SRCDIR)/Makefile.global
INCLUDE_OPT = -I..
@@ -35,19 +35,14 @@ SUBSYS.o: $(OBJS)
submake:
for i in $(DIRS); do $(MAKE) -C $$i SUBSYS.o; done
-fmgrtab.o: ../fmgr.h
-
-../fmgr.h:
- $(MAKE) -C .. fmgr.h
-
-fmgr.h fmgrtab.c: ./Gen_fmgrtab.sh ../../include/catalog/pg_proc.h
- sh $(SHOPTS) Gen_fmgrtab.sh ../../include/catalog/pg_proc.h
+fmgroids.h fmgrtab.c: Gen_fmgrtab.sh $(SRCDIR)/include/catalog/pg_proc.h
+ $(SHELL) $(SHOPTS) Gen_fmgrtab.sh $(SRCDIR)/include/catalog/pg_proc.h
clean:
- rm -f SUBSYS.o fmgr.h fmgrtab.o fmgrtab.c
+ rm -f SUBSYS.o fmgroids.h fmgrtab.o fmgrtab.c
for i in $(DIRS); do $(MAKE) -C $$i clean; done
-dep depend: fmgr.h fmgrtab.c
+dep depend: fmgroids.h fmgrtab.c
for i in $(DIRS); do $(MAKE) -C $$i depend; done
ifeq (depend,$(wildcard depend))
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 018352df1ad..a30a920b6a4 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -3,6 +3,12 @@
* int8.c
* Internal 64-bit integer operations
*
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.19 2000/05/28 17:56:05 tgl Exp $
+ *
*-------------------------------------------------------------------------
*/
#include <ctype.h>
@@ -18,6 +24,11 @@
#include "utils/int8.h"
+/* this should be set in config.h, but just in case it wasn't: */
+#ifndef INT64_FORMAT
+#define INT64_FORMAT "%ld"
+#endif
+
#define MAXINT8LEN 25
#ifndef INT_MAX
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 4060a846655..6db76ac8c5a 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.54 2000/04/12 17:15:51 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.55 2000/05/28 17:56:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,7 @@
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "utils/builtins.h"
+#include "utils/fmgroids.h"
#include "utils/syscache.h"
/*****************************************************************************
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 4718dc668a7..c93ef767d8e 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.66 2000/05/26 17:19:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.67 2000/05/28 17:56:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -889,17 +889,17 @@ convert_numeric_to_scalar(Datum value, Oid typid)
switch (typid)
{
case BOOLOID:
- return (double) DatumGetUInt8(value);
+ return (double) DatumGetBool(value);
case INT2OID:
return (double) DatumGetInt16(value);
case INT4OID:
return (double) DatumGetInt32(value);
case INT8OID:
- return (double) (*i8tod((int64 *) DatumGetPointer(value)));
+ return (double) DatumGetInt64(value);
case FLOAT4OID:
- return (double) (*DatumGetFloat32(value));
+ return (double) DatumGetFloat4(value);
case FLOAT8OID:
- return (double) (*DatumGetFloat64(value));
+ return (double) DatumGetFloat8(value);
case NUMERICOID:
return (double) (*numeric_float8((Numeric) DatumGetPointer(value)));
case OIDOID:
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index dbc5ea4b8fa..cc629c3ad85 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.30 2000/01/26 05:57:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.31 2000/05/28 17:56:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -56,8 +56,9 @@ SetDefine(char *querystr, char *typename)
"sql", /* languageName */
querystr, /* sourceCode */
fileName, /* fileName */
- false, /* canCache */
true, /* trusted */
+ false, /* canCache XXX appropriate? */
+ false, /* isStrict XXX appropriate? */
100, /* byte_pct */
0, /* perbyte_cpu */
0, /* percall_cpu */
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index b593920b1a8..e5fb546ca70 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.63 2000/04/12 17:15:52 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.64 2000/05/28 17:56:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,7 @@
#include "catalog/indexing.h"
#include "miscadmin.h"
#include "utils/builtins.h"
+#include "utils/fmgroids.h"
#include "utils/catcache.h"
#include "utils/syscache.h"
diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c
index 26f4cbd8d06..33528d7bb20 100644
--- a/src/backend/utils/cache/fcache.c
+++ b/src/backend/utils/cache/fcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.30 2000/04/12 17:15:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.31 2000/05/28 17:56:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,20 +24,9 @@
static Oid GetDynamicFuncArgType(Var *arg, ExprContext *econtext);
static FunctionCachePtr init_fcache(Oid foid,
- bool use_syscache,
- List *argList,
- ExprContext *econtext);
+ List *argList,
+ ExprContext *econtext);
-/*-----------------------------------------------------------------
- *
- * Initialize the 'FunctionCache' given the PG_PROC oid.
- *
- *
- * NOTE: This function can be called when the system cache is being
- * initialized. Therefore, use_syscache should ONLY be true
- * when the function return type is interesting (ie: set_fcache).
- *-----------------------------------------------------------------
- */
#define FuncArgTypeIsDynamic(arg) \
(IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber)
@@ -53,7 +42,6 @@ GetDynamicFuncArgType(Var *arg, ExprContext *econtext)
rtid = ((Var *) arg)->varno;
relname = (char *) getrelname(rtid, econtext->ecxt_range_table);
-
tup = SearchSysCacheTuple(TYPENAME,
PointerGetDatum(relname),
0, 0, 0);
@@ -64,9 +52,14 @@ GetDynamicFuncArgType(Var *arg, ExprContext *econtext)
return tup->t_data->t_oid;
}
+/*-----------------------------------------------------------------
+ *
+ * Initialize a 'FunctionCache' struct given the PG_PROC oid.
+ *
+ *-----------------------------------------------------------------
+ */
static FunctionCachePtr
init_fcache(Oid foid,
- bool use_syscache,
List *argList,
ExprContext *econtext)
{
@@ -79,16 +72,13 @@ init_fcache(Oid foid,
text *tmp;
bool isNull;
+ retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
+ MemSet(retval, 0, sizeof(FunctionCache));
+
/* ----------------
* get the procedure tuple corresponding to the given functionOid
* ----------------
*/
- retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
- memset(retval, 0, sizeof(FunctionCache));
-
- if (!use_syscache)
- elog(ERROR, "what the ????, init the fcache without the catalogs?");
-
procedureTuple = SearchSysCacheTuple(PROCOID,
ObjectIdGetDatum(foid),
0, 0, 0);
@@ -114,8 +104,7 @@ init_fcache(Oid foid,
typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
/* ----------------
- * get the type length and by-value from the type tuple and
- * save the information in our one element cache.
+ * get the type length and by-value flag from the type tuple
* ----------------
*/
retval->typlen = typeStruct->typlen;
@@ -136,10 +125,9 @@ init_fcache(Oid foid,
retval->foid = foid;
retval->language = procedureStruct->prolang;
retval->func_state = (char *) NULL;
- retval->setArg = NULL;
+ retval->setArg = (Datum) 0;
retval->hasSetArg = false;
retval->oneResult = !procedureStruct->proretset;
- retval->istrusted = procedureStruct->proistrusted;
/*
* If we are returning exactly one result then we have to copy tuples
@@ -162,9 +150,8 @@ init_fcache(Oid foid,
slot->ttc_tupleDescriptor = (TupleDesc) NULL;
slot->ttc_buffer = InvalidBuffer;
slot->ttc_whichplan = -1;
- retval->funcSlot = (Pointer) slot;
- relationTuple = (HeapTuple)
+ relationTuple =
SearchSysCacheTuple(RELNAME,
PointerGetDatum(&typeStruct->typname),
0, 0, 0);
@@ -177,10 +164,12 @@ init_fcache(Oid foid,
else
td = CreateTemplateTupleDesc(1);
- ((TupleTableSlot *) retval->funcSlot)->ttc_tupleDescriptor = td;
+ slot->ttc_tupleDescriptor = td;
+
+ retval->funcSlot = (Pointer) slot;
}
else
- retval->funcSlot = (char *) NULL;
+ retval->funcSlot = (Pointer) NULL;
nargs = procedureStruct->pronargs;
retval->nargs = nargs;
@@ -189,8 +178,6 @@ init_fcache(Oid foid,
{
Oid *argTypes;
- retval->nullVect = (bool *) palloc(retval->nargs * sizeof(bool));
-
if (retval->language == SQLlanguageId)
{
int i;
@@ -218,7 +205,6 @@ init_fcache(Oid foid,
else
{
retval->argOidVect = (Oid *) NULL;
- retval->nullVect = (BoolPtr) NULL;
}
if (procedureStruct->prolang == SQLlanguageId)
@@ -257,7 +243,7 @@ init_fcache(Oid foid,
retval->nargs = retval->func.fn_nargs;
}
else
- retval->func.fn_addr = (func_ptr) NULL;
+ retval->func.fn_addr = (PGFunction) NULL;
return retval;
}
@@ -269,7 +255,7 @@ setFcache(Node *node, Oid foid, List *argList, ExprContext *econtext)
Oper *onode;
FunctionCachePtr fcache;
- fcache = init_fcache(foid, true, argList, econtext);
+ fcache = init_fcache(foid, argList, econtext);
if (IsA(node, Oper))
{
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index b9e86d905ec..30f422de7f0 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.96 2000/05/21 02:28:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.97 2000/05/28 17:56:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,6 +58,7 @@
#include "storage/bufmgr.h"
#include "storage/smgr.h"
#include "utils/catcache.h"
+#include "utils/fmgroids.h"
#include "utils/relcache.h"
#include "utils/temprel.h"
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index a460fab05c2..2dfb54391c3 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.39 2000/04/12 17:15:57 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.40 2000/05/28 17:56:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,190 +17,127 @@
#include "postgres.h"
-#include "utils/dynamic_loader.h"
-
#include "access/heapam.h"
-#include "catalog/catname.h"
#include "catalog/pg_proc.h"
#include "dynloader.h"
#include "utils/builtins.h"
+#include "utils/dynamic_loader.h"
#include "utils/syscache.h"
+
+/*
+ * List of dynamically loaded files.
+ */
+
+typedef struct df_files
+{
+ struct df_files *next; /* List link */
+ dev_t device; /* Device file is on */
+ ino_t inode; /* Inode number of file */
+ void *handle; /* a handle for pg_dl* functions */
+ char filename[1]; /* Full pathname of file */
+ /* we allocate the block big enough for actual length of pathname.
+ * filename[] must be last item in struct!
+ */
+} DynamicFileList;
+
static DynamicFileList *file_list = (DynamicFileList *) NULL;
static DynamicFileList *file_tail = (DynamicFileList *) NULL;
-#define NOT_EQUAL(A, B) (((A).st_ino != (B).inode) \
- || ((A).st_dev != (B).device))
+#define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device)
-static Oid procedureId_save = -1;
-static int pronargs_save;
-static func_ptr user_fn_save = (func_ptr) NULL;
-static func_ptr handle_load(char *filename, char *funcname);
-func_ptr
-fmgr_dynamic(Oid procedureId, int *pronargs)
+PGFunction
+fmgr_dynamic(Oid functionId)
{
HeapTuple procedureTuple;
Form_pg_proc procedureStruct;
char *proname,
- *linksymbol,
+ *prosrcstring,
*probinstring;
- char *prosrcstring = NULL;
- Datum probinattr;
- Datum prosrcattr;
- func_ptr user_fn;
- Relation rel;
+ Datum prosrcattr,
+ probinattr;
+ PGFunction user_fn;
bool isnull;
- /* Implement simple one-element cache for function lookups */
- if (procedureId == procedureId_save)
- {
- *pronargs = pronargs_save;
- return user_fn_save;
- }
-
- /*
- * The procedure isn't a builtin, so we'll have to do a catalog lookup
- * to find its pg_proc entry. Moreover, since probin is varlena,
- * we're going to have to use heap_getattr, which means we need the
- * reldesc, which means we need to open the relation. So we might as
- * well do that first and get the benefit of SI inval if needed.
- */
- rel = heap_openr(ProcedureRelationName, AccessShareLock);
-
procedureTuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(procedureId),
+ ObjectIdGetDatum(functionId),
0, 0, 0);
if (!HeapTupleIsValid(procedureTuple))
- {
- elog(ERROR, "fmgr: Cache lookup failed for procedure %u\n",
- procedureId);
- return (func_ptr) NULL;
- }
-
+ elog(ERROR, "fmgr_dynamic: function %u: cache lookup failed",
+ functionId);
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
+
proname = NameStr(procedureStruct->proname);
- pronargs_save = *pronargs = procedureStruct->pronargs;
- probinattr = heap_getattr(procedureTuple,
- Anum_pg_proc_probin,
- RelationGetDescr(rel), &isnull);
- if (!PointerIsValid(probinattr) /* || isnull */ )
+
+ prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
+ Anum_pg_proc_prosrc, &isnull);
+ if (isnull || !PointerIsValid(prosrcattr))
{
- heap_close(rel, AccessShareLock);
- elog(ERROR, "fmgr: Could not extract probin for %u from %s",
- procedureId, ProcedureRelationName);
- return (func_ptr) NULL;
+ elog(ERROR, "fmgr: Could not extract prosrc for %u from pg_proc",
+ functionId);
}
- probinstring = textout((struct varlena *) probinattr);
-
- prosrcattr = heap_getattr(procedureTuple,
- Anum_pg_proc_prosrc,
- RelationGetDescr(rel), &isnull);
+ prosrcstring = textout((text *) DatumGetPointer(prosrcattr));
- if (isnull)
- { /* Use the proname for the link symbol */
- linksymbol = proname;
- }
- else if (!PointerIsValid(prosrcattr))
- { /* pg_proc must be messed up! */
- heap_close(rel, AccessShareLock);
- elog(ERROR, "fmgr: Could not extract prosrc for %u from %s",
- procedureId, ProcedureRelationName);
- return (func_ptr) NULL;
- }
- else
- { /* The text in prosrcattr is either "-" or
- * a link symbol */
- prosrcstring = textout((struct varlena *) prosrcattr);
- if (strcmp(prosrcstring, "-") == 0)
- linksymbol = proname;
- else
- linksymbol = prosrcstring;
+ probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
+ Anum_pg_proc_probin, &isnull);
+ if (isnull || !PointerIsValid(probinattr))
+ {
+ elog(ERROR, "fmgr: Could not extract probin for %u from pg_proc",
+ functionId);
}
+ probinstring = textout((text *) DatumGetPointer(probinattr));
- heap_close(rel, AccessShareLock);
-
- user_fn = handle_load(probinstring, linksymbol);
+ user_fn = load_external_function(probinstring, prosrcstring);
+ pfree(prosrcstring);
pfree(probinstring);
- if (prosrcstring)
- pfree(prosrcstring);
-
- procedureId_save = procedureId;
- user_fn_save = user_fn;
return user_fn;
}
-static func_ptr
-handle_load(char *filename, char *funcname)
+PGFunction
+load_external_function(char *filename, char *funcname)
{
- DynamicFileList *file_scanner = (DynamicFileList *) NULL;
- func_ptr retval = (func_ptr) NULL;
+ DynamicFileList *file_scanner;
+ PGFunction retval;
char *load_error;
struct stat stat_buf;
/*
- * Do this because loading files may screw up the dynamic function
- * manager otherwise.
- */
- procedureId_save = -1;
-
- /*
- * Scan the list of loaded FILES to see if the function has been
- * loaded.
+ * Scan the list of loaded FILES to see if the file has been loaded.
*/
-
- if (filename != (char *) NULL)
+ for (file_scanner = file_list;
+ file_scanner != (DynamicFileList *) NULL &&
+ strcmp(filename, file_scanner->filename) != 0;
+ file_scanner = file_scanner->next)
+ ;
+ if (file_scanner == (DynamicFileList *) NULL)
{
+ /*
+ * Check for same files - different paths (ie, symlink or link)
+ */
+ if (stat(filename, &stat_buf) == -1)
+ elog(ERROR, "stat failed on file '%s': %m", filename);
+
for (file_scanner = file_list;
- file_scanner != (DynamicFileList *) NULL
- && file_scanner->filename != (char *) NULL
- && strcmp(filename, file_scanner->filename) != 0;
+ file_scanner != (DynamicFileList *) NULL &&
+ !SAME_INODE(stat_buf, *file_scanner);
file_scanner = file_scanner->next)
;
- if (file_scanner == (DynamicFileList *) NULL)
- {
- if (stat(filename, &stat_buf) == -1)
- elog(ERROR, "stat failed on file '%s': %m", filename);
-
- for (file_scanner = file_list;
- file_scanner != (DynamicFileList *) NULL
- && (NOT_EQUAL(stat_buf, *file_scanner));
- file_scanner = file_scanner->next)
- ;
-
- /*
- * Same files - different paths (ie, symlink or link)
- */
- if (file_scanner != (DynamicFileList *) NULL)
- strcpy(file_scanner->filename, filename);
-
- }
}
- else
- file_scanner = (DynamicFileList *) NULL;
-
- /*
- * File not loaded yet.
- */
if (file_scanner == (DynamicFileList *) NULL)
{
- if (file_list == (DynamicFileList *) NULL)
- {
- file_list = (DynamicFileList *)
- malloc(sizeof(DynamicFileList));
- file_scanner = file_list;
- }
- else
- {
- file_tail->next = (DynamicFileList *)
- malloc(sizeof(DynamicFileList));
- file_scanner = file_tail->next;
- }
- MemSet((char *) file_scanner, 0, sizeof(DynamicFileList));
+ /*
+ * File not loaded yet.
+ */
+ file_scanner = (DynamicFileList *)
+ malloc(sizeof(DynamicFileList) + strlen(filename));
+ if (file_scanner == NULL)
+ elog(FATAL, "Out of memory in load_external_function");
+ MemSet((char *) file_scanner, 0, sizeof(DynamicFileList));
strcpy(file_scanner->filename, filename);
file_scanner->device = stat_buf.st_dev;
file_scanner->inode = stat_buf.st_ino;
@@ -210,42 +147,36 @@ handle_load(char *filename, char *funcname)
if (file_scanner->handle == (void *) NULL)
{
load_error = (char *) pg_dlerror();
- if (file_scanner == file_list)
- file_list = (DynamicFileList *) NULL;
- else
- file_tail->next = (DynamicFileList *) NULL;
-
free((char *) file_scanner);
elog(ERROR, "Load of file %s failed: %s", filename, load_error);
}
- /*
- * Just load the file - we are done with that so return.
- */
+ /* OK to link it into list */
+ if (file_list == (DynamicFileList *) NULL)
+ file_list = file_scanner;
+ else
+ file_tail->next = file_scanner;
file_tail = file_scanner;
-
- if (funcname == (char *) NULL)
- return (func_ptr) NULL;
}
- retval = (func_ptr) pg_dlsym(file_scanner->handle, funcname);
+ /*
+ * If funcname is NULL, we only wanted to load the file.
+ */
+ if (funcname == (char *) NULL)
+ return (PGFunction) NULL;
+
+ retval = pg_dlsym(file_scanner->handle, funcname);
- if (retval == (func_ptr) NULL)
+ if (retval == (PGFunction) NULL)
elog(ERROR, "Can't find function %s in file %s", funcname, filename);
return retval;
}
/*
- * This function loads files by the following:
- *
- * If the file is already loaded:
- * o Zero out that file's loaded space (so it doesn't screw up linking)
- * o Free all space associated with that file
- * o Free that file's descriptor.
- *
- * Now load the file by calling handle_load with a NULL argument as the
- * function.
+ * This function loads a shlib file without looking up any particular
+ * function in it. If the same shlib has previously been loaded,
+ * unload and reload it.
*/
void
load_file(char *filename)
@@ -253,7 +184,6 @@ load_file(char *filename)
DynamicFileList *file_scanner,
*p;
struct stat stat_buf;
- int done = 0;
/*
* We need to do stat() in order to determine whether this is the same
@@ -263,48 +193,32 @@ load_file(char *filename)
if (stat(filename, &stat_buf) == -1)
elog(ERROR, "LOAD: could not open file '%s': %m", filename);
- if (file_list != (DynamicFileList *) NULL
- && !NOT_EQUAL(stat_buf, *file_list))
+ if (file_list != (DynamicFileList *) NULL)
{
- file_scanner = file_list;
- file_list = file_list->next;
- pg_dlclose(file_scanner->handle);
- free((char *) file_scanner);
- }
- else if (file_list != (DynamicFileList *) NULL)
- {
- file_scanner = file_list;
- while (!done)
+ if (SAME_INODE(stat_buf, *file_list))
{
- if (file_scanner->next == (DynamicFileList *) NULL)
- done = 1;
- else if (!NOT_EQUAL(stat_buf, *(file_scanner->next)))
- done = 1;
- else
- file_scanner = file_scanner->next;
+ p = file_list;
+ file_list = p->next;
+ pg_dlclose(p->handle);
+ free((char *) p);
}
-
- if (file_scanner->next != (DynamicFileList *) NULL)
+ else
{
- p = file_scanner->next;
- file_scanner->next = file_scanner->next->next;
- pg_dlclose(file_scanner->handle);
- free((char *) p);
+ for (file_scanner = file_list;
+ file_scanner->next != (DynamicFileList *) NULL;
+ file_scanner = file_scanner->next)
+ {
+ if (SAME_INODE(stat_buf, *(file_scanner->next)))
+ {
+ p = file_scanner->next;
+ file_scanner->next = p->next;
+ pg_dlclose(p->handle);
+ free((char *) p);
+ break;
+ }
+ }
}
}
- handle_load(filename, (char *) NULL);
-}
-
-/* Is this used? bjm 1998/10/08 No. tgl 1999/02/07 */
-#ifdef NOT_USED
-func_ptr
-trigger_dynamic(char *filename, char *funcname)
-{
- func_ptr trigger_fn;
- trigger_fn = handle_load(filename, funcname);
-
- return trigger_fn;
+ load_external_function(filename, (char *) NULL);
}
-
-#endif
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index bdac32a2551..793497834fd 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* fmgr.c
- * Interface routines for the table-driven function manager.
+ * The Postgres function manager.
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.39 2000/05/22 02:34:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.40 2000/05/28 17:56:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,112 +17,249 @@
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
-#include "commands/trigger.h"
+#include "commands/trigger.h" /* TEMPORARY: for CurrentTriggerData */
#include "utils/builtins.h"
#include "utils/fmgrtab.h"
#include "utils/syscache.h"
+static Datum fmgr_oldstyle(PG_FUNCTION_ARGS);
+static Datum fmgr_untrusted(PG_FUNCTION_ARGS);
+static Datum fmgr_sql(PG_FUNCTION_ARGS);
+
/*
- * Interface for PL functions
- *
- * XXX: use of global fmgr_pl_finfo variable is really ugly. FIXME
+ * Lookup routines for builtin-function table. We can search by either Oid
+ * or name, but search by Oid is much faster.
*/
-FmgrInfo *fmgr_pl_finfo;
-static char *
-fmgr_pl(char *arg0,...)
+static const FmgrBuiltin *
+fmgr_isbuiltin(Oid id)
{
- va_list pvar;
- FmgrValues values;
- int n_arguments = fmgr_pl_finfo->fn_nargs;
- bool isNull = false;
- int i;
+ int low = 0;
+ int high = fmgr_nbuiltins - 1;
- memset(&values, 0, sizeof(values));
+ /* Loop invariant: low is the first index that could contain target
+ * entry, and high is the last index that could contain it.
+ */
+ while (low <= high)
+ {
+ int i = (high + low) / 2;
+ const FmgrBuiltin *ptr = &fmgr_builtins[i];
- if (n_arguments > 0)
+ if (id == ptr->foid)
+ return ptr;
+ else if (id > ptr->foid)
+ low = i + 1;
+ else
+ high = i - 1;
+ }
+ return (const FmgrBuiltin *) NULL;
+}
+
+/*
+ * Lookup a builtin by name. Note there can be more than one entry in
+ * the array with the same name, but they should all point to the same
+ * routine.
+ */
+static const FmgrBuiltin *
+fmgr_lookupByName(const char *name)
+{
+ int i;
+
+ for (i = 0; i < fmgr_nbuiltins; i++)
{
- values.data[0] = arg0;
- if (n_arguments > 1)
+ if (strcmp(name, fmgr_builtins[i].funcName) == 0)
+ return fmgr_builtins + i;
+ }
+ return (const FmgrBuiltin *) NULL;
+}
+
+/*
+ * This routine fills a FmgrInfo struct, given the OID
+ * of the function to be called.
+ */
+void
+fmgr_info(Oid functionId, FmgrInfo *finfo)
+{
+ const FmgrBuiltin *fbp;
+ HeapTuple procedureTuple;
+ Form_pg_proc procedureStruct;
+ HeapTuple languageTuple;
+ Form_pg_language languageStruct;
+ Oid language;
+ char *prosrc;
+
+ finfo->fn_oid = functionId;
+ finfo->fn_extra = NULL;
+
+ if ((fbp = fmgr_isbuiltin(functionId)) != NULL)
+ {
+ /*
+ * Fast path for builtin functions: don't bother consulting pg_proc
+ */
+ finfo->fn_nargs = fbp->nargs;
+ finfo->fn_strict = fbp->strict;
+ if (fbp->oldstyle)
{
- if (n_arguments > FUNC_MAX_ARGS)
- elog(ERROR, "fmgr_pl: function %u: too many arguments (%d > %d)",
- fmgr_pl_finfo->fn_oid, n_arguments, FUNC_MAX_ARGS);
- va_start(pvar, arg0);
- for (i = 1; i < n_arguments; i++)
- values.data[i] = va_arg(pvar, char *);
- va_end(pvar);
+ finfo->fn_addr = fmgr_oldstyle;
+ finfo->fn_extra = (void *) fbp->func;
}
+ else
+ {
+ finfo->fn_addr = fbp->func;
+ }
+ return;
}
- /* Call the PL handler */
- CurrentTriggerData = NULL;
- return (*(fmgr_pl_finfo->fn_plhandler)) (fmgr_pl_finfo,
- &values,
- &isNull);
-}
+ /* Otherwise we need the pg_proc entry */
+ procedureTuple = SearchSysCacheTuple(PROCOID,
+ ObjectIdGetDatum(functionId),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(procedureTuple))
+ elog(ERROR, "fmgr_info: function %u: cache lookup failed",
+ functionId);
+ procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
+ finfo->fn_nargs = procedureStruct->pronargs;
+ finfo->fn_strict = procedureStruct->proisstrict;
-/*
- * Interface for untrusted functions
- */
+ if (!procedureStruct->proistrusted)
+ {
+ finfo->fn_addr = fmgr_untrusted;
+ return;
+ }
-static char *
-fmgr_untrusted(char *arg0,...)
-{
+ language = procedureStruct->prolang;
+ switch (language)
+ {
+ case INTERNALlanguageId:
+ case NEWINTERNALlanguageId:
+ /*
+ * For an ordinary builtin function, we should never get
+ * here because the isbuiltin() search above will have
+ * succeeded. However, if the user has done a CREATE
+ * FUNCTION to create an alias for a builtin function, we
+ * can end up here. In that case we have to look up the
+ * function by name. The name of the internal function is
+ * stored in prosrc (it doesn't have to be the same as the
+ * name of the alias!)
+ */
+ prosrc = textout(&(procedureStruct->prosrc));
+ fbp = fmgr_lookupByName(prosrc);
+ if (fbp == NULL)
+ elog(ERROR, "fmgr_info: function %s not in internal table",
+ prosrc);
+ pfree(prosrc);
+ if (fbp->oldstyle)
+ {
+ finfo->fn_addr = fmgr_oldstyle;
+ finfo->fn_extra = (void *) fbp->func;
+ }
+ else
+ {
+ finfo->fn_addr = fbp->func;
+ }
+ break;
- /*
- * Currently these are unsupported. Someday we might do something
- * like forking a subprocess to execute 'em.
- */
- elog(ERROR, "Untrusted functions not supported.");
- return NULL; /* keep compiler happy */
+ case ClanguageId:
+ finfo->fn_addr = fmgr_oldstyle;
+ finfo->fn_extra = (void *) fmgr_dynamic(functionId);
+ break;
+
+ case NEWClanguageId:
+ finfo->fn_addr = fmgr_dynamic(functionId);
+ break;
+
+ case SQLlanguageId:
+ finfo->fn_addr = fmgr_sql;
+ break;
+
+ default:
+ /*
+ * Might be a created procedural language; try to look it up.
+ */
+ languageTuple = SearchSysCacheTuple(LANGOID,
+ ObjectIdGetDatum(language),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(languageTuple))
+ {
+ elog(ERROR, "fmgr_info: cache lookup for language %u failed",
+ language);
+ }
+ languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
+ if (languageStruct->lanispl)
+ {
+ FmgrInfo plfinfo;
+
+ fmgr_info(languageStruct->lanplcallfoid, &plfinfo);
+ finfo->fn_addr = plfinfo.fn_addr;
+ /*
+ * If lookup of the PL handler function produced nonnull
+ * fn_extra, complain --- it must be an oldstyle function!
+ * We no longer support oldstyle PL handlers.
+ */
+ if (plfinfo.fn_extra != NULL)
+ elog(ERROR, "fmgr_info: language %u has old-style handler",
+ language);
+ }
+ else
+ {
+ elog(ERROR, "fmgr_info: function %u: unsupported language %u",
+ functionId, language);
+ }
+ break;
+ }
}
/*
- * Interface for SQL-language functions
+ * Specialized lookup routine for pg_proc.c: given the alleged name of
+ * an internal function, return the OID of the function's language.
+ * If the name is not known, return InvalidOid.
*/
-
-static char *
-fmgr_sql(char *arg0,...)
+Oid
+fmgr_internal_language(const char *proname)
{
+ const FmgrBuiltin *fbp = fmgr_lookupByName(proname);
- /*
- * XXX It'd be really nice to support SQL functions anywhere that
- * builtins are supported. What would we have to do? What pitfalls
- * are there?
- */
- elog(ERROR, "SQL-language function not supported in this context.");
- return NULL; /* keep compiler happy */
+ if (fbp == NULL)
+ return InvalidOid;
+ return fbp->oldstyle ? INTERNALlanguageId : NEWINTERNALlanguageId;
}
/*
- * fmgr_c is not really for C functions only; it can be called for functions
- * in any language. Many parts of the system use this entry point if they
- * want to pass the arguments in an array rather than as explicit arguments.
+ * Handler for old-style internal and "C" language functions
+ *
+ * We expect fmgr_info to have placed the old-style function's address
+ * in fn_extra of *flinfo. This is a bit of a hack since fn_extra is really
+ * void * which might be a different size than a pointer to function, but
+ * it will work on any machine that our old-style call interface works on...
*/
-
-char *
-fmgr_c(FmgrInfo *finfo,
- FmgrValues *values,
- bool *isNull)
+static Datum
+fmgr_oldstyle(PG_FUNCTION_ARGS)
{
- char *returnValue = (char *) NULL;
- int n_arguments = finfo->fn_nargs;
- func_ptr user_fn = fmgr_faddr(finfo);
+ char *returnValue = NULL;
+ int n_arguments = fcinfo->nargs;
+ int i;
+ bool isnull;
+ func_ptr user_fn;
+
+ if (fcinfo->flinfo == NULL || fcinfo->flinfo->fn_extra == NULL)
+ elog(ERROR, "Internal error: fmgr_oldstyle received NULL function pointer");
/*
- * If finfo contains a PL handler for this function, call that
- * instead.
+ * Result is NULL if any argument is NULL, but we still call the function
+ * (peculiar, but that's the way it worked before, and after all this is
+ * a backwards-compatibility wrapper). Note, however, that we'll never
+ * get here with NULL arguments if the function is marked strict.
*/
- if (finfo->fn_plhandler != NULL)
- return (*(finfo->fn_plhandler)) (finfo, values, isNull);
+ isnull = false;
+ for (i = 0; i < n_arguments; i++)
+ isnull |= PG_ARGISNULL(i);
+ fcinfo->isnull = isnull;
- if (user_fn == (func_ptr) NULL)
- elog(ERROR, "Internal error: fmgr_c received NULL function pointer.");
+ user_fn = (func_ptr) fcinfo->flinfo->fn_extra;
switch (n_arguments)
{
@@ -130,604 +267,1038 @@ fmgr_c(FmgrInfo *finfo,
returnValue = (*user_fn) ();
break;
case 1:
- /* NullValue() uses isNull to check if args[0] is NULL */
- returnValue = (*user_fn) (values->data[0], isNull);
+ /*
+ * nullvalue() used to use isNull to check if arg is NULL;
+ * perhaps there are other functions still out there that
+ * also rely on this undocumented hack?
+ */
+ returnValue = (*user_fn) (fcinfo->arg[0], & fcinfo->isnull);
break;
case 2:
- returnValue = (*user_fn) (values->data[0], values->data[1]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1]);
break;
case 3:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2]);
break;
case 4:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3]);
break;
case 5:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4]);
break;
case 6:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5]);
break;
case 7:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6]);
break;
case 8:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7]);
break;
case 9:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8]);
break;
-#if FUNC_MAX_ARGS >= 10
case 10:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8], fcinfo->arg[9]);
break;
-#endif
-#if FUNC_MAX_ARGS >= 11
case 11:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8], fcinfo->arg[9],
+ fcinfo->arg[10]);
break;
-#endif
-#if FUNC_MAX_ARGS >= 12
case 12:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8], fcinfo->arg[9],
+ fcinfo->arg[10], fcinfo->arg[11]);
break;
-#endif
-#if FUNC_MAX_ARGS >= 13
case 13:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8], fcinfo->arg[9],
+ fcinfo->arg[10], fcinfo->arg[11],
+ fcinfo->arg[12]);
break;
-#endif
-#if FUNC_MAX_ARGS >= 14
case 14:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8], fcinfo->arg[9],
+ fcinfo->arg[10], fcinfo->arg[11],
+ fcinfo->arg[12], fcinfo->arg[13]);
break;
-#endif
-#if FUNC_MAX_ARGS >= 15
case 15:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8], fcinfo->arg[9],
+ fcinfo->arg[10], fcinfo->arg[11],
+ fcinfo->arg[12], fcinfo->arg[13],
+ fcinfo->arg[14]);
break;
-#endif
-#if FUNC_MAX_ARGS >= 16
case 16:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 17
- case 17:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 18
- case 18:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 19
- case 19:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 20
- case 20:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 21
- case 21:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 22
- case 22:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 23
- case 23:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 24
- case 24:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 25
- case 25:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 26
- case 26:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24], values->data[25]);
+ returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1],
+ fcinfo->arg[2], fcinfo->arg[3],
+ fcinfo->arg[4], fcinfo->arg[5],
+ fcinfo->arg[6], fcinfo->arg[7],
+ fcinfo->arg[8], fcinfo->arg[9],
+ fcinfo->arg[10], fcinfo->arg[11],
+ fcinfo->arg[12], fcinfo->arg[13],
+ fcinfo->arg[14], fcinfo->arg[15]);
break;
-#endif
-#if FUNC_MAX_ARGS >= 27
- case 27:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24], values->data[25],
- values->data[26]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 28
- case 28:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24], values->data[25],
- values->data[26], values->data[27]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 29
- case 29:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24], values->data[25],
- values->data[26], values->data[27],
- values->data[28]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 30
- case 30:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24], values->data[25],
- values->data[26], values->data[27],
- values->data[28], values->data[29]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 31
- case 31:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24], values->data[25],
- values->data[26], values->data[27],
- values->data[28], values->data[29],
- values->data[30]);
- break;
-#endif
-#if FUNC_MAX_ARGS >= 32
- case 32:
- returnValue = (*user_fn) (values->data[0], values->data[1],
- values->data[2], values->data[3],
- values->data[4], values->data[5],
- values->data[6], values->data[7],
- values->data[8], values->data[9],
- values->data[10], values->data[11],
- values->data[12], values->data[13],
- values->data[14], values->data[15],
- values->data[16], values->data[17],
- values->data[18], values->data[19],
- values->data[20], values->data[21],
- values->data[22], values->data[23],
- values->data[24], values->data[25],
- values->data[26], values->data[27],
- values->data[28], values->data[29],
- values->data[30], values->data[31]);
- break;
-#endif
default:
- elog(ERROR, "fmgr_c: function %u: too many arguments (%d > %d)",
- finfo->fn_oid, n_arguments, FUNC_MAX_ARGS);
+ /*
+ * Increasing FUNC_MAX_ARGS doesn't automatically add cases
+ * to the above code, so give the actual value in this error
+ * not FUNC_MAX_ARGS. You could add cases to the above if you
+ * needed to support old-style functions with many arguments,
+ * but making 'em be new-style is probably a better idea.
+ */
+ elog(ERROR, "fmgr_oldstyle: function %u: too many arguments (%d > %d)",
+ fcinfo->flinfo->fn_oid, n_arguments, 16);
break;
}
- return returnValue;
+
+ return (Datum) returnValue;
}
+
/*
- * Expand a regproc OID into an FmgrInfo cache struct.
+ * Handler for all functions marked "untrusted"
*/
+static Datum
+fmgr_untrusted(PG_FUNCTION_ARGS)
+{
+ /*
+ * Currently these are unsupported. Someday we might do something
+ * like forking a subprocess to execute 'em.
+ */
+ elog(ERROR, "Untrusted functions not supported");
+ return 0; /* keep compiler happy */
+}
-void
-fmgr_info(Oid procedureId, FmgrInfo *finfo)
+/*
+ * Handler for SQL-language functions
+ */
+static Datum
+fmgr_sql(PG_FUNCTION_ARGS)
{
- FmgrCall *fcp;
- HeapTuple procedureTuple;
- FormData_pg_proc *procedureStruct;
- HeapTuple languageTuple;
- Form_pg_language languageStruct;
- Oid language;
- char *prosrc;
+ /*
+ * XXX It'd be really nice to support SQL functions anywhere that
+ * builtins are supported. What would we have to do? What pitfalls
+ * are there?
+ */
+ elog(ERROR, "SQL-language function not supported in this context");
+ return 0; /* keep compiler happy */
+}
- finfo->fn_addr = NULL;
- finfo->fn_plhandler = NULL;
- finfo->fn_oid = procedureId;
+/*
+ * Interface routine for functions using fmgr_faddr
+ */
+FmgrInfo *fmgr_pl_finfo; /* should GO AWAY */
- if ((fcp = fmgr_isbuiltin(procedureId)) != NULL)
- {
+char *
+fmgr_faddr_link(char *arg0, ...)
+{
+ FunctionCallInfoData fcinfo;
+ int n_arguments;
+ Datum result;
- /*
- * Fast path for builtin functions: don't bother consulting
- * pg_proc
- */
- finfo->fn_addr = fcp->func;
- finfo->fn_nargs = fcp->nargs;
- }
- else
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ /* We rely on fmgr_faddr macro to have set back-link to FmgrInfo (ugh) */
+ fcinfo.flinfo = fmgr_pl_finfo;
+ fcinfo.nargs = fcinfo.flinfo->fn_nargs;
+ n_arguments = fcinfo.nargs;
+
+ if (n_arguments > 0)
{
- procedureTuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(procedureId),
- 0, 0, 0);
- if (!HeapTupleIsValid(procedureTuple))
- {
- elog(ERROR, "fmgr_info: function %u: cache lookup failed",
- procedureId);
- }
- procedureStruct = (FormData_pg_proc *) GETSTRUCT(procedureTuple);
- if (!procedureStruct->proistrusted)
- {
- finfo->fn_addr = (func_ptr) fmgr_untrusted;
- finfo->fn_nargs = procedureStruct->pronargs;
- return;
- }
- language = procedureStruct->prolang;
- switch (language)
+ fcinfo.arg[0] = (Datum) arg0;
+ if (n_arguments > 1)
{
- case INTERNALlanguageId:
-
- /*
- * For an ordinary builtin function, we should never get
- * here because the isbuiltin() search above will have
- * succeeded. However, if the user has done a CREATE
- * FUNCTION to create an alias for a builtin function, we
- * end up here. In that case we have to look up the
- * function by name. The name of the internal function is
- * stored in prosrc (it doesn't have to be the same as the
- * name of the alias!)
- */
- prosrc = textout(&(procedureStruct->prosrc));
- finfo->fn_addr = fmgr_lookupByName(prosrc);
- if (!finfo->fn_addr)
- elog(ERROR, "fmgr_info: function %s not in internal table",
- prosrc);
- finfo->fn_nargs = procedureStruct->pronargs;
- pfree(prosrc);
- break;
- case ClanguageId:
- finfo->fn_addr = fmgr_dynamic(procedureId, &(finfo->fn_nargs));
- break;
- case SQLlanguageId:
- finfo->fn_addr = (func_ptr) fmgr_sql;
- finfo->fn_nargs = procedureStruct->pronargs;
- break;
- default:
+ va_list pvar;
+ int i;
- /*
- * Might be a created procedural language Lookup the
- * syscache for the language and check the lanispl flag If
- * this is the case, we return a NULL function pointer and
- * the number of arguments from the procedure.
- */
- languageTuple = SearchSysCacheTuple(LANGOID,
- ObjectIdGetDatum(procedureStruct->prolang),
- 0, 0, 0);
- if (!HeapTupleIsValid(languageTuple))
- {
- elog(ERROR, "fmgr_info: %s %u",
- "Cache lookup for language failed",
- DatumGetObjectId(procedureStruct->prolang));
- }
- languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
- if (languageStruct->lanispl)
- {
- FmgrInfo plfinfo;
-
- fmgr_info(languageStruct->lanplcallfoid, &plfinfo);
- finfo->fn_addr = (func_ptr) fmgr_pl;
- finfo->fn_plhandler = plfinfo.fn_addr;
- finfo->fn_nargs = procedureStruct->pronargs;
- }
- else
- {
- elog(ERROR, "fmgr_info: function %u: unknown language %d",
- procedureId, language);
- }
- break;
+ if (n_arguments > FUNC_MAX_ARGS)
+ elog(ERROR, "fmgr_faddr_link: function %u: too many arguments (%d > %d)",
+ fcinfo.flinfo->fn_oid, n_arguments, FUNC_MAX_ARGS);
+ va_start(pvar, arg0);
+ for (i = 1; i < n_arguments; i++)
+ fcinfo.arg[i] = (Datum) va_arg(pvar, char *);
+ va_end(pvar);
}
}
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "fmgr_faddr_link: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return (char *) result;
}
/*
* fmgr - return the value of a function call
*
- * If the function is a system routine, it's compiled in, so call
- * it directly.
- *
- * Otherwise pass it to the the appropriate 'language' function caller.
- *
- * Returns the return value of the invoked function if succesful,
- * 0 if unsuccessful.
+ * This is essentially fmgr_info plus call the function.
*/
char *
fmgr(Oid procedureId,...)
{
- va_list pvar;
- int i;
- int pronargs;
- FmgrValues values;
- FmgrInfo finfo;
- bool isNull = false;
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ int n_arguments;
+ Datum result;
+
+ fmgr_info(procedureId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = flinfo.fn_nargs;
+ n_arguments = fcinfo.nargs;
+
+ if (n_arguments > 0)
+ {
+ va_list pvar;
+ int i;
- fmgr_info(procedureId, &finfo);
- pronargs = finfo.fn_nargs;
+ if (n_arguments > FUNC_MAX_ARGS)
+ elog(ERROR, "fmgr: function %u: too many arguments (%d > %d)",
+ flinfo.fn_oid, n_arguments, FUNC_MAX_ARGS);
+ va_start(pvar, procedureId);
+ for (i = 0; i < n_arguments; i++)
+ fcinfo.arg[i] = (Datum) va_arg(pvar, char *);
+ va_end(pvar);
+ }
- if (pronargs > FUNC_MAX_ARGS)
- elog(ERROR, "fmgr: function %u: too many arguments (%d > %d)",
- procedureId, pronargs, FUNC_MAX_ARGS);
+ result = FunctionCallInvoke(&fcinfo);
- va_start(pvar, procedureId);
- for (i = 0; i < pronargs; ++i)
- values.data[i] = va_arg(pvar, char *);
- va_end(pvar);
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "fmgr: function %u returned NULL",
+ flinfo.fn_oid);
- /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
- return fmgr_c(&finfo, &values, &isNull);
+ return (char *) result;
}
-/*
- * This is just a version of fmgr() in which the hacker can prepend a C
- * function pointer. This routine is not normally called; generally,
- * if you have all of this information you're likely to just jump through
- * the pointer, but it's available for use with macros in fmgr.h if you
- * want this routine to do sanity-checking for you.
- *
- * funcinfo, n_arguments, args...
+
+/*-------------------------------------------------------------------------
+ * Support routines for callers of fmgr-compatible functions
+ *-------------------------------------------------------------------------
*/
-#ifdef TRACE_FMGR_PTR
-char *
-fmgr_ptr(FmgrInfo *finfo,...)
+/* 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. Also, the function cannot be one that needs to
+ * look at FmgrInfo, since there won't be any.
+ */
+Datum
+DirectFunctionCall1(PGFunction func, Datum arg1)
{
- va_list pvar;
- int i;
- int n_arguments;
- FmgrInfo local_finfo;
- FmgrValues values;
- bool isNull = false;
-
- local_finfo->fn_addr = finfo->fn_addr;
- local_finfo->fn_plhandler = finfo->fn_plhandler;
- local_finfo->fn_oid = finfo->fn_oid;
-
- va_start(pvar, finfo);
- n_arguments = va_arg(pvar, int);
- local_finfo->fn_nargs = n_arguments;
- if (n_arguments > FUNC_MAX_ARGS)
- {
- elog(ERROR, "fmgr_ptr: function %u: too many arguments (%d > %d)",
- func_id, n_arguments, FUNC_MAX_ARGS);
- }
- for (i = 0; i < n_arguments; ++i)
- values.data[i] = va_arg(pvar, char *);
- va_end(pvar);
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 1;
+ fcinfo.arg[0] = arg1;
- /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
- return fmgr_c(&local_finfo, &values, &isNull);
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall1: function %p returned NULL",
+ (void *) func);
+
+ return result;
}
-#endif
+Datum
+DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
-/*
- * This routine is not well thought out. When I get around to adding a
- * function pointer field to FuncIndexInfo, it will be replace by calls
- * to fmgr_c().
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 2;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall2: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+Datum
+DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2,
+ Datum arg3)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 3;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall3: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+Datum
+DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 4;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall4: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+Datum
+DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 5;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+ fcinfo.arg[4] = arg5;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall5: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+Datum
+DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 6;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+ fcinfo.arg[4] = arg5;
+ fcinfo.arg[5] = arg6;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall6: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+Datum
+DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 7;
+ 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;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall7: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+Datum
+DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 8;
+ 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;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall8: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+Datum
+DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8,
+ Datum arg9)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.nargs = 9;
+ 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;
+
+ result = (* func) (&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "DirectFunctionCall9: function %p returned NULL",
+ (void *) func);
+
+ return result;
+}
+
+
+/* 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.
*/
-char *
-fmgr_array_args(Oid procedureId, int nargs, char *args[], bool *isNull)
+Datum
+FunctionCall1(FmgrInfo *flinfo, Datum arg1)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 1;
+ fcinfo.arg[0] = arg1;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall1: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 2;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall2: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+ Datum arg3)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 3;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall3: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 4;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall4: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 5;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+ fcinfo.arg[4] = arg5;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall5: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 6;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+ fcinfo.arg[4] = arg5;
+ fcinfo.arg[5] = arg6;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall6: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7)
{
- FmgrInfo finfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 7;
+ 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;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall7: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 8;
+ 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;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall8: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+
+ return result;
+}
+
+Datum
+FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8,
+ Datum arg9)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = flinfo;
+ fcinfo.nargs = 9;
+ 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;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "FunctionCall9: function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
- fmgr_info(procedureId, &finfo);
- finfo.fn_nargs = nargs;
+ return result;
+}
+
+
+/* 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 fmgr_info() followed
+ * by FunctionCallN(). If the same function is to be invoked repeatedly,
+ * do the fmgr_info() once and then use FunctionCallN().
+ */
+Datum
+OidFunctionCall1(Oid functionId, Datum arg1)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 1;
+ fcinfo.arg[0] = arg1;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall1: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 2;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall2: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
+ Datum arg3)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 3;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall3: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 4;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall4: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 5;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+ fcinfo.arg[4] = arg5;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall5: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 6;
+ fcinfo.arg[0] = arg1;
+ fcinfo.arg[1] = arg2;
+ fcinfo.arg[2] = arg3;
+ fcinfo.arg[3] = arg4;
+ fcinfo.arg[4] = arg5;
+ fcinfo.arg[5] = arg6;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall6: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 7;
+ 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;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall7: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 8;
+ 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;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall8: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+Datum
+OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8,
+ Datum arg9)
+{
+ FmgrInfo flinfo;
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ fmgr_info(functionId, &flinfo);
+
+ MemSet(&fcinfo, 0, sizeof(fcinfo));
+ fcinfo.flinfo = &flinfo;
+ fcinfo.nargs = 9;
+ 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;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo.isnull)
+ elog(ERROR, "OidFunctionCall9: function %u returned NULL",
+ flinfo.fn_oid);
+
+ return result;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Support routines for standard pass-by-reference datatypes
+ *
+ * Note: at some point, at least on some platforms, these might become
+ * pass-by-value types. Obviously Datum must be >= 8 bytes to allow
+ * int64 or float8 to be pass-by-value. I think that Float4GetDatum
+ * and Float8GetDatum will need to be out-of-line routines anyway,
+ * since just casting from float to Datum will not do the right thing;
+ * some kind of trick with pointer-casting or a union will be needed.
+ *-------------------------------------------------------------------------
+ */
+
+Datum
+Int64GetDatum(int64 X)
+{
+ int64 *retval = (int64 *) palloc(sizeof(int64));
+
+ *retval = X;
+ return PointerGetDatum(retval);
+}
+
+Datum
+Float4GetDatum(float4 X)
+{
+ float4 *retval = (float4 *) palloc(sizeof(float4));
+
+ *retval = X;
+ return PointerGetDatum(retval);
+}
+
+Datum
+Float8GetDatum(float8 X)
+{
+ float8 *retval = (float8 *) palloc(sizeof(float8));
- /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
- return fmgr_c(&finfo,
- (FmgrValues *) args,
- isNull);
+ *retval = X;
+ return PointerGetDatum(retval);
}
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index c4675a6b57d..68e293ef1da 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.57 2000/04/12 17:16:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.58 2000/05/28 17:56:08 tgl Exp $
*
*
*-------------------------------------------------------------------------
@@ -30,6 +30,7 @@
#include "storage/proc.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
+#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/portal.h"
#include "utils/relcache.h"