1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

plpgsql does OUT parameters, as per my proposal a few weeks ago.

This commit is contained in:
Tom Lane
2005-04-05 06:22:17 +00:00
parent 2af664e7ce
commit fd97cf4df0
10 changed files with 959 additions and 360 deletions

View File

@@ -7,7 +7,7 @@
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.19 2005/03/31 22:46:16 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.20 2005/04/05 06:22:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -483,6 +483,108 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
return true;
}
/*
* Given the declared argument types and modes for a function,
* replace any polymorphic types (ANYELEMENT/ANYARRAY) with correct data
* types deduced from the input arguments. Returns TRUE if able to deduce
* all types, FALSE if not. This is the same logic as
* resolve_polymorphic_tupdesc, but with a different argument representation.
*
* argmodes may be NULL, in which case all arguments are assumed to be IN mode.
*/
bool
resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
Node *call_expr)
{
bool have_anyelement_result = false;
bool have_anyarray_result = false;
Oid anyelement_type = InvalidOid;
Oid anyarray_type = InvalidOid;
int inargno;
int i;
/* First pass: resolve polymorphic inputs, check for outputs */
inargno = 0;
for (i = 0; i < numargs; i++)
{
char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
switch (argtypes[i])
{
case ANYELEMENTOID:
if (argmode == PROARGMODE_OUT)
have_anyelement_result = true;
else
{
if (!OidIsValid(anyelement_type))
{
anyelement_type = get_call_expr_argtype(call_expr,
inargno);
if (!OidIsValid(anyelement_type))
return false;
}
argtypes[i] = anyelement_type;
}
break;
case ANYARRAYOID:
if (argmode == PROARGMODE_OUT)
have_anyarray_result = true;
else
{
if (!OidIsValid(anyarray_type))
{
anyarray_type = get_call_expr_argtype(call_expr,
inargno);
if (!OidIsValid(anyarray_type))
return false;
}
argtypes[i] = anyarray_type;
}
break;
default:
break;
}
if (argmode != PROARGMODE_OUT)
inargno++;
}
/* Done? */
if (!have_anyelement_result && !have_anyarray_result)
return true;
/* If no input polymorphics, parser messed up */
if (!OidIsValid(anyelement_type) && !OidIsValid(anyarray_type))
return false;
/* If needed, deduce one polymorphic type from the other */
if (have_anyelement_result && !OidIsValid(anyelement_type))
anyelement_type = resolve_generic_type(ANYELEMENTOID,
anyarray_type,
ANYARRAYOID);
if (have_anyarray_result && !OidIsValid(anyarray_type))
anyarray_type = resolve_generic_type(ANYARRAYOID,
anyelement_type,
ANYELEMENTOID);
/* And finally replace the output column types as needed */
for (i = 0; i < numargs; i++)
{
switch (argtypes[i])
{
case ANYELEMENTOID:
argtypes[i] = anyelement_type;
break;
case ANYARRAYOID:
argtypes[i] = anyarray_type;
break;
default:
break;
}
}
return true;
}
/*
* get_type_func_class
* Given the type OID, obtain its TYPEFUNC classification.