aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-02-10 22:51:32 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2019-02-10 22:51:32 -0500
commit6bdc3005b54fc9c6ef27cd4e64edd548315f57ba (patch)
tree139cf0fbb94554bee8fda56cbc10c5a9067738f9 /src
parent72d71e03563b6c295b257040e324793a30162042 (diff)
downloadpostgresql-6bdc3005b54fc9c6ef27cd4e64edd548315f57ba.tar.gz
postgresql-6bdc3005b54fc9c6ef27cd4e64edd548315f57ba.zip
Fix indexable-row-comparison logic to account for covering indexes.
indxpath.c needs a good deal more attention for covering indexes than it's gotten. But so far as I can tell, the only really awful breakage is in expand_indexqual_rowcompare (nee adjust_rowcompare_for_index), which was only half fixed in c266ed31a. The other problems aren't bad enough to take the risk of a just-before-wrap fix. The problem here is that if the leading column of a row comparison matches an index (allowing this code to be reached), and some later column doesn't match the index, it'll nonetheless believe that that column matches the first included index column. Typically that'll lead to an error like "operator M is not a member of opfamily N" as a result of fetching a garbage opfamily OID. But with enough bad luck, maybe a broken plan would be generated. Discussion: https://postgr.es/m/25526.1549847928@sss.pgh.pa.us
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/path/indxpath.c4
-rw-r--r--src/test/regress/expected/index_including.out17
-rw-r--r--src/test/regress/sql/index_including.sql3
3 files changed, 22 insertions, 2 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 51d2da56832..c03777ed607 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3979,7 +3979,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
break; /* no good, volatile comparison value */
/*
- * The Var side can match any column of the index.
+ * The Var side can match any key column of the index.
*/
for (i = 0; i < index->nkeycolumns; i++)
{
@@ -3991,7 +3991,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
break;
}
- if (i >= index->ncolumns)
+ if (i >= index->nkeycolumns)
break; /* no match found */
/* Add column number to returned list */
diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out
index 16b4be34de3..f86e5953fac 100644
--- a/src/test/regress/expected/index_including.out
+++ b/src/test/regress/expected/index_including.out
@@ -127,6 +127,23 @@ INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) A
ERROR: null value in column "c2" violates not-null constraint
DETAIL: Failing row contains (1, null, 3, (4,4),(4,4)).
INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,10) AS x;
+explain (costs off)
+select * from tbl where (c1,c2,c3) < (2,5,1);
+ QUERY PLAN
+------------------------------------------------
+ Bitmap Heap Scan on tbl
+ Filter: (ROW(c1, c2, c3) < ROW(2, 5, 1))
+ -> Bitmap Index Scan on covering
+ Index Cond: (ROW(c1, c2) <= ROW(2, 5))
+(4 rows)
+
+select * from tbl where (c1,c2,c3) < (2,5,1);
+ c1 | c2 | c3 | c4
+----+----+----+----
+ 1 | 2 | |
+ 2 | 4 | |
+(2 rows)
+
DROP TABLE tbl;
CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box,
UNIQUE(c1,c2) INCLUDE(c3,c4));
diff --git a/src/test/regress/sql/index_including.sql b/src/test/regress/sql/index_including.sql
index ef5fd882f53..2c6dd6211e6 100644
--- a/src/test/regress/sql/index_including.sql
+++ b/src/test/regress/sql/index_including.sql
@@ -73,6 +73,9 @@ SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conre
INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x;
INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x;
INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,10) AS x;
+explain (costs off)
+select * from tbl where (c1,c2,c3) < (2,5,1);
+select * from tbl where (c1,c2,c3) < (2,5,1);
DROP TABLE tbl;
CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box,