List:Commits« Previous MessageNext Message »
From:Stewart Smith Date:October 16 2006 7:39am
Subject:bk commit into 5.0 tree (stewart:1.2265)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of stewart. When stewart does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-10-16 17:39:38+10:00, stewart@willster.(none) +30 -0
  Merge willster.(none):/home/stewart/Documents/MySQL/4.1/bug19914-mk2
  into  willster.(none):/home/stewart/Documents/MySQL/5.0/bug19914-mk2-merge
  MERGE: 1.1616.2144.184

  BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.29.5.2

  BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Merge rename: sql/ha_isam.cc -> BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e

  BitKeeper/deleted/.del-ha_isam.h~bf53d533be3d3927@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.28.2.2

  BitKeeper/deleted/.del-ha_isam.h~bf53d533be3d3927@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Merge rename: sql/ha_isam.h -> BitKeeper/deleted/.del-ha_isam.h~bf53d533be3d3927

  BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.15.5.2

  BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Merge rename: sql/ha_isammrg.cc -> BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e

  BitKeeper/deleted/.del-ha_isammrg.h~66fd2e5bfe7207dc@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.22.2.2

  BitKeeper/deleted/.del-ha_isammrg.h~66fd2e5bfe7207dc@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Merge rename: sql/ha_isammrg.h -> BitKeeper/deleted/.del-ha_isammrg.h~66fd2e5bfe7207dc

  sql/examples/ha_example.cc@stripped, 2006-10-16 17:31:08+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.8.1.5

  sql/examples/ha_example.h@stripped, 2006-10-16 17:31:08+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.9.1.1

  sql/examples/ha_tina.cc@stripped, 2006-10-16 17:31:08+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.3.1.8

  sql/examples/ha_tina.h@stripped, 2006-10-16 17:31:08+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.2.1.1

  sql/ha_archive.cc@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.13.8.2

  sql/ha_archive.cc@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Merge rename: sql/examples/ha_archive.cc -> sql/ha_archive.cc

  sql/ha_archive.h@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.9.1.8

  sql/ha_archive.h@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Merge rename: sql/examples/ha_archive.h -> sql/ha_archive.h

  sql/ha_berkeley.cc@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.117.1.37

  sql/ha_berkeley.h@stripped, 2006-10-16 17:31:06+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.57.1.13

  sql/ha_blackhole.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.2.1.11

  sql/ha_blackhole.h@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.3.1.2

  sql/ha_heap.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.47.1.14

  sql/ha_heap.h@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.26.1.9

  sql/ha_innodb.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.90.16.45

  sql/ha_innodb.h@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.57.6.5

  sql/ha_myisam.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.115.1.48

  sql/ha_myisam.h@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.61.1.4

  sql/ha_myisammrg.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.51.1.12

  sql/ha_myisammrg.h@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.35.1.4

  sql/ha_ndbcluster.cc@stripped, 2006-10-16 17:39:36+10:00, stewart@willster.(none) +2 -5
    merge
    MERGE: 1.114.3.76

  sql/ha_ndbcluster.h@stripped, 2006-10-16 17:39:36+10:00, stewart@willster.(none) +1 -2
    merge
    MERGE: 1.40.6.17

  sql/handler.h@stripped, 2006-10-16 17:39:36+10:00, stewart@willster.(none) +1 -2
    merge
    MERGE: 1.89.19.13

  sql/item_sum.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.89.1.60

  sql/opt_sum.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.33.6.3

  sql/sql_delete.cc@stripped, 2006-10-16 17:31:07+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.99.2.41

  sql/sql_select.cc@stripped, 2006-10-16 17:39:36+10:00, stewart@willster.(none) +0 -0
    merge
    MERGE: 1.216.137.4

  sql/sql_union.cc@stripped, 2006-10-16 17:31:08+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.74.1.72

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	stewart
# Host:	willster.(none)
# Root:	/home/stewart/Documents/MySQL/5.0/bug19914-mk2-merge/RESYNC

--- 1.162/sql/ha_berkeley.cc	2006-10-16 17:39:44 +10:00
+++ 1.163/sql/ha_berkeley.cc	2006-10-16 17:39:44 +10:00
@@ -1756,7 +1756,7 @@
 }
 
 
-void ha_berkeley::info(uint flag)
+int ha_berkeley::info(uint flag)
 {
   DBUG_ENTER("ha_berkeley::info");
   if (flag & HA_STATUS_VARIABLE)
@@ -1776,7 +1776,7 @@
   /* Don't return key if we got an error for the internal primary key */
   if (flag & HA_STATUS_ERRKEY && last_dup_key < table->s->keys)
     errkey= last_dup_key;
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(0);
 }
 
 

--- 1.77/sql/ha_berkeley.h	2006-10-16 17:39:44 +10:00
+++ 1.78/sql/ha_berkeley.h	2006-10-16 17:39:44 +10:00
@@ -123,7 +123,7 @@
   int rnd_next(byte *buf);
   int rnd_pos(byte * buf, byte *pos);
   void position(const byte *record);
-  void info(uint);
+  int info(uint);
   int extra(enum ha_extra_function operation);
   int reset(void);
   int external_lock(THD *thd, int lock_type);

--- 1.78/sql/ha_heap.cc	2006-10-16 17:39:44 +10:00
+++ 1.79/sql/ha_heap.cc	2006-10-16 17:39:44 +10:00
@@ -332,7 +332,7 @@
   *(HEAP_PTR*) ref= heap_position(file);	// Ref is aligned
 }
 
-void ha_heap::info(uint flag)
+int ha_heap::info(uint flag)
 {
   HEAPINFO info;
   (void) heap_info(file,&info,flag);
@@ -354,6 +354,7 @@
   */
   if (key_stat_version != file->s->key_stat_version)
     update_key_stats();
+  return 0;
 }
 
 int ha_heap::extra(enum ha_extra_function operation)

--- 1.39/sql/ha_heap.h	2006-10-16 17:39:44 +10:00
+++ 1.40/sql/ha_heap.h	2006-10-16 17:39:44 +10:00
@@ -85,7 +85,7 @@
   int rnd_next(byte *buf);
   int rnd_pos(byte * buf, byte *pos);
   void position(const byte *record);
-  void info(uint);
+  int info(uint);
   int extra(enum ha_extra_function operation);
   int external_lock(THD *thd, int lock_type);
   int delete_all_rows(void);

--- 1.29.5.1/sql/ha_isam.cc	2006-10-16 17:39:44 +10:00
+++ 1.41/BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e	2006-10-16 17:39:44 +10:00
@@ -68,7 +68,7 @@
 
 int ha_isam::write_row(byte * buf)
 {
-  statistic_increment(ha_write_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
     table->timestamp_field->set_time();
   if (table->next_number_field && buf == table->record[0])
@@ -78,7 +78,7 @@
 
 int ha_isam::update_row(const byte * old_data, byte * new_data)
 {
-  statistic_increment(ha_update_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_update_count, &LOCK_status);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
     table->timestamp_field->set_time();
   return !nisam_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1;
@@ -86,14 +86,15 @@
 
 int ha_isam::delete_row(const byte * buf)
 {
-  statistic_increment(ha_delete_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_delete_count, &LOCK_status);
   return !nisam_delete(file,buf) ? 0 : my_errno ? my_errno : -1;
 }
 
 int ha_isam::index_read(byte * buf, const byte * key,
 			uint key_len, enum ha_rkey_function find_flag)
 {
-  statistic_increment(ha_read_key_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_key_count,
+		      &LOCK_status);
   int error=nisam_rkey(file, buf, active_index, key, key_len, find_flag);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : -1;
@@ -102,7 +103,8 @@
 int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
 			    uint key_len, enum ha_rkey_function find_flag)
 {
-  statistic_increment(ha_read_key_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_key_count,
+		      &LOCK_status);
   int error=nisam_rkey(file, buf, index, key, key_len, find_flag);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : -1;
@@ -110,7 +112,8 @@
 
 int ha_isam::index_read_last(byte * buf, const byte * key, uint key_len)
 {
-  statistic_increment(ha_read_key_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_key_count,
+		      &LOCK_status);
   int error=nisam_rkey(file, buf, active_index, key, key_len,
 		       HA_READ_PREFIX_LAST);
   table->status=error ? STATUS_NOT_FOUND: 0;
@@ -119,7 +122,8 @@
 
 int ha_isam::index_next(byte * buf)
 {
-  statistic_increment(ha_read_next_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_next_count,
+		      &LOCK_status);
   int error=nisam_rnext(file,buf,active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
@@ -127,7 +131,8 @@
 
 int ha_isam::index_prev(byte * buf)
 {
-  statistic_increment(ha_read_prev_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_prev_count,
+		      &LOCK_status);
   int error=nisam_rprev(file,buf, active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
@@ -135,7 +140,8 @@
 
 int ha_isam::index_first(byte * buf)
 {
-  statistic_increment(ha_read_first_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_first_count,
+		      &LOCK_status);
   int error=nisam_rfirst(file, buf, active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
@@ -143,7 +149,8 @@
 
 int ha_isam::index_last(byte * buf)
 {
-  statistic_increment(ha_read_last_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_last_count,
+		      &LOCK_status);
   int error=nisam_rlast(file, buf, active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
@@ -156,7 +163,8 @@
 
 int ha_isam::rnd_next(byte *buf)
 {
-  statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+		      &LOCK_status);
   int error=nisam_rrnd(file, buf, NI_POS_ERROR);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : -1;
@@ -164,8 +172,9 @@
 
 int ha_isam::rnd_pos(byte * buf, byte *pos)
 {
-  statistic_increment(ha_read_rnd_count,&LOCK_status);
-  int error=nisam_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length));
+  statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+		      &LOCK_status);
+  int error=nisam_rrnd(file, buf, (ulong) my_get_ptr(pos,ref_length));
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : -1;
 }
@@ -175,7 +184,7 @@
   my_off_t position=nisam_position(file);
   if (position == (my_off_t) ~ (ulong) 0)
     position=HA_OFFSET_ERROR;
-  ha_store_ptr(ref, ref_length, position);
+  my_store_ptr(ref, ref_length, position);
 }
 
 int ha_isam::info(uint flag)
@@ -220,7 +229,7 @@
   if (flag & HA_STATUS_ERRKEY)
   {
     errkey  = info.errkey;
-    ha_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
+    my_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
   }
   if (flag & HA_STATUS_TIME)
     update_time = info.update_time;
@@ -330,7 +339,7 @@
 	}
       }
     }
-    DBUG_PRINT("loop",("found: %lx  recpos: %d  minpos: %d  length: %d",
+    DBUG_PRINT("loop",("found: 0x%lx  recpos: %d  minpos: %d  length: %d",
 		       found,recpos,minpos,length));
     if (recpos != minpos)
     {						// Reserved space (Null bits?)

--- 1.15.5.1/sql/ha_isammrg.cc	2006-10-16 17:39:44 +10:00
+++ 1.26/BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e	2006-10-16 17:39:44 +10:00
@@ -77,7 +77,7 @@
 
 int ha_isammrg::update_row(const byte * old_data, byte * new_data)
 {
-  statistic_increment(ha_update_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_update_count, &LOCK_status);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
     table->timestamp_field->set_time();
   return !mrg_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1;
@@ -85,7 +85,7 @@
 
 int ha_isammrg::delete_row(const byte * buf)
 {
-  statistic_increment(ha_delete_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_delete_count, &LOCK_status);
   return !mrg_delete(file,buf) ? 0 : my_errno ? my_errno : -1;
 }
 
@@ -128,7 +128,8 @@
 
 int ha_isammrg::rnd_next(byte *buf)
 {
-  statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+		      &LOCK_status);
   int error=mrg_rrnd(file, buf, ~(mrg_off_t) 0);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : -1;
@@ -136,8 +137,9 @@
 
 int ha_isammrg::rnd_pos(byte * buf, byte *pos)
 {
-  statistic_increment(ha_read_rnd_count,&LOCK_status);
-  int error=mrg_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length));
+  statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+		      &LOCK_status);
+  int error=mrg_rrnd(file, buf, (ulong) my_get_ptr(pos,ref_length));
   table->status=error ? STATUS_NOT_FOUND: 0;
   return !error ? 0 : my_errno ? my_errno : -1;
 }
@@ -145,7 +147,7 @@
 void ha_isammrg::position(const byte *record)
 {
   ulong position= mrg_position(file);
-  ha_store_ptr(ref, ref_length, (my_off_t) position);
+  my_store_ptr(ref, ref_length, (my_off_t) position);
 }
 
 

--- 1.168/sql/ha_myisam.cc	2006-10-16 17:39:44 +10:00
+++ 1.169/sql/ha_myisam.cc	2006-10-16 17:39:44 +10:00
@@ -1299,7 +1299,7 @@
   my_store_ptr(ref, ref_length, position);
 }
 
-void ha_myisam::info(uint flag)
+int ha_myisam::info(uint flag)
 {
   MI_ISAMINFO info;
   char name_buff[FN_REFLEN];
@@ -1358,6 +1358,8 @@
     update_time = info.update_time;
   if (flag & HA_STATUS_AUTO)
     auto_increment_value= info.auto_increment;
+
+  return 0;
 }
 
 

--- 1.69/sql/ha_myisam.h	2006-10-16 17:39:44 +10:00
+++ 1.70/sql/ha_myisam.h	2006-10-16 17:39:44 +10:00
@@ -95,7 +95,7 @@
   int rnd_pos(byte * buf, byte *pos);
   int restart_rnd_next(byte *buf, byte *pos);
   void position(const byte *record);
-  void info(uint);
+  int info(uint);
   int extra(enum ha_extra_function operation);
   int extra_opt(enum ha_extra_function operation, ulong cache_size);
   int external_lock(THD *thd, int lock_type);

--- 1.82/sql/ha_myisammrg.cc	2006-10-16 17:39:44 +10:00
+++ 1.83/sql/ha_myisammrg.cc	2006-10-16 17:39:44 +10:00
@@ -275,7 +275,7 @@
 }
 
 
-void ha_myisammrg::info(uint flag)
+int ha_myisammrg::info(uint flag)
 {
   MYMERGE_INFO info;
   (void) myrg_status(file,&info,flag);
@@ -343,6 +343,7 @@
              min(file->keys, table->s->key_parts));
     }
   }
+  return 0;
 }
 
 

--- 1.41/sql/ha_myisammrg.h	2006-10-16 17:39:44 +10:00
+++ 1.42/sql/ha_myisammrg.h	2006-10-16 17:39:44 +10:00
@@ -72,7 +72,7 @@
   int rnd_pos(byte * buf, byte *pos);
   void position(const byte *record);
   ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
-  void info(uint);
+  int info(uint);
   int extra(enum ha_extra_function operation);
   int extra_opt(enum ha_extra_function operation, ulong cache_size);
   int external_lock(THD *thd, int lock_type);

--- 1.179/sql/handler.h	2006-10-16 17:39:44 +10:00
+++ 1.180/sql/handler.h	2006-10-16 17:39:44 +10:00
@@ -682,7 +682,7 @@
                                    key_range *max_key)
     { return (ha_rows) 10; }
   virtual void position(const byte *record)=0;
-  virtual void info(uint)=0; // see my_base.h for full description
+  virtual int info(uint)=0; // see my_base.h for full description
   virtual int extra(enum ha_extra_function operation)
   { return 0; }
   virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)

--- 1.181/sql/item_sum.cc	2006-10-16 17:39:44 +10:00
+++ 1.182/sql/item_sum.cc	2006-10-16 17:39:44 +10:00
@@ -2675,6 +2675,7 @@
 
 longlong Item_sum_count_distinct::val_int()
 {
+  int error;
   DBUG_ASSERT(fixed == 1);
   if (!table)					// Empty query
     return LL(0);
@@ -2688,7 +2689,14 @@
     tree->walk(count_distinct_walk, (void*) &count);
     return (longlong) count;
   }
-  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+
+  error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+
+  if(error)
+  {
+    table->file->print_error(error, MYF(0));
+  }
+
   return table->file->records;
 }
 

--- 1.58/sql/opt_sum.cc	2006-10-16 17:39:44 +10:00
+++ 1.59/sql/opt_sum.cc	2006-10-16 17:39:44 +10:00
@@ -134,7 +134,12 @@
     }
     else
     {
-      tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+      error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+      if(error)
+      {
+        tl->table->file->print_error(error, MYF(0));
+        return error;
+      }
       count*= tl->table->file->records;
     }
   }

--- 1.179/sql/sql_delete.cc	2006-10-16 17:39:44 +10:00
+++ 1.180/sql/sql_delete.cc	2006-10-16 17:39:44 +10:00
@@ -49,7 +49,12 @@
 	     table_list->view_db.str, table_list->view_name.str);
     DBUG_RETURN(TRUE);
   }
-  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+  error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+  if (error)
+  {
+    table->file->print_error(error, MYF(0));
+    DBUG_RETURN(error);
+  }
   thd->proc_info="init";
   table->map=1;
 

--- 1.462/sql/sql_select.cc	2006-10-16 17:39:44 +10:00
+++ 1.463/sql/sql_select.cc	2006-10-16 17:39:44 +10:00
@@ -666,6 +666,8 @@
     {
       if (res > 1)
       {
+        thd->fatal_error();
+        error= res;
         DBUG_PRINT("error",("Error from opt_sum_query"));
 	DBUG_RETURN(1);
       }
@@ -2102,7 +2104,12 @@
     s->needed_reg.init();
     table_vector[i]=s->table=table=tables->table;
     table->pos_in_table_list= tables;
-    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);// record count
+    error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+    if(error)
+    {
+        table->file->print_error(error, MYF(0));
+        DBUG_RETURN(1);
+    }
     table->quick_keys.clear_all();
     table->reginfo.join_tab=s;
     table->reginfo.not_exists_optimize=0;

--- 1.132/sql/sql_union.cc	2006-10-16 17:39:44 +10:00
+++ 1.133/sql/sql_union.cc	2006-10-16 17:39:44 +10:00
@@ -496,7 +496,12 @@
 	DBUG_RETURN(res);
       }
       /* Needed for the following test and for records_at_start in next loop */
-      table->file->info(HA_STATUS_VARIABLE);
+      int error= table->file->info(HA_STATUS_VARIABLE);
+      if(error)
+      {
+        table->file->print_error(error, MYF(0));
+        DBUG_RETURN(1);
+      }
       if (found_rows_for_union && !sl->braces && 
           select_limit_cnt != HA_POS_ERROR)
       {

--- 1.13.8.1/sql/examples/ha_archive.cc	2006-10-16 17:39:44 +10:00
+++ 1.75/sql/ha_archive.cc	2006-10-16 17:39:44 +10:00
@@ -18,10 +18,11 @@
 #pragma implementation        // gcc: Class implementation
 #endif
 
-#include "../mysql_priv.h"
+#include "mysql_priv.h"
 
-#ifdef HAVE_ARCHIVE_DB
+#if defined(HAVE_ARCHIVE_DB)
 #include "ha_archive.h"
+#include <my_dir.h>
 
 /*
   First, if you want to understand storage engines you should look at 
@@ -115,10 +116,12 @@
 */
 
 /* If the archive storage engine has been inited */
-static bool archive_inited= 0;
+static bool archive_inited= FALSE;
 /* Variables for archive share methods */
 pthread_mutex_t archive_mutex;
 static HASH archive_open_tables;
+static z_off_t max_zfile_size;
+static int zoffset_size;
 
 /* The file extension */
 #define ARZ ".ARZ"               // The data file
@@ -134,6 +137,39 @@
 #define DATA_BUFFER_SIZE 2       // Size of the data used in the data file
 #define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption
 
+/* 
+  Number of rows that will force a bulk insert.
+*/
+#define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2
+
+
+
+/* dummy handlerton - only to have something to return from archive_db_init */
+handlerton archive_hton = {
+  "ARCHIVE",
+  SHOW_OPTION_YES,
+  "Archive storage engine", 
+  DB_TYPE_ARCHIVE_DB,
+  archive_db_init,
+  0,       /* slot */
+  0,       /* savepoint size. */
+  NULL,    /* close_connection */
+  NULL,    /* savepoint */
+  NULL,    /* rollback to savepoint */
+  NULL,    /* releas savepoint */
+  NULL,    /* commit */
+  NULL,    /* rollback */
+  NULL,    /* prepare */
+  NULL,    /* recover */
+  NULL,    /* commit_by_xid */
+  NULL,    /* rollback_by_xid */
+  NULL,    /* create_cursor_read_view */
+  NULL,    /* set_cursor_read_view */
+  NULL,    /* close_cursor_read_view */
+  HTON_NO_FLAGS
+};
+
+
 /*
   Used for hash table that tracks open tables.
 */
@@ -159,13 +195,36 @@
 
 bool archive_db_init()
 {
-  archive_inited= 1;
-  VOID(pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST));
-  return (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
-                    (hash_get_key) archive_get_key, 0, 0));
+  DBUG_ENTER("archive_db_init");
+  if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST))
+    goto error;
+  if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
+                (hash_get_key) archive_get_key, 0, 0))
+  {
+    VOID(pthread_mutex_destroy(&archive_mutex));
+  }
+  else
+  {
+    zoffset_size= 2 << ((zlibCompileFlags() >> 6) & 3);
+    switch (sizeof(z_off_t)) {
+    case 2:
+      max_zfile_size= INT_MAX16;
+      break;
+    case 8:
+      max_zfile_size= LONGLONG_MAX;
+      break;
+    case 4:
+    default:
+      max_zfile_size= INT_MAX32;
+    }
+    archive_inited= TRUE;
+    DBUG_RETURN(FALSE);
+  }
+error:
+  have_archive_db= SHOW_OPTION_DISABLED;	// If we couldn't use handler
+  DBUG_RETURN(TRUE);
 }
 
-
 /*
   Release the archive handler.
 
@@ -188,6 +247,16 @@
   return FALSE;
 }
 
+ha_archive::ha_archive(TABLE *table_arg)
+  :handler(&archive_hton, table_arg), delayed_insert(0), bulk_insert(0)
+{
+  /* Set our original buffer from pre-allocated memory */
+  buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
+
+  /* The size of the offset value we will use for position() */
+  ref_length = zoffset_size;
+  DBUG_ASSERT(ref_length <= sizeof(z_off_t));
+}
 
 /*
   This method reads the header of a datafile and returns whether or not it was successful.
@@ -239,7 +308,7 @@
   This method reads the header of a meta file and returns whether or not it was successful.
   *rows will contain the current number of rows in the data file upon success.
 */
-int ha_archive::read_meta_file(File meta_file, ulonglong *rows)
+int ha_archive::read_meta_file(File meta_file, ha_rows *rows)
 {
   uchar meta_buffer[META_BUFFER_SIZE];
   ulonglong check_point;
@@ -253,7 +322,7 @@
   /*
     Parse out the meta data, we ignore version at the moment
   */
-  *rows= uint8korr(meta_buffer + 2);
+  *rows= (ha_rows)uint8korr(meta_buffer + 2);
   check_point= uint8korr(meta_buffer + 10);
 
   DBUG_PRINT("ha_archive::read_meta_file", ("Check %d", (uint)meta_buffer[0]));
@@ -274,10 +343,9 @@
 /*
   This method writes out the header of a meta file and returns whether or not it was successful.
   By setting dirty you say whether or not the file represents the actual state of the data file.
-  Upon ::open() we set to dirty, and upon ::close() we set to clean. If we determine during
-  a read that the file was dirty we will force a rebuild of this file.
+  Upon ::open() we set to dirty, and upon ::close() we set to clean.
 */
-int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty)
+int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty)
 {
   uchar meta_buffer[META_BUFFER_SIZE];
   ulonglong check_point= 0; //Reserved for the future
@@ -286,12 +354,12 @@
 
   meta_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
   meta_buffer[1]= (uchar)ARCHIVE_VERSION;
-  int8store(meta_buffer + 2, rows); 
+  int8store(meta_buffer + 2, (ulonglong)rows); 
   int8store(meta_buffer + 10, check_point); 
   *(meta_buffer + 18)= (uchar)dirty;
   DBUG_PRINT("ha_archive::write_meta_file", ("Check %d", (uint)ARCHIVE_CHECK_HEADER));
   DBUG_PRINT("ha_archive::write_meta_file", ("Version %d", (uint)ARCHIVE_VERSION));
-  DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", rows));
+  DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", (ulonglong)rows));
   DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %llu", check_point));
   DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty));
 
@@ -307,14 +375,19 @@
 
 /*
   We create the shared memory space that we will use for the open table. 
+  No matter what we try to get or create a share. This is so that a repair
+  table operation can occur. 
+
   See ha_example.cc for a longer description.
 */
-ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
+ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, 
+                                     TABLE *table, int *rc)
 {
   ARCHIVE_SHARE *share;
   char meta_file_name[FN_REFLEN];
   uint length;
   char *tmp_name;
+  DBUG_ENTER("ha_archive::get_share");
 
   pthread_mutex_lock(&archive_mutex);
   length=(uint) strlen(table_name);
@@ -329,12 +402,15 @@
                           NullS)) 
     {
       pthread_mutex_unlock(&archive_mutex);
-      return NULL;
+      *rc= HA_ERR_OUT_OF_MEM;
+      DBUG_RETURN(NULL);
     }
 
     share->use_count= 0;
     share->table_name_length= length;
     share->table_name= tmp_name;
+    share->crashed= FALSE;
+    share->archive_write_open= FALSE;
     fn_format(share->data_file_name,table_name,"",ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
     fn_format(meta_file_name,table_name,"",ARM,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
     strmov(share->table_name,table_name);
@@ -343,54 +419,28 @@
     */
     VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST));
     if ((share->meta_file= my_open(meta_file_name, O_RDWR, MYF(0))) == -1)
-      goto error;
+      share->crashed= TRUE;
     
-    if (read_meta_file(share->meta_file, &share->rows_recorded))
-    {
-      /*
-        The problem here is that for some reason, probably a crash, the meta
-        file has been corrupted. So what do we do? Well we try to rebuild it
-        ourself. Once that happens, we reread it, but if that fails we just
-        call it quits and return an error.
-      */
-      if (rebuild_meta_file(share->table_name, share->meta_file))
-        goto error;
-      if (read_meta_file(share->meta_file, &share->rows_recorded))
-        goto error;
-    }
     /*
       After we read, we set the file to dirty. When we close, we will do the 
-      opposite.
+      opposite. If the meta file will not open we assume it is crashed and
+      leave it up to the user to fix.
     */
-    (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
+    if (read_meta_file(share->meta_file, &share->rows_recorded))
+      share->crashed= TRUE;
 
-    /* 
-      It is expensive to open and close the data files and since you can't have
-      a gzip file that can be both read and written we keep a writer open
-      that is shared amoung all open tables.
-    */
-    if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
-      goto error2;
-    if (my_hash_insert(&archive_open_tables, (byte*) share))
-      goto error3;
+    VOID(my_hash_insert(&archive_open_tables, (byte*) share));
     thr_lock_init(&share->lock);
   }
   share->use_count++;
+  DBUG_PRINT("info", ("archive table %.*s has %d open handles now", 
+                      share->table_name_length, share->table_name,
+                      share->use_count));
+  if (share->crashed)
+    *rc= HA_ERR_CRASHED_ON_USAGE;
   pthread_mutex_unlock(&archive_mutex);
 
-  return share;
-
-error3:
-  /* We close, but ignore errors since we already have errors */
-  (void)gzclose(share->archive_write);
-error2:
-  my_close(share->meta_file,MYF(0));
-error:
-  pthread_mutex_unlock(&archive_mutex);
-  VOID(pthread_mutex_destroy(&share->mutex));
-  my_free((gptr) share, MYF(0));
-
-  return NULL;
+  DBUG_RETURN(share);
 }
 
 
@@ -401,30 +451,68 @@
 int ha_archive::free_share(ARCHIVE_SHARE *share)
 {
   int rc= 0;
+  DBUG_ENTER("ha_archive::free_share");
+  DBUG_PRINT("info", ("archive table %.*s has %d open handles on entrance", 
+                      share->table_name_length, share->table_name,
+                      share->use_count));
+
   pthread_mutex_lock(&archive_mutex);
   if (!--share->use_count)
   {
     hash_delete(&archive_open_tables, (byte*) share);
     thr_lock_delete(&share->lock);
     VOID(pthread_mutex_destroy(&share->mutex));
-    (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
-    if (gzclose(share->archive_write) == Z_ERRNO)
-      rc= 1;
+    if (share->crashed)
+      (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
+    else
+      (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
+    if (share->archive_write_open)
+      if (gzclose(share->archive_write) == Z_ERRNO)
+        rc= 1;
     if (my_close(share->meta_file, MYF(0)))
       rc= 1;
     my_free((gptr) share, MYF(0));
   }
   pthread_mutex_unlock(&archive_mutex);
 
-  return rc;
+  DBUG_RETURN(rc);
 }
 
+int ha_archive::init_archive_writer()
+{
+  DBUG_ENTER("ha_archive::init_archive_writer");
+  (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
 
-/* 
+  /* 
+    It is expensive to open and close the data files and since you can't have
+    a gzip file that can be both read and written we keep a writer open
+    that is shared amoung all open tables.
+  */
+  if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
+  {
+    share->crashed= TRUE;
+    DBUG_RETURN(1);
+  }
+  share->archive_write_open= TRUE;
+  info(HA_STATUS_TIME);
+  share->approx_file_size= data_file_length;
+  DBUG_RETURN(0);
+}
+
+
+/*
   We just implement one additional file extension.
 */
+static const char *ha_archive_exts[] = {
+  ARZ,
+  ARM,
+  NullS
+};
+
 const char **ha_archive::bas_ext() const
-{ static const char *ext[]= { ARZ, ARN, ARM, NullS }; return ext; }
+{
+  return ha_archive_exts;
+}
 
 
 /* 
@@ -433,21 +521,42 @@
   Init out lock.
   We open the file we will read from.
 */
-int ha_archive::open(const char *name, int mode, uint test_if_locked)
+int ha_archive::open(const char *name, int mode, uint open_options)
 {
+  int rc= 0;
   DBUG_ENTER("ha_archive::open");
 
-  if (!(share= get_share(name, table)))
-    DBUG_RETURN(1);
+  DBUG_PRINT("info", ("archive table was opened for crash %s", 
+                      (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no"));
+  share= get_share(name, table, &rc);
+
+  if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR))
+  {
+    free_share(share);
+    DBUG_RETURN(rc);
+  }
+  else if (rc == HA_ERR_OUT_OF_MEM)
+  {
+    DBUG_RETURN(rc);
+  }
+
   thr_lock_data_init(&share->lock,&lock,NULL);
 
   if ((archive= gzopen(share->data_file_name, "rb")) == NULL)
   {
-    (void)free_share(share); //We void since we already have an error
-    DBUG_RETURN(errno ? errno : -1);
+    if (errno == EROFS || errno == EACCES)
+      DBUG_RETURN(my_errno= errno);
+    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
   }
 
-  DBUG_RETURN(0);
+  DBUG_PRINT("info", ("archive table was crashed %s", 
+                      rc == HA_ERR_CRASHED_ON_USAGE ? "yes" : "no"));
+  if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR)
+  {
+    DBUG_RETURN(0);
+  }
+  else
+    DBUG_RETURN(rc);
 }
 
 
@@ -520,7 +629,7 @@
     error= my_errno;
     goto error;
   }
-  if ((archive= gzdopen(create_file, "wb")) == NULL)
+  if ((archive= gzdopen(dup(create_file), "wb")) == NULL)
   {
     error= errno;
     goto error2;
@@ -552,6 +661,55 @@
   DBUG_RETURN(error ? error : -1);
 }
 
+/*
+  This is where the actual row is written out.
+*/
+int ha_archive::real_write_row(byte *buf, gzFile writer)
+{
+  z_off_t written, total_row_length;
+  uint *ptr, *end;
+  DBUG_ENTER("ha_archive::real_write_row");
+  total_row_length= table->s->reclength;
+  for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields;
+       ptr != end; ptr++)
+    total_row_length+= ((Field_blob*) table->field[*ptr])->get_length();
+  if (share->approx_file_size > max_zfile_size - total_row_length)
+  {
+    info(HA_STATUS_TIME);
+    share->approx_file_size= data_file_length;
+    if (share->approx_file_size > max_zfile_size - total_row_length)
+      DBUG_RETURN(HA_ERR_RECORD_FILE_FULL);
+  }
+  share->approx_file_size+= total_row_length;
+  written= gzwrite(writer, buf, table->s->reclength);
+  DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength));
+  if (!delayed_insert || !bulk_insert)
+    share->dirty= TRUE;
+
+  if (written != (z_off_t)table->s->reclength)
+    DBUG_RETURN(errno ? errno : -1);
+  /*
+    We should probably mark the table as damagaged if the record is written
+    but the blob fails.
+  */
+  for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields ;
+       ptr != end ;
+       ptr++)
+  {
+    char *data_ptr;
+    uint32 size= ((Field_blob*) table->field[*ptr])->get_length();
+
+    if (size)
+    {
+      ((Field_blob*) table->field[*ptr])->get_ptr(&data_ptr);
+      written= gzwrite(writer, data_ptr, (unsigned)size);
+      if (written != (z_off_t)size)
+        DBUG_RETURN(errno ? errno : -1);
+    }
+  }
+  DBUG_RETURN(0);
+}
+
 
 /* 
   Look at ha_archive::open() for an explanation of the row format.
@@ -562,48 +720,51 @@
   for implementing start_bulk_insert() is that we could skip 
   setting dirty to true each time.
 */
-int ha_archive::write_row(byte * buf)
+int ha_archive::write_row(byte *buf)
 {
-  z_off_t written;
-  Field_blob **field;
+  int rc;
   DBUG_ENTER("ha_archive::write_row");
 
-  statistic_increment(ha_write_count,&LOCK_status);
+  if (share->crashed)
+      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+  statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
     table->timestamp_field->set_time();
   pthread_mutex_lock(&share->mutex);
-  written= gzwrite(share->archive_write, buf, table->reclength);
-  DBUG_PRINT("ha_archive::get_row", ("Wrote %d bytes expected %d", written, table->reclength));
-  share->dirty= TRUE;
-  if (written != (z_off_t)table->reclength)
-    goto error;
+  if (!share->archive_write_open)
+    if (init_archive_writer())
+      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
   /*
-    We should probably mark the table as damagaged if the record is written
-    but the blob fails.
+    Varchar structures are constant in size but are not cleaned up request
+    to request. The following sets all unused space to null to improve
+    compression.
   */
-  for (field= table->blob_field ; *field ; field++)
+  for (Field **field=table->field ; *field ; field++)
   {
-    char *ptr;
-    uint32 size= (*field)->get_length();
-
-    if (size)
+    DBUG_PRINT("archive",("Pack is %d\n", (*field)->pack_length()));
+    DBUG_PRINT("archive",("MyPack is %d\n", (*field)->data_length((char*) buf + (*field)->offset())));
+    if ((*field)->real_type() == MYSQL_TYPE_VARCHAR) 
     {
-      (*field)->get_ptr(&ptr);
-      written= gzwrite(share->archive_write, ptr, (unsigned)size);
-      if (written != (z_off_t)size)
-        goto error;
+      uint actual_length= (*field)->data_length((char*) buf + (*field)->offset());
+      uint offset= (*field)->offset() + actual_length + 
+        (actual_length > 255 ? 2 : 1);
+      DBUG_PRINT("archive",("Offset is %d -> %d\n", actual_length, offset));
+      /*
+      if ((*field)->pack_length() + (*field)->offset() != offset)
+        bzero(buf + offset, (size_t)((*field)->pack_length() + (actual_length > 255 ? 2 : 1) - (*field)->data_length));
+    */
     }
   }
+
   share->rows_recorded++;
+  rc= real_write_row(buf, share->archive_write);
   pthread_mutex_unlock(&share->mutex);
 
-  DBUG_RETURN(0);
-error:
-  pthread_mutex_unlock(&share->mutex);
-  DBUG_RETURN(errno ? errno : -1);
+  DBUG_RETURN(rc);
 }
 
-
 /*
   All calls that need to scan the table start with this method. If we are told
   that it is a table scan we rewind the file to the beginning, otherwise
@@ -613,11 +774,15 @@
 int ha_archive::rnd_init(bool scan)
 {
   DBUG_ENTER("ha_archive::rnd_init");
+  
+  if (share->crashed)
+      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
   /* We rewind the file so that we can read from the beginning if scan */
   if (scan)
   {
     scan_rows= share->rows_recorded;
+    DBUG_PRINT("info", ("archive will retrieve %llu rows", scan_rows));
     records= 0;
 
     /* 
@@ -629,6 +794,7 @@
       pthread_mutex_lock(&share->mutex);
       if (share->dirty == TRUE)
       {
+        DBUG_PRINT("info", ("archive flushing out rows for scan"));
         gzflush(share->archive_write, Z_SYNC_FLUSH);
         share->dirty= FALSE;
       }
@@ -650,13 +816,13 @@
 int ha_archive::get_row(gzFile file_to_read, byte *buf)
 {
   int read; // Bytes read, gzread() returns int
+  uint *ptr, *end;
   char *last;
   size_t total_blob_length= 0;
-  Field_blob **field;
   DBUG_ENTER("ha_archive::get_row");
 
-  read= gzread(file_to_read, buf, table->reclength);
-  DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->reclength));
+  read= gzread(file_to_read, buf, table->s->reclength);
+  DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->s->reclength));
 
   if (read == Z_STREAM_ERROR)
     DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
@@ -665,28 +831,35 @@
   if (read == 0)
     DBUG_RETURN(HA_ERR_END_OF_FILE);
 
-  /* If the record is the wrong size, the file is probably damaged */
-  if ((ulong) read != table->reclength)
-    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+  /* 
+    If the record is the wrong size, the file is probably damaged, unless 
+    we are dealing with a delayed insert or a bulk insert.
+  */
+  if ((ulong) read != table->s->reclength)
+    DBUG_RETURN(HA_ERR_END_OF_FILE);
 
   /* Calculate blob length, we use this for our buffer */
-  for (field=table->blob_field; *field ; field++)
-    total_blob_length += (*field)->get_length();
+  for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+       ptr != end ;
+       ptr++)
+    total_blob_length += ((Field_blob*) table->field[*ptr])->get_length();
 
   /* Adjust our row buffer if we need be */
   buffer.alloc(total_blob_length);
   last= (char *)buffer.ptr();
 
   /* Loop through our blobs and read them */
-  for (field=table->blob_field; *field ; field++)
+  for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+       ptr != end ;
+       ptr++)
   {
-    size_t size= (*field)->get_length();
+    size_t size= ((Field_blob*) table->field[*ptr])->get_length();
     if (size)
     {
       read= gzread(file_to_read, last, size);
       if ((size_t) read != size)
-        DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
-      (*field)->set_ptr(size, last);
+        DBUG_RETURN(HA_ERR_END_OF_FILE);
+      ((Field_blob*) table->field[*ptr])->set_ptr(size, last);
       last += size;
     }
   }
@@ -704,11 +877,15 @@
   int rc;
   DBUG_ENTER("ha_archive::rnd_next");
 
+  if (share->crashed)
+      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
   if (!scan_rows)
     DBUG_RETURN(HA_ERR_END_OF_FILE);
   scan_rows--;
 
-  statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+  statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+		      &LOCK_status);
   current_position= gztell(archive);
   rc= get_row(archive, buf);
 
@@ -720,7 +897,7 @@
 }
 
 
-/* 
+/*
   Thanks to the table flag HA_REC_NOT_IN_SEQ this will be called after
   each call to ha_archive::rnd_next() if an ordering of the rows is
   needed.
@@ -729,7 +906,7 @@
 void ha_archive::position(const byte *record)
 {
   DBUG_ENTER("ha_archive::position");
-  ha_store_ptr(ref, ref_length, current_position);
+  my_store_ptr(ref, ref_length, current_position);
   DBUG_VOID_RETURN;
 }
 
@@ -744,68 +921,30 @@
 int ha_archive::rnd_pos(byte * buf, byte *pos)
 {
   DBUG_ENTER("ha_archive::rnd_pos");
-  statistic_increment(ha_read_rnd_count,&LOCK_status);
-  current_position= ha_get_ptr(pos, ref_length);
+  statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+		      &LOCK_status);
+  current_position= (z_off_t)my_get_ptr(pos, ref_length);
   (void)gzseek(archive, current_position, SEEK_SET);
 
   DBUG_RETURN(get_row(archive, buf));
 }
 
 /*
-  This method rebuilds the meta file. It does this by walking the datafile and 
-  rewriting the meta file.
+  This method repairs the meta file. It does this by walking the datafile and 
+  rewriting the meta file. Currently it does this by calling optimize with
+  the extended flag.
 */
-int ha_archive::rebuild_meta_file(char *table_name, File meta_file)
+int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
 {
-  int rc;
-  byte *buf; 
-  ulonglong rows_recorded= 0;
-  gzFile rebuild_file;            /* Archive file we are working with */
-  char data_file_name[FN_REFLEN];
-  DBUG_ENTER("ha_archive::rebuild_meta_file");
+  DBUG_ENTER("ha_archive::repair");
+  check_opt->flags= T_EXTEND;
+  int rc= optimize(thd, check_opt);
 
-  /*
-    Open up the meta file to recreate it.
-  */
-  fn_format(data_file_name, table_name, "", ARZ,
-            MY_REPLACE_EXT|MY_UNPACK_FILENAME);
-  if ((rebuild_file= gzopen(data_file_name, "rb")) == NULL)
-    DBUG_RETURN(errno ? errno : -1);
+  if (rc)
+    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
 
-  if ((rc= read_data_header(rebuild_file)))
-    goto error;
-
-  /*
-    We malloc up the buffer we will use for counting the rows. 
-    I know, this malloc'ing memory but this should be a very 
-    rare event.
-  */
-  if (!(buf= (byte*) my_malloc(table->rec_buff_length > sizeof(ulonglong) +1 ? 
-                               table->rec_buff_length : sizeof(ulonglong) +1 ,
-                               MYF(MY_WME))))
-  {
-    rc= HA_ERR_CRASHED_ON_USAGE;
-    goto error;
-  }
-
-  while (!(rc= get_row(rebuild_file, buf)))
-    rows_recorded++;
-
-  /* 
-    Only if we reach the end of the file do we assume we can rewrite.
-    At this point we reset rc to a non-message state.
-  */
-  if (rc == HA_ERR_END_OF_FILE)
-  {
-    (void)write_meta_file(meta_file, rows_recorded, FALSE);
-    rc= 0;
-  }
-
-  my_free((gptr) buf, MYF(0));
-error:
-  gzclose(rebuild_file);
-
-  DBUG_RETURN(rc);
+  share->crashed= FALSE;
+  DBUG_RETURN(0);
 }
 
 /*
@@ -815,56 +954,116 @@
 int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
 {
   DBUG_ENTER("ha_archive::optimize");
-  int read; // Bytes read, gzread() returns int
-  gzFile reader, writer;
-  char block[IO_SIZE];
+  int rc;
+  gzFile writer;
   char writer_filename[FN_REFLEN];
 
+  /* Open up the writer if we haven't yet */
+  if (!share->archive_write_open)
+    init_archive_writer();
+
+  /* Flush any waiting data */
+  gzflush(share->archive_write, Z_SYNC_FLUSH);
+
   /* Lets create a file to contain the new data */
   fn_format(writer_filename, share->table_name, "", ARN, 
             MY_REPLACE_EXT|MY_UNPACK_FILENAME);
 
-  /* Closing will cause all data waiting to be flushed, to be flushed */
-  gzclose(share->archive_write);
+  if ((writer= gzopen(writer_filename, "wb")) == NULL)
+    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); 
 
-  if ((reader= gzopen(share->data_file_name, "rb")) == NULL)
-    DBUG_RETURN(-1); 
+  /* 
+    An extended rebuild is a lot more effort. We open up each row and re-record it. 
+    Any dead rows are removed (aka rows that may have been partially recorded). 
+  */
 
-  if ((writer= gzopen(writer_filename, "wb")) == NULL)
+  if (check_opt->flags == T_EXTEND)
   {
-    gzclose(reader);
-    DBUG_RETURN(-1); 
-  }
+    byte *buf; 
 
-  while ((read= gzread(reader, block, IO_SIZE)))
-    gzwrite(writer, block, read);
+    /* 
+      First we create a buffer that we can use for reading rows, and can pass
+      to get_row().
+    */
+    if (!(buf= (byte*) my_malloc(table->s->reclength, MYF(MY_WME))))
+    {
+      rc= HA_ERR_OUT_OF_MEM;
+      goto error;
+    }
 
-  gzclose(reader);
-  gzclose(writer);
+    /*
+      Now we will rewind the archive file so that we are positioned at the 
+      start of the file.
+    */
+    rc= read_data_header(archive);
+    
+    /*
+      Assuming now error from rewinding the archive file, we now write out the 
+      new header for out data file.
+    */
+    if (!rc)
+      rc= write_data_header(writer);
+
+    /* 
+      On success of writing out the new header, we now fetch each row and
+      insert it into the new archive file. 
+    */
+    if (!rc)
+    {
+      share->rows_recorded= 0;
+      while (!(rc= get_row(archive, buf)))
+      {
+        real_write_row(buf, writer);
+        share->rows_recorded++;
+      }
+    }
+    DBUG_PRINT("info", ("recovered %llu archive rows", share->rows_recorded));
+
+    my_free((char*)buf, MYF(0));
+    if (rc && rc != HA_ERR_END_OF_FILE)
+      goto error;
+  } 
+  else
+  {
+    /* 
+      The quick method is to just read the data raw, and then compress it directly.
+    */
+    int read; // Bytes read, gzread() returns int
+    char block[IO_SIZE];
+    if (gzrewind(archive) == -1)
+    {
+      rc= HA_ERR_CRASHED_ON_USAGE;
+      goto error;
+    }
+
+    while ((read= gzread(archive, block, IO_SIZE)))
+      gzwrite(writer, block, read);
+  }
+
+  gzflush(writer, Z_SYNC_FLUSH);
+  share->dirty= FALSE;
+  gzclose(share->archive_write);
+  share->archive_write= writer; 
 
   my_rename(writer_filename,share->data_file_name,MYF(0));
 
-  /* 
-    We reopen the file in case some IO is waiting to go through.
-    In theory the table is closed right after this operation,
-    but it is possible for IO to still happen.
-    I may be being a bit too paranoid right here.
+  /*
+    Now we need to reopen our read descriptor since it has changed.
   */
-  if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
-    DBUG_RETURN(errno ? errno : -1);
-  share->dirty= FALSE;
+  gzclose(archive);
+  if ((archive= gzopen(share->data_file_name, "rb")) == NULL)
+  {
+    rc= HA_ERR_CRASHED_ON_USAGE;
+    goto error;
+  }
+
 
   DBUG_RETURN(0); 
-}
 
+error:
+  gzclose(writer);
 
-/*
-  No transactions yet, so this is pretty dull.
-*/
-int ha_archive::external_lock(THD *thd, int lock_type)
-{
-  DBUG_ENTER("ha_archive::external_lock");
-  DBUG_RETURN(0);
+  DBUG_RETURN(rc); 
 }
 
 /* 
@@ -874,6 +1073,11 @@
                                        THR_LOCK_DATA **to,
                                        enum thr_lock_type lock_type)
 {
+  if (lock_type == TL_WRITE_DELAYED)
+    delayed_insert= TRUE;
+  else
+    delayed_insert= FALSE;
+
   if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) 
   {
     /* 
@@ -908,108 +1112,144 @@
 }
 
 
-/******************************************************************************
-
-  Everything below here is default, please look at ha_example.cc for 
-  descriptions.
-
- ******************************************************************************/
-
-int ha_archive::update_row(const byte * old_data, byte * new_data)
+/*
+  Hints for optimizer, see ha_tina for more information
+*/
+int ha_archive::info(uint flag)
 {
+  DBUG_ENTER("ha_archive::info");
+  /* 
+    This should be an accurate number now, though bulk and delayed inserts can
+    cause the number to be inaccurate.
+  */
+  records= share->rows_recorded;
+  deleted= 0;
+  /* Costs quite a bit more to get all information */
+  if (flag & HA_STATUS_TIME)
+  {
+    MY_STAT file_stat;  // Stat information for the data file
 
-  DBUG_ENTER("ha_archive::update_row");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_archive::delete_row(const byte * buf)
-{
-  DBUG_ENTER("ha_archive::delete_row");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
+    VOID(my_stat(share->data_file_name, &file_stat, MYF(MY_WME)));
 
-int ha_archive::index_read(byte * buf, const byte * key,
-                           uint key_len __attribute__((unused)),
-                           enum ha_rkey_function find_flag
-                           __attribute__((unused)))
-{
-  DBUG_ENTER("ha_archive::index_read");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
+    mean_rec_length= table->s->reclength + buffer.alloced_length();
+    data_file_length= file_stat.st_size;
+    create_time= file_stat.st_ctime;
+    update_time= file_stat.st_mtime;
+    max_data_file_length= share->rows_recorded * mean_rec_length;
+  }
+  delete_length= 0;
+  index_file_length=0;
 
-int ha_archive::index_read_idx(byte * buf, uint index, const byte * key,
-                               uint key_len __attribute__((unused)),
-                               enum ha_rkey_function find_flag
-                               __attribute__((unused)))
-{
-  DBUG_ENTER("ha_archive::index_read_idx");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+  DBUG_RETURN(0);
 }
 
 
-int ha_archive::index_next(byte * buf)
-{
-  DBUG_ENTER("ha_archive::index_next");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+/*
+  This method tells us that a bulk insert operation is about to occur. We set
+  a flag which will keep write_row from saying that its data is dirty. This in
+  turn will keep selects from causing a sync to occur.
+  Basically, yet another optimizations to keep compression working well.
+*/
+void ha_archive::start_bulk_insert(ha_rows rows)
+{
+  DBUG_ENTER("ha_archive::start_bulk_insert");
+  if (!rows || rows >= ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT)
+    bulk_insert= TRUE;
+  DBUG_VOID_RETURN;
 }
 
-int ha_archive::index_prev(byte * buf)
+
+/* 
+  Other side of start_bulk_insert, is end_bulk_insert. Here we turn off the bulk insert
+  flag, and set the share dirty so that the next select will call sync for us.
+*/
+int ha_archive::end_bulk_insert()
 {
-  DBUG_ENTER("ha_archive::index_prev");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+  DBUG_ENTER("ha_archive::end_bulk_insert");
+  bulk_insert= FALSE;
+  share->dirty= TRUE;
+  DBUG_RETURN(0);
 }
 
-int ha_archive::index_first(byte * buf)
+/*
+  We cancel a truncate command. The only way to delete an archive table is to drop it.
+  This is done for security reasons. In a later version we will enable this by 
+  allowing the user to select a different row format.
+*/
+int ha_archive::delete_all_rows()
 {
-  DBUG_ENTER("ha_archive::index_first");
+  DBUG_ENTER("ha_archive::delete_all_rows");
   DBUG_RETURN(HA_ERR_WRONG_COMMAND);
 }
 
-int ha_archive::index_last(byte * buf)
+/*
+  We just return state if asked.
+*/
+bool ha_archive::is_crashed() const 
 {
-  DBUG_ENTER("ha_archive::index_last");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+  DBUG_ENTER("ha_archive::is_crashed");
+  DBUG_RETURN(share->crashed); 
 }
 
+/*
+  Simple scan of the tables to make sure everything is ok.
+*/
 
-int ha_archive::info(uint flag)
+int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
 {
-  DBUG_ENTER("ha_archive::info");
+  int rc= 0;
+  byte *buf; 
+  const char *old_proc_info=thd->proc_info;
+  ha_rows count= share->rows_recorded;
+  DBUG_ENTER("ha_archive::check");
+
+  thd->proc_info= "Checking table";
+  /* Flush any waiting data */
+  gzflush(share->archive_write, Z_SYNC_FLUSH);
 
-  /* This is a lie, but you don't want the optimizer to see zero or 1 */
-  records= share->rows_recorded;
-  deleted= 0;
+  /* 
+    First we create a buffer that we can use for reading rows, and can pass
+    to get_row().
+  */
+  if (!(buf= (byte*) my_malloc(table->s->reclength, MYF(MY_WME))))
+    rc= HA_ERR_OUT_OF_MEM;
 
-  DBUG_RETURN(0);
-}
+  /*
+    Now we will rewind the archive file so that we are positioned at the 
+    start of the file.
+  */
+  if (!rc)
+    read_data_header(archive);
 
-int ha_archive::extra(enum ha_extra_function operation)
-{
-  DBUG_ENTER("ha_archive::extra");
-  DBUG_RETURN(0);
-}
+  if (!rc)
+    while (!(rc= get_row(archive, buf)))
+      count--;
 
-int ha_archive::reset(void)
-{
-  DBUG_ENTER("ha_archive::reset");
-  DBUG_RETURN(0);
-}
+  my_free((char*)buf, MYF(0));
 
-ha_rows ha_archive::records_in_range(uint inx, key_range *min_key,
-                                     key_range *max_key)
-{
-  DBUG_ENTER("ha_archive::records_in_range ");
-  DBUG_RETURN(records); // HA_ERR_WRONG_COMMAND 
+  thd->proc_info= old_proc_info;
+
+  if ((rc && rc != HA_ERR_END_OF_FILE) || count)  
+  {
+    share->crashed= FALSE;
+    DBUG_RETURN(HA_ADMIN_CORRUPT);
+  }
+  else
+  {
+    DBUG_RETURN(HA_ADMIN_OK);
+  }
 }
 
 /*
-  We cancel a truncate command. The only way to delete an archive table is to drop it.
-  This is done for security reasons. In a later version we will enable this by 
-  allowing the user to select a different row format.
+  Check and repair the table if needed.
 */
-int ha_archive::delete_all_rows()
+bool ha_archive::check_and_repair(THD *thd) 
 {
-  DBUG_ENTER("ha_archive::delete_all_rows");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+  HA_CHECK_OPT check_opt;
+  DBUG_ENTER("ha_archive::check_and_repair");
+
+  check_opt.init();
+
+  DBUG_RETURN(repair(thd, &check_opt));
 }
 #endif /* HAVE_ARCHIVE_DB */

--- 1.9.1.7/sql/examples/ha_archive.h	2006-10-16 17:39:44 +10:00
+++ 1.35/sql/ha_archive.h	2006-10-16 17:39:44 +10:00
@@ -32,10 +32,13 @@
   uint table_name_length,use_count;
   pthread_mutex_t mutex;
   THR_LOCK lock;
-  File meta_file;                   /* Meta file we use */
-  gzFile archive_write;             /* Archive file we are working with */
-  bool dirty;                       /* Flag for if a flush should occur */
-  ulonglong rows_recorded;          /* Number of rows in tables */
+  File meta_file;           /* Meta file we use */
+  gzFile archive_write;     /* Archive file we are working with */
+  bool archive_write_open;
+  bool dirty;               /* Flag for if a flush should occur */
+  bool crashed;             /* Meta file is crashed */
+  ha_rows rows_recorded;    /* Number of rows in tables */
+  z_off_t approx_file_size; /* Approximate archive data file size */
 } ARCHIVE_SHARE;
 
 /*
@@ -52,17 +55,12 @@
   z_off_t current_position;  /* The position of the row we just read */
   byte byte_buffer[IO_SIZE]; /* Initial buffer for our string */
   String buffer;             /* Buffer used for blob storage */
-  ulonglong scan_rows;       /* Number of rows left in scan */
+  ha_rows scan_rows;         /* Number of rows left in scan */
+  bool delayed_insert;       /* If the insert is delayed */
+  bool bulk_insert;          /* If we are performing a bulk insert */
 
 public:
-  ha_archive(TABLE *table): handler(table)
-  {
-    /* Set our original buffer from pre-allocated memory */
-    buffer.set((char*)byte_buffer, IO_SIZE, system_charset_info);
-
-    /* The size of the offset value we will use for position() */
-    ref_length = sizeof(z_off_t);
-  }
+  ha_archive(TABLE *table_arg);
   ~ha_archive()
   {
   }
@@ -72,59 +70,45 @@
   ulong table_flags() const
   {
     return (HA_REC_NOT_IN_SEQ | HA_NOT_EXACT_COUNT | HA_NO_AUTO_INCREMENT |
-            HA_FILE_BASED);
+            HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
   }
   ulong index_flags(uint idx, uint part, bool all_parts) const
   {
     return 0;
   }
-  /*
-    Have to put something here, there is no real limit as far as
-    archive is concerned.
-  */
-  uint max_supported_record_length() const { return UINT_MAX; }
-  /*
-    Called in test_quick_select to determine if indexes should be used.
-  */
-  virtual double scan_time() { return (double) (records) / 20.0+10; }
-  /* The next method will never be called */
-  virtual double read_time(uint index, uint ranges, ha_rows rows)
-  { return (double) rows /  20.0+1; }
   int open(const char *name, int mode, uint test_if_locked);
   int close(void);
   int write_row(byte * buf);
-  int update_row(const byte * old_data, byte * new_data);
-  int delete_row(const byte * buf);
+  int real_write_row(byte *buf, gzFile writer);
   int delete_all_rows();
-  int index_read(byte * buf, const byte * key,
-                 uint key_len, enum ha_rkey_function find_flag);
-  int index_read_idx(byte * buf, uint idx, const byte * key,
-                     uint key_len, enum ha_rkey_function find_flag);
-  int index_next(byte * buf);
-  int index_prev(byte * buf);
-  int index_first(byte * buf);
-  int index_last(byte * buf);
   int rnd_init(bool scan=1);
   int rnd_next(byte *buf);
   int rnd_pos(byte * buf, byte *pos);
   int get_row(gzFile file_to_read, byte *buf);
-  int read_meta_file(File meta_file, ulonglong *rows);
-  int write_meta_file(File meta_file, ulonglong rows, bool dirty);
-  ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table);
+  int read_meta_file(File meta_file, ha_rows *rows);
+  int write_meta_file(File meta_file, ha_rows rows, bool dirty);
+  ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table, int *rc);
   int free_share(ARCHIVE_SHARE *share);
-  int rebuild_meta_file(char *table_name, File meta_file);
+  int init_archive_writer();
+  bool auto_repair() const { return 1; } // For the moment we just do this
   int read_data_header(gzFile file_to_read);
   int write_data_header(gzFile file_to_write);
   void position(const byte *record);
   int info(uint);
-  int extra(enum ha_extra_function operation);
-  int reset(void);
-  int external_lock(THD *thd, int lock_type);
-  ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
   int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
   int optimize(THD* thd, HA_CHECK_OPT* check_opt);
+  int repair(THD* thd, HA_CHECK_OPT* check_opt);
+  void start_bulk_insert(ha_rows rows);
+  int end_bulk_insert();
+  enum row_type get_row_type() const 
+  { 
+    return ROW_TYPE_COMPRESSED;
+  }
   THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
                              enum thr_lock_type lock_type);
+  bool is_crashed() const;
+  int check(THD* thd, HA_CHECK_OPT* check_opt);
+  bool check_and_repair(THD *thd);
 };
 
 bool archive_db_init(void);

--- 1.24/sql/examples/ha_tina.cc	2006-10-16 17:39:44 +10:00
+++ 1.25/sql/examples/ha_tina.cc	2006-10-16 17:39:44 +10:00
@@ -792,13 +792,13 @@
   Currently this table handler doesn't implement most of the fields
   really needed. SHOW also makes use of this data
 */
-void ha_tina::info(uint flag)
+int ha_tina::info(uint flag)
 {
   DBUG_ENTER("ha_tina::info");
   /* This is a lie, but you don't want the optimizer to see zero or 1 */
   if (!records_is_known && records < 2) 
     records= 2;
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(0);
 }
 
 /*

--- 1.6/sql/examples/ha_tina.h	2006-10-16 17:39:44 +10:00
+++ 1.7/sql/examples/ha_tina.h	2006-10-16 17:39:44 +10:00
@@ -105,7 +105,7 @@
   int rnd_pos(byte * buf, byte *pos);
   int rnd_end();
   void position(const byte *record);
-  void info(uint);
+  int info(uint);
   int extra(enum ha_extra_function operation);
   int reset(void);
   int external_lock(THD *thd, int lock_type);

--- 1.20/sql/examples/ha_example.cc	2006-10-16 17:39:44 +10:00
+++ 1.21/sql/examples/ha_example.cc	2006-10-16 17:39:44 +10:00
@@ -523,10 +523,10 @@
     sql_update.cc
 
 */
-void ha_example::info(uint flag)
+int ha_example::info(uint flag)
 {
   DBUG_ENTER("ha_example::info");
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(0);
 }
 
 

--- 1.10/sql/examples/ha_example.h	2006-10-16 17:39:44 +10:00
+++ 1.11/sql/examples/ha_example.h	2006-10-16 17:39:44 +10:00
@@ -136,7 +136,7 @@
   int rnd_next(byte *buf);                                      //required
   int rnd_pos(byte * buf, byte *pos);                           //required
   void position(const byte *record);                            //required
-  void info(uint);                                              //required
+  int info(uint);                                              //required
 
   int extra(enum ha_extra_function operation);
   int reset(void);

--- 1.23/sql/ha_blackhole.cc	2006-10-16 17:39:44 +10:00
+++ 1.24/sql/ha_blackhole.cc	2006-10-16 17:39:44 +10:00
@@ -138,7 +138,7 @@
 }
 
 
-void ha_blackhole::info(uint flag)
+int ha_blackhole::info(uint flag)
 {
   DBUG_ENTER("ha_blackhole::info");
 
@@ -152,7 +152,7 @@
   delete_length= 0;
   if (flag & HA_STATUS_AUTO)
     auto_increment_value= 1;
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(0);
 }
 
 int ha_blackhole::external_lock(THD *thd, int lock_type)

--- 1.5/sql/ha_blackhole.h	2006-10-16 17:39:44 +10:00
+++ 1.6/sql/ha_blackhole.h	2006-10-16 17:39:44 +10:00
@@ -76,7 +76,7 @@
   int index_first(byte * buf);
   int index_last(byte * buf);
   void position(const byte *record);
-  void info(uint flag);
+  int info(uint flag);
   int external_lock(THD *thd, int lock_type);
   uint lock_count(void) const;
   int create(const char *name, TABLE *table_arg,

--- 1.280/sql/ha_ndbcluster.cc	2006-10-16 17:39:44 +10:00
+++ 1.281/sql/ha_ndbcluster.cc	2006-10-16 17:39:44 +10:00
@@ -355,11 +355,13 @@
   DBUG_VOID_RETURN;
 }
 
-void ha_ndbcluster::records_update()
+int ha_ndbcluster::records_update()
 {
   if (m_ha_not_exact_count)
-    return;
+    return 0;
   DBUG_ENTER("ha_ndbcluster::records_update");
+  int result= 0;
+
   struct Ndb_local_table_statistics *info= 
     (struct Ndb_local_table_statistics *)m_table_info;
   DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
@@ -370,7 +372,7 @@
     Ndb *ndb= get_ndb();
     struct Ndb_statistics stat;
     ndb->setDatabaseName(m_dbname);
-    if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){
+    if ((result= ndb_get_table_statistics(ndb, m_tabname, &stat)) == 0){
       mean_rec_length= stat.row_size;
       data_file_length= stat.fragment_memory;
       info->records= stat.row_count;
@@ -382,7 +384,7 @@
       info->no_uncommitted_rows_count= 0;
   }
   records= info->records+ info->no_uncommitted_rows_count;
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(result);
 }
 
 void ha_ndbcluster::no_uncommitted_rows_execute_failure()
@@ -3086,8 +3088,9 @@
 }
 
 
-void ha_ndbcluster::info(uint flag)
+int ha_ndbcluster::info(uint flag)
 {
+  int result= 0;
   DBUG_ENTER("info");
   DBUG_PRINT("enter", ("flag: %d", flag));
   
@@ -3105,17 +3108,17 @@
       if (m_ha_not_exact_count)
         records= 100;
       else
-        records_update();
+	result= records_update();
     }
     else
     {
       if ((my_errno= check_ndb_connection()))
-        DBUG_VOID_RETURN;
+        DBUG_RETURN(my_errno);
       Ndb *ndb= get_ndb();
       struct Ndb_statistics stat;
       ndb->setDatabaseName(m_dbname);
       if (current_thd->variables.ndb_use_exact_count &&
-          ndb_get_table_statistics(ndb, m_tabname, &stat) == 0)
+          (result= ndb_get_table_statistics(ndb, m_tabname, &stat)) == 0)
       {
         mean_rec_length= stat.row_size;
         data_file_length= stat.fragment_memory;
@@ -3158,7 +3161,11 @@
         auto_increment_value= (ulonglong)auto_increment_value64;
     }
   }
-  DBUG_VOID_RETURN;
+
+  if(result == -1)
+    result= HA_ERR_NO_CONNECTION;
+
+  DBUG_RETURN(result);
 }
 
 

--- 1.100/sql/ha_ndbcluster.h	2006-10-16 17:39:44 +10:00
+++ 1.101/sql/ha_ndbcluster.h	2006-10-16 17:39:44 +10:00
@@ -505,7 +505,7 @@
   int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
 
   bool get_error_message(int error, String *buf);
-  void info(uint);
+  int info(uint);
   int extra(enum ha_extra_function operation);
   int extra_opt(enum ha_extra_function operation, ulong cache_size);
   int external_lock(THD *thd, int lock_type);
@@ -657,7 +657,7 @@
   int check_ndb_connection(THD* thd= current_thd);
 
   void set_rec_per_key();
-  void records_update();
+  int records_update();
   void no_uncommitted_rows_execute_failure();
   void no_uncommitted_rows_update(int);
   void no_uncommitted_rows_init(THD *);

--- 1.300/sql/ha_innodb.cc	2006-10-16 17:39:44 +10:00
+++ 1.301/sql/ha_innodb.cc	2006-10-16 17:39:44 +10:00
@@ -5258,7 +5258,7 @@
 Returns statistics information of the table to the MySQL interpreter,
 in various fields of the handle object. */
 
-void
+int
 ha_innobase::info(
 /*==============*/
 	uint flag)	/* in: what information MySQL requests */
@@ -5281,7 +5281,7 @@
 
         if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
-                DBUG_VOID_RETURN;
+                DBUG_RETURN(HA_ERR_CRASHED);
         }
 
 	/* We do not know if MySQL can call this function before calling
@@ -5476,7 +5476,7 @@
 
 	prebuilt->trx->op_info = (char*)"";
 
-  	DBUG_VOID_RETURN;
+  	DBUG_RETURN(0);
 }
 
 /**************************************************************************

--- 1.112/sql/ha_innodb.h	2006-10-16 17:39:44 +10:00
+++ 1.113/sql/ha_innodb.h	2006-10-16 17:39:44 +10:00
@@ -140,7 +140,7 @@
   	int rnd_pos(byte * buf, byte *pos);
 
   	void position(const byte *record);
-  	void info(uint);
+  	int info(uint);
         int analyze(THD* thd,HA_CHECK_OPT* check_opt);
         int optimize(THD* thd,HA_CHECK_OPT* check_opt);
 	int discard_or_import_tablespace(my_bool discard);
Thread
bk commit into 5.0 tree (stewart:1.2265)Stewart Smith16 Oct