@@ -2018,11 +2018,16 @@ rowtype_field_matches(Oid rowtypeid, int fieldnum,
2018
2018
* will not be pre-evaluated here, although we will reduce their
2019
2019
* arguments as far as possible.
2020
2020
*
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
+ *
2021
2026
* We assume that the tree has already been type-checked and contains
2022
2027
* only operators and functions that are reasonable to try to execute.
2023
2028
*
2024
2029
* 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 .
2026
2031
*
2027
2032
* NOTE: the planner assumes that this will always flatten nested AND and
2028
2033
* OR clauses into N-argument form. See comments in prepqual.c.
@@ -4107,6 +4112,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
4107
4112
bool modifyTargetList ;
4108
4113
MemoryContext oldcxt ;
4109
4114
MemoryContext mycxt ;
4115
+ List * saveInvalItems ;
4110
4116
inline_error_callback_arg callback_arg ;
4111
4117
ErrorContextCallback sqlerrcontext ;
4112
4118
List * raw_parsetree_list ;
@@ -4193,6 +4199,16 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
4193
4199
ALLOCSET_DEFAULT_MAXSIZE );
4194
4200
oldcxt = MemoryContextSwitchTo (mycxt );
4195
4201
4202
+ /*
4203
+ * When we call eval_const_expressions below, it might try to add items
4204
+ * to root->glob->invalItems. Since it is running in the temp context,
4205
+ * those items will be in that context, and will need to be copied out
4206
+ * if we're successful. Temporarily reset the list so that we can keep
4207
+ * those items separate from the pre-existing list contents.
4208
+ */
4209
+ saveInvalItems = root -> glob -> invalItems ;
4210
+ root -> glob -> invalItems = NIL ;
4211
+
4196
4212
/* Fetch the function body */
4197
4213
tmp = SysCacheGetAttr (PROCOID ,
4198
4214
func_tuple ,
@@ -4319,6 +4335,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
4319
4335
4320
4336
querytree = copyObject (querytree );
4321
4337
4338
+ /* copy up any new invalItems, too */
4339
+ root -> glob -> invalItems = list_concat (saveInvalItems ,
4340
+ copyObject (root -> glob -> invalItems ));
4341
+
4322
4342
MemoryContextDelete (mycxt );
4323
4343
error_context_stack = sqlerrcontext .previous ;
4324
4344
ReleaseSysCache (func_tuple );
@@ -4334,6 +4354,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
4334
4354
/* Here if func is not inlinable: release temp memory and return NULL */
4335
4355
fail :
4336
4356
MemoryContextSwitchTo (oldcxt );
4357
+ root -> glob -> invalItems = saveInvalItems ;
4337
4358
MemoryContextDelete (mycxt );
4338
4359
error_context_stack = sqlerrcontext .previous ;
4339
4360
ReleaseSysCache (func_tuple );
0 commit comments