diff options
Diffstat (limited to 'src/backend/utils/fmgr/fmgr.c')
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 193 |
1 files changed, 98 insertions, 95 deletions
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 7a3798ebe11..6a11bda292c 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.9 1998/01/07 21:06:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.10 1998/01/15 19:45:58 pgsql Exp $ * *------------------------------------------------------------------------- */ @@ -32,78 +32,64 @@ #include "commands/trigger.h" -char * -fmgr_pl(Oid func_id, - int n_arguments, - FmgrValues * values, - bool * isNull) -{ - HeapTuple procedureTuple; - HeapTuple languageTuple; - Form_pg_proc procedureStruct; - Form_pg_language languageStruct; - func_ptr plcall_fn; - int plcall_nargs; - - /* Fetch the pg_proc tuple from the syscache */ - procedureTuple = SearchSysCacheTuple(PROOID, - ObjectIdGetDatum(func_id), - 0, 0, 0); - if (!HeapTupleIsValid(procedureTuple)) - { - elog(ERROR, "fmgr_pl(): Cache lookup of procedure %ld failed.", - ObjectIdGetDatum(func_id)); - } - procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); +static FmgrInfo *fmgr_pl_finfo; - /* Fetch the pg_language tuple from the syscache */ - languageTuple = SearchSysCacheTuple(LANOID, - ObjectIdGetDatum(procedureStruct->prolang), - 0, 0, 0); - if (!HeapTupleIsValid(languageTuple)) - { - elog(ERROR, "fmgr_pl(): Cache lookup of language %ld for procedure %ld failed.", - ObjectIdGetDatum(procedureStruct->prolang), - ObjectIdGetDatum(func_id)); - } - languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); - - /* Get the function pointer for the PL call handler */ - fmgr_info(languageStruct->lanplcallfoid, &plcall_fn, &plcall_nargs); - if (plcall_fn == NULL) - { - elog(ERROR, "fmgr_pl(): failed to load PL handler for procedure %ld.", - ObjectIdGetDatum(func_id)); +static char * +fmgr_pl(char *arg0, ...) +{ + va_list pvar; + FmgrValues values; + bool isNull = false; + int i; + + memset(&values, 0, sizeof(values)); + + if (fmgr_pl_finfo->fn_nargs > 0) { + values.data[0] = arg0; + if (fmgr_pl_finfo->fn_nargs > 1) { + va_start(pvar, arg0); + for (i = 1; i < fmgr_pl_finfo->fn_nargs; i++) { + values.data[i] = va_arg(pvar, char *); + } + va_end(pvar); + } } /* Call the PL handler */ CurrentTriggerData = NULL; - return (*plcall_fn) (func_id, - n_arguments, - values, - isNull); -} - - -char * -fmgr_c(func_ptr user_fn, - Oid func_id, - int n_arguments, - FmgrValues * values, - bool * isNull) -{ - char *returnValue = (char *) NULL; - - + return (*(fmgr_pl_finfo->fn_plhandler)) (fmgr_pl_finfo, + &values, + &isNull); +} + + +char * +fmgr_c(FmgrInfo *finfo, + FmgrValues * values, + bool * isNull) +{ + char *returnValue = (char *) NULL; + 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 now - * use this feature for procedural languages. + * Untrusted functions have very limited use and is clumsy. We + * just get rid of it. */ - return fmgr_pl(func_id, n_arguments, values, isNull); + elog(WARN, "internal error: untrusted function not supported."); + } + + /* + * If finfo contains a PL handler for this function, + * call that instead. + */ + if (finfo->fn_plhandler != NULL) { + return (*(finfo->fn_plhandler))(finfo, values, isNull); } switch (n_arguments) @@ -164,14 +150,14 @@ fmgr_c(func_ptr user_fn, break; default: elog(ERROR, "fmgr_c: function %d: too many arguments (%d > %d)", - func_id, n_arguments, MAXFMGRARGS); + finfo->fn_oid, n_arguments, MAXFMGRARGS); break; } return (returnValue); } void -fmgr_info(Oid procedureId, func_ptr * function, int *nargs) +fmgr_info(Oid procedureId, FmgrInfo *finfo) { func_ptr user_fn = NULL; FmgrCall *fcp; @@ -181,6 +167,10 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs) Form_pg_language languageStruct; Oid language; + finfo->fn_addr = NULL; + finfo->fn_plhandler = NULL; + finfo->fn_oid = procedureId; + if (!(fcp = fmgr_isbuiltin(procedureId))) { procedureTuple = SearchSysCacheTuple(PROOID, @@ -191,29 +181,29 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs) elog(ERROR, "fmgr_info: function %d: cache lookup failed\n", procedureId); } - procedureStruct = (FormData_pg_proc *) - GETSTRUCT(procedureTuple); + procedureStruct = (FormData_pg_proc *) GETSTRUCT(procedureTuple); if (!procedureStruct->proistrusted) { - *function = (func_ptr) NULL; - *nargs = procedureStruct->pronargs; + finfo->fn_addr = (func_ptr) NULL; + finfo->fn_nargs = procedureStruct->pronargs; return; } language = procedureStruct->prolang; switch (language) { case INTERNALlanguageId: - user_fn = fmgr_lookupByName(procedureStruct->proname.data); - if (!user_fn) - elog(ERROR, "fmgr_info: function %s: not in internal table", - procedureStruct->proname.data); + finfo->fn_addr = + fmgr_lookupByName(procedureStruct->proname.data); + if (!finfo->fn_addr) + elog(WARN, "fmgr_info: function %s: not in internal table", + procedureStruct->proname.data); break; case ClanguageId: - user_fn = fmgr_dynamic(procedureId, nargs); + finfo->fn_addr = fmgr_dynamic(procedureId, &(finfo->fn_nargs)); break; case SQLlanguageId: - user_fn = (func_ptr) NULL; - *nargs = procedureStruct->pronargs; + finfo->fn_addr = (func_ptr) NULL; + finfo->fn_nargs = procedureStruct->pronargs; break; default: @@ -236,8 +226,12 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs) GETSTRUCT(languageTuple); if (languageStruct->lanispl) { - user_fn = (func_ptr) NULL; - *nargs = procedureStruct->pronargs; + FmgrInfo plfinfo; + + fmgr_info(((Form_pg_language)GETSTRUCT(languageTuple))->lanplcallfoid, &plfinfo); + finfo->fn_addr = (func_ptr) fmgr_pl; + finfo->fn_plhandler = plfinfo.fn_addr; + finfo->fn_nargs = procedureStruct->pronargs; } else { @@ -249,10 +243,16 @@ fmgr_info(Oid procedureId, func_ptr * function, int *nargs) } else { - user_fn = fcp->func; - *nargs = fcp->nargs; + finfo->fn_addr = fcp->func; + finfo->fn_nargs = fcp->nargs; } - *function = user_fn; +} + +func_ptr +fmgr_faddr(FmgrInfo *finfo) +{ + fmgr_pl_finfo = finfo; + return finfo->fn_addr; } /* @@ -273,12 +273,13 @@ fmgr(Oid procedureId,...) register i; int pronargs; FmgrValues values; - func_ptr user_fn; + FmgrInfo finfo; bool isNull = false; va_start(pvar, procedureId); - fmgr_info(procedureId, &user_fn, &pronargs); + fmgr_info(procedureId, &finfo); + pronargs = finfo.fn_nargs; if (pronargs > MAXFMGRARGS) { @@ -290,8 +291,7 @@ fmgr(Oid procedureId,...) va_end(pvar); /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ - return (fmgr_c(user_fn, procedureId, pronargs, &values, - &isNull)); + return (fmgr_c(&finfo, &values, &isNull)); } /* @@ -301,20 +301,26 @@ fmgr(Oid procedureId,...) * the pointer, but it's available for use with macros in fmgr.h if you * want this routine to do sanity-checking for you. * - * func_ptr, func_id, n_arguments, args... + * funcinfo, n_arguments, args... */ #ifdef NOT_USED char * -fmgr_ptr(func_ptr user_fn, Oid func_id,...) +fmgr_ptr(FmgrInfo *finfo, ...) { va_list pvar; register i; int n_arguments; + FmgrInfo local_finfo; FmgrValues values; bool isNull = false; - va_start(pvar, func_id); + local_finfo->fn_addr = finfo->fn_addr; + local_finfo->fn_plhandler = finfo->fn_plhandler; + local_finfo->fn_oid = finfo->fn_oid; + + va_start(pvar, finfo); n_arguments = va_arg(pvar, int); + local_finfo->fn_nargs = n_arguments; if (n_arguments > MAXFMGRARGS) { elog(ERROR, "fmgr_ptr: function %d: too many arguments (%d > %d)", @@ -325,8 +331,7 @@ fmgr_ptr(func_ptr user_fn, Oid func_id,...) va_end(pvar); /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ - return (fmgr_c(user_fn, func_id, n_arguments, &values, - &isNull)); + return (fmgr_c(&local_finfo, &values, &isNull)); } #endif @@ -339,16 +344,14 @@ fmgr_ptr(func_ptr user_fn, Oid func_id,...) char * fmgr_array_args(Oid procedureId, int nargs, char *args[], bool * isNull) { - func_ptr user_fn; - int true_arguments; + FmgrInfo finfo; - fmgr_info(procedureId, &user_fn, &true_arguments); + fmgr_info(procedureId, &finfo); + finfo.fn_nargs = nargs; /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */ return - (fmgr_c(user_fn, - procedureId, - true_arguments, + (fmgr_c(&finfo, (FmgrValues *) args, isNull)); } |