Commit b837c992 authored by Tom Lane's avatar Tom Lane

Support polymorphic functions in plpgsql. Along the way, replace

linked-list search of function cache with hash-table lookup.
By Joe Conway.
parent cc300231
This diff is collapsed.
......@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.12 2002/08/30 00:28:41 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.13 2003/07/01 21:47:09 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -45,15 +45,6 @@
#include "utils/syscache.h"
/*
* Head of list of already-compiled functions
*/
static PLpgSQL_function *compiled_functions = NULL;
static bool func_up_to_date(PLpgSQL_function * func);
/* ----------
* plpgsql_call_handler
*
......@@ -67,8 +58,6 @@ PG_FUNCTION_INFO_V1(plpgsql_call_handler);
Datum
plpgsql_call_handler(PG_FUNCTION_ARGS)
{
bool isTrigger = CALLED_AS_TRIGGER(fcinfo);
Oid funcOid = fcinfo->flinfo->fn_oid;
PLpgSQL_function *func;
Datum retval;
......@@ -78,55 +67,14 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
if (SPI_connect() != SPI_OK_CONNECT)
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)
{
Assert(func->fn_oid == funcOid);
/*
* But is the function still up to date?
*/
if (!func_up_to_date(func))
func = NULL;
}
if (func == NULL)
{
/*
* Check if we already compiled this function for another caller
*/
for (func = compiled_functions; func != NULL; func = func->next)
{
if (funcOid == func->fn_oid && func_up_to_date(func))
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;
}
/* Find or compile the function */
func = plpgsql_compile(fcinfo);
/*
* Determine if called as function or trigger and call appropriate
* subhandler
*/
if (isTrigger)
if (CALLED_AS_TRIGGER(fcinfo))
retval = PointerGetDatum(plpgsql_exec_trigger(func,
(TriggerData *) fcinfo->context));
else
......@@ -140,30 +88,3 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
return retval;
}
/*
* Check to see if a compiled function is still up-to-date. This
* is needed because CREATE OR REPLACE FUNCTION can modify the
* function's pg_proc entry without changing its OID.
*/
static bool
func_up_to_date(PLpgSQL_function * func)
{
HeapTuple procTup;
bool result;
procTup = SearchSysCache(PROCOID,
ObjectIdGetDatum(func->fn_oid),
0, 0, 0);
if (!HeapTupleIsValid(procTup))
elog(ERROR, "plpgsql: cache lookup for proc %u failed",
func->fn_oid);
result = (func->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
func->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
ReleaseSysCache(procTup);
return result;
}
......@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.36 2003/05/05 16:46:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.37 2003/07/01 21:47:09 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -487,6 +487,18 @@ typedef struct
} PLpgSQL_stmt_dynexecute;
typedef struct PLpgSQL_func_hashkey
{ /* Hash lookup key for functions */
Oid funcOid;
/*
* We include actual argument types in the hash key to support
* polymorphic PLpgSQL functions. Be careful that extra positions
* are zeroed!
*/
Oid argtypes[FUNC_MAX_ARGS];
} PLpgSQL_func_hashkey;
typedef struct PLpgSQL_function
{ /* Complete compiled function */
char *fn_name;
......@@ -494,6 +506,7 @@ typedef struct PLpgSQL_function
TransactionId fn_xmin;
CommandId fn_cmin;
int fn_functype;
PLpgSQL_func_hashkey *fn_hashkey; /* back-link to hashtable key */
Oid fn_rettype;
int fn_rettyplen;
......@@ -519,8 +532,6 @@ typedef struct PLpgSQL_function
int ndatums;
PLpgSQL_datum **datums;
PLpgSQL_stmt_block *action;
struct PLpgSQL_function *next; /* for chaining list of functions */
} PLpgSQL_function;
......@@ -588,7 +599,7 @@ extern PLpgSQL_function *plpgsql_curr_compile;
* Functions in pl_comp.c
* ----------
*/
extern PLpgSQL_function *plpgsql_compile(Oid fn_oid, int functype);
extern PLpgSQL_function *plpgsql_compile(FunctionCallInfo fcinfo);
extern int plpgsql_parse_word(char *word);
extern int plpgsql_parse_dblword(char *word);
extern int plpgsql_parse_tripword(char *word);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment