diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index cfca6d2268e68680bbdce4f185251288de84ebac..a0205d7b8c60f0aaf4bb30c6c0ef82c832da52f1 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;
 }