diff options
Diffstat (limited to 'src/backend/utils/fmgr/funcapi.c')
-rw-r--r-- | src/backend/utils/fmgr/funcapi.c | 104 |
1 files changed, 103 insertions, 1 deletions
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index b6ccd63d4dd..598168a70a0 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -7,7 +7,7 @@ * Copyright (c) 2002-2005, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.24 2005/07/03 21:14:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.25 2005/10/06 19:51:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -628,6 +628,108 @@ get_type_func_class(Oid typid) /* + * get_func_result_name + * + * If the function has exactly one output parameter, and that parameter + * is named, return the name (as a palloc'd string). Else return NULL. + * + * This is used to determine the default output column name for functions + * returning scalar types. + */ +char * +get_func_result_name(Oid functionId) +{ + char *result; + HeapTuple procTuple; + Datum proargmodes; + Datum proargnames; + bool isnull; + ArrayType *arr; + int numargs; + char *argmodes; + Datum *argnames; + int numoutargs; + int nargnames; + int i; + + /* First fetch the function's pg_proc row */ + procTuple = SearchSysCache(PROCOID, + ObjectIdGetDatum(functionId), + 0, 0, 0); + if (!HeapTupleIsValid(procTuple)) + elog(ERROR, "cache lookup failed for function %u", functionId); + + /* If there are no named OUT parameters, return NULL */ + if (heap_attisnull(procTuple, Anum_pg_proc_proargmodes) || + heap_attisnull(procTuple, Anum_pg_proc_proargnames)) + result = NULL; + else + { + /* Get the data out of the tuple */ + proargmodes = SysCacheGetAttr(PROCOID, procTuple, + Anum_pg_proc_proargmodes, + &isnull); + Assert(!isnull); + proargnames = SysCacheGetAttr(PROCOID, procTuple, + Anum_pg_proc_proargnames, + &isnull); + Assert(!isnull); + + /* + * We expect the arrays to be 1-D arrays of the right types; verify + * that. For the char array, we don't need to use deconstruct_array() + * since the array data is just going to look like a C array of + * values. + */ + arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */ + numargs = ARR_DIMS(arr)[0]; + if (ARR_NDIM(arr) != 1 || + numargs < 0 || + ARR_ELEMTYPE(arr) != CHAROID) + elog(ERROR, "proargmodes is not a 1-D char array"); + argmodes = (char *) ARR_DATA_PTR(arr); + arr = DatumGetArrayTypeP(proargnames); /* ensure not toasted */ + if (ARR_NDIM(arr) != 1 || + ARR_DIMS(arr)[0] != numargs || + ARR_ELEMTYPE(arr) != TEXTOID) + elog(ERROR, "proargnames is not a 1-D text array"); + deconstruct_array(arr, TEXTOID, -1, false, 'i', + &argnames, &nargnames); + Assert(nargnames == numargs); + + /* scan for output argument(s) */ + result = NULL; + numoutargs = 0; + for (i = 0; i < numargs; i++) + { + if (argmodes[i] == PROARGMODE_IN) + continue; + Assert(argmodes[i] == PROARGMODE_OUT || + argmodes[i] == PROARGMODE_INOUT); + if (++numoutargs > 1) + { + /* multiple out args, so forget it */ + result = NULL; + break; + } + result = DatumGetCString(DirectFunctionCall1(textout, + argnames[i])); + if (result == NULL || result[0] == '\0') + { + /* Parameter is not named, so forget it */ + result = NULL; + break; + } + } + } + + ReleaseSysCache(procTuple); + + return result; +} + + +/* * build_function_result_tupdesc_t * * Given a pg_proc row for a function, return a tuple descriptor for the |