mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +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:
		@@ -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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user