Commit 6480c143 authored by Tom Lane's avatar Tom Lane

Partially revert my patch of 2008-11-12 that installed a limit on the number

of AND/OR clause branches that predtest.c would attempt to deal with.  As
noted in bug #4721, that change disabled proof attempts for sizes of problems
that people are actually expecting it to work for.  The original complaint
it was trying to solve was O(N^2) behavior for long IN-lists, so let's try
applying the limit to just ScalarArrayOpExprs rather than everything.
Another case of "foolish consistency" I fear.

Back-patch to 8.2, same as the previous patch was.
parent e54ec923
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.25 2009/05/10 22:45:28 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.26 2009/05/11 17:56:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,13 +31,13 @@ ...@@ -31,13 +31,13 @@
/* /*
* Proof attempts involving many AND or OR branches are likely to require * Proof attempts involving large arrays in ScalarArrayOpExpr nodes are
* O(N^2) time, and more often than not fail anyway. So we set an arbitrary * likely to require O(N^2) time, and more often than not fail anyway.
* limit on the number of branches that we will allow at any one level of * So we set an arbitrary limit on the number of array elements that
* clause. (Note that this is only effective because the trees have been * we will allow to be treated as an AND or OR clause.
* AND/OR flattened!) XXX is it worth exposing this as a GUC knob? * XXX is it worth exposing this as a GUC knob?
*/ */
#define MAX_BRANCHES_TO_TEST 100 #define MAX_SAOP_ARRAY_SIZE 100
/* /*
* To avoid redundant coding in predicate_implied_by_recurse and * To avoid redundant coding in predicate_implied_by_recurse and
...@@ -735,12 +735,12 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate) ...@@ -735,12 +735,12 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
* If the expression is classified as AND- or OR-type, then *info is filled * If the expression is classified as AND- or OR-type, then *info is filled
* in with the functions needed to iterate over its components. * in with the functions needed to iterate over its components.
* *
* This function also implements enforcement of MAX_BRANCHES_TO_TEST: if an * This function also implements enforcement of MAX_SAOP_ARRAY_SIZE: if a
* AND/OR expression has too many branches, we just classify it as an atom. * ScalarArrayOpExpr's array has too many elements, we just classify it as an
* (This will result in its being passed as-is to the simple_clause functions, * atom. (This will result in its being passed as-is to the simple_clause
* which will fail to prove anything about it.) Note that we cannot just stop * functions, which will fail to prove anything about it.) Note that we
* after considering MAX_BRANCHES_TO_TEST branches; in general that would * cannot just stop after considering MAX_SAOP_ARRAY_SIZE elements; in general
* result in wrong proofs rather than failing to prove anything. * that would result in wrong proofs, rather than failing to prove anything.
*/ */
static PredClass static PredClass
predicate_classify(Node *clause, PredIterInfo info) predicate_classify(Node *clause, PredIterInfo info)
...@@ -753,8 +753,7 @@ predicate_classify(Node *clause, PredIterInfo info) ...@@ -753,8 +753,7 @@ predicate_classify(Node *clause, PredIterInfo info)
* If we see a List, assume it's an implicit-AND list; this is the correct * If we see a List, assume it's an implicit-AND list; this is the correct
* semantics for lists of RestrictInfo nodes. * semantics for lists of RestrictInfo nodes.
*/ */
if (IsA(clause, List) && if (IsA(clause, List))
list_length((List *) clause) <= MAX_BRANCHES_TO_TEST)
{ {
info->startup_fn = list_startup_fn; info->startup_fn = list_startup_fn;
info->next_fn = list_next_fn; info->next_fn = list_next_fn;
...@@ -763,16 +762,14 @@ predicate_classify(Node *clause, PredIterInfo info) ...@@ -763,16 +762,14 @@ predicate_classify(Node *clause, PredIterInfo info)
} }
/* Handle normal AND and OR boolean clauses */ /* Handle normal AND and OR boolean clauses */
if (and_clause(clause) && if (and_clause(clause))
list_length(((BoolExpr *) clause)->args) <= MAX_BRANCHES_TO_TEST)
{ {
info->startup_fn = boolexpr_startup_fn; info->startup_fn = boolexpr_startup_fn;
info->next_fn = list_next_fn; info->next_fn = list_next_fn;
info->cleanup_fn = list_cleanup_fn; info->cleanup_fn = list_cleanup_fn;
return CLASS_AND; return CLASS_AND;
} }
if (or_clause(clause) && if (or_clause(clause))
list_length(((BoolExpr *) clause)->args) <= MAX_BRANCHES_TO_TEST)
{ {
info->startup_fn = boolexpr_startup_fn; info->startup_fn = boolexpr_startup_fn;
info->next_fn = list_next_fn; info->next_fn = list_next_fn;
...@@ -800,7 +797,7 @@ predicate_classify(Node *clause, PredIterInfo info) ...@@ -800,7 +797,7 @@ predicate_classify(Node *clause, PredIterInfo info)
arrayval = DatumGetArrayTypeP(((Const *) arraynode)->constvalue); arrayval = DatumGetArrayTypeP(((Const *) arraynode)->constvalue);
nelems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval)); nelems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval));
if (nelems <= MAX_BRANCHES_TO_TEST) if (nelems <= MAX_SAOP_ARRAY_SIZE)
{ {
info->startup_fn = arrayconst_startup_fn; info->startup_fn = arrayconst_startup_fn;
info->next_fn = arrayconst_next_fn; info->next_fn = arrayconst_next_fn;
...@@ -810,7 +807,7 @@ predicate_classify(Node *clause, PredIterInfo info) ...@@ -810,7 +807,7 @@ predicate_classify(Node *clause, PredIterInfo info)
} }
else if (arraynode && IsA(arraynode, ArrayExpr) && else if (arraynode && IsA(arraynode, ArrayExpr) &&
!((ArrayExpr *) arraynode)->multidims && !((ArrayExpr *) arraynode)->multidims &&
list_length(((ArrayExpr *) arraynode)->elements) <= MAX_BRANCHES_TO_TEST) list_length(((ArrayExpr *) arraynode)->elements) <= MAX_SAOP_ARRAY_SIZE)
{ {
info->startup_fn = arrayexpr_startup_fn; info->startup_fn = arrayexpr_startup_fn;
info->next_fn = arrayexpr_next_fn; info->next_fn = arrayexpr_next_fn;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment