diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c new file mode 100644 index a912174..ed87261 *** a/src/backend/optimizer/path/indxpath.c --- b/src/backend/optimizer/path/indxpath.c *************** *** 32,37 **** --- 32,38 ---- #include "optimizer/predtest.h" #include "optimizer/restrictinfo.h" #include "optimizer/var.h" + #include "parser/parsetree.h" #include "utils/builtins.h" #include "utils/bytea.h" #include "utils/lsyscache.h" *************** static PathClauseUsage *classify_index_c *** 135,141 **** static Relids get_bitmap_tree_required_outer(Path *bitmapqual); static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds); static int find_list_position(Node *node, List **nodelist); ! static bool check_index_only(RelOptInfo *rel, IndexOptInfo *index); static double get_loop_count(PlannerInfo *root, Relids outer_relids); static void match_restriction_clauses_to_index(RelOptInfo *rel, IndexOptInfo *index, --- 136,143 ---- static Relids get_bitmap_tree_required_outer(Path *bitmapqual); static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds); static int find_list_position(Node *node, List **nodelist); ! static bool check_index_only(PlannerInfo *root, RelOptInfo *rel, ! IndexOptInfo *index, List *index_clauses); static double get_loop_count(PlannerInfo *root, Relids outer_relids); static void match_restriction_clauses_to_index(RelOptInfo *rel, IndexOptInfo *index, *************** build_index_paths(PlannerInfo *root, Rel *** 980,986 **** * index data retrieval anyway. */ index_only_scan = (scantype != ST_BITMAPSCAN && ! check_index_only(rel, index)); /* * 4. Generate an indexscan path if there are relevant restriction clauses --- 982,988 ---- * index data retrieval anyway. */ index_only_scan = (scantype != ST_BITMAPSCAN && ! check_index_only(root, rel, index, index_clauses)); /* * 4. Generate an indexscan path if there are relevant restriction clauses *************** find_list_position(Node *node, List **no *** 1741,1747 **** * Determine whether an index-only scan is possible for this index. */ static bool ! check_index_only(RelOptInfo *rel, IndexOptInfo *index) { bool result; Bitmapset *attrs_used = NULL; --- 1743,1750 ---- * Determine whether an index-only scan is possible for this index. */ static bool ! check_index_only(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, ! List *index_clauses) { bool result; Bitmapset *attrs_used = NULL; *************** check_index_only(RelOptInfo *rel, IndexO *** 1758,1771 **** /* * Check that all needed attributes of the relation are available from the * index. - * - * XXX this is overly conservative for partial indexes, since we will - * consider attributes involved in the index predicate as required even - * though the predicate won't need to be checked at runtime. (The same is - * true for attributes used only in index quals, if we are certain that - * the index is not lossy.) However, it would be quite expensive to - * determine that accurately at this point, so for now we take the easy - * way out. */ /* --- 1761,1766 ---- *************** check_index_only(RelOptInfo *rel, IndexO *** 1775,1785 **** */ pull_varattnos((Node *) rel->reltargetlist, rel->relid, &attrs_used); ! /* Add all the attributes used by restriction clauses. */ foreach(lc, rel->baserestrictinfo) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); pull_varattnos((Node *) rinfo->clause, rel->relid, &attrs_used); } --- 1770,1805 ---- */ pull_varattnos((Node *) rel->reltargetlist, rel->relid, &attrs_used); ! /* ! * Add all the attributes required by restriction clauses. This is ! * essentially the same thing we do in create_indexscan_plan. ! */ foreach(lc, rel->baserestrictinfo) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); + Assert(IsA(rinfo, RestrictInfo)); + if (rinfo->pseudoconstant) + continue; /* we may drop pseudoconstants here */ + if (list_member_ptr(index_clauses, rinfo)) + continue; /* simple duplicate */ + if (is_redundant_derived_clause(rinfo, index_clauses)) + continue; /* derived from same EquivalenceClass */ + if (!contain_mutable_functions((Node *) rinfo->clause)) + { + List *clausel = list_make1(rinfo->clause); + + if (predicate_implied_by(clausel, index_clauses)) + continue; /* provably implied by index_clauses */ + if (index->indpred != NIL) + { + if (rel->relid != root->parse->resultRelation && + get_parse_rowmark(root->parse, rel->relid) == NULL) + if (predicate_implied_by(clausel, index->indpred)) + continue; /* implied by index predicate */ + } + } + pull_varattnos((Node *) rinfo->clause, rel->relid, &attrs_used); } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c new file mode 100644 index 184d37a..d1b656f *** a/src/backend/optimizer/plan/createplan.c --- b/src/backend/optimizer/plan/createplan.c *************** create_indexscan_plan(PlannerInfo *root, *** 1215,1221 **** if (predicate_implied_by(clausel, indexquals)) continue; /* provably implied by indexquals */ ! if (best_path->indexinfo->indpred) { if (baserelid != root->parse->resultRelation && get_parse_rowmark(root->parse, baserelid) == NULL) --- 1215,1221 ---- if (predicate_implied_by(clausel, indexquals)) continue; /* provably implied by indexquals */ ! if (best_path->indexinfo->indpred != NIL) { if (baserelid != root->parse->resultRelation && get_parse_rowmark(root->parse, baserelid) == NULL)