From 10374a34c685db5b40b9a53313564b8934ef9ec8 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 6 Jan 2009 01:23:21 +0000 Subject: [PATCH] Fix an oversight in the function-default-arguments patch: after adding some default expressions to a function call, eval_const_expressions must recurse on those expressions. Else they don't get simplified, and in particular we fail to insert additional default arguments if any functions needing defaults are in there. Per report from Rushabh Lathia. --- src/backend/optimizer/util/clauses.c | 31 +++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index cfca6d2268..a0205d7b8c 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.273 2009/01/01 17:23:44 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.274 2009/01/06 01:23:21 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -98,7 +98,8 @@ static Expr *simplify_function(Oid funcid, bool allow_inline, eval_const_expressions_context *context); static List *add_function_defaults(List *args, Oid result_type, - HeapTuple func_tuple); + HeapTuple func_tuple, + eval_const_expressions_context *context); static Expr *evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, List *args, HeapTuple func_tuple, @@ -3279,7 +3280,7 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod, /* While we have the tuple, check if we need to add defaults */ if (((Form_pg_proc) GETSTRUCT(func_tuple))->pronargs > list_length(*args)) - *args = add_function_defaults(*args, result_type, func_tuple); + *args = add_function_defaults(*args, result_type, func_tuple, context); newexpr = evaluate_function(funcid, result_type, result_typmod, *args, func_tuple, context); @@ -3302,9 +3303,11 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod, * just like the parser did. */ static List * -add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple) +add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple, + eval_const_expressions_context *context) { Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple); + int nargsprovided = list_length(args); Datum proargdefaults; bool isnull; char *str; @@ -3327,7 +3330,7 @@ add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple) Assert(IsA(defaults, List)); pfree(str); /* Delete any unused defaults from the list */ - ndelete = list_length(args) + list_length(defaults) - funcform->pronargs; + ndelete = nargsprovided + list_length(defaults) - funcform->pronargs; if (ndelete < 0) elog(ERROR, "not enough default arguments"); while (ndelete-- > 0) @@ -3337,8 +3340,8 @@ add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple) Assert(list_length(args) == funcform->pronargs); /* - * The rest of this should be a no-op if there are no polymorphic - * arguments, but we do it anyway to be sure. + * The next part should be a no-op if there are no polymorphic arguments, + * but we do it anyway to be sure. */ if (list_length(args) > FUNC_MAX_ARGS) elog(ERROR, "too many function arguments"); @@ -3361,6 +3364,20 @@ add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple) /* perform any necessary typecasting of arguments */ make_fn_arguments(NULL, args, actual_arg_types, declared_arg_types); + /* + * Lastly, we have to recursively simplify the arguments we just added + * (but don't recurse on the ones passed in, as we already did those). + * This isn't merely an optimization, it's *necessary* since there could + * be functions with defaulted arguments down in there. + */ + foreach(lc, args) + { + if (nargsprovided-- > 0) + continue; /* skip original arg positions */ + lfirst(lc) = eval_const_expressions_mutator((Node *) lfirst(lc), + context); + } + return args; }