mirror of
https://github.com/postgres/postgres.git
synced 2025-06-10 09:21:54 +03:00
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
|
* 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"
|
#include "commands/trigger.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interface for PL functions
|
||||||
|
*
|
||||||
|
* XXX: use of global fmgr_pl_finfo variable is really ugly. FIXME
|
||||||
|
*/
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
fmgr_pl(char *arg0,...)
|
fmgr_pl(char *arg0,...)
|
||||||
{
|
{
|
||||||
va_list pvar;
|
va_list pvar;
|
||||||
FmgrValues values;
|
FmgrValues values;
|
||||||
|
int n_arguments = fmgr_pl_finfo->fn_nargs;
|
||||||
bool isNull = false;
|
bool isNull = false;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(&values, 0, sizeof(values));
|
memset(&values, 0, sizeof(values));
|
||||||
|
|
||||||
if (fmgr_pl_finfo->fn_nargs > 0)
|
if (n_arguments > 0)
|
||||||
{
|
{
|
||||||
values.data[0] = arg0;
|
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);
|
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 *);
|
values.data[i] = va_arg(pvar, char *);
|
||||||
va_end(pvar);
|
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 *
|
char *
|
||||||
fmgr_c(FmgrInfo *finfo,
|
fmgr_c(FmgrInfo *finfo,
|
||||||
FmgrValues *values,
|
FmgrValues *values,
|
||||||
@ -72,18 +119,6 @@ fmgr_c(FmgrInfo *finfo,
|
|||||||
int n_arguments = finfo->fn_nargs;
|
int n_arguments = finfo->fn_nargs;
|
||||||
func_ptr user_fn = fmgr_faddr(finfo);
|
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
|
* If finfo contains a PL handler for this function, call that
|
||||||
* instead.
|
* instead.
|
||||||
@ -91,6 +126,9 @@ fmgr_c(FmgrInfo *finfo,
|
|||||||
if (finfo->fn_plhandler != NULL)
|
if (finfo->fn_plhandler != NULL)
|
||||||
return (*(finfo->fn_plhandler)) (finfo, values, isNull);
|
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)
|
switch (n_arguments)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -155,6 +193,10 @@ fmgr_c(FmgrInfo *finfo,
|
|||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expand a regproc OID into an FmgrInfo cache struct.
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
fmgr_info(Oid procedureId, FmgrInfo *finfo)
|
fmgr_info(Oid procedureId, FmgrInfo *finfo)
|
||||||
{
|
{
|
||||||
@ -188,7 +230,7 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
|
|||||||
procedureStruct = (FormData_pg_proc *) GETSTRUCT(procedureTuple);
|
procedureStruct = (FormData_pg_proc *) GETSTRUCT(procedureTuple);
|
||||||
if (!procedureStruct->proistrusted)
|
if (!procedureStruct->proistrusted)
|
||||||
{
|
{
|
||||||
finfo->fn_addr = (func_ptr) NULL;
|
finfo->fn_addr = (func_ptr) fmgr_untrusted;
|
||||||
finfo->fn_nargs = procedureStruct->pronargs;
|
finfo->fn_nargs = procedureStruct->pronargs;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -207,7 +249,7 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
|
|||||||
finfo->fn_addr = fmgr_dynamic(procedureId, &(finfo->fn_nargs));
|
finfo->fn_addr = fmgr_dynamic(procedureId, &(finfo->fn_nargs));
|
||||||
break;
|
break;
|
||||||
case SQLlanguageId:
|
case SQLlanguageId:
|
||||||
finfo->fn_addr = (func_ptr) NULL;
|
finfo->fn_addr = (func_ptr) fmgr_sql;
|
||||||
finfo->fn_nargs = procedureStruct->pronargs;
|
finfo->fn_nargs = procedureStruct->pronargs;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -227,13 +269,12 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
|
|||||||
"Cache lookup for language %d failed",
|
"Cache lookup for language %d failed",
|
||||||
ObjectIdGetDatum(procedureStruct->prolang));
|
ObjectIdGetDatum(procedureStruct->prolang));
|
||||||
}
|
}
|
||||||
languageStruct = (Form_pg_language)
|
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
|
||||||
GETSTRUCT(languageTuple);
|
|
||||||
if (languageStruct->lanispl)
|
if (languageStruct->lanispl)
|
||||||
{
|
{
|
||||||
FmgrInfo plfinfo;
|
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_addr = (func_ptr) fmgr_pl;
|
||||||
finfo->fn_plhandler = plfinfo.fn_addr;
|
finfo->fn_plhandler = plfinfo.fn_addr;
|
||||||
finfo->fn_nargs = procedureStruct->pronargs;
|
finfo->fn_nargs = procedureStruct->pronargs;
|
||||||
@ -269,16 +310,14 @@ fmgr(Oid procedureId,...)
|
|||||||
FmgrInfo finfo;
|
FmgrInfo finfo;
|
||||||
bool isNull = false;
|
bool isNull = false;
|
||||||
|
|
||||||
va_start(pvar, procedureId);
|
|
||||||
|
|
||||||
fmgr_info(procedureId, &finfo);
|
fmgr_info(procedureId, &finfo);
|
||||||
pronargs = finfo.fn_nargs;
|
pronargs = finfo.fn_nargs;
|
||||||
|
|
||||||
if (pronargs > MAXFMGRARGS)
|
if (pronargs > MAXFMGRARGS)
|
||||||
{
|
|
||||||
elog(ERROR, "fmgr: function %d: too many arguments (%d > %d)",
|
elog(ERROR, "fmgr: function %d: too many arguments (%d > %d)",
|
||||||
procedureId, pronargs, MAXFMGRARGS);
|
procedureId, pronargs, MAXFMGRARGS);
|
||||||
}
|
|
||||||
|
va_start(pvar, procedureId);
|
||||||
for (i = 0; i < pronargs; ++i)
|
for (i = 0; i < pronargs; ++i)
|
||||||
values.data[i] = va_arg(pvar, char *);
|
values.data[i] = va_arg(pvar, char *);
|
||||||
va_end(pvar);
|
va_end(pvar);
|
||||||
@ -296,7 +335,8 @@ fmgr(Oid procedureId,...)
|
|||||||
*
|
*
|
||||||
* funcinfo, n_arguments, args...
|
* funcinfo, n_arguments, args...
|
||||||
*/
|
*/
|
||||||
#ifdef NOT_USED
|
#ifdef TRACE_FMGR_PTR
|
||||||
|
|
||||||
char *
|
char *
|
||||||
fmgr_ptr(FmgrInfo *finfo,...)
|
fmgr_ptr(FmgrInfo *finfo,...)
|
||||||
{
|
{
|
||||||
@ -343,7 +383,7 @@ fmgr_array_args(Oid procedureId, int nargs, char *args[], bool *isNull)
|
|||||||
finfo.fn_nargs = nargs;
|
finfo.fn_nargs = nargs;
|
||||||
|
|
||||||
/* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
|
/* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
|
||||||
return (fmgr_c(&finfo,
|
return fmgr_c(&finfo,
|
||||||
(FmgrValues *) args,
|
(FmgrValues *) args,
|
||||||
isNull));
|
isNull);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user