77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.23 1999/03/29 01:30:36 tgl Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.24 1999/04/03 22:57:29 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
3333#include "commands/trigger.h"
3434
3535
36+ /*
37+ * Interface for PL functions
38+ *
39+ * XXX: use of global fmgr_pl_finfo variable is really ugly. FIXME
40+ */
41+
3642static char *
3743fmgr_pl (char * arg0 ,...)
3844{
3945va_list pvar ;
4046FmgrValues values ;
47+ int n_arguments = fmgr_pl_finfo -> fn_nargs ;
4148bool isNull = false;
4249int i ;
4350
4451memset (& values ,0 ,sizeof (values ));
4552
46- if (fmgr_pl_finfo -> fn_nargs > 0 )
53+ if (n_arguments > 0 )
4754{
4855values .data [0 ]= arg0 ;
49- if (fmgr_pl_finfo -> fn_nargs > 1 )
56+ if (n_arguments > 1 )
5057{
58+ if (n_arguments > MAXFMGRARGS )
59+ elog (ERROR ,"fmgr_pl: function %d: too many arguments (%d > %d)" ,
60+ fmgr_pl_finfo -> fn_oid ,n_arguments ,MAXFMGRARGS );
5161va_start (pvar ,arg0 );
52- for (i = 1 ;i < fmgr_pl_finfo -> fn_nargs ;i ++ )
62+ for (i = 1 ;i < n_arguments ;i ++ )
5363values .data [i ]= va_arg (pvar ,char * );
5464va_end (pvar );
5565}
@@ -63,6 +73,43 @@ fmgr_pl(char *arg0,...)
6373}
6474
6575
76+ /*
77+ * Interface for untrusted functions
78+ */
79+
80+ static char *
81+ fmgr_untrusted (char * arg0 ,...)
82+ {
83+ /* Currently these are unsupported. Someday we might do something like
84+ * forking a subprocess to execute 'em.
85+ */
86+ elog (ERROR ,"Untrusted functions not supported." );
87+ return NULL ;/* keep compiler happy */
88+ }
89+
90+
91+ /*
92+ * Interface for SQL-language functions
93+ */
94+
95+ static char *
96+ fmgr_sql (char * arg0 ,...)
97+ {
98+ /*
99+ * XXX It'd be really nice to support SQL functions anywhere that builtins
100+ * are supported. What would we have to do? What pitfalls are there?
101+ */
102+ elog (ERROR ,"SQL-language function not supported in this context." );
103+ return NULL ;/* keep compiler happy */
104+ }
105+
106+
107+ /*
108+ * fmgr_c is not really for C functions only; it can be called for functions
109+ * in any language. Many parts of the system use this entry point if they
110+ * want to pass the arguments in an array rather than as explicit arguments.
111+ */
112+
66113char *
67114fmgr_c (FmgrInfo * finfo ,
68115FmgrValues * values ,
@@ -72,25 +119,16 @@ fmgr_c(FmgrInfo *finfo,
72119int n_arguments = finfo -> fn_nargs ;
73120func_ptr user_fn = fmgr_faddr (finfo );
74121
75-
76- if (user_fn == (func_ptr )NULL )
77- {
78-
79- /*
80- * a NULL func_ptr denotet untrusted function (in postgres 4.2).
81- * Untrusted functions have very limited use and is clumsy. We
82- * just get rid of it.
83- */
84- elog (ERROR ,"internal error: untrusted function not supported." );
85- }
86-
87122/*
88123 * If finfo contains a PL handler for this function, call that
89124 * instead.
90125 */
91126if (finfo -> fn_plhandler != NULL )
92127return (* (finfo -> fn_plhandler )) (finfo ,values ,isNull );
93128
129+ if (user_fn == (func_ptr )NULL )
130+ elog (ERROR ,"Internal error: fmgr_c received NULL function pointer." );
131+
94132switch (n_arguments )
95133{
96134case 0 :
@@ -155,6 +193,10 @@ fmgr_c(FmgrInfo *finfo,
155193return returnValue ;
156194}
157195
196+ /*
197+ * Expand a regproc OID into an FmgrInfo cache struct.
198+ */
199+
158200void
159201fmgr_info (Oid procedureId ,FmgrInfo * finfo )
160202{
@@ -188,7 +230,7 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
188230procedureStruct = (FormData_pg_proc * )GETSTRUCT (procedureTuple );
189231if (!procedureStruct -> proistrusted )
190232{
191- finfo -> fn_addr = (func_ptr )NULL ;
233+ finfo -> fn_addr = (func_ptr )fmgr_untrusted ;
192234finfo -> fn_nargs = procedureStruct -> pronargs ;
193235return ;
194236}
@@ -207,7 +249,7 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
207249finfo -> fn_addr = fmgr_dynamic (procedureId ,& (finfo -> fn_nargs ));
208250break ;
209251case SQLlanguageId :
210- finfo -> fn_addr = (func_ptr )NULL ;
252+ finfo -> fn_addr = (func_ptr )fmgr_sql ;
211253finfo -> fn_nargs = procedureStruct -> pronargs ;
212254break ;
213255default :
@@ -227,13 +269,12 @@ fmgr_info(Oid procedureId, FmgrInfo *finfo)
227269"Cache lookup for language %d failed" ,
228270ObjectIdGetDatum (procedureStruct -> prolang ));
229271}
230- languageStruct = (Form_pg_language )
231- GETSTRUCT (languageTuple );
272+ languageStruct = (Form_pg_language )GETSTRUCT (languageTuple );
232273if (languageStruct -> lanispl )
233274{
234275FmgrInfo plfinfo ;
235276
236- fmgr_info ((( Form_pg_language ) GETSTRUCT ( languageTuple )) -> lanplcallfoid ,& plfinfo );
277+ fmgr_info (languageStruct -> lanplcallfoid ,& plfinfo );
237278finfo -> fn_addr = (func_ptr )fmgr_pl ;
238279finfo -> fn_plhandler = plfinfo .fn_addr ;
239280finfo -> fn_nargs = procedureStruct -> pronargs ;
@@ -269,16 +310,14 @@ fmgr(Oid procedureId,...)
269310FmgrInfo finfo ;
270311bool isNull = false;
271312
272- va_start (pvar ,procedureId );
273-
274313fmgr_info (procedureId ,& finfo );
275314pronargs = finfo .fn_nargs ;
276315
277316if (pronargs > MAXFMGRARGS )
278- {
279317elog (ERROR ,"fmgr: function %d: too many arguments (%d > %d)" ,
280318procedureId ,pronargs ,MAXFMGRARGS );
281- }
319+
320+ va_start (pvar ,procedureId );
282321for (i = 0 ;i < pronargs ;++ i )
283322values .data [i ]= va_arg (pvar ,char * );
284323va_end (pvar );
@@ -296,7 +335,8 @@ fmgr(Oid procedureId,...)
296335 *
297336 * funcinfo, n_arguments, args...
298337 */
299- #ifdef NOT_USED
338+ #ifdef TRACE_FMGR_PTR
339+
300340char *
301341fmgr_ptr (FmgrInfo * finfo ,...)
302342{
@@ -343,7 +383,7 @@ fmgr_array_args(Oid procedureId, int nargs, char *args[], bool *isNull)
343383finfo .fn_nargs = nargs ;
344384
345385/* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
346- return ( fmgr_c (& finfo ,
347- (FmgrValues * )args ,
348- isNull ) );
386+ return fmgr_c (& finfo ,
387+ (FmgrValues * )args ,
388+ isNull );
349389}