diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-09-18 12:20:34 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-09-18 12:20:34 -0400 |
commit | 807a40c551dd30c8dd5a0b3bd82f5bbb1e7fd285 (patch) | |
tree | a8535d90e7e352592ed6cd85c82a83db927516bb /src/backend/optimizer | |
parent | 3f828fae6221d93cbef370f57ab3f234b590ca98 (diff) | |
download | postgresql-807a40c551dd30c8dd5a0b3bd82f5bbb1e7fd285.tar.gz postgresql-807a40c551dd30c8dd5a0b3bd82f5bbb1e7fd285.zip |
Fix planning of btree index scans using ScalarArrayOpExpr quals.
In commit 9e8da0f75731aaa7605cf4656c21ea09e84d2eb1, I improved btree
to handle ScalarArrayOpExpr quals natively, so that constructs like
"indexedcol IN (list)" could be supported by index-only scans. Using
such a qual results in multiple scans of the index, under-the-hood.
I went to some lengths to ensure that this still produces rows in index
order ... but I failed to recognize that if a higher-order index column
is lacking an equality constraint, rescans can produce out-of-order
data from that column. Tweak the planner to not expect sorted output
in that case. Per trouble report from Robert McGehee.
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 53bf15aea23..444ec2a40e4 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -787,6 +787,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, List *index_pathkeys; List *useful_pathkeys; bool found_clause; + bool found_lower_saop_clause; bool pathkeys_possibly_useful; bool index_is_ordered; bool index_only_scan; @@ -824,6 +825,13 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, * if saop_control is SAOP_REQUIRE, it has to be a ScalarArrayOpExpr * clause. * + * found_lower_saop_clause is set true if there's a ScalarArrayOpExpr + * index clause for a non-first index column. This prevents us from + * assuming that the scan result is ordered. (Actually, the result is + * still ordered if there are equality constraints for all earlier + * columns, but it seems too expensive and non-modular for this code to be + * aware of that refinement.) + * * We also build a Relids set showing which outer rels are required by the * selected clauses. Any lateral_relids are included in that, but not * otherwise accounted for. @@ -831,6 +839,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, index_clauses = NIL; clause_columns = NIL; found_clause = false; + found_lower_saop_clause = false; outer_relids = bms_copy(rel->lateral_relids); for (indexcol = 0; indexcol < index->ncolumns; indexcol++) { @@ -846,6 +855,8 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, if (saop_control == SAOP_PER_AM && !index->amsearcharray) continue; found_clause = true; + if (indexcol > 0) + found_lower_saop_clause = true; } else { @@ -882,9 +893,11 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, /* * 2. Compute pathkeys describing index's ordering, if any, then see how * many of them are actually useful for this query. This is not relevant - * if we are only trying to build bitmap indexscans. + * if we are only trying to build bitmap indexscans, nor if we have to + * assume the scan is unordered. */ pathkeys_possibly_useful = (scantype != ST_BITMAPSCAN && + !found_lower_saop_clause && has_useful_pathkeys(root, rel)); index_is_ordered = (index->sortopfamily != NULL); if (index_is_ordered && pathkeys_possibly_useful) |