Commit d18e334c authored by Tom Lane's avatar Tom Lane

Fix thinko in recent changes to handle ScalarArrayOpExpr as an indexable

condition: when there are multiple possible index paths involving
ScalarArrayOpExprs, they are logically to be ANDed together not ORed.
This thinko was a direct consequence of trying to put the processing
inside generate_bitmap_or_paths(), which I now see was a bit too cute.
So pull it out and make the callers do it separately (there are only two
that need it anyway).  Partially responds to bug #2441 from Arjen van der Meijden.
There are some additional infelicities exposed by his example, but they
are also in 8.1.x, while this mistake is not.
parent d0f9ca34
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.204 2006/04/09 18:18:41 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.205 2006/05/18 17:12:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -50,6 +50,10 @@ static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, ...@@ -50,6 +50,10 @@ static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
bool istoplevel, bool isjoininner, bool istoplevel, bool isjoininner,
Relids outer_relids, Relids outer_relids,
SaOpControl saop_control); SaOpControl saop_control);
static List *find_saop_paths(PlannerInfo *root, RelOptInfo *rel,
List *clauses, List *outer_clauses,
bool istoplevel, bool isjoininner,
Relids outer_relids);
static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths); static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths);
static int bitmap_path_comparator(const void *a, const void *b); static int bitmap_path_comparator(const void *a, const void *b);
static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths); static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths);
...@@ -189,6 +193,15 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) ...@@ -189,6 +193,15 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
false, NULL); false, NULL);
bitindexpaths = list_concat(bitindexpaths, indexpaths); bitindexpaths = list_concat(bitindexpaths, indexpaths);
/*
* Likewise, generate paths using ScalarArrayOpExpr clauses; these can't
* be simple indexscans but they can be used in bitmap scans.
*/
indexpaths = find_saop_paths(root, rel,
rel->baserestrictinfo, NIL,
true, false, NULL);
bitindexpaths = list_concat(bitindexpaths, indexpaths);
/* /*
* If we found anything usable, generate a BitmapHeapPath for the most * If we found anything usable, generate a BitmapHeapPath for the most
* promising combination of bitmap index paths. * promising combination of bitmap index paths.
...@@ -279,10 +292,6 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, ...@@ -279,10 +292,6 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
* predOK index to an arm of an OR, which would be a legal but * predOK index to an arm of an OR, which would be a legal but
* pointlessly inefficient plan. (A better plan will be generated by * pointlessly inefficient plan. (A better plan will be generated by
* just scanning the predOK index alone, no OR.) * just scanning the predOK index alone, no OR.)
*
* If saop_control is SAOP_REQUIRE and istoplevel is false, the caller
* is only interested in indexquals involving ScalarArrayOps, so don't
* set useful_predicate to true.
*/ */
useful_predicate = false; useful_predicate = false;
if (index->indpred != NIL) if (index->indpred != NIL)
...@@ -308,8 +317,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, ...@@ -308,8 +317,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
if (!predicate_implied_by(index->indpred, all_clauses)) if (!predicate_implied_by(index->indpred, all_clauses))
continue; /* can't use it at all */ continue; /* can't use it at all */
if (saop_control != SAOP_REQUIRE && if (!predicate_implied_by(index->indpred, outer_clauses))
!predicate_implied_by(index->indpred, outer_clauses))
useful_predicate = true; useful_predicate = true;
} }
} }
...@@ -398,11 +406,54 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, ...@@ -398,11 +406,54 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
} }
/*
* find_saop_paths
* Find all the potential indexpaths that make use of ScalarArrayOpExpr
* clauses. The executor only supports these in bitmap scans, not
* plain indexscans, so we need to segregate them from the normal case.
* Otherwise, same API as find_usable_indexes().
* Returns a list of IndexPaths.
*/
static List *
find_saop_paths(PlannerInfo *root, RelOptInfo *rel,
List *clauses, List *outer_clauses,
bool istoplevel, bool isjoininner,
Relids outer_relids)
{
bool have_saop = false;
ListCell *l;
/*
* Since find_usable_indexes is relatively expensive, don't bother to
* run it unless there are some top-level ScalarArrayOpExpr clauses.
*/
foreach(l, clauses)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
Assert(IsA(rinfo, RestrictInfo));
if (IsA(rinfo->clause, ScalarArrayOpExpr))
{
have_saop = true;
break;
}
}
if (!have_saop)
return NIL;
return find_usable_indexes(root, rel,
clauses, outer_clauses,
istoplevel, isjoininner,
outer_relids,
SAOP_REQUIRE);
}
/* /*
* generate_bitmap_or_paths * generate_bitmap_or_paths
* Look through the list of clauses to find OR clauses and * Look through the list of clauses to find OR clauses, and generate
* ScalarArrayOpExpr clauses, and generate a BitmapOrPath for each one * a BitmapOrPath for each one we can handle that way. Return a list
* we can handle that way. Return a list of the generated BitmapOrPaths. * of the generated BitmapOrPaths.
* *
* outer_clauses is a list of additional clauses that can be assumed true * outer_clauses is a list of additional clauses that can be assumed true
* for the purpose of generating indexquals, but are not to be searched for * for the purpose of generating indexquals, but are not to be searched for
...@@ -416,7 +467,6 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, ...@@ -416,7 +467,6 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
{ {
List *result = NIL; List *result = NIL;
List *all_clauses; List *all_clauses;
bool have_saop = false;
ListCell *l; ListCell *l;
/* /*
...@@ -433,16 +483,9 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, ...@@ -433,16 +483,9 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
ListCell *j; ListCell *j;
Assert(IsA(rinfo, RestrictInfo)); Assert(IsA(rinfo, RestrictInfo));
/* /* Ignore RestrictInfos that aren't ORs */
* In this loop we ignore RestrictInfos that aren't ORs; but take
* note of ScalarArrayOpExpr for later.
*/
if (!restriction_is_or_clause(rinfo)) if (!restriction_is_or_clause(rinfo))
{
if (IsA(rinfo->clause, ScalarArrayOpExpr))
have_saop = true;
continue; continue;
}
/* /*
* We must be able to match at least one index to each of the arms of * We must be able to match at least one index to each of the arms of
...@@ -516,29 +559,6 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, ...@@ -516,29 +559,6 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
} }
} }
/*
* If we saw any top-level ScalarArrayOpExpr clauses, see if we can
* generate a bitmap index path that uses those but not any OR clauses.
*/
if (have_saop)
{
List *pathlist;
Path *bitmapqual;
pathlist = find_usable_indexes(root, rel,
clauses,
outer_clauses,
false,
isjoininner,
outer_relids,
SAOP_REQUIRE);
if (pathlist != NIL)
{
bitmapqual = (Path *) create_bitmap_or_path(root, rel, pathlist);
result = lappend(result, bitmapqual);
}
}
return result; return result;
} }
...@@ -1429,14 +1449,24 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, ...@@ -1429,14 +1449,24 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
SAOP_FORBID); SAOP_FORBID);
/* /*
* Generate BitmapOrPaths for any suitable OR-clauses or ScalarArrayOpExpr * Generate BitmapOrPaths for any suitable OR-clauses present in the
* clauses present in the clause list. * clause list.
*/ */
bitindexpaths = generate_bitmap_or_paths(root, rel, bitindexpaths = generate_bitmap_or_paths(root, rel,
clause_list, NIL, clause_list, NIL,
true, true,
outer_relids); outer_relids);
/*
* Likewise, generate paths using ScalarArrayOpExpr clauses; these can't
* be simple indexscans but they can be used in bitmap scans.
*/
bitindexpaths = list_concat(bitindexpaths,
find_saop_paths(root, rel,
clause_list, NIL,
false, true,
outer_relids));
/* /*
* Include the regular index paths in bitindexpaths. * Include the regular index paths in bitindexpaths.
*/ */
......
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