1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

First phase of work on array improvements. ARRAY[x,y,z] constructor

expressions, ARRAY(sub-SELECT) expressions, some array functions.
Polymorphic functions using ANYARRAY/ANYELEMENT argument and return
types.  Some regression tests in place, documentation is lacking.
Joe Conway, with some kibitzing from Tom Lane.
This commit is contained in:
Tom Lane
2003-04-08 23:20:04 +00:00
parent 6fb5115850
commit 730840c9b6
47 changed files with 2597 additions and 479 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.144 2003/02/09 06:56:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.145 2003/04/08 23:20:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -37,10 +37,6 @@ static Oid **argtype_inherit(int nargs, Oid *argtypes);
static int find_inheritors(Oid relid, Oid **supervec);
static Oid **gen_cross_product(InhPaths *arginh, int nargs);
static void make_arguments(int nargs,
List *fargs,
Oid *input_typeids,
Oid *function_typeids);
static int match_argtypes(int nargs,
Oid *input_typeids,
FuncCandidateList function_typeids,
@ -81,8 +77,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
Node *first_arg = NULL;
int nargs = length(fargs);
int argn;
Oid oid_array[FUNC_MAX_ARGS];
Oid *true_oid_array;
Oid actual_arg_types[FUNC_MAX_ARGS];
Oid *declared_arg_types;
Node *retval;
bool retset;
FuncDetailCode fdresult;
@ -145,7 +141,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
* function. Extract arg type info and transform RangeVar arguments
* into varnodes of the appropriate form.
*/
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
MemSet(actual_arg_types, 0, FUNC_MAX_ARGS * sizeof(Oid));
argn = 0;
foreach(i, fargs)
@ -238,7 +234,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
else
toid = exprType(arg);
oid_array[argn++] = toid;
actual_arg_types[argn++] = toid;
}
/*
@ -248,16 +244,16 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
* function's return value. it also returns the true argument types
* to the function.
*/
fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
fdresult = func_get_detail(funcname, fargs, nargs, actual_arg_types,
&funcid, &rettype, &retset,
&true_oid_array);
&declared_arg_types);
if (fdresult == FUNCDETAIL_COERCION)
{
/*
* We can do it as a trivial coercion. coerce_type can handle
* these cases, so why duplicate code...
*/
return coerce_type(lfirst(fargs), oid_array[0], rettype,
return coerce_type(lfirst(fargs), actual_arg_types[0], rettype,
COERCION_EXPLICIT, COERCE_EXPLICIT_CALL);
}
else if (fdresult == FUNCDETAIL_NORMAL)
@ -303,14 +299,24 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
/*
* Else generate a detailed complaint for a function
*/
func_error(NULL, funcname, nargs, oid_array,
func_error(NULL, funcname, nargs, actual_arg_types,
"Unable to identify a function that satisfies the "
"given argument types"
"\n\tYou may need to add explicit typecasts");
}
/*
* enforce consistency with ANYARRAY and ANYELEMENT argument and
* return types, possibly adjusting return type or declared_arg_types
* (which will be used as the cast destination by make_fn_arguments)
*/
rettype = enforce_generic_type_consistency(actual_arg_types,
declared_arg_types,
nargs,
rettype);
/* perform the necessary typecasting of arguments */
make_arguments(nargs, fargs, oid_array, true_oid_array);
make_fn_arguments(fargs, actual_arg_types, declared_arg_types);
/* build the appropriate output structure */
if (fdresult == FUNCDETAIL_NORMAL)
@ -1130,32 +1136,36 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
}
/* make_arguments()
* Given the number and types of arguments to a function, and the
* actual arguments and argument types, do the necessary typecasting.
/*
* make_fn_arguments()
*
* Given the actual argument expressions for a function, and the desired
* input types for the function, add any necessary typecasting to the
* expression tree. Caller should already have verified that casting is
* allowed.
*
* Caution: given argument list is modified in-place.
*/
static void
make_arguments(int nargs,
List *fargs,
Oid *input_typeids,
Oid *function_typeids)
void
make_fn_arguments(List *fargs,
Oid *actual_arg_types,
Oid *declared_arg_types)
{
List *current_fargs;
int i;
int i = 0;
for (i = 0, current_fargs = fargs;
i < nargs;
i++, current_fargs = lnext(current_fargs))
foreach(current_fargs, fargs)
{
/* types don't match? then force coercion using a function call... */
if (input_typeids[i] != function_typeids[i])
if (actual_arg_types[i] != declared_arg_types[i])
{
lfirst(current_fargs) = coerce_type(lfirst(current_fargs),
input_typeids[i],
function_typeids[i],
actual_arg_types[i],
declared_arg_types[i],
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST);
}
i++;
}
}