Give a better error message if an SQL-language function is

called through fmgr.  Someday we should try to actually execute the function,
but that looks like it might be a major feature addition.
Not something to try during beta phase.
This commit is contained in:
Tom Lane 1999-04-03 22:57:29 +00:00
parent 4ed9269676
commit a253dcdb23
1 changed files with 69 additions and 29 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.23 1999/03/29 01:30:36 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.24 1999/04/03 22:57:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -33,23 +33,33 @@
#include "commands/trigger.h"
/*
* Interface for PL functions
*
* XXX: use of global fmgr_pl_finfo variable is really ugly. FIXME
*/
static char *
fmgr_pl(char *arg0,...)
{
va_list pvar;
FmgrValues values;
int n_arguments = fmgr_pl_finfo->fn_nargs;
bool isNull = false;
int i;
memset(&values, 0, sizeof(values));
if (fmgr_pl_finfo->fn_nargs > 0)
if (n_arguments > 0)
{
values.data[0] = arg0;
if (fmgr_pl_finfo->fn_nargs > 1)
if (n_arguments > 1)
{
if (n_arguments > MAXFMGRARGS)
elog(ERROR, "fmgr_pl: function %d: too many arguments (%d > %d)",
fmgr_pl_finfo->fn_oid, n_arguments, MAXFMGRARGS);
va_start(pvar, arg0);
for (i = 1; i < fmgr_pl_finfo->fn_nargs; i++)
for (i = 1; i < n_arguments; i++)
values.data[i] = va_arg(pvar, char *);
va_end(pvar);
}
@ -63,6 +73,43 @@ fmgr_pl(char *arg0,...)
}
/*
* Interface for untrusted functions
*/
static char *
fmgr_untrusted(char *arg0,...)
{
/* Currently these are unsupported. Someday we might do something like
* forking a subprocess to execute 'em.
*/
elog(ERROR, "Untrusted functions not supported.");
return NULL; /* keep compiler happy */
}
/*
* Interface for SQL-language functions
*/
static char *
fmgr_sql(char *arg0,...)
{
/*
* XXX It'd be really nice to support SQL functions anywhere that builtins
* are supported. What would we have to do? What pitfalls are there?
*/
elog(ERROR, "SQL-language function not supported in this context.");
return NULL; /* keep compiler happy */
}
/*
* fmgr_c is not really for C functions only; it can be called for functions
* in any language. Many parts of the system use this entry point if they
* want to pass the arguments in an array rather than as explicit arguments.
*/
char *
fmgr_c(FmgrInfo *finfo,
FmgrValues *values,
@ -72,18 +119,6 @@ fmgr_c(FmgrInfo *finfo,
int n_arguments = finfo->fn_nargs;
func_ptr user_fn = fmgr_faddr(finfo);
if (user_fn == (func_ptr) NULL)
{
/*
* a NULL func_ptr denotet untrusted function (in postgres 4.2).
* Untrusted functions have very limited use and is clumsy. We
* just get rid of it.
*/
elog(ERROR, "internal error: untrusted function not supported.");
}
/*
* If finfo contains a PL handler for this function, call that
* instead.
@ -91,6 +126,9 @@ fmgr_c(FmgrInfo *finfo,
if (finfo->fn_plhandler != NULL)
return (*(finfo->fn_plhandler)) (finfo, values, isNull);
if (user_fn == (func_ptr) NULL)
elog(ERROR, "Internal error: fmgr_c received NULL function pointer.");
switch (n_arguments)
{
case 0:
@ -155,6 +193,10 @@ fmgr_c(FmgrInfo *finfo,
return returnValue;
}
/*
* Expand a regproc OID into an FmgrInfo cache struct.
*/
void
fmgr_info(Oid procedureId, FmgrInfo *finfo)
{
@ -188,7 +230,7 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
procedureStruct = (FormData_pg_proc *) GETSTRUCT(procedureTuple);
if (!procedureStruct->proistrusted)
{
finfo->fn_addr = (func_ptr) NULL;
finfo->fn_addr = (func_ptr) fmgr_untrusted;
finfo->fn_nargs = procedureStruct->pronargs;
return;
}
@ -207,7 +249,7 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
finfo->fn_addr = fmgr_dynamic(procedureId, &(finfo->fn_nargs));
break;
case SQLlanguageId:
finfo->fn_addr = (func_ptr) NULL;
finfo->fn_addr = (func_ptr) fmgr_sql;
finfo->fn_nargs = procedureStruct->pronargs;
break;
default:
@ -227,13 +269,12 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
"Cache lookup for language %d failed",
ObjectIdGetDatum(procedureStruct->prolang));
}
languageStruct = (Form_pg_language)
GETSTRUCT(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
if (languageStruct->lanispl)
{
FmgrInfo plfinfo;
fmgr_info(((Form_pg_language) GETSTRUCT(languageTuple))->lanplcallfoid, &plfinfo);
fmgr_info(languageStruct->lanplcallfoid, &plfinfo);
finfo->fn_addr = (func_ptr) fmgr_pl;
finfo->fn_plhandler = plfinfo.fn_addr;
finfo->fn_nargs = procedureStruct->pronargs;
@ -269,16 +310,14 @@ fmgr(Oid procedureId,...)
FmgrInfo finfo;
bool isNull = false;
va_start(pvar, procedureId);
fmgr_info(procedureId, &finfo);
pronargs = finfo.fn_nargs;
if (pronargs > MAXFMGRARGS)
{
elog(ERROR, "fmgr: function %d: too many arguments (%d > %d)",
procedureId, pronargs, MAXFMGRARGS);
}
va_start(pvar, procedureId);
for (i = 0; i < pronargs; ++i)
values.data[i] = va_arg(pvar, char *);
va_end(pvar);
@ -296,7 +335,8 @@ fmgr(Oid procedureId,...)
*
* funcinfo, n_arguments, args...
*/
#ifdef NOT_USED
#ifdef TRACE_FMGR_PTR
char *
fmgr_ptr(FmgrInfo *finfo,...)
{
@ -343,7 +383,7 @@ fmgr_array_args(Oid procedureId, int nargs, char *args[], bool *isNull)
finfo.fn_nargs = nargs;
/* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
return (fmgr_c(&finfo,
(FmgrValues *) args,
isNull));
return fmgr_c(&finfo,
(FmgrValues *) args,
isNull);
}