diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index f4446169f5..58755151fa 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -4648,6 +4648,9 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, Query *querytree; Node *newexpr; int *usecounts; + double *paramcosts; + Cost total_param_cost; + double func_cost; ListCell *arg; int i; @@ -4839,9 +4842,20 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, * substituted. */ usecounts = (int *) palloc0(funcform->pronargs * sizeof(int)); + paramcosts = (double *) palloc0(funcform->pronargs * sizeof(double)); newexpr = substitute_actual_parameters(newexpr, funcform->pronargs, args, usecounts); + /* + * Get the cost of the function without parameters. + * + * Calculation based on how costsize.c performs lookup for function costs + * via 'cost_qual_eval_walker'. + */ + func_cost = get_func_cost(funcid) * cpu_operator_cost; + + total_param_cost = 0.0; + /* Now check for parameter usage */ i = 0; foreach(arg, args) @@ -4867,10 +4881,10 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, */ if (contain_subplans(param)) goto fail; + cost_qual_eval(&eval_cost, list_make1(param), NULL); - if (eval_cost.startup + eval_cost.per_tuple > - 10 * cpu_operator_cost) - goto fail; + paramcosts[i] = (eval_cost.startup + eval_cost.per_tuple); + total_param_cost += (eval_cost.startup + eval_cost.per_tuple); /* * Check volatility last since this is more expensive than the @@ -4883,6 +4897,19 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, } /* + * If the cost of the function is greater than the sum of all the param + * costs, then inline. Otherwise, check the cost of each param. + */ + if (func_cost * INLINE_FUNC_COST_FACTOR < total_param_cost) + { + for (i = 0; i < funcform->pronargs; i++) + { + if (paramcosts[i] > 10 * cpu_operator_cost) + goto fail; + } + } + + /* * Whew --- we can make the substitution. Copy the modified expression * out of the temporary memory context, and clean up. */ diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index ed854fdd40..475df16b28 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -20,6 +20,8 @@ #define is_opclause(clause) ((clause) != NULL && IsA(clause, OpExpr)) #define is_funcclause(clause) ((clause) != NULL && IsA(clause, FuncExpr)) +#define INLINE_FUNC_COST_FACTOR 1 + typedef struct { int numWindowFuncs; /* total number of WindowFuncs found */