@@ -2018,11 +2018,16 @@ rowtype_field_matches(Oid rowtypeid, int fieldnum,
20182018 * will not be pre-evaluated here, although we will reduce their
20192019 * arguments as far as possible.
20202020 *
2021+ * Whenever a function is eliminated from the expression by means of
2022+ * constant-expression evaluation or inlining, we add the function to
2023+ * root->glob->invalItems. This ensures the plan is known to depend on
2024+ * such functions, even though they aren't referenced anymore.
2025+ *
20212026 * We assume that the tree has already been type-checked and contains
20222027 * only operators and functions that are reasonable to try to execute.
20232028 *
20242029 * NOTE: "root" can be passed as NULL if the caller never wants to do any
2025- * Param substitutions.
2030+ * Param substitutions nor receive info about inlined functions .
20262031 *
20272032 * NOTE: the planner assumes that this will always flatten nested AND and
20282033 * OR clauses into N-argument form. See comments in prepqual.c.
@@ -4095,6 +4100,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
40954100 bool modifyTargetList ;
40964101 MemoryContext oldcxt ;
40974102 MemoryContext mycxt ;
4103+ List * saveInvalItems ;
40984104 inline_error_callback_arg callback_arg ;
40994105 ErrorContextCallback sqlerrcontext ;
41004106 List * raw_parsetree_list ;
@@ -4181,6 +4187,16 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
41814187 ALLOCSET_DEFAULT_MAXSIZE );
41824188 oldcxt = MemoryContextSwitchTo (mycxt );
41834189
4190+ /*
4191+ * When we call eval_const_expressions below, it might try to add items
4192+ * to root->glob->invalItems. Since it is running in the temp context,
4193+ * those items will be in that context, and will need to be copied out
4194+ * if we're successful. Temporarily reset the list so that we can keep
4195+ * those items separate from the pre-existing list contents.
4196+ */
4197+ saveInvalItems = root -> glob -> invalItems ;
4198+ root -> glob -> invalItems = NIL ;
4199+
41844200 /* Fetch the function body */
41854201 tmp = SysCacheGetAttr (PROCOID ,
41864202 func_tuple ,
@@ -4307,6 +4323,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
43074323
43084324 querytree = copyObject (querytree );
43094325
4326+ /* copy up any new invalItems, too */
4327+ root -> glob -> invalItems = list_concat (saveInvalItems ,
4328+ copyObject (root -> glob -> invalItems ));
4329+
43104330 MemoryContextDelete (mycxt );
43114331 error_context_stack = sqlerrcontext .previous ;
43124332 ReleaseSysCache (func_tuple );
@@ -4322,6 +4342,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
43224342 /* Here if func is not inlinable: release temp memory and return NULL */
43234343fail :
43244344 MemoryContextSwitchTo (oldcxt );
4345+ root -> glob -> invalItems = saveInvalItems ;
43254346 MemoryContextDelete (mycxt );
43264347 error_context_stack = sqlerrcontext .previous ;
43274348 ReleaseSysCache (func_tuple );
0 commit comments