List:Commits« Previous MessageNext Message »
From:eugene Date:June 18 2006 10:56am
Subject:bk commit into 5.1 tree (evgen:1.2218)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of evgen. When evgen 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
  1.2218 06/06/18 14:56:35 evgen@stripped +49 -0
  Manually merged

  sql/item_timefunc.h
    1.72 06/06/18 14:56:31 evgen@stripped +1 -1
    Manually merged

  sql/item_cmpfunc.cc
    1.206 06/06/18 14:56:31 evgen@stripped +0 -12
    Manually merged

  sql/field.h
    1.187 06/06/18 14:56:31 evgen@stripped +0 -0
    Manually merged

  mysql-test/r/select.result
    1.129 06/06/18 14:56:31 evgen@stripped +64 -0
    Manually merged

  mysql-test/r/rpl_stm_log.result
    1.69 06/06/18 14:56:31 evgen@stripped +0 -0
    Manually merged

  mysql-test/extra/rpl_tests/rpl_log.test
    1.38 06/06/18 14:56:31 evgen@stripped +6 -5
    Manually merged

  tests/mysql_client_test.c
    1.193 06/06/18 14:20:29 evgen@stripped +0 -0
    Auto merged

  storage/archive/ha_archive.cc
    1.98 06/06/18 14:20:29 evgen@stripped +0 -0
    Auto merged

  sql/structs.h
    1.61 06/06/18 14:20:29 evgen@stripped +0 -0
    Auto merged

  sql/sql_yacc.yy
    1.482 06/06/18 14:20:29 evgen@stripped +0 -0
    Auto merged

  sql/sql_select.h
    1.108 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_select.cc
    1.413 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.561 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_lex.h
    1.233 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_lex.cc
    1.185 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_insert.cc
    1.204 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_class.h
    1.298 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_class.cc
    1.266 06/06/18 14:20:28 evgen@stripped +0 -0
    Auto merged

  sql/sql_base.cc
    1.328 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/opt_sum.cc
    1.52 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/opt_range.cc
    1.221 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/item_timefunc.cc
    1.122 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/item_strfunc.cc
    1.273 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/item_func.cc
    1.299 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/item_cmpfunc.h
    1.127 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/item.h
    1.203 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/ha_ndbcluster.cc
    1.328 06/06/18 14:20:27 evgen@stripped +0 -0
    Auto merged

  sql/field.cc
    1.318 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/t/select.test
    1.104 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/t/ndb_lock.test
    1.12 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/t/multi_update.test
    1.51 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/t/func_time.test
    1.45 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/t/delayed.test
    1.14 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/t/auto_increment.test
    1.27 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/t/archive.test
    1.22 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/union.result
    1.84 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/replace.result
    1.11 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/ndb_lock.result
    1.12 06/06/18 14:20:26 evgen@stripped +0 -1
    Auto merged

  mysql-test/r/multi_update.result
    1.45 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/func_time.result
    1.55 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/func_str.result
    1.117 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/func_group.result
    1.50 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/ctype_utf8.result
    1.90 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/cast.result
    1.43 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/auto_increment.result
    1.42 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/r/archive.result
    1.22 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.pl
    1.124 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  client/mysqlbinlog.cc
    1.131 06/06/18 14:20:26 evgen@stripped +0 -0
    Auto merged

  storage/archive/ha_archive.cc
    1.60.1.11 06/06/18 14:20:25 evgen@stripped +0 -0
    Merge rename: sql/ha_archive.cc -> storage/archive/ha_archive.cc

  mysql-test/r/rpl_stm_log.result
    1.62.2.4 06/06/18 14:20:25 evgen@stripped +0 -0
    Merge rename: mysql-test/r/rpl_log.result -> mysql-test/r/rpl_stm_log.result

  mysql-test/extra/rpl_tests/rpl_log.test
    1.27.2.3 06/06/18 14:20:25 evgen@stripped +0 -0
    Merge rename: mysql-test/t/rpl_log.test -> mysql-test/extra/rpl_tests/rpl_log.test

  configure.in
    1.363 06/06/18 14:20:25 evgen@stripped +0 -0
    Auto merged

# 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:	evgen
# Host:	moonbone.local
# Root:	/work/tmp_merge-5.1-opt-mysql/RESYNC

--- 1.317/sql/field.cc	2006-06-16 18:26:11 +04:00
+++ 1.318/sql/field.cc	2006-06-18 14:20:26 +04:00
@@ -4604,11 +4604,11 @@
   int error;
   bool have_smth_to_conv;
   my_bool in_dst_time_gap;
-  THD *thd= table->in_use;
+  THD *thd= table ? table->in_use : current_thd;
 
   /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
   have_smth_to_conv= (str_to_datetime(from, len, &l_time,
-                                      (table->in_use->variables.sql_mode &
+                                      (thd->variables.sql_mode &
                                        MODE_NO_ZERO_DATE) |
                                       MODE_NO_ZERO_IN_DATE, &error) >
                       MYSQL_TIMESTAMP_ERROR);
@@ -4674,7 +4674,7 @@
   my_time_t timestamp= 0;
   int error;
   my_bool in_dst_time_gap;
-  THD *thd= table->in_use;
+  THD *thd= table ? table->in_use : current_thd;
 
   /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
   longlong tmp= number_to_datetime(nr, &l_time, (thd->variables.sql_mode &
@@ -4730,7 +4730,7 @@
   ASSERT_COLUMN_MARKED_FOR_READ;
   uint32 temp;
   TIME time_tmp;
-  THD  *thd= table->in_use;
+  THD  *thd= table ? table->in_use : current_thd;
 
 #ifdef WORDS_BIGENDIAN
   if (table->s->db_low_byte_first)
@@ -4756,7 +4756,7 @@
   ASSERT_COLUMN_MARKED_FOR_READ;
   uint32 temp, temp2;
   TIME time_tmp;
-  THD *thd= table->in_use;
+  THD *thd= table ? table->in_use : current_thd;
   char *to;
 
   val_buffer->alloc(field_length+1);
@@ -4827,7 +4827,7 @@
 bool Field_timestamp::get_date(TIME *ltime, uint fuzzydate)
 {
   long temp;
-  THD *thd= table->in_use;
+  THD *thd= table ? table->in_use : current_thd;
 #ifdef WORDS_BIGENDIAN
   if (table->s->db_low_byte_first)
     temp=uint4korr(ptr);
@@ -4910,7 +4910,8 @@
 
 void Field_timestamp::set_time()
 {
-  long tmp= (long) table->in_use->query_start();
+  THD *thd= table ? table->in_use : current_thd;
+  long tmp= (long) thd->query_start();
   set_notnull();
 #ifdef WORDS_BIGENDIAN
   if (table->s->db_low_byte_first)
@@ -5107,12 +5108,13 @@
 bool Field_time::get_date(TIME *ltime, uint fuzzydate)
 {
   long tmp;
+  THD *thd= table ? table->in_use : current_thd;
   if (!(fuzzydate & TIME_FUZZY_DATE))
   {
-    push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                         ER_WARN_DATA_OUT_OF_RANGE,
                         ER(ER_WARN_DATA_OUT_OF_RANGE), field_name,
-                        table->in_use->row_count);
+                        thd->row_count);
     return 1;
   }
   tmp=(long) sint3korr(ptr);
@@ -5305,9 +5307,10 @@
   TIME l_time;
   uint32 tmp;
   int error;
+  THD *thd= table ? table->in_use : current_thd;
 
   if (str_to_datetime(from, len, &l_time, TIME_FUZZY_DATE |
-                      (table->in_use->variables.sql_mode &
+                      (thd->variables.sql_mode &
                        (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
                         MODE_INVALID_DATES)),
                       &error) <= MYSQL_TIMESTAMP_ERROR)
@@ -5361,9 +5364,10 @@
   TIME not_used;
   int error;
   longlong initial_nr= nr;
+  THD *thd= table ? table->in_use : current_thd;
 
   nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
-                                         (table->in_use->variables.sql_mode &
+                                         (thd->variables.sql_mode &
                                           (MODE_NO_ZERO_IN_DATE |
                                            MODE_NO_ZERO_DATE |
                                            MODE_INVALID_DATES))), &error);
@@ -5513,9 +5517,10 @@
   TIME l_time;
   long tmp;
   int error;
+  THD *thd= table ? table->in_use : current_thd;
   if (str_to_datetime(from, len, &l_time,
                       (TIME_FUZZY_DATE |
-                       (table->in_use->variables.sql_mode &
+                       (thd->variables.sql_mode &
                         (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
                          MODE_INVALID_DATES))),
                       &error) <= MYSQL_TIMESTAMP_ERROR)
@@ -5554,9 +5559,10 @@
   TIME l_time;
   longlong tmp;
   int error;
+  THD *thd= table ? table->in_use : current_thd;
   if (number_to_datetime(nr, &l_time,
                          (TIME_FUZZY_DATE |
-                          (table->in_use->variables.sql_mode &
+                          (thd->variables.sql_mode &
                            (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
                             MODE_INVALID_DATES))),
                          &error) == LL(-1))
@@ -5704,10 +5710,11 @@
   int error;
   ulonglong tmp= 0;
   enum enum_mysql_timestamp_type func_res;
+  THD *thd= table ? table->in_use : current_thd;
 
   func_res= str_to_datetime(from, len, &time_tmp,
                             (TIME_FUZZY_DATE |
-                             (table->in_use->variables.sql_mode &
+                             (thd->variables.sql_mode &
                               (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
                                MODE_INVALID_DATES))),
                             &error);
@@ -5755,9 +5762,10 @@
   TIME not_used;
   int error;
   longlong initial_nr= nr;
+  THD *thd= table ? table->in_use : current_thd;
 
   nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
-                                         (table->in_use->variables.sql_mode &
+                                         (thd->variables.sql_mode &
                                           (MODE_NO_ZERO_IN_DATE |
                                            MODE_NO_ZERO_DATE |
                                            MODE_INVALID_DATES))), &error);
@@ -6173,17 +6181,6 @@
 {
   uint a_len, b_len;
 
-  if (field_charset->strxfrm_multiply > 1)
-  {
-    /*
-      We have to remove end space to be able to compare multi-byte-characters
-      like in latin_de 'ae' and 0xe4
-    */
-    return field_charset->coll->strnncollsp(field_charset,
-                                            (const uchar*) a_ptr, field_length,
-                                            (const uchar*) b_ptr,
-                                            field_length, 0);
-  }
   if (field_charset->mbmaxlen != 1)
   {
     uint char_len= field_length/field_charset->mbmaxlen;
@@ -6192,8 +6189,14 @@
   }
   else
     a_len= b_len= field_length;
-  return my_strnncoll(field_charset,(const uchar*) a_ptr, a_len,
-                                    (const uchar*) b_ptr, b_len);
+  /*
+    We have to remove end space to be able to compare multi-byte-characters
+    like in latin_de 'ae' and 0xe4
+  */
+  return field_charset->coll->strnncollsp(field_charset,
+                                          (const uchar*) a_ptr, a_len,
+                                          (const uchar*) b_ptr, b_len,
+                                          0);
 }
 
 
@@ -9247,7 +9250,11 @@
 Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
                    int cuted_increment)
 {
-  THD *thd= table->in_use;
+  /*
+    If this field was created only for type conversion purposes it
+    will have table == NULL.
+  */
+  THD *thd= table ? table->in_use : current_thd;
   if (thd->count_cuted_fields)
   {
     thd->cuted_fields+= cuted_increment;
@@ -9282,9 +9289,10 @@
                             const char *str, uint str_length, 
                             timestamp_type ts_type, int cuted_increment)
 {
-  if (table->in_use->really_abort_on_warning() ||
+  THD *thd= table ? table->in_use : current_thd;
+  if (thd->really_abort_on_warning() ||
       set_warning(level, code, cuted_increment))
-    make_truncated_value_warning(table->in_use, str, str_length, ts_type,
+    make_truncated_value_warning(thd, str, str_length, ts_type,
                                  field_name);
 }
 
@@ -9311,13 +9319,13 @@
                             longlong nr, timestamp_type ts_type,
                             int cuted_increment)
 {
-  if (table->in_use->really_abort_on_warning() ||
+  THD *thd= table ? table->in_use : current_thd;
+  if (thd->really_abort_on_warning() ||
       set_warning(level, code, cuted_increment))
   {
     char str_nr[22];
     char *str_end= longlong10_to_str(nr, str_nr, -10);
-    make_truncated_value_warning(table->in_use, str_nr, 
-                                 (uint) (str_end - str_nr), 
+    make_truncated_value_warning(thd, str_nr, (uint) (str_end - str_nr), 
                                  ts_type, field_name);
   }
 }
@@ -9343,13 +9351,15 @@
 Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code, 
                             double nr, timestamp_type ts_type)
 {
-  if (table->in_use->really_abort_on_warning() ||
+  THD *thd= table ? table->in_use : current_thd;
+  if (thd->really_abort_on_warning() ||
       set_warning(level, code, 1))
   {
     /* DBL_DIG is enough to print '-[digits].E+###' */
     char str_nr[DBL_DIG + 8];
     uint str_len= my_sprintf(str_nr, (str_nr, "%g", nr));
-    make_truncated_value_warning(table->in_use, str_nr, str_len, ts_type,
+    make_truncated_value_warning(thd, str_nr, str_len, ts_type,
                                  field_name);
   }
 }
+

--- 1.186/sql/field.h	2006-06-04 20:23:38 +04:00
+++ 1.187/sql/field.h	2006-06-18 14:56:31 +04:00
@@ -124,7 +124,7 @@
   static bool type_can_have_key_part(enum_field_types);
   static enum_field_types field_type_merge(enum_field_types, enum_field_types);
   static Item_result result_merge_type(enum_field_types);
-  bool eq(Field *field)
+  virtual bool eq(Field *field)
   {
     return (ptr == field->ptr && null_ptr == field->null_ptr &&
             null_bit == field->null_bit);
@@ -1386,6 +1386,13 @@
   {
     bit_ptr= bit_ptr_arg;
     bit_ofs= bit_ofs_arg;
+  }
+  bool eq(Field *field)
+  {
+    return (Field::eq(field) &&
+            field->type() == type() &&
+            bit_ptr == ((Field_bit *)field)->bit_ptr &&
+            bit_ofs == ((Field_bit *)field)->bit_ofs);
   }
   void move_field_offset(my_ptrdiff_t ptr_diff)
   {

--- 1.202/sql/item.h	2006-06-13 23:33:08 +04:00
+++ 1.203/sql/item.h	2006-06-18 14:20:27 +04:00
@@ -857,6 +857,14 @@
   {
     return 0;
   }
+  /*
+    result_as_longlong() must return TRUE for Items representing DATE/TIME
+    functions and DATE/TIME table fields.
+    Those Items have result_type()==STRING_RESULT (and not INT_RESULT), but
+    their values should be compared as integers (because the integer
+    representation is more precise than the string one).
+  */
+  virtual bool result_as_longlong() { return FALSE; }
 };
 
 
@@ -1283,6 +1291,10 @@
   bool register_field_in_read_map(byte *arg);
   bool check_partition_func_processor(byte *bool_arg) { return 0; }
   void cleanup();
+  bool result_as_longlong()
+  {
+    return field->can_be_compared_as_longlong();
+  }
   Item_equal *find_item_equal(COND_EQUAL *cond_equal);
   Item *equal_fields_propagator(byte *arg);
   Item *set_no_const_sub(byte *arg);
@@ -1904,6 +1916,10 @@
   bool walk(Item_processor processor, bool walk_subquery, byte *arg)
   { return (*ref)->walk(processor, walk_subquery, arg); }
   void print(String *str);
+  bool result_as_longlong()
+  {
+    return (*ref)->result_as_longlong();
+  }
   void cleanup();
   Item_field *filed_for_view_update()
     { return (*ref)->filed_for_view_update(); }

--- 1.205/sql/item_cmpfunc.cc	2006-06-04 22:05:17 +04:00
+++ 1.206/sql/item_cmpfunc.cc	2006-06-18 14:56:31 +04:00
@@ -63,25 +63,144 @@
 }
 
 
+/*
+  Aggregates result types from the array of items.
+
+  SYNOPSIS:
+    agg_cmp_type()
+    thd          thread handle
+    type   [out] the aggregated type
+    items        array of items to aggregate the type from
+    nitems       number of items in the array
+
+  DESCRIPTION
+    This function aggregates result types from the array of items. Found type
+    supposed to be used later for comparison of values of these items.
+    Aggregation itself is performed by the item_cmp_type() function.
+
+  NOTES
+    Aggregation rules:
+    If all items are constants the type will be aggregated from all items.
+    If there are some non-constant items then only types of non-constant
+    items will be used for aggregation.
+    If there are DATE/TIME fields/functions in the list and no string
+    fields/functions in the list then:
+      The INT_RESULT type will be used for aggregation instead of original
+      result type of any DATE/TIME field/function in the list
+      All constant items in the list will be converted to a DATE/TIME using
+      found field or result field of found function.
+
+    Implementation notes:
+      The code is equivalent to:
+      1. Check the list for presence of a STRING field/function.
+         Collect the is_const flag.
+      2. Get a Field* object to use for type coercion
+      3. Perform type conversion.
+      1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME
+      field/function and checks presence of a STRING field/function.
+      The second loop works only if a DATE/TIME field/function is found.
+      It checks presence of a STRING field/function in the rest of the list.
+
+  TODO
+    1) The current implementation can produce false comparison results for
+    expressions like:
+      date_time_field BETWEEN string_field_with_dates AND string_constant
+    if the string_constant will omit some of leading zeroes.
+    In order to fully implement correct comparison of DATE/TIME the new
+    DATETIME_RESULT result type should be introduced and agg_cmp_type()
+    should return the DATE/TIME field used for the conversion. Later
+    this field can be used by comparison functions like Item_func_between to
+    convert string values to ints on the fly and thus return correct results.
+    This modification will affect functions BETWEEN, IN and CASE.
+
+    2) If in the list a DATE field/function and a DATETIME field/function
+    are present in the list then the first found field/function will be
+    used for conversion. This may lead to wrong results and probably should
+    be fixed.
+*/
+
 static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
 {
   uint i;
+  Item::Type res= (Item::Type)0;
+  /* Used only for date/time fields, max_length = 19 */
+  char buff[20];
+  uchar null_byte;
   Field *field= NULL;
 
-  /* If the first argument is a FIELD_ITEM, pull out the field. */
-  if (items[0]->real_item()->type() == Item::FIELD_ITEM)
-    field=((Item_field *)(items[0]->real_item()))->field;
-  /* But if it can't be compared as a longlong, we don't really care. */
-  if (field && !field->can_be_compared_as_longlong())
-    field= NULL;
-
-  type[0]= items[0]->result_type();
-  for (i= 1; i < nitems; i++)
-  {
-    type[0]= item_cmp_type(type[0], items[i]->result_type());
-    if (field && convert_constant_item(thd, field, &items[i]))
-      type[0]= INT_RESULT;
+  /* Search for date/time fields/functions */
+  for (i= 0; i < nitems; i++)
+  {
+    if (!items[i]->result_as_longlong())
+    {
+      /* Do not convert anything if a string field/function is present */
+      if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT)
+      {
+        i= nitems;
+        break;
+      }
+      continue;
+    }
+    if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM)
+    {
+      field= ((Item_field *)items[i]->real_item())->field;
+      break;
+    }
+    else if (res == Item::FUNC_ITEM)
+    {
+      field= items[i]->tmp_table_field_from_field_type(0);
+      if (field)
+        field->move_field(buff, &null_byte, 0);
+      break;
+    }
   }
+  if (field)
+  {
+    /* Check the rest of the list for presence of a string field/function. */
+    for (i++ ; i < nitems; i++)
+    {
+      if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT &&
+          !items[i]->result_as_longlong())
+      {
+        if (res == Item::FUNC_ITEM)
+          delete field;
+        field= 0;
+        break;
+      }
+    }
+  }
+  /* Reset to 0 on first occurence of non-const item. 1 otherwise */
+  bool is_const= items[0]->const_item();
+  /*
+    If the first item is a date/time function then its result should be
+    compared as int
+  */
+  if (field)
+  {
+    /* Suppose we are comparing dates and some non-constant items are present. */
+    type[0]= INT_RESULT;
+    is_const= 0;
+  }
+  else
+    type[0]= items[0]->result_type();
+
+  for (i= 0; i < nitems ; i++)
+  {
+    if (!items[i]->const_item())
+    {
+      Item_result result= field && items[i]->result_as_longlong() ?
+                            INT_RESULT : items[i]->result_type();
+      type[0]= is_const ? result : item_cmp_type(type[0], result);
+      is_const= 0;
+    }
+    else if (is_const)
+      type[0]= item_cmp_type(type[0], items[i]->result_type());
+    else if (field)
+      convert_constant_item(thd, field, &items[i]);
+  }
+
+  if (res == Item::FUNC_ITEM && field)
+    delete field;
 }
 
 
@@ -238,14 +357,6 @@
   if (!(*item)->with_subselect && (*item)->const_item())
   {
     /* For comparison purposes allow invalid dates like 2000-01-32 */
-    TABLE *table= field->table;
-    ulong orig_sql_mode= table->in_use->variables.sql_mode;
-    my_bitmap_map *old_write_map=
-      dbug_tmp_use_all_columns(table, table->write_set);
-    my_bitmap_map *old_read_map=
-      dbug_tmp_use_all_columns(table, table->read_set);
-
-    table->in_use->variables.sql_mode|= MODE_INVALID_DATES;
     if (!(*item)->save_in_field(field, 1) && !((*item)->null_value))
     {
       Item *tmp= new Item_int_with_ref(field->val_int(), *item,
@@ -1106,9 +1217,8 @@
     return;
   agg_cmp_type(thd, &cmp_type, args, 3);
 
-  if (cmp_type == STRING_RESULT &&
-      agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV))
-    return;
+  if (cmp_type == STRING_RESULT)
+      agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV);
 }
 
 

--- 1.126/sql/item_cmpfunc.h	2006-06-04 20:23:40 +04:00
+++ 1.127/sql/item_cmpfunc.h	2006-06-18 14:20:27 +04:00
@@ -46,7 +46,7 @@
   inline int set_compare_func(Item_bool_func2 *owner_arg)
   {
     return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(),
-						     (*b)->result_type()));
+                                                     (*b)->result_type()));
   }
   inline int set_cmp_func(Item_bool_func2 *owner_arg,
 			  Item **a1, Item **a2,
@@ -59,8 +59,9 @@
   inline int set_cmp_func(Item_bool_func2 *owner_arg,
 			  Item **a1, Item **a2)
   {
-    return set_cmp_func(owner_arg, a1, a2, item_cmp_type((*a1)->result_type(),
-							 (*a2)->result_type()));
+    return set_cmp_func(owner_arg, a1, a2,
+                        item_cmp_type((*a1)->result_type(),
+                                      (*a2)->result_type()));
   }
   inline int compare() { return (this->*func)(); }
 

--- 1.298/sql/item_func.cc	2006-06-16 14:16:58 +04:00
+++ 1.299/sql/item_func.cc	2006-06-18 14:20:27 +04:00
@@ -3288,7 +3288,7 @@
     return value;                       // Avoid side effect of insert_id()
   }
   thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
-  return thd->insert_id();
+  return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id();
 }
 
 /* This function is just used to test speed of different functions */

--- 1.272/sql/item_strfunc.cc	2006-06-16 14:16:58 +04:00
+++ 1.273/sql/item_strfunc.cc	2006-06-18 14:20:27 +04:00
@@ -154,7 +154,15 @@
 
 void Item_func_md5::fix_length_and_dec()
 {
-   max_length=32;
+  max_length=32;
+  /*
+    The MD5() function treats its parameter as being a case sensitive. Thus
+    we set binary collation on it so different instances of MD5() will be
+    compared properly.
+  */
+  args[0]->collation.set(
+      get_charset_by_csname(args[0]->collation.collation->csname,
+                            MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
 }
 
 
@@ -195,7 +203,15 @@
 
 void Item_func_sha::fix_length_and_dec()
 {
-   max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
+  max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
+  /*
+    The SHA() function treats its parameter as being a case sensitive. Thus
+    we set binary collation on it so different instances of MD5() will be
+    compared properly.
+  */
+  args[0]->collation.set(
+      get_charset_by_csname(args[0]->collation.collation->csname,
+                            MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
 }
 
 
@@ -288,11 +304,14 @@
   DBUG_ASSERT(fixed == 1);
   String *res,*res2,*use_as_buff;
   uint i;
+  bool is_const= 0;
 
   null_value=0;
   if (!(res=args[0]->val_str(str)))
     goto null;
   use_as_buff= &tmp_value;
+  /* Item_subselect in --ps-protocol mode will state it as a non-const */
+  is_const= args[0]->const_item() || !args[0]->used_tables();
   for (i=1 ; i < arg_count ; i++)
   {
     if (res->length() == 0)
@@ -315,7 +334,7 @@
 			    current_thd->variables.max_allowed_packet);
 	goto null;
       }
-      if (res->alloced_length() >= res->length()+res2->length())
+      if (!is_const && res->alloced_length() >= res->length()+res2->length())
       {						// Use old buffer
 	res->append(*res2);
       }
@@ -370,6 +389,7 @@
 	res= &tmp_value;
 	use_as_buff=str;
       }
+      is_const= 0;
     }
   }
   res->set_charset(collation.collation);
@@ -389,7 +409,14 @@
     return;
 
   for (uint i=0 ; i < arg_count ; i++)
-    max_result_length+= args[i]->max_length;
+  {
+    if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
+      max_result_length+= (args[i]->max_length /
+                           args[i]->collation.collation->mbmaxlen) *
+                           collation.collation->mbmaxlen;
+    else
+      max_result_length+= args[i]->max_length;
+  }
 
   if (max_result_length >= MAX_BLOB_WIDTH)
   {

--- 1.121/sql/item_timefunc.cc	2006-06-16 14:16:59 +04:00
+++ 1.122/sql/item_timefunc.cc	2006-06-18 14:20:27 +04:00
@@ -2344,6 +2344,20 @@
 }
 
 
+longlong Item_datetime_typecast::val_int()
+{
+  DBUG_ASSERT(fixed == 1);
+  TIME ltime;
+  if (get_arg0_date(&ltime,1))
+  {
+    null_value= 1;
+    return 0;
+  }
+
+  return TIME_to_ulonglong_datetime(&ltime);
+}
+
+
 bool Item_time_typecast::get_time(TIME *ltime)
 {
   bool res= get_arg0_time(ltime);
@@ -2358,6 +2372,17 @@
 }
 
 
+longlong Item_time_typecast::val_int()
+{
+  TIME ltime;
+  if (get_time(&ltime))
+  {
+    null_value= 1;
+    return 0;
+  }
+  return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
+}
+
 String *Item_time_typecast::val_str(String *str)
 {
   DBUG_ASSERT(fixed == 1);
@@ -2397,6 +2422,14 @@
   return 0;
 }
 
+longlong Item_date_typecast::val_int()
+{
+  DBUG_ASSERT(fixed == 1);
+  TIME ltime;
+  if (args[0]->get_date(&ltime, TIME_FUZZY_DATE))
+    return 0;
+  return (longlong) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
+}
 
 /*
   MAKEDATE(a,b) is a date function that creates a date value 
@@ -2429,6 +2462,33 @@
 
 err:
   null_value=1;
+  return 0;
+}
+
+
+longlong Item_func_makedate::val_int()
+{
+  DBUG_ASSERT(fixed == 1);
+  TIME l_time;
+  long daynr=  (long) args[1]->val_int();
+  long yearnr= (long) args[0]->val_int();
+  long days;
+
+  if (args[0]->null_value || args[1]->null_value ||
+      yearnr < 0 || daynr <= 0)
+    goto err;
+
+  days= calc_daynr(yearnr,1,1) + daynr - 1;
+  /* Day number from year 0 to 9999-12-31 */
+  if (days >= 0 && days < MAX_DAY_NUMBER)
+  {
+    null_value=0;
+    get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
+    return (longlong) (l_time.year * 10000L + l_time.month * 100 + l_time.day);
+  }
+
+err:
+  null_value= 1;
   return 0;
 }
 

--- 1.71/sql/item_timefunc.h	2006-06-15 06:53:51 +04:00
+++ 1.72/sql/item_timefunc.h	2006-06-18 14:56:31 +04:00
@@ -365,6 +365,7 @@
   {
     return tmp_table_field_from_field_type(table, 0);
   }
+  bool result_as_longlong() { return TRUE; }
 };
 
 
@@ -380,6 +381,7 @@
   {
     return tmp_table_field_from_field_type(table, 0);
   }
+  bool result_as_longlong() { return TRUE; }
 };
 
 
@@ -409,6 +411,7 @@
     TIME representation using UTC-SYSTEM or per-thread time zone.
   */
   virtual void store_now_in_TIME(TIME *now_time)=0;
+  bool result_as_longlong() { return TRUE; }
 };
 
 
@@ -647,6 +650,7 @@
   {
     return tmp_table_field_from_field_type(table, 0);
   }
+  bool result_as_longlong() { return TRUE; }
   bool check_partition_func_processor(byte *bool_arg) { return 0;}
 };
 
@@ -768,6 +772,8 @@
     max_length= 10;
     maybe_null= 1;
   }
+  bool result_as_longlong() { return TRUE; }
+  longlong val_int();
 };
 
 
@@ -784,6 +790,8 @@
   {
     return tmp_table_field_from_field_type(table, 0);
   }
+  bool result_as_longlong() { return TRUE; }
+  longlong val_int();
 };
 
 
@@ -799,6 +807,8 @@
   {
     return tmp_table_field_from_field_type(table, 0);
   }
+  bool result_as_longlong() { return TRUE; }
+  longlong val_int();
 };
 
 class Item_func_makedate :public Item_str_func
@@ -817,6 +827,8 @@
   {
     return tmp_table_field_from_field_type(table, 0);
   }
+  bool result_as_longlong() { return TRUE; }
+  longlong val_int();
   bool check_partition_func_processor(byte *bool_arg) { return 0;}
 };
 

--- 1.220/sql/opt_range.cc	2006-06-13 23:33:08 +04:00
+++ 1.221/sql/opt_range.cc	2006-06-18 14:20:27 +04:00
@@ -107,7 +107,7 @@
 	  uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
   SEL_ARG(enum Type type_arg)
     :elements(1),use_count(1),left(0),next_key_part(0),color(BLACK),
-     type(type_arg)
+     type(type_arg),min_flag(0)
   {}
   inline bool is_same(SEL_ARG *arg)
   {

--- 1.51/sql/opt_sum.cc	2006-06-04 19:52:12 +04:00
+++ 1.52/sql/opt_sum.cc	2006-06-18 14:20:27 +04:00
@@ -651,7 +651,8 @@
     }
     else
     {
-      store_val_in_field(part->field, args[between && max_fl ? 2 : 1]);
+      store_val_in_field(part->field, args[between && max_fl ? 2 : 1],
+                         CHECK_FIELD_IGNORE);
       if (part->null_bit) 
         *key_ptr++= (byte) test(part->field->is_null());
       part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW);
@@ -706,6 +707,8 @@
         field BETWEEN const1 AND const2
      3. all references to the columns from the same table as column field
         occur only in conjucts mentioned above.
+     4. each of k first components the index is not partial, i.e. is not
+        defined on a fixed length proper prefix of the field.
 
      If such an index exists the function through the ref parameter
      returns the key value to find max/min for the field using the index,
@@ -715,8 +718,8 @@
       of the whole search key)
 
   NOTE
-   This function may set table->key_read to 1, which must be reset after
-   index is used! (This can only happen when function returns 1)
+    This function may set table->key_read to 1, which must be reset after
+    index is used! (This can only happen when function returns 1)
 
   RETURN
     0   Index can not be used to optimize MIN(field)/MAX(field)
@@ -749,6 +752,12 @@
     {
       if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER))
         return 0;
+
+      /* Check whether the index component is partial */
+      Field *part_field= table->field[part->fieldnr-1];
+      if ((part_field->flags & BLOB_FLAG) ||
+          part->length < part_field->key_length())
+        break;
 
       if (field->eq(part->field))
       {

--- 1.327/sql/sql_base.cc	2006-06-13 01:40:58 +04:00
+++ 1.328/sql/sql_base.cc	2006-06-18 14:20:27 +04:00
@@ -5084,10 +5084,6 @@
   if (from_clause->elements == 0)
     return FALSE; /* We come here in the case of UNIONs. */
 
-  /* For stored procedures do not redo work if already done. */
-  if (!context->select_lex->first_execution)
-    return FALSE;
-
   List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause);
   TABLE_LIST *table_ref; /* Current table reference. */
   /* Table reference to the left of the current. */
@@ -5100,14 +5096,18 @@
   {
     table_ref= left_neighbor;
     left_neighbor= table_ref_it++;
-    if (store_top_level_join_columns(thd, table_ref,
-                                     left_neighbor, right_neighbor))
-      return TRUE;
-    if (left_neighbor)
+    /* For stored procedures do not redo work if already done. */
+    if (context->select_lex->first_execution)
     {
-      TABLE_LIST *first_leaf_on_the_right;
-      first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution();
-      left_neighbor->next_name_resolution_table= first_leaf_on_the_right;
+      if (store_top_level_join_columns(thd, table_ref,
+                                       left_neighbor, right_neighbor))
+        return TRUE;
+      if (left_neighbor)
+      {
+        TABLE_LIST *first_leaf_on_the_right;
+        first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution();
+        left_neighbor->next_name_resolution_table= first_leaf_on_the_right;
+      }
     }
     right_neighbor= table_ref;
   }

--- 1.265/sql/sql_class.cc	2006-06-06 03:47:26 +04:00
+++ 1.266/sql/sql_class.cc	2006-06-18 14:20:28 +04:00
@@ -2121,7 +2121,9 @@
   backup->enable_slow_log= enable_slow_log;
   backup->last_insert_id=  last_insert_id;
   backup->next_insert_id=  next_insert_id;
+  backup->current_insert_id=  current_insert_id;
   backup->insert_id_used=  insert_id_used;
+  backup->last_insert_id_used=  last_insert_id_used;
   backup->clear_next_insert_id= clear_next_insert_id;
   backup->limit_found_rows= limit_found_rows;
   backup->examined_row_count= examined_row_count;
@@ -2171,7 +2173,9 @@
   enable_slow_log=  backup->enable_slow_log;
   last_insert_id=   backup->last_insert_id;
   next_insert_id=   backup->next_insert_id;
+  current_insert_id= backup->current_insert_id;
   insert_id_used=   backup->insert_id_used;
+  last_insert_id_used= backup->last_insert_id_used;
   clear_next_insert_id= backup->clear_next_insert_id;
   limit_found_rows= backup->limit_found_rows;
   sent_row_count=   backup->sent_row_count;

--- 1.297/sql/sql_class.h	2006-06-13 18:44:02 +04:00
+++ 1.298/sql/sql_class.h	2006-06-18 14:20:28 +04:00
@@ -763,12 +763,13 @@
 {
 public:
   ulonglong options;
-  ulonglong last_insert_id, next_insert_id;
+  ulonglong last_insert_id, next_insert_id, current_insert_id;
   ulonglong limit_found_rows;
   ha_rows    cuted_fields, sent_row_count, examined_row_count;
   ulong client_capabilities;
   uint in_sub_stmt;
   bool enable_slow_log, insert_id_used, clear_next_insert_id;
+  bool last_insert_id_used;
   my_bool no_send_ok;
   SAVEPOINT *savepoints;
 };

--- 1.203/sql/sql_insert.cc	2006-06-09 18:09:35 +04:00
+++ 1.204/sql/sql_insert.cc	2006-06-18 14:20:28 +04:00
@@ -2009,6 +2009,14 @@
   if (!using_bin_log)
     table->file->extra(HA_EXTRA_WRITE_CACHE);
   pthread_mutex_lock(&mutex);
+
+  /* Reset auto-increment cacheing */
+  if (thd.clear_next_insert_id)
+  {
+    thd.next_insert_id= 0;
+    thd.clear_next_insert_id= 0;
+  }
+
   while ((row=rows.get()))
   {
     stacked_inserts--;

--- 1.232/sql/sql_lex.h	2006-05-30 15:24:26 +04:00
+++ 1.233/sql/sql_lex.h	2006-06-18 14:20:28 +04:00
@@ -1120,6 +1120,8 @@
     case SQLCOM_UPDATE_MULTI:
     case SQLCOM_INSERT:
     case SQLCOM_INSERT_SELECT:
+    case SQLCOM_REPLACE:
+    case SQLCOM_REPLACE_SELECT:
     case SQLCOM_LOAD:
       return TRUE;
     default:

--- 1.412/sql/sql_select.cc	2006-06-09 20:38:51 +04:00
+++ 1.413/sql/sql_select.cc	2006-06-18 14:20:28 +04:00
@@ -4823,7 +4823,7 @@
 */
 
 bool
-store_val_in_field(Field *field,Item *item)
+store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
 {
   bool error;
   TABLE *table= field->table;
@@ -4838,7 +4838,7 @@
     with select_insert, which make count_cuted_fields= 1
    */
   enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
-  thd->count_cuted_fields= CHECK_FIELD_WARN;
+  thd->count_cuted_fields= check_flag;
   error= item->save_in_field(field, 1);
   thd->count_cuted_fields= old_count_cuted_fields;
   dbug_tmp_restore_column_map(table->write_set, old_map);
@@ -11031,7 +11031,7 @@
 	    field->real_type() != MYSQL_TYPE_VARCHAR &&
 	    (field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
 	{
-	  return !store_val_in_field(field,right_item);
+	  return !store_val_in_field(field, right_item, CHECK_FIELD_WARN);
 	}
       }
     }

--- 1.107/sql/sql_select.h	2006-06-04 19:52:15 +04:00
+++ 1.108/sql/sql_select.h	2006-06-18 14:20:28 +04:00
@@ -406,7 +406,7 @@
 void TEST_join(JOIN *join);
 
 /* Extern functions in sql_select.cc */
-bool store_val_in_field(Field *field,Item *val);
+bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag);
 TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
 			ORDER *group, bool distinct, bool save_sum_fields,
 			ulonglong select_options, ha_rows rows_limit,

--- 1.481/sql/sql_yacc.yy	2006-06-14 16:41:07 +04:00
+++ 1.482/sql/sql_yacc.yy	2006-06-18 14:20:29 +04:00
@@ -10635,6 +10635,8 @@
             yyerror(ER(ER_SYNTAX_ERROR));
 	    YYABORT;
 	  }
+          /* This counter shouldn't be incremented for UNION parts */
+          Lex->nest_level--;
 	  if (mysql_new_select(lex, 0))
 	    YYABORT;
           mysql_init_select(lex);

--- 1.60/sql/structs.h	2006-05-22 14:05:11 +04:00
+++ 1.61/sql/structs.h	2006-06-18 14:20:29 +04:00
@@ -54,7 +54,13 @@
   Field *field;
   uint	offset;				/* offset in record (from 0) */
   uint	null_offset;			/* Offset to null_bit in record */
-  uint16 length;			/* Length of key_part */
+  uint16 length;                        /* Length of keypart value in bytes */
+  /* 
+    Number of bytes required to store the keypart value. This may be
+    different from the "length" field as it also counts
+     - possible NULL-flag byte (see HA_KEY_NULL_LENGTH)
+     - possible HA_KEY_BLOB_LENGTH bytes needed to store actual value length.
+  */
   uint16 store_length;
   uint16 key_type;
   uint16 fieldnr;			/* Fieldnum in UNIREG */

--- 1.83/mysql-test/r/union.result	2006-03-08 00:06:47 +03:00
+++ 1.84/mysql-test/r/union.result	2006-06-18 14:20:26 +04:00
@@ -1306,3 +1306,48 @@
 5
 99
 drop table t1;
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1)) union
+(select avg(1)) union (select avg(1)) union (select avg(1));
+avg(1)
+NULL

--- 1.89/mysql-test/r/ctype_utf8.result	2006-05-09 19:13:26 +04:00
+++ 1.90/mysql-test/r/ctype_utf8.result	2006-06-18 14:20:26 +04:00
@@ -1112,6 +1112,46 @@
 Table	Op	Msg_type	Msg_text
 test.t1	check	status	OK
 drop table t1;
+SET NAMES utf8;
+CREATE TABLE t1 (id int PRIMARY KEY,
+a varchar(16) collate utf8_unicode_ci NOT NULL default '',
+b int,
+f varchar(128) default 'XXX',
+INDEX (a(4))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t1(id, a, b) VALUES
+(1, 'cccc', 50), (2, 'cccc', 70), (3, 'cccc', 30),
+(4, 'cccc', 30), (5, 'cccc', 20), (6, 'bbbbbb', 40),
+(7, 'dddd', 30), (8, 'aaaa', 10), (9, 'aaaa', 50),
+(10, 'eeeee', 40), (11, 'bbbbbb', 60);
+SELECT id, a, b FROM t1;
+id	a	b
+1	cccc	50
+2	cccc	70
+3	cccc	30
+4	cccc	30
+5	cccc	20
+6	bbbbbb	40
+7	dddd	30
+8	aaaa	10
+9	aaaa	50
+10	eeeee	40
+11	bbbbbb	60
+SELECT id, a, b FROM t1 WHERE a BETWEEN 'aaaa' AND 'bbbbbb';
+id	a	b
+8	aaaa	10
+9	aaaa	50
+6	bbbbbb	40
+11	bbbbbb	60
+SELECT id, a FROM t1 WHERE a='bbbbbb';
+id	a
+6	bbbbbb
+11	bbbbbb
+SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b;
+id	a
+6	bbbbbb
+11	bbbbbb
+DROP TABLE t1;
 CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8;
 INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa');
 SELECT id FROM t1;

--- 1.21/mysql-test/r/archive.result	2006-05-15 21:31:03 +04:00
+++ 1.22/mysql-test/r/archive.result	2006-06-18 14:20:26 +04:00
@@ -6254,6 +6254,7 @@
 3	011402	37	Romans	scholastics	jarring	
 4	011403	37	intercepted	audiology	tinily	
 DELETE FROM t2;
+ERROR HY000: Table storage engine for 't2' doesn't have this option
 SELECT * FROM t2;
 auto	fld1	companynr	fld3	fld4	fld5	fld6
 1	000001	00	Omaha	teethe	neat	
@@ -8685,6 +8686,7 @@
 3	011402	37	Romans	scholastics	jarring	
 4	011403	37	intercepted	audiology	tinily	
 TRUNCATE TABLE t2;
+ERROR HY000: Table storage engine for 't2' doesn't have this option
 SELECT * FROM t2;
 auto	fld1	companynr	fld3	fld4	fld5	fld6
 1	000001	00	Omaha	teethe	neat	

--- 1.21/mysql-test/t/archive.test	2006-05-15 21:31:04 +04:00
+++ 1.22/mysql-test/t/archive.test	2006-06-18 14:20:26 +04:00
@@ -1330,12 +1330,14 @@
 #
 # For bug #12836
 # Delete was allowing all rows to be removed
+--error 1031
 DELETE FROM t2;
 SELECT * FROM t2;
 INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W');
 INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring','');
 INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
 SELECT * FROM t2;
+--error 1031
 TRUNCATE TABLE t2;
 SELECT * FROM t2;
 

--- 1.60.1.10/sql/ha_archive.cc	2006-06-17 03:35:06 +04:00
+++ 1.98/storage/archive/ha_archive.cc	2006-06-18 14:20:29 +04:00
@@ -19,11 +19,13 @@
 #endif
 
 #include "mysql_priv.h"
+#include <myisam.h>
 
-#if defined(HAVE_ARCHIVE_DB)
 #include "ha_archive.h"
 #include <my_dir.h>
 
+#include <mysql/plugin.h>
+
 /*
   First, if you want to understand storage engines you should look at 
   ha_example.cc and ha_example.h. 
@@ -31,13 +33,13 @@
   a storage engine without indexes that could compress data very well.
   So, welcome to a completely compressed storage engine. This storage
   engine only does inserts. No replace, deletes, or updates. All reads are 
-  complete table scans. Compression is done through gzip (bzip compresses
+  complete table scans. Compression is done through azip (bzip compresses
   better, but only marginally, if someone asks I could add support for
-  it too, but beaware that it costs a lot more in CPU time then gzip).
+  it too, but beaware that it costs a lot more in CPU time then azip).
   
   We keep a file pointer open for each instance of ha_archive for each read
   but for writes we keep one open file handle just for that. We flush it
-  only if we have a read occur. gzip handles compressing lots of records
+  only if we have a read occur. azip handles compressing lots of records
   at once much better then doing lots of little records between writes.
   It is possible to not lock on writes but this would then mean we couldn't
   handle bulk inserts as well (that is if someone was trying to read at
@@ -64,8 +66,7 @@
   pool. For MyISAM its a question of how much the file system caches the
   MyISAM file. With enough free memory MyISAM is faster. Its only when the OS
   doesn't have enough memory to cache entire table that archive turns out 
-  to be any faster. For writes it is always a bit slower then MyISAM. It has no
-  internal limits though for row length.
+  to be any faster. 
 
   Examples between MyISAM (packed) and Archive.
 
@@ -82,11 +83,8 @@
   TODO:
    Add bzip optional support.
    Allow users to set compression level.
-   Add truncate table command.
    Implement versioning, should be easy.
    Allow for errors, find a way to mark bad rows.
-   Talk to the gzip guys, come up with a writable format so that updates are doable
-     without switching to a block method.
    Add optional feature so that rows can be flushed at interval (which will cause less
      compression but may speed up ordered searches).
    Checkpoint the meta file to allow for faster rebuilds.
@@ -105,6 +103,7 @@
   rows - This is an unsigned long long which is the number of rows in the data
          file.
   check point - Reserved for future use
+  auto increment - MAX value for autoincrement
   dirty - Status of the file, whether or not its values are the latest. This
           flag is what causes a repair to occur
 
@@ -126,47 +125,32 @@
 #define ARN ".ARN"               // Files used during an optimize call
 #define ARM ".ARM"               // Meta file
 /*
-  uchar + uchar + ulonglong + ulonglong + uchar
+  uchar + uchar + ulonglong + ulonglong + ulonglong + ulonglong + FN_REFLEN 
+  + uchar
 */
-#define META_BUFFER_SIZE 19      // Size of the data used in the meta file
+#define META_BUFFER_SIZE sizeof(uchar) + sizeof(uchar) + sizeof(ulonglong) \
+  + sizeof(ulonglong) + sizeof(ulonglong) + sizeof(ulonglong) + FN_REFLEN \
+  + sizeof(uchar)
+
 /*
   uchar + uchar
 */
 #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
 
-/* 
+/* Static declarations for handerton */
+static handler *archive_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root);
+/*
   Number of rows that will force a bulk insert.
 */
 #define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2
 
+handlerton archive_hton;
 
-
-/* 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
-};
-
+static handler *archive_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
+{
+  return new (mem_root) ha_archive(table);
+}
 
 /*
   Used for hash table that tracks open tables.
@@ -191,9 +175,18 @@
     TRUE        Error
 */
 
-bool archive_db_init()
+int archive_db_init()
 {
   DBUG_ENTER("archive_db_init");
+  if (archive_inited)
+    DBUG_RETURN(FALSE);
+
+  archive_hton.state=SHOW_OPTION_YES;
+  archive_hton.db_type=DB_TYPE_ARCHIVE_DB;
+  archive_hton.create=archive_create_handler;
+  archive_hton.panic=archive_db_end;
+  archive_hton.flags=HTON_NO_FLAGS;
+
   if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST))
     goto error;
   if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
@@ -207,7 +200,6 @@
     DBUG_RETURN(FALSE);
   }
 error:
-  have_archive_db= SHOW_OPTION_DISABLED;	// If we couldn't use handler
   DBUG_RETURN(TRUE);
 }
 
@@ -215,14 +207,14 @@
   Release the archive handler.
 
   SYNOPSIS
-    archive_db_end()
+    archive_db_done()
     void
 
   RETURN
     FALSE       OK
 */
 
-bool archive_db_end()
+int archive_db_done()
 {
   if (archive_inited)
   {
@@ -230,32 +222,37 @@
     VOID(pthread_mutex_destroy(&archive_mutex));
   }
   archive_inited= 0;
-  return FALSE;
+  return 0;
+}
+
+
+int archive_db_end(ha_panic_function type)
+{
+  return archive_db_done();
 }
 
-ha_archive::ha_archive(TABLE *table_arg)
+ha_archive::ha_archive(TABLE_SHARE *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 = 2 << ((zlibCompileFlags() >> 6) & 3);
-  DBUG_ASSERT(ref_length <= sizeof(z_off_t));
+  ref_length = sizeof(my_off_t);
 }
 
 /*
   This method reads the header of a datafile and returns whether or not it was successful.
 */
-int ha_archive::read_data_header(gzFile file_to_read)
+int ha_archive::read_data_header(azio_stream *file_to_read)
 {
   uchar data_buffer[DATA_BUFFER_SIZE];
   DBUG_ENTER("ha_archive::read_data_header");
 
-  if (gzrewind(file_to_read) == -1)
+  if (azrewind(file_to_read) == -1)
     DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
-  if (gzread(file_to_read, data_buffer, DATA_BUFFER_SIZE) != DATA_BUFFER_SIZE)
+  if (azread(file_to_read, data_buffer, DATA_BUFFER_SIZE) != DATA_BUFFER_SIZE)
     DBUG_RETURN(errno ? errno : -1);
   
   DBUG_PRINT("ha_archive::read_data_header", ("Check %u", data_buffer[0]));
@@ -271,7 +268,7 @@
 /*
   This method writes out the header of a datafile and returns whether or not it was successful.
 */
-int ha_archive::write_data_header(gzFile file_to_write)
+int ha_archive::write_data_header(azio_stream *file_to_write)
 {
   uchar data_buffer[DATA_BUFFER_SIZE];
   DBUG_ENTER("ha_archive::write_data_header");
@@ -279,7 +276,7 @@
   data_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
   data_buffer[1]= (uchar)ARCHIVE_VERSION;
 
-  if (gzwrite(file_to_write, &data_buffer, DATA_BUFFER_SIZE) != 
+  if (azwrite(file_to_write, &data_buffer, DATA_BUFFER_SIZE) != 
       DATA_BUFFER_SIZE)
     goto error;
   DBUG_PRINT("ha_archive::write_data_header", ("Check %u", (uint)data_buffer[0]));
@@ -294,9 +291,13 @@
   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, ha_rows *rows)
+int ha_archive::read_meta_file(File meta_file, ha_rows *rows, 
+                               ulonglong *auto_increment,
+                               ulonglong *forced_flushes,
+                               char *real_path)
 {
   uchar meta_buffer[META_BUFFER_SIZE];
+  uchar *ptr= meta_buffer;
   ulonglong check_point;
 
   DBUG_ENTER("ha_archive::read_meta_file");
@@ -308,17 +309,30 @@
   /*
     Parse out the meta data, we ignore version at the moment
   */
-  *rows= (ha_rows)uint8korr(meta_buffer + 2);
-  check_point= uint8korr(meta_buffer + 10);
+
+  ptr+= sizeof(uchar)*2; // Move past header
+  *rows= (ha_rows)uint8korr(ptr);
+  ptr+= sizeof(ulonglong); // Move past rows
+  check_point= uint8korr(ptr);
+  ptr+= sizeof(ulonglong); // Move past check_point
+  *auto_increment= uint8korr(ptr);
+  ptr+= sizeof(ulonglong); // Move past auto_increment
+  *forced_flushes= uint8korr(ptr);
+  ptr+= sizeof(ulonglong); // Move past forced_flush
+  memmove(real_path, ptr, FN_REFLEN);
+  ptr+= FN_REFLEN; // Move past the possible location of the file
 
   DBUG_PRINT("ha_archive::read_meta_file", ("Check %d", (uint)meta_buffer[0]));
   DBUG_PRINT("ha_archive::read_meta_file", ("Version %d", (uint)meta_buffer[1]));
-  DBUG_PRINT("ha_archive::read_meta_file", ("Rows %lld", *rows));
-  DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %lld", check_point));
-  DBUG_PRINT("ha_archive::read_meta_file", ("Dirty %d", (int)meta_buffer[18]));
+  DBUG_PRINT("ha_archive::read_meta_file", ("Rows %llu", *rows));
+  DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %llu", check_point));
+  DBUG_PRINT("ha_archive::read_meta_file", ("Auto-Increment %llu", *auto_increment));
+  DBUG_PRINT("ha_archive::read_meta_file", ("Forced Flushes %llu", *forced_flushes));
+  DBUG_PRINT("ha_archive::read_meta_file", ("Real Path %s", real_path));
+  DBUG_PRINT("ha_archive::read_meta_file", ("Dirty %d", (int)(*ptr)));
 
   if ((meta_buffer[0] != (uchar)ARCHIVE_CHECK_HEADER) || 
-      ((bool)meta_buffer[18] == TRUE))
+      ((bool)(*ptr)== TRUE))
     DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
   my_sync(meta_file, MYF(MY_WME));
@@ -331,22 +345,49 @@
   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.
 */
-int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty)
+int ha_archive::write_meta_file(File meta_file, ha_rows rows, 
+                                ulonglong auto_increment, 
+                                ulonglong forced_flushes, 
+                                char *real_path,
+                                bool dirty)
 {
   uchar meta_buffer[META_BUFFER_SIZE];
+  uchar *ptr= meta_buffer;
   ulonglong check_point= 0; //Reserved for the future
 
   DBUG_ENTER("ha_archive::write_meta_file");
 
-  meta_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
-  meta_buffer[1]= (uchar)ARCHIVE_VERSION;
-  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));
+  *ptr= (uchar)ARCHIVE_CHECK_HEADER;
+  ptr += sizeof(uchar);
+  *ptr= (uchar)ARCHIVE_VERSION;
+  ptr += sizeof(uchar);
+  int8store(ptr, (ulonglong)rows); 
+  ptr += sizeof(ulonglong);
+  int8store(ptr, check_point); 
+  ptr += sizeof(ulonglong);
+  int8store(ptr, auto_increment); 
+  ptr += sizeof(ulonglong);
+  int8store(ptr, forced_flushes); 
+  ptr += sizeof(ulonglong);
+  // No matter what, we pad with nulls
+  if (real_path)
+    strncpy((char *)ptr, real_path, FN_REFLEN);
+  else
+    bzero(ptr, FN_REFLEN);
+  ptr += FN_REFLEN;
+  *ptr= (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", (ulonglong)rows));
   DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %llu", check_point));
+  DBUG_PRINT("ha_archive::write_meta_file", ("Auto Increment %llu",
+                                             auto_increment));
+  DBUG_PRINT("ha_archive::write_meta_file", ("Forced Flushes %llu", 
+                                            forced_flushes));
+  DBUG_PRINT("ha_archive::write_meta_file", ("Real path %s", 
+                                            real_path));
   DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty));
 
   VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
@@ -397,8 +438,10 @@
     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);
+    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);
     /*
       We will use this lock for rows.
@@ -406,15 +449,24 @@
     VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST));
     if ((share->meta_file= my_open(meta_file_name, O_RDWR, MYF(0))) == -1)
       share->crashed= TRUE;
+    DBUG_PRINT("info", ("archive opening (1) up write at %s", 
+                        share->data_file_name));
     
     /*
-      After we read, we set the file to dirty. When we close, we will do the 
-      opposite. If the meta file will not open we assume it is crashed and
-      leave it up to the user to fix.
+      We read the meta file, but do not mark it dirty unless we actually do
+      a write.
     */
-    if (read_meta_file(share->meta_file, &share->rows_recorded))
+    if (read_meta_file(share->meta_file, &share->rows_recorded, 
+                       &share->auto_increment_value,
+                       &share->forced_flushes,
+                       share->real_path))
       share->crashed= TRUE;
-
+    /*
+      Since we now possibly no real_path, we will use it instead if it exists.
+    */
+    if (*share->real_path)
+      fn_format(share->data_file_name, share->real_path, "", ARZ,
+                MY_REPLACE_EXT|MY_UNPACK_FILENAME);
     VOID(my_hash_insert(&archive_open_tables, (byte*) share));
     thr_lock_init(&share->lock);
   }
@@ -448,12 +500,21 @@
     hash_delete(&archive_open_tables, (byte*) share);
     thr_lock_delete(&share->lock);
     VOID(pthread_mutex_destroy(&share->mutex));
-    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);
+    /* 
+      We need to make sure we don't reset the crashed state.
+      If we open a crashed file, wee need to close it as crashed unless
+      it has been repaired.
+      Since we will close the data down after this, we go on and count
+      the flush on close;
+    */
+    share->forced_flushes++;
+    (void)write_meta_file(share->meta_file, share->rows_recorded,
+                          share->auto_increment_value, 
+                          share->forced_flushes, 
+                          share->real_path, 
+                          share->crashed ? TRUE :FALSE);
     if (share->archive_write_open)
-      if (gzclose(share->archive_write) == Z_ERRNO)
+      if (azclose(&(share->archive_write)))
         rc= 1;
     if (my_close(share->meta_file, MYF(0)))
       rc= 1;
@@ -467,15 +528,21 @@
 int ha_archive::init_archive_writer()
 {
   DBUG_ENTER("ha_archive::init_archive_writer");
-  (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
+  (void)write_meta_file(share->meta_file, share->rows_recorded,
+                        share->auto_increment_value, 
+                        share->forced_flushes, 
+                        share->real_path,
+                        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)
+  if (!(azopen(&(share->archive_write), share->data_file_name, 
+               O_WRONLY|O_APPEND|O_BINARY)))
   {
+    DBUG_PRINT("info", ("Could not open archive write file"));
     share->crashed= TRUE;
     DBUG_RETURN(1);
   }
@@ -511,7 +578,7 @@
   int rc= 0;
   DBUG_ENTER("ha_archive::open");
 
-  DBUG_PRINT("info", ("archive table was opened for crash %s", 
+  DBUG_PRINT("info", ("archive table was opened for crash: %s", 
                       (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no"));
   share= get_share(name, table, &rc);
 
@@ -527,7 +594,8 @@
 
   thr_lock_data_init(&share->lock,&lock,NULL);
 
-  if ((archive= gzopen(share->data_file_name, "rb")) == NULL)
+  DBUG_PRINT("info", ("archive data_file_name %s", share->data_file_name));
+  if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)))
   {
     if (errno == EROFS || errno == EACCES)
       DBUG_RETURN(my_errno= errno);
@@ -568,7 +636,7 @@
   DBUG_ENTER("ha_archive::close");
 
   /* First close stream */
-  if (gzclose(archive) == Z_ERRNO)
+  if (azclose(&archive))
     rc= 1;
   /* then also close share */
   rc|= free_share(share);
@@ -594,6 +662,29 @@
   int error;
   DBUG_ENTER("ha_archive::create");
 
+  stats.auto_increment_value= (create_info->auto_increment_value ?
+                               create_info->auto_increment_value -1 :
+                   (ulonglong) 0);
+
+  for (uint key= 0; key < table_arg->s->keys; key++)
+  {
+    KEY *pos= table_arg->key_info+key;
+    KEY_PART_INFO *key_part=     pos->key_part;
+    KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
+
+    for (; key_part != key_part_end; key_part++)
+    {
+      Field *field= key_part->field;
+
+      if (!(field->flags & AUTO_INCREMENT_FLAG))
+      {
+        error= -1;
+        DBUG_PRINT("info", ("Index error in creating archive table"));
+        goto error;
+      }
+    }
+  }
+
   if ((create_file= my_create(fn_format(name_buff,name,"",ARM,
                                         MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
                               O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
@@ -601,43 +692,64 @@
     error= my_errno;
     goto error;
   }
-  write_meta_file(create_file, 0, FALSE);
+
+  write_meta_file(create_file, 0, stats.auto_increment_value, 0, 
+                  (char *)create_info->data_file_name,
+                  FALSE);
   my_close(create_file,MYF(0));
 
   /* 
     We reuse name_buff since it is available.
   */
-  if ((create_file= my_create(fn_format(name_buff,name,"",ARZ,
-                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
-                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+  if (create_info->data_file_name)
   {
-    error= my_errno;
-    goto error;
+    char linkname[FN_REFLEN];
+    DBUG_PRINT("info", ("archive will create stream file %s", 
+                        create_info->data_file_name));
+                        
+    fn_format(name_buff, create_info->data_file_name, "", ARZ,
+              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
+    fn_format(linkname, name, "", ARZ,
+              MY_UNPACK_FILENAME | MY_APPEND_EXT);
+    if ((create_file= my_create_with_symlink(linkname, name_buff, 0,
+                                O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+    {
+      error= my_errno;
+      goto error;
+    }
+  }
+  else
+  {
+    if ((create_file= my_create(fn_format(name_buff, name,"", ARZ,
+                                          MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
+                                O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+    {
+      error= my_errno;
+      goto error;
+    }
   }
-  if ((archive= gzdopen(create_file, "wb")) == NULL)
+  if (!azdopen(&archive, create_file, O_WRONLY|O_BINARY))
   {
     error= errno;
     goto error2;
   }
-  if (write_data_header(archive))
+  if (write_data_header(&archive))
   {
     error= errno;
     goto error3;
   }
 
-  if (gzclose(archive))
+  if (azclose(&archive))
   {
     error= errno;
     goto error2;
   }
 
-  my_close(create_file, MYF(0));
-
   DBUG_RETURN(0);
 
 error3:
-  /* We already have an error, so ignore results of gzclose. */
-  (void)gzclose(archive);
+  /* We already have an error, so ignore results of azclose. */
+  (void)azclose(&archive);
 error2:
   my_close(create_file, MYF(0));
   delete_table(name);
@@ -649,18 +761,19 @@
 /*
   This is where the actual row is written out.
 */
-int ha_archive::real_write_row(byte *buf, gzFile writer)
+int ha_archive::real_write_row(byte *buf, azio_stream *writer)
 {
-  z_off_t written;
+  my_off_t written;
   uint *ptr, *end;
   DBUG_ENTER("ha_archive::real_write_row");
 
-  written= gzwrite(writer, buf, table->s->reclength);
-  DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength));
+  written= azwrite(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)
+  if (written != (my_off_t)table->s->reclength)
     DBUG_RETURN(errno ? errno : -1);
   /*
     We should probably mark the table as damagaged if the record is written
@@ -676,8 +789,8 @@
     if (size)
     {
       ((Field_blob*) table->field[*ptr])->get_ptr(&data_ptr);
-      written= gzwrite(writer, data_ptr, (unsigned)size);
-      if (written != (z_off_t)size)
+      written= azwrite(writer, data_ptr, (unsigned)size);
+      if (written != (my_off_t)size)
         DBUG_RETURN(errno ? errno : -1);
     }
   }
@@ -697,26 +810,206 @@
 int ha_archive::write_row(byte *buf)
 {
   int rc;
+  byte *read_buf= NULL;
+  ulonglong temp_auto;
   DBUG_ENTER("ha_archive::write_row");
 
   if (share->crashed)
       DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
-  statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
+  ha_statistic_increment(&SSV::ha_write_count);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
     table->timestamp_field->set_time();
   pthread_mutex_lock(&share->mutex);
+
+  if (table->next_number_field)
+  {
+    KEY *mkey= &table->s->key_info[0]; // We only support one key right now
+    update_auto_increment();
+    temp_auto= table->next_number_field->val_int();
+
+    /*
+      Bad news, this will cause a search for the unique value which is very 
+      expensive since we will have to do a table scan which will lock up 
+      all other writers during this period. This could perhaps be optimized 
+      in the future.
+    */
+    if (temp_auto == share->auto_increment_value && 
+        mkey->flags & HA_NOSAME)
+    {
+      rc= HA_ERR_FOUND_DUPP_KEY;
+      goto error;
+    }
+
+    if (temp_auto < share->auto_increment_value && 
+        mkey->flags & HA_NOSAME)
+    {
+      /* 
+        First we create a buffer that we can use for reading rows, and can pass
+        to get_row().
+      */
+      if (!(read_buf= (byte*) my_malloc(table->s->reclength, MYF(MY_WME))))
+      {
+        rc= HA_ERR_OUT_OF_MEM;
+        goto error;
+      }
+       /* 
+         All of the buffer must be written out or we won't see all of the
+         data 
+       */
+      azflush(&(share->archive_write), Z_SYNC_FLUSH);
+      share->forced_flushes++;
+      /*
+        Set the position of the local read thread to the beginning postion.
+      */
+      if (read_data_header(&archive))
+      {
+        rc= HA_ERR_CRASHED_ON_USAGE;
+        goto error;
+      }
+
+      /*
+        Now we read and check all of the rows.
+        if (!memcmp(table->next_number_field->ptr, mfield->ptr, mfield->max_length()))
+        if ((longlong)temp_auto == 
+            mfield->val_int((char*)(read_buf + mfield->offset())))
+      */
+      Field *mfield= table->next_number_field;
+
+      while (!(get_row(&archive, read_buf)))
+      {
+        if (!memcmp(read_buf + mfield->offset(), table->next_number_field->ptr,
+                    mfield->max_length()))
+        {
+          rc= HA_ERR_FOUND_DUPP_KEY;
+          goto error;
+        }
+      }
+    }
+    else
+    {
+      if (temp_auto > share->auto_increment_value)
+        stats.auto_increment_value= share->auto_increment_value= temp_auto;
+    }
+  }
+
+  /*
+    Notice that the global auto_increment has been increased.
+    In case of a failed row write, we will never try to reuse the value.
+  */
   if (!share->archive_write_open)
     if (init_archive_writer())
       DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
   share->rows_recorded++;
-  rc= real_write_row(buf, share->archive_write);
+  rc= real_write_row(buf, &(share->archive_write));
+error:
   pthread_mutex_unlock(&share->mutex);
+  if (read_buf)
+    my_free((gptr) read_buf, MYF(0));
 
   DBUG_RETURN(rc);
 }
 
+
+void ha_archive::get_auto_increment(ulonglong offset, ulonglong increment,
+                                    ulonglong nb_desired_values,
+                                    ulonglong *first_value,
+                                    ulonglong *nb_reserved_values)
+{
+  *nb_reserved_values= 1;
+  *first_value= share->auto_increment_value + 1;
+}
+
+/* Initialized at each key walk (called multiple times unlike rnd_init()) */
+int ha_archive::index_init(uint keynr, bool sorted)
+{
+  DBUG_ENTER("ha_archive::index_init");
+  active_index= keynr;
+  DBUG_RETURN(0);
+}
+
+
+/*
+  No indexes, so if we get a request for an index search since we tell
+  the optimizer that we have unique indexes, we scan
+*/
+int ha_archive::index_read(byte *buf, const byte *key,
+                             uint key_len, enum ha_rkey_function find_flag)
+{
+  int rc;
+  DBUG_ENTER("ha_archive::index_read");
+  rc= index_read_idx(buf, active_index, key, key_len, find_flag);
+  DBUG_RETURN(rc);
+}
+
+
+int ha_archive::index_read_idx(byte *buf, uint index, const byte *key,
+                                 uint key_len, enum ha_rkey_function find_flag)
+{
+  int rc= 0;
+  bool found= 0;
+  KEY *mkey= &table->s->key_info[index];
+  current_k_offset= mkey->key_part->offset;
+  current_key= key;
+  current_key_len= key_len;
+
+
+  DBUG_ENTER("ha_archive::index_read_idx");
+
+  /* 
+    All of the buffer must be written out or we won't see all of the
+    data 
+  */
+  pthread_mutex_lock(&share->mutex);
+  azflush(&(share->archive_write), Z_SYNC_FLUSH);
+  share->forced_flushes++;
+  pthread_mutex_unlock(&share->mutex);
+
+  /*
+    Set the position of the local read thread to the beginning postion.
+  */
+  if (read_data_header(&archive))
+  {
+    rc= HA_ERR_CRASHED_ON_USAGE;
+    goto error;
+  }
+
+  while (!(get_row(&archive, buf)))
+  {
+    if (!memcmp(current_key, buf + current_k_offset, current_key_len))
+    {
+      found= 1;
+      break;
+    }
+  }
+
+  if (found)
+    DBUG_RETURN(0);
+
+error:
+  DBUG_RETURN(rc ? rc : HA_ERR_END_OF_FILE);
+}
+
+
+int ha_archive::index_next(byte * buf) 
+{ 
+  bool found= 0;
+
+  DBUG_ENTER("ha_archive::index_next");
+
+  while (!(get_row(&archive, buf)))
+  {
+    if (!memcmp(current_key, buf+current_k_offset, current_key_len))
+    {
+      found= 1;
+      break;
+    }
+  }
+
+  DBUG_RETURN(found ? 0 : HA_ERR_END_OF_FILE); 
+}
+
 /*
   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
@@ -735,11 +1028,11 @@
   {
     scan_rows= share->rows_recorded;
     DBUG_PRINT("info", ("archive will retrieve %llu rows", scan_rows));
-    records= 0;
+    stats.records= 0;
 
     /* 
       If dirty, we lock, and then reset/flush the data.
-      I found that just calling gzflush() doesn't always work.
+      I found that just calling azflush() doesn't always work.
     */
     if (share->dirty == TRUE)
     {
@@ -747,13 +1040,14 @@
       if (share->dirty == TRUE)
       {
         DBUG_PRINT("info", ("archive flushing out rows for scan"));
-        gzflush(share->archive_write, Z_SYNC_FLUSH);
+        azflush(&(share->archive_write), Z_SYNC_FLUSH);
+        share->forced_flushes++;
         share->dirty= FALSE;
       }
       pthread_mutex_unlock(&share->mutex);
     }
 
-    if (read_data_header(archive))
+    if (read_data_header(&archive))
       DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
   }
 
@@ -765,16 +1059,18 @@
   This is the method that is used to read a row. It assumes that the row is 
   positioned where you want it.
 */
-int ha_archive::get_row(gzFile file_to_read, byte *buf)
+int ha_archive::get_row(azio_stream *file_to_read, byte *buf)
 {
-  int read; // Bytes read, gzread() returns int
+  int read; // Bytes read, azread() returns int
   uint *ptr, *end;
   char *last;
   size_t total_blob_length= 0;
+  MY_BITMAP *read_set= table->read_set;
   DBUG_ENTER("ha_archive::get_row");
 
-  read= gzread(file_to_read, buf, table->s->reclength);
-  DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->s->reclength));
+  read= azread(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);
@@ -794,7 +1090,11 @@
   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();
+  {
+    if (bitmap_is_set(read_set,
+                      (((Field_blob*) table->field[*ptr])->field_index)))
+        total_blob_length += ((Field_blob*) table->field[*ptr])->get_length();
+  }
 
   /* Adjust our row buffer if we need be */
   buffer.alloc(total_blob_length);
@@ -808,11 +1108,19 @@
     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_END_OF_FILE);
-      ((Field_blob*) table->field[*ptr])->set_ptr(size, last);
-      last += size;
+      if (bitmap_is_set(read_set,
+                        ((Field_blob*) table->field[*ptr])->field_index))
+      {
+        read= azread(file_to_read, last, size);
+        if ((size_t) read != size)
+          DBUG_RETURN(HA_ERR_END_OF_FILE);
+        ((Field_blob*) table->field[*ptr])->set_ptr(size, last);
+        last += size;
+      }
+      else
+      {
+        (void)azseek(file_to_read, size, SEEK_CUR);
+      }
     }
   }
   DBUG_RETURN(0);
@@ -836,14 +1144,13 @@
     DBUG_RETURN(HA_ERR_END_OF_FILE);
   scan_rows--;
 
-  statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
-		      &LOCK_status);
-  current_position= gztell(archive);
-  rc= get_row(archive, buf);
+  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
+  current_position= aztell(&archive);
+  rc= get_row(&archive, buf);
 
 
   if (rc != HA_ERR_END_OF_FILE)
-    records++;
+    stats.records++;
 
   DBUG_RETURN(rc);
 }
@@ -873,12 +1180,11 @@
 int ha_archive::rnd_pos(byte * buf, byte *pos)
 {
   DBUG_ENTER("ha_archive::rnd_pos");
-  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);
+  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
+  current_position= (my_off_t)my_get_ptr(pos, ref_length);
+  (void)azseek(&archive, current_position, SEEK_SET);
 
-  DBUG_RETURN(get_row(archive, buf));
+  DBUG_RETURN(get_row(&archive, buf));
 }
 
 /*
@@ -906,8 +1212,8 @@
 int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
 {
   DBUG_ENTER("ha_archive::optimize");
-  int rc;
-  gzFile writer;
+  int rc= 0;
+  azio_stream writer;
   char writer_filename[FN_REFLEN];
 
   /* Open up the writer if we haven't yet */
@@ -915,13 +1221,14 @@
     init_archive_writer();
 
   /* Flush any waiting data */
-  gzflush(share->archive_write, Z_SYNC_FLUSH);
+  azflush(&(share->archive_write), Z_SYNC_FLUSH);
+  share->forced_flushes++;
 
   /* Lets create a file to contain the new data */
   fn_format(writer_filename, share->table_name, "", ARN, 
             MY_REPLACE_EXT|MY_UNPACK_FILENAME);
 
-  if ((writer= gzopen(writer_filename, "wb")) == NULL)
+  if (!(azopen(&writer, writer_filename, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)))
     DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); 
 
   /* 
@@ -931,6 +1238,7 @@
 
   if (check_opt->flags == T_EXTEND)
   {
+    DBUG_PRINT("info", ("archive extended rebuild"));
     byte *buf; 
 
     /* 
@@ -947,14 +1255,14 @@
       Now we will rewind the archive file so that we are positioned at the 
       start of the file.
     */
-    rc= read_data_header(archive);
+    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);
+      rc= write_data_header(&writer);
 
     /* 
       On success of writing out the new header, we now fetch each row and
@@ -963,9 +1271,19 @@
     if (!rc)
     {
       share->rows_recorded= 0;
-      while (!(rc= get_row(archive, buf)))
+      stats.auto_increment_value= share->auto_increment_value= 0;
+      while (!(rc= get_row(&archive, buf)))
       {
-        real_write_row(buf, writer);
+        real_write_row(buf, &writer);
+        if (table->found_next_number_field)
+        {
+          Field *field= table->found_next_number_field;
+          ulonglong auto_value=
+            (ulonglong) field->val_int((char*)(buf + field->offset()));
+          if (share->auto_increment_value < auto_value)
+            stats.auto_increment_value= share->auto_increment_value=
+              auto_value;
+        }
         share->rows_recorded++;
       }
     }
@@ -977,43 +1295,53 @@
   } 
   else
   {
+    DBUG_PRINT("info", ("archive quick rebuild"));
     /* 
       The quick method is to just read the data raw, and then compress it directly.
     */
-    int read; // Bytes read, gzread() returns int
+    int read; // Bytes read, azread() returns int
     char block[IO_SIZE];
-    if (gzrewind(archive) == -1)
+    if (azrewind(&archive) == -1)
     {
       rc= HA_ERR_CRASHED_ON_USAGE;
+      DBUG_PRINT("info", ("archive HA_ERR_CRASHED_ON_USAGE"));
       goto error;
     }
 
-    while ((read= gzread(archive, block, IO_SIZE)))
-      gzwrite(writer, block, read);
+    while ((read= azread(&archive, block, IO_SIZE)) > 0)
+      azwrite(&writer, block, read);
   }
 
-  gzflush(writer, Z_SYNC_FLUSH);
+  azclose(&writer);
   share->dirty= FALSE;
-  gzclose(share->archive_write);
-  share->archive_write= writer; 
+  share->forced_flushes= 0;
+  
+  // now we close both our writer and our reader for the rename
+  azclose(&(share->archive_write));
+  azclose(&archive);
 
-  my_rename(writer_filename,share->data_file_name,MYF(0));
+  // make the file we just wrote be our data file
+  rc = my_rename(writer_filename,share->data_file_name,MYF(0));
 
   /*
-    Now we need to reopen our read descriptor since it has changed.
+    now open the shared writer back up
+    we don't check rc here because we want to open the file back up even
+    if the optimize failed but we will return rc below so that we will
+    know it failed.
+    We also need to reopen our read descriptor since it has changed.
   */
-  gzclose(archive);
-  if ((archive= gzopen(share->data_file_name, "rb")) == NULL)
+  DBUG_PRINT("info", ("Reopening archive data file"));
+  if (!azopen(&(share->archive_write), share->data_file_name,
+               O_WRONLY|O_APPEND|O_BINARY) ||
+      !azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY))
   {
+    DBUG_PRINT("info", ("Could not open archive write file"));
     rc= HA_ERR_CRASHED_ON_USAGE;
-    goto error;
   }
 
-
-  DBUG_RETURN(0); 
-
+  DBUG_RETURN(rc);
 error:
-  gzclose(writer);
+  azclose(&writer);
 
   DBUG_RETURN(rc); 
 }
@@ -1040,8 +1368,8 @@
     */
 
     if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
-         lock_type <= TL_WRITE) && !thd->in_lock_tables
-        && !thd->tablespace_op)
+         lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
+        && !thd_tablespace_op(thd))
       lock_type = TL_WRITE_ALLOW_WRITE;
 
     /* 
@@ -1052,7 +1380,7 @@
       concurrent inserts to t2. 
     */
 
-    if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) 
+    if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd)) 
       lock_type = TL_READ;
 
     lock.type=lock_type;
@@ -1063,6 +1391,17 @@
   return to;
 }
 
+void ha_archive::update_create_info(HA_CREATE_INFO *create_info)
+{
+  ha_archive::info(HA_STATUS_AUTO | HA_STATUS_CONST);
+  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
+  {
+    create_info->auto_increment_value= stats.auto_increment_value;
+  }
+  if (*share->real_path)
+    create_info->data_file_name= share->real_path;
+}
+
 
 /*
   Hints for optimizer, see ha_tina for more information
@@ -1074,8 +1413,8 @@
     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;
+  stats.records= share->rows_recorded;
+  stats.deleted= 0;
   /* Costs quite a bit more to get all information */
   if (flag & HA_STATUS_TIME)
   {
@@ -1083,14 +1422,17 @@
 
     VOID(my_stat(share->data_file_name, &file_stat, MYF(MY_WME)));
 
-    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;
+    stats.mean_rec_length= table->s->reclength + buffer.alloced_length();
+    stats.data_file_length= file_stat.st_size;
+    stats.create_time= file_stat.st_ctime;
+    stats.update_time= file_stat.st_mtime;
+    stats.max_data_file_length= share->rows_recorded * stats.mean_rec_length;
   }
-  delete_length= 0;
-  index_file_length=0;
+  stats.delete_length= 0;
+  stats.index_file_length=0;
+
+  if (flag & HA_STATUS_AUTO)
+    stats.auto_increment_value= share->auto_increment_value;
 
   DBUG_VOID_RETURN;
 }
@@ -1151,13 +1493,14 @@
 {
   int rc= 0;
   byte *buf; 
-  const char *old_proc_info=thd->proc_info;
+  const char *old_proc_info;
   ha_rows count= share->rows_recorded;
   DBUG_ENTER("ha_archive::check");
 
-  thd->proc_info= "Checking table";
+  old_proc_info= thd_proc_info(thd, "Checking table");
   /* Flush any waiting data */
-  gzflush(share->archive_write, Z_SYNC_FLUSH);
+  azflush(&(share->archive_write), Z_SYNC_FLUSH);
+  share->forced_flushes++;
 
   /* 
     First we create a buffer that we can use for reading rows, and can pass
@@ -1171,15 +1514,15 @@
     start of the file.
   */
   if (!rc)
-    read_data_header(archive);
+    read_data_header(&archive);
 
   if (!rc)
-    while (!(rc= get_row(archive, buf)))
+    while (!(rc= get_row(&archive, buf)))
       count--;
 
   my_free((char*)buf, MYF(0));
 
-  thd->proc_info= old_proc_info;
+  thd_proc_info(thd, old_proc_info);
 
   if ((rc && rc != HA_ERR_END_OF_FILE) || count)  
   {
@@ -1204,4 +1547,21 @@
 
   DBUG_RETURN(repair(thd, &check_opt));
 }
-#endif /* HAVE_ARCHIVE_DB */
+
+struct st_mysql_storage_engine archive_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION, &archive_hton };
+
+mysql_declare_plugin(archive)
+{
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &archive_storage_engine,
+  "ARCHIVE",
+  "Brian Aker, MySQL AB",
+  "Archive storage engine",
+  archive_db_init, /* Plugin Init */
+  archive_db_done, /* Plugin Deinit */
+  0x0100 /* 1.0 */,
+  0
+}
+mysql_declare_plugin_end;
+

--- 1.41/mysql-test/r/auto_increment.result	2006-05-18 11:42:31 +04:00
+++ 1.42/mysql-test/r/auto_increment.result	2006-06-18 14:20:26 +04:00
@@ -378,6 +378,28 @@
   KEY `t1_name` (`t1_name`)
 ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1
 DROP TABLE `t1`;
+create table t1(a int not null auto_increment primary key);
+create table t2(a int not null auto_increment primary key, t1a int);
+insert into t1 values(NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+select * from t2;
+a	t1a
+1	1
+2	1
+3	2
+4	2
+5	2
+6	3
+7	3
+8	3
+9	3
+drop table t1, t2;
 End of 4.1 tests
 CREATE TABLE t1 ( `a` int(11) NOT NULL auto_increment, `b` int(11) default NULL,PRIMARY KEY  (`a`),UNIQUE KEY `b` (`b`));
 insert into t1 (b) values (1);

--- 1.49/mysql-test/r/func_group.result	2006-05-22 19:15:40 +04:00
+++ 1.50/mysql-test/r/func_group.result	2006-06-18 14:20:26 +04:00
@@ -821,6 +821,41 @@
 MAX(id)
 NULL
 DROP TABLE t1;
+CREATE TABLE t1 (id int PRIMARY KEY, b char(3), INDEX(b));
+INSERT INTO t1 VALUES (1,'xx'), (2,'aa');
+SELECT * FROM t1;
+id	b
+1	xx
+2	aa
+SELECT MAX(b) FROM t1 WHERE b < 'ppppp';
+MAX(b)
+aa
+SHOW WARNINGS;
+Level	Code	Message
+SELECT MAX(b) FROM t1 WHERE b < 'pp';
+MAX(b)
+aa
+DROP TABLE t1;
+CREATE TABLE t1 (id int PRIMARY KEY, b char(16), INDEX(b(4)));
+INSERT INTO t1 VALUES (1, 'xxxxbbbb'), (2, 'xxxxaaaa');
+SELECT MAX(b) FROM t1;
+MAX(b)
+xxxxbbbb
+EXPLAIN SELECT MAX(b) FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	
+DROP TABLE t1;
+CREATE TABLE t1 (id int , b varchar(512), INDEX(b(250))) COLLATE latin1_bin;
+INSERT INTO t1 VALUES
+(1,CONCAT(REPEAT('_', 250), "qq")), (1,CONCAT(REPEAT('_', 250), "zz")),
+(1,CONCAT(REPEAT('_', 250), "aa")), (1,CONCAT(REPEAT('_', 250), "ff"));
+SELECT MAX(b) FROM t1;
+MAX(b)
+__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________zz
+EXPLAIN SELECT MAX(b) FROM t1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	4	
+DROP TABLE t1;
 create table t2 (ff double);
 insert into t2 values (2.2);
 select cast(sum(distinct ff) as decimal(5,2)) from t2;

--- 1.54/mysql-test/r/func_time.result	2006-06-15 07:00:30 +04:00
+++ 1.55/mysql-test/r/func_time.result	2006-06-18 14:20:26 +04:00
@@ -751,6 +751,49 @@
 monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
 monthname(str_to_date(null, '%m'))	monthname(str_to_date(null, '%m'))	monthname(str_to_date(1, '%m'))	monthname(str_to_date(0, '%m'))
 NULL	NULL	January	NULL
+create table t1(f1 date, f2 time, f3 datetime);
+insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01");
+insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02");
+select f1 from t1 where f1 between "2006-1-1" and 20060101;
+f1
+2006-01-01
+select f1 from t1 where f1 between "2006-1-1" and "2006.1.1";
+f1
+2006-01-01
+select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1";
+f1
+2006-01-01
+select f2 from t1 where f2 between "12:1:2" and "12:2:2";
+f2
+12:01:02
+select f2 from t1 where time(f2) between "12:1:2" and "12:2:2";
+f2
+12:01:02
+select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+f3
+2006-01-01 12:01:01
+select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+f3
+2006-01-01 12:01:01
+select f1 from t1 where "2006-1-1" between f1 and f3;
+f1
+2006-01-01
+select f1 from t1 where "2006-1-1" between date(f1) and date(f3);
+f1
+2006-01-01
+select f1 from t1 where "2006-1-1" between f1 and 'zzz';
+f1
+Warnings:
+Warning	1292	Incorrect date value: 'zzz' for column 'f1' at row 1
+Warning	1292	Truncated incorrect INTEGER value: 'zzz'
+Warning	1292	Truncated incorrect INTEGER value: 'zzz'
+select f1 from t1 where makedate(2006,1) between date(f1) and date(f3);
+f1
+2006-01-01
+select f1 from t1 where makedate(2006,2) between date(f1) and date(f3);
+f1
+2006-01-02
+drop table t1;
 select now() - now() + 0, curtime() - curtime() + 0, 
 sec_to_time(1) + 0, from_unixtime(1) + 0;
 now() - now() + 0	curtime() - curtime() + 0	sec_to_time(1) + 0	from_unixtime(1) + 0

--- 1.128/mysql-test/r/select.result	2006-06-09 23:27:19 +04:00
+++ 1.129/mysql-test/r/select.result	2006-06-18 14:56:31 +04:00
@@ -2656,16 +2656,6 @@
 select 123 as a from t1 where f1 is null;
 a
 drop table t1,t11;
-CREATE TABLE t1 (a INT, b INT);
-(SELECT a, b AS c FROM t1) ORDER BY c+1;
-a	c
-(SELECT a, b AS c FROM t1) ORDER BY b+1;
-a	c
-SELECT a, b AS c FROM t1 ORDER BY c+1;
-a	c
-SELECT a, b AS c FROM t1 ORDER BY b+1;
-a	c
-drop table t1;
 CREATE TABLE t1 ( a INT NOT NULL, b INT NOT NULL, UNIQUE idx (a,b) );
 INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4);
 CREATE TABLE t2 ( a INT NOT NULL, b INT NOT NULL, e INT );
@@ -2716,14 +2706,37 @@
 f1	f2
 1	1
 drop table t1,t2;
+CREATE TABLE t1(a int, b int, c int, KEY b(b), KEY c(c));
+insert into t1 values (1,0,0),(2,0,0);
+CREATE TABLE t2 (a int, b varchar(2), c varchar(2), PRIMARY KEY(a));
+insert into t2 values (1,'',''), (2,'','');
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a,b), KEY a (a), KEY b (b));
+insert into t3 values (1,1),(1,2);
+explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2 
+where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and 
+t2.b like '%%' order by t2.b limit 0,1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	b,c	b	5	const	1	Using where; Using temporary; Using filesort
+1	SIMPLE	t3	index	PRIMARY,a,b	PRIMARY	8	NULL	2	Using index
+1	SIMPLE	t2	ALL	PRIMARY	NULL	NULL	NULL	2	Range checked for each record (index map: 0x1)
+DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (a int, INDEX idx(a));
 INSERT INTO t1 VALUES (2), (3), (1);
 EXPLAIN SELECT * FROM t1 IGNORE INDEX (idx);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	
 EXPLAIN SELECT * FROM t1 IGNORE INDEX (a);
-ERROR 42000: Key 'a' doesn't exist in table 't1'
+ERROR HY000: Key 'a' doesn't exist in table 't1'
 EXPLAIN SELECT * FROM t1 FORCE INDEX (a);
+ERROR HY000: Key 'a' doesn't exist in table 't1'
+DROP TABLE t1;
+CREATE TABLE t1 (a int, INDEX idx(a));
+INSERT INTO t1 VALUES (2), (3), (1);
+EXPLAIN SELECT * FROM t1 IGNORE INDEX (idx);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	
+EXPLAIN SELECT * FROM t1 IGNORE INDEX (a);
+ERROR 42000: Key 'a' doesn't exist in table 't1'
 ERROR 42000: Key 'a' doesn't exist in table 't1'
 DROP TABLE t1;
 CREATE TABLE t1 ( city char(30) );
@@ -2814,19 +2827,6 @@
 WART	0200	1
 WART	0300	3
 DROP TABLE t1;
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
-1	SIMPLE	t2	ref	a	a	23	test.t1.a	2	
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
-1	SIMPLE	t2	ref	a	a	23	test.t1.a	2	
-DROP TABLE t1, t2;
 create table t1 (a int, b int);
 create table t2 like t1;
 select t1.a from (t1 inner join t2 on t1.a=t2.a) where t2.a=1;
@@ -2857,29 +2857,6 @@
 NULL
 1.0000
 drop table t1;
-create table t1 (a int(11));
-select all all * from t1;
-a
-select distinct distinct * from t1;
-a
-select all distinct * from t1;
-ERROR HY000: Incorrect usage of ALL and DISTINCT
-select distinct all * from t1;
-ERROR HY000: Incorrect usage of ALL and DISTINCT
-drop table t1;
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
-1	SIMPLE	t2	ref	a	a	23	test.t1.a	2	
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
-1	SIMPLE	t2	ref	a	a	23	test.t1.a	2	
-DROP TABLE t1, t2;
 CREATE TABLE t1 (a int);
 CREATE TABLE t2 (a int);
 INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
@@ -3456,3 +3433,23 @@
 1	SIMPLE	t1	range	PRIMARY,b	b	5	NULL	3	Using where
 1	SIMPLE	t2	ref	c	c	5	test.t1.a	2	Using where
 DROP TABLE t1, t2;
+create table t1 (
+a int unsigned    not null auto_increment primary key,
+b bit             not null,
+c bit             not null
+);
+create table t2 (
+a int unsigned    not null auto_increment primary key,
+b bit             not null,
+c int unsigned    not null,
+d varchar(50)
+);
+insert into t1 (b,c) values (0,1), (0,1);
+insert into t2 (b,c) values (0,1);
+select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d
+from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
+where t1.b <> 1 order by t1.a;
+a	t1.b + 0	t1.c + 0	a	t2.b + 0	c	d
+1	0	1	1	0	1	NULL
+2	0	1	NULL	NULL	NULL	NULL
+drop table t1,t2;

--- 1.26/mysql-test/t/auto_increment.test	2006-05-12 17:00:46 +04:00
+++ 1.27/mysql-test/t/auto_increment.test	2006-06-18 14:20:26 +04:00
@@ -238,6 +238,23 @@
 
 DROP TABLE `t1`;
 
+#
+# Bug #6880: LAST_INSERT_ID() within a statement
+#
+
+create table t1(a int not null auto_increment primary key);              
+create table t2(a int not null auto_increment primary key, t1a int);     
+insert into t1 values(NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID());
+insert into t1 values (NULL);                                            
+insert into t2 values (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID()),
+(NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID());
+select * from t2;
+drop table t1, t2;
+
 --echo End of 4.1 tests
 
 #

--- 1.13/mysql-test/t/delayed.test	2006-02-25 21:35:06 +03:00
+++ 1.14/mysql-test/t/delayed.test	2006-06-18 14:20:26 +04:00
@@ -50,3 +50,52 @@
 insert delayed into t1 values (1);
 select * from t1;
 drop table t1;
+
+#
+# Bug #20195: INSERT DELAYED with auto_increment is assigned wrong values
+#
+CREATE TABLE t1 ( a int(10) NOT NULL auto_increment, PRIMARY KEY (a));
+
+# Make one delayed insert to start the separate thread
+insert delayed into t1 values(null);
+
+# Do some normal inserts
+insert into t1 values(null);
+insert into t1 values(null);
+
+# Discarded, since the delayed-counter is 2, which is already used
+insert delayed into t1 values(null);
+
+# Discarded, since the delayed-counter is 3, which is already used
+insert delayed into t1 values(null);
+
+# Works, since the delayed-counter is 4, which is unused
+insert delayed into t1 values(null);
+
+# Do some more inserts
+insert into t1 values(null);
+insert into t1 values(null);
+insert into t1 values(null);
+
+# Delete one of the above to make a hole
+delete from t1 where a=6;
+
+# Discarded, since the delayed-counter is 5, which is already used
+insert delayed into t1 values(null);
+
+# Works, since the delayed-counter is 6, which is unused (the row we deleted)
+insert delayed into t1 values(null);
+
+# Discarded, since the delayed-counter is 7, which is already used
+insert delayed into t1 values(null);
+
+# Works, since the delayed-counter is 8, which is unused
+insert delayed into t1 values(null);
+
+# Check what we have now
+# must wait so that the delayed thread finishes
+# Note: this must be increased if the test fails
+--sleep 1
+select * from t1 order by a;
+
+DROP TABLE t1;

--- 1.44/mysql-test/t/func_time.test	2006-06-15 07:00:30 +04:00
+++ 1.45/mysql-test/t/func_time.test	2006-06-18 14:20:26 +04:00
@@ -368,6 +368,27 @@
        monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
 
 #
+# Bug#16377 result of DATE/TIME functions were compared as strings which
+#           can lead to a wrong result.
+#
+create table t1(f1 date, f2 time, f3 datetime);
+insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01");
+insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02");
+select f1 from t1 where f1 between "2006-1-1" and 20060101;
+select f1 from t1 where f1 between "2006-1-1" and "2006.1.1";
+select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1";
+select f2 from t1 where f2 between "12:1:2" and "12:2:2";
+select f2 from t1 where time(f2) between "12:1:2" and "12:2:2";
+select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2";
+select f1 from t1 where "2006-1-1" between f1 and f3;
+select f1 from t1 where "2006-1-1" between date(f1) and date(f3);
+select f1 from t1 where "2006-1-1" between f1 and 'zzz';
+select f1 from t1 where makedate(2006,1) between date(f1) and date(f3);
+select f1 from t1 where makedate(2006,2) between date(f1) and date(f3);
+drop table t1;
+
+#
 # Bug #16546
 # 
 

--- 1.103/mysql-test/t/select.test	2006-06-09 11:23:52 +04:00
+++ 1.104/mysql-test/t/select.test	2006-06-18 14:20:26 +04:00
@@ -2217,15 +2217,6 @@
 select 123 as a from t1 where f1 is null;
 drop table t1,t11;
 
-# Bug 7672 Unknown column error in order clause
-#
-CREATE TABLE t1 (a INT, b INT);
-(SELECT a, b AS c FROM t1) ORDER BY c+1;
-(SELECT a, b AS c FROM t1) ORDER BY b+1;
-SELECT a, b AS c FROM t1 ORDER BY c+1;
-SELECT a, b AS c FROM t1 ORDER BY b+1;
-drop table t1;
-
 #
 # Bug #3874 (function in GROUP and LEFT JOIN)
 #
@@ -2265,6 +2256,21 @@
 drop table t1,t2;
 
 #
+# Bug #4981: 4.x and 5.x produce non-optimal execution path, 3.23 regression test failure
+#
+CREATE TABLE t1(a int, b int, c int, KEY b(b), KEY c(c));
+insert into t1 values (1,0,0),(2,0,0);
+CREATE TABLE t2 (a int, b varchar(2), c varchar(2), PRIMARY KEY(a));
+insert into t2 values (1,'',''), (2,'','');
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a,b), KEY a (a), KEY b (b));
+insert into t3 values (1,1),(1,2);
+# must have "range checked" for t2
+explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2 
+ where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and 
+       t2.b like '%%' order by t2.b limit 0,1;
+DROP TABLE t1,t2,t3;
+
+#
 # Bug #17873: confusing error message when IGNORE INDEX refers a column name
 #
 
@@ -2282,48 +2288,6 @@
 # End of 4.1 tests
 
 #
-# Test case for bug 7098: substitution of a constant for a string field 
-#
-
-CREATE TABLE t1 ( city char(30) );
-INSERT INTO t1 VALUES ('London');
-INSERT INTO t1 VALUES ('Paris');
-
-SELECT * FROM t1 WHERE city='London';
-SELECT * FROM t1 WHERE city='london';
-EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london';
-SELECT * FROM t1 WHERE city='London' AND city='london';
-EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
-SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
-
-DROP TABLE t1;
-
-#
-# Bug#7425 inconsistent sort order on unsigned columns result of substraction
-#
-
-create table t1 (a int(11) unsigned, b int(11) unsigned);
-insert into t1 values (1,0), (1,1), (1,2);
-select a-b  from t1 order by 1;
-select a-b , (a-b < 0)  from t1 order by 1;
-select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
-select cast((a - b) as unsigned) from t1 order by 1;
-drop table t1;
-
-
-#
-# Bug#8733 server accepts malformed query (multiply mentioned distinct)
-#
-create table t1 (a int(11));
-select all all * from t1;
-select distinct distinct * from t1;
---error 1221
-select all distinct * from t1;
---error 1221
-select distinct all * from t1;
-drop table t1;
-
-#
 # Test for bug #6474
 #
 
@@ -2358,21 +2322,6 @@
 DROP TABLE t1;
 
 #
-# Test case for bug 7520: a wrong cost of the index for a BLOB field
-#
-
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-
-DROP TABLE t1, t2;
-
-#
 # Bug#8670
 #
 create table t1 (a int, b int);
@@ -2411,34 +2360,6 @@
 
 
 #
-# Bug#8733 server accepts malformed query (multiply mentioned distinct)
-#
-create table t1 (a int(11));
-select all all * from t1;
-select distinct distinct * from t1;
---error 1221
-select all distinct * from t1;
---error 1221
-select distinct all * from t1;
-drop table t1;
-
-
-#
-# Test case for bug 7520: a wrong cost of the index for a BLOB field
-#
-
-CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
-CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
-
-INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
-INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
-
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
-EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
-
-DROP TABLE t1, t2;
-
-#
 # Test for bug #10084: STRAIGHT_JOIN with ON expression 
 #
 
@@ -2935,3 +2856,29 @@
 SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
 
 DROP TABLE t1, t2;
+
+#
+# Bug #18895: BIT values cause joins to fail
+#
+create table t1 (
+    a int unsigned    not null auto_increment primary key,
+    b bit             not null,
+    c bit             not null
+);
+
+create table t2 (
+    a int unsigned    not null auto_increment primary key,
+    b bit             not null,
+    c int unsigned    not null,
+    d varchar(50)
+);
+
+insert into t1 (b,c) values (0,1), (0,1);
+insert into t2 (b,c) values (0,1);
+
+-- Row 1 should succeed.  Row 2 should fail.  Both fail.
+select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d
+from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
+where t1.b <> 1 order by t1.a;
+
+drop table t1,t2;

--- 1.116/mysql-test/r/func_str.result	2006-05-20 06:00:54 +04:00
+++ 1.117/mysql-test/r/func_str.result	2006-06-18 14:20:26 +04:00
@@ -1023,6 +1023,21 @@
 select ifnull(load_file("lkjlkj"),"it's null");
 ifnull(load_file("lkjlkj"),"it's null")
 it's null
+create table t1 (f1 varchar(4), f2 varchar(64), unique key k1 (f1,f2));
+insert into t1 values ( 'test',md5('test')), ('test', sha('test'));
+select * from t1 where f1='test' and (f2= md5("test") or f2= md5("TEST"));
+f1	f2
+test	098f6bcd4621d373cade4e832627b4f6
+select * from t1 where f1='test' and (f2= md5("TEST") or f2= md5("test"));
+f1	f2
+test	098f6bcd4621d373cade4e832627b4f6
+select * from t1 where f1='test' and (f2= sha("test") or f2= sha("TEST"));
+f1	f2
+test	a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
+select * from t1 where f1='test' and (f2= sha("TEST") or f2= sha("test"));
+f1	f2
+test	a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
+drop table t1;
 End of 4.1 tests
 create table t1 (d decimal default null);
 insert into t1 values (null);

--- 1.44/mysql-test/r/multi_update.result	2006-05-30 23:04:34 +04:00
+++ 1.45/mysql-test/r/multi_update.result	2006-06-18 14:20:26 +04:00
@@ -524,3 +524,83 @@
 30
 drop view v1;
 drop table t1, t2;
+create table t1 (i1 int, i2 int, i3 int);
+create table t2 (id int, c1 varchar(20), c2 varchar(20));
+insert into t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
+insert into t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
+select * from t1 order by i1;
+i1	i2	i3
+1	5	10
+2	2	2
+3	7	12
+4	5	2
+9	10	15
+select * from t2;
+id	c1	c2
+9	abc	def
+5	opq	lmn
+2	test t	t test
+update t1,t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
+select * from t1 order by i1;
+i1	i2	i3
+1	5	10
+2	15	2
+3	7	12
+4	5	2
+9	15	15
+select * from t2 order by id;
+id	c1	c2
+2	test t	ppc
+5	opq	lmn
+9	abc	ppc
+delete t1.*,t2.* from t1,t2 where t1.i2=t2.id;
+select * from t1 order by i1;
+i1	i2	i3
+2	15	2
+3	7	12
+9	15	15
+select * from t2 order by id;
+id	c1	c2
+2	test t	ppc
+9	abc	ppc
+drop table t1, t2;
+create table t1 (i1 int auto_increment not null, i2 int, i3 int, primary key (i1));
+create table t2 (id int auto_increment not null, c1 varchar(20), c2 varchar(20), primary key(id));
+insert into t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
+insert into t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
+select * from t1 order by i1;
+i1	i2	i3
+1	5	10
+2	2	2
+3	7	12
+4	5	2
+9	10	15
+select * from t2 order by id;
+id	c1	c2
+2	test t	t test
+5	opq	lmn
+9	abc	def
+update t1,t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
+select * from t1 order by i1;
+i1	i2	i3
+1	5	10
+2	15	2
+3	7	12
+4	5	2
+9	15	15
+select * from t2 order by id;
+id	c1	c2
+2	test t	ppc
+5	opq	lmn
+9	abc	ppc
+delete t1.*,t2.* from t1,t2 where t1.i2=t2.id;
+select * from t1 order by i1;
+i1	i2	i3
+2	15	2
+3	7	12
+9	15	15
+select * from t2 order by id;
+id	c1	c2
+2	test t	ppc
+9	abc	ppc
+drop table t1, t2;

--- 1.62.2.3/mysql-test/r/rpl_log.result	2006-06-17 03:35:06 +04:00
+++ 1.69/mysql-test/r/rpl_stm_log.result	2006-06-18 14:56:31 +04:00
@@ -8,97 +8,91 @@
 reset master;
 reset slave;
 reset master;
-create table t1(n int not null auto_increment primary key);
+create table t1(n int not null auto_increment primary key)ENGINE=MyISAM;
 insert into t1 values (NULL);
 drop table t1;
-create table t1 (word char(20) not null);
+create table t1 (word char(20) not null)ENGINE=MyISAM;
 load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines;
 select count(*) from t1;
 count(*)
 69
-drop table t1;
 show binlog events;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	4	Format_desc	1	98	Server ver: VERSION, Binlog ver: 4
-master-bin.000001	98	Query	1	219	use `test`; create table t1(n int not null auto_increment primary key)
-master-bin.000001	219	Intvar	1	247	INSERT_ID=1
-master-bin.000001	247	Query	1	338	use `test`; insert into t1 values (NULL)
-master-bin.000001	338	Query	1	414	use `test`; drop table t1
-master-bin.000001	414	Query	1	517	use `test`; create table t1 (word char(20) not null)
-master-bin.000001	517	Begin_load_query	1	1121	;file_id=1;block_len=581
-master-bin.000001	1121	Execute_load_query	1	1269	use `test`; load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines ;file_id=1
-master-bin.000001	1269	Query	1	1345	use `test`; drop table t1
-show binlog events from 98 limit 1;
-Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	98	Query	1	219	use `test`; create table t1(n int not null auto_increment primary key)
-show binlog events from 98 limit 2;
-Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	98	Query	1	219	use `test`; create table t1(n int not null auto_increment primary key)
-master-bin.000001	219	Intvar	1	247	INSERT_ID=1
-show binlog events from 98 limit 2,1;
+master-bin.000001	#	Format_desc	1	#	Server ver: VERSION, Binlog ver: 4
+master-bin.000001	#	Query	1	#	use `test`; create table t1(n int not null auto_increment primary key)ENGINE=MyISAM
+master-bin.000001	#	Intvar	1	#	INSERT_ID=1
+master-bin.000001	#	Query	1	#	use `test`; insert into t1 values (NULL)
+master-bin.000001	#	Query	1	#	use `test`; drop table t1
+master-bin.000001	#	Query	1	#	use `test`; create table t1 (word char(20) not null)ENGINE=MyISAM
+master-bin.000001	#	Begin_load_query	1	#	;file_id=1;block_len=581
+master-bin.000001	#	Execute_load_query	1	#	use `test`; load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines ;file_id=1
+show binlog events from 102 limit 1;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	1	#	use `test`; create table t1(n int not null auto_increment primary key)ENGINE=MyISAM
+show binlog events from 102 limit 2;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	1	#	use `test`; create table t1(n int not null auto_increment primary key)ENGINE=MyISAM
+master-bin.000001	#	Intvar	1	#	INSERT_ID=1
+show binlog events from 102 limit 2,1;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	247	Query	1	338	use `test`; insert into t1 values (NULL)
+master-bin.000001	#	Query	1	#	use `test`; insert into t1 values (NULL)
 flush logs;
-create table t5 (a int);
-drop table t5;
+create table t3 (a int)ENGINE=MyISAM;
 start slave;
+
+let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%' ;
+
+--source include/wait_slave_status.inc
 flush logs;
 stop slave;
-create table t1 (n int);
-insert into t1 values (1);
-drop table t1;
+create table t2 (n int)ENGINE=MyISAM;
+insert into t2 values (1);
 show binlog events;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	4	Format_desc	1	98	Server ver: VERSION, Binlog ver: 4
-master-bin.000001	98	Query	1	219	use `test`; create table t1(n int not null auto_increment primary key)
-master-bin.000001	219	Intvar	1	247	INSERT_ID=1
-master-bin.000001	247	Query	1	338	use `test`; insert into t1 values (NULL)
-master-bin.000001	338	Query	1	414	use `test`; drop table t1
-master-bin.000001	414	Query	1	517	use `test`; create table t1 (word char(20) not null)
-master-bin.000001	517	Begin_load_query	1	1121	;file_id=1;block_len=581
-master-bin.000001	1121	Execute_load_query	1	1269	use `test`; load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines ;file_id=1
-master-bin.000001	1269	Query	1	1345	use `test`; drop table t1
-master-bin.000001	1345	Rotate	1	1389	master-bin.000002;pos=4
+master-bin.000001	#	Format_desc	1	#	Server ver: VERSION, Binlog ver: 4
+master-bin.000001	#	Query	1	#	use `test`; create table t1(n int not null auto_increment primary key)ENGINE=MyISAM
+master-bin.000001	#	Intvar	1	#	INSERT_ID=1
+master-bin.000001	#	Query	1	#	use `test`; insert into t1 values (NULL)
+master-bin.000001	#	Query	1	#	use `test`; drop table t1
+master-bin.000001	#	Query	1	#	use `test`; create table t1 (word char(20) not null)ENGINE=MyISAM
+master-bin.000001	#	Begin_load_query	1	#	;file_id=1;block_len=581
+master-bin.000001	#	Execute_load_query	1	#	use `test`; load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines ;file_id=1
+master-bin.000001	#	Rotate	1	#	master-bin.000002;pos=4
 show binlog events in 'master-bin.000002';
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000002	4	Format_desc	1	98	Server ver: VERSION, Binlog ver: 4
-master-bin.000002	98	Query	1	184	use `test`; create table t5 (a int)
-master-bin.000002	184	Query	1	260	use `test`; drop table t5
-master-bin.000002	260	Query	1	346	use `test`; create table t1 (n int)
-master-bin.000002	346	Query	1	434	use `test`; insert into t1 values (1)
-master-bin.000002	434	Query	1	510	use `test`; drop table t1
+master-bin.000002	#	Format_desc	1	#	Server ver: VERSION, Binlog ver: 4
+master-bin.000002	#	Query	1	#	use `test`; create table t3 (a int)ENGINE=MyISAM
+master-bin.000002	#	Query	1	#	use `test`; create table t2 (n int)ENGINE=MyISAM
+master-bin.000002	#	Query	1	#	use `test`; insert into t2 values (1)
 show binary logs;
 Log_name	File_size
-master-bin.000001	1389
-master-bin.000002	510
+master-bin.000001	1343
+master-bin.000002	388
 start slave;
 show binary logs;
 Log_name	File_size
-slave-bin.000001	1552
-slave-bin.000002	348
+slave-bin.000001	1443
+slave-bin.000002	289
 show binlog events in 'slave-bin.000001' from 4;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-slave-bin.000001	4	Format_desc	2	98	Server ver: VERSION, Binlog ver: 4
-slave-bin.000001	98	Query	1	219	use `test`; create table t1(n int not null auto_increment primary key)
-slave-bin.000001	219	Intvar	1	247	INSERT_ID=1
-slave-bin.000001	247	Query	1	338	use `test`; insert into t1 values (NULL)
-slave-bin.000001	338	Query	1	414	use `test`; drop table t1
-slave-bin.000001	414	Query	1	517	use `test`; create table t1 (word char(20) not null)
-slave-bin.000001	517	Begin_load_query	1	1121	;file_id=1;block_len=581
-slave-bin.000001	1121	Execute_load_query	1	1271	use `test`; load data INFILE '../tmp/SQL_LOAD-2-1-1.data' INTO table t1 ignore 1 lines ;file_id=1
-slave-bin.000001	1271	Query	1	1347	use `test`; drop table t1
-slave-bin.000001	1347	Query	1	1433	use `test`; create table t5 (a int)
-slave-bin.000001	1433	Query	1	1509	use `test`; drop table t5
-slave-bin.000001	1509	Rotate	2	1552	slave-bin.000002;pos=4
+slave-bin.000001	#	Format_desc	2	#	Server ver: VERSION, Binlog ver: 4
+slave-bin.000001	#	Query	1	#	use `test`; create table t1(n int not null auto_increment primary key)ENGINE=MyISAM
+slave-bin.000001	#	Intvar	1	#	INSERT_ID=1
+slave-bin.000001	#	Query	1	#	use `test`; insert into t1 values (NULL)
+slave-bin.000001	#	Query	1	#	use `test`; drop table t1
+slave-bin.000001	#	Query	1	#	use `test`; create table t1 (word char(20) not null)ENGINE=MyISAM
+slave-bin.000001	#	Begin_load_query	1	#	;file_id=1;block_len=581
+slave-bin.000001	#	Execute_load_query	1	#	use `test`; load data INFILE '../tmp/SQL_LOAD-2-1-1.data' INTO table t1 ignore 1 lines ;file_id=1
+slave-bin.000001	#	Query	1	#	use `test`; create table t3 (a int)ENGINE=MyISAM
+slave-bin.000001	#	Rotate	2	#	slave-bin.000002;pos=4
 show binlog events in 'slave-bin.000002' from 4;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-slave-bin.000002	4	Format_desc	2	98	Server ver: VERSION, Binlog ver: 4
-slave-bin.000002	98	Query	1	184	use `test`; create table t1 (n int)
-slave-bin.000002	184	Query	1	272	use `test`; insert into t1 values (1)
-slave-bin.000002	272	Query	1	348	use `test`; drop table t1
+slave-bin.000002	#	Format_desc	2	#	Server ver: VERSION, Binlog ver: 4
+slave-bin.000002	#	Query	1	#	use `test`; create table t2 (n int)ENGINE=MyISAM
+slave-bin.000002	#	Query	1	#	use `test`; insert into t2 values (1)
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	510	#	#	master-bin.000002	Yes	Yes							0		0	510	#	None		0	No						#
+#	127.0.0.1	root	MASTER_PORT	1	master-bin.000002	388	#	#	master-bin.000002	Yes	Yes				#			0		0	388	#	None		0	No						#
 show binlog events in 'slave-bin.000005' from 4;
 ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
 create table t1(a int auto_increment primary key, b int);
@@ -118,3 +112,6 @@
 5	1
 6	1
 drop table t1;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;

--- 1.50/mysql-test/t/multi_update.test	2006-06-04 19:52:06 +04:00
+++ 1.51/mysql-test/t/multi_update.test	2006-06-18 14:20:26 +04:00
@@ -452,6 +452,14 @@
 delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1';
 drop table t1, t2;
 
+#
+# Bug#19225: unchecked error leads to server crash
+#
+create table t1(a int);
+create table t2(a int);
+--error 1093
+delete from t1,t2 using t1,t2 where t1.a=(select a from t1);
+drop table t1, t2;
 # End of 4.1 tests
 
 #

--- 1.27.2.2/mysql-test/t/rpl_log.test	2006-06-17 03:35:06 +04:00
+++ 1.38/mysql-test/extra/rpl_tests/rpl_log.test	2006-06-18 14:56:31 +04:00
@@ -1,4 +1,5 @@
-source include/master-slave.inc;
+# Requires statement logging
+-- source include/master-slave.inc
 
 # Clean up old slave's binlogs.
 # The slave is started with --log-slave-updates
@@ -29,18 +30,25 @@
 
 connection master;
 reset master;
-create table t1(n int not null auto_increment primary key);
+eval create table t1(n int not null auto_increment primary key)ENGINE=$engine_type;
 insert into t1 values (NULL);
 drop table t1;
-create table t1 (word char(20) not null);
+eval create table t1 (word char(20) not null)ENGINE=$engine_type;
 load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines;
 select count(*) from t1;
-drop table t1;
 --replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
 show binlog events;
-show binlog events from 98 limit 1;
-show binlog events from 98 limit 2;
-show binlog events from 98 limit 2,1;
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
+show binlog events from 102 limit 1;
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
+show binlog events from 102 limit 2;
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
+show binlog events from 102 limit 2,1;
 flush logs;
 
 # We need an extra update before doing save_master_pos.
@@ -59,8 +67,7 @@
 # To make it predictable, we do a useless update now, but which has the
 # interest of making the slave catch both rotate events.
 
-create table t5 (a int);
-drop table t5;
+eval create table t3 (a int)ENGINE=$engine_type;
 
 # Sync slave and force it to start on another binary log
 
@@ -70,6 +77,8 @@
 # to go into the relay log (the master always sends a fake one when replication
 # starts). 
 start slave;
+let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%';
+--source include/wait_slave_status.inc
 sync_with_master;
 flush logs;
 stop slave;
@@ -77,12 +86,15 @@
 
 # Create some entries for second log
 
-create table t1 (n int);
-insert into t1 values (1);
-drop table t1;
+eval create table t2 (n int)ENGINE=$engine_type;
+insert into t2 values (1);
 --replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
 show binlog events;
 --replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
 show binlog events in 'master-bin.000002';
 show binary logs;
 save_master_pos;
@@ -91,11 +103,15 @@
 sync_with_master;
 show binary logs;
 --replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
 show binlog events in 'slave-bin.000001' from 4;
 --replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION
+--replace_column 2 # 5 #
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/
 show binlog events in 'slave-bin.000002' from 4;
 --replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 8 # 9 # 23 # 33 #
+--replace_column 1 # 8 # 9 # 16 # 23 # 33 #
 show slave status;
 
 # Need to recode the following
@@ -124,4 +140,8 @@
 drop table t1;
 
 # End of 4.1 tests
-# Adding comment for force manual merge 5.0 -> wl1012: Delete me
+# The table drops caused Cluster Replication wrapper to fail as event ID would never be the same.# Moving drops here.
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;

--- 1.10/mysql-test/r/replace.result	2006-01-23 14:16:58 +03:00
+++ 1.11/mysql-test/r/replace.result	2006-06-18 14:20:26 +04:00
@@ -24,3 +24,9 @@
 63	default_value
 127	last
 drop table t1;
+CREATE TABLE t1 (f1 INT);
+CREATE VIEW v1 AS SELECT f1 FROM t1 WHERE f1 = 0 WITH CHECK OPTION;
+REPLACE INTO v1 (f1) VALUES (1);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+DROP TABLE t1;
+DROP VIEW v1;
Thread
bk commit into 5.1 tree (evgen:1.2218)eugene19 Jun