List:Commits« Previous MessageNext Message »
From:Konstantin Osipov Date:August 16 2008 9:36pm
Subject:bzr commit into mysql-6.0-runtime branch (konstantin:2700) WL#3288
View as plain text  
#At file:///opt/local/work/mysql-6.0-records/

 2700 Konstantin Osipov	2008-08-16
      WL#3288, work in progress.
modified:
  BUILD/SETUP.sh
  mysql-test/include/mix1.inc
  sql/event_db_repository.cc
  sql/events.cc
  sql/item_subselect.cc
  sql/mysql_priv.h
  sql/opt_range.cc
  sql/records.cc
  sql/records.h
  sql/sql_acl.cc
  sql/sql_delete.cc
  sql/sql_help.cc
  sql/sql_plugin.cc
  sql/sql_select.cc
  sql/sql_select.h
  sql/sql_servers.cc
  sql/sql_table.cc
  sql/sql_udf.cc
  sql/sql_update.cc

=== modified file 'BUILD/SETUP.sh'
--- a/BUILD/SETUP.sh	2008-07-25 17:21:55 +0000
+++ b/BUILD/SETUP.sh	2008-08-16 19:36:24 +0000
@@ -105,7 +105,7 @@ if [ "x$warning_mode" != "xpedantic" ]; 
   cxx_warnings="$cxx_warnings -Wreorder"
   cxx_warnings="$cxx_warnings -Wctor-dtor-privacy -Wnon-virtual-dtor"
 # Added unless --with-debug=full
-  debug_extra_cflags="-O1 -Wuninitialized"
+  debug_extra_cflags="-O0"
 else
   warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE"
   c_warnings="$warnings"

=== modified file 'mysql-test/include/mix1.inc'
--- a/mysql-test/include/mix1.inc	2008-07-17 19:55:18 +0000
+++ b/mysql-test/include/mix1.inc	2008-08-16 19:36:24 +0000
@@ -941,7 +941,7 @@ drop table t1;
 
 #
 # Bug #28570: handler::index_read() is called with different find_flag when 
-# ORDER BY is used
+# ORDER BY is use
 #
 
 CREATE TABLE t1 (

=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc	2008-07-17 19:55:18 +0000
+++ b/sql/event_db_repository.cc	2008-08-16 19:36:24 +0000
@@ -452,7 +452,8 @@ Event_db_repository::table_scan_all_for_
   READ_RECORD read_record_info;
   DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
 
-  init_read_record(&read_record_info, thd, event_table, NULL, 1, 0, FALSE);
+  if (init_read_record(&read_record_info, thd, event_table, NULL, 1, 0, FALSE))
+    DBUG_RETURN(TRUE);
 
   /*
     rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
@@ -461,7 +462,7 @@ Event_db_repository::table_scan_all_for_
   */
   do
   {
-    ret= read_record_info.read_record(&read_record_info);
+    ret= read_record_info.read_record();
     if (ret == 0)
       ret= copy_event_to_schema_table(thd, schema_table, event_table);
   } while (ret == 0);
@@ -925,9 +926,11 @@ Event_db_repository::drop_events_by_fiel
   if (open_event_table(thd, TL_WRITE, &table))
     DBUG_VOID_RETURN;
 
+  if (init_read_record(&read_record_info, thd, table, NULL, 1, 0, FALSE))
+    DBUG_VOID_RETURN; /* Out of resources. */
+
   /* only enabled events are in memory, so we go now and delete the rest */
-  init_read_record(&read_record_info, thd, table, NULL, 1, 0, FALSE);
-  while (!ret && !(read_record_info.read_record(&read_record_info)) )
+  while (!ret && !(read_record_info.read_record()) )
   {
     char *et_field= get_field(thd->mem_root, table->field[field]);
 

=== modified file 'sql/events.cc'
--- a/sql/events.cc	2008-08-07 17:52:43 +0000
+++ b/sql/events.cc	2008-08-16 19:36:24 +0000
@@ -1118,8 +1118,9 @@ Events::load_events_from_db(THD *thd)
     DBUG_RETURN(TRUE);
   }
 
-  init_read_record(&read_record_info, thd, table, NULL, 0, 1, FALSE);
-  while (!(read_record_info.read_record(&read_record_info)))
+  if (init_read_record(&read_record_info, thd, table, NULL, 0, 1, FALSE))
+    DBUG_RETURN(TRUE); /* Out of resources. */
+  while (!(read_record_info.read_record()))
   {
     Event_queue_element *et;
     bool created;

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2008-07-24 10:00:56 +0000
+++ b/sql/item_subselect.cc	2008-08-16 19:36:24 +0000
@@ -2283,17 +2283,20 @@ int subselect_single_select_engine::exec
         {
           for (uint i= 0; i < tab->ref.key_parts; i++)
           {
-            bool *cond_guard= tab->ref.cond_guards[i];
+            bool *cond_guard= tab->ref.cond_guard.guard_list[i];
             if (cond_guard && !*cond_guard)
             {
-              /* Change the access method to full table scan */
-              tab->save_read_first_record= tab->read_first_record;
-              tab->save_read_record= tab->read_record.read_record;
-              tab->read_record.read_record= rr_sequential;
+              READ_RECORD *full_scan_info= &tab->ref.cond_guard.full_scan_info;
+              if (! full_scan_info->is_initialized())
+              {
+                full_scan_info->set_read_record_func(tab->table, rr_sequential);
+                full_scan_info->ref_length= tab->table->file->ref_length;
+                full_scan_info->print_error= tab->read_record.print_error;
+                tab->ref.cond_guard.save_read_first_record= tab->read_first_record;
+              }
               tab->read_first_record= read_first_record_seq;
-              tab->read_record.record= tab->table->record[0];
-              tab->read_record.thd= join->thd;
-              tab->read_record.ref_length= tab->table->file->ref_length;
+              full_scan_info->swap(tab->read_record);
+
               *(last_changed_tab++)= tab;
               break;
             }
@@ -2301,17 +2304,15 @@ int subselect_single_select_engine::exec
         }
       }
     }
-    
+
     join->exec();
 
     /* Enable the optimizations back */
     for (JOIN_TAB **ptab= changed_tabs; ptab != last_changed_tab; ptab++)
     {
       JOIN_TAB *tab= *ptab;
-      tab->read_record.record= 0;
-      tab->read_record.ref_length= 0;
-      tab->read_first_record= tab->save_read_first_record; 
-      tab->read_record.read_record= tab->save_read_record;
+      tab->read_record.swap(tab->ref.cond_guard.full_scan_info);
+      tab->read_first_record= tab->ref.cond_guard.save_read_first_record;
     }
     executed= 1;
     thd->where= save_where;

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2008-08-11 12:40:09 +0000
+++ b/sql/mysql_priv.h	2008-08-16 19:36:24 +0000
@@ -2267,12 +2267,6 @@ ulonglong get_datetime_value(THD *thd, I
 
 int test_if_number(char *str,int *res,bool allow_wildcards);
 void change_byte(uchar *,uint,char,char);
-void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
-		      SQL_SELECT *select, int use_record_cache, 
-                      bool print_errors, bool disable_rr_cache);
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, 
-                          bool print_error, uint idx);
-void end_read_record(READ_RECORD *info);
 ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
 		 uint s_length, SQL_SELECT *select,
 		 ha_rows max_rows, bool sort_positions,

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2008-07-17 19:55:18 +0000
+++ b/sql/opt_range.cc	2008-08-16 19:36:24 +0000
@@ -1177,7 +1177,6 @@ QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_ME
   DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT");
   index= MAX_KEY;
   head= table;
-  bzero(&read_record, sizeof(read_record));
   init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
   DBUG_VOID_RETURN;
 }
@@ -1215,6 +1214,7 @@ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_M
   QUICK_RANGE_SELECT* quick;
   DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT");
   quick_it.rewind();
+  end_read_record(&read_record);
   while ((quick= quick_it++))
     quick->file= NULL;
   quick_selects.delete_elements();
@@ -8109,7 +8109,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_
   doing_pk_scan= FALSE;
   /* index_merge currently doesn't support "using index" at all */
   file->extra(HA_EXTRA_NO_KEYREAD);
-  init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE);
+  if (init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE))
+    DBUG_RETURN(1);
   DBUG_RETURN(result);
 }
 
@@ -8131,7 +8132,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
   if (doing_pk_scan)
     DBUG_RETURN(pk_quick_select->get_next());
 
-  if ((result= read_record.read_record(&read_record)) == -1)
+  if ((result= read_record.read_record()) == -1)
   {
     result= HA_ERR_END_OF_FILE;
     end_read_record(&read_record);

=== modified file 'sql/records.cc'
--- a/sql/records.cc	2008-08-11 12:40:09 +0000
+++ b/sql/records.cc	2008-08-16 19:36:24 +0000
@@ -25,8 +25,34 @@
 */
 
 #include "records.h"
+
 #include "mysql_priv.h"
 
+void READ_RECORD::clear_read_record()
+{
+  bzero(this, sizeof(*this));
+}
+
+
+void READ_RECORD::set_read_record_func(TABLE *table_arg, Read_func read_func)
+{
+  DBUG_ASSERT(m_is_initialized == FALSE);
+  table= table_arg;
+  file= table->file;
+  record= table->record[0];
+  thd= table->in_use;
+  m_read_record= read_func;
+  m_is_initialized= TRUE;
+}
+
+
+void READ_RECORD::swap(READ_RECORD &other)
+{
+  READ_RECORD tmp(other);
+  other= *this;
+  *this= tmp;
+  tmp.m_is_initialized= FALSE; /* prevent the assert */
+}
 
 static int rr_quick(READ_RECORD *info);
 int rr_sequential(READ_RECORD *info);
@@ -34,9 +60,11 @@ static int rr_from_tempfile(READ_RECORD 
 static int rr_unpack_from_tempfile(READ_RECORD *info);
 static int rr_unpack_from_buffer(READ_RECORD *info);
 static int rr_from_pointers(READ_RECORD *info);
+#ifdef NOT_USED
 static int rr_from_cache(READ_RECORD *info);
 static int init_rr_cache(THD *thd, READ_RECORD *info);
 static int rr_cmp(uchar *a,uchar *b);
+#endif
 static int rr_index_first(READ_RECORD *info);
 static int rr_index(READ_RECORD *info);
 
@@ -57,21 +85,19 @@ static int rr_index(READ_RECORD *info);
   @param idx          index to scan
 */
 
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
-                          bool print_error, uint idx)
+bool 
+init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+                     bool print_error, uint idx)
 {
   empty_record(table);
-  bzero((char*) info,sizeof(*info));
-  info->table= table;
-  info->file=  table->file;
-  info->record= table->record[0];
   info->print_error= print_error;
 
   table->status=0;			/* And it's always found */
   if (!table->file->inited)
     table->file->ha_index_init(idx, 1);
   /* read_record will be changed to rr_index in rr_index_first */
-  info->read_record= rr_index_first;
+  info->set_read_record_func(table, rr_index_first);
+  return FALSE;
 }
 
 
@@ -160,7 +186,9 @@ void init_read_record_idx(READ_RECORD *i
     This is the most basic access method of a table using rnd_init,
     rnd_next and rnd_end. No indexes are used.
 */
-void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
+
+bool
+init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
 		      SQL_SELECT *select,
 		      int use_record_cache, bool print_error, 
                       bool disable_rr_cache)
@@ -168,16 +196,10 @@ void init_read_record(READ_RECORD *info,
   IO_CACHE *tempfile;
   DBUG_ENTER("init_read_record");
 
-  bzero((char*) info,sizeof(*info));
-  info->thd=thd;
-  info->table=table;
-  info->file= table->file;
-  info->forms= &info->table;		/* Only one table */
-  
   if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
       !table->sort.addon_field)
     (void) table->file->extra(HA_EXTRA_MMAP);
-  
+
   if (table->sort.addon_field)
   {
     info->rec_buf= table->sort.addon_buf;
@@ -186,10 +208,8 @@ void init_read_record(READ_RECORD *info,
   else
   {
     empty_record(table);
-    info->record= table->record[0];
     info->ref_length= table->file->ref_length;
   }
-  info->select=select;
   info->print_error=print_error;
   info->ignore_not_found_rows= 0;
   table->status=0;			/* And it's always found */
@@ -201,8 +221,9 @@ void init_read_record(READ_RECORD *info,
   if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
   {
     DBUG_PRINT("info",("using rr_from_tempfile"));
-    info->read_record= (table->sort.addon_field ?
-                        rr_unpack_from_tempfile : rr_from_tempfile);
+    info->set_read_record_func(table,
+                               table->sort.addon_field ?
+                               rr_unpack_from_tempfile : rr_from_tempfile);
     info->io_cache=tempfile;
     reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
     info->ref_pos=table->file->ref;
@@ -229,17 +250,24 @@ void init_read_record(READ_RECORD *info,
 	!table->s->blob_fields &&
         info->ref_length <= MAX_REFLENGTH)
     {
+      DBUG_ASSERT(0); /* The condition above is impossible. */
+      /* Leave the read type unchanged in production. */
+#ifdef NOT_USED
       if (! init_rr_cache(thd, info))
       {
 	DBUG_PRINT("info",("using rr_from_cache"));
-	info->read_record=rr_from_cache;
+	info->set_read_record_func(table, rr_from_cache);
       }
+#endif
     }
   }
   else if (select && select->quick)
   {
     DBUG_PRINT("info",("using rr_quick"));
-    info->read_record=rr_quick;
+    if (select->quick->reset())
+      DBUG_RETURN(TRUE);
+    info->select= select;
+    info->set_read_record_func(table, rr_quick);
   }
   else if (table->sort.record_pointers)
   {
@@ -248,13 +276,14 @@ void init_read_record(READ_RECORD *info,
     info->cache_pos=table->sort.record_pointers;
     info->cache_end=info->cache_pos+ 
                     table->sort.found_records*info->ref_length;
-    info->read_record= (table->sort.addon_field ?
-                        rr_unpack_from_buffer : rr_from_pointers);
+    info->set_read_record_func(table,
+                               table->sort.addon_field ?
+                               rr_unpack_from_buffer : rr_from_pointers);
   }
   else
   {
     DBUG_PRINT("info",("using rr_sequential"));
-    info->read_record=rr_sequential;
+    info->set_read_record_func(table, rr_sequential);
     table->file->ha_rnd_init(1);
     /* We can use record cache if we don't update dynamic length tables */
     if (!table->no_cache &&
@@ -277,10 +306,46 @@ void init_read_record(READ_RECORD *info,
       !table->file->pushed_cond)
     table->file->cond_push(select->cond);
 
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(FALSE);
 } /* init_read_record */
 
 
+/**
+  Reset READ_RECORD structure between two sweeps of the nested join
+  loop.
+*/
+
+bool
+reset_read_record(READ_RECORD *info)
+{
+  TABLE *table= info->table;
+  SQL_SELECT *select= info->select;
+  DBUG_ENTER("reset_read_record");
+
+  empty_record(table);
+  table->status=0;
+
+  if (info->io_cache && my_b_inited(info->io_cache))
+  {
+    reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
+  }
+  else if (select && select->quick)
+  {
+    if (select->quick->reset())
+      DBUG_RETURN(TRUE);
+  }
+  else if (table->sort.record_pointers)
+  {
+    info->cache_pos= table->sort.record_pointers;
+  }
+  else
+  {
+    table->file->ha_index_or_rnd_end();
+    table->file->ha_rnd_init(1);
+  }
+  DBUG_RETURN(FALSE);
+}
+
 
 void end_read_record(READ_RECORD *info)
 {                   /* free cache if used */
@@ -293,10 +358,10 @@ void end_read_record(READ_RECORD *info)
   {
     filesort_free_buffers(info->table,0);
     (void) info->file->extra(HA_EXTRA_NO_CACHE);
-    if (info->read_record != rr_quick) // otherwise quick_range does it
-      (void) info->file->ha_index_or_rnd_end();
+    (void) info->file->ha_index_or_rnd_end();
     info->table=0;
   }
+  info->clear_read_record();
 }
 
 static int rr_handle_error(READ_RECORD *info, int error)
@@ -351,10 +416,14 @@ static int rr_quick(READ_RECORD *info)
 
 static int rr_index_first(READ_RECORD *info)
 {
+  READ_RECORD backup= *info;
   int tmp= info->file->index_first(info->record);
-  info->read_record= rr_index;
   if (tmp)
     tmp= rr_handle_error(info, tmp);
+  info->clear_read_record();
+  info->set_read_record_func(backup.table, rr_index);
+  info->print_error= backup.print_error;
+  backup.clear_read_record();
   return tmp;
 }
 
@@ -505,6 +574,9 @@ static int rr_unpack_from_buffer(READ_RE
 
   return 0;
 }
+
+
+#ifdef NOT_USED
 	/* cacheing of records from a database */
 
 static int init_rr_cache(THD *thd, READ_RECORD *info)
@@ -636,3 +708,4 @@ static int rr_cmp(uchar *a,uchar *b)
   return (int) a[7] - (int) b[7];
 #endif
 }
+#endif /* NOT_USED */

=== modified file 'sql/records.h'
--- a/sql/records.h	2008-08-11 12:40:09 +0000
+++ b/sql/records.h	2008-08-16 19:36:24 +0000
@@ -47,30 +47,47 @@ struct READ_RECORD
 
   TABLE *table;                                 /* Head-form */
   handler *file;
-  TABLE **forms;                                /* head and ref forms */
-  Read_func read_record;
   THD *thd;
   SQL_SELECT *select;
-  uint cache_records;
-  uint ref_length,struct_length,reclength,rec_cache_size,error_offset;
+  uint ref_length;
+#ifdef NOT_USED
+  uint cache_records,struct_length,reclength,rec_cache_size,error_offset;
+#endif
   uint index;
   uchar *ref_pos;				/* pointer to form->refpos */
   uchar *record;
   uchar *rec_buf;                /* to read field values  after filesort */
-  uchar	*cache,*cache_pos,*cache_end,*read_positions;
+  uchar	*cache,*cache_pos,*cache_end;
+#ifdef NOT_USED
+  uchar *read_positions;
+#endif
   struct st_io_cache *io_cache;
   bool print_error, ignore_not_found_rows;
   struct st_join_table *do_insideout_scan;
-
 public:
-  READ_RECORD() {}
+  READ_RECORD() { clear_read_record(); }
+  ~READ_RECORD() { DBUG_ASSERT(is_initialized() == FALSE); }
+
+  void clear_read_record();
+
+  void set_read_record_func(TABLE *table, Read_func read_func);
+  int read_record() { return m_read_record(this); }
+  bool is_initialized() const { return m_is_initialized; }
+
+  void swap(READ_RECORD &rhs);
+private:
+  bool m_is_initialized;
+  Read_func m_read_record;
 };
 
-void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
-		      SQL_SELECT *select, int use_record_cache,
-                      bool print_errors, bool disable_rr_cache);
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+bool
+init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
+                 SQL_SELECT *select, int use_record_cache,
+                 bool print_errors, bool disable_rr_cache);
+
+bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
                           bool print_error, uint idx);
 void end_read_record(READ_RECORD *info);
+bool reset_read_record(READ_RECORD *info);
 
 #endif /* SQL_RECORDS_H */

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2008-08-07 17:52:43 +0000
+++ b/sql/sql_acl.cc	2008-08-16 19:36:24 +0000
@@ -324,11 +324,12 @@ static my_bool acl_load(THD *thd, TABLE_
   acl_cache->clear(1);				// Clear locked hostname cache
 
   init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
-  init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0, 
-                   FALSE);
+  if (init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0,
+                       FALSE))
+    goto end;
   table->use_all_columns();
   (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50);
-  while (!(read_record_info.read_record(&read_record_info)))
+  while (!(read_record_info.read_record()))
   {
     ACL_HOST host;
     update_hostname(&host.host,get_field(&mem, table->field[0]));
@@ -374,7 +375,8 @@ static my_bool acl_load(THD *thd, TABLE_
   end_read_record(&read_record_info);
   freeze_size(&acl_hosts);
 
-  init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE);
+  if (init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE))
+    goto end;
   table->use_all_columns();
   (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100);
   password_length= table->field[2]->field_length /
@@ -419,7 +421,7 @@ static my_bool acl_load(THD *thd, TABLE_
   }
 
   allow_all_hosts=0;
-  while (!(read_record_info.read_record(&read_record_info)))
+  while (!(read_record_info.read_record()))
   {
     ACL_USER user;
     update_hostname(&user.host, get_field(&mem, table->field[0]));
@@ -562,10 +564,11 @@ static my_bool acl_load(THD *thd, TABLE_
   end_read_record(&read_record_info);
   freeze_size(&acl_users);
 
-  init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE);
+  if (init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE))
+    goto end;
   table->use_all_columns();
   (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100);
-  while (!(read_record_info.read_record(&read_record_info)))
+  while (!(read_record_info.read_record()))
   {
     ACL_DB db;
     update_hostname(&db.host,get_field(&mem,
table->field[MYSQL_DB_FIELD_HOST]));

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2008-07-26 16:38:20 +0000
+++ b/sql/sql_delete.cc	2008-08-16 19:36:24 +0000
@@ -239,17 +239,17 @@ bool mysql_delete(THD *thd, TABLE_LIST *
     }
   }
 
-  /* If quick select is used, initialize it before retrieving rows. */
-  if (select && select->quick && select->quick->reset())
+  if (usable_index==MAX_KEY)
+    error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
+  else
+    error= init_read_record_idx(&info, thd, table, 1, usable_index);
+
+  if (error)
   {
     delete select;
     free_underlaid_joins(thd, select_lex);
     goto err;
   }
-  if (usable_index==MAX_KEY)
-    init_read_record(&info, thd, table, select, 1, 1, FALSE);
-  else
-    init_read_record_idx(&info, thd, table, 1, usable_index);
 
   init_ftfuncs(thd, select_lex, 1);
   thd_proc_info(thd, "updating");
@@ -277,8 +277,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 
   table->mark_columns_needed_for_delete();
 
-  while (!(error=info.read_record(&info)) && !thd->killed &&
-	 ! thd->is_error())
+  while (!(error= info.read_record()) && !thd->killed && !
thd->is_error())
   {
     // thd->is_error() is tested to disallow delete row on error
     if (!(select && select->skip_record())&& ! thd->is_error() )
@@ -837,21 +836,26 @@ int multi_delete::do_deletes()
   { 
     ha_rows last_deleted= deleted;
     TABLE *table = table_being_deleted->table;
+    READ_RECORD	info;
+
     if (tempfiles[counter]->get(table))
     {
       local_error=1;
       break;
     }
 
-    READ_RECORD	info;
-    init_read_record(&info, thd, table, NULL, 0, 1, FALSE);
+    if (init_read_record(&info, thd, table, NULL, 0, 1, FALSE))
+    {
+      local_error= 1;
+      break;
+    }
     /*
       Ignore any rows not found in reference tables as they may already have
       been deleted by foreign key handling
     */
     info.ignore_not_found_rows= 1;
     will_batch= !table->file->start_bulk_delete();
-    while (!(local_error=info.read_record(&info)) && !thd->killed)
+    while (!(local_error= info.read_record()) && !thd->killed)
     {
       if (table->triggers &&
           table->triggers->process_triggers(thd, TRG_EVENT_DELETE,

=== modified file 'sql/sql_help.cc'
--- a/sql/sql_help.cc	2008-08-07 17:52:43 +0000
+++ b/sql/sql_help.cc	2008-08-16 19:36:24 +0000
@@ -186,8 +186,9 @@ int search_topics(THD *thd, TABLE *topic
   int count= 0;
 
   READ_RECORD read_record_info;
-  init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE);
-  while (!read_record_info.read_record(&read_record_info))
+  if (init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE))
+    DBUG_RETURN(0); /* Out of resources. */
+  while (!read_record_info.read_record())
   {
     if (!select->cond->val_int())		// Doesn't match like
       continue;
@@ -226,8 +227,9 @@ int search_keyword(THD *thd, TABLE *keyw
   int count= 0;
 
   READ_RECORD read_record_info;
-  init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE);
-  while (!read_record_info.read_record(&read_record_info) && count<2)
+  if (init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE))
+    DBUG_RETURN(0); /* Out of resources. */
+  while (!read_record_info.read_record() && count<2)
   {
     if (!select->cond->val_int())		// Dosn't match like
       continue;
@@ -350,8 +352,9 @@ int search_categories(THD *thd, TABLE *c
 
   DBUG_ENTER("search_categories");
 
-  init_read_record(&read_record_info, thd, categories, select,1,0,FALSE);
-  while (!read_record_info.read_record(&read_record_info))
+  if (init_read_record(&read_record_info, thd, categories, select,1,0,FALSE))
+    DBUG_RETURN(0); /* Out of resources */
+  while (!read_record_info.read_record())
   {
     if (select && !select->cond->val_int())
       continue;
@@ -384,8 +387,9 @@ void get_all_items_for_category(THD *thd
   DBUG_ENTER("get_all_items_for_category");
 
   READ_RECORD read_record_info;
-  init_read_record(&read_record_info, thd, items, select,1,0,FALSE);
-  while (!read_record_info.read_record(&read_record_info))
+  if (init_read_record(&read_record_info, thd, items, select,1,0,FALSE))
+    DBUG_VOID_RETURN; /* Do nothing if out of resources. */
+  while (!read_record_info.read_record())
   {
     if (!select->cond->val_int())
       continue;
@@ -559,6 +563,7 @@ int send_variant_2_list(MEM_ROOT *mem_ro
     #  created SQL_SELECT
 */
 
+static
 SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
 				  TABLE *table, int *error)
 {
@@ -569,8 +574,7 @@ SQL_SELECT *prepare_simple_select(THD *t
   table->covering_keys.clear_all();
 
   SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error);
-  if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) ||
-      (res && res->quick && res->quick->reset()))
+  if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)))
   {
     delete res;
     res=0;

=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc	2008-07-17 19:55:18 +0000
+++ b/sql/sql_plugin.cc	2008-08-16 19:36:24 +0000
@@ -1367,7 +1367,8 @@ static void plugin_load(MEM_ROOT *tmp_ro
     goto end;
   }
   table= tables.table;
-  init_read_record(&read_record_info, new_thd, table, NULL, 1, 0, FALSE);
+  if (init_read_record(&read_record_info, new_thd, table, NULL, 1, 0, FALSE))
+    goto end;
   table->use_all_columns();
   /*
     there're no other threads running yet, so we don't need a mutex.
@@ -1376,7 +1377,7 @@ static void plugin_load(MEM_ROOT *tmp_ro
     the mutex here to satisfy the assert
   */
   pthread_mutex_lock(&LOCK_plugin);
-  while (!(error= read_record_info.read_record(&read_record_info)))
+  while (!(error= read_record_info.read_record()))
   {
     DBUG_PRINT("info", ("init plugin record"));
     String str_name, str_dl;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2008-08-07 17:52:43 +0000
+++ b/sql/sql_select.cc	2008-08-16 19:36:24 +0000
@@ -883,7 +883,7 @@ static void save_index_subquery_explain_
     join_tab->packed_info |= TAB_INFO_USING_WHERE;
   for (uint i = 0; i < join_tab->ref.key_parts; i++)
   {
-    if (join_tab->ref.cond_guards[i])
+    if (join_tab->ref.cond_guard.guard_list[i])
     {
       join_tab->packed_info |= TAB_INFO_FULL_SCAN_ON_NULL;
       break;
@@ -7033,7 +7033,7 @@ static bool create_ref_for_key(JOIN *joi
       !(j->ref.key_copy= (store_key**) thd->alloc((sizeof(store_key*) *
 						   (keyparts+1)))) ||
       !(j->ref.items=    (Item**) thd->alloc(sizeof(Item*)*keyparts)) ||
-      !(j->ref.cond_guards= (bool**) thd->alloc(sizeof(uint*)*keyparts)))
+      !(j->ref.cond_guard.guard_list= (bool**) thd->alloc(sizeof(bool*)*keyparts)))
   {
     DBUG_RETURN(TRUE);
   }
@@ -7050,7 +7050,7 @@ static bool create_ref_for_key(JOIN *joi
   {
     j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
     /* Predicates pushed down into subquery can't be used FT access */
-    j->ref.cond_guards[0]= NULL;
+    j->ref.cond_guard.guard_list[0]= NULL;
     if (keyuse->used_tables)
       DBUG_RETURN(TRUE);                        // not supported yet. SerG
 
@@ -7067,7 +7067,7 @@ static bool create_ref_for_key(JOIN *joi
 
       uint maybe_null= test(keyinfo->key_part[i].null_bit);
       j->ref.items[i]=keyuse->val;		// Save for cond removal
-      j->ref.cond_guards[i]= keyuse->cond_guard;
+      j->ref.cond_guard.guard_list[i]= keyuse->cond_guard;
       if (keyuse->null_rejecting) 
         j->ref.null_rejecting |= 1 << i;
       keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
@@ -7214,7 +7214,7 @@ make_simple_join(JOIN *join,TABLE *tmp_t
   if (!join->join_tab_reexec)
   {
     if (!(join->join_tab_reexec=
-          (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
+          (JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB))))
       DBUG_RETURN(TRUE);                        /* purecov: inspected */
     if (join->tmp_join)
       join->tmp_join->join_tab_reexec= join->join_tab_reexec;
@@ -7255,7 +7255,9 @@ make_simple_join(JOIN *join,TABLE *tmp_t
   join_tab->ref.key_parts= 0;
   join_tab->flush_weedout_table= join_tab->check_weed_out_table= NULL;
   join_tab->do_firstmatch= NULL;
-  bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
+  DBUG_ASSERT(join_tab->read_record.is_initialized() == FALSE);
+  /* Don't take chances in production */
+  join_tab->read_record.clear_read_record();
   tmp_table->status=0;
   tmp_table->null_row=0;
   DBUG_RETURN(FALSE);
@@ -8277,8 +8279,6 @@ make_join_readinfo(JOIN *join, ulonglong
     JOIN_TAB *tab=join->join_tab+i;
     TABLE *table=tab->table;
     bool using_join_cache;
-    tab->read_record.table= table;
-    tab->read_record.file=table->file;
     tab->next_select=sub_select;		/* normal select */
     /* 
       TODO: don't always instruct first table's ref/range access method to 
@@ -8297,12 +8297,12 @@ make_join_readinfo(JOIN *join, ulonglong
     case JT_SYSTEM:				// Only happens with left join
       table->status=STATUS_NO_RECORD;
       tab->read_first_record= join_read_system;
-      tab->read_record.read_record= join_no_more_records;
+      tab->read_record.set_read_record_func(table, join_no_more_records);
       break;
     case JT_CONST:				// Only happens with left join
       table->status=STATUS_NO_RECORD;
       tab->read_first_record= join_read_const;
-      tab->read_record.read_record= join_no_more_records;
+      tab->read_record.set_read_record_func(table, join_no_more_records);
       if (table->covering_keys.is_set(tab->ref.key) &&
           !table->no_keyread)
       {
@@ -8320,7 +8320,7 @@ make_join_readinfo(JOIN *join, ulonglong
       delete tab->quick;
       tab->quick=0;
       tab->read_first_record= join_read_key;
-      tab->read_record.read_record= join_no_more_records;
+      tab->read_record.set_read_record_func(table, join_no_more_records);
       if (table->covering_keys.is_set(tab->ref.key) &&
 	  !table->no_keyread)
       {
@@ -8351,19 +8351,23 @@ make_join_readinfo(JOIN *join, ulonglong
       if (tab->type == JT_REF)
       {
 	tab->read_first_record= join_read_always_key;
-	tab->read_record.read_record= tab->insideout_match_tab? 
-           join_read_next_same_diff : join_read_next_same;
+        tab->read_record.
+          set_read_record_func(table,
+                               tab->insideout_match_tab?
+                               join_read_next_same_diff : join_read_next_same);
       }
       else
       {
 	tab->read_first_record= join_read_always_key_or_null;
-	tab->read_record.read_record= join_read_next_same_or_null;
+	tab->read_record.set_read_record_func(table,
+                                              join_read_next_same_or_null);
       }
       break;
     case JT_FT:
       table->status=STATUS_NO_RECORD;
       tab->read_first_record= join_ft_read_first;
-      tab->read_record.read_record= join_ft_read_next;
+      tab->read_record.set_read_record_func(table,
+                                            join_ft_read_next);
       break;
     case JT_ALL:
       /*
@@ -8531,6 +8535,7 @@ void JOIN_TAB::cleanup()
     table->reginfo.join_tab= 0;
   }
   end_read_record(&read_record);
+  end_read_record(&ref.cond_guard.full_scan_info);
 }
 
 
@@ -13646,7 +13651,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab
   */
   while (rc == NESTED_LOOP_OK && join->return_tab >= join_tab)
   {
-    error= info->read_record(info);
+    error= info->read_record();
     rc= evaluate_join_record(join, join_tab, error);
   }
 
@@ -14032,7 +14037,7 @@ flush_cached_records(JOIN *join,JOIN_TAB
         }
       }
     }
-  } while (!(error=info->read_record(info)));
+  } while (!(error=info->read_record()));
 
   if (skip_last)
     read_cached_record(join_tab);		// Restore current record
@@ -14448,9 +14453,20 @@ join_read_prev_same(READ_RECORD *info)
 static int
 join_init_quick_read_record(JOIN_TAB *tab)
 {
-  if (test_if_quick_select(tab) == -1)
+  delete tab->select->quick;
+  tab->select->quick=0;
+  if (tab->read_record.is_initialized())
+    end_read_record(&tab->read_record);
+
+  if (tab->select->test_quick_select(tab->join->thd, tab->keys,
+                                     (table_map) 0, HA_POS_ERROR, 0,
+                                     FALSE) == -1)
     return -1;					/* No possible records */
-  return join_init_read_record(tab);
+
+  if (init_read_record(&tab->read_record, tab->join->thd, tab->table,
+                       tab->select,1,1, FALSE))
+    return 1;                                   /* Out of resources. */
+  return tab->read_record.read_record();
 }
 
 
@@ -14458,7 +14474,7 @@ int read_first_record_seq(JOIN_TAB *tab)
 {
   if (tab->read_record.file->ha_rnd_init(1))
     return 1;
-  return (*tab->read_record.read_record)(&tab->read_record);
+  return tab->read_record.read_record();
 }
 
 static int
@@ -14475,11 +14491,19 @@ test_if_quick_select(JOIN_TAB *tab)
 static int
 join_init_read_record(JOIN_TAB *tab)
 {
-  if (tab->select && tab->select->quick &&
tab->select->quick->reset())
-    return 1;
-  init_read_record(&tab->read_record, tab->join->thd, tab->table,
-		   tab->select,1,1, FALSE);
-  return (*tab->read_record.read_record)(&tab->read_record);
+  if (! tab->read_record.is_initialized())
+  {
+    if (init_read_record(&tab->read_record, tab->join->thd, tab->table,
+                         tab->select,1,1, FALSE))
+      return 1; /* Out of resources. */
+  }
+  else
+  {
+    if (reset_read_record(&tab->read_record))
+      return 1; /* Out of resources. */
+  }
+
+  return tab->read_record.read_record();
 }
 
 
@@ -14487,7 +14511,11 @@ static int
 join_read_first(JOIN_TAB *tab)
 {
   int error;
-  TABLE *table=tab->table;
+  TABLE *table= tab->table;
+
+  if (tab->read_record.is_initialized())
+    goto read;
+
   if (!table->key_read && table->covering_keys.is_set(tab->index)
&&
       !table->no_keyread)
   {
@@ -14495,23 +14523,27 @@ join_read_first(JOIN_TAB *tab)
     table->file->extra(HA_EXTRA_KEYREAD);
   }
   tab->table->status=0;
-  tab->read_record.table=table;
-  tab->read_record.file=table->file;
   tab->read_record.index=tab->index;
-  tab->read_record.record=table->record[0];
   if (tab->insideout_match_tab)
   {
     tab->read_record.do_insideout_scan= tab;
-    tab->read_record.read_record=join_read_next_different;
+    tab->read_record.set_read_record_func(table, join_read_next_different);
     tab->insideout_match_tab->found_match= 0;
   }
   else
   {
-    tab->read_record.read_record=join_read_next;
+    tab->read_record.set_read_record_func(table, join_read_next);
     tab->read_record.do_insideout_scan= 0;
   }
 
-  if (!table->file->inited)
+  DBUG_ASSERT( !table->file->inited);
+read:
+  /*
+    In case of a correlated subquery, we may have inited= false,
+    m_initialied= TRUE. In case of a nested iteration of a join
+    loop, we may have both true.
+  */
+  if (! table->file->inited)
     table->file->ha_index_init(tab->index, tab->sorted);
   if ((error=tab->table->file->index_first(tab->table->record[0])))
   {
@@ -14564,21 +14596,24 @@ join_read_last(JOIN_TAB *tab)
 {
   TABLE *table=tab->table;
   int error;
+
+  if (tab->read_record.is_initialized())
+    goto read;
+
   if (!table->key_read && table->covering_keys.is_set(tab->index)
&&
       !table->no_keyread)
   {
     table->key_read=1;
     table->file->extra(HA_EXTRA_KEYREAD);
   }
-  tab->table->status=0;
-  tab->read_record.read_record=join_read_prev;
-  tab->read_record.table=table;
-  tab->read_record.file=table->file;
+  tab->read_record.set_read_record_func(table, join_read_prev);
   tab->read_record.index=tab->index;
-  tab->read_record.record=table->record[0];
-  if (!table->file->inited)
+  DBUG_ASSERT (!table->file->inited);
+read:
+  table->status=0;
+  if (! table->file->inited)
     table->file->ha_index_init(tab->index, 1);
-  if ((error= tab->table->file->index_last(tab->table->record[0])))
+  if ((error= table->file->index_last(table->record[0])))
     return report_error(table, error);
   return 0;
 }
@@ -15406,7 +15441,7 @@ part_of_refkey(TABLE *table,Field *field
 
     for (part=0 ; part < ref_parts ; part++)
     {
-      if (table->reginfo.join_tab->ref.cond_guards[part])
+      if (table->reginfo.join_tab->ref.cond_guard.guard_list[part])
         return 0;
     }
 
@@ -16137,6 +16172,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
       {
         if (!quick_created)
 	{
+          table->file->ha_index_or_rnd_end();
+          end_read_record(&tab->read_record);
           tab->index= best_key;
           tab->read_first_record= best_key_direction > 0 ?
                                   join_read_first:join_read_last;
@@ -16151,7 +16188,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
             table->key_read=1;
             table->file->extra(HA_EXTRA_KEYREAD);
           }
-          table->file->ha_index_or_rnd_end();
           if (join->select_options & SELECT_DESCRIBE)
           {
             tab->ref.key= -1;
@@ -16172,6 +16208,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
           tab->use_quick=1;
           tab->ref.key= -1;
           tab->ref.key_parts=0;		// Don't use ref key.
+          end_read_record(&tab->read_record);
           tab->read_first_record= join_init_read_record;
           if (tab->is_using_loose_index_scan())
             join->tmp_table_param.precomputed_group_by= TRUE;
@@ -16227,6 +16264,7 @@ check_reverse_order:                  
     else if (tab->type != JT_NEXT && 
              tab->ref.key >= 0 && tab->ref.key_parts <=
used_key_parts)
     {
+      end_read_record(&tab->read_record);
       /*
 	SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
 
@@ -16234,7 +16272,7 @@ check_reverse_order:                  
 	with key part (A) and then traverse the index backwards.
       */
       tab->read_first_record= join_read_last_key;
-      tab->read_record.read_record= join_read_prev_same;
+      tab->read_record.set_read_record_func(table, join_read_prev_same);
     }
   }
   else if (select && select->quick)
@@ -16355,6 +16393,7 @@ create_sort_index(THD *thd, JOIN *join, 
       get_schema_tables_result(join, PROCESSED_BY_CREATE_SORT_INDEX))
     goto err;
 
+  end_read_record(&tab->read_record);
   if (table->s->tmp_table)
     table->file->info(HA_STATUS_VARIABLE);	// Get record count
   table->sort.found_records=filesort(thd, table,join->sortorder, length,
@@ -19286,7 +19325,7 @@ void select_describe(JOIN *join, bool ne
 
         for (uint part= 0; part < tab->ref.key_parts; part++)
         {
-          if (tab->ref.cond_guards[part])
+          if (tab->ref.cond_guard.guard_list[part])
           {
             extra.append(STRING_WITH_LEN("; Full scan on NULL key"));
             break;

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2008-08-11 12:40:09 +0000
+++ b/sql/sql_select.h	2008-08-16 19:36:24 +0000
@@ -64,6 +64,47 @@ typedef struct keyuse_t {
 
 class store_key;
 
+/**
+  Represents an array of pointers to trigger variables.
+  Some/all of the pointers may be NULL. The array is stored in JOIN_TAB.
+
+  The ref access can be used iff
+
+  for each used key part i, (!cond_guards[i] || *cond_guards[i]) 
+
+  An instance of this class is a member of TABLE_REF and is used by
+  subquery code. The subquery code may inject triggered conditions, i.e.
+  conditions that can be 'switched off'. A ref access created from such
+  condition is not valid when at least one of the underlying conditions is
+  switched off (see subquery code for more details).
+
+  If, to evaluate a subquery with the attached disabled condition we
+  originally intended to use an index access method, we also must replace it
+  with a full scan. READ_RECORD information for the full scan is in that
+  case stored in "full_scan_info" member.
+*/
+
+struct Cond_guard
+{
+  /** A pointer to a boolean variable which indicates whether
+    the condition is switched off or not. The condition
+    may only be switched off if it returns NULL. Therefore, this
+    points to "is_null" member of the associated condition item,
+    or the pointer is set to zero if the item is not nullable.
+  */
+  bool **guard_list;
+  /** May point to a READ_RECORD structure for full scan access.  */
+  READ_RECORD full_scan_info;
+  /*
+    The following field is used only for a [NOT] IN
+    subquery if it is executed by an alternative full table scan
+    when the left operand of the subquery predicate is evaluated
+    to NULL.
+  */  
+  READ_RECORD::Setup_func save_read_first_record;/* to save read_first_record */
+};
+
+
 typedef struct st_table_ref
 {
   bool		key_err;
@@ -74,18 +115,7 @@ typedef struct st_table_ref
   uchar         *key_buff2;               ///< key_buff+key_length
   store_key     **key_copy;               //
   Item          **items;                  ///< val()'s for each keypart
-  /*  
-    Array of pointers to trigger variables. Some/all of the pointers may be
-    NULL.  The ref access can be used iff
-    
-      for each used key part i, (!cond_guards[i] || *cond_guards[i]) 
-
-    This array is used by subquery code. The subquery code may inject
-    triggered conditions, i.e. conditions that can be 'switched off'. A ref 
-    access created from such condition is not valid when at least one of the 
-    underlying conditions is switched off (see subquery code for more details)
-  */
-  bool          **cond_guards;
+  Cond_guard    cond_guard;
   /**
     (null_rejecting & (1<<i)) means the condition is '=' and no matching
     rows will be produced if items[i] IS NULL (see add_not_null_conds())
@@ -212,13 +242,6 @@ typedef struct st_join_table {
   READ_RECORD::Setup_func read_first_record;
   Next_select_func next_select;
   READ_RECORD	read_record;
-  /* 
-    Currently the following two fields are used only for a [NOT] IN subquery
-    if it is executed by an alternative full table scan when the left operand of
-    the subquery predicate is evaluated to NULL.
-  */  
-  READ_RECORD::Setup_func save_read_first_record;/* to save read_first_record */
-  READ_RECORD::Read_func save_read_record;/* to save read_record.read_record */
   double	worst_seeks;
   key_map	const_keys;			/**< Keys with constant part */
   key_map	checked_keys;			/**< Keys checked in find_best */

=== modified file 'sql/sql_servers.cc'
--- a/sql/sql_servers.cc	2008-07-17 19:55:18 +0000
+++ b/sql/sql_servers.cc	2008-08-16 19:36:24 +0000
@@ -182,9 +182,10 @@ static bool servers_load(THD *thd, TABLE
   free_root(&mem, MYF(0));
   init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
 
-  init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0, 
-                   FALSE);
-  while (!(read_record_info.read_record(&read_record_info)))
+  if (init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0,
+                   FALSE))
+    DBUG_RETURN(TRUE);
+  while (!(read_record_info.read_record()))
   {
     /* return_val is already TRUE, so no need to set */
     if ((get_server_from_table_to_cache(table)))

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2008-08-08 01:39:23 +0000
+++ b/sql/sql_table.cc	2008-08-16 19:36:24 +0000
@@ -7307,13 +7307,14 @@ copy_data_between_tables(TABLE *from,TAB
 
   /* Tell handler that we have values for all columns in the to table */
   to->use_all_columns();
-  init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
+  if (init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE))
+    goto err;
   errpos= 4;
   if (ignore)
     to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
   thd->row_count= 0;
   restore_record(to, s->default_values);        // Create empty record
-  while (!(error=info.read_record(&info)))
+  while (!(error=info.read_record()))
   {
     if (thd->killed)
     {

=== modified file 'sql/sql_udf.cc'
--- a/sql/sql_udf.cc	2008-07-17 19:55:18 +0000
+++ b/sql/sql_udf.cc	2008-08-16 19:36:24 +0000
@@ -153,9 +153,10 @@ void udf_init()
   }
 
   table= tables.table;
-  init_read_record(&read_record_info, new_thd, table, NULL,1,0,FALSE);
+  if (init_read_record(&read_record_info, new_thd, table, NULL,1,0,FALSE))
+    goto end;
   table->use_all_columns();
-  while (!(error= read_record_info.read_record(&read_record_info)))
+  while (!(error= read_record_info.read_record()))
   {
     DBUG_PRINT("info",("init udf record"));
     LEX_STRING name;

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2008-07-17 19:55:18 +0000
+++ b/sql/sql_update.cc	2008-08-16 19:36:24 +0000
@@ -442,10 +442,6 @@ int mysql_update(THD *thd,
 			   DISK_BUFFER_SIZE, MYF(MY_WME)))
 	goto err;
 
-      /* If quick select is used, initialize it before retrieving rows. */
-      if (select && select->quick && select->quick->reset())
-        goto err;
-      table->file->try_semi_consistent_read(1);
 
       /*
         When we get here, we have one of the following options:
@@ -459,14 +455,19 @@ int mysql_update(THD *thd,
       */
 
       if (used_index == MAX_KEY || (select && select->quick))
-        init_read_record(&info, thd, table, select, 0, 1, FALSE);
+        error= init_read_record(&info, thd, table, select, 0, 1, FALSE);
       else
-        init_read_record_idx(&info, thd, table, 1, used_index);
+        error= init_read_record_idx(&info, thd, table, 1, used_index);
+
+      if (error)
+        goto err;
+
+      table->file->try_semi_consistent_read(1);
 
       thd_proc_info(thd, "Searching rows for update");
       ha_rows tmp_limit= limit;
 
-      while (!(error=info.read_record(&info)) && !thd->killed)
+      while (!(error= info.read_record()) && !thd->killed)
       {
 	if (!(select && select->skip_record()))
 	{
@@ -521,11 +522,10 @@ int mysql_update(THD *thd,
 
   if (ignore)
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
-  
-  if (select && select->quick && select->quick->reset())
-    goto err;
+
   table->file->try_semi_consistent_read(1);
-  init_read_record(&info, thd, table, select, 0, 1, FALSE);
+  if ((error= init_read_record(&info, thd, table, select, 0, 1, FALSE)))
+    goto err;
 
   updated= found= 0;
   /* Generate an error when trying to set a NOT NULL field to NULL. */
@@ -570,7 +570,7 @@ int mysql_update(THD *thd,
                          HA_PARTIAL_COLUMN_READ) ||
                        bitmap_is_subset(table->write_set, table->read_set));
 
-  while (!(error=info.read_record(&info)) && !thd->killed)
+  while (!(error= info.read_record()) && !thd->killed)
   {
     if (!(select && select->skip_record()))
     {

Thread
bzr commit into mysql-6.0-runtime branch (konstantin:2700) WL#3288Konstantin Osipov16 Aug