Skip to content

Commit 4d4b286

Browse files
committed
MDEV-20056 Assertion `!prebuilt->index->is_primary()' failed
in row_search_idx_cond_check When usage of rowid filter is evaluated by the optimizer to join a table to the current partial join employing a certain index it should be checked that a key for at least the major component of this index can be constructed using values from the columns of the partial join.
1 parent b6f7ec6 commit 4d4b286

File tree

3 files changed

+137
-1
lines changed

3 files changed

+137
-1
lines changed

mysql-test/main/rowid_filter_innodb.result

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,3 +2245,79 @@ a
22452245
5
22462246
DROP TABLE t1;
22472247
SET GLOBAL innodb_stats_persistent= @stats.save;
2248+
#
2249+
# MDEV-20056: index to build range filter should not be
2250+
# the same as table access index
2251+
#
2252+
SET @stats.save= @@innodb_stats_persistent;
2253+
SET GLOBAL innodb_stats_persistent= ON;
2254+
CREATE TABLE t1 (ch varchar(1), id int, id2 int) ENGINE=InnoDB;
2255+
INSERT INTO t1 VALUES
2256+
('l',3,2), ('e',NULL,NULL), ('r',7,3), ('h',NULL,2), (NULL,4,4), ('c',4,NULL),
2257+
('k',NULL,NULL), ('h',NULL,NULL), ('b',9,NULL), ('f',6,NULL);
2258+
CREATE TABLE t2 (
2259+
pk int NOT NULL, col_date_key date, ch2 varchar(1), id2 int,
2260+
PRIMARY KEY (pk), KEY (col_date_key), KEY (ch2), KEY (id2)
2261+
) ENGINE=InnoDB;
2262+
INSERT INTO t2 VALUES
2263+
(1,'2034-04-21','g',9), (2,'2006-09-08','y',1), (3,NULL,'h',2),
2264+
(4,'1987-03-02','s',2), (5,'2019-07-02','u',NULL),(6,'2012-12-18','z',1),
2265+
(7,NULL,'w',4), (8,'2005-03-10','o',8), (9,'1987-02-12','d',4);
2266+
CREATE TABLE t3 (id int) ENGINE=InnoDB;
2267+
INSERT INTO t3 VALUES (6);
2268+
ANALYZE TABLE t1,t2,t3;
2269+
Table Op Msg_type Msg_text
2270+
test.t1 analyze status Engine-independent statistics collected
2271+
test.t1 analyze status OK
2272+
test.t2 analyze status Engine-independent statistics collected
2273+
test.t2 analyze status OK
2274+
test.t3 analyze status Engine-independent statistics collected
2275+
test.t3 analyze status OK
2276+
EXPLAIN EXTENDED SELECT 1 FROM t3
2277+
WHERE EXISTS ( SELECT 1 FROM t1
2278+
WHERE t3.id IN ( SELECT bt1.id FROM t2, t1 AS bt1
2279+
WHERE bt1.id = t2.pk AND
2280+
t2.ch2 <= 'g' ) OR
2281+
t1.id2 = t1.id);
2282+
id select_type table type possible_keys key key_len ref rows filtered Extra
2283+
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 100.00 Using where
2284+
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 10 100.00 Using where
2285+
3 MATERIALIZED t2 range PRIMARY,col_date_key,ch2,id2 ch2 4 NULL 2 100.00 Using where; Using index
2286+
3 MATERIALIZED bt1 ALL NULL NULL NULL NULL 10 100.00 Using where; Using join buffer (flat, BNL join)
2287+
Warnings:
2288+
Note 1276 Field or reference 'test.t3.id' of SELECT #2 was resolved in SELECT #1
2289+
Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where <in_optimizer>(1,<expr_cache><`test`.`t3`.`id`>(exists(/* select#2 */ select 1 from `test`.`t1` where <expr_cache><`test`.`t3`.`id`>(<in_optimizer>(`test`.`t3`.`id`,`test`.`t3`.`id` in ( <materialize> (/* select#3 */ select `test`.`bt1`.`id` from `test`.`t2` join `test`.`t1` `bt1` where `test`.`bt1`.`id` = `test`.`t2`.`pk` and `test`.`t2`.`ch2` <= 'g' ), <primary_index_lookup>(`test`.`t3`.`id` in <temporary table> on distinct_key where `test`.`t3`.`id` = `<subquery3>`.`id`)))) or `test`.`t1`.`id2` = `test`.`t1`.`id` limit 1)))
2290+
SELECT 1 FROM t3
2291+
WHERE EXISTS ( SELECT 1 FROM t1
2292+
WHERE t3.id IN ( SELECT bt1.id FROM t2, t1 AS bt1
2293+
WHERE bt1.id = t2.pk AND
2294+
t2.ch2 <= 'g' ) OR
2295+
t1.id2 = t1.id);
2296+
1
2297+
1
2298+
EXPLAIN EXTENDED SELECT 1 FROM t3
2299+
WHERE EXISTS ( SELECT 1 FROM t1
2300+
WHERE t3.id IN ( SELECT bt1.id FROM t2, t1 AS bt1
2301+
WHERE bt1.ch = t2.ch2 AND
2302+
bt1.id = t2.pk AND
2303+
t2.ch2 <= 'g' ) OR
2304+
t1.id2 = t1.id);
2305+
id select_type table type possible_keys key key_len ref rows filtered Extra
2306+
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 100.00 Using where
2307+
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 10 100.00 Using where
2308+
3 MATERIALIZED t2 range PRIMARY,col_date_key,ch2,id2 ch2 4 NULL 2 100.00 Using where; Using index
2309+
3 MATERIALIZED bt1 ALL NULL NULL NULL NULL 10 100.00 Using where; Using join buffer (flat, BNL join)
2310+
Warnings:
2311+
Note 1276 Field or reference 'test.t3.id' of SELECT #2 was resolved in SELECT #1
2312+
Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where <in_optimizer>(1,<expr_cache><`test`.`t3`.`id`>(exists(/* select#2 */ select 1 from `test`.`t1` where <expr_cache><`test`.`t3`.`id`>(<in_optimizer>(`test`.`t3`.`id`,`test`.`t3`.`id` in ( <materialize> (/* select#3 */ select `test`.`bt1`.`id` from `test`.`t2` join `test`.`t1` `bt1` where `test`.`bt1`.`ch` = `test`.`t2`.`ch2` and `test`.`bt1`.`id` = `test`.`t2`.`pk` and `test`.`t2`.`ch2` <= 'g' ), <primary_index_lookup>(`test`.`t3`.`id` in <temporary table> on distinct_key where `test`.`t3`.`id` = `<subquery3>`.`id`)))) or `test`.`t1`.`id2` = `test`.`t1`.`id` limit 1)))
2313+
SELECT 1 FROM t3
2314+
WHERE EXISTS ( SELECT 1 FROM t1
2315+
WHERE t3.id IN ( SELECT bt1.id FROM t2, t1 AS bt1
2316+
WHERE bt1.ch = t2.ch2 AND
2317+
bt1.id = t2.pk AND
2318+
t2.ch2 <= 'g' ) OR
2319+
t1.id2 = t1.id);
2320+
1
2321+
1
2322+
DROP TABLE t1, t2, t3;
2323+
SET GLOBAL innodb_stats_persistent= @stats.save;

mysql-test/main/rowid_filter_innodb.test

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,56 @@ SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a;
129129

130130
DROP TABLE t1;
131131
SET GLOBAL innodb_stats_persistent= @stats.save;
132+
133+
--echo #
134+
--echo # MDEV-20056: index to build range filter should not be
135+
--echo # the same as table access index
136+
--echo #
137+
138+
SET @stats.save= @@innodb_stats_persistent;
139+
SET GLOBAL innodb_stats_persistent= ON;
140+
141+
CREATE TABLE t1 (ch varchar(1), id int, id2 int) ENGINE=InnoDB;
142+
INSERT INTO t1 VALUES
143+
('l',3,2), ('e',NULL,NULL), ('r',7,3), ('h',NULL,2), (NULL,4,4), ('c',4,NULL),
144+
('k',NULL,NULL), ('h',NULL,NULL), ('b',9,NULL), ('f',6,NULL);
145+
146+
CREATE TABLE t2 (
147+
pk int NOT NULL, col_date_key date, ch2 varchar(1), id2 int,
148+
PRIMARY KEY (pk), KEY (col_date_key), KEY (ch2), KEY (id2)
149+
) ENGINE=InnoDB;
150+
INSERT INTO t2 VALUES
151+
(1,'2034-04-21','g',9), (2,'2006-09-08','y',1), (3,NULL,'h',2),
152+
(4,'1987-03-02','s',2), (5,'2019-07-02','u',NULL),(6,'2012-12-18','z',1),
153+
(7,NULL,'w',4), (8,'2005-03-10','o',8), (9,'1987-02-12','d',4);
154+
155+
CREATE TABLE t3 (id int) ENGINE=InnoDB;
156+
INSERT INTO t3 VALUES (6);
157+
158+
ANALYZE TABLE t1,t2,t3;
159+
160+
let $q1=
161+
SELECT 1 FROM t3
162+
WHERE EXISTS ( SELECT 1 FROM t1
163+
WHERE t3.id IN ( SELECT bt1.id FROM t2, t1 AS bt1
164+
WHERE bt1.id = t2.pk AND
165+
t2.ch2 <= 'g' ) OR
166+
t1.id2 = t1.id);
167+
168+
eval EXPLAIN EXTENDED $q1;
169+
eval $q1;
170+
171+
let $q2=
172+
SELECT 1 FROM t3
173+
WHERE EXISTS ( SELECT 1 FROM t1
174+
WHERE t3.id IN ( SELECT bt1.id FROM t2, t1 AS bt1
175+
WHERE bt1.ch = t2.ch2 AND
176+
bt1.id = t2.pk AND
177+
t2.ch2 <= 'g' ) OR
178+
t1.id2 = t1.id);
179+
180+
eval EXPLAIN EXTENDED $q2;
181+
eval $q2;
182+
183+
DROP TABLE t1, t2, t3;
184+
SET GLOBAL innodb_stats_persistent= @stats.save;

sql/sql_select.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,12 @@ bool JOIN::make_range_rowid_filters()
16381638
{
16391639
if (!tab->range_rowid_filter_info)
16401640
continue;
1641+
1642+
DBUG_ASSERT(!(tab->ref.key >= 0 &&
1643+
tab->ref.key == (int) tab->range_rowid_filter_info->key_no));
1644+
DBUG_ASSERT(!(tab->ref.key == -1 && tab->quick &&
1645+
tab->quick->index == tab->range_rowid_filter_info->key_no));
1646+
16411647
int err;
16421648
SQL_SELECT *sel= NULL;
16431649
Rowid_filter_container *filter_container= NULL;
@@ -7701,7 +7707,8 @@ best_access_path(JOIN *join,
77017707
found_ref);
77027708
} /* not ft_key */
77037709

7704-
if (records < DBL_MAX)
7710+
if (records < DBL_MAX &&
7711+
(found_part & 1)) // start_key->key can be used for index access
77057712
{
77067713
double rows= record_count * records;
77077714
double access_cost_factor= MY_MIN(tmp / rows, 1.0);

0 commit comments

Comments
 (0)