9
9
*
10
10
*
11
11
* IDENTIFICATION
12
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.183 2005/06/10 22:25:36 tgl Exp $
12
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.184 2005/06/13 23:14:48 tgl Exp $
13
13
*
14
14
*-------------------------------------------------------------------------
15
15
*/
@@ -87,7 +87,8 @@ static Const *string_to_const(const char *str, Oid datatype);
87
87
*
88
88
* To be considered for an index scan, an index must match one or more
89
89
* restriction clauses or join clauses from the query's qual condition,
90
- * or match the query's ORDER BY condition.
90
+ * or match the query's ORDER BY condition, or have a predicate that
91
+ * matches the query's qual condition.
91
92
*
92
93
* There are two basic kinds of index scans. A "plain" index scan uses
93
94
* only restriction clauses (possibly none at all) in its indexqual,
@@ -210,6 +211,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
210
211
* 'clauses' is the current list of clauses (RestrictInfo nodes)
211
212
* 'outer_clauses' is the list of additional upper-level clauses
212
213
* 'istoplevel' is true if clauses are the rel's top-level restriction list
214
+ * (outer_clauses must be NIL when this is true)
213
215
* 'isjoininner' is true if forming an inner indexscan (so some of the
214
216
* given clauses are join clauses)
215
217
* 'outer_relids' identifies the outer side of the join (pass NULL
@@ -295,13 +297,12 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
295
297
* selectivity of the predicate might alone make the index useful.
296
298
*
297
299
* Note: not all index AMs support scans with no restriction clauses.
298
- * We assume here that the AM does so if and only if it supports
299
- * ordered scans. (It would probably be better if there were a
300
- * specific flag for this in pg_am, but there's not.)
300
+ * We can't generate a scan over an index with amoptionalkey = false
301
+ * unless there's at least one restriction clause.
301
302
*/
302
303
if (restrictclauses != NIL ||
303
- useful_pathkeys != NIL ||
304
- ( index -> indpred != NIL && index_is_ordered ))
304
+ ( index -> amoptionalkey &&
305
+ ( useful_pathkeys != NIL || index -> indpred != NIL ) ))
305
306
{
306
307
ipath = create_index_path (root , index ,
307
308
restrictclauses ,
@@ -608,6 +609,11 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
608
609
* group_clauses_by_indexkey
609
610
* Find restriction clauses that can be used with an index.
610
611
*
612
+ * Returns a list of sublists of RestrictInfo nodes for clauses that can be
613
+ * used with this index. Each sublist contains clauses that can be used
614
+ * with one index key (in no particular order); the top list is ordered by
615
+ * index key. (This is depended on by expand_indexqual_conditions().)
616
+ *
611
617
* As explained in the comments for find_usable_indexes(), we can use
612
618
* clauses from either of the given lists, but the result is required to
613
619
* use at least one clause from the "current clauses" list. We return
@@ -616,18 +622,14 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
616
622
* outer_relids determines what Vars will be allowed on the other side
617
623
* of a possible index qual; see match_clause_to_indexcol().
618
624
*
619
- * Returns a list of sublists of RestrictInfo nodes for clauses that can be
620
- * used with this index. Each sublist contains clauses that can be used
621
- * with one index key (in no particular order); the top list is ordered by
622
- * index key. (This is depended on by expand_indexqual_conditions().)
625
+ * If the index has amoptionalkey = false, we give up and return NIL when
626
+ * there are no restriction clauses matching the first index key. Otherwise,
627
+ * we return NIL if there are no restriction clauses matching any index key.
628
+ * A non-NIL result will have one (possibly empty) sublist for each index key.
623
629
*
624
- * Note that in a multi-key index, we stop if we find a key that cannot be
625
- * used with any clause. For example, given an index on (A,B,C), we might
626
- * return ((C1 C2) (C3 C4)) if we find that clauses C1 and C2 use column A,
627
- * clauses C3 and C4 use column B, and no clauses use column C. But if
628
- * no clauses match B we will return ((C1 C2)), whether or not there are
629
- * clauses matching column C, because the executor couldn't use them anyway.
630
- * Therefore, there are no empty sublists in the result.
630
+ * Example: given an index on (A,B,C), we would return ((C1 C2) () (C3 C4))
631
+ * if we find that clauses C1 and C2 use column A, clauses C3 and C4 use
632
+ * column C, and no clauses use column B.
631
633
*/
632
634
List *
633
635
group_clauses_by_indexkey (IndexOptInfo * index ,
@@ -680,11 +682,10 @@ group_clauses_by_indexkey(IndexOptInfo *index,
680
682
}
681
683
682
684
/*
683
- * If no clauses match this key, we're done; we don't want to look
684
- * at keys to its right.
685
+ * If no clauses match this key, check for amoptionalkey restriction.
685
686
*/
686
- if (clausegroup == NIL )
687
- break ;
687
+ if (clausegroup == NIL && ! index -> amoptionalkey && indexcol == 0 )
688
+ return NIL ;
688
689
689
690
clausegroup_list = lappend (clausegroup_list , clausegroup );
690
691
@@ -1581,11 +1582,9 @@ match_special_index_operator(Expr *clause, Oid opclass,
1581
1582
* will know what to do with.
1582
1583
*
1583
1584
* The input list is ordered by index key, and so the output list is too.
1584
- * (The latter is not depended on by any part of the planner, so far as I can
1585
- * tell; but some parts of the executor do assume that the indexqual list
1586
- * ultimately delivered to the executor is so ordered. One such place is
1587
- * _bt_preprocess_keys() in the btree support. Perhaps that ought to be fixed
1588
- * someday --- tgl 7/00)
1585
+ * (The latter is not depended on by any part of the core planner, I believe,
1586
+ * but parts of the executor require it, and so do the amcostestimate
1587
+ * functions.)
1589
1588
*/
1590
1589
List *
1591
1590
expand_indexqual_conditions (IndexOptInfo * index , List * clausegroups )
0 commit comments