List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:April 27 2012 11:22am
Subject:bzr push into mysql-trunk branch (mattias.jonsson:3752 to 3754) Bug#11761652
View as plain text  
 3754 Mattias Jonsson	2012-04-27
      bug#11761652,
      pre-push fix of result file, due to changed error code.

    modified:
      mysql-test/suite/innodb/r/innodb_corrupt_bit.result
 3753 Mattias Jonsson	2012-04-26
      Bug#11761652: 54166: HA_RND_INIT() RESULT CODE NOT CHECKED
      Bug#11746399: 26040: RETURN VALUES OF HA_INDEX_INIT() AND
                                             INDEX_INIT() IGNORED
      
      Added checks for ha_rnd_init and ha_index_init return codes.
      
      Also added DBUG_ASSERT's to spot SE API violations.
      
      Changed InnoDB to return a more correct error in index_init.
      
      All this changes are done to enforce correct locking and cursor/handler
      usage by the server in debug mode.
      
      Updated according to reviewers comments.

    modified:
      mysql-test/suite/innodb/r/innodb_corrupt_bit.result
      mysql-test/suite/innodb/t/innodb_corrupt_bit.test
      sql/event_db_repository.cc
      sql/filesort.cc
      sql/ha_partition.cc
      sql/handler.cc
      sql/handler.h
      sql/item_subselect.cc
      sql/log_event.cc
      sql/log_event_old.cc
      sql/opt_range.cc
      sql/opt_sum.cc
      sql/sp.cc
      sql/sql_acl.cc
      sql/sql_executor.cc
      sql/sql_help.cc
      sql/sql_join_buffer.cc
      sql/sql_show.cc
      sql/sql_tmp_table.cc
      sql/sql_update.cc
      sql/tztime.cc
      storage/innobase/handler/ha_innodb.cc
 3752 Yasufumi Kinoshita	2012-04-27 [merge]
      Bug#11758510 (#50723): INNODB CHECK TABLE FATAL SEMAPHORE WAIT TIMEOUT POSSIBLY TOO SHORT FOR BI
      Fixed not to check timeout during the check table.

    modified:
      storage/innobase/dict/dict0load.cc
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/include/srv0srv.h
      storage/innobase/sync/sync0arr.cc
=== modified file 'mysql-test/suite/innodb/r/innodb_corrupt_bit.result'
--- a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result	revid:yasufumi.kinoshita@stripped238-3xbr6v0y4szr7bkq
+++ b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result	revid:mattias.jonsson@stripped120427093827-0156tdjcpts8h40s
@@ -40,13 +40,13 @@ test.corrupt_bit_test_─ü	check	Warning	I
 test.corrupt_bit_test_─ü	check	Warning	InnoDB: The B-tree of index "idxor	Corrupt
 select c from corrupt_bit_test_─ü;
-ERROR HY000: Incorrect key file for table 'corrupt_bit_test_─ü'; try to repair it
+ERROR HY000: Index corrupt_bit_test_─ü is corrupted
 select z from corrupt_bit_test_─t_test_─ü'; try to repair it
+ERROR HY000: Index corrupt_bit_test_─ü is corrupted
 show warnings;
 Level	Code	Message
 Warning	180	InnoDB: Index "idx─ô" for table "test"."corrupt_bit_test_─ü" is marked as corrupted
-Error	1034	Incorrect key file for table 'corrupt_bit_test_─ü'; try to repair it
+Error	1712	Index corrupt_bit_test_─ü is corrupted
 insert into corrupt_bit_test_─pt_bit_test_─ü use index(primary) where a = 10001;
 a	b	c	z
@@ -63,7 +63,7 @@ test.corrupt_bit_test_─ü	check	Warning	I
 test.corrupt_bit_test_─ü	check	error	Corrupt
 set names utf8;
 select z from corrupt_bit_test_─ü;
-ERROR HY000: Incorrect key file for table 'corrupt_bit_test_─ü'; try to repair it
+ERROR HY000: Index corrupt_bit_test_─ü is corrupted
 drop index idx─ô on corrupt_bit_test_─ü;
 select z from corrupt_bit_test_─b/t/innodb_corrupt_bit.test'
--- a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test	revid:mattias.jonsson@stripped
@@ -80,10 +80,10 @@ CREATE INDEX idx4 ON corrupt_bit_test_─ü
 check table corrupt_bit_test_─ü;
 
 # This selection intend to use the corrupted index. Expect to fail
--- error ER_NOT_KEYFILE
+-- error ER_INDEX_CORRUPT
 select c from corrupt_bit_test_─ü;
 
--- error ER_NOT_KEYFILE
+-- error ER_INDEX_CORRUPT
 select z from corrupt_bit_test_─ü;
 
 show warnings;
@@ -109,7 +109,7 @@ check table corrupt_bit_test_─ü;
 
 set names utf8;
 
--- error ER_NOT_KEYFILE
+-- error ER_INDEX_CORRUPT
 select z from corrupt_bit_test_─ü;
 
 # Drop the corrupted index

=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc	revid:yasufumi.kinoshita@stripped7104238-3xbr6v0y4szr7bkq
+++ b/sql/event_db_repository.cc	revid:mattias.jonsson@strippedpts8h40s
@@ -416,7 +416,11 @@ Event_db_repository::index_read_for_db_f
   DBUG_ENTER("Event_db_repository::index_read_for_db_for_i_s");
 
   DBUG_PRINT("info", ("Using prefix scanning on PK"));
-  event_table->file->ha_index_init(0, 1);
+  if ((ret= event_table->file->ha_index_init(0, 1)))
+  {
+    event_table->file->print_error(ret, MYF(0));
+    DBUG_RETURN(true);
+  }
   key_info= event_table->key_info;
 
   if (key_info->key_parts == 0 ||

=== modified file 'sql/filesort.cc'
--- a/sql/filesort.cc	revid:yasufumi.kinoshita@stripped7bkq
+++ b/sql/filesort.cc	revid:mattias.jonsson@strippedom-20120427093827-0156tdjcpts8h40s
@@ -658,7 +658,8 @@ static ha_rows find_all_keys(Sort_param 
   if (!quick_select)
   {
     next_pos=(uchar*) 0;			/* Find records in sequence */
-    file->ha_rnd_init(1);
+    if (file->ha_rnd_init(1))
+      DBUG_RETURN(HA_POS_ERROR);
     file->extra_opt(HA_EXTRA_CACHE,
 		    current_thd->variables.read_buff_size);
   }

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/ha_partition.cc	revid:mattias.jonsson@stripped7-0156tdjcpts8h40s
@@ -4631,7 +4631,6 @@ int ha_partition::index_init(uint inx, b
   file= m_file;
   do
   {
-    /* TODO RONM: Change to index_init() when code is stable */
     if (bitmap_is_set(&(m_part_info->read_partitions), (file - m_file)))
       if ((error= (*file)->ha_index_init(inx, sorted)))
       {
@@ -4670,7 +4669,6 @@ int ha_partition::index_end()
   do
   {
     int tmp;
-    /* TODO RONM: Change to index_end() when code is stable */
     if (bitmap_is_set(&(m_part_info->read_partitions), (file - m_file)))
       if ((tmp= (*file)->ha_index_end()))
         error= tmp;
@@ -7581,7 +7579,7 @@ void ha_partition::get_auto_increment(ul
       /* Only nb_desired_values = 1 makes sense */
       (*file)->get_auto_increment(offset, increment, 1,
                                  &first_value_part, &nb_reserved_values_part);
-      if (first_value_part == ~(ulonglong)(0)) // error in one partition
+      if (first_value_part == ULONGLONG_MAX) // error in one partition
       {
         *first_value= first_value_part;
         /* log that the error was between table/partition handler */

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/handler.cc	revid:mattias.jonsson@strippeddjcpts8h40s
@@ -2373,52 +2373,213 @@ int handler::ha_open(TABLE *table_arg, c
   DBUG_RETURN(error);
 }
 
+
+/**
+  Close handler.
+*/
+
 int handler::ha_close(void)
 {
+  DBUG_ENTER("handler::ha_close");
 #ifdef HAVE_PSI_TABLE_INTERFACE
   PSI_CALL(close_table)(m_psi);
   m_psi= NULL; /* instrumentation handle, invalid after close_table() */
 #endif
   DBUG_ASSERT(m_psi == NULL);
   DBUG_ASSERT(m_lock_type == F_UNLCK);
-  return close();
+  DBUG_ASSERT(inited == NONE);
+  DBUG_RETURN(close());
+}
+
+
+/**
+  Initialize use of index.
+
+  @param idx     Index to use
+  @param sorted  Use sorted order
+
+  @return Operation status
+    @retval 0     Success
+    @retval != 0  Error (error code returned)
+*/
+
+int handler::ha_index_init(uint idx, bool sorted)
+{
+  int result;
+  DBUG_ENTER("ha_index_init");
+  DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
+              m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == NONE);
+  if (!(result= index_init(idx, sorted)))
+    inited= INDEX;
+  end_range= NULL;
+  DBUG_RETURN(result);
+}
+
+
+/**
+  End use of index.
+
+  @return Operation status
+    @retval 0     Success
+    @retval != 0  Error (error code returned)
+*/
+
+int handler::ha_index_end()
+{
+  DBUG_ENTER("ha_index_end");
+  /* SQL HANDLER function can call this without having it locked. */
+  DBUG_ASSERT(table->open_by_handler ||
+              table_share->tmp_table != NO_TMP_TABLE ||
+              m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
+  inited= NONE;
+  end_range= NULL;
+  DBUG_RETURN(index_end());
+}
+
+
+/**
+  Initialize table for random read or scan.
+
+  @param scan  if true: Initialize for random scans through rnd_next()
+               if false: Initialize for random reads through rnd_pos()
+
+  @return Operation status
+    @retval 0     Success
+    @retval != 0  Error (error code returned)
+*/
+
+int handler::ha_rnd_init(bool scan)
+{
+  int result;
+  DBUG_ENTER("ha_rnd_init");
+  DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
+              m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == NONE || (inited == RND && scan));
+  inited= (result= rnd_init(scan)) ? NONE : RND;
+  end_range= NULL;
+  DBUG_RETURN(result);
 }
 
+
+/**
+  End use of random access.
+
+  @return Operation status
+    @retval 0     Success
+    @retval != 0  Error (error code returned)
+*/
+
+int handler::ha_rnd_end()
+{
+  DBUG_ENTER("ha_rnd_end");
+  /* SQL HANDLER function can call this without having it locked. */
+  DBUG_ASSERT(table->open_by_handler ||
+              table_share->tmp_table != NO_TMP_TABLE ||
+              m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == RND);
+  inited= NONE;
+  end_range= NULL;
+  DBUG_RETURN(rnd_end());
+}
+
+
+/**
+  Read next row via random scan.
+
+  @param buf  Buffer to read the row into
+
+  @return Operation status
+    @retval 0     Success
+    @retval != 0  Error (error code returned)
+*/
+
 int handler::ha_rnd_next(uchar *buf)
 {
   int result;
+  DBUG_ENTER("handler::ha_rnd_next");
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == RND);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
     { result= rnd_next(buf); })
-  return result;
+  DBUG_RETURN(result);
 }
 
+
+/**
+  Read row via random scan from position.
+
+  @param[out] buf  Buffer to read the row into
+  @param      pos  Position from position() call
+
+  @return Operation status
+    @retval 0     Success
+    @retval != 0  Error (error code returned)
+*/
+
 int handler::ha_rnd_pos(uchar *buf, uchar *pos)
 {
   int result;
+  DBUG_ENTER("handler::ha_rnd_pos");
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  /* TODO: Find out how to solve ha_rnd_pos when finding duplicate update. */
+  /* DBUG_ASSERT(inited == RND); */
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
     { result= rnd_pos(buf, pos); })
-  return result;
+  DBUG_RETURN(result);
 }
 
+
+/**
+  Read [part of] row via [part of] index.
+  @param[out] buf          buffer where store the data
+  @param      key          Key to search for
+  @param      keypart_map  Which part of key to use
+  @param      find_flag    Direction/condition on key usage
+
+  @returns Operation status
+    @retval  0                   Success (found a record, and function has
+                                 set table->status to 0)
+    @retval  HA_ERR_END_OF_FILE  Row not found (function has set table->status
+                                 to STATUS_NOT_FOUND)
+    @retval  != 0                Error
+
+  @note Positions an index cursor to the index specified in the handle.
+  Fetches the row if available. If the key value is null,
+  begin at the first key of the index.
+  ha_index_read_map can be restarted without calling index_end on the previous
+  index scan and without calling ha_index_init. In this case the
+  ha_index_read_map is on the same index as the previous ha_index_scan.
+  This is particularly used in conjunction with multi read ranges.
+*/
+
 int handler::ha_index_read_map(uchar *buf, const uchar *key,
                                key_part_map keypart_map,
                                enum ha_rkey_function find_flag)
 {
   int result;
+  DBUG_ENTER("handler::ha_index_read_map");
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_read_map(buf, key, keypart_map, find_flag); })
-  return result;
+  DBUG_RETURN(result);
 }
 
+
+/**
+  Initializes an index and read it.
+
+  @see handler::ha_index_read_map.
+*/
+
 int handler::ha_index_read_idx_map(uchar *buf, uint index, const uchar *key,
                                    key_part_map keypart_map,
                                    enum ha_rkey_function find_flag)
@@ -2433,84 +2594,186 @@ int handler::ha_index_read_idx_map(uchar
   return result;
 }
 
+
+/**
+  Reads the next row via index.
+
+  @param[out] buf  Row data
+
+  @return Operation status.
+    @retval  0                   Success
+    @retval  HA_ERR_END_OF_FILE  Row not found
+    @retval  != 0                Error
+*/
+
 int handler::ha_index_next(uchar * buf)
 {
   int result;
+  DBUG_ENTER("handler::ha_index_next");
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_next(buf); })
-  return result;
+  DBUG_RETURN(result);
 }
 
+
+/**
+  Reads the previous row via index.
+
+  @param[out] buf  Row data
+
+  @return Operation status.
+    @retval  0                   Success
+    @retval  HA_ERR_END_OF_FILE  Row not found
+    @retval  != 0                Error
+*/
+
 int handler::ha_index_prev(uchar * buf)
 {
   int result;
+  DBUG_ENTER("handler::ha_index_prev");
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_prev(buf); })
-  return result;
+  DBUG_RETURN(result);
 }
 
+
+/**
+  Reads the first row via index.
+
+  @param[out] buf  Row data
+
+  @return Operation status.
+    @retval  0                   Success
+    @retval  HA_ERR_END_OF_FILE  Row not found
+    @retval  != 0                Error
+*/
+
 int handler::ha_index_first(uchar * buf)
 {
   int result;
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_first(buf); })
   return result;
 }
 
+
+/**
+  Reads the last row via index.
+
+  @param[out] buf  Row data
+
+  @return Operation status.
+    @retval  0                   Success
+    @retval  HA_ERR_END_OF_FILE  Row not found
+    @retval  != 0                Error
+*/
+
 int handler::ha_index_last(uchar * buf)
 {
   int result;
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_last(buf); })
   return result;
 }
 
+
+/**
+  Reads the next same row via index.
+
+  @param[out] buf     Row data
+  @param      key     Key to search for
+  @param      keylen  Length of key
+
+  @return Operation status.
+    @retval  0                   Success
+    @retval  HA_ERR_END_OF_FILE  Row not found
+    @retval  != 0                Error
+*/
+
 int handler::ha_index_next_same(uchar *buf, const uchar *key, uint keylen)
 {
   int result;
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_next_same(buf, key, keylen); })
   return result;
 }
 
+
+
+/**
+  Read one row via index.
+
+  @param[out] buf        Row data
+  @param      key        Key to search for
+  @param      keylen     Length of key
+  @param      find_flag  Direction/condition on key usage
+
+  @return Operation status.
+    @retval  0                   Success
+    @retval  HA_ERR_END_OF_FILE  Row not found
+    @retval  != 0                Error
+*/
+
 int handler::ha_index_read(uchar *buf, const uchar *key, uint key_len,
                            enum ha_rkey_function find_flag)
 {
   int result;
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_read(buf, key, key_len, find_flag); })
   return result;
 }
 
+
+/**
+  Reads the last row via index.
+
+  @param[out] buf        Row data
+  @param      key        Key to search for
+  @param      keylen     Length of key
+
+  @return Operation status.
+    @retval  0                   Success
+    @retval  HA_ERR_END_OF_FILE  Row not found
+    @retval  != 0                Error
+*/
+
 int handler::ha_index_read_last(uchar *buf, const uchar *key, uint key_len)
 {
   int result;
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               m_lock_type != F_UNLCK);
+  DBUG_ASSERT(inited == INDEX);
 
   MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
     { result= index_read_last(buf, key, key_len); })
   return result;
 }
 
+
 /**
   Read first row (only) from a table.
 
@@ -2532,16 +2795,27 @@ int handler::read_first_row(uchar * buf,
   if (stats.deleted < 10 || primary_key >= MAX_KEY ||
       !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
   {
-    (void) ha_rnd_init(1);
-    while ((error= ha_rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
-    (void) ha_rnd_end();
+    if (!(error= ha_rnd_init(1)))
+    {
+      int end_error;
+      while ((error= ha_rnd_next(buf)) == HA_ERR_RECORD_DELETED)
+        /* skip deleted row */;
+      end_error= ha_rnd_end();
+      if (!error)
+        error= end_error;
+    }
   }
   else
   {
     /* Find the first row through the primary key */
-    (void) ha_index_init(primary_key, 0);
-    error= ha_index_first(buf);
-    (void) ha_index_end();
+    if (!(error= ha_index_init(primary_key, 0)))
+    {
+      int end_error;
+      error= ha_index_first(buf);
+      end_error= ha_index_end();
+      if (!error)
+        error= end_error;
+    }
   }
   DBUG_RETURN(error);
 }
@@ -2898,23 +3172,22 @@ void handler::column_bitmaps_signal()
 }
 
 
-/** @brief
+/**
   Reserves an interval of auto_increment values from the handler.
 
-  SYNOPSIS
-    get_auto_increment()
-    offset              
-    increment
-    nb_desired_values   how many values we want
-    first_value         (OUT) the first value reserved by the handler
-    nb_reserved_values  (OUT) how many values the handler reserved
+  @param       offset              offset (modulus increment)
+  @param       increment           increment between calls
+  @param       nb_desired_values   how many values we want
+  @param[out]  first_value         the first value reserved by the handler
+  @param[out]  nb_reserved_values  how many values the handler reserved
 
   offset and increment means that we want values to be of the form
   offset + N * increment, where N>=0 is integer.
-  If the function sets *first_value to ~(ulonglong)0 it means an error.
+  If the function sets *first_value to ULONGLONG_MAX it means an error.
   If the function sets *nb_reserved_values to ULONGLONG_MAX it means it has
   reserved to "positive infinite".
 */
+
 void handler::get_auto_increment(ulonglong offset, ulonglong increment,
                                  ulonglong nb_desired_values,
                                  ulonglong *first_value,
@@ -2922,12 +3195,20 @@ void handler::get_auto_increment(ulonglo
 {
   ulonglong nr;
   int error;
+  DBUG_ENTER("handler::get_auto_increment");
 
   (void) extra(HA_EXTRA_KEYREAD);
   table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
                                         table->read_set);
   column_bitmaps_signal();
-  index_init(table->s->next_number_index, 1);
+  if (ha_index_init(table->s->next_number_index, 1))
+  {
+    /* This should never happen, assert in debug, and fail in release build */
+    DBUG_ASSERT(0);
+    *first_value= ULONGLONG_MAX;
+    *nb_reserved_values= 0;
+    DBUG_VOID_RETURN;
+  }
   if (table->s->next_number_keypart == 0)
   {						// Autoincrement at key-start
     error= ha_index_last(table->record[1]);
@@ -2957,13 +3238,25 @@ void handler::get_auto_increment(ulonglo
   }
 
   if (error)
-    nr=1;
+  {
+    if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
+    {
+      /* No entry found, start with 1. */
+      nr= 1;
+    }
+    else
+    {
+      DBUG_ASSERT(0);
+      nr= ULONGLONG_MAX;
+    }
+  }
   else
     nr= ((ulonglong) table->next_number_field->
          val_int_offset(table->s->rec_buff_length)+1);
-  index_end();
+  ha_index_end();
   (void) extra(HA_EXTRA_NO_KEYREAD);
   *first_value= nr;
+  DBUG_VOID_RETURN;
 }
 
 
@@ -3603,6 +3896,43 @@ int handler::ha_repair(THD* thd, HA_CHEC
 
 
 /**
+  Start bulk insert.
+
+  Allow the handler to optimize for multiple row insert.
+
+  @param rows  Estimated rows to insert
+*/
+
+void handler::ha_start_bulk_insert(ha_rows rows)
+{
+  DBUG_ENTER("handler::ha_start_bulk_insert");
+  DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
+              m_lock_type == F_WRLCK);
+  estimation_rows_to_insert= rows;
+  start_bulk_insert(rows);
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  End bulk insert.
+
+  @return Operation status
+    @retval 0     Success
+    @retval != 0  Failure (error code returned)
+*/
+
+int handler::ha_end_bulk_insert()
+{
+  DBUG_ENTER("handler::ha_end_bulk_insert");
+  DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
+              m_lock_type == F_WRLCK);
+  estimation_rows_to_insert= 0;
+  DBUG_RETURN(end_bulk_insert());
+}
+
+
+/**
   Bulk update row: public interface.
 
   @sa handler::bulk_update_row()
@@ -6423,7 +6753,21 @@ int handler::ha_external_lock(THD *thd, 
   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
               ((lock_type != F_UNLCK && m_lock_type == F_UNLCK) ||
                lock_type == F_UNLCK));
-              
+  /* SQL HANDLER call locks/unlock while scanning (RND/INDEX). */
+  DBUG_ASSERT(inited == NONE || table->open_by_handler);
+#ifndef DBUG_OFF
+  /*
+    If this handler is cloned, then table->file is not this handler!
+    TODO: have an indicator in the handler to show that it is clone,
+    since table->file may point to ha_partition too...
+  */
+  if (table->key_read != 0 && table->file == this)
+  {
+    DBUG_PRINT("error", ("key_read != 0 (%d)", table->key_read));
+    table->key_read= 0;
+    DBUG_ASSERT(0);
+  }
+#endif
 
   if (MYSQL_HANDLER_RDLOCK_START_ENABLED() ||
       MYSQL_HANDLER_WRLOCK_START_ENABLED() ||

=== modified file 'sql/handler.h'
--- a/sql/handler.h	revid:yasufumi.kinoshita@stripped
+++ b/sql/handler.h	revid:mattias.jonsson@stripped20427093827-0156tdjcpts8h40s
@@ -96,7 +96,7 @@ enum enum_alter_inplace_result {
 */
 #define HA_REQUIRES_KEY_COLUMNS_FOR_DELETE (1 << 6)
 #define HA_NULL_IN_KEY         (1 << 7) /* One can have keys with NULL */
-#define HA_DUPLICATE_POS       (1 << 8)    /* ha_position() gives dup row */
+#define HA_DUPLICATE_POS       (1 << 8)    /* position() gives dup row */
 #define HA_NO_BLOBS            (1 << 9) /* Doesn't support blobs */
 #define HA_CAN_INDEX_BLOBS     (1 << 10)
 #define HA_AUTO_PART_KEY       (1 << 11) /* auto-increment in multi-part key */
@@ -1772,41 +1772,10 @@ public:
 
   int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
   int ha_close(void);
-  int ha_index_init(uint idx, bool sorted)
-  {
-    int result;
-    DBUG_ENTER("ha_index_init");
-    DBUG_ASSERT(inited==NONE);
-    if (!(result= index_init(idx, sorted)))
-      inited=INDEX;
-    end_range= NULL;
-    DBUG_RETURN(result);
-  }
-  int ha_index_end()
-  {
-    DBUG_ENTER("ha_index_end");
-    DBUG_ASSERT(inited==INDEX);
-    inited=NONE;
-    end_range= NULL;
-    DBUG_RETURN(index_end());
-  }
-  int ha_rnd_init(bool scan)
-  {
-    int result;
-    DBUG_ENTER("ha_rnd_init");
-    DBUG_ASSERT(inited==NONE || (inited==RND && scan));
-    inited= (result= rnd_init(scan)) ? NONE: RND;
-    end_range= NULL;
-    DBUG_RETURN(result);
-  }
-  int ha_rnd_end()
-  {
-    DBUG_ENTER("ha_rnd_end");
-    DBUG_ASSERT(inited==RND);
-    inited=NONE;
-    end_range= NULL;
-    DBUG_RETURN(rnd_end());
-  }
+  int ha_index_init(uint idx, bool sorted);
+  int ha_index_end();
+  int ha_rnd_init(bool scan);
+  int ha_rnd_end();
   int ha_rnd_next(uchar *buf);
   int ha_rnd_pos(uchar * buf, uchar *pos);
   int ha_index_read_map(uchar *buf, const uchar *key,
@@ -1850,16 +1819,8 @@ public:
   /** to be actually called to get 'check()' functionality*/
   int ha_check(THD *thd, HA_CHECK_OPT *check_opt);
   int ha_repair(THD* thd, HA_CHECK_OPT* check_opt);
-  void ha_start_bulk_insert(ha_rows rows)
-  {
-    estimation_rows_to_insert= rows;
-    start_bulk_insert(rows);
-  }
-  int ha_end_bulk_insert()
-  {
-    estimation_rows_to_insert= 0;
-    return end_bulk_insert();
-  }
+  void ha_start_bulk_insert(ha_rows rows);
+  int ha_end_bulk_insert();
   int ha_bulk_update_row(const uchar *old_data, uchar *new_data,
                          uint *dup_key_found);
   int ha_delete_all_rows();

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/item_subselect.cc	revid:mattias.jonsson@stripped-0156tdjcpts8h40s
@@ -2597,10 +2597,18 @@ bool subselect_indexsubquery_engine::sca
   // We never need to do a table scan of the materialized table.
   DBUG_ASSERT(engine_type() != HASH_SJ_ENGINE);
 
-  if (table->file->inited)
-    table->file->ha_index_end();
+  if (table->file->inited &&
+      (error= table->file->ha_index_end()))
+  {
+    (void) report_error(table, error);
+    DBUG_RETURN(true);
+  }
  
-  table->file->ha_rnd_init(1);
+  if ((error= table->file->ha_rnd_init(1)))
+  {
+    (void) report_error(table, error);
+    DBUG_RETURN(true);
+  }
   table->file->extra_opt(HA_EXTRA_CACHE,
                          current_thd->variables.read_buff_size);
   table->null_row= 0;
@@ -2841,8 +2849,12 @@ bool subselect_indexsubquery_engine::exe
     DBUG_RETURN(scan_result);
   }
 
-  if (!table->file->inited)
-    table->file->ha_index_init(tab->ref.key, !unique /* sorted */);
+  if (!table->file->inited &&
+      (error= table->file->ha_index_init(tab->ref.key, !unique /* sorted */)))
+  {
+    (void) report_error(table, error);
+    DBUG_RETURN(true);
+  }
   error= table->file->ha_index_read_map(table->record[0],
                                         tab->ref.key_buff,
                                         make_prev_keypart_map(tab->ref.key_parts),

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	revid:yasufumi.kinoshita@stripped
+++ b/sql/log_event.cc	revid:mattias.jonsson@stripped7-0156tdjcpts8h40s
@@ -10430,9 +10430,15 @@ Rows_log_event::write_row(const Relay_lo
       DBUG_PRINT("info",("Locating offending record using ha_rnd_pos()"));
 
       if (table->file->inited && (error= table->file->ha_index_end()))
-        DBUG_RETURN(error);
+      {
+        table->file->print_error(error, MYF(0));
+        goto error;
+      }
       if ((error= table->file->ha_rnd_init(FALSE)))
-        DBUG_RETURN(error);
+      {
+        table->file->print_error(error, MYF(0));
+        goto error;
+      }
 
       error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
 
@@ -11287,14 +11293,20 @@ TABLE_SCAN:
 
       case HA_ERR_END_OF_FILE:
         if (++restart_count < 2)
-          table->file->ha_rnd_init(1);
+        {
+          if ((error= table->file->ha_rnd_init(1)))
+          {
+            table->file->print_error(error, MYF(0));
+            goto err;
+          }
+        }
         break;
 
       default:
         DBUG_PRINT("info", ("Failed to get next record"
                             " (ha_rnd_next returns %d)",error));
         table->file->print_error(error, MYF(0));
-        table->file->ha_rnd_end();
+        (void) table->file->ha_rnd_end();
         goto err;
       }
     }

=== modified file 'sql/log_event_old.cc'
--- a/sql/log_event_old.cc	revid:yasufumi.kinoshita@stripped238-3xbr6v0y4szr7bkq
+++ b/sql/log_event_old.cc	revid:mattias.jonsson@stripped
@@ -729,7 +729,10 @@ static int find_and_fetch_row(TABLE *tab
     int error;
     /* We have a key: search the table using the index */
     if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE)))
+    {
+      table->file->print_error(error, MYF(0));
       DBUG_RETURN(error);
+    }
 
   /*
     Don't print debug messages when running valgrind since they can
@@ -827,7 +830,10 @@ static int find_and_fetch_row(TABLE *tab
 
     /* We don't have a key: search the table using ha_rnd_next() */
     if ((error= table->file->ha_rnd_init(1)))
+    {
+      table->file->print_error(error, MYF(0));
       return error;
+    }
 
     /* Continue until we find the right record or have made a full loop */
     do
@@ -850,14 +856,20 @@ static int find_and_fetch_row(TABLE *tab
         goto restart_ha_rnd_next;
 
       case HA_ERR_END_OF_FILE:
-  if (++restart_count < 2)
-    table->file->ha_rnd_init(1);
-  break;
+        if (++restart_count < 2)
+        {
+          if ((error= table->file->ha_rnd_init(1)))
+          {
+            table->file->print_error(error, MYF(0));
+            DBUG_RETURN(error);
+          }
+        }
+       break;
 
       default:
   table->file->print_error(error, MYF(0));
         DBUG_PRINT("info", ("Record not found"));
-        table->file->ha_rnd_end();
+        (void) table->file->ha_rnd_end();
   DBUG_RETURN(error);
       }
     }
@@ -2400,7 +2412,7 @@ int Old_rows_log_event::find_row(const R
           continue;
         DBUG_PRINT("info",("no record matching the given row found"));
         table->file->print_error(error, MYF(0));
-        table->file->ha_index_end();
+        (void) table->file->ha_index_end();
         DBUG_RETURN(error);
       }
     }
@@ -2441,7 +2453,13 @@ int Old_rows_log_event::find_row(const R
 
       case HA_ERR_END_OF_FILE:
         if (++restart_count < 2)
-          table->file->ha_rnd_init(1);
+        {
+          if ((error= table->file->ha_rnd_init(1)))
+          {
+            table->file->print_error(error, MYF(0));
+            DBUG_RETURN(error);
+          }
+        }
         break;
 
       default:

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/opt_range.cc	revid:mattias.jonsson@strippedjcpts8h40s
@@ -1326,7 +1326,7 @@ int QUICK_RANGE_SELECT::init()
 {
   DBUG_ENTER("QUICK_RANGE_SELECT::init");
 
-  if (file->inited != handler::NONE)
+  if (file->inited)
     file->ha_index_or_rnd_end();
   DBUG_RETURN(FALSE);
 }
@@ -1334,7 +1334,7 @@ int QUICK_RANGE_SELECT::init()
 
 void QUICK_RANGE_SELECT::range_end()
 {
-  if (file->inited != handler::NONE)
+  if (file->inited)
     file->ha_index_or_rnd_end();
 }
 
@@ -1585,6 +1585,7 @@ failure:
 */
 int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
 {
+  int error;
   List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
   QUICK_RANGE_SELECT* quick;
   DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan");
@@ -1598,8 +1599,8 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror
       There is no use of this->file. Use it for the first of merged range
       selects.
     */
-    if (quick->init_ror_merged_scan(TRUE))
-      DBUG_RETURN(1);
+    if ((error= quick->init_ror_merged_scan(TRUE)))
+      DBUG_RETURN(error);
     quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
   }
   while ((quick= quick_it++))
@@ -1608,8 +1609,8 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror
     const MY_BITMAP * const save_read_set= quick->head->read_set;
     const MY_BITMAP * const save_write_set= quick->head->write_set;
 #endif
-    if (quick->init_ror_merged_scan(FALSE))
-      DBUG_RETURN(1);
+    if ((error= quick->init_ror_merged_scan(FALSE)))
+      DBUG_RETURN(error);
     quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
     // Sets are shared by all members of "quick_selects" so must not change
     DBUG_ASSERT(quick->head->read_set == save_read_set);
@@ -1618,10 +1619,10 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror
     quick->record= head->record[0];
   }
 
-  if (need_to_fetch_row && head->file->ha_rnd_init(1))
+  if (need_to_fetch_row && (error= head->file->ha_rnd_init(1)))
   {
     DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
-    DBUG_RETURN(1);
+    DBUG_RETURN(error);
   }
   DBUG_RETURN(0);
 }
@@ -1677,7 +1678,7 @@ QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_I
   quick_selects.delete_elements();
   delete cpk_quick;
   free_root(&alloc,MYF(0));
-  if (need_to_fetch_row && head->file->inited != handler::NONE)
+  if (need_to_fetch_row && head->file->inited)
     head->file->ha_rnd_end();
   DBUG_VOID_RETURN;
 }
@@ -1781,8 +1782,8 @@ int QUICK_ROR_UNION_SELECT::reset()
   List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
   while ((quick= it++))
   {
-    if (quick->reset())
-      DBUG_RETURN(1);
+    if ((error= quick->reset()))
+      DBUG_RETURN(error);
     if ((error= quick->get_next()))
     {
       if (error == HA_ERR_END_OF_FILE)
@@ -1793,10 +1794,10 @@ int QUICK_ROR_UNION_SELECT::reset()
     queue_insert(&queue, (uchar*)quick);
   }
 
-  if (head->file->ha_rnd_init(1))
+  if ((error= head->file->ha_rnd_init(1)))
   {
     DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
-    DBUG_RETURN(1);
+    DBUG_RETURN(error);
   }
 
   DBUG_RETURN(0);
@@ -1814,7 +1815,7 @@ QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION
   DBUG_ENTER("QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT");
   delete_queue(&queue);
   quick_selects.delete_elements();
-  if (head->file->inited != handler::NONE)
+  if (head->file->inited)
     head->file->ha_rnd_end();
   free_root(&alloc,MYF(0));
   DBUG_VOID_RETURN;
@@ -9603,7 +9604,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_
       if (!cur_quick)
         break;
 
-      if (cur_quick->file->inited != handler::NONE) 
+      if (cur_quick->file->inited) 
         cur_quick->file->ha_index_end();
       if (cur_quick->init() || cur_quick->reset())
         DBUG_RETURN(1);
@@ -9852,7 +9853,7 @@ int QUICK_RANGE_SELECT::reset()
   last_range= NULL;
   cur_range= (QUICK_RANGE**) ranges.buffer;
 
-  if (file->inited == handler::NONE)
+  if (!file->inited)
   {
     if (in_ror_merged_scan)
       head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
@@ -12054,7 +12055,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::init()
 QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT()
 {
   DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT");
-  if (head->file->inited != handler::NONE) 
+  if (head->file->inited) 
     head->file->ha_index_end();
   if (min_max_arg_part)
     delete_dynamic(&min_max_ranges);

=== modified file 'sql/opt_sum.cc'
--- a/sql/opt_sum.cc	revid:yasufumi.kinoshita@stripped427104238-3xbr6v0y4szr7bkq
+++ b/sql/opt_sum.cc	revid:mattias.jonsson@stripped
@@ -415,7 +415,11 @@ int opt_sum_query(THD *thd,
             const_result= 0;
             break;
           }
-          table->file->ha_index_init((uint) ref.key, 1);
+          if ((error= table->file->ha_index_init((uint) ref.key, 1)))
+          {
+            table->file->print_error(error, MYF(0));
+            DBUG_RETURN(error);
+          }
 
           error= is_max ? 
                  get_index_max_value(table, &ref, range_fl) :

=== modified file 'sql/sp.cc'
--- a/sql/sp.cc	revid:yasufumi.kinoshita@stripped
+++ b/sql/sp.cc	revid:mattias.jonsson@stripped56tdjcpts8h40s
@@ -1470,7 +1470,12 @@ bool lock_db_routines(THD *thd, char *db
 
   table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
   key_len= table->key_info->key_part[0].store_length;
-  table->file->ha_index_init(0, 1);
+  if ((nxtres= table->file->ha_index_init(0, 1)))
+  {
+    table->file->print_error(nxtres, MYF(0));
+    close_system_tables(thd, &open_tables_state_backup);
+    DBUG_RETURN(true);
+  }
 
   if (! table->file->index_read_map(table->record[0],
                                     table->field[MYSQL_PROC_FIELD_DB]->ptr,
@@ -1534,7 +1539,11 @@ sp_drop_db_routines(THD *thd, char *db)
   key_len= table->key_info->key_part[0].store_length;
 
   ret= SP_OK;
-  table->file->ha_index_init(0, 1);
+  if (table->file->ha_index_init(0, 1))
+  {
+    ret= SP_KEY_NOT_FOUND;
+    goto err_idx_init;
+  }
   if (! table->file->ha_index_read_map(table->record[0],
                                        (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
                                        (key_part_map)1, HA_READ_KEY_EXACT))
@@ -1562,6 +1571,7 @@ sp_drop_db_routines(THD *thd, char *db)
   }
   table->file->ha_index_end();
 
+err_idx_init:
   close_thread_tables(thd);
   /*
     Make sure to only release the MDL lock on mysql.proc, not other

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	revid:yasufumi.kinoshita@stripped
+++ b/sql/sql_acl.cc	revid:mattias.jonsson@stripped427093827-0156tdjcpts8h40s
@@ -2675,7 +2675,13 @@ replace_proxies_priv_table(THD *thd, TAB
 
   get_grantor(thd, grantor);
 
-  table->file->ha_index_init(0, 1);
+  if ((error= table->file->ha_index_init(0, 1)))
+  {
+    table->file->print_error(error, MYF(0));
+    DBUG_PRINT("info", ("ha_index_init error"));
+    DBUG_RETURN(-1);
+  }
+
   if (table->file->ha_index_read_map(table->record[0], user_key,
                                      HA_WHOLE_KEY,
                                      HA_READ_KEY_EXACT))
@@ -2915,7 +2921,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TA
     key_copy(key, col_privs->record[0], col_privs->key_info, key_prefix_len);
     col_privs->field[4]->store("",0, &my_charset_latin1);
 
-    col_privs->file->ha_index_init(0, 1);
+    if (col_privs->file->ha_index_init(0, 1))
+    {
+      cols= 0;
+      return;
+    }
+
     if (col_privs->file->ha_index_read_map(col_privs->record[0], (uchar*) key,
                                            (key_part_map)15, HA_READ_KEY_EXACT))
     {
@@ -3073,7 +3084,11 @@ static int replace_column_table(GRANT_TA
 
   List_iterator <LEX_COLUMN> iter(columns);
   class LEX_COLUMN *column;
-  table->file->ha_index_init(0, 1);
+  if ((error= table->file->ha_index_init(0, 1)))
+  {
+    table->file->print_error(error, MYF(0));
+    DBUG_RETURN(-1);
+  }
   while ((column= iter++))
   {
     ulong privileges= column->rights;
@@ -4238,7 +4253,8 @@ static my_bool grant_load_procs_priv(TAB
   (void) my_hash_init(&func_priv_hash, &my_charset_utf8_bin,
                       0,0,0, (my_hash_get_key) get_grant_table,
                       0,0);
-  p_table->file->ha_index_init(0, 1);
+  if (p_table->file->ha_index_init(0, 1))
+    DBUG_RETURN(TRUE);
   p_table->use_all_columns();
 
   if (!p_table->file->ha_index_first(p_table->record[0]))
@@ -4339,7 +4355,8 @@ static my_bool grant_load(THD *thd, TABL
 
   t_table = tables[0].table;
   c_table = tables[1].table;
-  t_table->file->ha_index_init(0, 1);
+  if (t_table->file->ha_index_init(0, 1))
+    goto end_index_init;
   t_table->use_all_columns();
   c_table->use_all_columns();
 
@@ -4384,9 +4401,10 @@ static my_bool grant_load(THD *thd, TABL
   return_val=0;					// Return ok
 
 end_unlock:
-  thd->variables.sql_mode= old_sql_mode;
   t_table->file->ha_index_end();
   my_pthread_setspecific_ptr(THR_MALLOC, save_mem_root_ptr);
+end_index_init:
+  thd->variables.sql_mode= old_sql_mode;
   DBUG_RETURN(return_val);
 }
 

=== modified file 'sql/sql_executor.cc'
--- a/sql/sql_executor.cc	revid:yasufumi.kinoshita@stripped20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/sql_executor.cc	revid:mattias.jonsson@strippedpts8h40s
@@ -1594,7 +1594,13 @@ do_select(JOIN *join,List<Item> *fields,
     empty_record(table);
     if (table->group && join->tmp_table_param.sum_func_count &&
         table->s->keys && !table->file->inited)
-      table->file->ha_index_init(0, 0);
+    {
+      if ((rc= table->file->ha_index_init(0, 0)))
+      {
+        table->file->print_error(rc, MYF(0));
+        DBUG_RETURN(-1);
+      }
+    }
   }
   /* Set up select_end */
   Next_select_func end_select= setup_end_select_func(join);
@@ -2899,7 +2905,11 @@ join_read_key2(JOIN_TAB *tab, TABLE *tab
   if (!table->file->inited)
   {
     DBUG_ASSERT(!tab->sorted);  // Don't expect sort req. for single row.
-    table->file->ha_index_init(table_ref->key, tab->sorted);
+    if ((error= table->file->ha_index_init(table_ref->key, tab->sorted)))
+    {
+      (void) report_error(table, error);
+      return 1;
+    }
   }
 
   /*
@@ -2988,8 +2998,12 @@ join_read_always_key(JOIN_TAB *tab)
   TABLE *table= tab->table;
 
   /* Initialize the index first */
-  if (!table->file->inited)
-    table->file->ha_index_init(tab->ref.key, tab->sorted);
+  if (!table->file->inited &&
+      (error= table->file->ha_index_init(tab->ref.key, tab->sorted)))
+  {
+    (void) report_error(table, error);
+    return 1;
+  }
 
   /* Perform "Late NULLs Filtering" (see internals manual for explanations) */
   TABLE_REF *ref= &tab->ref;
@@ -3025,8 +3039,12 @@ join_read_last_key(JOIN_TAB *tab)
   int error;
   TABLE *table= tab->table;
 
-  if (!table->file->inited)
-    table->file->ha_index_init(tab->ref.key, tab->sorted);
+  if (!table->file->inited &&
+      (error= table->file->ha_index_init(tab->ref.key, tab->sorted)))
+  {
+    (void) report_error(table, error);
+    return 1;
+  }
   if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
     return -1;
   if ((error=table->file->index_read_last_map(table->record[0],
@@ -3199,8 +3217,12 @@ join_read_first(JOIN_TAB *tab)
   tab->read_record.record=table->record[0];
   tab->read_record.read_record=join_read_next;
 
-  if (!table->file->inited)
-    table->file->ha_index_init(tab->index, tab->sorted);
+  if (!table->file->inited &&
+      (error= table->file->ha_index_init(tab->index, tab->sorted)))
+  {
+    (void) report_error(table, error);
+    return 1;
+  }
   if ((error= tab->table->file->ha_index_first(tab->table->record[0])))
   {
     if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
@@ -3233,8 +3255,12 @@ join_read_last(JOIN_TAB *tab)
   tab->read_record.table=table;
   tab->read_record.index=tab->index;
   tab->read_record.record=table->record[0];
-  if (!table->file->inited)
-    table->file->ha_index_init(tab->index, tab->sorted);
+  if (!table->file->inited &&
+      (error= table->file->ha_index_init(tab->index, tab->sorted)))
+  {
+    (void) report_error(table, error);
+    return 1;
+  }
   if ((error= tab->table->file->ha_index_last(tab->table->record[0])))
     return report_error(table, error);
   return 0;
@@ -3257,8 +3283,12 @@ join_ft_read_first(JOIN_TAB *tab)
   int error;
   TABLE *table= tab->table;
 
-  if (!table->file->inited)
-    table->file->ha_index_init(tab->ref.key, tab->sorted);
+  if (!table->file->inited &&
+      (error= table->file->ha_index_init(tab->ref.key, tab->sorted)))
+  {
+    (void) report_error(table, error);
+    return 1;
+  }
   table->file->ft_init();
 
   if ((error= table->file->ft_read(table->record[0])))
@@ -3749,7 +3779,11 @@ end_update(JOIN *join, JOIN_TAB *join_ta
 				error, FALSE, NULL))
       DBUG_RETURN(NESTED_LOOP_ERROR);            // Not a table_is_full error
     /* Change method to update rows */
-    table->file->ha_index_init(0, 0);
+    if ((error= table->file->ha_index_init(0, 0)))
+    {
+      table->file->print_error(error, MYF(0));
+      DBUG_RETURN(NESTED_LOOP_ERROR);
+    }
     join->join_tab[join->tables-1].next_select=end_unique_update;
   }
   join->send_records++;
@@ -4178,7 +4212,8 @@ static int remove_dup_with_compare(THD *
   org_record=(char*) (record=table->record[0])+offset;
   new_record=(char*) table->record[1]+offset;
 
-  file->ha_rnd_init(1);
+  if ((error= file->ha_rnd_init(1)))
+    goto err;
   error=file->ha_rnd_next(record);
   for (;;)
   {
@@ -4306,7 +4341,8 @@ static int remove_dup_with_hash_index(TH
     DBUG_RETURN(1);
   }
 
-  file->ha_rnd_init(1);
+  if ((error= file->ha_rnd_init(1)))
+    goto err;
   key_pos=key_buffer;
   for (;;)
   {
@@ -4364,7 +4400,8 @@ err:
   my_free(key_buffer);
   my_hash_free(&hash);
   file->extra(HA_EXTRA_NO_CACHE);
-  (void) file->ha_rnd_end();
+  if (file->inited)
+    (void) file->ha_rnd_end();
   if (error)
     file->print_error(error,MYF(0));
   DBUG_RETURN(1);

=== modified file 'sql/sql_help.cc'
--- a/sql/sql_help.cc	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/sql_help.cc	revid:mattias.jonsson@stripped6tdjcpts8h40s
@@ -302,8 +302,17 @@ int get_topics_for_keyword(THD *thd, TAB
   rtopic_id= find_fields[help_relation_help_topic_id].field;
   rkey_id=   find_fields[help_relation_help_keyword_id].field;
 
-  topics->file->ha_index_init(iindex_topic,1);
-  relations->file->ha_index_init(iindex_relations,1);
+  if (topics->file->ha_index_init(iindex_topic, 1))
+  {
+    my_message(ER_CORRUPT_HELP_DB, ER(ER_CORRUPT_HELP_DB), MYF(0));
+    DBUG_RETURN(-1);
+  }
+  if (relations->file->ha_index_init(iindex_relations, 1))
+  {
+    topics->file->ha_index_end();
+    my_message(ER_CORRUPT_HELP_DB, ER(ER_CORRUPT_HELP_DB), MYF(0));
+    DBUG_RETURN(-1);
+  }
 
   rkey_id->store((longlong) key_id, TRUE);
   rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW);

=== modified file 'sql/sql_join_buffer.cc'
--- a/sql/sql_join_buffer.cc	revid:yasufumi.kinoshita@strippedkq
+++ b/sql/sql_join_buffer.cc	revid:mattias.jonsson@oracle.com-20120427093827-0156tdjcpts8h40s
@@ -2400,8 +2400,9 @@ JOIN_CACHE_BKA::init_join_matching_recor
     Prepare to iterate over keys from the join buffer and to get
     matching candidates obtained with MMR handler functions.
   */ 
-  if (!file->inited)
-    file->ha_index_init(join_tab->ref.key, 1);
+  if (!file->inited &&
+      (error= file->ha_index_init(join_tab->ref.key, 1)))
+    return NESTED_LOOP_ERROR;
   if ((error= file->multi_range_read_init(seq_funcs, (void*) this, ranges,
 					  mrr_mode, &mrr_buff)))
     rc= error < 0 ? NESTED_LOOP_NO_MORE_ROWS: NESTED_LOOP_ERROR;

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/sql_show.cc	revid:mattias.jonsson@strippedjcpts8h40s
@@ -5254,7 +5254,11 @@ int fill_schema_proc(THD *thd, TABLE_LIS
   {
     DBUG_RETURN(1);
   }
-  proc_table->file->ha_index_init(0, 1);
+  if (proc_table->file->ha_index_init(0, 1))
+  {
+    res= 1;
+    goto err;
+  }
   if ((res= proc_table->file->ha_index_first(proc_table->record[0])))
   {
     res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
@@ -5280,7 +5284,8 @@ int fill_schema_proc(THD *thd, TABLE_LIS
   }
 
 err:
-  proc_table->file->ha_index_end();
+  if (proc_table->file->inited)
+    (void) proc_table->file->ha_index_end();
   close_system_tables(thd, &open_tables_state_backup);
   DBUG_RETURN(res);
 }

=== modified file 'sql/sql_tmp_table.cc'
--- a/sql/sql_tmp_table.cc	revid:yasufumi.kinoshita@stripped04238-3xbr6v0y4szr7bkq
+++ b/sql/sql_tmp_table.cc	revid:mattias.jonsson@stripped
@@ -1918,7 +1918,7 @@ bool create_myisam_from_heap(THD *thd, T
   TABLE new_table;
   TABLE_SHARE share;
   const char *save_proc_info;
-  int write_err;
+  int write_err= 0;
   DBUG_ENTER("create_myisam_from_heap");
 
   if (table->s->db_type() != heap_hton || 
@@ -1974,7 +1974,12 @@ bool create_myisam_from_heap(THD *thd, T
   if (table->file->indexes_are_disabled())
     new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
   table->file->ha_index_or_rnd_end();
-  table->file->ha_rnd_init(1);
+  if ((write_err= table->file->ha_rnd_init(1)))
+  {
+    table->file->print_error(write_err, MYF(ME_FATALERROR));
+    write_err= 0;
+    goto err;
+  }
   if (table->no_rows)
   {
     new_table.file->extra(HA_EXTRA_NO_ROWS);
@@ -2053,9 +2058,13 @@ bool create_myisam_from_heap(THD *thd, T
   DBUG_RETURN(0);
 
  err:
-  DBUG_PRINT("error",("Got error: %d",write_err));
-  table->file->print_error(write_err, MYF(0));
-  (void) table->file->ha_rnd_end();
+  if (write_err)
+  {
+    DBUG_PRINT("error",("Got error: %d",write_err));
+    new_table.file->print_error(write_err, MYF(0));
+  }
+  if (table->file->inited)
+    (void) table->file->ha_rnd_end();
   (void) new_table.file->ha_close();
  err1:
   new_table.file->ha_delete_table(new_table.s->table_name.str);

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	revid:yasufumi.kinoshita@oracle.com-20120427104238-3xbr6v0y4szr7bkq
+++ b/sql/sql_update.cc	revid:mattias.jonsson@strippeddjcpts8h40s
@@ -2165,7 +2165,8 @@ int multi_update::do_updates()
     org_updated= updated;
     tmp_table= tmp_tables[cur_table->shared];
     tmp_table->file->extra(HA_EXTRA_CACHE);	// Change to read cache
-    (void) table->file->ha_rnd_init(0);
+    if ((local_error= table->file->ha_rnd_init(0)))
+      goto err;
     table->file->extra(HA_EXTRA_NO_CACHE);
 
     check_opt_it.rewind();
@@ -2290,11 +2291,16 @@ err:
   }
 
 err2:
-  (void) table->file->ha_rnd_end();
-  (void) tmp_table->file->ha_rnd_end();
+  if (table->file->inited)
+    (void) table->file->ha_rnd_end();
+  if (tmp_table->file->inited)
+    (void) tmp_table->file->ha_rnd_end();
   check_opt_it.rewind();
   while (TABLE *tbl= check_opt_it++)
-      tbl->file->ha_rnd_end();
+  {
+    if (tbl->file->inited)
+      (void) tbl->file->ha_rnd_end();
+  }
 
   if (updated != org_updated)
   {

=== modified file 'sql/tztime.cc'
--- a/sql/tztime.cc	revid:yasufumi.kinoshita@stripped238-3xbr6v0y4szr7bkq
+++ b/sql/tztime.cc	revid:mattias.jonsson@stripped
@@ -1701,12 +1701,9 @@ my_tz_init(THD *org_thd, const char *def
   }
 
   table= tz_tables[0].table;
-  /*
-    It is OK to ignore ha_index_init()/ha_index_end() return values since
-    mysql.time_zone* tables are MyISAM and these operations always succeed
-    for MyISAM.
-  */
-  (void)table->file->ha_index_init(0, 1);
+
+  if (table->file->ha_index_init(0, 1))
+    goto end_with_close;
   table->use_all_columns();
 
   tz_leapcnt= 0;
@@ -1894,12 +1891,9 @@ tz_load_from_open_tables(const String *t
   tz_tables= tz_tables->next_local;
   table->field[0]->store(tz_name->ptr(), tz_name->length(),
                          &my_charset_latin1);
-  /*
-    It is OK to ignore ha_index_init()/ha_index_end() return values since
-    mysql.time_zone* tables are MyISAM and these operations always succeed
-    for MyISAM.
-  */
-  (void)table->file->ha_index_init(0, 1);
+
+  if (table->file->ha_index_init(0, 1))
+    goto end;
 
   if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr,
                                      HA_WHOLE_KEY, HA_READ_KEY_EXACT))
@@ -1927,7 +1921,8 @@ tz_load_from_open_tables(const String *t
   table= tz_tables->table;
   tz_tables= tz_tables->next_local;
   table->field[0]->store((longlong) tzid, TRUE);
-  (void)table->file->ha_index_init(0, 1);
+  if (table->file->ha_index_init(0, 1))
+    goto end;
 
   if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr,
                                      HA_WHOLE_KEY, HA_READ_KEY_EXACT))
@@ -1954,7 +1949,8 @@ tz_load_from_open_tables(const String *t
   table= tz_tables->table;
   tz_tables= tz_tables->next_local;
   table->field[0]->store((longlong) tzid, TRUE);
-  (void)table->file->ha_index_init(0, 1);
+  if (table->file->ha_index_init(0, 1))
+    goto end;
 
   res= table->file->ha_index_read_map(table->record[0], table->field[0]->ptr,
                                       (key_part_map)1, HA_READ_KEY_EXACT);
@@ -2025,7 +2021,8 @@ tz_load_from_open_tables(const String *t
   */
   table= tz_tables->table; 
   table->field[0]->store((longlong) tzid, TRUE);
-  (void)table->file->ha_index_init(0, 1);
+  if (table->file->ha_index_init(0, 1))
+    goto end;
 
   res= table->file->ha_index_read_map(table->record[0], table->field[0]->ptr,
                                       (key_part_map)1, HA_READ_KEY_EXACT);
@@ -2160,8 +2157,8 @@ tz_load_from_open_tables(const String *t
 
 end:
 
-  if (table)
-    (void)table->file->ha_index_end();
+  if (table && table->file->inited)
+    (void) table->file->ha_index_end();
 
   DBUG_RETURN(return_val);
 }

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	revid:yasufumi.kinoshita@strippedxbr6v0y4szr7bkq
+++ b/storage/innobase/handler/ha_innodb.cc	revid:mattias.jonsson@strippedjcpts8h40s
@@ -7362,7 +7362,7 @@ ha_innobase::change_active_index(
 				"InnoDB: Index %s for table %s is"
 				" marked as corrupted",
 				index_name, table_name);
-			DBUG_RETURN(1);
+			DBUG_RETURN(HA_ERR_INDEX_CORRUPT);
 		} else {
 			push_warning_printf(
 				user_thd, Sql_condition::WARN_LEVEL_WARN,
@@ -7373,7 +7373,7 @@ ha_innobase::change_active_index(
 
 		/* The caller seems to ignore this.  Thus, we must check
 		this again in row_search_for_mysql(). */
-		DBUG_RETURN(2);
+		DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED);
 	}
 
 	ut_a(prebuilt->search_tuple != 0);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (mattias.jonsson:3752 to 3754) Bug#11761652Mattias Jonsson27 Apr