aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/clauses.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r--src/backend/optimizer/util/clauses.c41
1 files changed, 6 insertions, 35 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 99dbf8da189..7ad9d9ab79e 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -4870,6 +4870,10 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
* set-returning SQL function that can safely be inlined, expand the function
* and return the substitute Query structure. Otherwise, return NULL.
*
+ * We assume that the RTE's expression has already been put through
+ * eval_const_expressions(), which among other things will take care of
+ * default arguments and named-argument notation.
+ *
* This has a good deal of similarity to inline_function(), but that's
* for the non-set-returning case, and there are enough differences to
* justify separate functions.
@@ -4888,7 +4892,6 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
bool modifyTargetList;
MemoryContext oldcxt;
MemoryContext mycxt;
- List *saveInvalItems;
inline_error_callback_arg callback_arg;
ErrorContextCallback sqlerrcontext;
SQLFunctionParseInfoPtr pinfo;
@@ -4966,7 +4969,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
* sharing the snapshot of the calling query. We also disallow returning
* SETOF VOID, because inlining would result in exposing the actual result
* of the function's last SELECT, which should not happen in that case.
- * (Rechecking prokind and proretset is just paranoia.)
+ * (Rechecking prokind, proretset, and pronargs is just paranoia.)
*/
if (funcform->prolang != SQLlanguageId ||
funcform->prokind != PROKIND_FUNCTION ||
@@ -4975,6 +4978,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
funcform->prorettype == VOIDOID ||
funcform->prosecdef ||
!funcform->proretset ||
+ list_length(fexpr->args) != funcform->pronargs ||
!heap_attisnull(func_tuple, Anum_pg_proc_proconfig, NULL))
{
ReleaseSysCache(func_tuple);
@@ -4990,16 +4994,6 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
ALLOCSET_DEFAULT_SIZES);
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,
@@ -5022,24 +5016,6 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
error_context_stack = &sqlerrcontext;
/*
- * Run eval_const_expressions on the function call. This is necessary to
- * ensure that named-argument notation is converted to positional notation
- * and any default arguments are inserted. It's a bit of overkill for the
- * arguments, since they'll get processed again later, but no harm will be
- * done.
- */
- fexpr = (FuncExpr *) eval_const_expressions(root, (Node *) fexpr);
-
- /* It should still be a call of the same function, but let's check */
- if (!IsA(fexpr, FuncExpr) ||
- fexpr->funcid != func_oid)
- goto fail;
-
- /* Arg list length should now match the function */
- if (list_length(fexpr->args) != funcform->pronargs)
- goto fail;
-
- /*
* Set up to handle parameters while parsing the function body. We can
* use the FuncExpr just created as the input for
* prepare_sql_fn_parse_info.
@@ -5129,10 +5105,6 @@ 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);
@@ -5153,7 +5125,6 @@ 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);