99 *
1010 *
1111 * 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 $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
4545((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
4646
4747
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+
4856/* Per-path data used within choose_bitmap_and() */
4957typedef struct
5058{
@@ -58,7 +66,7 @@ typedef struct
5866static List * find_usable_indexes (PlannerInfo * root ,RelOptInfo * rel ,
5967List * clauses ,List * outer_clauses ,
6068bool istoplevel ,RelOptInfo * outer_rel ,
61- SaOpControl saop_control );
69+ SaOpControl saop_control , ScanTypeControl scantype );
6270static List * find_saop_paths (PlannerInfo * root ,RelOptInfo * rel ,
6371List * clauses ,List * outer_clauses ,
6472bool istoplevel ,RelOptInfo * outer_rel );
@@ -168,22 +176,28 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
168176 */
169177indexpaths = find_usable_indexes (root ,rel ,
170178rel -> baserestrictinfo ,NIL ,
171- true,NULL ,SAOP_FORBID );
179+ true,NULL ,SAOP_FORBID , ST_ANYSCAN );
172180
173181/*
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
177189 * generated solely for ordering purposes.
178190 */
179191bitindexpaths = NIL ;
180192foreach (l ,indexpaths )
181193{
182194IndexPath * ipath = (IndexPath * )lfirst (l );
183195
184- add_path (rel , (Path * )ipath );
196+ if (ipath -> indexinfo -> amhasgettuple )
197+ add_path (rel , (Path * )ipath );
185198
186- if (ipath -> indexselectivity < 1.0 &&
199+ if (ipath -> indexinfo -> amhasgetbitmap &&
200+ ipath -> indexselectivity < 1.0 &&
187201!ScanDirectionIsBackward (ipath -> indexscandir ))
188202bitindexpaths = lappend (bitindexpaths ,ipath );
189203}
@@ -254,6 +268,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
254268 * 'outer_rel' is the outer side of the join if forming an inner indexscan
255269 *(so some of the given clauses are join clauses); NULL if not
256270 * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used
271+ * 'scantype' indicates whether we need plain or bitmap scan support
257272 *
258273 * Note: check_partial_indexes() must have been run previously.
259274 *----------
@@ -262,7 +277,7 @@ static List *
262277find_usable_indexes (PlannerInfo * root ,RelOptInfo * rel ,
263278List * clauses ,List * outer_clauses ,
264279bool istoplevel ,RelOptInfo * outer_rel ,
265- SaOpControl saop_control )
280+ SaOpControl saop_control , ScanTypeControl scantype )
266281{
267282Relids outer_relids = outer_rel ?outer_rel -> relids :NULL ;
268283bool possibly_useful_pathkeys = has_useful_pathkeys (root ,rel );
@@ -281,6 +296,24 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
281296bool found_clause ;
282297bool index_is_ordered ;
283298
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+
284317/*
285318 * Ignore partial indexes that do not match the query.If a partial
286319 * 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,
445478return find_usable_indexes (root ,rel ,
446479clauses ,outer_clauses ,
447480istoplevel ,outer_rel ,
448- SAOP_REQUIRE );
481+ SAOP_REQUIRE , ST_BITMAPSCAN );
449482}
450483
451484
@@ -507,7 +540,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
507540all_clauses ,
508541 false,
509542outer_rel ,
510- SAOP_ALLOW );
543+ SAOP_ALLOW ,
544+ ST_BITMAPSCAN );
511545/* Recurse in case there are sub-ORs */
512546indlist = list_concat (indlist ,
513547generate_bitmap_or_paths (root ,rel ,
@@ -524,7 +558,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
524558all_clauses ,
525559 false,
526560outer_rel ,
527- SAOP_ALLOW );
561+ SAOP_ALLOW ,
562+ ST_BITMAPSCAN );
528563}
529564
530565/*
@@ -1641,6 +1676,7 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
16411676List * clause_list ;
16421677List * indexpaths ;
16431678List * bitindexpaths ;
1679+ List * allindexpaths ;
16441680ListCell * l ;
16451681InnerIndexscanInfo * info ;
16461682MemoryContext oldcontext ;
@@ -1736,18 +1772,36 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
17361772 * Find all the index paths that are usable for this join, except for
17371773 * stuff involving OR and ScalarArrayOpExpr clauses.
17381774 */
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+ }
17431796
17441797/*
17451798 * Generate BitmapOrPaths for any suitable OR-clauses present in the
17461799 * clause list.
17471800 */
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 ));
17511805
17521806/*
17531807 * Likewise, generate paths using ScalarArrayOpExpr clauses; these can't
@@ -1758,11 +1812,6 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
17581812clause_list ,NIL ,
17591813false,outer_rel ));
17601814
1761- /*
1762- * Include the regular index paths in bitindexpaths.
1763- */
1764- bitindexpaths = list_concat (bitindexpaths ,list_copy (indexpaths ));
1765-
17661815/*
17671816 * If we found anything usable, generate a BitmapHeapPath for the most
17681817 * promising combination of bitmap index paths.