aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-08-03 23:46:37 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-08-03 23:46:37 +0000
commit455a55fc291b75d0ec955909f8b44d100c751cca (patch)
tree53fec21ac20fabc2311c88f8b424e62da18e2561 /src
parentc1c7b338eebe986dfa50da8a99b804ccc4e85160 (diff)
downloadpostgresql-455a55fc291b75d0ec955909f8b44d100c751cca.tar.gz
postgresql-455a55fc291b75d0ec955909f8b44d100c751cca.zip
Tighten inline_function's test for overly complex parameters. This
should catch most situations where repeated inlining blows up the expression complexity unreasonably, as in Joe Conway's recent example.
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/util/clauses.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 6060f462e8f..3ebc1c650e8 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.148 2003/07/28 18:33:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.149 2003/08/03 23:46:37 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -26,6 +26,7 @@
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
+#include "optimizer/cost.h"
#include "optimizer/planmain.h"
#include "optimizer/var.h"
#include "parser/analyze.h"
@@ -1710,8 +1711,12 @@ evaluate_function(Oid funcid, Oid result_type, List *args,
* so we keep track of which functions we are already expanding and
* do not re-expand them. Also, if a parameter is used more than once
* in the SQL-function body, we require it not to contain any volatile
- * functions or sublinks --- volatiles might deliver inconsistent answers,
- * and subplans might be unreasonably expensive to evaluate multiple times.
+ * functions (volatiles might deliver inconsistent answers) nor to be
+ * unreasonably expensive to evaluate. The expensiveness check not only
+ * prevents us from doing multiple evaluations of an expensive parameter
+ * at runtime, but is a safety value to limit growth of an expression due
+ * to repeated inlining.
+ *
* We must also beware of changing the volatility or strictness status of
* functions by inlining them.
*
@@ -1912,9 +1917,26 @@ inline_function(Oid funcid, Oid result_type, List *args,
}
else if (usecounts[i] != 1)
{
- /* Param used multiple times: uncool if volatile or expensive */
- if (contain_volatile_functions(param) ||
- contain_subplans(param))
+ /* Param used multiple times: uncool if expensive or volatile */
+ QualCost eval_cost;
+
+ /*
+ * We define "expensive" as "contains any subplan or more than
+ * 10 operators". Note that the subplan search has to be done
+ * explicitly, since cost_qual_eval() will barf on unplanned
+ * subselects.
+ */
+ if (contain_subplans(param))
+ goto fail;
+ cost_qual_eval(&eval_cost, makeList1(param));
+ if (eval_cost.startup + eval_cost.per_tuple >
+ 10 * cpu_operator_cost)
+ goto fail;
+ /*
+ * Check volatility last since this is more expensive than the
+ * above tests
+ */
+ if (contain_volatile_functions(param))
goto fail;
}
i++;