From 6d14cae604d064ec5cd8141bfd05408cc41bf134 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 12 Aug 2010 15:59:02 +0500 Subject: [PATCH 1/2] Bug#55146 Assertion `m_part_spec.start_part == m_part_spec.end_part' in index_read_idx_map As we check for the impossible partitions earlier, it's possible that we don't find any suitable partitions at all. So this assertion just has to be corrected for this case. per-file comments: mysql-test/r/partition_innodb.result Bug#55146 Assertion `m_part_spec.start_part == m_part_spec.end_part' in index_read_idx_map test result updated. mysql-test/t/partition_innodb.test Bug#55146 Assertion `m_part_spec.start_part == m_part_spec.end_part' in index_read_idx_map test case added. sql/ha_partition.cc Bug#55146 Assertion `m_part_spec.start_part == m_part_spec.end_part' in index_read_idx_map Assertion changed to '>=' as the prune_partition_set() in the get_partition_set() can do start_part= end_part+1 if no possible partitions were found. --- mysql-test/r/partition_innodb.result | 6 ++++++ mysql-test/t/partition_innodb.test | 13 +++++++++++++ sql/ha_partition.cc | 8 ++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 2a04aafe554..98104310227 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -387,3 +387,9 @@ a b 3 2003-03-03 COMMIT; DROP TABLE t1; +CREATE TABLE t1 (i1 int NOT NULL primary key, f1 int) ENGINE = InnoDB +PARTITION BY HASH(i1) PARTITIONS 2; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1 WHERE i1 = ( SELECT i1 FROM t1 WHERE f1=0 LIMIT 1 ); +i1 f1 +DROP TABLE t1; diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index e1ac7b4c7eb..cef3540f9a7 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -401,3 +401,16 @@ connection default; SELECT * FROM t1; COMMIT; DROP TABLE t1; + +# +# Bug #55146 Assertion `m_part_spec.start_part == m_part_spec.end_part' in index_read_idx_map +# + +CREATE TABLE t1 (i1 int NOT NULL primary key, f1 int) ENGINE = InnoDB + PARTITION BY HASH(i1) PARTITIONS 2; + +INSERT INTO t1 VALUES (1,1), (2,2); + +SELECT * FROM t1 WHERE i1 = ( SELECT i1 FROM t1 WHERE f1=0 LIMIT 1 ); + +DROP TABLE t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index a87c7fbf7b8..dea889663d1 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4242,8 +4242,12 @@ int ha_partition::index_read_idx_map(uchar *buf, uint index, get_partition_set(table, buf, index, &m_start_key, &m_part_spec); - /* How can it be more than one partition with the current use? */ - DBUG_ASSERT(m_part_spec.start_part == m_part_spec.end_part); + /* + We have either found exactly 1 partition + (in which case start_part == end_part) + or no matching partitions (start_part > end_part) + */ + DBUG_ASSERT(m_part_spec.start_part >= m_part_spec.end_part); for (part= m_part_spec.start_part; part <= m_part_spec.end_part; part++) { From 428f0bdefbf866f0a9939e4153393b1e4b8a1a82 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 16 Sep 2010 11:01:06 +0200 Subject: [PATCH 2/2] Bug#56287: mysql5.1.50 crash when using Partition datetime in sub in query When having a sub query in partitioned innodb one could make the partitioning engine to search for a 'index_next_same' on a partition that had not been initialized. Problem was that the subselect function looks at table->status which was not set in the partitioning handler when it skipped scanning due to no matching partitions found. Fixed by setting table->status = STATUS_NOT_FOUND when there was no partitions to scan. (If there are partitions to scan, it will be set in the partitions handler.) mysql-test/r/partition_innodb.result: added result mysql-test/t/partition_innodb.test: added test sql/ha_partition.cc: set table status to not found, if there ar no partitions to scan. --- mysql-test/r/partition_innodb.result | 26 ++++++++++++++++++++++++++ mysql-test/t/partition_innodb.test | 24 ++++++++++++++++++++++++ sql/ha_partition.cc | 2 ++ 3 files changed, 52 insertions(+) diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 2a04aafe554..950eb5de3d8 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -1,5 +1,31 @@ drop table if exists t1, t2; # +# Bug#56287: crash when using Partition datetime in sub in query +# +CREATE TABLE t1 +(c1 bigint(20) unsigned NOT NULL AUTO_INCREMENT, +c2 varchar(40) not null default '', +c3 datetime not NULL, +PRIMARY KEY (c1,c3), +KEY partidx(c3)) +ENGINE=InnoDB +PARTITION BY RANGE (TO_DAYS(c3)) +(PARTITION p200912 VALUES LESS THAN (to_days('2010-01-01')), +PARTITION p201103 VALUES LESS THAN (to_days('2011-04-01')), +PARTITION p201912 VALUES LESS THAN MAXVALUE); +insert into t1(c2,c3) values ("Test row",'2010-01-01 00:00:00'); +SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test'; +PARTITION_NAME TABLE_ROWS +p200912 0 +p201103 1 +p201912 0 +SELECT count(*) FROM t1 p where c3 in +(select c3 from t1 t where t.c3 < date '2011-04-26 19:19:44' + and t.c3 > date '2011-04-26 19:18:44') ; +count(*) +0 +DROP TABLE t1; +# # Bug#51830: Incorrect partition pruning on range partition (regression) # CREATE TABLE t1 (a INT NOT NULL) diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index e1ac7b4c7eb..ca668d77199 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -7,6 +7,30 @@ drop table if exists t1, t2; let $MYSQLD_DATADIR= `SELECT @@datadir`; +--echo # +--echo # Bug#56287: crash when using Partition datetime in sub in query +--echo # +CREATE TABLE t1 +(c1 bigint(20) unsigned NOT NULL AUTO_INCREMENT, + c2 varchar(40) not null default '', + c3 datetime not NULL, + PRIMARY KEY (c1,c3), + KEY partidx(c3)) +ENGINE=InnoDB +PARTITION BY RANGE (TO_DAYS(c3)) +(PARTITION p200912 VALUES LESS THAN (to_days('2010-01-01')), + PARTITION p201103 VALUES LESS THAN (to_days('2011-04-01')), + PARTITION p201912 VALUES LESS THAN MAXVALUE); + +insert into t1(c2,c3) values ("Test row",'2010-01-01 00:00:00'); + +SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'test'; +SELECT count(*) FROM t1 p where c3 in +(select c3 from t1 t where t.c3 < date '2011-04-26 19:19:44' + and t.c3 > date '2011-04-26 19:18:44') ; + +DROP TABLE t1; + --echo # --echo # Bug#51830: Incorrect partition pruning on range partition (regression) --echo # diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 624ef1aff5b..d3846db42c2 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4483,6 +4483,7 @@ int ha_partition::partition_scan_set_up(uchar * buf, bool idx_read_flag) key not found. */ DBUG_PRINT("info", ("scan with no partition to scan")); + table->status= STATUS_NOT_FOUND; DBUG_RETURN(HA_ERR_END_OF_FILE); } if (m_part_spec.start_part == m_part_spec.end_part) @@ -4507,6 +4508,7 @@ int ha_partition::partition_scan_set_up(uchar * buf, bool idx_read_flag) if (start_part == MY_BIT_NONE) { DBUG_PRINT("info", ("scan with no partition to scan")); + table->status= STATUS_NOT_FOUND; DBUG_RETURN(HA_ERR_END_OF_FILE); } if (start_part > m_part_spec.start_part)