From ef55e294e66725c412d55b9689328235141d816d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 25 Oct 2010 13:04:37 -0400 Subject: [PATCH] Fix inline_set_returning_function() to preserve the invalItems list properly. This avoids a possible crash when inlining a SRF whose argument list contains a reference to an inline-able user function. The crash is quite reproducible with CLOBBER_FREED_MEMORY enabled, but would be less certain in a production build. Problem introduced in 9.0 by the named-arguments patch, which requires invoking eval_const_expressions() before we can try to inline a SRF. Per report from Brendan Jurd. --- src/backend/optimizer/util/clauses.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 13e89ec667..e948bccc1a 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -2018,11 +2018,16 @@ rowtype_field_matches(Oid rowtypeid, int fieldnum, * will not be pre-evaluated here, although we will reduce their * arguments as far as possible. * + * Whenever a function is eliminated from the expression by means of + * constant-expression evaluation or inlining, we add the function to + * root->glob->invalItems. This ensures the plan is known to depend on + * such functions, even though they aren't referenced anymore. + * * We assume that the tree has already been type-checked and contains * only operators and functions that are reasonable to try to execute. * * NOTE: "root" can be passed as NULL if the caller never wants to do any - * Param substitutions. + * Param substitutions nor receive info about inlined functions. * * NOTE: the planner assumes that this will always flatten nested AND and * OR clauses into N-argument form. See comments in prepqual.c. @@ -4095,6 +4100,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) bool modifyTargetList; MemoryContext oldcxt; MemoryContext mycxt; + List *saveInvalItems; inline_error_callback_arg callback_arg; ErrorContextCallback sqlerrcontext; List *raw_parsetree_list; @@ -4181,6 +4187,16 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) ALLOCSET_DEFAULT_MAXSIZE); oldcxt = MemoryContextSwitchTo(mycxt); + /* + * When we call eval_const_expressions below, it might try to add items + * to root->glob->invalItems. Since it is running in the temp context, + * those items will be in that context, and will need to be copied out + * if we're successful. Temporarily reset the list so that we can keep + * those items separate from the pre-existing list contents. + */ + saveInvalItems = root->glob->invalItems; + root->glob->invalItems = NIL; + /* Fetch the function body */ tmp = SysCacheGetAttr(PROCOID, func_tuple, @@ -4307,6 +4323,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) querytree = copyObject(querytree); + /* copy up any new invalItems, too */ + root->glob->invalItems = list_concat(saveInvalItems, + copyObject(root->glob->invalItems)); + MemoryContextDelete(mycxt); error_context_stack = sqlerrcontext.previous; ReleaseSysCache(func_tuple); @@ -4322,6 +4342,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) /* Here if func is not inlinable: release temp memory and return NULL */ fail: MemoryContextSwitchTo(oldcxt); + root->glob->invalItems = saveInvalItems; MemoryContextDelete(mycxt); error_context_stack = sqlerrcontext.previous; ReleaseSysCache(func_tuple); -- 2.40.0