1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-13 18:28:01 +03:00

Implement SQL-spec RETURNS TABLE syntax for functions.

(Unlike the original submission, this patch treats TABLE output parameters
as being entirely equivalent to OUT parameters -- tgl)

Pavel Stehule
This commit is contained in:
Tom Lane
2008-07-18 03:32:53 +00:00
parent a8fb90cf2d
commit 69a785b8bf
23 changed files with 626 additions and 85 deletions

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.277 2008/07/16 16:55:23 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.278 2008/07/18 03:32:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -135,6 +135,8 @@ static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
int prettyFlags);
static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
int prettyFlags);
static int print_function_arguments(StringInfo buf, HeapTuple proctup,
bool print_table_args);
static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
int prettyFlags);
static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
@@ -1395,6 +1397,147 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
}
/*
* pg_get_function_arguments
* Get a nicely-formatted list of arguments for a function.
* This is everything that would go between the parentheses in
* CREATE FUNCTION.
*/
Datum
pg_get_function_arguments(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
StringInfoData buf;
HeapTuple proctup;
initStringInfo(&buf);
proctup = SearchSysCache(PROCOID,
ObjectIdGetDatum(funcid),
0, 0, 0);
if (!HeapTupleIsValid(proctup))
elog(ERROR, "cache lookup failed for function %u", funcid);
(void) print_function_arguments(&buf, proctup, false);
ReleaseSysCache(proctup);
PG_RETURN_TEXT_P(string_to_text(buf.data));
}
/*
* pg_get_function_result
* Get a nicely-formatted version of the result type of a function.
* This is what would appear after RETURNS in CREATE FUNCTION.
*/
Datum
pg_get_function_result(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
StringInfoData buf;
HeapTuple proctup;
Form_pg_proc procform;
int ntabargs = 0;
initStringInfo(&buf);
proctup = SearchSysCache(PROCOID,
ObjectIdGetDatum(funcid),
0, 0, 0);
if (!HeapTupleIsValid(proctup))
elog(ERROR, "cache lookup failed for function %u", funcid);
procform = (Form_pg_proc) GETSTRUCT(proctup);
if (procform->proretset)
{
/* It might be a table function; try to print the arguments */
appendStringInfoString(&buf, "TABLE(");
ntabargs = print_function_arguments(&buf, proctup, true);
if (ntabargs > 0)
appendStringInfoString(&buf, ")");
else
resetStringInfo(&buf);
}
if (ntabargs == 0)
{
/* Not a table function, so do the normal thing */
if (procform->proretset)
appendStringInfoString(&buf, "SETOF ");
appendStringInfoString(&buf, format_type_be(procform->prorettype));
}
ReleaseSysCache(proctup);
PG_RETURN_TEXT_P(string_to_text(buf.data));
}
/*
* Common code for pg_get_function_arguments and pg_get_function_result:
* append the desired subset of arguments to buf. We print only TABLE
* arguments when print_table_args is true, and all the others when it's false.
* Function return value is the number of arguments printed.
*/
static int
print_function_arguments(StringInfo buf, HeapTuple proctup,
bool print_table_args)
{
int numargs;
Oid *argtypes;
char **argnames;
char *argmodes;
int argsprinted;
int i;
numargs = get_func_arg_info(proctup,
&argtypes, &argnames, &argmodes);
argsprinted = 0;
for (i = 0; i < numargs; i++)
{
Oid argtype = argtypes[i];
char *argname = argnames ? argnames[i] : NULL;
char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
const char *modename;
if (print_table_args != (argmode == PROARGMODE_TABLE))
continue;
switch (argmode)
{
case PROARGMODE_IN:
modename = "";
break;
case PROARGMODE_INOUT:
modename = "INOUT ";
break;
case PROARGMODE_OUT:
modename = "OUT ";
break;
case PROARGMODE_VARIADIC:
modename = "VARIADIC ";
break;
case PROARGMODE_TABLE:
modename = "";
break;
default:
elog(ERROR, "invalid parameter mode '%c'", argmode);
modename = NULL; /* keep compiler quiet */
break;
}
if (argsprinted)
appendStringInfoString(buf, ", ");
appendStringInfoString(buf, modename);
if (argname && argname[0])
appendStringInfo(buf, "%s ", argname);
appendStringInfoString(buf, format_type_be(argtype));
argsprinted++;
}
return argsprinted;
}
/*
* deparse_expression - General utility for deparsing expressions
*