Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 10374a3

Browse files
committed
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.
1 parent ba748f7 commit 10374a3

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.273 2009/01/01 17:23:44 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.274 2009/01/06 01:23:21 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHOR DATE MAJOR EVENT
@@ -98,7 +98,8 @@ static Expr *simplify_function(Oid funcid,
9898
bool allow_inline,
9999
eval_const_expressions_context *context);
100100
static List *add_function_defaults(List *args, Oid result_type,
101-
HeapTuple func_tuple);
101+
HeapTuple func_tuple,
102+
eval_const_expressions_context *context);
102103
static Expr *evaluate_function(Oid funcid,
103104
Oid result_type, int32 result_typmod, List *args,
104105
HeapTuple func_tuple,
@@ -3279,7 +3280,7 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
32793280

32803281
/* While we have the tuple, check if we need to add defaults */
32813282
if (((Form_pg_proc) GETSTRUCT(func_tuple))->pronargs > list_length(*args))
3282-
*args = add_function_defaults(*args, result_type, func_tuple);
3283+
*args = add_function_defaults(*args, result_type, func_tuple, context);
32833284

32843285
newexpr = evaluate_function(funcid, result_type, result_typmod, *args,
32853286
func_tuple, context);
@@ -3302,9 +3303,11 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
33023303
* just like the parser did.
33033304
*/
33043305
static List *
3305-
add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple)
3306+
add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple,
3307+
eval_const_expressions_context *context)
33063308
{
33073309
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
3310+
int nargsprovided = list_length(args);
33083311
Datum proargdefaults;
33093312
bool isnull;
33103313
char *str;
@@ -3327,7 +3330,7 @@ add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple)
33273330
Assert(IsA(defaults, List));
33283331
pfree(str);
33293332
/* Delete any unused defaults from the list */
3330-
ndelete = list_length(args) + list_length(defaults) - funcform->pronargs;
3333+
ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
33313334
if (ndelete < 0)
33323335
elog(ERROR, "not enough default arguments");
33333336
while (ndelete-- > 0)
@@ -3337,8 +3340,8 @@ add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple)
33373340
Assert(list_length(args) == funcform->pronargs);
33383341

33393342
/*
3340-
* The rest of this should be a no-op if there are no polymorphic
3341-
* arguments, but we do it anyway to be sure.
3343+
* The next part should be a no-op if there are no polymorphic arguments,
3344+
* but we do it anyway to be sure.
33423345
*/
33433346
if (list_length(args) > FUNC_MAX_ARGS)
33443347
elog(ERROR, "too many function arguments");
@@ -3361,6 +3364,20 @@ add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple)
33613364
/* perform any necessary typecasting of arguments */
33623365
make_fn_arguments(NULL, args, actual_arg_types, declared_arg_types);
33633366

3367+
/*
3368+
* Lastly, we have to recursively simplify the arguments we just added
3369+
* (but don't recurse on the ones passed in, as we already did those).
3370+
* This isn't merely an optimization, it's *necessary* since there could
3371+
* be functions with defaulted arguments down in there.
3372+
*/
3373+
foreach(lc, args)
3374+
{
3375+
if (nargsprovided-- > 0)
3376+
continue; /* skip original arg positions */
3377+
lfirst(lc) = eval_const_expressions_mutator((Node *) lfirst(lc),
3378+
context);
3379+
}
3380+
33643381
return args;
33653382
}
33663383

0 commit comments

Comments
 (0)