1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-16 15:02:33 +03:00

First round of changes for new fmgr interface. fmgr itself and the

key call sites are changed, but most called functions are still oldstyle.
An exception is that the PL managers are updated (so, for example, NULL
handling now behaves as expected in plperl and plpgsql functions).
NOTE initdb is forced due to added column in pg_proc.
This commit is contained in:
Tom Lane
2000-05-28 17:56:29 +00:00
parent 5005bb060b
commit 0a7fb4e918
80 changed files with 3779 additions and 2908 deletions

View File

@@ -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

View File

@@ -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))

View File

@@ -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

View File

@@ -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"
/*****************************************************************************

View File

@@ -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:

View File

@@ -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 */

View File

@@ -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"

View File

@@ -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))
{

View File

@@ -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"

View File

@@ -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);
prosrcstring = textout((text *) DatumGetPointer(prosrcattr));
prosrcattr = heap_getattr(procedureTuple,
Anum_pg_proc_prosrc,
RelationGetDescr(rel), &isnull);
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.
* Scan the list of loaded FILES to see if the file has been loaded.
*/
procedureId_save = -1;
/*
* Scan the list of loaded FILES to see if the function 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;
if (retval == (func_ptr) NULL)
retval = pg_dlsym(file_scanner->handle, funcname);
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;
}
if (file_scanner->next != (DynamicFileList *) NULL)
{
p = file_scanner->next;
file_scanner->next = file_scanner->next->next;
pg_dlclose(file_scanner->handle);
p = file_list;
file_list = p->next;
pg_dlclose(p->handle);
free((char *) p);
}
else
{
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);
load_external_function(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;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -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"