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:
parent
4ed9269676
commit
a253dcdb23
@ -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,
|
||||
return fmgr_c(&finfo,
|
||||
(FmgrValues *) args,
|
||||
isNull));
|
||||
isNull);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user