From: Mattias Jonsson Date: April 25 2012 12:37pm Subject: bzr push into mysql-trunk branch (mattias.jonsson:3739 to 3740) Bug#13008220 List-Archive: http://lists.mysql.com/commits/143658 X-Bug: 13008220 Message-Id: <201204251237.q3PCbLkw001852@acsmt357.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3740 Mattias Jonsson 2012-04-23 Bug#13008220: HANDLER SQL STATEMENT CAN MISS TO INITIALIZE FOR RANDOM READ When doing index scans and then swithing to random scans, without restart, ha_rnd_init is not called, when using the HANDLER SQL interface. Fixed by ensuring that when switching between index and random scans there will always be a call to ha_index/rnd_end and then ha_index/rnd_init. Also checking return values from ha_index/rnd_init/end. (updated with DBUG_ASSERT from reviewers suggestion). modified: mysql-test/include/handler.inc mysql-test/r/handler_innodb.result mysql-test/r/handler_myisam.result mysql-test/t/handler_myisam.test sql/sql_handler.cc 3739 Vasil Dimov 2012-04-25 Non-functional change: fix the names of DICT_STAT_PERSISTEN_ON/OFF macros modified: storage/innobase/include/dict0mem.h storage/innobase/include/dict0stats.ic === modified file 'mysql-test/include/handler.inc' --- a/mysql-test/include/handler.inc revid:vasil.dimov@stripped +++ b/mysql-test/include/handler.inc revid:mattias.jonsson@stripped @@ -1839,3 +1839,34 @@ HANDLER t1 READ FIRST WHERE f1() = 1; HANDLER t1 CLOSE; DROP FUNCTION f1; DROP TABLE t1; + +--echo # +--echo # Bug#13008220 HANDLER SQL STATEMENT CAN MISS TO INITIALIZE +--echo # FOR RANDOM READ +--echo # + +CREATE TABLE t1(a INT, b INT, KEY b(b)); +INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30); +HANDLER t1 OPEN; +HANDLER t1 READ b FIRST; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ b FIRST; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ FIRST; +HANDLER t1 READ b FIRST; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 CLOSE; +DROP TABLE t1; === modified file 'mysql-test/r/handler_innodb.result' --- a/mysql-test/r/handler_innodb.result revid:vasil.dimov@stripped +++ b/mysql-test/r/handler_innodb.result revid:mattias.jonsson@stripped @@ -1744,3 +1744,70 @@ ERROR 42000: This version of MySQL doesn HANDLER t1 CLOSE; DROP FUNCTION f1; DROP TABLE t1; +# +# Bug#13008220 HANDLER SQL STATEMENT CAN MISS TO INITIALIZE +# FOR RANDOM READ +# +CREATE TABLE t1(a INT, b INT, KEY b(b)); +INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30); +HANDLER t1 OPEN; +HANDLER t1 READ b FIRST; +a b +1 10 +HANDLER t1 READ NEXT; +a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ b FIRST; +a b +1 10 +HANDLER t1 READ b NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +3 30 +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ b FIRST; +a b +1 10 +HANDLER t1 READ NEXT; +a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ NEXT; +a b +4 40 +HANDLER t1 READ NEXT; +a b +3 30 +HANDLER t1 READ NEXT; +a b +HANDLER t1 READ b NEXT; +a b +1 10 +HANDLER t1 READ b NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +3 30 +HANDLER t1 READ b NEXT; +a b +4 40 +HANDLER t1 READ b NEXT; +a b +HANDLER t1 READ NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +1 10 +HANDLER t1 CLOSE; +DROP TABLE t1; === modified file 'mysql-test/r/handler_myisam.result' --- a/mysql-test/r/handler_myisam.result revid:vasil.dimov@stripped +++ b/mysql-test/r/handler_myisam.result revid:mattias.jonsson@stripped @@ -1741,6 +1741,73 @@ HANDLER t1 CLOSE; DROP FUNCTION f1; DROP TABLE t1; # +# Bug#13008220 HANDLER SQL STATEMENT CAN MISS TO INITIALIZE +# FOR RANDOM READ +# +CREATE TABLE t1(a INT, b INT, KEY b(b)); +INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30); +HANDLER t1 OPEN; +HANDLER t1 READ b FIRST; +a b +1 10 +HANDLER t1 READ NEXT; +a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ b FIRST; +a b +1 10 +HANDLER t1 READ b NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +3 30 +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ b FIRST; +a b +1 10 +HANDLER t1 READ NEXT; +a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ NEXT; +a b +4 40 +HANDLER t1 READ NEXT; +a b +3 30 +HANDLER t1 READ NEXT; +a b +HANDLER t1 READ b NEXT; +a b +1 10 +HANDLER t1 READ b NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +3 30 +HANDLER t1 READ b NEXT; +a b +4 40 +HANDLER t1 READ b NEXT; +a b +HANDLER t1 READ NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +1 10 +HANDLER t1 CLOSE; +DROP TABLE t1; +# # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash # CREATE TABLE t1 AS SELECT 1 AS f1; @@ -1820,6 +1887,12 @@ HANDLER t1 READ b NEXT; a b HANDLER t1 READ NEXT; a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ NEXT; +a b 4 40 HANDLER t1 READ NEXT; a b === modified file 'mysql-test/t/handler_myisam.test' --- a/mysql-test/t/handler_myisam.test revid:vasil.dimov@stripped +++ b/mysql-test/t/handler_myisam.test revid:mattias.jonsson@stripped @@ -78,6 +78,8 @@ HANDLER t1 READ b NEXT; HANDLER t1 READ NEXT; HANDLER t1 READ NEXT; HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; HANDLER t1 CLOSE; HANDLER t1 OPEN; === modified file 'sql/sql_handler.cc' --- a/sql/sql_handler.cc revid:vasil.dimov@stripped +++ b/sql/sql_handler.cc revid:mattias.jonsson@stripped @@ -668,18 +668,19 @@ retry: { switch (mode) { case RNEXT: - if (table->file->inited != handler::NONE) + if (m_key_name) { - if (m_key_name) + if (table->file->inited == handler::INDEX) { /* Check if we read from the same index. */ DBUG_ASSERT((uint) keyno == table->file->get_index()); error= table->file->ha_index_next(table->record[0]); + break; } - else - { - error= table->file->ha_rnd_next(table->record[0]); - } + } + else if (table->file->inited == handler::RND) + { + error= table->file->ha_rnd_next(table->record[0]); break; } /* else fall through */ @@ -687,8 +688,8 @@ retry: if (m_key_name) { table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno, 1); - error= table->file->ha_index_first(table->record[0]); + if (!(error= table->file->ha_index_init(keyno, 1))) + error= table->file->ha_index_first(table->record[0]); } else { @@ -702,7 +703,7 @@ retry: DBUG_ASSERT(m_key_name != 0); /* Check if we read from the same index. */ DBUG_ASSERT((uint) keyno == table->file->get_index()); - if (table->file->inited != handler::NONE) + if (table->file->inited == handler::INDEX) { error= table->file->ha_index_prev(table->record[0]); break; @@ -710,15 +711,22 @@ retry: /* else fall through */ case RLAST: DBUG_ASSERT(m_key_name != 0); - table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno, 1); - error= table->file->ha_index_last(table->record[0]); + if (!(error= table->file->ha_index_or_rnd_end()) && + !(error= table->file->ha_index_init(keyno, 1))) + error= table->file->ha_index_last(table->record[0]); mode=RPREV; break; case RNEXT_SAME: /* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */ DBUG_ASSERT(m_key_name != 0); - error= table->file->ha_index_next_same(table->record[0], key, key_len); + /* Continue scan, or start a new scan if no previous index scan */ + if (table->file->inited == handler::INDEX || + (!(error= table->file->ha_index_or_rnd_end()) && + !(error= table->file->ha_index_init(keyno, 1)))) + { + DBUG_ASSERT((uint) keyno == table->file->get_index()); + error= table->file->ha_index_next_same(table->record[0], key, key_len); + } break; case RKEY: { @@ -755,11 +763,12 @@ retry: if (!(key= (uchar*) thd->calloc(ALIGN_SIZE(key_len)))) goto err; - table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno, 1); + if ((error= table->file->ha_index_or_rnd_end())) + break; key_copy(key, table->record[0], table->key_info + keyno, key_len); - error= table->file->ha_index_read_map(table->record[0], - key, keypart_map, m_rkey_mode); + if (!(error= table->file->ha_index_init(keyno, 1))) + error= table->file->ha_index_read_map(table->record[0], + key, keypart_map, m_rkey_mode); mode=rkey_to_rnext[(int)m_rkey_mode]; break; } No bundle (reason: useless for push emails).