is zero based. <function>get_call_result_type</> can also be used
as an alternative to <function>get_fn_expr_rettype</>.
There is also <function>get_fn_expr_variadic</>, which can be used to
- find out whether the call contained an explicit <literal>VARIADIC</>
- keyword. This is primarily useful for <literal>VARIADIC "any"</>
- functions, as described below.
+ find out whether variadic arguments have been merged into an array.
+ This is primarily useful for <literal>VARIADIC "any"</> functions,
+ since such merging will always have occurred for variadic functions
+ taking ordinary array types.
</para>
<para>
/* perform the necessary typecasting of arguments */
make_fn_arguments(pstate, fargs, actual_arg_types, declared_arg_types);
+ /*
+ * If the function isn't actually variadic, forget any VARIADIC decoration
+ * on the call. (Perhaps we should throw an error instead, but
+ * historically we've allowed people to write that.)
+ */
+ if (!OidIsValid(vatype))
+ {
+ Assert(nvargs == 0);
+ func_variadic = false;
+ }
+
/*
* If it's a variadic function call, transform the last nvargs arguments
* into an array --- unless it's an "any" variadic.
newa->location = exprLocation((Node *) vargs);
fargs = lappend(fargs, newa);
+
+ /* We could not have had VARIADIC marking before ... */
+ Assert(!func_variadic);
+ /* ... but now, it's a VARIADIC call */
+ func_variadic = true;
}
/*
static char *generate_relation_name(Oid relid, List *namespaces);
static char *generate_function_name(Oid funcid, int nargs,
List *argnames, Oid *argtypes,
- bool was_variadic, bool *use_variadic_p);
+ bool has_variadic, bool *use_variadic_p);
static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
static text *string_to_text(char *str);
static char *flatten_reloptions(Oid relid);
*
* If we're dealing with a potentially variadic function (in practice, this
* means a FuncExpr or Aggref, not some other way of calling a function), then
- * was_variadic must specify whether VARIADIC appeared in the original call,
+ * has_variadic must specify whether variadic arguments have been merged,
* and *use_variadic_p will be set to indicate whether to print VARIADIC in
- * the output. For non-FuncExpr cases, was_variadic should be FALSE and
+ * the output. For non-FuncExpr cases, has_variadic should be FALSE and
* use_variadic_p can be NULL.
*
* The result includes all necessary quoting and schema-prefixing.
*/
static char *
generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
- bool was_variadic, bool *use_variadic_p)
+ bool has_variadic, bool *use_variadic_p)
{
char *result;
HeapTuple proctup;
* Determine whether VARIADIC should be printed. We must do this first
* since it affects the lookup rules in func_get_detail().
*
- * Currently, we always print VARIADIC if the function is variadic and
- * takes a variadic type other than ANY. (In principle, if VARIADIC
- * wasn't originally specified and the array actual argument is
- * deconstructable, we could print the array elements separately and not
- * print VARIADIC, thus more nearly reproducing the original input. For
- * the moment that seems like too much complication for the benefit.)
- * However, if the function takes VARIADIC ANY, then the parser didn't
- * fold the arguments together into an array, so we must print VARIADIC if
- * and only if it was used originally.
+ * Currently, we always print VARIADIC if the function has a merged
+ * variadic-array argument. Note that this is always the case for
+ * functions taking a VARIADIC argument type other than VARIADIC ANY.
+ *
+ * In principle, if VARIADIC wasn't originally specified and the array
+ * actual argument is deconstructable, we could print the array elements
+ * separately and not print VARIADIC, thus more nearly reproducing the
+ * original input. For the moment that seems like too much complication
+ * for the benefit, and anyway we do not know whether VARIADIC was
+ * originally specified if it's a non-ANY type.
*/
if (use_variadic_p)
{
- if (OidIsValid(procform->provariadic))
- {
- if (procform->provariadic != ANYOID)
- use_variadic = true;
- else
- use_variadic = was_variadic;
- }
- else
- use_variadic = false;
+ /* Parser should not have set funcvariadic unless fn is variadic */
+ Assert(!has_variadic || OidIsValid(procform->provariadic));
+ use_variadic = has_variadic;
*use_variadic_p = use_variadic;
}
else
{
- Assert(!was_variadic);
+ Assert(!has_variadic);
use_variadic = false;
}
List *aggdistinct; /* DISTINCT (list of SortGroupClause) */
Expr *aggfilter; /* FILTER expression, if any */
bool aggstar; /* TRUE if argument list was really '*' */
- bool aggvariadic; /* TRUE if VARIADIC was used in call */
+ bool aggvariadic; /* true if variadic arguments have been
+ * combined into an array last argument */
char aggkind; /* aggregate kind (see pg_aggregate.h) */
Index agglevelsup; /* > 0 if agg belongs to outer query */
int location; /* token location, or -1 if unknown */
Oid funcid; /* PG_PROC OID of the function */
Oid funcresulttype; /* PG_TYPE OID of result value */
bool funcretset; /* true if function returns set */
- bool funcvariadic; /* true if VARIADIC was used in call */
+ bool funcvariadic; /* true if variadic arguments have been
+ * combined into an array last argument */
CoercionForm funcformat; /* how to display this function call */
Oid funccollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */