Skip to content

Commit d18e334

Browse files
committed
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.
1 parent d0f9ca3 commit d18e334

File tree

1 file changed

+74
-44
lines changed

1 file changed

+74
-44
lines changed

src/backend/optimizer/path/indxpath.c

Lines changed: 74 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.204 2006/04/09 18:18:41 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.205 2006/05/18 17:12:10 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -50,6 +50,10 @@ static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
5050
bool istoplevel, bool isjoininner,
5151
Relids outer_relids,
5252
SaOpControl saop_control);
53+
static List *find_saop_paths(PlannerInfo *root, RelOptInfo *rel,
54+
List *clauses, List *outer_clauses,
55+
bool istoplevel, bool isjoininner,
56+
Relids outer_relids);
5357
static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths);
5458
static int bitmap_path_comparator(const void *a, const void *b);
5559
static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths);
@@ -189,6 +193,15 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
189193
false, NULL);
190194
bitindexpaths = list_concat(bitindexpaths, indexpaths);
191195

196+
/*
197+
* Likewise, generate paths using ScalarArrayOpExpr clauses; these can't
198+
* be simple indexscans but they can be used in bitmap scans.
199+
*/
200+
indexpaths = find_saop_paths(root, rel,
201+
rel->baserestrictinfo, NIL,
202+
true, false, NULL);
203+
bitindexpaths = list_concat(bitindexpaths, indexpaths);
204+
192205
/*
193206
* If we found anything usable, generate a BitmapHeapPath for the most
194207
* promising combination of bitmap index paths.
@@ -279,10 +292,6 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
279292
* predOK index to an arm of an OR, which would be a legal but
280293
* pointlessly inefficient plan. (A better plan will be generated by
281294
* just scanning the predOK index alone, no OR.)
282-
*
283-
* If saop_control is SAOP_REQUIRE and istoplevel is false, the caller
284-
* is only interested in indexquals involving ScalarArrayOps, so don't
285-
* set useful_predicate to true.
286295
*/
287296
useful_predicate = false;
288297
if (index->indpred != NIL)
@@ -308,8 +317,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
308317
if (!predicate_implied_by(index->indpred, all_clauses))
309318
continue; /* can't use it at all */
310319

311-
if (saop_control != SAOP_REQUIRE &&
312-
!predicate_implied_by(index->indpred, outer_clauses))
320+
if (!predicate_implied_by(index->indpred, outer_clauses))
313321
useful_predicate = true;
314322
}
315323
}
@@ -398,11 +406,54 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
398406
}
399407

400408

409+
/*
410+
* find_saop_paths
411+
* Find all the potential indexpaths that make use of ScalarArrayOpExpr
412+
* clauses. The executor only supports these in bitmap scans, not
413+
* plain indexscans, so we need to segregate them from the normal case.
414+
* Otherwise, same API as find_usable_indexes().
415+
* Returns a list of IndexPaths.
416+
*/
417+
static List *
418+
find_saop_paths(PlannerInfo *root, RelOptInfo *rel,
419+
List *clauses, List *outer_clauses,
420+
bool istoplevel, bool isjoininner,
421+
Relids outer_relids)
422+
{
423+
bool have_saop = false;
424+
ListCell *l;
425+
426+
/*
427+
* Since find_usable_indexes is relatively expensive, don't bother to
428+
* run it unless there are some top-level ScalarArrayOpExpr clauses.
429+
*/
430+
foreach(l, clauses)
431+
{
432+
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
433+
434+
Assert(IsA(rinfo, RestrictInfo));
435+
if (IsA(rinfo->clause, ScalarArrayOpExpr))
436+
{
437+
have_saop = true;
438+
break;
439+
}
440+
}
441+
if (!have_saop)
442+
return NIL;
443+
444+
return find_usable_indexes(root, rel,
445+
clauses, outer_clauses,
446+
istoplevel, isjoininner,
447+
outer_relids,
448+
SAOP_REQUIRE);
449+
}
450+
451+
401452
/*
402453
* generate_bitmap_or_paths
403-
* Look through the list of clauses to find OR clauses and
404-
* ScalarArrayOpExpr clauses, and generate a BitmapOrPath for each one
405-
* we can handle that way. Return a list of the generated BitmapOrPaths.
454+
* Look through the list of clauses to find OR clauses, and generate
455+
* a BitmapOrPath for each one we can handle that way. Return a list
456+
* of the generated BitmapOrPaths.
406457
*
407458
* outer_clauses is a list of additional clauses that can be assumed true
408459
* 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,
416467
{
417468
List *result = NIL;
418469
List *all_clauses;
419-
bool have_saop = false;
420470
ListCell *l;
421471

422472
/*
@@ -433,16 +483,9 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
433483
ListCell *j;
434484

435485
Assert(IsA(rinfo, RestrictInfo));
436-
/*
437-
* In this loop we ignore RestrictInfos that aren't ORs; but take
438-
* note of ScalarArrayOpExpr for later.
439-
*/
486+
/* Ignore RestrictInfos that aren't ORs */
440487
if (!restriction_is_or_clause(rinfo))
441-
{
442-
if (IsA(rinfo->clause, ScalarArrayOpExpr))
443-
have_saop = true;
444488
continue;
445-
}
446489

447490
/*
448491
* 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,
516559
}
517560
}
518561

519-
/*
520-
* If we saw any top-level ScalarArrayOpExpr clauses, see if we can
521-
* generate a bitmap index path that uses those but not any OR clauses.
522-
*/
523-
if (have_saop)
524-
{
525-
List *pathlist;
526-
Path *bitmapqual;
527-
528-
pathlist = find_usable_indexes(root, rel,
529-
clauses,
530-
outer_clauses,
531-
false,
532-
isjoininner,
533-
outer_relids,
534-
SAOP_REQUIRE);
535-
if (pathlist != NIL)
536-
{
537-
bitmapqual = (Path *) create_bitmap_or_path(root, rel, pathlist);
538-
result = lappend(result, bitmapqual);
539-
}
540-
}
541-
542562
return result;
543563
}
544564

@@ -1429,14 +1449,24 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
14291449
SAOP_FORBID);
14301450

14311451
/*
1432-
* Generate BitmapOrPaths for any suitable OR-clauses or ScalarArrayOpExpr
1433-
* clauses present in the clause list.
1452+
* Generate BitmapOrPaths for any suitable OR-clauses present in the
1453+
* clause list.
14341454
*/
14351455
bitindexpaths = generate_bitmap_or_paths(root, rel,
14361456
clause_list, NIL,
14371457
true,
14381458
outer_relids);
14391459

1460+
/*
1461+
* Likewise, generate paths using ScalarArrayOpExpr clauses; these can't
1462+
* be simple indexscans but they can be used in bitmap scans.
1463+
*/
1464+
bitindexpaths = list_concat(bitindexpaths,
1465+
find_saop_paths(root, rel,
1466+
clause_list, NIL,
1467+
false, true,
1468+
outer_relids));
1469+
14401470
/*
14411471
* Include the regular index paths in bitindexpaths.
14421472
*/

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy