Hello, since CF4 is already closed but this patch ramains marked as 'Ready for Committer', please let me re-post the latest version for CF4 to get rid of vanishing :-p
> tgl> But aside from hasty typos, > > Oops! I've picked up wrong node. It always denies pathkeys extension. > > | !IsA(member, Var)) > > is a mistake of the following. > > | !IsA(member->em_expr, Var)) regards, -- Kyotaro Horiguchi NTT Open Source Software Center
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 4f63906..b695e40 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1790,6 +1790,7 @@ _outIndexOptInfo(StringInfo str, const IndexOptInfo *node) WRITE_BOOL_FIELD(predOK); WRITE_BOOL_FIELD(unique); WRITE_BOOL_FIELD(immediate); + WRITE_BOOL_FIELD(allnotnull); WRITE_BOOL_FIELD(hypothetical); /* we don't bother with fields copied from the pg_am entry */ } diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 606734a..0b2f529 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -952,8 +952,11 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, { index_pathkeys = build_index_pathkeys(root, index, ForwardScanDirection); - useful_pathkeys = truncate_useless_pathkeys(root, rel, - index_pathkeys); + if (index_pathkeys_are_extensible(root, index, index_pathkeys)) + useful_pathkeys = root->query_pathkeys; + else + useful_pathkeys = truncate_useless_pathkeys(root, rel, + index_pathkeys); orderbyclauses = NIL; orderbyclausecols = NIL; } diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 9c8ede6..ad3a8b7 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -502,6 +502,60 @@ build_index_pathkeys(PlannerInfo *root, } /* + * index_pathkeys_are_extensible + * Check whether the pathkeys are extensible to query_pathkeys. + */ +bool +index_pathkeys_are_extensible(PlannerInfo *root, + IndexOptInfo *index, + List *pathkeys) +{ + bool result; + ListCell *lc1; + + if (root->query_pathkeys == NIL || pathkeys == NIL) + return false; + + if (!index->unique || !index->immediate || !index->allnotnull) + return false; + + if (!pathkeys_contained_in(pathkeys, root->query_pathkeys)) + return false; + + if (list_length(pathkeys) == list_length(root->query_pathkeys)) + return true; + + result = true; + foreach(lc1, root->query_pathkeys) + { + PathKey *pathkey = (PathKey *) lfirst(lc1); + bool found = false; + ListCell *lc2; + + foreach(lc2, pathkey->pk_eclass->ec_members) + { + EquivalenceMember *member = (EquivalenceMember *) lfirst(lc2); + + if (!bms_equal(member->em_relids, index->rel->relids) || + !IsA(member->em_expr, Var)) + continue; + else + { + found = true; + break; + } + } + + if (!found) + { + result = false; + break; + } + } + return result; +} + +/* * build_expression_pathkey * Build a pathkeys list that describes an ordering by a single expression * using the given sort operator. diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index de981cb..4e24220 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -333,6 +333,26 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->immediate = index->indimmediate; info->hypothetical = false; + info->allnotnull = true; + for (i = 0; i < ncolumns; i++) + { + int attrno = info->indexkeys[i]; + + if (attrno == 0) + { + info->allnotnull = false; + break; + } + else if (attrno > 0) + { + if (!relation->rd_att->attrs[attrno - 1]->attnotnull) + { + info->allnotnull = false; + break; + } + } + } + /* * Estimate the index size. If it's not a partial index, we lock * the number-of-tuples estimate to equal the parent table; if it diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index a9219e0..d9a3b9b 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -525,6 +525,7 @@ typedef struct IndexOptInfo bool predOK; /* true if predicate matches query */ bool unique; /* true if a unique index */ bool immediate; /* is uniqueness enforced immediately? */ + bool allnotnull; /* true if index's keys are all not null */ bool hypothetical; /* true if index doesn't really exist */ bool canreturn; /* can index return IndexTuples? */ bool amcanorderbyop; /* does AM support order by operator result? */ diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 999adaa..5ee2e56 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -196,5 +196,8 @@ extern List *truncate_useless_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *pathkeys); extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel); +extern bool index_pathkeys_are_extensible(PlannerInfo *root, + IndexOptInfo *index, + List *pathkeys); #endif /* PATHS_H */ diff --git a/src/test/isolation/expected/drop-index-concurrently-1.out b/src/test/isolation/expected/drop-index-concurrently-1.out index 75dff56..ab96fa0 100644 --- a/src/test/isolation/expected/drop-index-concurrently-1.out +++ b/src/test/isolation/expected/drop-index-concurrently-1.out @@ -19,10 +19,8 @@ Sort step explains: EXPLAIN (COSTS OFF) EXECUTE getrow_seq; QUERY PLAN -Sort - Sort Key: id, data - -> Seq Scan on test_dc - Filter: ((data)::text = '34'::text) +Index Scan using test_dc_pkey on test_dc + Filter: ((data)::text = '34'::text) step select2: SELECT * FROM test_dc WHERE data=34 ORDER BY id,data; id data
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers