9
9
*
10
10
*
11
11
* IDENTIFICATION
12
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.236 2009/02/15 20:16:21 tgl Exp $
12
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.237 2009/03/05 23:06:45 tgl Exp $
13
13
*
14
14
*-------------------------------------------------------------------------
15
15
*/
45
45
((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
46
46
47
47
48
+ /* Whether we are looking for plain indexscan, bitmap scan, or either */
49
+ typedef enum
50
+ {
51
+ ST_INDEXSCAN , /* must support amgettuple */
52
+ ST_BITMAPSCAN , /* must support amgetbitmap */
53
+ ST_ANYSCAN /* either is okay */
54
+ } ScanTypeControl ;
55
+
48
56
/* Per-path data used within choose_bitmap_and() */
49
57
typedef struct
50
58
{
@@ -58,7 +66,7 @@ typedef struct
58
66
static List * find_usable_indexes (PlannerInfo * root , RelOptInfo * rel ,
59
67
List * clauses , List * outer_clauses ,
60
68
bool istoplevel , RelOptInfo * outer_rel ,
61
- SaOpControl saop_control );
69
+ SaOpControl saop_control , ScanTypeControl scantype );
62
70
static List * find_saop_paths (PlannerInfo * root , RelOptInfo * rel ,
63
71
List * clauses , List * outer_clauses ,
64
72
bool istoplevel , RelOptInfo * outer_rel );
@@ -168,22 +176,28 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
168
176
*/
169
177
indexpaths = find_usable_indexes (root , rel ,
170
178
rel -> baserestrictinfo , NIL ,
171
- true, NULL , SAOP_FORBID );
179
+ true, NULL , SAOP_FORBID , ST_ANYSCAN );
172
180
173
181
/*
174
- * We can submit them all to add_path. (This generates access paths for
175
- * plain IndexScan plans.) However, for the next step we will only want
176
- * the ones that have some selectivity; we must discard anything that was
182
+ * Submit all the ones that can form plain IndexScan plans to add_path.
183
+ * (A plain IndexPath always represents a plain IndexScan plan; however
184
+ * some of the indexes might support only bitmap scans, and those we
185
+ * mustn't submit to add_path here.) Also, pick out the ones that might
186
+ * be useful as bitmap scans. For that, we must discard indexes that
187
+ * don't support bitmap scans, and we also are only interested in paths
188
+ * that have some selectivity; we should discard anything that was
177
189
* generated solely for ordering purposes.
178
190
*/
179
191
bitindexpaths = NIL ;
180
192
foreach (l , indexpaths )
181
193
{
182
194
IndexPath * ipath = (IndexPath * ) lfirst (l );
183
195
184
- add_path (rel , (Path * ) ipath );
196
+ if (ipath -> indexinfo -> amhasgettuple )
197
+ add_path (rel , (Path * ) ipath );
185
198
186
- if (ipath -> indexselectivity < 1.0 &&
199
+ if (ipath -> indexinfo -> amhasgetbitmap &&
200
+ ipath -> indexselectivity < 1.0 &&
187
201
!ScanDirectionIsBackward (ipath -> indexscandir ))
188
202
bitindexpaths = lappend (bitindexpaths , ipath );
189
203
}
@@ -254,6 +268,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
254
268
* 'outer_rel' is the outer side of the join if forming an inner indexscan
255
269
* (so some of the given clauses are join clauses); NULL if not
256
270
* 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used
271
+ * 'scantype' indicates whether we need plain or bitmap scan support
257
272
*
258
273
* Note: check_partial_indexes() must have been run previously.
259
274
*----------
@@ -262,7 +277,7 @@ static List *
262
277
find_usable_indexes (PlannerInfo * root , RelOptInfo * rel ,
263
278
List * clauses , List * outer_clauses ,
264
279
bool istoplevel , RelOptInfo * outer_rel ,
265
- SaOpControl saop_control )
280
+ SaOpControl saop_control , ScanTypeControl scantype )
266
281
{
267
282
Relids outer_relids = outer_rel ? outer_rel -> relids : NULL ;
268
283
bool possibly_useful_pathkeys = has_useful_pathkeys (root , rel );
@@ -281,6 +296,24 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
281
296
bool found_clause ;
282
297
bool index_is_ordered ;
283
298
299
+ /*
300
+ * Check that index supports the desired scan type(s)
301
+ */
302
+ switch (scantype )
303
+ {
304
+ case ST_INDEXSCAN :
305
+ if (!index -> amhasgettuple )
306
+ continue ;
307
+ break ;
308
+ case ST_BITMAPSCAN :
309
+ if (!index -> amhasgetbitmap )
310
+ continue ;
311
+ break ;
312
+ case ST_ANYSCAN :
313
+ /* either or both are OK */
314
+ break ;
315
+ }
316
+
284
317
/*
285
318
* Ignore partial indexes that do not match the query. If a partial
286
319
* index is marked predOK then we know it's OK; otherwise, if we are
@@ -445,7 +478,7 @@ find_saop_paths(PlannerInfo *root, RelOptInfo *rel,
445
478
return find_usable_indexes (root , rel ,
446
479
clauses , outer_clauses ,
447
480
istoplevel , outer_rel ,
448
- SAOP_REQUIRE );
481
+ SAOP_REQUIRE , ST_BITMAPSCAN );
449
482
}
450
483
451
484
@@ -507,7 +540,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
507
540
all_clauses ,
508
541
false,
509
542
outer_rel ,
510
- SAOP_ALLOW );
543
+ SAOP_ALLOW ,
544
+ ST_BITMAPSCAN );
511
545
/* Recurse in case there are sub-ORs */
512
546
indlist = list_concat (indlist ,
513
547
generate_bitmap_or_paths (root , rel ,
@@ -524,7 +558,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
524
558
all_clauses ,
525
559
false,
526
560
outer_rel ,
527
- SAOP_ALLOW );
561
+ SAOP_ALLOW ,
562
+ ST_BITMAPSCAN );
528
563
}
529
564
530
565
/*
@@ -1641,6 +1676,7 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
1641
1676
List * clause_list ;
1642
1677
List * indexpaths ;
1643
1678
List * bitindexpaths ;
1679
+ List * allindexpaths ;
1644
1680
ListCell * l ;
1645
1681
InnerIndexscanInfo * info ;
1646
1682
MemoryContext oldcontext ;
@@ -1736,18 +1772,36 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
1736
1772
* Find all the index paths that are usable for this join, except for
1737
1773
* stuff involving OR and ScalarArrayOpExpr clauses.
1738
1774
*/
1739
- indexpaths = find_usable_indexes (root , rel ,
1740
- clause_list , NIL ,
1741
- false, outer_rel ,
1742
- SAOP_FORBID );
1775
+ allindexpaths = find_usable_indexes (root , rel ,
1776
+ clause_list , NIL ,
1777
+ false, outer_rel ,
1778
+ SAOP_FORBID ,
1779
+ ST_ANYSCAN );
1780
+
1781
+ /*
1782
+ * Include the ones that are usable as plain indexscans in indexpaths, and
1783
+ * include the ones that are usable as bitmap scans in bitindexpaths.
1784
+ */
1785
+ indexpaths = bitindexpaths = NIL ;
1786
+ foreach (l , allindexpaths )
1787
+ {
1788
+ IndexPath * ipath = (IndexPath * ) lfirst (l );
1789
+
1790
+ if (ipath -> indexinfo -> amhasgettuple )
1791
+ indexpaths = lappend (indexpaths , ipath );
1792
+
1793
+ if (ipath -> indexinfo -> amhasgetbitmap )
1794
+ bitindexpaths = lappend (bitindexpaths , ipath );
1795
+ }
1743
1796
1744
1797
/*
1745
1798
* Generate BitmapOrPaths for any suitable OR-clauses present in the
1746
1799
* clause list.
1747
1800
*/
1748
- bitindexpaths = generate_bitmap_or_paths (root , rel ,
1749
- clause_list , NIL ,
1750
- outer_rel );
1801
+ bitindexpaths = list_concat (bitindexpaths ,
1802
+ generate_bitmap_or_paths (root , rel ,
1803
+ clause_list , NIL ,
1804
+ outer_rel ));
1751
1805
1752
1806
/*
1753
1807
* Likewise, generate paths using ScalarArrayOpExpr clauses; these can't
@@ -1758,11 +1812,6 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
1758
1812
clause_list , NIL ,
1759
1813
false, outer_rel ));
1760
1814
1761
- /*
1762
- * Include the regular index paths in bitindexpaths.
1763
- */
1764
- bitindexpaths = list_concat (bitindexpaths , list_copy (indexpaths ));
1765
-
1766
1815
/*
1767
1816
* If we found anything usable, generate a BitmapHeapPath for the most
1768
1817
* promising combination of bitmap index paths.
0 commit comments