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

@ -34,7 +34,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.47 2000/05/11 17:46:28 momjian Exp $ # $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.48 2000/05/28 17:55:51 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -79,7 +79,7 @@ all: postgres $(POSTGRES_IMP) global1.bki.source local1_template1.bki.source \
global1.description local1_template1.description global1.description local1_template1.description
ifneq ($(PORTNAME), win) ifneq ($(PORTNAME), win)
postgres: fmgr.h $(OBJS) $(VERSIONOBJ) postgres: utils/fmgroids.h $(OBJS) $(VERSIONOBJ)
$(CC) $(CFLAGS) -o postgres $(OBJS) $(OBJS1) $(VERSIONOBJ) $(LDFLAGS) $(CC) $(CFLAGS) -o postgres $(OBJS) $(OBJS1) $(VERSIONOBJ) $(LDFLAGS)
else else
postgres: $(DLLOBJS) $(SRCDIR)/utils/dllinit.o postgres.def libpostgres.a postgres: $(DLLOBJS) $(SRCDIR)/utils/dllinit.o postgres.def libpostgres.a
@ -126,15 +126,12 @@ parse.h: parser/parse.h
parser/parse.h: parser/parse.h:
$(MAKE) -C parser parse.h $(MAKE) -C parser parse.h
fmgr.h: utils/fmgr.h utils/fmgroids.h:
cp utils/fmgr.h . $(MAKE) -C utils fmgroids.h
utils/fmgr.h:
$(MAKE) -C utils fmgr.h
############################################################################# #############################################################################
clean: clean:
rm -f postgres$(X) $(POSTGRES_IMP) fmgr.h parse.h \ rm -f postgres$(X) $(POSTGRES_IMP) parse.h \
global1.bki.source local1_template1.bki.source \ global1.bki.source local1_template1.bki.source \
global1.description local1_template1.description global1.description local1_template1.description
ifeq ($(PORTNAME), win) ifeq ($(PORTNAME), win)
@ -205,7 +202,7 @@ install-templates: $(TEMPLATEDIR) \
$(INSTALL) $(INSTLOPTS) pg_options.sample \ $(INSTALL) $(INSTLOPTS) pg_options.sample \
$(TEMPLATEDIR)/pg_options.sample $(TEMPLATEDIR)/pg_options.sample
install-headers: fmgr.h $(SRCDIR)/include/config.h install-headers: utils/fmgroids.h $(SRCDIR)/include/config.h
-@if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi -@if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi
-@if [ ! -d $(HEADERDIR)/port ]; then mkdir $(HEADERDIR)/port; fi -@if [ ! -d $(HEADERDIR)/port ]; then mkdir $(HEADERDIR)/port; fi
-@if [ ! -d $(HEADERDIR)/port/$(PORTNAME) ]; \ -@if [ ! -d $(HEADERDIR)/port/$(PORTNAME) ]; \
@ -222,8 +219,6 @@ install-headers: fmgr.h $(SRCDIR)/include/config.h
then mkdir $(HEADERDIR)/executor; fi then mkdir $(HEADERDIR)/executor; fi
-@if [ ! -d $(HEADERDIR)/commands ]; \ -@if [ ! -d $(HEADERDIR)/commands ]; \
then mkdir $(HEADERDIR)/commands; fi then mkdir $(HEADERDIR)/commands; fi
$(INSTALL) $(INSTLOPTS) fmgr.h \
$(HEADERDIR)/fmgr.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/os.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/os.h \
$(HEADERDIR)/os.h $(HEADERDIR)/os.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/config.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/config.h \
@ -244,6 +239,8 @@ install-headers: fmgr.h $(SRCDIR)/include/config.h
$(HEADERDIR)/utils/geo_decls.h $(HEADERDIR)/utils/geo_decls.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/utils/elog.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/utils/elog.h \
$(HEADERDIR)/utils/elog.h $(HEADERDIR)/utils/elog.h
$(INSTALL) $(INSTLOPTS) utils/fmgroids.h \
$(HEADERDIR)/utils/fmgroids.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/utils/palloc.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/utils/palloc.h \
$(HEADERDIR)/utils/palloc.h $(HEADERDIR)/utils/palloc.h
$(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/utils/mcxt.h \ $(INSTALL) $(INSTLOPTS) $(SRCDIR)/include/utils/mcxt.h \

View File

@ -4,7 +4,7 @@
# Makefile for access/common # Makefile for access/common
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/access/common/Makefile,v 1.16 2000/01/19 02:58:50 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/access/common/Makefile,v 1.17 2000/05/28 17:55:52 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -21,12 +21,7 @@ all: SUBSYS.o
SUBSYS.o: $(OBJS) SUBSYS.o: $(OBJS)
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS) $(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
heaptuple.o heapvalid.o tupdesc.o: ../../fmgr.h dep depend:
../../fmgr.h:
$(MAKE) -C ../.. fmgr.h
dep depend: ../../fmgr.h
$(CC) -MM $(CFLAGS) *.c >depend $(CC) -MM $(CFLAGS) *.c >depend
clean: clean:

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.42 2000/04/12 17:14:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.43 2000/05/28 17:55:52 tgl Exp $
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
* index_open - open an index relation by relationId * index_open - open an index relation by relationId
@ -418,28 +418,43 @@ GetIndexValue(HeapTuple tuple,
bool *attNull) bool *attNull)
{ {
Datum returnVal; Datum returnVal;
bool isNull = FALSE;
if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid) if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid)
{ {
int i; FmgrInfo flinfo;
Datum *attData = (Datum *) palloc(FIgetnArgs(fInfo) * sizeof(Datum)); FunctionCallInfoData fcinfo;
int i;
bool anynull = false;
/*
* XXX ought to store lookup info in FuncIndexInfo so it need not
* be repeated on each call?
*/
fmgr_info(FIgetProcOid(fInfo), &flinfo);
MemSet(&fcinfo, 0, sizeof(fcinfo));
fcinfo.flinfo = &flinfo;
fcinfo.nargs = FIgetnArgs(fInfo);
for (i = 0; i < FIgetnArgs(fInfo); i++) for (i = 0; i < FIgetnArgs(fInfo); i++)
{ {
attData[i] = heap_getattr(tuple, fcinfo.arg[i] = heap_getattr(tuple,
attrNums[i], attrNums[i],
hTupDesc, hTupDesc,
attNull); &fcinfo.argnull[i]);
if (*attNull) anynull |= fcinfo.argnull[i];
isNull = TRUE; }
if (flinfo.fn_strict && anynull)
{
/* force a null result for strict function */
returnVal = (Datum) 0;
*attNull = true;
}
else
{
returnVal = FunctionCallInvoke(&fcinfo);
*attNull = fcinfo.isnull;
} }
returnVal = (Datum) fmgr_array_args(FIgetProcOid(fInfo),
FIgetnArgs(fInfo),
(char **) attData,
&isNull);
pfree(attData);
*attNull = isNull;
} }
else else
returnVal = heap_getattr(tuple, attrNums[attOff], hTupDesc, attNull); returnVal = heap_getattr(tuple, attrNums[attOff], hTupDesc, attNull);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.42 2000/04/12 17:14:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.43 2000/05/28 17:55:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -24,6 +24,7 @@
#include "catalog/pg_index.h" #include "catalog/pg_index.h"
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.81 2000/04/12 17:14:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.82 2000/05/28 17:55:53 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -34,6 +34,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/portal.h" #include "utils/portal.h"

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.128 2000/05/25 21:25:32 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.129 2000/05/28 17:55:54 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -63,6 +63,7 @@
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/catcache.h" #include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/portal.h" #include "utils/portal.h"
#include "utils/relcache.h" #include "utils/relcache.h"
#include "utils/syscache.h" #include "utils/syscache.h"
@ -1148,7 +1149,7 @@ RelationTruncateIndexes(Relation heapRelation)
/* If a valid where predicate, compute predicate Node */ /* If a valid where predicate, compute predicate Node */
if (VARSIZE(&index->indpred) != 0) if (VARSIZE(&index->indpred) != 0)
{ {
predString = fmgr(F_TEXTOUT, &index->indpred); predString = textout(&index->indpred);
oldPred = stringToNode(predString); oldPred = stringToNode(predString);
pfree(predString); pfree(predString);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.110 2000/05/20 23:11:28 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.111 2000/05/28 17:55:54 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -42,6 +42,7 @@
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/catcache.h" #include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/relcache.h" #include "utils/relcache.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/temprel.h" #include "utils/temprel.h"
@ -688,11 +689,11 @@ UpdateIndexRelation(Oid indexoid,
if (predicate != NULL) if (predicate != NULL)
{ {
predString = nodeToString(predicate); predString = nodeToString(predicate);
predText = (text *) fmgr(F_TEXTIN, predString); predText = textin(predString);
pfree(predString); pfree(predString);
} }
else else
predText = (text *) fmgr(F_TEXTIN, ""); predText = textin("");
predLen = VARSIZE(predText); predLen = VARSIZE(predText);
itupLen = predLen + sizeof(FormData_pg_index); itupLen = predLen + sizeof(FormData_pg_index);
@ -832,11 +833,11 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
if (newPred != NULL) if (newPred != NULL)
{ {
predString = nodeToString(newPred); predString = nodeToString(newPred);
predText = (text *) fmgr(F_TEXTIN, predString); predText = textin(predString);
pfree(predString); pfree(predString);
} }
else else
predText = (text *) fmgr(F_TEXTIN, ""); predText = textin("");
/* open the index system catalog relation */ /* open the index system catalog relation */
pg_index = heap_openr(IndexRelationName, RowExclusiveLock); pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
@ -2109,7 +2110,7 @@ reindex_index(Oid indexId, bool force)
/* If a valid where predicate, compute predicate Node */ /* If a valid where predicate, compute predicate Node */
if (VARSIZE(&index->indpred) != 0) if (VARSIZE(&index->indpred) != 0)
{ {
predString = fmgr(F_TEXTOUT, &index->indpred); predString = textout(&index->indpred);
oldPred = stringToNode(predString); oldPred = stringToNode(predString);
pfree(predString); pfree(predString);
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.60 2000/04/12 17:14:56 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.61 2000/05/28 17:55:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -24,6 +24,7 @@
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/pg_index.h" #include "catalog/pg_index.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
/* /*

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.49 2000/01/26 05:56:10 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.50 2000/05/28 17:55:54 tgl Exp $
* *
* NOTES * NOTES
* these routines moved here from commands/define.c and somewhat cleaned up. * these routines moved here from commands/define.c and somewhat cleaned up.
@ -26,6 +26,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.42 2000/04/12 17:14:56 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.43 2000/05/28 17:55:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -17,6 +17,7 @@
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "miscadmin.h" #include "miscadmin.h"
@ -24,7 +25,6 @@
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgrtab.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/sets.h" #include "utils/sets.h"
#include "utils/syscache.h" #include "utils/syscache.h"
@ -41,8 +41,9 @@ ProcedureCreate(char *procedureName,
char *languageName, char *languageName,
char *prosrc, char *prosrc,
char *probin, char *probin,
bool canCache,
bool trusted, bool trusted,
bool canCache,
bool isStrict,
int32 byte_pct, int32 byte_pct,
int32 perbyte_cpu, int32 perbyte_cpu,
int32 percall_cpu, int32 percall_cpu,
@ -74,6 +75,15 @@ ProcedureCreate(char *procedureName,
Assert(PointerIsValid(prosrc)); Assert(PointerIsValid(prosrc));
Assert(PointerIsValid(probin)); Assert(PointerIsValid(probin));
tup = SearchSysCacheTuple(LANGNAME,
PointerGetDatum(languageName),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "ProcedureCreate: no such language '%s'", languageName);
languageObjectId = tup->t_data->t_oid;
parameterCount = 0; parameterCount = 0;
MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid)); MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
foreach(x, argList) foreach(x, argList)
@ -86,7 +96,7 @@ ProcedureCreate(char *procedureName,
if (strcmp(strVal(t), "opaque") == 0) if (strcmp(strVal(t), "opaque") == 0)
{ {
if (strcmp(languageName, "sql") == 0) if (languageObjectId == SQLlanguageId)
elog(ERROR, "ProcedureCreate: sql functions cannot take type \"opaque\""); elog(ERROR, "ProcedureCreate: sql functions cannot take type \"opaque\"");
toid = 0; toid = 0;
} }
@ -120,7 +130,7 @@ ProcedureCreate(char *procedureName,
elog(ERROR, "ProcedureCreate: procedure %s already exists with same arguments", elog(ERROR, "ProcedureCreate: procedure %s already exists with same arguments",
procedureName); procedureName);
if (!strcmp(languageName, "sql")) if (languageObjectId == SQLlanguageId)
{ {
/* /*
@ -129,7 +139,7 @@ ProcedureCreate(char *procedureName,
* matches a function already in pg_proc. If so just return the * matches a function already in pg_proc. If so just return the
* OID of the existing set. * OID of the existing set.
*/ */
if (!strcmp(procedureName, GENERICSETNAME)) if (strcmp(procedureName, GENERICSETNAME) == 0)
{ {
#ifdef SETS_FIXED #ifdef SETS_FIXED
/* ---------- /* ----------
@ -138,7 +148,7 @@ ProcedureCreate(char *procedureName,
* have been removed. Instead a sequential heap scan * have been removed. Instead a sequential heap scan
* or something better must get implemented. The reason * or something better must get implemented. The reason
* for removing is that nbtree index crashes if sources * for removing is that nbtree index crashes if sources
* exceed 2K what's likely for procedural languages. * exceed 2K --- what's likely for procedural languages.
* *
* 1999/09/30 Jan * 1999/09/30 Jan
* ---------- * ----------
@ -158,18 +168,9 @@ ProcedureCreate(char *procedureName,
} }
} }
tup = SearchSysCacheTuple(LANGNAME,
PointerGetDatum(languageName),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "ProcedureCreate: no such language %s", languageName);
languageObjectId = tup->t_data->t_oid;
if (strcmp(returnTypeName, "opaque") == 0) if (strcmp(returnTypeName, "opaque") == 0)
{ {
if (strcmp(languageName, "sql") == 0) if (languageObjectId == SQLlanguageId)
elog(ERROR, "ProcedureCreate: sql functions cannot return type \"opaque\""); elog(ERROR, "ProcedureCreate: sql functions cannot return type \"opaque\"");
typeObjectId = 0; typeObjectId = 0;
} }
@ -181,16 +182,10 @@ ProcedureCreate(char *procedureName,
{ {
elog(NOTICE, "ProcedureCreate: type '%s' is not yet defined", elog(NOTICE, "ProcedureCreate: type '%s' is not yet defined",
returnTypeName); returnTypeName);
#ifdef NOT_USED
elog(NOTICE, "ProcedureCreate: creating a shell for type '%s'",
returnTypeName);
#endif
typeObjectId = TypeShellMake(returnTypeName); typeObjectId = TypeShellMake(returnTypeName);
if (!OidIsValid(typeObjectId)) if (!OidIsValid(typeObjectId))
{
elog(ERROR, "ProcedureCreate: could not create type '%s'", elog(ERROR, "ProcedureCreate: could not create type '%s'",
returnTypeName); returnTypeName);
}
} }
else if (!defined) else if (!defined)
{ {
@ -219,7 +214,7 @@ ProcedureCreate(char *procedureName,
* procedure's text in the prosrc attribute. * procedure's text in the prosrc attribute.
*/ */
if (strcmp(languageName, "sql") == 0) if (languageObjectId == SQLlanguageId)
{ {
querytree_list = pg_parse_and_rewrite(prosrc, typev, parameterCount, querytree_list = pg_parse_and_rewrite(prosrc, typev, parameterCount,
FALSE); FALSE);
@ -237,16 +232,50 @@ ProcedureCreate(char *procedureName,
* FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some modicum * FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some modicum
* of backwards compatibility, accept an empty 'prosrc' value as * of backwards compatibility, accept an empty 'prosrc' value as
* meaning the supplied SQL function name. * meaning the supplied SQL function name.
*
* XXX: we could treat "internal" and "newinternal" language specs
* as equivalent, and take the actual language ID from the table of
* known builtin functions. Is that a better idea than making the
* user specify the right thing? Not sure.
*/ */
if (strcmp(languageName, "internal") == 0) if (languageObjectId == INTERNALlanguageId ||
languageObjectId == NEWINTERNALlanguageId)
{ {
Oid actualLangID;
if (strlen(prosrc) == 0) if (strlen(prosrc) == 0)
prosrc = procedureName; prosrc = procedureName;
if (fmgr_lookupByName(prosrc) == (func_ptr) NULL) actualLangID = fmgr_internal_language(prosrc);
if (actualLangID == InvalidOid)
elog(ERROR, elog(ERROR,
"ProcedureCreate: there is no builtin function named \"%s\"", "ProcedureCreate: there is no builtin function named \"%s\"",
prosrc); prosrc);
if (actualLangID != languageObjectId)
elog(ERROR,
"ProcedureCreate: \"%s\" is not %s internal function",
prosrc,
((languageObjectId == INTERNALlanguageId) ?
"an old-style" : "a new-style"));
}
/*
* If this is a dynamically loadable procedure, make sure that the
* library file exists, is loadable, and contains the specified link
* symbol.
*
* We used to perform these checks only when the function was first
* called, but it seems friendlier to verify the library's validity
* at CREATE FUNCTION time.
*/
if (languageObjectId == ClanguageId ||
languageObjectId == NEWClanguageId)
{
/* If link symbol is specified as "-", substitute procedure name */
if (strcmp(prosrc, "-") == 0)
prosrc = procedureName;
(void) load_external_function(probin, prosrc);
} }
/* /*
@ -265,9 +294,10 @@ ProcedureCreate(char *procedureName,
values[i++] = Int32GetDatum(GetUserId()); values[i++] = Int32GetDatum(GetUserId());
values[i++] = ObjectIdGetDatum(languageObjectId); values[i++] = ObjectIdGetDatum(languageObjectId);
/* XXX isinherited is always false for now */ /* XXX isinherited is always false for now */
values[i++] = Int8GetDatum((bool) 0); values[i++] = Int8GetDatum((bool) false);
values[i++] = Int8GetDatum(trusted); values[i++] = Int8GetDatum(trusted);
values[i++] = Int8GetDatum(canCache); values[i++] = Int8GetDatum(canCache);
values[i++] = Int8GetDatum(isStrict);
values[i++] = UInt16GetDatum(parameterCount); values[i++] = UInt16GetDatum(parameterCount);
values[i++] = Int8GetDatum(returnsSet); values[i++] = Int8GetDatum(returnsSet);
values[i++] = ObjectIdGetDatum(typeObjectId); values[i++] = ObjectIdGetDatum(typeObjectId);
@ -276,8 +306,8 @@ ProcedureCreate(char *procedureName,
values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */ values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */ values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
values[i++] = Int32GetDatum(outin_ratio); /* prooutin_ratio */ values[i++] = Int32GetDatum(outin_ratio); /* prooutin_ratio */
values[i++] = (Datum) fmgr(F_TEXTIN, prosrc); /* prosrc */ values[i++] = (Datum) textin(prosrc); /* prosrc */
values[i++] = (Datum) fmgr(F_TEXTIN, probin); /* probin */ values[i++] = (Datum) textin(probin); /* probin */
rel = heap_openr(ProcedureRelationName, RowExclusiveLock); rel = heap_openr(ProcedureRelationName, RowExclusiveLock);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.50 2000/04/12 17:14:56 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.51 2000/05/28 17:55:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -21,6 +21,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
@ -190,7 +191,7 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
/* /*
* ... and fill typdefault with a bogus value * ... and fill typdefault with a bogus value
*/ */
values[i++] = (Datum) fmgr(F_TEXTIN, typeName); /* 15 */ values[i++] = (Datum) textin(typeName); /* 15 */
/* ---------------- /* ----------------
* create a new type tuple with FormHeapTuple * create a new type tuple with FormHeapTuple
@ -449,10 +450,9 @@ TypeCreate(char *typeName,
* initialize the default value for this type. * initialize the default value for this type.
* ---------------- * ----------------
*/ */
values[i] = (Datum) fmgr(F_TEXTIN, /* 16 */ values[i] = (Datum) textin(PointerIsValid(defaultTypeValue) /* 16 */
PointerIsValid(defaultTypeValue) ? defaultTypeValue : "-"); /* XXX default
? defaultTypeValue : "-"); /* XXX default * typdefault */
* typdefault */
/* ---------------- /* ----------------
* open pg_type and begin a scan for the type name. * open pg_type and begin a scan for the type name.

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.60 2000/05/14 03:18:35 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.61 2000/05/28 17:55:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -87,6 +87,7 @@
#include "libpq/libpq.h" #include "libpq/libpq.h"
#include "libpq/pqformat.h" #include "libpq/pqformat.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/ps_status.h" #include "utils/ps_status.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/trace.h" #include "utils/trace.h"

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.71 2000/04/12 17:14:57 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.72 2000/05/28 17:55:54 tgl Exp $
* *
* NOTES * NOTES
* The PortalExecutorHeapMemory crap needs to be eliminated * The PortalExecutorHeapMemory crap needs to be eliminated
@ -40,6 +40,7 @@
#include "optimizer/prep.h" #include "optimizer/prep.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/temprel.h" #include "utils/temprel.h"
#include "commands/trigger.h" #include "commands/trigger.h"
@ -614,12 +615,15 @@ AlterTableAlterColumn(const char *relationName,
HeapTuple tuple; HeapTuple tuple;
attr_rel = heap_openr(AttributeRelationName, AccessExclusiveLock); attr_rel = heap_openr(AttributeRelationName, AccessExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0, Anum_pg_attribute_attrelid, F_OIDEQ, ScanKeyEntryInitialize(&scankeys[0], 0x0,
Anum_pg_attribute_attrelid, F_OIDEQ,
ObjectIdGetDatum(myrelid)); ObjectIdGetDatum(myrelid));
ScanKeyEntryInitialize(&scankeys[1], 0x0, Anum_pg_attribute_attnum, F_INT2EQ, ScanKeyEntryInitialize(&scankeys[1], 0x0,
Anum_pg_attribute_attnum, F_INT2EQ,
Int16GetDatum(attnum)); Int16GetDatum(attnum));
ScanKeyEntryInitialize(&scankeys[2], 0x0, Anum_pg_attribute_atthasdef, F_BOOLEQ, ScanKeyEntryInitialize(&scankeys[2], 0x0,
TRUE); Anum_pg_attribute_atthasdef, F_BOOLEQ,
Int32GetDatum(TRUE));
scan = heap_beginscan(attr_rel, false, SnapshotNow, 3, scankeys); scan = heap_beginscan(attr_rel, false, SnapshotNow, 3, scankeys);
AssertState(scan != NULL); AssertState(scan != NULL);
@ -661,9 +665,11 @@ drop_default(Oid relid, int16 attnum)
HeapTuple tuple; HeapTuple tuple;
attrdef_rel = heap_openr(AttrDefaultRelationName, AccessExclusiveLock); attrdef_rel = heap_openr(AttrDefaultRelationName, AccessExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0, Anum_pg_attrdef_adrelid, F_OIDEQ, ScanKeyEntryInitialize(&scankeys[0], 0x0,
Anum_pg_attrdef_adrelid, F_OIDEQ,
ObjectIdGetDatum(relid)); ObjectIdGetDatum(relid));
ScanKeyEntryInitialize(&scankeys[1], 0x0, Anum_pg_attrdef_adnum, F_INT2EQ, ScanKeyEntryInitialize(&scankeys[1], 0x0,
Anum_pg_attrdef_adnum, F_INT2EQ,
Int16GetDatum(attnum)); Int16GetDatum(attnum));
scan = heap_beginscan(attrdef_rel, false, SnapshotNow, 2, scankeys); scan = heap_beginscan(attrdef_rel, false, SnapshotNow, 2, scankeys);

View File

@ -27,11 +27,12 @@
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/comment.h" #include "commands/comment.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse.h"
#include "rewrite/rewriteRemove.h" #include "rewrite/rewriteRemove.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "../backend/parser/parse.h"
/*------------------------------------------------------------------ /*------------------------------------------------------------------
* Static Function Prototypes -- * Static Function Prototypes --
@ -153,7 +154,7 @@ CreateComments(Oid oid, char *comment)
} }
i = 0; i = 0;
values[i++] = ObjectIdGetDatum(oid); values[i++] = ObjectIdGetDatum(oid);
values[i++] = (Datum) fmgr(F_TEXTIN, comment); values[i++] = (Datum) textin(comment);
} }
/*** Now, open pg_description and attempt to find the old tuple ***/ /*** Now, open pg_description and attempt to find the old tuple ***/

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.106 2000/05/18 01:52:45 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.107 2000/05/28 17:55:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -680,7 +680,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
indexNatts[i] = natts; indexNatts[i] = natts;
if (VARSIZE(&pgIndexP[i]->indpred) != 0) if (VARSIZE(&pgIndexP[i]->indpred) != 0)
{ {
predString = fmgr(F_TEXTOUT, &pgIndexP[i]->indpred); predString = textout(&pgIndexP[i]->indpred);
indexPred[i] = stringToNode(predString); indexPred[i] = stringToNode(predString);
pfree(predString); pfree(predString);
/* make dummy ExprContext for use by ExecQual */ /* make dummy ExprContext for use by ExecQual */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.54 2000/05/25 06:53:43 ishii Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.55 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -37,6 +37,7 @@
#include "storage/fd.h" /* for closeAllVfds */ #include "storage/fd.h" /* for closeAllVfds */
#include "storage/sinval.h" /* for DatabaseHasActiveBackends */ #include "storage/sinval.h" /* for DatabaseHasActiveBackends */
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/elog.h" #include "utils/elog.h"
#include "utils/palloc.h" #include "utils/palloc.h"
#include "utils/rel.h" #include "utils/rel.h"

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.42 2000/05/12 18:51:59 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.43 2000/05/28 17:55:55 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
@ -35,8 +35,6 @@
*/ */
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
#include <sys/stat.h>
#include "postgres.h" #include "postgres.h"
@ -66,18 +64,20 @@ static void
case_translate_language_name(const char *input, char *output) case_translate_language_name(const char *input, char *output)
{ {
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
Translate the input language name to lower case, except if it's C, Translate the input language name to lower case, except if it's "C",
translate to upper case. translate to upper case, or "newC", translate to that spelling.
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
int i; int i;
for (i = 0; i < NAMEDATALEN && input[i]; ++i) for (i = 0; i < NAMEDATALEN-1 && input[i]; ++i)
output[i] = tolower(input[i]); output[i] = tolower(input[i]);
output[i] = '\0'; output[i] = '\0';
if (strcmp(output, "c") == 0) if (strcmp(output, "c") == 0)
output[0] = 'C'; output[0] = 'C';
else if (strcmp(output, "newc") == 0)
output[3] = 'C';
} }
@ -108,9 +108,10 @@ compute_return_type(const Node *returnType,
static void static void
compute_full_attributes(List *parameters, int32 *byte_pct_p, compute_full_attributes(List *parameters,
int32 *perbyte_cpu_p, int32 *percall_cpu_p, int32 *byte_pct_p, int32 *perbyte_cpu_p,
int32 *outin_ratio_p, bool *canCache_p) int32 *percall_cpu_p, int32 *outin_ratio_p,
bool *canCache_p, bool *isStrict_p)
{ {
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
Interpret the parameters *parameters and return their contents as Interpret the parameters *parameters and return their contents as
@ -119,14 +120,20 @@ compute_full_attributes(List *parameters, int32 *byte_pct_p,
These parameters supply optional information about a function. These parameters supply optional information about a function.
All have defaults if not specified. All have defaults if not specified.
Note: as of version 6.6, canCache is used (if set, the optimizer's Note: currently, only two of these parameters actually do anything:
constant-folder is allowed to pre-evaluate the function if all its
inputs are constant). The other four are not used. They used to be * canCache means the optimizer's constant-folder is allowed to
pre-evaluate the function when all its inputs are constants.
* isStrict means the function should not be called when any NULL
inputs are present; instead a NULL result value should be assumed.
The other four parameters are not used anywhere. They used to be
used in the "expensive functions" optimizer, but that's been dead code used in the "expensive functions" optimizer, but that's been dead code
for a long time. for a long time.
Since canCache is useful for any function, we now allow attributes to be Since canCache and isStrict are useful for any function, we now allow
supplied for all functions regardless of language. attributes to be supplied for all functions regardless of language.
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
List *pl; List *pl;
@ -136,6 +143,7 @@ compute_full_attributes(List *parameters, int32 *byte_pct_p,
*percall_cpu_p = PERCALL_CPU; *percall_cpu_p = PERCALL_CPU;
*outin_ratio_p = OUTIN_RATIO; *outin_ratio_p = OUTIN_RATIO;
*canCache_p = false; *canCache_p = false;
*isStrict_p = false;
foreach(pl, parameters) foreach(pl, parameters)
{ {
@ -143,6 +151,8 @@ compute_full_attributes(List *parameters, int32 *byte_pct_p,
if (strcasecmp(param->defname, "iscachable") == 0) if (strcasecmp(param->defname, "iscachable") == 0)
*canCache_p = true; *canCache_p = true;
else if (strcasecmp(param->defname, "isstrict") == 0)
*isStrict_p = true;
else if (strcasecmp(param->defname, "trusted") == 0) else if (strcasecmp(param->defname, "trusted") == 0)
{ {
@ -182,24 +192,17 @@ static void
interpret_AS_clause(const char *languageName, const List *as, interpret_AS_clause(const char *languageName, const List *as,
char **prosrc_str_p, char **probin_str_p) char **prosrc_str_p, char **probin_str_p)
{ {
struct stat stat_buf;
Assert(as != NIL); Assert(as != NIL);
if (strcmp(languageName, "C") == 0) if (strcmp(languageName, "C") == 0 ||
strcmp(languageName, "newC") == 0)
{ {
/* /*
* For "C" language, store the file name in probin and, when * For "C" language, store the file name in probin and, when
* given, the link symbol name in prosrc. But first, stat the * given, the link symbol name in prosrc.
* file to make sure it's there!
*/ */
if (stat(strVal(lfirst(as)), &stat_buf) == -1)
elog(ERROR, "stat failed on file '%s': %m", strVal(lfirst(as)));
*probin_str_p = strVal(lfirst(as)); *probin_str_p = strVal(lfirst(as));
if (lnext(as) == NULL) if (lnext(as) == NULL)
*prosrc_str_p = "-"; *prosrc_str_p = "-";
else else
@ -239,8 +242,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
char languageName[NAMEDATALEN]; char languageName[NAMEDATALEN];
/* /*
* name of language of function, with case adjusted: "C", "internal", * name of language of function, with case adjusted: "C", "newC",
* or "SQL" * "internal", "newinternal", "sql", etc.
*/ */
bool returnsSet; bool returnsSet;
@ -257,19 +260,21 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
perbyte_cpu, perbyte_cpu,
percall_cpu, percall_cpu,
outin_ratio; outin_ratio;
bool canCache; bool canCache,
isStrict;
case_translate_language_name(stmt->language, languageName); case_translate_language_name(stmt->language, languageName);
if (strcmp(languageName, "C") == 0 || if (strcmp(languageName, "C") == 0 ||
strcmp(languageName, "internal") == 0) strcmp(languageName, "newC") == 0 ||
strcmp(languageName, "internal") == 0 ||
strcmp(languageName, "newinternal") == 0)
{ {
if (!superuser()) if (!superuser())
elog(ERROR, elog(ERROR,
"Only users with Postgres superuser privilege are " "Only users with Postgres superuser privilege are "
"permitted to create a function " "permitted to create a function in the '%s' language.\n\t"
"in the '%s' language. Others may use the 'sql' language " "Others may use the 'sql' language "
"or the created procedural languages.", "or the created procedural languages.",
languageName); languageName);
} }
@ -288,28 +293,23 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(languageTuple)) if (!HeapTupleIsValid(languageTuple))
{
elog(ERROR, elog(ERROR,
"Unrecognized language specified in a CREATE FUNCTION: " "Unrecognized language specified in a CREATE FUNCTION: "
"'%s'. Recognized languages are sql, C, internal " "'%s'.\n\tRecognized languages are sql, C, newC, "
"and the created procedural languages.", "internal, newinternal, and created procedural languages.",
languageName); languageName);
}
/* Check that this language is a PL */ /* Check that this language is a PL */
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
if (!(languageStruct->lanispl)) if (!(languageStruct->lanispl))
{
elog(ERROR, elog(ERROR,
"Language '%s' isn't defined as PL", languageName); "Language '%s' isn't defined as PL", languageName);
}
/* /*
* Functions in untrusted procedural languages are restricted to * Functions in untrusted procedural languages are restricted to
* be defined by postgres superusers only * be defined by postgres superusers only
*/ */
if (languageStruct->lanpltrusted == false && !superuser()) if (!languageStruct->lanpltrusted && !superuser())
{ {
elog(ERROR, "Only users with Postgres superuser privilege " elog(ERROR, "Only users with Postgres superuser privilege "
"are permitted to create a function in the '%s' " "are permitted to create a function in the '%s' "
@ -324,7 +324,7 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
compute_full_attributes(stmt->withClause, compute_full_attributes(stmt->withClause,
&byte_pct, &perbyte_cpu, &percall_cpu, &byte_pct, &perbyte_cpu, &percall_cpu,
&outin_ratio, &canCache); &outin_ratio, &canCache, &isStrict);
interpret_AS_clause(languageName, stmt->as, &prosrc_str, &probin_str); interpret_AS_clause(languageName, stmt->as, &prosrc_str, &probin_str);
@ -338,8 +338,9 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
languageName, languageName,
prosrc_str, /* converted to text later */ prosrc_str, /* converted to text later */
probin_str, /* converted to text later */ probin_str, /* converted to text later */
canCache,
true, /* (obsolete "trusted") */ true, /* (obsolete "trusted") */
canCache,
isStrict,
byte_pct, byte_pct,
perbyte_cpu, perbyte_cpu,
percall_cpu, percall_cpu,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.26 2000/04/25 10:38:38 inoue Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.27 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -37,6 +37,7 @@
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "miscadmin.h" /* ReindexDatabase() */ #include "miscadmin.h" /* ReindexDatabase() */
#include "utils/portal.h" /* ReindexDatabase() */ #include "utils/portal.h" /* ReindexDatabase() */
@ -298,7 +299,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
{ {
char *predString; char *predString;
predString = fmgr(F_TEXTOUT, &index->indpred); predString = textout(&index->indpred);
oldPred = stringToNode(predString); oldPred = stringToNode(predString);
pfree(predString); pfree(predString);
} }

View File

@ -17,6 +17,7 @@
#include "catalog/pg_shadow.h" #include "catalog/pg_shadow.h"
#include "commands/proclang.h" #include "commands/proclang.h"
#include "fmgr.h" #include "fmgr.h"
#include "utils/builtins.h"
#include "utils/syscache.h" #include "utils/syscache.h"
@ -119,7 +120,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
values[i++] = Int8GetDatum((bool) 1); values[i++] = Int8GetDatum((bool) 1);
values[i++] = Int8GetDatum(stmt->pltrusted); values[i++] = Int8GetDatum(stmt->pltrusted);
values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid); values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
values[i++] = (Datum) fmgr(F_TEXTIN, stmt->plcompiler); values[i++] = (Datum) textin(stmt->plcompiler);
rel = heap_openr(LanguageRelationName, RowExclusiveLock); rel = heap_openr(LanguageRelationName, RowExclusiveLock);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.64 2000/04/16 04:25:42 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.65 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -27,6 +27,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h" #include "utils/inval.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/tqual.h" #include "utils/tqual.h"
@ -757,16 +758,9 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
static HeapTuple static HeapTuple
ExecCallTriggerFunc(Trigger *trigger) ExecCallTriggerFunc(Trigger *trigger)
{ {
if (trigger->tgfunc.fn_addr == NULL) if (trigger->tgfunc.fn_addr == NULL)
fmgr_info(trigger->tgfoid, &trigger->tgfunc); fmgr_info(trigger->tgfoid, &trigger->tgfunc);
if (trigger->tgfunc.fn_plhandler != NULL)
{
return (HeapTuple) (*(trigger->tgfunc.fn_plhandler))
(&trigger->tgfunc);
}
return (HeapTuple) ((*fmgr_faddr(&trigger->tgfunc)) ()); return (HeapTuple) ((*fmgr_faddr(&trigger->tgfunc)) ());
} }

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: user.c,v 1.53 2000/05/04 20:06:07 tgl Exp $ * $Id: user.c,v 1.54 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -33,6 +33,7 @@
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/array.h" #include "utils/array.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
static void CheckPgUserAclNotNull(void); static void CheckPgUserAclNotNull(void);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.148 2000/05/19 03:22:29 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.149 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -38,6 +38,7 @@
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h" #include "utils/inval.h"
#include "utils/portal.h" #include "utils/portal.h"
#include "utils/relcache.h" #include "utils/relcache.h"

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.69 2000/04/12 17:15:08 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.70 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -41,6 +41,7 @@
#include "executor/functions.h" #include "executor/functions.h"
#include "executor/nodeSubplan.h" #include "executor/nodeSubplan.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/fcache2.h" #include "utils/fcache2.h"
@ -64,7 +65,8 @@ static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext, static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
bool *isNull, bool *isDone); bool *isNull, bool *isDone);
static void ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext *econtext, static void ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext *econtext,
List *argList, Datum argV[], bool *argIsDone); List *argList, FunctionCallInfo fcinfo,
bool *argIsDone);
static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull); static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext, static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
bool *isNull); bool *isNull);
@ -614,15 +616,12 @@ static void
ExecEvalFuncArgs(FunctionCachePtr fcache, ExecEvalFuncArgs(FunctionCachePtr fcache,
ExprContext *econtext, ExprContext *econtext,
List *argList, List *argList,
Datum argV[], FunctionCallInfo fcinfo,
bool *argIsDone) bool *argIsDone)
{ {
int i; int i;
bool *nullVect;
List *arg; List *arg;
nullVect = fcache->nullVect;
i = 0; i = 0;
foreach(arg, argList) foreach(arg, argList)
{ {
@ -632,16 +631,16 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
* as arguments but we make an exception in the case of nested dot * as arguments but we make an exception in the case of nested dot
* expressions. We have to watch out for this case here. * expressions. We have to watch out for this case here.
*/ */
argV[i] = ExecEvalExpr((Node *) lfirst(arg), fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg),
econtext, econtext,
&nullVect[i], &fcinfo->argnull[i],
argIsDone); argIsDone);
if (!(*argIsDone)) if (!(*argIsDone))
{ {
if (i != 0) if (i != 0)
elog(ERROR, "functions can only take sets in their first argument"); elog(ERROR, "functions can only take sets in their first argument");
fcache->setArg = (char *) argV[0]; fcache->setArg = fcinfo->arg[0];
fcache->hasSetArg = true; fcache->hasSetArg = true;
} }
i++; i++;
@ -658,40 +657,45 @@ ExecMakeFunctionResult(Node *node,
bool *isNull, bool *isNull,
bool *isDone) bool *isDone)
{ {
Datum argV[FUNC_MAX_ARGS]; FunctionCallInfoData fcinfo;
FunctionCachePtr fcache; FunctionCachePtr fcache;
Func *funcNode = NULL; List *ftlist;
Oper *operNode = NULL; bool funcisset;
bool funcisset = false; Datum result;
bool argDone;
MemSet(&fcinfo, 0, sizeof(fcinfo));
/* /*
* This is kind of ugly, Func nodes now have targetlists so that we * This is kind of ugly, Func nodes now have targetlists so that we
* know when and what to project out from postquel function results. * know when and what to project out from postquel function results.
* This means we have to pass the func node all the way down instead * ExecMakeFunctionResult becomes a little bit more of a dual personality
* of using only the fcache struct as before. ExecMakeFunctionResult * as a result.
* becomes a little bit more of a dual personality as a result.
*/ */
if (IsA(node, Func)) if (IsA(node, Func))
{ {
funcNode = (Func *) node; fcache = ((Func *) node)->func_fcache;
fcache = funcNode->func_fcache; ftlist = ((Func *) node)->func_tlist;
funcisset = (((Func *) node)->funcid == F_SETEVAL);
} }
else else
{ {
operNode = (Oper *) node; fcache = ((Oper *) node)->op_fcache;
fcache = operNode->op_fcache; ftlist = NIL;
funcisset = false;
} }
fcinfo.flinfo = &fcache->func;
fcinfo.nargs = fcache->nargs;
/* /*
* arguments is a list of expressions to evaluate before passing to * arguments is a list of expressions to evaluate before passing to
* the function manager. We collect the results of evaluating the * the function manager. We collect the results of evaluating the
* expressions into a datum array (argV) and pass this array to * expressions into the FunctionCallInfo struct. Note we assume that
* arrayFmgr() * fcache->nargs is the correct length of the arguments list!
*/ */
if (fcache->nargs != 0) if (fcache->nargs > 0)
{ {
bool argDone;
if (fcache->nargs > FUNC_MAX_ARGS) if (fcache->nargs > FUNC_MAX_ARGS)
elog(ERROR, "ExecMakeFunctionResult: too many arguments"); elog(ERROR, "ExecMakeFunctionResult: too many arguments");
@ -700,21 +704,23 @@ ExecMakeFunctionResult(Node *node,
* returning a set of tuples (i.e. a nested dot expression). We * returning a set of tuples (i.e. a nested dot expression). We
* don't want to evaluate the arguments again until the function * don't want to evaluate the arguments again until the function
* is done. hasSetArg will always be false until we eval the args * is done. hasSetArg will always be false until we eval the args
* for the first time. We should set this in the parser. * for the first time.
*/ */
if ((fcache->hasSetArg) && fcache->setArg != NULL) if (fcache->hasSetArg && fcache->setArg != (Datum) 0)
{ {
argV[0] = (Datum) fcache->setArg; fcinfo.arg[0] = fcache->setArg;
argDone = false; argDone = false;
} }
else else
ExecEvalFuncArgs(fcache, econtext, arguments, argV, &argDone); ExecEvalFuncArgs(fcache, econtext, arguments, &fcinfo, &argDone);
if ((fcache->hasSetArg) && (argDone)) if (fcache->hasSetArg && argDone)
{ {
/* can only get here if input is an empty set. */
if (isDone) if (isDone)
*isDone = true; *isDone = true;
return (Datum) NULL; *isNull = true;
return (Datum) 0;
} }
} }
@ -731,27 +737,23 @@ ExecMakeFunctionResult(Node *node,
* which defines this set. So replace the existing funcid in the * which defines this set. So replace the existing funcid in the
* funcnode with the set's OID. Also, we want a new fcache which * funcnode with the set's OID. Also, we want a new fcache which
* points to the right function, so get that, now that we have the * points to the right function, so get that, now that we have the
* right OID. Also zero out the argV, since the real set doesn't take * right OID. Also zero out fcinfo.arg, since the real set doesn't take
* any arguments. * any arguments.
*/ */
if (((Func *) node)->funcid == F_SETEVAL) if (funcisset)
{ {
funcisset = true;
if (fcache->setArg) if (fcache->setArg)
{ {
argV[0] = 0; ((Func *) node)->funcid = DatumGetObjectId(fcache->setArg);
((Func *) node)->funcid = (Oid) PointerGetDatum(fcache->setArg);
} }
else else
{ {
((Func *) node)->funcid = (Oid) argV[0]; ((Func *) node)->funcid = DatumGetObjectId(fcinfo.arg[0]);
setFcache(node, argV[0], NIL, econtext); setFcache(node, DatumGetObjectId(fcinfo.arg[0]), NIL, econtext);
fcache = ((Func *) node)->func_fcache; fcache = ((Func *) node)->func_fcache;
fcache->setArg = (char *) argV[0]; fcache->setArg = fcinfo.arg[0];
argV[0] = (Datum) 0;
} }
fcinfo.arg[0] = (Datum) 0;
} }
/* /*
@ -760,11 +762,6 @@ ExecMakeFunctionResult(Node *node,
*/ */
if (fcache->language == SQLlanguageId) if (fcache->language == SQLlanguageId)
{ {
Datum result;
bool argDone;
Assert(funcNode);
/*-------------------- /*--------------------
* This loop handles the situation where we are iterating through * This loop handles the situation where we are iterating through
* all results in a nested dot function (whose argument function * all results in a nested dot function (whose argument function
@ -777,8 +774,37 @@ ExecMakeFunctionResult(Node *node,
*/ */
for (;;) for (;;)
{ {
result = postquel_function(funcNode, (char **) argV, /*
isNull, isDone); * If function is strict, and there are any NULL arguments,
* skip calling the function (at least for this set of args).
*/
bool callit = true;
if (fcinfo.flinfo->fn_strict)
{
int i;
for (i = 0; i < fcinfo.nargs; i++)
{
if (fcinfo.argnull[i])
{
callit = false;
break;
}
}
}
if (callit)
{
result = postquel_function(&fcinfo, fcache, ftlist, isDone);
*isNull = fcinfo.isnull;
}
else
{
result = (Datum) 0;
*isDone = true;
*isNull = true;
}
if (!*isDone) if (!*isDone)
break; /* got a result from current argument */ break; /* got a result from current argument */
@ -786,7 +812,7 @@ ExecMakeFunctionResult(Node *node,
break; /* input not a set, so done */ break; /* input not a set, so done */
/* OK, get the next argument... */ /* OK, get the next argument... */
ExecEvalFuncArgs(fcache, econtext, arguments, argV, &argDone); ExecEvalFuncArgs(fcache, econtext, arguments, &fcinfo, &argDone);
if (argDone) if (argDone)
{ {
@ -795,10 +821,11 @@ ExecMakeFunctionResult(Node *node,
* End of arguments, so reset the setArg flag and say * End of arguments, so reset the setArg flag and say
* "Done" * "Done"
*/ */
fcache->setArg = (char *) NULL; fcache->setArg = (Datum) 0;
fcache->hasSetArg = false; fcache->hasSetArg = false;
*isDone = true; *isDone = true;
result = (Datum) NULL; *isNull = true;
result = (Datum) 0;
break; break;
} }
@ -826,21 +853,34 @@ ExecMakeFunctionResult(Node *node,
if (*isDone) if (*isDone)
((Func *) node)->func_fcache = NULL; ((Func *) node)->func_fcache = NULL;
} }
return result;
} }
else else
{ {
int i; /* A non-SQL function cannot return a set, at present. */
if (isDone) if (isDone)
*isDone = true; *isDone = true;
for (i = 0; i < fcache->nargs; i++) /*
if (fcache->nullVect[i] == true) * If function is strict, and there are any NULL arguments,
*isNull = true; * skip calling the function and return NULL.
*/
if (fcinfo.flinfo->fn_strict)
{
int i;
return (Datum) fmgr_c(&fcache->func, (FmgrValues *) argV, isNull); for (i = 0; i < fcinfo.nargs; i++)
{
if (fcinfo.argnull[i])
{
*isNull = true;
return (Datum) 0;
}
}
}
result = FunctionCallInvoke(&fcinfo);
*isNull = fcinfo.isnull;
} }
return result;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.55 2000/04/12 17:15:08 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.56 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -52,6 +52,8 @@
#include "executor/execdebug.h" #include "executor/execdebug.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP, static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP,
AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP); AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
@ -843,7 +845,7 @@ ExecOpenIndices(Oid resultRelationOid,
*/ */
if (VARSIZE(&indexStruct->indpred) != 0) if (VARSIZE(&indexStruct->indpred) != 0)
{ {
predString = fmgr(F_TEXTOUT, &indexStruct->indpred); predString = textout(&indexStruct->indpred);
predicate = (PredInfo *) stringToNode(predString); predicate = (PredInfo *) stringToNode(predString);
pfree(predString); pfree(predString);
} }

View File

@ -2,14 +2,13 @@
* *
* functions.c * functions.c
* Routines to handle functions called from the executor * Routines to handle functions called from the executor
* Putting this stuff in fmgr makes the postmaster a mess....
* *
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.33 2000/04/12 17:15:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.34 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -24,7 +23,6 @@
#include "tcop/utility.h" #include "tcop/utility.h"
#include "utils/datum.h" #include "utils/datum.h"
#undef new
typedef enum typedef enum
{ {
@ -39,18 +37,18 @@ typedef struct local_es
ExecStatus status; ExecStatus status;
} execution_state; } execution_state;
#define LAST_POSTQUEL_COMMAND(es) ((es)->next == (execution_state *)NULL) #define LAST_POSTQUEL_COMMAND(es) ((es)->next == (execution_state *) NULL)
/* non-export function prototypes */ /* non-export function prototypes */
static TupleDesc postquel_start(execution_state *es); static TupleDesc postquel_start(execution_state *es);
static execution_state *init_execution_state(FunctionCachePtr fcache, static execution_state *init_execution_state(FunctionCachePtr fcache);
char *args[]);
static TupleTableSlot *postquel_getnext(execution_state *es); static TupleTableSlot *postquel_getnext(execution_state *es);
static void postquel_end(execution_state *es); static void postquel_end(execution_state *es);
static void postquel_sub_params(execution_state *es, int nargs, static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo);
char *args[], bool *nullV); static Datum postquel_execute(execution_state *es,
static Datum postquel_execute(execution_state *es, FunctionCachePtr fcache, FunctionCallInfo fcinfo,
List *fTlist, char **args, bool *isNull); FunctionCachePtr fcache,
List *func_tlist);
Datum Datum
@ -64,7 +62,6 @@ ProjectAttribute(TupleDesc TD,
Var *attrVar = (Var *) tlist->expr; Var *attrVar = (Var *) tlist->expr;
AttrNumber attrno = attrVar->varattno; AttrNumber attrno = attrVar->varattno;
val = heap_getattr(tup, attrno, TD, isnullP); val = heap_getattr(tup, attrno, TD, isnullP);
if (*isnullP) if (*isnullP)
return (Datum) NULL; return (Datum) NULL;
@ -77,8 +74,7 @@ ProjectAttribute(TupleDesc TD,
} }
static execution_state * static execution_state *
init_execution_state(FunctionCachePtr fcache, init_execution_state(FunctionCachePtr fcache)
char *args[])
{ {
execution_state *newes; execution_state *newes;
execution_state *nextes; execution_state *nextes;
@ -196,13 +192,10 @@ postquel_end(execution_state *es)
} }
static void static void
postquel_sub_params(execution_state *es, postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo)
int nargs,
char *args[],
bool *nullV)
{ {
ParamListInfo paramLI;
EState *estate; EState *estate;
ParamListInfo paramLI;
estate = es->estate; estate = es->estate;
paramLI = estate->es_param_list_info; paramLI = estate->es_param_list_info;
@ -211,9 +204,9 @@ postquel_sub_params(execution_state *es,
{ {
if (paramLI->kind == PARAM_NUM) if (paramLI->kind == PARAM_NUM)
{ {
Assert(paramLI->id <= nargs); Assert(paramLI->id <= fcinfo->nargs);
paramLI->value = (Datum) args[(paramLI->id - 1)]; paramLI->value = fcinfo->arg[paramLI->id - 1];
paramLI->isnull = nullV[(paramLI->id - 1)]; paramLI->isnull = fcinfo->argnull[paramLI->id - 1];
} }
paramLI++; paramLI++;
} }
@ -264,10 +257,9 @@ copy_function_result(FunctionCachePtr fcache,
static Datum static Datum
postquel_execute(execution_state *es, postquel_execute(execution_state *es,
FunctionCallInfo fcinfo,
FunctionCachePtr fcache, FunctionCachePtr fcache,
List *fTlist, List *func_tlist)
char **args,
bool *isNull)
{ {
TupleTableSlot *slot; TupleTableSlot *slot;
Datum value; Datum value;
@ -278,8 +270,8 @@ postquel_execute(execution_state *es,
* ExecutorStart->ExecInitIndexScan->ExecEvalParam works ok. (But * ExecutorStart->ExecInitIndexScan->ExecEvalParam works ok. (But
* note: I HOPE we can do it here). - vadim 01/22/97 * note: I HOPE we can do it here). - vadim 01/22/97
*/ */
if (fcache->nargs > 0) if (fcinfo->nargs > 0)
postquel_sub_params(es, fcache->nargs, args, fcache->nullVect); postquel_sub_params(es, fcinfo);
if (es->status == F_EXEC_START) if (es->status == F_EXEC_START)
{ {
@ -293,7 +285,7 @@ postquel_execute(execution_state *es,
{ {
postquel_end(es); postquel_end(es);
es->status = F_EXEC_DONE; es->status = F_EXEC_DONE;
*isNull = true; fcinfo->isnull = true;
/* /*
* If this isn't the last command for the function we have to * If this isn't the last command for the function we have to
@ -315,19 +307,20 @@ postquel_execute(execution_state *es,
* logic and code redundancy here. * logic and code redundancy here.
*/ */
resSlot = copy_function_result(fcache, slot); resSlot = copy_function_result(fcache, slot);
if (fTlist != NIL) if (func_tlist != NIL)
{ {
TargetEntry *tle = lfirst(fTlist); TargetEntry *tle = lfirst(func_tlist);
value = ProjectAttribute(resSlot->ttc_tupleDescriptor, value = ProjectAttribute(resSlot->ttc_tupleDescriptor,
tle, tle,
resSlot->val, resSlot->val,
isNull); &fcinfo->isnull);
} }
else else
{ {
value = (Datum) resSlot; /* XXX is this right? Return whole tuple slot?? */
*isNull = false; value = PointerGetDatum(resSlot);
fcinfo->isnull = false;
} }
/* /*
@ -353,11 +346,13 @@ postquel_execute(execution_state *es,
} }
Datum Datum
postquel_function(Func *funcNode, char **args, bool *isNull, bool *isDone) postquel_function(FunctionCallInfo fcinfo,
FunctionCachePtr fcache,
List *func_tlist,
bool *isDone)
{ {
execution_state *es; execution_state *es;
Datum result = 0; Datum result = 0;
FunctionCachePtr fcache = funcNode->func_fcache;
CommandId savedId; CommandId savedId;
/* /*
@ -371,7 +366,7 @@ postquel_function(Func *funcNode, char **args, bool *isNull, bool *isDone)
es = (execution_state *) fcache->func_state; es = (execution_state *) fcache->func_state;
if (es == NULL) if (es == NULL)
{ {
es = init_execution_state(fcache, args); es = init_execution_state(fcache);
fcache->func_state = (char *) es; fcache->func_state = (char *) es;
} }
@ -388,15 +383,19 @@ postquel_function(Func *funcNode, char **args, bool *isNull, bool *isDone)
while (es != (execution_state *) NULL) while (es != (execution_state *) NULL)
{ {
result = postquel_execute(es, result = postquel_execute(es,
fcinfo,
fcache, fcache,
funcNode->func_tlist, func_tlist);
args,
isNull);
if (es->status != F_EXEC_DONE) if (es->status != F_EXEC_DONE)
break; break;
es = es->next; es = es->next;
} }
/*
* Restore outer command ID.
*/
SetScanCommandId(savedId);
/* /*
* If we've gone through every command in this function, we are done. * If we've gone through every command in this function, we are done.
*/ */
@ -417,17 +416,15 @@ postquel_function(Func *funcNode, char **args, bool *isNull, bool *isDone)
* Let caller know we're finished. * Let caller know we're finished.
*/ */
*isDone = true; *isDone = true;
SetScanCommandId(savedId);
return (fcache->oneResult) ? result : (Datum) NULL; return (fcache->oneResult) ? result : (Datum) NULL;
} }
/* /*
* If we got a result from a command within the function it has to be * If we got a result from a command within the function it has to be
* the final command. All others shouldn't be returing anything. * the final command. All others shouldn't be returning anything.
*/ */
Assert(LAST_POSTQUEL_COMMAND(es)); Assert(LAST_POSTQUEL_COMMAND(es));
*isDone = false;
SetScanCommandId(savedId); *isDone = false;
return result; return result;
} }

View File

@ -32,7 +32,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.63 2000/04/12 17:15:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.64 2000/05/28 17:55:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -218,8 +218,13 @@ static void
advance_transition_functions(AggStatePerAgg peraggstate, advance_transition_functions(AggStatePerAgg peraggstate,
Datum newVal, bool isNull) Datum newVal, bool isNull)
{ {
Datum args[2]; FunctionCallInfoData fcinfo;
MemSet(&fcinfo, 0, sizeof(fcinfo));
/*
* XXX reconsider isNULL handling here
*/
if (OidIsValid(peraggstate->xfn1_oid) && !isNull) if (OidIsValid(peraggstate->xfn1_oid) && !isNull)
{ {
if (peraggstate->noInitValue) if (peraggstate->noInitValue)
@ -244,28 +249,48 @@ advance_transition_functions(AggStatePerAgg peraggstate,
else else
{ {
/* apply transition function 1 */ /* apply transition function 1 */
args[0] = peraggstate->value1; fcinfo.flinfo = &peraggstate->xfn1;
args[1] = newVal; fcinfo.nargs = 2;
newVal = (Datum) fmgr_c(&peraggstate->xfn1, fcinfo.arg[0] = peraggstate->value1;
(FmgrValues *) args, fcinfo.argnull[0] = peraggstate->value1IsNull;
&isNull); fcinfo.arg[1] = newVal;
if (!peraggstate->transtype1ByVal) fcinfo.argnull[1] = isNull;
if (fcinfo.flinfo->fn_strict &&
(peraggstate->value1IsNull || isNull))
{
/* don't call a strict function with NULL inputs */
newVal = (Datum) 0;
fcinfo.isnull = true;
}
else
newVal = FunctionCallInvoke(&fcinfo);
if (!peraggstate->transtype1ByVal && !peraggstate->value1IsNull)
pfree(peraggstate->value1); pfree(peraggstate->value1);
peraggstate->value1 = newVal; peraggstate->value1 = newVal;
peraggstate->value1IsNull = fcinfo.isnull;
} }
} }
if (OidIsValid(peraggstate->xfn2_oid)) if (OidIsValid(peraggstate->xfn2_oid))
{ {
/* apply transition function 2 */ /* apply transition function 2 */
args[0] = peraggstate->value2; fcinfo.flinfo = &peraggstate->xfn2;
isNull = false; /* value2 cannot be null, currently */ fcinfo.nargs = 1;
newVal = (Datum) fmgr_c(&peraggstate->xfn2, fcinfo.arg[0] = peraggstate->value2;
(FmgrValues *) args, fcinfo.argnull[0] = peraggstate->value2IsNull;
&isNull); fcinfo.isnull = false; /* must reset after use by xfn1 */
if (!peraggstate->transtype2ByVal) if (fcinfo.flinfo->fn_strict && peraggstate->value2IsNull)
{
/* don't call a strict function with NULL inputs */
newVal = (Datum) 0;
fcinfo.isnull = true;
}
else
newVal = FunctionCallInvoke(&fcinfo);
if (!peraggstate->transtype2ByVal && !peraggstate->value2IsNull)
pfree(peraggstate->value2); pfree(peraggstate->value2);
peraggstate->value2 = newVal; peraggstate->value2 = newVal;
peraggstate->value2IsNull = fcinfo.isnull;
} }
} }
@ -276,8 +301,10 @@ static void
finalize_aggregate(AggStatePerAgg peraggstate, finalize_aggregate(AggStatePerAgg peraggstate,
Datum *resultVal, bool *resultIsNull) Datum *resultVal, bool *resultIsNull)
{ {
Aggref *aggref = peraggstate->aggref; Aggref *aggref = peraggstate->aggref;
char *args[2]; FunctionCallInfoData fcinfo;
MemSet(&fcinfo, 0, sizeof(fcinfo));
/* /*
* If it's a DISTINCT aggregate, all we've done so far is to stuff the * If it's a DISTINCT aggregate, all we've done so far is to stuff the
@ -337,21 +364,41 @@ finalize_aggregate(AggStatePerAgg peraggstate,
if (OidIsValid(peraggstate->finalfn_oid) && if (OidIsValid(peraggstate->finalfn_oid) &&
!peraggstate->noInitValue) !peraggstate->noInitValue)
{ {
fcinfo.flinfo = &peraggstate->finalfn;
if (peraggstate->finalfn.fn_nargs > 1) if (peraggstate->finalfn.fn_nargs > 1)
{ {
args[0] = (char *) peraggstate->value1; fcinfo.nargs = 2;
args[1] = (char *) peraggstate->value2; fcinfo.arg[0] = peraggstate->value1;
fcinfo.argnull[0] = peraggstate->value1IsNull;
fcinfo.arg[1] = peraggstate->value2;
fcinfo.argnull[1] = peraggstate->value2IsNull;
} }
else if (OidIsValid(peraggstate->xfn1_oid)) else if (OidIsValid(peraggstate->xfn1_oid))
args[0] = (char *) peraggstate->value1; {
fcinfo.nargs = 1;
fcinfo.arg[0] = peraggstate->value1;
fcinfo.argnull[0] = peraggstate->value1IsNull;
}
else if (OidIsValid(peraggstate->xfn2_oid)) else if (OidIsValid(peraggstate->xfn2_oid))
args[0] = (char *) peraggstate->value2; {
fcinfo.nargs = 1;
fcinfo.arg[0] = peraggstate->value2;
fcinfo.argnull[0] = peraggstate->value2IsNull;
}
else else
elog(ERROR, "ExecAgg: no valid transition functions??"); elog(ERROR, "ExecAgg: no valid transition functions??");
*resultIsNull = false; if (fcinfo.flinfo->fn_strict &&
*resultVal = (Datum) fmgr_c(&peraggstate->finalfn, (fcinfo.argnull[0] || fcinfo.argnull[1]))
(FmgrValues *) args, {
resultIsNull); /* don't call a strict function with NULL inputs */
*resultVal = (Datum) 0;
*resultIsNull = true;
}
else
{
*resultVal = FunctionCallInvoke(&fcinfo);
*resultIsNull = fcinfo.isnull;
}
} }
else if (OidIsValid(peraggstate->xfn1_oid)) else if (OidIsValid(peraggstate->xfn1_oid))
{ {

View File

@ -4,7 +4,7 @@
# Makefile for libpq subsystem (backend half of libpq interface) # Makefile for libpq subsystem (backend half of libpq interface)
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.17 2000/01/19 02:58:52 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.18 2000/05/28 17:55:56 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -29,11 +29,6 @@ all: SUBSYS.o
SUBSYS.o: $(OBJS) SUBSYS.o: $(OBJS)
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS) $(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
be-dumpdata.o be-pqexec.o: ../fmgr.h
../fmgr.h:
$(MAKE) -C .. fmgr.h
depend dep: depend dep:
$(CC) -MM $(CFLAGS) *.c >depend $(CC) -MM $(CFLAGS) *.c >depend

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.31 2000/03/17 02:36:08 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.32 2000/05/28 17:55:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -42,11 +42,11 @@ static char *strmake(char *str, int len);
* result_buf : pointer to result buffer (&int if integer) * result_buf : pointer to result buffer (&int if integer)
* result_len : length of return value. * result_len : length of return value.
* result_is_int : If the result is an integer, this must be non-zero * result_is_int : If the result is an integer, this must be non-zero
* args : pointer to a NULL terminated arg array. * args : pointer to an array of PQArgBlock items.
* (length, if integer, and result-pointer) * (length, if integer, and result-pointer)
* nargs : # of arguments in args array. * nargs : # of arguments in args array.
* *
* This code scavanged from HandleFunctionRequest() in tcop/fastpath.h * This code scavenged from HandleFunctionRequest() in tcop/fastpath.h
* ---------------- * ----------------
*/ */
char * char *
@ -57,46 +57,53 @@ PQfn(int fnid,
PQArgBlock *args, PQArgBlock *args,
int nargs) int nargs)
{ {
char *retval; /* XXX - should be datum, maybe ? */ FmgrInfo flinfo;
char *arg[FUNC_MAX_ARGS]; FunctionCallInfoData fcinfo;
bool isNull; Datum retval;
int i; int i;
/* ----------------
* fill args[] array
* ----------------
*/
if (nargs > FUNC_MAX_ARGS) if (nargs > FUNC_MAX_ARGS)
elog(ERROR, "functions cannot have more than %d arguments", elog(ERROR, "functions cannot have more than %d arguments",
FUNC_MAX_ARGS); FUNC_MAX_ARGS);
/* ----------------
* set up the argument block for the function manager
* ----------------
*/
fmgr_info((Oid) fnid, &flinfo);
MemSet(&fcinfo, 0, sizeof(fcinfo));
fcinfo.flinfo = &flinfo;
fcinfo.nargs = nargs;
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
if (args[i].len == VAR_LENGTH_ARG) if (args[i].len == VAR_LENGTH_ARG)
arg[i] = (char *) args[i].u.ptr; fcinfo.arg[i] = (Datum) args[i].u.ptr;
else if ((Size) args[i].len > sizeof(int4)) else if ((Size) args[i].len > sizeof(int4))
elog(ERROR, "arg_length of argument %d too long", i); elog(ERROR, "arg_length of argument %d too long", i);
else else
arg[i] = (char *) args[i].u.integer; fcinfo.arg[i] = (Datum) args[i].u.integer;
} }
/* ---------------- /* ----------------
* call the postgres function manager * call the postgres function manager
* ---------------- * ----------------
*/ */
retval = fmgr_array_args(fnid, nargs, arg, &isNull); retval = FunctionCallInvoke(&fcinfo);
/* ---------------- /* ----------------
* put the result in the buffer the user specified and * put the result in the buffer the user specified and
* return the proper code. * return the proper code.
* ---------------- * ----------------
*/ */
if (isNull) /* void retval */ if (fcinfo.isnull) /* void retval */
return "0"; return "0";
if (result_is_int) if (result_is_int)
*result_buf = (int) retval; *result_buf = DatumGetInt32(retval);
else else
memmove(result_buf, retval, result_len); memmove(result_buf, DatumGetPointer(retval), result_len);
return "G"; return "G";
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.40 2000/04/12 17:15:16 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.41 2000/05/28 17:55:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -530,16 +530,12 @@ _freeFcache(FunctionCachePtr ptr)
{ {
if (ptr->argOidVect) if (ptr->argOidVect)
pfree(ptr->argOidVect); pfree(ptr->argOidVect);
if (ptr->nullVect)
pfree(ptr->nullVect);
if (ptr->src) if (ptr->src)
pfree(ptr->src); pfree(ptr->src);
if (ptr->bin) if (ptr->bin)
pfree(ptr->bin); pfree(ptr->bin);
if (ptr->func_state) if (ptr->func_state)
pfree(ptr->func_state); pfree(ptr->func_state);
if (ptr->setArg)
pfree(ptr->setArg);
pfree(ptr); pfree(ptr);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.34 2000/04/12 17:15:19 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.35 2000/05/28 17:55:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -21,6 +21,7 @@
#include "optimizer/plancat.h" #include "optimizer/plancat.h"
#include "optimizer/restrictinfo.h" #include "optimizer/restrictinfo.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.83 2000/04/16 04:41:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.84 2000/05/28 17:55:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -37,6 +37,7 @@
#include "parser/parse_oper.h" #include "parser/parse_oper.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/syscache.h" #include "utils/syscache.h"

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.50 2000/04/12 17:15:24 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.51 2000/05/28 17:55:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -28,6 +28,8 @@
#include "optimizer/paths.h" #include "optimizer/paths.h"
#include "optimizer/plancat.h" #include "optimizer/plancat.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "miscadmin.h" #include "miscadmin.h"
@ -117,7 +119,7 @@ find_secondary_indexes(Query *root, Index relid)
info->indproc = index->indproc; /* functional index ?? */ info->indproc = index->indproc; /* functional index ?? */
if (VARSIZE(&index->indpred) != 0) /* partial index ?? */ if (VARSIZE(&index->indpred) != 0) /* partial index ?? */
{ {
char *predString = fmgr(F_TEXTOUT, &index->indpred); char *predString = textout(&index->indpred);
info->indpred = (List *) stringToNode(predString); info->indpred = (List *) stringToNode(predString);
pfree(predString); pfree(predString);

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: analyze.c,v 1.142 2000/04/12 17:15:26 momjian Exp $ * $Id: analyze.c,v 1.143 2000/05/28 17:56:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -26,6 +26,7 @@
#include "parser/parse_target.h" #include "parser/parse_target.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/numeric.h" #include "utils/numeric.h"
void CheckSelectForUpdate(Query *qry); /* no points for style... */ void CheckSelectForUpdate(Query *qry); /* no points for style... */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.79 2000/05/26 03:56:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.80 2000/05/28 17:56:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -34,6 +34,7 @@
#include "parser/parse_target.h" #include "parser/parse_target.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/syscache.h" #include "utils/syscache.h"

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.39 2000/04/12 17:15:27 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.40 2000/05/28 17:56:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -442,14 +442,11 @@ make_const(Value *value)
case T_Float: case T_Float:
if (fitsInFloat(value)) if (fitsInFloat(value))
{ {
float64 fltval = (float64) palloc(sizeof(float64data)); val = Float8GetDatum(floatVal(value));
*fltval = floatVal(value);
val = Float64GetDatum(fltval);
typeid = FLOAT8OID; typeid = FLOAT8OID;
typelen = sizeof(float64data); typelen = sizeof(float8);
typebyval = false; typebyval = false; /* XXX might change someday */
} }
else else
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.40 2000/04/12 17:15:27 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.41 2000/05/28 17:56:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -22,6 +22,7 @@
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "parser/parse_oper.h" #include "parser/parse_oper.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
static Oid *oper_select_candidate(int nargs, Oid *input_typeids, static Oid *oper_select_candidate(int nargs, Oid *input_typeids,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: alpha.h,v 1.4 2000/01/26 05:56:44 momjian Exp $ * $Id: alpha.h,v 1.5 2000/05/28 17:56:02 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -29,7 +29,7 @@
* *
*/ */
#define pg_dlopen(f) dlopen(f, RTLD_LAZY) #define pg_dlopen(f) dlopen(f, RTLD_LAZY)
#define pg_dlsym(h, f) ((func_ptr)dlsym(h, f)) #define pg_dlsym(h, f) ((PGFunction) dlsym(h, f))
#define pg_dlclose(h) dlclose(h) #define pg_dlclose(h) dlclose(h)
#define pg_dlerror() dlerror() #define pg_dlerror() dlerror()

View File

@ -26,7 +26,7 @@
#define pg_dlclose dlclose #define pg_dlclose dlclose
#define pg_dlerror dlerror #define pg_dlerror dlerror
#else #else
#define pg_dlsym(handle, funcname) ((func_ptr) dld_get_func((funcname))) #define pg_dlsym(handle, funcname) ((PGFunction) dld_get_func((funcname)))
#define pg_dlclose(handle) ({ dld_unlink_by_file(handle, 1); free(handle); }) #define pg_dlclose(handle) ({ dld_unlink_by_file(handle, 1); free(handle); })
#endif #endif

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/port/dynloader/hpux.c,v 1.13 2000/04/26 23:35:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/port/dynloader/hpux.c,v 1.14 2000/05/28 17:56:02 tgl Exp $
* *
* NOTES * NOTES
* all functions are defined here -- it's impossible to trace the * all functions are defined here -- it's impossible to trace the
@ -39,13 +39,13 @@ pg_dlopen(char *filename)
return (void *) handle; return (void *) handle;
} }
func_ptr PGFunction
pg_dlsym(void *handle, char *funcname) pg_dlsym(void *handle, char *funcname)
{ {
func_ptr f; PGFunction f;
if (shl_findsym((shl_t *) & handle, funcname, TYPE_PROCEDURE, &f) == -1) if (shl_findsym((shl_t *) & handle, funcname, TYPE_PROCEDURE, &f) == -1)
f = (func_ptr) NULL; f = (PGFunction) NULL;
return f; return f;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/port/dynloader/hpux.h,v 1.3 2000/01/26 05:56:44 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/port/dynloader/hpux.h,v 1.4 2000/05/28 17:56:02 tgl Exp $
* *
* NOTES * NOTES
* all functions are defined here -- it's impossible to trace the * all functions are defined here -- it's impossible to trace the
@ -17,7 +17,9 @@
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
/* System includes */ /* System includes */
#include "fmgr.h"
void *pg_dlopen(char *filename); void *pg_dlopen(char *filename);
func_ptr pg_dlsym(void *handle, char *funcname); PGFunction pg_dlsym(void *handle, char *funcname);
void pg_dlclose(void *handle); void pg_dlclose(void *handle);
char *pg_dlerror(); char *pg_dlerror();

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: linux.h,v 1.8 2000/01/26 05:56:44 momjian Exp $ * $Id: linux.h,v 1.9 2000/05/28 17:56:02 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -27,7 +27,7 @@
#define pg_dlsym(handle, funcname) (NULL) #define pg_dlsym(handle, funcname) (NULL)
#define pg_dlclose(handle) ({}) #define pg_dlclose(handle) ({})
#else #else
#define pg_dlsym(handle, funcname) ((func_ptr) dld_get_func((funcname))) #define pg_dlsym(handle, funcname) ((PGFunction) dld_get_func((funcname)))
#define pg_dlclose(handle) ({ dld_unlink_by_file(handle, 1); free(handle); }) #define pg_dlclose(handle) ({ dld_unlink_by_file(handle, 1); free(handle); })
#endif #endif
#else #else

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/port/dynloader/Attic/qnx4.c,v 1.1 1999/12/16 01:25:04 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/port/dynloader/Attic/qnx4.c,v 1.2 2000/05/28 17:56:02 tgl Exp $
* *
* NOTES * NOTES
* *
@ -30,7 +30,7 @@ pg_dlopen(char *filename)
return (void *) NULL; return (void *) NULL;
} }
func_ptr PGFunction
pg_dlsym(void *handle, char *funcname) pg_dlsym(void *handle, char *funcname)
{ {
return NULL; return NULL;

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/port/dynloader/Attic/qnx4.h,v 1.1 1999/12/16 01:25:04 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/port/dynloader/Attic/qnx4.h,v 1.2 2000/05/28 17:56:02 tgl Exp $
* *
* NOTES * NOTES
* *
@ -15,6 +15,6 @@
*/ */
/* System includes */ /* System includes */
void *pg_dlopen(char *filename); void *pg_dlopen(char *filename);
func_ptr pg_dlsym(void *handle, char *funcname); PGFunction pg_dlsym(void *handle, char *funcname);
void pg_dlclose(void *handle); void pg_dlclose(void *handle);
char *pg_dlerror(); char *pg_dlerror();

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.36 2000/04/12 17:15:32 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.37 2000/05/28 17:56:02 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -23,6 +23,7 @@
#include "commands/comment.h" #include "commands/comment.h"
#include "rewrite/rewriteRemove.h" #include "rewrite/rewriteRemove.h"
#include "rewrite/rewriteSupport.h" #include "rewrite/rewriteSupport.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
/*----------------------------------------------------------------------- /*-----------------------------------------------------------------------

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.67 2000/04/12 17:15:37 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.68 2000/05/28 17:56:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -31,6 +31,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/large_object.h" #include "storage/large_object.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/fmgroids.h"
#include "utils/relcache.h" #include "utils/relcache.h"
/* /*

View File

@ -4,7 +4,7 @@
# Makefile for tcop # Makefile for tcop
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/tcop/Makefile,v 1.21 2000/01/19 02:58:56 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/tcop/Makefile,v 1.22 2000/05/28 17:56:04 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -29,18 +29,12 @@ SUBSYS.o: $(OBJS)
# dependencies (because they don't even exist until you make them), # dependencies (because they don't even exist until you make them),
# they are hardcoded here. # they are hardcoded here.
utility.o: ../parse.h ../fmgr.h utility.o: ../parse.h
aclchk.o: ../fmgr.h
fastpath.o: ../fmgr.h
postgres.o: ../fmgr.h
../parse.h: ../parse.h:
$(MAKE) -C .. parse.h $(MAKE) -C .. parse.h
../fmgr.h: dep depend: ../parse.h
$(MAKE) -C .. fmgr.h
dep depend: ../parse.h ../fmgr.h
$(CC) -MM $(CFLAGS) *.c >depend $(CC) -MM $(CFLAGS) *.c >depend
clean: clean:

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.38 2000/04/12 17:15:43 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.39 2000/05/28 17:56:04 tgl Exp $
* *
* NOTES * NOTES
* This cruft is the server side of PQfn. * This cruft is the server side of PQfn.
@ -76,11 +76,9 @@
* ---------------- * ----------------
*/ */
static void static void
SendFunctionResult(Oid fid, /* function id */ SendFunctionResult(Datum retval, /* actual return value */
char *retval,/* actual return value */
bool retbyval, bool retbyval,
int retlen /* the length according to the catalogs */ int retlen) /* the length according to the catalogs */
)
{ {
StringInfoData buf; StringInfoData buf;
@ -93,19 +91,21 @@ SendFunctionResult(Oid fid, /* function id */
if (retbyval) if (retbyval)
{ /* by-value */ { /* by-value */
pq_sendint(&buf, retlen, 4); pq_sendint(&buf, retlen, 4);
pq_sendint(&buf, (int) (Datum) retval, retlen); pq_sendint(&buf, DatumGetInt32(retval), retlen);
} }
else else
{ /* by-reference ... */ { /* by-reference ... */
if (retlen < 0) if (retlen < 0)
{ /* ... varlena */ { /* ... varlena */
pq_sendint(&buf, VARSIZE(retval) - VARHDRSZ, VARHDRSZ); struct varlena *v = (struct varlena *) DatumGetPointer(retval);
pq_sendbytes(&buf, VARDATA(retval), VARSIZE(retval) - VARHDRSZ);
pq_sendint(&buf, VARSIZE(v) - VARHDRSZ, VARHDRSZ);
pq_sendbytes(&buf, VARDATA(v), VARSIZE(v) - VARHDRSZ);
} }
else else
{ /* ... fixed */ { /* ... fixed */
pq_sendint(&buf, retlen, 4); pq_sendint(&buf, retlen, 4);
pq_sendbytes(&buf, retval, retlen); pq_sendbytes(&buf, DatumGetPointer(retval), retlen);
} }
} }
} }
@ -127,12 +127,12 @@ SendFunctionResult(Oid fid, /* function id */
struct fp_info struct fp_info
{ {
Oid funcid; Oid funcid;
int nargs; FmgrInfo flinfo; /* function lookup info for funcid */
bool argbyval[FUNC_MAX_ARGS]; bool argbyval[FUNC_MAX_ARGS];
int32 arglen[FUNC_MAX_ARGS]; /* signed (for varlena) */ int32 arglen[FUNC_MAX_ARGS]; /* signed (for varlena) */
bool retbyval; bool retbyval;
int32 retlen; /* signed (for varlena) */ int32 retlen; /* signed (for varlena) */
TransactionId xid; TransactionId xid; /* when the lookup was done */
CommandId cid; CommandId cid;
}; };
@ -147,17 +147,17 @@ static struct fp_info last_fp = {InvalidOid};
* valid_fp_info * valid_fp_info
* *
* RETURNS: * RETURNS:
* 1 if the state in 'fip' is valid * T if the state in 'fip' is valid for the given func OID
* 0 otherwise * F otherwise
* *
* "valid" means: * "invalid" means:
* The saved state was either uninitialized, for another function, * The saved state was either uninitialized, for another function,
* or from a previous command. (Commands can do updates, which * or from a previous command. (Commands can do updates, which
* may invalidate catalog entries for subsequent commands. This * may invalidate catalog entries for subsequent commands. This
* is overly pessimistic but since there is no smarter invalidation * is overly pessimistic but since there is no smarter invalidation
* scheme...). * scheme...).
*/ */
static int static bool
valid_fp_info(Oid func_id, struct fp_info * fip) valid_fp_info(Oid func_id, struct fp_info * fip)
{ {
Assert(OidIsValid(func_id)); Assert(OidIsValid(func_id));
@ -212,11 +212,10 @@ update_fp_info(Oid func_id, struct fp_info * fip)
func_id); func_id);
} }
pp = (Form_pg_proc) GETSTRUCT(func_htp); pp = (Form_pg_proc) GETSTRUCT(func_htp);
fip->nargs = pp->pronargs;
rettype = pp->prorettype; rettype = pp->prorettype;
argtypes = pp->proargtypes; argtypes = pp->proargtypes;
for (i = 0; i < fip->nargs; ++i) for (i = 0; i < fip->flinfo.fn_nargs; ++i)
{ {
if (OidIsValid(argtypes[i])) if (OidIsValid(argtypes[i]))
{ {
@ -252,6 +251,8 @@ update_fp_info(Oid func_id, struct fp_info * fip)
fip->xid = GetCurrentTransactionId(); fip->xid = GetCurrentTransactionId();
fip->cid = GetCurrentCommandId(); fip->cid = GetCurrentCommandId();
fmgr_info(func_id, &fip->flinfo);
/* /*
* This must be last! * This must be last!
*/ */
@ -279,11 +280,9 @@ HandleFunctionRequest()
int argsize; int argsize;
int nargs; int nargs;
int tmp; int tmp;
char *arg[FUNC_MAX_ARGS]; FunctionCallInfoData fcinfo;
char *retval; Datum retval;
bool isNull;
int i; int i;
uint32 palloced;
char *p; char *p;
struct fp_info *fip; struct fp_info *fip;
@ -305,89 +304,81 @@ HandleFunctionRequest()
* XXX FIXME: elog() here means we lose sync with the frontend, since * XXX FIXME: elog() here means we lose sync with the frontend, since
* we have not swallowed all of its input message. What should happen * we have not swallowed all of its input message. What should happen
* is we absorb all of the input message per protocol syntax, and * is we absorb all of the input message per protocol syntax, and
* *then* do error checking and elog if appropriate. * *then* do error checking (including lookup of the given function ID)
* and elog if appropriate. Unfortunately, because we cannot even read
* the message properly without knowing whether the data types are
* pass-by-ref or pass-by-value, it's not all that easy to fix :-(.
* This protocol is misdesigned.
*/ */
if (fip->nargs != nargs) if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)
{ {
elog(ERROR, "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)", elog(ERROR, "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)",
nargs, fip->nargs); nargs, fip->flinfo.fn_nargs);
} }
/* MemSet(&fcinfo, 0, sizeof(fcinfo));
* Copy arguments into arg vector. If we palloc() an argument, we fcinfo.flinfo = &fip->flinfo;
* need to remember, so that we pfree() it after the call. fcinfo.nargs = nargs;
*/
palloced = 0x0;
for (i = 0; i < FUNC_MAX_ARGS; ++i)
{
if (i >= nargs)
arg[i] = (char *) NULL;
else
{
if (pq_getint(&argsize, 4))
return EOF;
Assert(argsize > 0); /*
if (fip->argbyval[i]) * Copy supplied arguments into arg vector. Note there is no way for
{ /* by-value */ * frontend to specify a NULL argument --- more misdesign.
Assert(argsize <= 4); */
if (pq_getint(&tmp, argsize)) for (i = 0; i < nargs; ++i)
{
if (pq_getint(&argsize, 4))
return EOF;
if (fip->argbyval[i])
{ /* by-value */
if (argsize < 1 || argsize > 4)
elog(ERROR, "HandleFunctionRequest: bogus argsize %d",
argsize);
/* XXX should we demand argsize == fip->arglen[i] ? */
if (pq_getint(&tmp, argsize))
return EOF;
fcinfo.arg[i] = (Datum) tmp;
}
else
{ /* by-reference ... */
if (fip->arglen[i] < 0)
{ /* ... varlena */
if (argsize < 0)
elog(ERROR, "HandleFunctionRequest: bogus argsize %d",
argsize);
/* I suspect this +1 isn't really needed - tgl 5/2000 */
p = palloc(argsize + VARHDRSZ + 1); /* Added +1 to solve
* memory leak - Peter
* 98 Jan 6 */
VARSIZE(p) = argsize + VARHDRSZ;
if (pq_getbytes(VARDATA(p), argsize))
return EOF; return EOF;
arg[i] = (char *) tmp;
} }
else else
{ /* by-reference ... */ { /* ... fixed */
if (fip->arglen[i] < 0) if (argsize != fip->arglen[i])
{ /* ... varlena */ elog(ERROR, "HandleFunctionRequest: bogus argsize %d, should be %d",
if (!(p = palloc(argsize + VARHDRSZ + 1))) /* Added +1 to solve argsize, fip->arglen[i]);
* memory leak - Peter p = palloc(argsize + 1); /* +1 in case argsize is 0 */
* 98 Jan 6 */ if (pq_getbytes(p, argsize))
elog(ERROR, "HandleFunctionRequest: palloc failed"); return EOF;
VARSIZE(p) = argsize + VARHDRSZ;
if (pq_getbytes(VARDATA(p), argsize))
return EOF;
}
else
{ /* ... fixed */
/* XXX cross our fingers and trust "argsize" */
if (!(p = palloc(argsize + 1)))
elog(ERROR, "HandleFunctionRequest: palloc failed");
if (pq_getbytes(p, argsize))
return EOF;
}
palloced |= (1 << i);
arg[i] = p;
} }
fcinfo.arg[i] = PointerGetDatum(p);
} }
} }
#ifndef NO_FASTPATH #ifdef NO_FASTPATH
retval = fmgr_array_args(fid, nargs, arg, &isNull); /* force a NULL return */
retval = (Datum) 0;
fcinfo.isnull = true;
#else #else
retval = NULL; retval = FunctionCallInvoke(&fcinfo);
#endif /* NO_FASTPATH */ #endif /* NO_FASTPATH */
/* free palloc'ed arguments */ if (fcinfo.isnull)
for (i = 0; i < nargs; ++i) SendFunctionResult(retval, fip->retbyval, 0);
{ else
if (palloced & (1 << i)) SendFunctionResult(retval, fip->retbyval, fip->retlen);
pfree(arg[i]);
}
/*
* If this is an ordinary query (not a retrieve portal p ...), then we
* return the data to the user. If the return value was palloc'ed,
* then it must also be freed.
*/
#ifndef NO_FASTPATH
SendFunctionResult(fid, retval, fip->retbyval, fip->retlen);
#else
SendFunctionResult(fid, retval, fip->retbyval, 0);
#endif /* NO_FASTPATH */
if (!fip->retbyval)
pfree(retval);
return 0; return 0;
} }

View File

@ -1,14 +1,15 @@
#!/bin/sh #!/bin/sh
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Gen_fmgrtab.sh-- # Gen_fmgrtab.sh
# shell script to generate fmgr.h and fmgrtab.c from pg_proc.h # 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 # 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 # NOTES
# Passes any -D options on to cpp prior to generating the list # 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='' BKIOPTS=''
# #
@ -32,7 +27,7 @@ for opt in $*
do do
case $opt in case $opt in
-D) BKIOPTS="$BKIOPTS -D$2"; shift; shift;; -D) BKIOPTS="$BKIOPTS -D$2"; shift; shift;;
-D*) BKIOPTS="$BKIOPTS $1";shift;; -D*) BKIOPTS="$BKIOPTS $1"; shift;;
--) shift; break;; --) shift; break;;
-*) shift;; -*) shift;;
esac esac
@ -41,8 +36,8 @@ done
INFILE=$1 INFILE=$1
RAWFILE=fmgr.raw RAWFILE=fmgr.raw
CPPTMPFILE=fmgrtmp.c CPPTMPFILE=fmgrtmp.c
HFILE=fmgr.h OIDSFILE=fmgroids.h
TABCFILE=fmgrtab.c TABLEFILE=fmgrtab.c
# #
# Generate the file containing raw pg_proc tuple data # Generate the file containing raw pg_proc tuple data
@ -63,7 +58,8 @@ sed -e 's/^.*OID[^=]*=[^0-9]*//' \
-e 's/[ ]*).*$//' | \ -e 's/[ ]*).*$//' | \
awk ' awk '
/^#/ { print; next; } /^#/ { print; next; }
$4 == "11" { print; next; }' > $CPPTMPFILE $4 == "11" { print; next; }
$4 == "12" { print; next; }' > $CPPTMPFILE
@CPP@ $BKIOPTS $CPPTMPFILE | \ @CPP@ $BKIOPTS $CPPTMPFILE | \
egrep '^[0-9]' | \ egrep '^[0-9]' | \
@ -72,18 +68,21 @@ sort -n > $RAWFILE
rm -f $CPPTMPFILE rm -f $CPPTMPFILE
# #
# Generate fmgr.h # Generate fmgroids.h
# #
cat > $HFILE <<FuNkYfMgRsTuFf cat > $OIDSFILE <<FuNkYfMgRsTuFf
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* $HFILE-- * $OIDSFILE
* Definitions for using internal procedures. * 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 * NOTES
* ****************************** * ******************************
@ -91,77 +90,12 @@ cat > $HFILE <<FuNkYfMgRsTuFf
* ****************************** * ******************************
* *
* It has been GENERATED by $0 * It has been GENERATED by $0
* from $1 * from $INFILE
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef FMGR_H #ifndef FMGROIDS_H
#define FMGR_H #define FMGROIDS_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 */
/* /*
* Constant macros for the OIDs of entries in pg_proc. * Constant macros for the OIDs of entries in pg_proc.
@ -174,30 +108,33 @@ FuNkYfMgRsTuFf
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $RAWFILE | \ tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $RAWFILE | \
awk ' awk '
BEGIN { OFS = ""; } 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 FuNkYfMgRsTuFf
# #
# Generate fmgr function table file. # Generate fmgr's built-in-function table.
# #
# Print out the bogus function declarations, then the table that # Print out the function declarations, then the table that refers to them.
# 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. * 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 * 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 * NOTES
* *
@ -206,72 +143,41 @@ cat > $TABCFILE <<FuNkYfMgRtAbStUfF
* ****************************** * ******************************
* *
* It has been GENERATED by $0 * 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 * builtin functions; all ld cares about is the fact that it
* will need to resolve an external function reference. * will need to resolve an external function reference.
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include <string.h>
#include "postgres.h" #include "postgres.h"
#include "utils/fmgrtab.h" #include "utils/fmgrtab.h"
FuNkYfMgRtAbStUfF 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 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 */ /* 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 */ /* Note fmgr_nbuiltins excludes the dummy entry */
#define FMGR_NBUILTINS ((sizeof(fmgr_builtins) / sizeof(FmgrCall)) - 1) const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 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;
}
FuNkYfMgRtAbStUfF FuNkYfMgRtAbStUfF

View File

@ -4,12 +4,12 @@
# Makefile for utils # Makefile for utils
# #
# IDENTIFICATION # 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 = ../.. SRCDIR = ../..
include ../../Makefile.global include $(SRCDIR)/Makefile.global
INCLUDE_OPT = -I.. INCLUDE_OPT = -I..
@ -35,19 +35,14 @@ SUBSYS.o: $(OBJS)
submake: submake:
for i in $(DIRS); do $(MAKE) -C $$i SUBSYS.o; done for i in $(DIRS); do $(MAKE) -C $$i SUBSYS.o; done
fmgrtab.o: ../fmgr.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
../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
clean: 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 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 for i in $(DIRS); do $(MAKE) -C $$i depend; done
ifeq (depend,$(wildcard depend)) ifeq (depend,$(wildcard depend))

View File

@ -3,6 +3,12 @@
* int8.c * int8.c
* Internal 64-bit integer operations * 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> #include <ctype.h>
@ -18,6 +24,11 @@
#include "utils/int8.h" #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 #define MAXINT8LEN 25
#ifndef INT_MAX #ifndef INT_MAX

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 "catalog/pg_type.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
/***************************************************************************** /*****************************************************************************

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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) switch (typid)
{ {
case BOOLOID: case BOOLOID:
return (double) DatumGetUInt8(value); return (double) DatumGetBool(value);
case INT2OID: case INT2OID:
return (double) DatumGetInt16(value); return (double) DatumGetInt16(value);
case INT4OID: case INT4OID:
return (double) DatumGetInt32(value); return (double) DatumGetInt32(value);
case INT8OID: case INT8OID:
return (double) (*i8tod((int64 *) DatumGetPointer(value))); return (double) DatumGetInt64(value);
case FLOAT4OID: case FLOAT4OID:
return (double) (*DatumGetFloat32(value)); return (double) DatumGetFloat4(value);
case FLOAT8OID: case FLOAT8OID:
return (double) (*DatumGetFloat64(value)); return (double) DatumGetFloat8(value);
case NUMERICOID: case NUMERICOID:
return (double) (*numeric_float8((Numeric) DatumGetPointer(value))); return (double) (*numeric_float8((Numeric) DatumGetPointer(value)));
case OIDOID: case OIDOID:

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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 */ "sql", /* languageName */
querystr, /* sourceCode */ querystr, /* sourceCode */
fileName, /* fileName */ fileName, /* fileName */
false, /* canCache */
true, /* trusted */ true, /* trusted */
false, /* canCache XXX appropriate? */
false, /* isStrict XXX appropriate? */
100, /* byte_pct */ 100, /* byte_pct */
0, /* perbyte_cpu */ 0, /* perbyte_cpu */
0, /* percall_cpu */ 0, /* percall_cpu */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 "catalog/indexing.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/catcache.h" #include "utils/catcache.h"
#include "utils/syscache.h" #include "utils/syscache.h"

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 Oid GetDynamicFuncArgType(Var *arg, ExprContext *econtext);
static FunctionCachePtr init_fcache(Oid foid, static FunctionCachePtr init_fcache(Oid foid,
bool use_syscache, List *argList,
List *argList, ExprContext *econtext);
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) \ #define FuncArgTypeIsDynamic(arg) \
(IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber) (IsA(arg,Var) && ((Var*)arg)->varattno == InvalidAttrNumber)
@ -53,7 +42,6 @@ GetDynamicFuncArgType(Var *arg, ExprContext *econtext)
rtid = ((Var *) arg)->varno; rtid = ((Var *) arg)->varno;
relname = (char *) getrelname(rtid, econtext->ecxt_range_table); relname = (char *) getrelname(rtid, econtext->ecxt_range_table);
tup = SearchSysCacheTuple(TYPENAME, tup = SearchSysCacheTuple(TYPENAME,
PointerGetDatum(relname), PointerGetDatum(relname),
0, 0, 0); 0, 0, 0);
@ -64,9 +52,14 @@ GetDynamicFuncArgType(Var *arg, ExprContext *econtext)
return tup->t_data->t_oid; return tup->t_data->t_oid;
} }
/*-----------------------------------------------------------------
*
* Initialize a 'FunctionCache' struct given the PG_PROC oid.
*
*-----------------------------------------------------------------
*/
static FunctionCachePtr static FunctionCachePtr
init_fcache(Oid foid, init_fcache(Oid foid,
bool use_syscache,
List *argList, List *argList,
ExprContext *econtext) ExprContext *econtext)
{ {
@ -79,16 +72,13 @@ init_fcache(Oid foid,
text *tmp; text *tmp;
bool isNull; bool isNull;
retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
MemSet(retval, 0, sizeof(FunctionCache));
/* ---------------- /* ----------------
* get the procedure tuple corresponding to the given functionOid * 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, procedureTuple = SearchSysCacheTuple(PROCOID,
ObjectIdGetDatum(foid), ObjectIdGetDatum(foid),
0, 0, 0); 0, 0, 0);
@ -114,8 +104,7 @@ init_fcache(Oid foid,
typeStruct = (Form_pg_type) GETSTRUCT(typeTuple); typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
/* ---------------- /* ----------------
* get the type length and by-value from the type tuple and * get the type length and by-value flag from the type tuple
* save the information in our one element cache.
* ---------------- * ----------------
*/ */
retval->typlen = typeStruct->typlen; retval->typlen = typeStruct->typlen;
@ -136,10 +125,9 @@ init_fcache(Oid foid,
retval->foid = foid; retval->foid = foid;
retval->language = procedureStruct->prolang; retval->language = procedureStruct->prolang;
retval->func_state = (char *) NULL; retval->func_state = (char *) NULL;
retval->setArg = NULL; retval->setArg = (Datum) 0;
retval->hasSetArg = false; retval->hasSetArg = false;
retval->oneResult = !procedureStruct->proretset; retval->oneResult = !procedureStruct->proretset;
retval->istrusted = procedureStruct->proistrusted;
/* /*
* If we are returning exactly one result then we have to copy tuples * 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_tupleDescriptor = (TupleDesc) NULL;
slot->ttc_buffer = InvalidBuffer; slot->ttc_buffer = InvalidBuffer;
slot->ttc_whichplan = -1; slot->ttc_whichplan = -1;
retval->funcSlot = (Pointer) slot;
relationTuple = (HeapTuple) relationTuple =
SearchSysCacheTuple(RELNAME, SearchSysCacheTuple(RELNAME,
PointerGetDatum(&typeStruct->typname), PointerGetDatum(&typeStruct->typname),
0, 0, 0); 0, 0, 0);
@ -177,10 +164,12 @@ init_fcache(Oid foid,
else else
td = CreateTemplateTupleDesc(1); td = CreateTemplateTupleDesc(1);
((TupleTableSlot *) retval->funcSlot)->ttc_tupleDescriptor = td; slot->ttc_tupleDescriptor = td;
retval->funcSlot = (Pointer) slot;
} }
else else
retval->funcSlot = (char *) NULL; retval->funcSlot = (Pointer) NULL;
nargs = procedureStruct->pronargs; nargs = procedureStruct->pronargs;
retval->nargs = nargs; retval->nargs = nargs;
@ -189,8 +178,6 @@ init_fcache(Oid foid,
{ {
Oid *argTypes; Oid *argTypes;
retval->nullVect = (bool *) palloc(retval->nargs * sizeof(bool));
if (retval->language == SQLlanguageId) if (retval->language == SQLlanguageId)
{ {
int i; int i;
@ -218,7 +205,6 @@ init_fcache(Oid foid,
else else
{ {
retval->argOidVect = (Oid *) NULL; retval->argOidVect = (Oid *) NULL;
retval->nullVect = (BoolPtr) NULL;
} }
if (procedureStruct->prolang == SQLlanguageId) if (procedureStruct->prolang == SQLlanguageId)
@ -257,7 +243,7 @@ init_fcache(Oid foid,
retval->nargs = retval->func.fn_nargs; retval->nargs = retval->func.fn_nargs;
} }
else else
retval->func.fn_addr = (func_ptr) NULL; retval->func.fn_addr = (PGFunction) NULL;
return retval; return retval;
} }
@ -269,7 +255,7 @@ setFcache(Node *node, Oid foid, List *argList, ExprContext *econtext)
Oper *onode; Oper *onode;
FunctionCachePtr fcache; FunctionCachePtr fcache;
fcache = init_fcache(foid, true, argList, econtext); fcache = init_fcache(foid, argList, econtext);
if (IsA(node, Oper)) if (IsA(node, Oper))
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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/bufmgr.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/catcache.h" #include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/relcache.h" #include "utils/relcache.h"
#include "utils/temprel.h" #include "utils/temprel.h"

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include "utils/dynamic_loader.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "dynloader.h" #include "dynloader.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/dynamic_loader.h"
#include "utils/syscache.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_list = (DynamicFileList *) NULL;
static DynamicFileList *file_tail = (DynamicFileList *) NULL; static DynamicFileList *file_tail = (DynamicFileList *) NULL;
#define NOT_EQUAL(A, B) (((A).st_ino != (B).inode) \ #define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device)
|| ((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 PGFunction
fmgr_dynamic(Oid procedureId, int *pronargs) fmgr_dynamic(Oid functionId)
{ {
HeapTuple procedureTuple; HeapTuple procedureTuple;
Form_pg_proc procedureStruct; Form_pg_proc procedureStruct;
char *proname, char *proname,
*linksymbol, *prosrcstring,
*probinstring; *probinstring;
char *prosrcstring = NULL; Datum prosrcattr,
Datum probinattr; probinattr;
Datum prosrcattr; PGFunction user_fn;
func_ptr user_fn;
Relation rel;
bool isnull; 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, procedureTuple = SearchSysCacheTuple(PROCOID,
ObjectIdGetDatum(procedureId), ObjectIdGetDatum(functionId),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(procedureTuple)) if (!HeapTupleIsValid(procedureTuple))
{ elog(ERROR, "fmgr_dynamic: function %u: cache lookup failed",
elog(ERROR, "fmgr: Cache lookup failed for procedure %u\n", functionId);
procedureId);
return (func_ptr) NULL;
}
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
proname = NameStr(procedureStruct->proname); proname = NameStr(procedureStruct->proname);
pronargs_save = *pronargs = procedureStruct->pronargs;
probinattr = heap_getattr(procedureTuple, prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
Anum_pg_proc_probin, Anum_pg_proc_prosrc, &isnull);
RelationGetDescr(rel), &isnull); if (isnull || !PointerIsValid(prosrcattr))
if (!PointerIsValid(probinattr) /* || isnull */ )
{ {
heap_close(rel, AccessShareLock); elog(ERROR, "fmgr: Could not extract prosrc for %u from pg_proc",
elog(ERROR, "fmgr: Could not extract probin for %u from %s", functionId);
procedureId, ProcedureRelationName);
return (func_ptr) NULL;
} }
probinstring = textout((struct varlena *) probinattr); prosrcstring = textout((text *) DatumGetPointer(prosrcattr));
prosrcattr = heap_getattr(procedureTuple, probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
Anum_pg_proc_prosrc, Anum_pg_proc_probin, &isnull);
RelationGetDescr(rel), &isnull); if (isnull || !PointerIsValid(probinattr))
{
if (isnull) elog(ERROR, "fmgr: Could not extract probin for %u from pg_proc",
{ /* Use the proname for the link symbol */ functionId);
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;
} }
probinstring = textout((text *) DatumGetPointer(probinattr));
heap_close(rel, AccessShareLock); user_fn = load_external_function(probinstring, prosrcstring);
user_fn = handle_load(probinstring, linksymbol);
pfree(prosrcstring);
pfree(probinstring); pfree(probinstring);
if (prosrcstring)
pfree(prosrcstring);
procedureId_save = procedureId;
user_fn_save = user_fn;
return user_fn; return user_fn;
} }
static func_ptr PGFunction
handle_load(char *filename, char *funcname) load_external_function(char *filename, char *funcname)
{ {
DynamicFileList *file_scanner = (DynamicFileList *) NULL; DynamicFileList *file_scanner;
func_ptr retval = (func_ptr) NULL; PGFunction retval;
char *load_error; char *load_error;
struct stat stat_buf; struct stat stat_buf;
/* /*
* Do this because loading files may screw up the dynamic function * Scan the list of loaded FILES to see if the file has been loaded.
* manager otherwise.
*/ */
procedureId_save = -1; for (file_scanner = file_list;
file_scanner != (DynamicFileList *) NULL &&
/* strcmp(filename, file_scanner->filename) != 0;
* Scan the list of loaded FILES to see if the function has been file_scanner = file_scanner->next)
* loaded. ;
*/ if (file_scanner == (DynamicFileList *) NULL)
if (filename != (char *) 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; for (file_scanner = file_list;
file_scanner != (DynamicFileList *) NULL file_scanner != (DynamicFileList *) NULL &&
&& file_scanner->filename != (char *) NULL !SAME_INODE(stat_buf, *file_scanner);
&& strcmp(filename, file_scanner->filename) != 0;
file_scanner = file_scanner->next) 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_scanner == (DynamicFileList *) NULL)
{ {
if (file_list == (DynamicFileList *) NULL) /*
{ * File not loaded yet.
file_list = (DynamicFileList *) */
malloc(sizeof(DynamicFileList)); file_scanner = (DynamicFileList *)
file_scanner = file_list; malloc(sizeof(DynamicFileList) + strlen(filename));
} if (file_scanner == NULL)
else elog(FATAL, "Out of memory in load_external_function");
{
file_tail->next = (DynamicFileList *)
malloc(sizeof(DynamicFileList));
file_scanner = file_tail->next;
}
MemSet((char *) file_scanner, 0, sizeof(DynamicFileList));
MemSet((char *) file_scanner, 0, sizeof(DynamicFileList));
strcpy(file_scanner->filename, filename); strcpy(file_scanner->filename, filename);
file_scanner->device = stat_buf.st_dev; file_scanner->device = stat_buf.st_dev;
file_scanner->inode = stat_buf.st_ino; file_scanner->inode = stat_buf.st_ino;
@ -210,42 +147,36 @@ handle_load(char *filename, char *funcname)
if (file_scanner->handle == (void *) NULL) if (file_scanner->handle == (void *) NULL)
{ {
load_error = (char *) pg_dlerror(); load_error = (char *) pg_dlerror();
if (file_scanner == file_list)
file_list = (DynamicFileList *) NULL;
else
file_tail->next = (DynamicFileList *) NULL;
free((char *) file_scanner); free((char *) file_scanner);
elog(ERROR, "Load of file %s failed: %s", filename, load_error); elog(ERROR, "Load of file %s failed: %s", filename, load_error);
} }
/* /* OK to link it into list */
* Just load the file - we are done with that so return. if (file_list == (DynamicFileList *) NULL)
*/ file_list = file_scanner;
else
file_tail->next = file_scanner;
file_tail = 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); elog(ERROR, "Can't find function %s in file %s", funcname, filename);
return retval; return retval;
} }
/* /*
* This function loads files by the following: * This function loads a shlib file without looking up any particular
* * function in it. If the same shlib has previously been loaded,
* If the file is already loaded: * unload and reload it.
* 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.
*/ */
void void
load_file(char *filename) load_file(char *filename)
@ -253,7 +184,6 @@ load_file(char *filename)
DynamicFileList *file_scanner, DynamicFileList *file_scanner,
*p; *p;
struct stat stat_buf; struct stat stat_buf;
int done = 0;
/* /*
* We need to do stat() in order to determine whether this is the same * 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) if (stat(filename, &stat_buf) == -1)
elog(ERROR, "LOAD: could not open file '%s': %m", filename); elog(ERROR, "LOAD: could not open file '%s': %m", filename);
if (file_list != (DynamicFileList *) NULL if (file_list != (DynamicFileList *) NULL)
&& !NOT_EQUAL(stat_buf, *file_list))
{ {
file_scanner = file_list; if (SAME_INODE(stat_buf, *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 (file_scanner->next == (DynamicFileList *) NULL) p = file_list;
done = 1; file_list = p->next;
else if (!NOT_EQUAL(stat_buf, *(file_scanner->next))) pg_dlclose(p->handle);
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);
free((char *) p); 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 * 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/proc.h"
#include "storage/sinval.h" #include "storage/sinval.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/fmgroids.h"
#include "utils/inval.h" #include "utils/inval.h"
#include "utils/portal.h" #include "utils/portal.h"
#include "utils/relcache.h" #include "utils/relcache.h"

View File

@ -8,7 +8,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.11 2000/05/15 16:20:45 momjian Exp $ # $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.12 2000/05/28 17:56:08 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -244,7 +244,7 @@ fi
# ---------- # ----------
# Create the call handler and the language # Create the call handler and the language
# ---------- # ----------
$PSQL "CREATE FUNCTION $handler () RETURNS OPAQUE AS '$PGLIB/${langname}__DLSUFFIX__' LANGUAGE 'C'" $PSQL "CREATE FUNCTION $handler () RETURNS OPAQUE AS '$PGLIB/${langname}__DLSUFFIX__' LANGUAGE 'newC'"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "$CMDNAME: language installation failed" echo "$CMDNAME: language installation failed"
exit 1 exit 1

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: valid.h,v 1.20 2000/01/26 05:57:51 momjian Exp $ * $Id: valid.h,v 1.21 2000/05/28 17:56:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -58,7 +58,7 @@ do \
break; \ break; \
} \ } \
\ \
if (__cur_keys->sk_func.fn_addr == (func_ptr) oideq) /* optimization */ \ if (__cur_keys->sk_func.fn_addr == (PGFunction) oideq) /* optimization */ \
__test = (__cur_keys->sk_argument == __atp); \ __test = (__cur_keys->sk_argument == __atp); \
else if (__cur_keys->sk_flags & SK_COMMUTE) \ else if (__cur_keys->sk_flags & SK_COMMUTE) \
__test = (long) FMGR_PTR2(&__cur_keys->sk_func, \ __test = (long) FMGR_PTR2(&__cur_keys->sk_func, \

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: c.h,v 1.69 2000/04/12 17:16:24 momjian Exp $ * $Id: c.h,v 1.70 2000/05/28 17:56:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -250,6 +250,28 @@ typedef struct
*/ */
typedef signed int Offset; typedef signed int Offset;
/*
* Common Postgres datatypes.
*/
typedef int16 int2;
typedef int32 int4;
typedef float float4;
typedef double float8;
#ifdef HAVE_LONG_INT_64
/* Plain "long int" fits, use it */
typedef long int int64;
#else
#ifdef HAVE_LONG_LONG_INT_64
/* We have working support for "long long int", use that */
typedef long long int int64;
#else
/* Won't actually work, but fall back to long int so that code compiles */
typedef long int int64;
#define INT64_IS_BUSTED
#endif
#endif
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Section 4: datum type + support macros * Section 4: datum type + support macros
* ---------------------------------------------------------------- * ----------------------------------------------------------------
@ -287,6 +309,24 @@ typedef Datum *DatumPtr;
#define SET_2_BYTES(value) (((Datum) (value)) & 0x0000ffff) #define SET_2_BYTES(value) (((Datum) (value)) & 0x0000ffff)
#define SET_4_BYTES(value) (((Datum) (value)) & 0xffffffff) #define SET_4_BYTES(value) (((Datum) (value)) & 0xffffffff)
/*
* DatumGetBool
* Returns boolean value of a datum.
*
* Note: any nonzero value will be considered TRUE.
*/
#define DatumGetBool(X) ((bool) (((Datum) (X)) != 0))
/*
* BoolGetDatum
* Returns datum representation for a boolean.
*
* Note: any nonzero value will be considered TRUE.
*/
#define BoolGetDatum(X) ((Datum) ((X) ? 1 : 0))
/* /*
* DatumGetChar * DatumGetChar
* Returns character value of a datum. * Returns character value of a datum.
@ -406,25 +446,112 @@ typedef Datum *DatumPtr;
#define PointerGetDatum(X) ((Datum) (X)) #define PointerGetDatum(X) ((Datum) (X))
/*
* DatumGetCString
* Returns C string (null-terminated string) value of a datum.
*
* Note: C string is not a full-fledged Postgres type at present,
* but type input functions use this conversion for their inputs.
*/
#define DatumGetCString(X) ((char *) DatumGetPointer(X))
/*
* CStringGetDatum
* Returns datum representation for a C string (null-terminated string).
*
* Note: C string is not a full-fledged Postgres type at present,
* but type output functions use this conversion for their outputs.
* Note: CString is pass-by-reference; caller must ensure the pointed-to
* value has adequate lifetime.
*/
#define CStringGetDatum(X) PointerGetDatum(X)
/* /*
* DatumGetName * DatumGetName
* Returns name value of a datum. * Returns name value of a datum.
*/ */
#define DatumGetName(X) ((Name) DatumGetPointer((Datum) (X))) #define DatumGetName(X) ((Name) DatumGetPointer(X))
/* /*
* NameGetDatum * NameGetDatum
* Returns datum representation for a name. * Returns datum representation for a name.
*
* Note: Name is pass-by-reference; caller must ensure the pointed-to
* value has adequate lifetime.
*/ */
#define NameGetDatum(X) PointerGetDatum((Pointer) (X)) #define NameGetDatum(X) PointerGetDatum(X)
/*
* DatumGetInt64
* Returns 64-bit integer value of a datum.
*
* Note: this macro hides the fact that int64 is currently a
* pass-by-reference type. Someday it may be pass-by-value,
* at least on some platforms.
*/
#define DatumGetInt64(X) (* ((int64 *) DatumGetPointer(X)))
/*
* Int64GetDatum
* Returns datum representation for a 64-bit integer.
*
* Note: this routine returns a reference to palloc'd space.
*/
extern Datum Int64GetDatum(int64 X);
/*
* DatumGetFloat4
* Returns 4-byte floating point value of a datum.
*
* Note: this macro hides the fact that float4 is currently a
* pass-by-reference type. Someday it may be pass-by-value.
*/
#define DatumGetFloat4(X) (* ((float4 *) DatumGetPointer(X)))
/*
* Float4GetDatum
* Returns datum representation for a 4-byte floating point number.
*
* Note: this routine returns a reference to palloc'd space.
*/
extern Datum Float4GetDatum(float4 X);
/*
* DatumGetFloat8
* Returns 8-byte floating point value of a datum.
*
* Note: this macro hides the fact that float8 is currently a
* pass-by-reference type. Someday it may be pass-by-value,
* at least on some platforms.
*/
#define DatumGetFloat8(X) (* ((float8 *) DatumGetPointer(X)))
/*
* Float8GetDatum
* Returns datum representation for an 8-byte floating point number.
*
* Note: this routine returns a reference to palloc'd space.
*/
extern Datum Float8GetDatum(float8 X);
/* /*
* DatumGetFloat32 * DatumGetFloat32
* Returns 32-bit floating point value of a datum. * Returns 32-bit floating point value of a datum.
* This is really a pointer, of course. * This is really a pointer, of course.
*
* XXX: this macro is now deprecated in favor of DatumGetFloat4.
* It will eventually go away.
*/ */
#define DatumGetFloat32(X) ((float32) DatumGetPointer(X)) #define DatumGetFloat32(X) ((float32) DatumGetPointer(X))
@ -433,14 +560,20 @@ typedef Datum *DatumPtr;
* Float32GetDatum * Float32GetDatum
* Returns datum representation for a 32-bit floating point number. * Returns datum representation for a 32-bit floating point number.
* This is really a pointer, of course. * This is really a pointer, of course.
*
* XXX: this macro is now deprecated in favor of Float4GetDatum.
* It will eventually go away.
*/ */
#define Float32GetDatum(X) PointerGetDatum((Pointer) (X)) #define Float32GetDatum(X) PointerGetDatum(X)
/* /*
* DatumGetFloat64 * DatumGetFloat64
* Returns 64-bit floating point value of a datum. * Returns 64-bit floating point value of a datum.
* This is really a pointer, of course. * This is really a pointer, of course.
*
* XXX: this macro is now deprecated in favor of DatumGetFloat8.
* It will eventually go away.
*/ */
#define DatumGetFloat64(X) ((float64) DatumGetPointer(X)) #define DatumGetFloat64(X) ((float64) DatumGetPointer(X))
@ -449,9 +582,12 @@ typedef Datum *DatumPtr;
* Float64GetDatum * Float64GetDatum
* Returns datum representation for a 64-bit floating point number. * Returns datum representation for a 64-bit floating point number.
* This is really a pointer, of course. * This is really a pointer, of course.
*
* XXX: this macro is now deprecated in favor of Float8GetDatum.
* It will eventually go away.
*/ */
#define Float64GetDatum(X) PointerGetDatum((Pointer) (X)) #define Float64GetDatum(X) PointerGetDatum(X)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Section 5: IsValid macros for system types * Section 5: IsValid macros for system types

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.21 2000/05/05 03:10:24 tgl Exp $ * $Id: catversion.h,v 1.22 2000/05/28 17:56:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200005041 #define CATALOG_VERSION_NO 200005281
#endif #endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_attribute.h,v 1.55 2000/04/12 17:16:28 momjian Exp $ * $Id: pg_attribute.h,v 1.56 2000/05/28 17:56:16 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
@ -294,16 +294,17 @@ DATA(insert OID = 0 ( 1262 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
{ 1255, {"proisinh"}, 16, 0, 1, 4, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1255, {"proisinh"}, 16, 0, 1, 4, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1255, {"proistrusted"}, 16, 0, 1, 5, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1255, {"proistrusted"}, 16, 0, 1, 5, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1255, {"proiscachable"}, 16, 0, 1, 6, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1255, {"proiscachable"}, 16, 0, 1, 6, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1255, {"pronargs"}, 21, 0, 2, 7, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ { 1255, {"proisstrict"}, 16, 0, 1, 7, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1255, {"proretset"}, 16, 0, 1, 8, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1255, {"pronargs"}, 21, 0, 2, 8, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \
{ 1255, {"prorettype"}, 26, 0, 4, 9, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1255, {"proretset"}, 16, 0, 1, 9, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \
{ 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 10, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' }, \ { 1255, {"prorettype"}, 26, 0, 4, 10, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \
{ 1255, {"probyte_pct"}, 23, 0, 4, 11, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 11, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' }, \
{ 1255, {"properbyte_cpu"}, 23, 0, 4, 12, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1255, {"probyte_pct"}, 23, 0, 4, 12, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \
{ 1255, {"propercall_cpu"}, 23, 0, 4, 13, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1255, {"properbyte_cpu"}, 23, 0, 4, 13, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \
{ 1255, {"prooutin_ratio"}, 23, 0, 4, 14, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \ { 1255, {"propercall_cpu"}, 23, 0, 4, 14, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \
{ 1255, {"prosrc"}, 25, 0, -1, 15, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' }, \ { 1255, {"prooutin_ratio"}, 23, 0, 4, 15, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0' }, \
{ 1255, {"probin"}, 17, 0, -1, 16, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' } { 1255, {"prosrc"}, 25, 0, -1, 16, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' }, \
{ 1255, {"probin"}, 17, 0, -1, 17, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' }
DATA(insert OID = 0 ( 1255 proname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1255 proname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert OID = 0 ( 1255 proowner 23 0 4 2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 proowner 23 0 4 2 0 -1 -1 t p f i f f));
@ -311,16 +312,17 @@ DATA(insert OID = 0 ( 1255 prolang 26 0 4 3 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1255 proisinh 16 0 1 4 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1255 proisinh 16 0 1 4 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1255 proistrusted 16 0 1 5 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1255 proistrusted 16 0 1 5 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1255 proiscachable 16 0 1 6 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1255 proiscachable 16 0 1 6 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1255 pronargs 21 0 2 7 0 -1 -1 t p f s f f)); DATA(insert OID = 0 ( 1255 proisstrict 16 0 1 7 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1255 proretset 16 0 1 8 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1255 pronargs 21 0 2 8 0 -1 -1 t p f s f f));
DATA(insert OID = 0 ( 1255 prorettype 26 0 4 9 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 proretset 16 0 1 9 0 -1 -1 t p f c f f));
DATA(insert OID = 0 ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 10 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1255 prorettype 26 0 4 10 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1255 probyte_pct 23 0 4 11 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 11 0 -1 -1 f p f i f f));
DATA(insert OID = 0 ( 1255 properbyte_cpu 23 0 4 12 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 probyte_pct 23 0 4 12 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1255 propercall_cpu 23 0 4 13 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 properbyte_cpu 23 0 4 13 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1255 prooutin_ratio 23 0 4 14 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 propercall_cpu 23 0 4 14 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1255 prosrc 25 0 -1 15 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1255 prooutin_ratio 23 0 4 15 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1255 probin 17 0 -1 16 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1255 prosrc 25 0 -1 16 0 -1 -1 f p f i f f));
DATA(insert OID = 0 ( 1255 probin 17 0 -1 17 0 -1 -1 f p f i f f));
DATA(insert OID = 0 ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert OID = 0 ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert OID = 0 ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i f f));

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_class.h,v 1.33 2000/01/26 05:57:57 momjian Exp $ * $Id: pg_class.h,v 1.34 2000/05/28 17:56:16 tgl Exp $
* *
* NOTES * NOTES
* ``pg_relation'' is being replaced by ``pg_class''. currently * ``pg_relation'' is being replaced by ``pg_class''. currently
@ -133,7 +133,7 @@ DATA(insert OID = 1247 ( pg_type 71 PGUID 0 0 0 0 f f r 16 0 0 0 0 0 f f _nu
DESCR(""); DESCR("");
DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 0 0 0 f f r 15 0 0 0 0 0 f f _null_ )); DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 0 0 0 f f r 15 0 0 0 0 0 f f _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 0 0 0 f f r 16 0 0 0 0 0 f f _null_ )); DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 0 0 0 f f r 17 0 0 0 0 0 f f _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1259 ( pg_class 83 PGUID 0 0 0 0 f f r 19 0 0 0 0 0 f f _null_ )); DATA(insert OID = 1259 ( pg_class 83 PGUID 0 0 0 0 f f r 19 0 0 0 0 0 f f _null_ ));
DESCR(""); DESCR("");

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_language.h,v 1.10 2000/01/26 05:57:57 momjian Exp $ * $Id: pg_language.h,v 1.11 2000/05/28 17:56:16 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
@ -63,14 +63,20 @@ typedef FormData_pg_language *Form_pg_language;
* ---------------- * ----------------
*/ */
DATA(insert OID = 11 ( internal f 0 0 "n/a" )); DATA(insert OID = 11 ( internal f f 0 "n/a" ));
DESCR(""); DESCR("old-style built-in functions");
#define INTERNALlanguageId 11 #define INTERNALlanguageId 11
DATA(insert OID = 13 ( "C" f 0 0 "/bin/cc" )); DATA(insert OID = 12 ( newinternal f f 0 "n/a" ));
DESCR(""); DESCR("new-style built-in functions");
#define NEWINTERNALlanguageId 12
DATA(insert OID = 13 ( "C" f f 0 "/bin/cc" ));
DESCR("Dynamically-loaded old-style C functions");
#define ClanguageId 13 #define ClanguageId 13
DATA(insert OID = 14 ( "sql" f 0 0 "postgres")); DATA(insert OID = 10 ( "newC" f f 0 "/bin/cc" ));
DESCR(""); DESCR("Dynamically-loaded new-style C functions");
#define NEWClanguageId 10
DATA(insert OID = 14 ( "sql" f f 0 "postgres"));
DESCR("SQL-language functions");
#define SQLlanguageId 14 #define SQLlanguageId 14

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: functions.h,v 1.11 2000/01/26 05:58:05 momjian Exp $ * $Id: functions.h,v 1.12 2000/05/28 17:56:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -18,9 +18,11 @@
#include "utils/syscache.h" #include "utils/syscache.h"
extern Datum ProjectAttribute(TupleDesc TD, TargetEntry *tlist, extern Datum ProjectAttribute(TupleDesc TD, TargetEntry *tlist,
HeapTuple tup, bool *isnullP); HeapTuple tup, bool *isnullP);
extern Datum postquel_function(Func *funcNode, char **args, extern Datum postquel_function(FunctionCallInfo fcinfo,
bool *isNull, bool *isDone); FunctionCachePtr fcache,
List *func_tlist,
bool *isDone);
#endif /* FUNCTIONS_H */ #endif /* FUNCTIONS_H */

301
src/include/fmgr.h Normal file
View File

@ -0,0 +1,301 @@
/*-------------------------------------------------------------------------
*
* fmgr.h
* Definitions for the Postgres function manager and function-call
* interface.
*
* This file must be included by all Postgres modules that either define
* or call fmgr-callable functions.
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: fmgr.h,v 1.1 2000/05/28 17:56:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FMGR_H
#define FMGR_H
/*
* All functions that can be called directly by fmgr must have this signature.
* (Other functions can be called by using a handler that does have this
* signature.)
*/
typedef struct FunctionCallInfoData *FunctionCallInfo;
typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);
/*
* This struct holds the system-catalog information that must be looked up
* before a function can be called through fmgr. If the same function is
* to be called multiple times, the lookup need be done only once and the
* info struct saved for re-use.
*/
typedef struct
{
PGFunction fn_addr; /* pointer to function or handler to be called */
Oid fn_oid; /* OID of function (NOT of handler, if any) */
short fn_nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable arg count */
bool fn_strict; /* function is "strict" (NULL in => NULL out) */
void *fn_extra; /* extra space for use by handler */
} FmgrInfo;
/*
* This struct is the data actually passed to an fmgr-called function.
*/
typedef struct FunctionCallInfoData
{
FmgrInfo *flinfo; /* ptr to lookup info used for this call */
struct Node *context; /* pass info about context of call */
struct Node *resultinfo; /* pass or return extra info about result */
bool isnull; /* function must set true if result is NULL */
short nargs; /* # arguments actually passed */
Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */
bool argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */
} FunctionCallInfoData;
/*
* This routine fills a FmgrInfo struct, given the OID
* of the function to be called.
*/
extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
/*
* This macro invokes a function given a filled-in FunctionCallInfoData
* struct. The macro result is the returned Datum --- but note that
* caller must still check fcinfo->isnull! Also, if function is strict,
* it is caller's responsibility to verify that no null arguments are present
* before calling.
*/
#define FunctionCallInvoke(fcinfo) ((* (fcinfo)->flinfo->fn_addr) (fcinfo))
/*-------------------------------------------------------------------------
* Support macros to ease writing fmgr-compatible functions
*
* A C-coded fmgr-compatible function should be declared as
*
* Datum
* function_name(PG_FUNCTION_ARGS)
* {
* ...
* }
*
* It should access its arguments using appropriate PG_GETARG_xxx macros
* and should return its result using PG_RETURN_xxx.
*
*-------------------------------------------------------------------------
*/
/* Standard parameter list for fmgr-compatible functions */
#define PG_FUNCTION_ARGS FunctionCallInfo fcinfo
/* If function is not marked "proisstrict" in pg_proc, it must check for
* null arguments using this macro. Do not try to GETARG a null argument!
*/
#define PG_ARGISNULL(n) (fcinfo->argnull[n])
/* Macros for fetching arguments of standard types */
#define PG_GETARG_INT32(n) DatumGetInt32(fcinfo->arg[n])
#define PG_GETARG_INT16(n) DatumGetInt16(fcinfo->arg[n])
#define PG_GETARG_CHAR(n) DatumGetChar(fcinfo->arg[n])
#define PG_GETARG_BOOL(n) DatumGetBool(fcinfo->arg[n])
#define PG_GETARG_OID(n) DatumGetObjectId(fcinfo->arg[n])
#define PG_GETARG_POINTER(n) DatumGetPointer(fcinfo->arg[n])
/* these macros hide the pass-by-reference-ness of the datatype: */
#define PG_GETARG_FLOAT4(n) DatumGetFloat4(fcinfo->arg[n])
#define PG_GETARG_FLOAT8(n) DatumGetFloat8(fcinfo->arg[n])
#define PG_GETARG_INT64(n) DatumGetInt64(fcinfo->arg[n])
/* use this if you want the raw, possibly-toasted input datum: */
#define PG_GETARG_RAW_VARLENA_P(n) ((struct varlena *) PG_GETARG_POINTER(n))
/* use this if you want the input datum de-toasted: */
#define PG_GETARG_VARLENA_P(n) \
(VARATT_IS_EXTENDED(PG_GETARG_RAW_VARLENA_P(n)) ? \
(struct varlena *) heap_tuple_untoast_attr((varattrib *) PG_GETARG_RAW_VARLENA_P(n)) : \
PG_GETARG_RAW_VARLENA_P(n))
/* GETARG macros for varlena types will typically look like this: */
#define PG_GETARG_TEXT_P(n) ((text *) PG_GETARG_VARLENA_P(n))
/* To return a NULL do this: */
#define PG_RETURN_NULL() \
do { fcinfo->isnull = true; return (Datum) 0; } while (0)
/* Macros for returning results of standard types */
#define PG_RETURN_INT32(x) return Int32GetDatum(x)
#define PG_RETURN_INT16(x) return Int16GetDatum(x)
#define PG_RETURN_CHAR(x) return CharGetDatum(x)
#define PG_RETURN_BOOL(x) return BoolGetDatum(x)
#define PG_RETURN_OID(x) return ObjectIdGetDatum(x)
#define PG_RETURN_POINTER(x) return PointerGetDatum(x)
/* these macros hide the pass-by-reference-ness of the datatype: */
#define PG_RETURN_FLOAT4(x) return Float4GetDatum(x)
#define PG_RETURN_FLOAT8(x) return Float8GetDatum(x)
#define PG_RETURN_INT64(x) return Int64GetDatum(x)
/* RETURN macros for other pass-by-ref types will typically look like this: */
#define PG_RETURN_TEXT_P(x) PG_RETURN_POINTER(x)
/*-------------------------------------------------------------------------
* Support routines and macros for callers of fmgr-compatible functions
*-------------------------------------------------------------------------
*/
/* These are for invocation of a specifically named function with a
* directly-computed parameter list. Note that neither arguments nor result
* are allowed to be NULL.
*/
extern Datum DirectFunctionCall1(PGFunction func, Datum arg1);
extern Datum DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2);
extern Datum DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2,
Datum arg3);
extern Datum DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2,
Datum arg3, Datum arg4);
extern Datum DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5);
extern Datum DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6);
extern Datum DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7);
extern Datum DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8);
extern Datum DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8,
Datum arg9);
/* These are for invocation of a previously-looked-up function with a
* directly-computed parameter list. Note that neither arguments nor result
* are allowed to be NULL.
*/
extern Datum FunctionCall1(FmgrInfo *flinfo, Datum arg1);
extern Datum FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2);
extern Datum FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2,
Datum arg3);
extern Datum FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2,
Datum arg3, Datum arg4);
extern Datum FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5);
extern Datum FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6);
extern Datum FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7);
extern Datum FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8);
extern Datum FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8,
Datum arg9);
/* These are for invocation of a function identified by OID with a
* directly-computed parameter list. Note that neither arguments nor result
* are allowed to be NULL. These are essentially FunctionLookup() followed
* by FunctionCallN(). If the same function is to be invoked repeatedly,
* do the FunctionLookup() once and then use FunctionCallN().
*/
extern Datum OidFunctionCall1(Oid functionId, Datum arg1);
extern Datum OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2);
extern Datum OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
Datum arg3);
extern Datum OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
Datum arg3, Datum arg4);
extern Datum OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5);
extern Datum OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6);
extern Datum OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7);
extern Datum OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8);
extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8,
Datum arg9);
/*
* Routines in fmgr.c
*/
extern Oid fmgr_internal_language(const char *proname);
/*
* Routines in dfmgr.c
*/
extern PGFunction fmgr_dynamic(Oid functionId);
extern PGFunction load_external_function(char *filename, char *funcname);
extern void load_file(char *filename);
/*-------------------------------------------------------------------------
*
* !!! OLD INTERFACE !!!
*
* All the definitions below here are associated with the old fmgr API.
* They will go away as soon as we have converted all call points to use
* the new API. Note that old-style callee functions do not depend on
* these definitions, so we don't need to have converted all of them before
* dropping the old API ... just all the old-style call points.
*
*-------------------------------------------------------------------------
*/
/* ptr to func returning (char *) */
#if defined(__mc68000__) && defined(__ELF__)
/* The m68k SVR4 ABI defines that pointers are returned in %a0 instead of
* %d0. So if a function pointer is declared to return a pointer, the
* compiler may look only into %a0, but if the called function was declared
* to return return an integer type, it puts its value only into %d0. So the
* caller doesn't pink up the correct return value. The solution is to
* declare the function pointer to return int, so the compiler picks up the
* return value from %d0. (Functions returning pointers put their value
* *additionally* into %d0 for compability.) The price is that there are
* some warnings about int->pointer conversions...
*/
typedef int32 ((*func_ptr) ());
#else
typedef char *((*func_ptr) ());
#endif
typedef struct {
char *data[FUNC_MAX_ARGS];
} FmgrValues;
/*
* defined in fmgr.c
*/
extern char *fmgr(Oid procedureId, ... );
extern char *fmgr_faddr_link(char *arg0, ...);
/*
* Macros for calling through the result of fmgr_info.
*/
/* 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) fmgr_faddr_link)
#define FMGR_PTR2(FINFO, ARG1, ARG2) ((*(fmgr_faddr(FINFO))) (ARG1, ARG2))
/*
* Flags for the builtin oprrest selectivity routines.
* XXX These do not belong here ... put 'em in some planner/optimizer header.
*/
#define SEL_CONSTANT 1 /* operator's non-var arg is a constant */
#define SEL_RIGHT 2 /* operator's non-var arg is on the right */
#endif /* FMGR_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1995, Regents of the University of California * Portions Copyright (c) 1995, Regents of the University of California
* *
* $Id: postgres.h,v 1.38 2000/04/12 17:16:24 momjian Exp $ * $Id: postgres.h,v 1.39 2000/05/28 17:56:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -47,11 +47,6 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
typedef int16 int2;
typedef int32 int4;
typedef float float4;
typedef double float8;
typedef int4 aclitem; typedef int4 aclitem;
#define InvalidOid 0 #define InvalidOid 0
@ -61,26 +56,6 @@ typedef int4 aclitem;
typedef Oid regproc; typedef Oid regproc;
typedef Oid RegProcedure; typedef Oid RegProcedure;
/* ptr to func returning (char *) */
#if defined(__mc68000__) && defined(__ELF__)
/* The m68k SVR4 ABI defines that pointers are returned in %a0 instead of
* %d0. So if a function pointer is declared to return a pointer, the
* compiler may look only into %a0, but if the called function was declared
* to return return an integer type, it puts its value only into %d0. So the
* caller doesn't pink up the correct return value. The solution is to
* declare the function pointer to return int, so the compiler picks up the
* return value from %d0. (Functions returning pointers put their value
* *additionally* into %d0 for compability.) The price is that there are
* some warnings about int->pointer conversions...
*/
typedef int32 ((*func_ptr) ());
#else
typedef char *((*func_ptr) ());
#endif
#define RegProcedureIsValid(p) OidIsValid(p) #define RegProcedureIsValid(p) OidIsValid(p)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: dynamic_loader.h,v 1.14 2000/01/26 05:58:37 momjian Exp $ * $Id: dynamic_loader.h,v 1.15 2000/05/28 17:56:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,26 +19,12 @@
/* we need this include because port files use them */ /* we need this include because port files use them */
#include "postgres.h" #include "postgres.h"
#ifdef MIN /* and this one for typedef PGFunction */
#undef MIN #include "fmgr.h"
#undef MAX
#endif /* MIN */
/*
* List of dynamically loaded files.
*/
typedef struct df_files
{
char filename[MAXPGPATH]; /* Full pathname of file */
dev_t device; /* Device file is on */
ino_t inode; /* Inode number of file */
void *handle; /* a handle for pg_dl* functions */
struct df_files *next;
} DynamicFileList;
extern void *pg_dlopen(char *filename); extern void *pg_dlopen(char *filename);
extern func_ptr pg_dlsym(void *handle, char *funcname); extern PGFunction pg_dlsym(void *handle, char *funcname);
extern void pg_dlclose(void *handle); extern void pg_dlclose(void *handle);
extern char *pg_dlerror(void); extern char *pg_dlerror(void);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: fcache.h,v 1.10 2000/01/26 05:58:38 momjian Exp $ * $Id: fcache.h,v 1.11 2000/05/28 17:56:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,22 +19,11 @@
typedef struct typedef struct
{ {
int typlen; /* length of the return type */ FmgrInfo func; /* info for fmgr call mechanism */
int typbyval; /* true if return type is pass by value */
FmgrInfo func; /* address of function to call (for c
* funcs) */
Oid foid; /* oid of the function in pg_proc */ Oid foid; /* oid of the function in pg_proc */
Oid language; /* oid of the language in pg_language */ Oid language; /* oid of the language in pg_language */
int nargs; /* number of arguments */ int typlen; /* length of the return type */
bool typbyval; /* true if return type is pass by value */
/* Might want to make these two arrays of size MAXFUNCARGS */
Oid *argOidVect; /* oids of all the arguments */
bool *nullVect; /* keep track of null arguments */
char *src; /* source code of the function */
char *bin; /* binary object code ?? */
char *func_state; /* fuction_state struct for execution */
bool oneResult; /* true we only want 1 result from the bool oneResult; /* true we only want 1 result from the
* function */ * function */
@ -42,17 +31,23 @@ typedef struct
* expr whose argument is func returning a * expr whose argument is func returning a
* set ugh! */ * set ugh! */
int nargs; /* actual number of arguments */
Oid *argOidVect; /* oids of all the argument types */
char *src; /* source code of the function */
char *bin; /* binary object code ?? */
char *func_state; /* function_state struct for execution */
Pointer funcSlot; /* if one result we need to copy it before Pointer funcSlot; /* if one result we need to copy it before
* we end execution of the function and * we end execution of the function and
* free stuff */ * free stuff */
char *setArg; /* current argument for nested dot Datum setArg; /* current argument for nested dot
* execution Nested dot expressions mean * execution Nested dot expressions mean
* we have funcs whose argument is a set * we have funcs whose argument is a set
* of tuples */ * of tuples */
} FunctionCache;
bool istrusted; /* trusted fn? */ typedef FunctionCache *FunctionCachePtr;
} FunctionCache,
*FunctionCachePtr;
#endif /* FCACHE_H */ #endif /* FCACHE_H */

View File

@ -1,30 +1,39 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* fmgrtab.h * fmgrtab.h
* * The function manager's table of internal functions.
*
* *
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: fmgrtab.h,v 1.12 2000/01/26 05:58:38 momjian Exp $ * $Id: fmgrtab.h,v 1.13 2000/05/28 17:56:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef FMGRTAB_H #ifndef FMGRTAB_H
#define FMGRTAB_H #define FMGRTAB_H
#include "fmgr.h"
/*
* This table stores info about all the built-in functions (ie, functions
* that are compiled into the Postgres executable). The table entries are
* required to appear in Oid order, so that binary search can be used.
*/
typedef struct typedef struct
{ {
Oid proid; Oid foid; /* OID of the function */
int nargs; const char *funcName; /* C name of the function */
func_ptr func; short nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable count */
char *funcName; bool strict; /* T if function is "strict" */
} FmgrCall; bool oldstyle; /* T if function uses old fmgr interface */
PGFunction func; /* pointer to compiled function */
} FmgrBuiltin;
extern FmgrCall *fmgr_isbuiltin(Oid id); extern const FmgrBuiltin fmgr_builtins[];
extern func_ptr fmgr_lookupByName(char *name);
extern void load_file(char *filename); extern const int fmgr_nbuiltins; /* number of entries in table */
#endif /* FMGRTAB_H */ #endif /* FMGRTAB_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: int8.h,v 1.20 2000/04/12 17:16:55 momjian Exp $ * $Id: int8.h,v 1.21 2000/05/28 17:56:20 tgl Exp $
* *
* NOTES * NOTES
* These data types are supported on all 64-bit architectures, and may * These data types are supported on all 64-bit architectures, and may
@ -24,28 +24,6 @@
#ifndef INT8_H #ifndef INT8_H
#define INT8_H #define INT8_H
#ifdef HAVE_LONG_INT_64
/* Plain "long int" fits, use it */
typedef long int int64;
#else
#ifdef HAVE_LONG_LONG_INT_64
/* We have working support for "long long int", use that */
typedef long long int int64;
#else
/* Won't actually work, but fall back to long int so that int8.c compiles */
typedef long int int64;
#define INT64_IS_BUSTED
#endif
#endif
/* this should be set in config.h: */
#ifndef INT64_FORMAT
#define INT64_FORMAT "%ld"
#endif
extern int64 *int8in(char *str); extern int64 *int8in(char *str);
extern char *int8out(int64 *val); extern char *int8out(int64 *val);

View File

@ -6,7 +6,7 @@
# Copyright (c) 1994, Regents of the University of California # Copyright (c) 1994, Regents of the University of California
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.57 2000/05/27 04:13:05 momjian Exp $ # $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.58 2000/05/28 17:56:25 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -70,15 +70,6 @@ big5.c: $(SRCDIR)/backend/utils/mb/big5.c
endif endif
# The following rules cause dependencies in the backend directory to
# get made if they don't exist, but don't cause them to get remade if they
# are out of date.
fe-lobj.o: $(SRCDIR)/backend/fmgr.h
$(SRCDIR)/backend/fmgr.h:
$(MAKE) -C $(SRCDIR)/backend fmgr.h
.PHONY: install install-headers .PHONY: install install-headers
install: install-headers install-lib $(install-shlib-dep) install: install-headers install-lib $(install-shlib-dep)

View File

@ -32,6 +32,9 @@
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS. * ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.7 2000/05/28 17:56:26 tgl Exp $
*
**********************************************************************/ **********************************************************************/
@ -130,17 +133,15 @@ static Tcl_HashTable *plperl_query_hash = NULL;
static void plperl_init_all(void); static void plperl_init_all(void);
static void plperl_init_safe_interp(void); static void plperl_init_safe_interp(void);
Datum plperl_call_handler(FmgrInfo *proinfo, Datum plperl_call_handler(PG_FUNCTION_ARGS);
FmgrValues *proargs, bool *isNull);
static Datum plperl_func_handler(FmgrInfo *proinfo, static Datum plperl_func_handler(PG_FUNCTION_ARGS);
FmgrValues *proargs, bool *isNull);
static SV *plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc); static SV *plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc);
static void plperl_init_shared_libs(void); static void plperl_init_shared_libs(void);
#ifdef REALLYHAVEITONTHEBALL #ifdef REALLYHAVEITONTHEBALL
static HeapTuple plperl_trigger_handler(FmgrInfo *proinfo); static HeapTuple plperl_trigger_handler(PG_FUNCTION_ARGS);
static int plperl_elog(ClientData cdata, Tcl_Interp *interp, static int plperl_elog(ClientData cdata, Tcl_Interp *interp,
int argc, char *argv[]); int argc, char *argv[]);
@ -258,9 +259,7 @@ plperl_init_safe_interp(void)
/* keep non-static */ /* keep non-static */
Datum Datum
plperl_call_handler(FmgrInfo *proinfo, plperl_call_handler(PG_FUNCTION_ARGS)
FmgrValues *proargs,
bool *isNull)
{ {
Datum retval; Datum retval;
@ -285,13 +284,13 @@ plperl_call_handler(FmgrInfo *proinfo,
* call appropriate subhandler * call appropriate subhandler
************************************************************/ ************************************************************/
if (CurrentTriggerData == NULL) if (CurrentTriggerData == NULL)
retval = plperl_func_handler(proinfo, proargs, isNull); retval = plperl_func_handler(fcinfo);
else else
{ {
elog(ERROR, "plperl: can't use perl in triggers yet."); elog(ERROR, "plperl: can't use perl in triggers yet.");
/* /*
* retval = (Datum) plperl_trigger_handler(proinfo); * retval = (Datum) plperl_trigger_handler(fcinfo);
*/ */
/* make the compiler happy */ /* make the compiler happy */
retval = (Datum) 0; retval = (Datum) 0;
@ -390,7 +389,7 @@ plperl_init_shared_libs(void)
**********************************************************************/ **********************************************************************/
static static
SV * SV *
plperl_call_perl_func(plperl_proc_desc * desc, FmgrValues *pargs) plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo)
{ {
dSP; dSP;
@ -407,25 +406,34 @@ plperl_call_perl_func(plperl_proc_desc * desc, FmgrValues *pargs)
{ {
if (desc->arg_is_rel[i]) if (desc->arg_is_rel[i])
{ {
TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
SV *hashref;
Assert(slot != NULL && ! fcinfo->argnull[i]);
/* /*
* plperl_build_tuple_argument better return a mortal SV. * plperl_build_tuple_argument better return a mortal SV.
*/ */
SV *hashref = plperl_build_tuple_argument( hashref = plperl_build_tuple_argument(slot->val,
((TupleTableSlot *) (pargs->data[i]))->val, slot->ttc_tupleDescriptor);
((TupleTableSlot *) (pargs->data[i]))->ttc_tupleDescriptor);
XPUSHs(hashref); XPUSHs(hashref);
} }
else else
{ {
char *tmp = (*fmgr_faddr(&(desc->arg_out_func[i]))) if (fcinfo->argnull[i])
(pargs->data[i], {
desc->arg_out_elem[i], XPUSHs(&PL_sv_undef);
desc->arg_out_len[i]); }
else
{
char *tmp;
XPUSHs(sv_2mortal(newSVpv(tmp, 0))); tmp = (*fmgr_faddr(&(desc->arg_out_func[i])))
pfree(tmp); (fcinfo->arg[i],
desc->arg_out_elem[i],
desc->arg_out_len[i]);
XPUSHs(sv_2mortal(newSVpv(tmp, 0)));
pfree(tmp);
}
} }
} }
PUTBACK; PUTBACK;
@ -466,14 +474,11 @@ plperl_call_perl_func(plperl_proc_desc * desc, FmgrValues *pargs)
* plperl_func_handler() - Handler for regular function calls * plperl_func_handler() - Handler for regular function calls
**********************************************************************/ **********************************************************************/
static Datum static Datum
plperl_func_handler(FmgrInfo *proinfo, plperl_func_handler(PG_FUNCTION_ARGS)
FmgrValues *proargs,
bool *isNull)
{ {
int i; int i;
char internal_proname[512]; char internal_proname[512];
int proname_len; int proname_len;
char *stroid;
plperl_proc_desc *prodesc; plperl_proc_desc *prodesc;
SV *perlret; SV *perlret;
Datum retval; Datum retval;
@ -482,10 +487,7 @@ plperl_func_handler(FmgrInfo *proinfo,
/************************************************************ /************************************************************
* Build our internal proc name from the functions Oid * Build our internal proc name from the functions Oid
************************************************************/ ************************************************************/
stroid = oidout(proinfo->fn_oid); sprintf(internal_proname, "__PLPerl_proc_%u", fcinfo->flinfo->fn_oid);
strcpy(internal_proname, "__PLperl_proc_");
strcat(internal_proname, stroid);
pfree(stroid);
proname_len = strlen(internal_proname); proname_len = strlen(internal_proname);
/************************************************************ /************************************************************
@ -518,14 +520,14 @@ plperl_func_handler(FmgrInfo *proinfo,
* Lookup the pg_proc tuple by Oid * Lookup the pg_proc tuple by Oid
************************************************************/ ************************************************************/
procTup = SearchSysCacheTuple(PROCOID, procTup = SearchSysCacheTuple(PROCOID,
ObjectIdGetDatum(proinfo->fn_oid), ObjectIdGetDatum(fcinfo->flinfo->fn_oid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(procTup)) if (!HeapTupleIsValid(procTup))
{ {
free(prodesc->proname); free(prodesc->proname);
free(prodesc); free(prodesc);
elog(ERROR, "plperl: cache lookup for proc %u failed", elog(ERROR, "plperl: cache lookup for proc %u failed",
proinfo->fn_oid); fcinfo->flinfo->fn_oid);
} }
procStruct = (Form_pg_proc) GETSTRUCT(procTup); procStruct = (Form_pg_proc) GETSTRUCT(procTup);
@ -560,8 +562,8 @@ plperl_func_handler(FmgrInfo *proinfo,
* Get the required information for output conversion * Get the required information for output conversion
* of all procedure arguments * of all procedure arguments
************************************************************/ ************************************************************/
prodesc->nargs = proinfo->fn_nargs; prodesc->nargs = procStruct->pronargs;
for (i = 0; i < proinfo->fn_nargs; i++) for (i = 0; i < prodesc->nargs; i++)
{ {
typeTup = SearchSysCacheTuple(TYPEOID, typeTup = SearchSysCacheTuple(TYPEOID,
ObjectIdGetDatum(procStruct->proargtypes[i]), ObjectIdGetDatum(procStruct->proargtypes[i]),
@ -639,7 +641,7 @@ plperl_func_handler(FmgrInfo *proinfo,
/************************************************************ /************************************************************
* Call the Perl function * Call the Perl function
************************************************************/ ************************************************************/
perlret = plperl_call_perl_func(prodesc, proargs); perlret = plperl_call_perl_func(prodesc, fcinfo);
/************************************************************ /************************************************************
* Disconnect from SPI manager and then create the return * Disconnect from SPI manager and then create the return
@ -650,10 +652,19 @@ plperl_func_handler(FmgrInfo *proinfo,
if (SPI_finish() != SPI_OK_FINISH) if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "plperl: SPI_finish() failed"); elog(ERROR, "plperl: SPI_finish() failed");
retval = (Datum) (*fmgr_faddr(&prodesc->result_in_func)) /* XXX is this the approved way to check for an undef result? */
(SvPV(perlret, na), if (perlret == &PL_sv_undef)
prodesc->result_in_elem, {
prodesc->result_in_len); retval = (Datum) 0;
fcinfo->isnull = true;
}
else
{
retval = FunctionCall3(&prodesc->result_in_func,
PointerGetDatum(SvPV(perlret, na)),
ObjectIdGetDatum(prodesc->result_in_elem),
Int32GetDatum(prodesc->result_in_len));
}
SvREFCNT_dec(perlret); SvREFCNT_dec(perlret);
@ -674,7 +685,7 @@ plperl_func_handler(FmgrInfo *proinfo,
* plperl_trigger_handler() - Handler for trigger calls * plperl_trigger_handler() - Handler for trigger calls
**********************************************************************/ **********************************************************************/
static HeapTuple static HeapTuple
plperl_trigger_handler(FmgrInfo *proinfo) plperl_trigger_handler(PG_FUNCTION_ARGS)
{ {
TriggerData *trigdata; TriggerData *trigdata;
char internal_proname[512]; char internal_proname[512];
@ -708,10 +719,7 @@ plperl_trigger_handler(FmgrInfo *proinfo)
/************************************************************ /************************************************************
* Build our internal proc name from the functions Oid * Build our internal proc name from the functions Oid
************************************************************/ ************************************************************/
stroid = oidout(proinfo->fn_oid); sprintf(internal_proname, "__PLPerl_proc_%u", fcinfo->flinfo->fn_oid);
strcpy(internal_proname, "__PLTcl_proc_");
strcat(internal_proname, stroid);
pfree(stroid);
/************************************************************ /************************************************************
* Lookup the internal proc name in the hashtable * Lookup the internal proc name in the hashtable
@ -741,14 +749,14 @@ plperl_trigger_handler(FmgrInfo *proinfo)
* Lookup the pg_proc tuple by Oid * Lookup the pg_proc tuple by Oid
************************************************************/ ************************************************************/
procTup = SearchSysCacheTuple(PROCOID, procTup = SearchSysCacheTuple(PROCOID,
ObjectIdGetDatum(proinfo->fn_oid), ObjectIdGetDatum(fcinfo->flinfo->fn_oid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(procTup)) if (!HeapTupleIsValid(procTup))
{ {
free(prodesc->proname); free(prodesc->proname);
free(prodesc); free(prodesc);
elog(ERROR, "plperl: cache lookup for proc %u failed", elog(ERROR, "plperl: cache lookup for proc %u failed",
proinfo->fn_oid); fcinfo->flinfo->fn_oid);
} }
procStruct = (Form_pg_proc) GETSTRUCT(procTup); procStruct = (Form_pg_proc) GETSTRUCT(procTup);

View File

@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.21 2000/04/28 00:12:44 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.22 2000/05/28 17:56:28 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -141,8 +141,7 @@ static void exec_set_found(PLpgSQL_execstate * estate, bool state);
* ---------- * ----------
*/ */
Datum Datum
plpgsql_exec_function(PLpgSQL_function * func, plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
FmgrValues *args, bool *isNull)
{ {
PLpgSQL_execstate estate; PLpgSQL_execstate estate;
int i; int i;
@ -302,21 +301,22 @@ plpgsql_exec_function(PLpgSQL_function * func,
{ {
PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n]; PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
var->value = (Datum) (args->data[i]); var->value = fcinfo->arg[i];
var->isnull = *isNull; var->isnull = fcinfo->argnull[i];
var->shouldfree = false; var->shouldfree = false;
} }
break; break;
case PLPGSQL_DTYPE_ROW: case PLPGSQL_DTYPE_ROW:
{ {
PLpgSQL_row *row = (PLpgSQL_row *) estate.datums[n];
TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
HeapTuple tup; HeapTuple tup;
TupleDesc tupdesc; TupleDesc tupdesc;
PLpgSQL_row *row = (PLpgSQL_row *) estate.datums[n];
tup = ((TupleTableSlot *) (args->data[i]))->val;
tupdesc = ((TupleTableSlot *) (args->data[i]))->ttc_tupleDescriptor;
Assert(slot != NULL && ! fcinfo->argnull[i]);
tup = slot->val;
tupdesc = slot->ttc_tupleDescriptor;
exec_move_row(&estate, NULL, row, tup, tupdesc); exec_move_row(&estate, NULL, row, tup, tupdesc);
} }
break; break;
@ -384,7 +384,7 @@ plpgsql_exec_function(PLpgSQL_function * func,
error_info_stmt = NULL; error_info_stmt = NULL;
error_info_text = "while casting return value to functions return type"; error_info_text = "while casting return value to functions return type";
*isNull = estate.retisnull; fcinfo->isnull = estate.retisnull;
if (!estate.retistuple) if (!estate.retistuple)
{ {
@ -393,14 +393,14 @@ plpgsql_exec_function(PLpgSQL_function * func,
&(func->fn_retinput), &(func->fn_retinput),
func->fn_rettypelem, func->fn_rettypelem,
-1, -1,
isNull); &fcinfo->isnull);
/* ---------- /* ----------
* If the functions return type isn't by value, * If the functions return type isn't by value,
* copy the value into upper executor memory context. * copy the value into upper executor memory context.
* ---------- * ----------
*/ */
if (!*isNull && !func->fn_retbyval) if (!fcinfo->isnull && !func->fn_retbyval)
{ {
int len; int len;
Datum tmp; Datum tmp;

View File

@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.3 1999/07/15 15:21:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.4 2000/05/28 17:56:28 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -45,44 +45,45 @@
#include "plpgsql.h" #include "plpgsql.h"
#include "pl.tab.h" #include "pl.tab.h"
#include "executor/spi.h"
#include "commands/trigger.h"
#include "utils/builtins.h"
#include "fmgr.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "utils/syscache.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
/*
* Head of list of already-compiled functions
*/
static PLpgSQL_function *compiled_functions = NULL; static PLpgSQL_function *compiled_functions = NULL;
Datum plpgsql_call_handler(FmgrInfo *proinfo,
FmgrValues *proargs, bool *isNull);
static Datum plpgsql_func_handler(FmgrInfo *proinfo,
FmgrValues *proargs, bool *isNull);
static HeapTuple plpgsql_trigger_handler(FmgrInfo *proinfo);
/* ---------- /* ----------
* plpgsql_call_handler - This is the only visible function * plpgsql_call_handler
* of the PL interpreter. The PostgreSQL *
* function manager and trigger manager * This is the only visible function of the PL interpreter.
* call this function for execution of * The PostgreSQL function manager and trigger manager
* PL/pgSQL procedures. * call this function for execution of PL/pgSQL procedures.
* ---------- * ----------
*/ */
Datum Datum
plpgsql_call_handler(FmgrInfo *proinfo, plpgsql_call_handler(PG_FUNCTION_ARGS)
FmgrValues *proargs,
bool *isNull)
{ {
TriggerData *trigdata;
bool isTrigger;
PLpgSQL_function *func;
Datum retval; Datum retval;
/* ----------
* Save the current trigger data local
*
* XXX this should go away in favor of using fcinfo->context
* ----------
*/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
isTrigger = (trigdata != NULL);
/* ---------- /* ----------
* Connect to SPI manager * Connect to SPI manager
* ---------- * ----------
@ -90,15 +91,54 @@ plpgsql_call_handler(FmgrInfo *proinfo,
if (SPI_connect() != SPI_OK_CONNECT) if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "plpgsql: cannot connect to SPI manager"); elog(ERROR, "plpgsql: cannot connect to SPI manager");
/* ----------
* Check if we already compiled this function and saved the pointer
* (ie, current FmgrInfo has been used before)
* ----------
*/
func = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
if (func == NULL)
{
/* ----------
* Check if we already compiled this function
* ----------
*/
Oid funcOid = fcinfo->flinfo->fn_oid;
for (func = compiled_functions; func != NULL; func = func->next)
{
if (funcOid == func->fn_oid)
break;
}
/* ----------
* If not, do so and add it to the compiled ones
* ----------
*/
if (func == NULL)
{
func = plpgsql_compile(funcOid,
isTrigger ? T_TRIGGER : T_FUNCTION);
func->next = compiled_functions;
compiled_functions = func;
}
/* ----------
* Save pointer in FmgrInfo to avoid search on subsequent calls
* ----------
*/
fcinfo->flinfo->fn_extra = (void *) func;
}
/* ---------- /* ----------
* Determine if called as function or trigger and * Determine if called as function or trigger and
* call appropriate subhandler * call appropriate subhandler
* ---------- * ----------
*/ */
if (CurrentTriggerData == NULL) if (isTrigger)
retval = plpgsql_func_handler(proinfo, proargs, isNull); retval = PointerGetDatum(plpgsql_exec_trigger(func, trigdata));
else else
retval = (Datum) plpgsql_trigger_handler(proinfo); retval = plpgsql_exec_function(func, fcinfo);
/* ---------- /* ----------
* Disconnect from SPI manager * Disconnect from SPI manager
@ -109,83 +149,3 @@ plpgsql_call_handler(FmgrInfo *proinfo,
return retval; return retval;
} }
/* ----------
* plpgsql_func_handler() - Handler for regular function calls
* ----------
*/
static Datum
plpgsql_func_handler(FmgrInfo *proinfo,
FmgrValues *proargs,
bool *isNull)
{
PLpgSQL_function *func;
/* ----------
* Check if we already compiled this function
* ----------
*/
for (func = compiled_functions; func != NULL; func = func->next)
{
if (proinfo->fn_oid == func->fn_oid)
break;
}
/* ----------
* If not, do so and add it to the compiled ones
* ----------
*/
if (func == NULL)
{
func = plpgsql_compile(proinfo->fn_oid, T_FUNCTION);
func->next = compiled_functions;
compiled_functions = func;
}
return plpgsql_exec_function(func, proargs, isNull);
}
/* ----------
* plpgsql_trigger_handler() - Handler for trigger calls
* ----------
*/
static HeapTuple
plpgsql_trigger_handler(FmgrInfo *proinfo)
{
TriggerData *trigdata;
PLpgSQL_function *func;
/* ----------
* Save the current trigger data local
* ----------
*/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
/* ----------
* Check if we already compiled this trigger procedure
* ----------
*/
for (func = compiled_functions; func != NULL; func = func->next)
{
if (proinfo->fn_oid == func->fn_oid)
break;
}
/* ----------
* If not, do so and add it to the compiled ones
* ----------
*/
if (func == NULL)
{
func = plpgsql_compile(proinfo->fn_oid, T_TRIGGER);
func->next = compiled_functions;
compiled_functions = func;
}
return plpgsql_exec_trigger(func, trigdata);
}

View File

@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.8 2000/01/20 05:44:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.9 2000/05/28 17:56:28 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -38,9 +38,10 @@
#define PLPGSQL_H #define PLPGSQL_H
#include "postgres.h" #include "postgres.h"
#include "fmgr.h"
#include "executor/spi.h" #include "executor/spi.h"
#include "commands/trigger.h" #include "commands/trigger.h"
#include "fmgr.h"
/********************************************************************** /**********************************************************************
* Definitions * Definitions
@ -451,15 +452,20 @@ extern void plpgsql_adddatum(PLpgSQL_datum * new);
extern int plpgsql_add_initdatums(int **varnos); extern int plpgsql_add_initdatums(int **varnos);
extern void plpgsql_comperrinfo(void); extern void plpgsql_comperrinfo(void);
/* ----------
* Functions in pl_handler.c
* ----------
*/
extern Datum plpgsql_call_handler(PG_FUNCTION_ARGS);
/* ---------- /* ----------
* Functions in pl_exec.c * Functions in pl_exec.c
* ---------- * ----------
*/ */
extern Datum plpgsql_exec_function(PLpgSQL_function * func, extern Datum plpgsql_exec_function(PLpgSQL_function * func,
FmgrValues *args, bool *isNull); FunctionCallInfo fcinfo);
extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function * func, extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function * func,
TriggerData *trigdata); TriggerData *trigdata);
/* ---------- /* ----------

View File

@ -2,9 +2,6 @@
* pltcl.c - PostgreSQL support for Tcl as * pltcl.c - PostgreSQL support for Tcl as
* procedural language (PL) * procedural language (PL)
* *
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.22 2000/05/23 01:59:05 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
* The author hereby grants permission to use, copy, modify, * The author hereby grants permission to use, copy, modify,
@ -33,6 +30,9 @@
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS. * ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.23 2000/05/28 17:56:29 tgl Exp $
*
**********************************************************************/ **********************************************************************/
#include <tcl.h> #include <tcl.h>
@ -111,13 +111,11 @@ static void pltcl_init_load_unknown(void);
#endif /* PLTCL_UNKNOWN_SUPPORT */ #endif /* PLTCL_UNKNOWN_SUPPORT */
Datum pltcl_call_handler(FmgrInfo *proinfo, Datum pltcl_call_handler(PG_FUNCTION_ARGS);
FmgrValues *proargs, bool *isNull);
static Datum pltcl_func_handler(FmgrInfo *proinfo, static Datum pltcl_func_handler(PG_FUNCTION_ARGS);
FmgrValues *proargs, bool *isNull);
static HeapTuple pltcl_trigger_handler(FmgrInfo *proinfo); static HeapTuple pltcl_trigger_handler(PG_FUNCTION_ARGS);
static int pltcl_elog(ClientData cdata, Tcl_Interp *interp, static int pltcl_elog(ClientData cdata, Tcl_Interp *interp,
int argc, char *argv[]); int argc, char *argv[]);
@ -368,9 +366,7 @@ pltcl_init_load_unknown(void)
/* keep non-static */ /* keep non-static */
Datum Datum
pltcl_call_handler(FmgrInfo *proinfo, pltcl_call_handler(PG_FUNCTION_ARGS)
FmgrValues *proargs,
bool *isNull)
{ {
Datum retval; Datum retval;
@ -395,9 +391,9 @@ pltcl_call_handler(FmgrInfo *proinfo,
* call appropriate subhandler * call appropriate subhandler
************************************************************/ ************************************************************/
if (CurrentTriggerData == NULL) if (CurrentTriggerData == NULL)
retval = pltcl_func_handler(proinfo, proargs, isNull); retval = pltcl_func_handler(fcinfo);
else else
retval = (Datum) pltcl_trigger_handler(proinfo); retval = (Datum) pltcl_trigger_handler(fcinfo);
pltcl_call_level--; pltcl_call_level--;
@ -408,13 +404,10 @@ pltcl_call_handler(FmgrInfo *proinfo,
* pltcl_func_handler() - Handler for regular function calls * pltcl_func_handler() - Handler for regular function calls
**********************************************************************/ **********************************************************************/
static Datum static Datum
pltcl_func_handler(FmgrInfo *proinfo, pltcl_func_handler(PG_FUNCTION_ARGS)
FmgrValues *proargs,
bool *isNull)
{ {
int i; int i;
char internal_proname[512]; char internal_proname[512];
char *stroid;
Tcl_HashEntry *hashent; Tcl_HashEntry *hashent;
int hashnew; int hashnew;
pltcl_proc_desc *volatile prodesc; pltcl_proc_desc *volatile prodesc;
@ -427,10 +420,7 @@ pltcl_func_handler(FmgrInfo *proinfo,
/************************************************************ /************************************************************
* Build our internal proc name from the functions Oid * Build our internal proc name from the functions Oid
************************************************************/ ************************************************************/
stroid = oidout(proinfo->fn_oid); sprintf(internal_proname, "__PLTcl_proc_%u", fcinfo->flinfo->fn_oid);
strcpy(internal_proname, "__PLTcl_proc_");
strcat(internal_proname, stroid);
pfree(stroid);
/************************************************************ /************************************************************
* Lookup the internal proc name in the hashtable * Lookup the internal proc name in the hashtable
@ -467,14 +457,14 @@ pltcl_func_handler(FmgrInfo *proinfo,
* Lookup the pg_proc tuple by Oid * Lookup the pg_proc tuple by Oid
************************************************************/ ************************************************************/
procTup = SearchSysCacheTuple(PROCOID, procTup = SearchSysCacheTuple(PROCOID,
ObjectIdGetDatum(proinfo->fn_oid), ObjectIdGetDatum(fcinfo->flinfo->fn_oid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(procTup)) if (!HeapTupleIsValid(procTup))
{ {
free(prodesc->proname); free(prodesc->proname);
free(prodesc); free(prodesc);
elog(ERROR, "pltcl: cache lookup for proc %u failed", elog(ERROR, "pltcl: cache lookup for proc %u failed",
proinfo->fn_oid); fcinfo->flinfo->fn_oid);
} }
procStruct = (Form_pg_proc) GETSTRUCT(procTup); procStruct = (Form_pg_proc) GETSTRUCT(procTup);
@ -508,9 +498,9 @@ pltcl_func_handler(FmgrInfo *proinfo,
* Get the required information for output conversion * Get the required information for output conversion
* of all procedure arguments * of all procedure arguments
************************************************************/ ************************************************************/
prodesc->nargs = proinfo->fn_nargs; prodesc->nargs = procStruct->pronargs;
proc_internal_args[0] = '\0'; proc_internal_args[0] = '\0';
for (i = 0; i < proinfo->fn_nargs; i++) for (i = 0; i < prodesc->nargs; i++)
{ {
typeTup = SearchSysCacheTuple(TYPEOID, typeTup = SearchSysCacheTuple(TYPEOID,
ObjectIdGetDatum(procStruct->proargtypes[i]), ObjectIdGetDatum(procStruct->proargtypes[i]),
@ -564,7 +554,7 @@ pltcl_func_handler(FmgrInfo *proinfo,
Tcl_DStringAppend(&proc_internal_body, "upvar #0 ", -1); Tcl_DStringAppend(&proc_internal_body, "upvar #0 ", -1);
Tcl_DStringAppend(&proc_internal_body, internal_proname, -1); Tcl_DStringAppend(&proc_internal_body, internal_proname, -1);
Tcl_DStringAppend(&proc_internal_body, " GD\n", -1); Tcl_DStringAppend(&proc_internal_body, " GD\n", -1);
for (i = 0; i < proinfo->fn_nargs; i++) for (i = 0; i < fcinfo->nargs; i++)
{ {
if (!prodesc->arg_is_rel[i]) if (!prodesc->arg_is_rel[i])
continue; continue;
@ -640,10 +630,12 @@ pltcl_func_handler(FmgrInfo *proinfo,
/************************************************** /**************************************************
* For tuple values, add a list for 'array set ...' * For tuple values, add a list for 'array set ...'
**************************************************/ **************************************************/
TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
Assert(slot != NULL && ! fcinfo->argnull[i]);
Tcl_DStringInit(&list_tmp); Tcl_DStringInit(&list_tmp);
pltcl_build_tuple_argument( pltcl_build_tuple_argument(slot->val,
((TupleTableSlot *) (proargs->data[i]))->val, slot->ttc_tupleDescriptor,
((TupleTableSlot *) (proargs->data[i]))->ttc_tupleDescriptor,
&list_tmp); &list_tmp);
Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&list_tmp)); Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&list_tmp));
Tcl_DStringFree(&list_tmp); Tcl_DStringFree(&list_tmp);
@ -655,14 +647,21 @@ pltcl_func_handler(FmgrInfo *proinfo,
* Single values are added as string element * Single values are added as string element
* of their external representation * of their external representation
**************************************************/ **************************************************/
char *tmp; if (fcinfo->argnull[i])
{
Tcl_DStringAppendElement(&tcl_cmd, "");
}
else
{
char *tmp;
tmp = (*fmgr_faddr(&(prodesc->arg_out_func[i]))) tmp = (*fmgr_faddr(&(prodesc->arg_out_func[i])))
(proargs->data[i], (fcinfo->arg[i],
prodesc->arg_out_elem[i], prodesc->arg_out_elem[i],
prodesc->arg_out_len[i]); prodesc->arg_out_len[i]);
Tcl_DStringAppendElement(&tcl_cmd, tmp); Tcl_DStringAppendElement(&tcl_cmd, tmp);
pfree(tmp); pfree(tmp);
}
} }
} }
Tcl_DStringFree(&list_tmp); Tcl_DStringFree(&list_tmp);
@ -719,10 +718,10 @@ pltcl_func_handler(FmgrInfo *proinfo,
if (SPI_finish() != SPI_OK_FINISH) if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "pltcl: SPI_finish() failed"); elog(ERROR, "pltcl: SPI_finish() failed");
retval = (Datum) (*fmgr_faddr(&prodesc->result_in_func)) retval = FunctionCall3(&prodesc->result_in_func,
(pltcl_safe_interp->result, PointerGetDatum(pltcl_safe_interp->result),
prodesc->result_in_elem, ObjectIdGetDatum(prodesc->result_in_elem),
-1); Int32GetDatum(-1));
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart)); memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
return retval; return retval;
@ -733,7 +732,7 @@ pltcl_func_handler(FmgrInfo *proinfo,
* pltcl_trigger_handler() - Handler for trigger calls * pltcl_trigger_handler() - Handler for trigger calls
**********************************************************************/ **********************************************************************/
static HeapTuple static HeapTuple
pltcl_trigger_handler(FmgrInfo *proinfo) pltcl_trigger_handler(PG_FUNCTION_ARGS)
{ {
TriggerData *trigdata; TriggerData *trigdata;
char internal_proname[512]; char internal_proname[512];
@ -767,10 +766,7 @@ pltcl_trigger_handler(FmgrInfo *proinfo)
/************************************************************ /************************************************************
* Build our internal proc name from the functions Oid * Build our internal proc name from the functions Oid
************************************************************/ ************************************************************/
stroid = oidout(proinfo->fn_oid); sprintf(internal_proname, "__PLTcl_proc_%u", fcinfo->flinfo->fn_oid);
strcpy(internal_proname, "__PLTcl_proc_");
strcat(internal_proname, stroid);
pfree(stroid);
/************************************************************ /************************************************************
* Lookup the internal proc name in the hashtable * Lookup the internal proc name in the hashtable
@ -800,14 +796,14 @@ pltcl_trigger_handler(FmgrInfo *proinfo)
* Lookup the pg_proc tuple by Oid * Lookup the pg_proc tuple by Oid
************************************************************/ ************************************************************/
procTup = SearchSysCacheTuple(PROCOID, procTup = SearchSysCacheTuple(PROCOID,
ObjectIdGetDatum(proinfo->fn_oid), ObjectIdGetDatum(fcinfo->flinfo->fn_oid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(procTup)) if (!HeapTupleIsValid(procTup))
{ {
free(prodesc->proname); free(prodesc->proname);
free(prodesc); free(prodesc);
elog(ERROR, "pltcl: cache lookup for proc %u failed", elog(ERROR, "pltcl: cache lookup for proc %u failed",
proinfo->fn_oid); fcinfo->flinfo->fn_oid);
} }
procStruct = (Form_pg_proc) GETSTRUCT(procTup); procStruct = (Form_pg_proc) GETSTRUCT(procTup);