List:Commits« Previous MessageNext Message »
From:eugene Date:August 29 2006 4:58pm
Subject:bk commit into 5.1 tree (evgen:1.2286)
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@stripped, 2006-08-29 18:58:50+04:00, evgen@stripped +57 -0
  Merge moonbone.local:/work/tmp_merge-5.0-mysql
  into  moonbone.local:/work/tmp_merge-5.1-opt-mysql
  MERGE: 1.1810.1697.129

  BUILD/check-cpu@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.13.1.1

  client/mysqltest.c@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +0 -0
    Manual merge
    MERGE: 1.155.9.50

  include/config-netware.h@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.14.2.1

  mysql-test/r/func_time.result@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.47.1.19

  mysql-test/r/group_by.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.69.1.1

  mysql-test/r/innodb_mysql.result@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +0
-0
    Manual merge
    MERGE: 1.3.4.3

  mysql-test/r/join_outer.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.44.1.7

  mysql-test/r/ndb_condition_pushdown.result@stripped, 2006-08-29 17:35:47+04:00,
evgen@stripped +0 -0
    Auto merged
    MERGE: 1.15.1.6

  mysql-test/r/range.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.44.1.4

  mysql-test/r/select.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.121.1.17

  mysql-test/r/subselect.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.134.1.20

  mysql-test/r/type_datetime.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped
+0 -0
    Auto merged
    MERGE: 1.30.1.2

  mysql-test/r/user_var.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.37.1.3

  mysql-test/r/view.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.138.1.33

  mysql-test/t/func_time.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.41.1.13

  mysql-test/t/innodb_mysql.test@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +0
-0
    Manual merge
    MERGE: 1.3.4.3

  mysql-test/t/join_outer.test@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +6 -0
    Manual merge
    MERGE: 1.37.1.1

  mysql-test/t/range.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.37.1.4

  mysql-test/t/select.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.102.1.10

  mysql-test/t/type_datetime.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.18.1.1

  mysql-test/t/view.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.126.1.32

  sql/ha_innodb.cc@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.202.1.96

  sql/item.cc@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.113.1.119

  sql/item.h@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.183.1.23

  sql/item_cmpfunc.cc@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +1 -1
    Manual merge
    MERGE: 1.187.1.29

  sql/item_func.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.270.1.29

  sql/item_func.h@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.136.2.11

  sql/item_subselect.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.113.1.19

  sql/item_timefunc.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.100.1.24

  sql/mysql_priv.h@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +1 -1
    Manual merge
    MERGE: 1.290.1.116

  sql/opt_range.cc@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +2 -2
    Manual merge
    MERGE: 1.159.1.63

  sql/opt_range.h@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.57.1.3

  sql/set_var.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.125.5.20

  sql/sql_acl.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.128.1.76

  sql/sql_base.cc@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +5 -8
    Manual merge
    MERGE: 1.235.1.114

  sql/sql_class.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.223.1.23

  sql/sql_delete.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.144.1.34

  sql/sql_insert.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.146.1.53

  sql/sql_load.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.78.1.19

  sql/sql_parse.cc@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.426.1.138

  sql/sql_select.cc@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.312.1.135

  sql/sql_update.cc@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.154.2.42

  storage/innobase/btr/btr0btr.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.38.3.2

  storage/innobase/btr/btr0btr.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
    Merge rename: innobase/btr/btr0btr.c -> storage/innobase/btr/btr0btr.c

  storage/innobase/buf/buf0buf.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.45.6.2

  storage/innobase/buf/buf0buf.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
    Merge rename: innobase/buf/buf0buf.c -> storage/innobase/buf/buf0buf.c

  storage/innobase/dict/dict0dict.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped
+0 -0
    Auto merged
    MERGE: 1.65.11.2

  storage/innobase/dict/dict0dict.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/dict/dict0dict.c -> storage/innobase/dict/dict0dict.c

  storage/innobase/fil/fil0fil.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.54.11.2

  storage/innobase/fil/fil0fil.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/fil/fil0fil.c -> storage/innobase/fil/fil0fil.c

  storage/innobase/fsp/fsp0fsp.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.25.2.2

  storage/innobase/fsp/fsp0fsp.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
    Merge rename: innobase/fsp/fsp0fsp.c -> storage/innobase/fsp/fsp0fsp.c

  storage/innobase/include/btr0cur.ic@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped
+0 -0
    Manual merge
    MERGE: 1.2.2.2

  storage/innobase/include/btr0cur.ic@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/include/btr0cur.ic -> storage/innobase/include/btr0cur.ic

  storage/innobase/include/buf0buf.ic@stripped, 2006-08-29 17:35:49+04:00,
evgen@stripped +0 -0
    Auto merged
    MERGE: 1.17.2.2

  storage/innobase/include/buf0buf.ic@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/include/buf0buf.ic -> storage/innobase/include/buf0buf.ic

  storage/innobase/log/log0log.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.41.4.2

  storage/innobase/log/log0log.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
    Merge rename: innobase/log/log0log.c -> storage/innobase/log/log0log.c

  storage/innobase/log/log0recv.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.46.5.2

  storage/innobase/log/log0recv.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/log/log0recv.c -> storage/innobase/log/log0recv.c

  storage/innobase/os/os0file.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.103.10.2

  storage/innobase/os/os0file.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/os/os0file.c -> storage/innobase/os/os0file.c

  storage/innobase/row/row0mysql.c@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped
+1 -2
    Manual merge
    MERGE: 1.103.15.2

  storage/innobase/row/row0mysql.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/row/row0mysql.c -> storage/innobase/row/row0mysql.c

  storage/innobase/row/row0sel.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0
-0
    Auto merged
    MERGE: 1.92.8.2

  storage/innobase/row/row0sel.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
    Merge rename: innobase/row/row0sel.c -> storage/innobase/row/row0sel.c

  storage/innobase/srv/srv0start.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped
+0 -0
    Auto merged
    MERGE: 1.80.10.2

  storage/innobase/srv/srv0start.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
    Merge rename: innobase/srv/srv0start.c -> storage/innobase/srv/srv0start.c

  storage/innobase/ut/ut0dbg.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.7.2.2

  storage/innobase/ut/ut0dbg.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0
-0
    Merge rename: innobase/ut/ut0dbg.c -> storage/innobase/ut/ut0dbg.c

  tests/mysql_client_test.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0 -0
    Auto merged
    MERGE: 1.167.1.37

# 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.205/sql/item.cc	2006-08-29 18:58:58 +04:00
+++ 1.206/sql/item.cc	2006-08-29 18:58:58 +04:00
@@ -302,6 +302,7 @@
   maybe_null=null_value=with_sum_func=unsigned_flag=0;
   decimals= 0; max_length= 0;
   with_subselect= 0;
+  cmp_context= (Item_result)-1;
 
   /* Put item in free list so that we can free all items at end */
   THD *thd= current_thd;
@@ -340,7 +341,8 @@
   unsigned_flag(item->unsigned_flag),
   with_sum_func(item->with_sum_func),
   fixed(item->fixed),
-  collation(item->collation)
+  collation(item->collation),
+  cmp_context(item->cmp_context)
 {
   next= thd->free_list;				// Put in free list
   thd->free_list= this;
@@ -3828,7 +3830,19 @@
   Item *item= 0;
   if (item_equal)
     item= item_equal->get_const();
-  if (!item)
+  /*
+    Disable const propagation for items used in different comparison contexts.
+    This must be done because, for example, Item_hex_string->val_int() is not
+    the same as (Item_hex_string->val_str() in BINARY column)->val_int().
+    We cannot simply disable the replacement in a particular context (
+    e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>)
since
+    Items don't know the context they are in and there are functions like 
+    IF (<hex_string>, 'yes', 'no').
+    The same problem occurs when comparing a DATE/TIME field with a
+    DATE/TIME represented as an int and as a string.
+  */
+  if (!item ||
+      (cmp_context != (Item_result)-1 && item->cmp_context != cmp_context))
     item= this;
   return item;
 }

--- 1.207/sql/item.h	2006-08-29 18:58:58 +04:00
+++ 1.208/sql/item.h	2006-08-29 18:58:58 +04:00
@@ -495,7 +495,7 @@
   my_bool with_subselect;               /* If this item is a subselect or some
                                            of its arguments is or contains a
                                            subselect */
-
+  Item_result cmp_context;              /* Comparison context */
   // alloc & destruct is done as start of select using sql_alloc
   Item();
   /*

--- 1.213/sql/item_cmpfunc.cc	2006-08-29 18:58:58 +04:00
+++ 1.214/sql/item_cmpfunc.cc	2006-08-29 18:58:58 +04:00
@@ -125,31 +125,39 @@
   uchar null_byte;
   Field *field= NULL;
 
-  /* Search for date/time fields/functions */
-  for (i= 0; i < nitems; i++)
+  /*
+    Do not convert items while creating a or showing a view in order
+    to store/display the original query in these cases.
+  */
+  if (thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
+      thd->lex->sql_command != SQLCOM_SHOW_CREATE)
   {
-    if (!items[i]->result_as_longlong())
+    /* Search for date/time fields/functions */
+    for (i= 0; i < nitems; i++)
     {
-      /* Do not convert anything if a string field/function is present */
-      if (!items[i]->const_item() && items[i]->result_type() ==
STRING_RESULT)
+      if (!items[i]->result_as_longlong())
       {
-        i= nitems;
+        /* 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 &&
+          items[i]->result_type() != INT_RESULT)
+      {
+        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,0);
+        if (field)
+          field->move_field(buff, &null_byte, 0);
         break;
       }
-      continue;
-    }
-    if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM &&
-        items[i]->result_type() != INT_RESULT)
-    {
-      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, 0);
-      if (field)
-        field->move_field(buff, &null_byte, 0);
-      break;
     }
   }
   if (field)
@@ -412,7 +420,8 @@
       agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV, 1))
     return;
     
- 
+  args[0]->cmp_context= args[1]->cmp_context=
+    item_cmp_type(args[0]->result_type(), args[1]->result_type());
   // Make a special case of compare with fields to get nicer DATE comparisons
 
   if (functype() == LIKE_FUNC)  // Disable conversion in case of LIKE function.
@@ -433,6 +442,7 @@
         {
           cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
                            INT_RESULT);		// Works for all types.
+          args[0]->cmp_context= args[1]->cmp_context= INT_RESULT;
           return;
         }
       }
@@ -447,6 +457,7 @@
         {
           cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
                            INT_RESULT); // Works for all types.
+          args[0]->cmp_context= args[1]->cmp_context= INT_RESULT;
           return;
         }
       }
@@ -1224,6 +1235,7 @@
   if (!args[0] || !args[1] || !args[2])
     return;
   agg_cmp_type(thd, &cmp_type, args, 3);
+  args[0]->cmp_context= args[1]->cmp_context= args[2]->cmp_context= cmp_type;
 
   if (cmp_type == STRING_RESULT)
       agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1);

--- 1.308/sql/item_func.cc	2006-08-29 18:58:58 +04:00
+++ 1.309/sql/item_func.cc	2006-08-29 18:58:58 +04:00
@@ -551,7 +551,7 @@
 
 Item *Item_func::get_tmp_table_item(THD *thd)
 {
-  if (!with_sum_func && !const_item())
+  if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
     return new Item_field(result_field);
   return copy_or_same(thd);
 }
@@ -3741,30 +3741,38 @@
 */
 
 bool
-Item_func_set_user_var::check()
+Item_func_set_user_var::check(bool use_result_field)
 {
   DBUG_ENTER("Item_func_set_user_var::check");
+  if (use_result_field)
+    DBUG_ASSERT(result_field);
 
   switch (cached_result_type) {
   case REAL_RESULT:
   {
-    save_result.vreal= args[0]->val_real();
+    save_result.vreal= use_result_field ? result_field->val_real() :
+                        args[0]->val_real();
     break;
   }
   case INT_RESULT:
   {
-    save_result.vint= args[0]->val_int();
-    unsigned_flag= args[0]->unsigned_flag;
+    save_result.vint= use_result_field ? result_field->val_int() :
+                       args[0]->val_int();
+    unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
+                    args[0]->unsigned_flag;
     break;
   }
   case STRING_RESULT:
   {
-    save_result.vstr= args[0]->val_str(&value);
+    save_result.vstr= use_result_field ? result_field->val_str(&value) :
+                       args[0]->val_str(&value);
     break;
   }
   case DECIMAL_RESULT:
   {
-    save_result.vdec= args[0]->val_decimal(&decimal_buff);
+    save_result.vdec= use_result_field ?
+                       result_field->val_decimal(&decimal_buff) :
+                       args[0]->val_decimal(&decimal_buff);
     break;
   }
   case ROW_RESULT:
@@ -3850,7 +3858,7 @@
 double Item_func_set_user_var::val_real()
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_real(&null_value);
 }
@@ -3858,7 +3866,7 @@
 longlong Item_func_set_user_var::val_int()
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_int(&null_value);
 }
@@ -3866,7 +3874,7 @@
 String *Item_func_set_user_var::val_str(String *str)
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_str(&null_value, str, decimals);
 }
@@ -3875,7 +3883,7 @@
 my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
 {
   DBUG_ASSERT(fixed == 1);
-  check();
+  check(0);
   update();					// Store expression
   return entry->val_decimal(&null_value, val);
 }
@@ -3900,6 +3908,29 @@
   str->append(')');
 }
 
+bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
+{
+  if (result_field)
+  {
+    check(1);
+    update();
+    return protocol->store(result_field);
+  }
+  return Item::send(protocol, str_arg);
+}
+
+void Item_func_set_user_var::make_field(Send_field *tmp_field)
+{
+  if (result_field)
+  {
+    result_field->make_field(tmp_field);
+    DBUG_ASSERT(tmp_field->table_name != 0);
+    if (Item::name)
+      tmp_field->col_name=Item::name;               // Use user supplied name
+  }
+  else
+    Item::make_field(tmp_field);
+}
 
 String *
 Item_func_get_user_var::val_str(String *str)
@@ -4165,7 +4196,7 @@
     Item_func_set_user_var is not fixed after construction, call
     fix_fields().
   */
-  return (!suv || suv->fix_fields(thd, it) || suv->check() || suv->update());
+  return (!suv || suv->fix_fields(thd, it) || suv->check(0) || suv->update());
 }
 
 

--- 1.144/sql/item_func.h	2006-08-29 18:58:58 +04:00
+++ 1.145/sql/item_func.h	2006-08-29 18:58:58 +04:00
@@ -54,7 +54,7 @@
 		  SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN,
                   NOT_FUNC, NOT_ALL_FUNC,
                   NOW_FUNC, TRIG_COND_FUNC,
-                  GUSERVAR_FUNC, COLLATE_FUNC,
+                  SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
                   EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC };
   enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
                        OPTIMIZE_EQUAL };
@@ -1196,13 +1196,16 @@
   Item_func_set_user_var(LEX_STRING a,Item *b)
     :Item_func(b), cached_result_type(INT_RESULT), name(a)
   {}
+  enum Functype functype() const { return SUSERVAR_FUNC; }
   double val_real();
   longlong val_int();
   String *val_str(String *str);
   my_decimal *val_decimal(my_decimal *);
   bool update_hash(void *ptr, uint length, enum Item_result type,
   		   CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0);
-  bool check();
+  bool send(Protocol *protocol, String *str_arg);
+  void make_field(Send_field *tmp_field);
+  bool check(bool use_result_field);
   bool update();
   enum Item_result result_type () const { return cached_result_type; }
   bool fix_fields(THD *thd, Item **ref);

--- 1.131/sql/item_timefunc.cc	2006-08-29 18:58:58 +04:00
+++ 1.132/sql/item_timefunc.cc	2006-08-29 18:58:58 +04:00
@@ -224,7 +224,7 @@
 	tmp= (char*) val + min(2, val_len);
 	l_time->day= (int) my_strtoll10(val, &tmp, &error);
 	/* Skip 'st, 'nd, 'th .. */
-	val= tmp + min((int) (end-tmp), 2);
+	val= tmp + min((int) (val_end-tmp), 2);
 	break;
 
 	/* Hour */

--- 1.431/sql/mysql_priv.h	2006-08-29 18:58:58 +04:00
+++ 1.432/sql/mysql_priv.h	2006-08-29 18:58:58 +04:00
@@ -111,6 +111,15 @@
   TYPELIB *ab_month_names;
   TYPELIB *day_names;
   TYPELIB *ab_day_names;
+#ifdef __cplusplus 
+  my_locale_st(const char *name_par, const char *descr_par, bool is_ascii_par,
+               TYPELIB *month_names_par, TYPELIB *ab_month_names_par,
+               TYPELIB *day_names_par, TYPELIB *ab_day_names_par) : 
+    name(name_par), description(descr_par), is_ascii(is_ascii_par),
+    month_names(month_names_par), ab_month_names(ab_month_names_par),
+    day_names(day_names_par), ab_day_names(ab_day_names_par)
+  {}
+#endif
 } MY_LOCALE;
 
 extern MY_LOCALE my_locale_en_US;
@@ -1131,6 +1140,7 @@
                                    TABLE_LIST *tables, 
                                    TABLE_LIST **leaves, 
                                    bool select_insert,
+                                   ulong want_access_first,
                                    ulong want_access);
 int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
 	       List<Item> *sum_func_list, uint wild_num);

--- 1.229/sql/opt_range.cc	2006-08-29 18:58:58 +04:00
+++ 1.230/sql/opt_range.cc	2006-08-29 18:58:58 +04:00
@@ -549,6 +549,7 @@
 
   uint fields_bitmap_size;
   MY_BITMAP needed_fields;    /* bitmask of fields needed by the query */
+  MY_BITMAP tmp_covered_fields;
 
   key_map *needed_reg;        /* ptr to SQL_SELECT::needed_reg */
 
@@ -1916,6 +1917,7 @@
   TABLE *table= param->table;
   my_bitmap_map *tmp;
   uint pk;
+  param->tmp_covered_fields.bitmap= 0;
   param->fields_bitmap_size= table->s->column_bitmap_size;
   if (!(tmp= (my_bitmap_map*) alloc_root(param->mem_root,
                                   param->fields_bitmap_size)) ||
@@ -4494,11 +4496,15 @@
   /*I=set of all covering indexes */
   ror_scan_mark= tree->ror_scans;
 
-  my_bitmap_map int_buf[MAX_KEY/(sizeof(my_bitmap_map)*8)+1];
-  MY_BITMAP covered_fields;
-  if (bitmap_init(&covered_fields, int_buf, param->table->s->fields, FALSE))
+  MY_BITMAP *covered_fields= &param->tmp_covered_fields;
+  if (!covered_fields->bitmap) 
+    covered_fields->bitmap= (uchar*)alloc_root(param->mem_root,
+                                               param->fields_bitmap_size);
+  if (!covered_fields->bitmap ||
+      bitmap_init(covered_fields, covered_fields->bitmap,
+                  param->table->s->fields, FALSE))
     DBUG_RETURN(0);
-  bitmap_clear_all(&covered_fields);
+  bitmap_clear_all(covered_fields);
 
   double total_cost= 0.0f;
   ha_rows records=0;
@@ -4518,7 +4524,7 @@
     */
     for (ROR_SCAN_INFO **scan= ror_scan_mark; scan != ror_scans_end; ++scan)
     {
-      bitmap_subtract(&(*scan)->covered_fields, &covered_fields);
+      bitmap_subtract(&(*scan)->covered_fields, covered_fields);
       (*scan)->used_fields_covered=
         bitmap_bits_set(&(*scan)->covered_fields);
       (*scan)->first_uncovered_field=
@@ -4540,8 +4546,8 @@
     if (total_cost > read_time)
       DBUG_RETURN(NULL);
     /* F=F-covered by first(I) */
-    bitmap_union(&covered_fields, &(*ror_scan_mark)->covered_fields);
-    all_covered= bitmap_is_subset(&param->needed_fields, &covered_fields);
+    bitmap_union(covered_fields, &(*ror_scan_mark)->covered_fields);
+    all_covered= bitmap_is_subset(&param->needed_fields, covered_fields);
   } while ((++ror_scan_mark < ror_scans_end) && !all_covered);
   
   if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1)
@@ -4876,25 +4882,37 @@
     break;
 
   case Item_func::BETWEEN:
-    if (inv)
-    {
-      tree= get_ne_mm_tree(param, cond_func, field, cond_func->arguments()[1],
-                           cond_func->arguments()[2], cmp_type);
-    }
-    else
+  {
+    if (!value)
     {
-      tree= get_mm_parts(param, cond_func, field, Item_func::GE_FUNC,
-		         cond_func->arguments()[1],cmp_type);
-      if (tree)
+      if (inv)
       {
-        tree= tree_and(param, tree, get_mm_parts(param, cond_func, field,
-					         Item_func::LE_FUNC,
-					         cond_func->arguments()[2],
-                                                 cmp_type));
+        tree= get_ne_mm_tree(param, cond_func, field, cond_func->arguments()[1],
+                             cond_func->arguments()[2], cmp_type);
+      }
+      else
+      {
+        tree= get_mm_parts(param, cond_func, field, Item_func::GE_FUNC,
+		           cond_func->arguments()[1],cmp_type);
+        if (tree)
+        {
+          tree= tree_and(param, tree, get_mm_parts(param, cond_func, field,
+					           Item_func::LE_FUNC,
+					           cond_func->arguments()[2],
+                                                   cmp_type));
+        }
       }
     }
+    else
+      tree= get_mm_parts(param, cond_func, field,
+                         (inv ?
+                          (value == (Item*)1 ? Item_func::GT_FUNC :
+                                               Item_func::LT_FUNC):
+                          (value == (Item*)1 ? Item_func::LE_FUNC :
+                                               Item_func::GE_FUNC)),
+                         cond_func->arguments()[0], cmp_type);
     break;
-
+  }
   case Item_func::IN_FUNC:
   {
     Item_func_in *func=(Item_func_in*) cond_func;
@@ -4904,41 +4922,33 @@
       if (func->array && func->cmp_type != ROW_RESULT)
       {
         /*
-          We get here for conditions in form "t.key NOT IN (c1, c2, ...)" 
-          (where c{i} are constants).
-          Our goal is to produce a SEL_ARG graph that represents intervals:
+          We get here for conditions in form "t.key NOT IN (c1, c2, ...)",
+          where c{i} are constants. Our goal is to produce a SEL_TREE that 
+          represents intervals:
           
           ($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ...   
(*)
           
           where $MIN is either "-inf" or NULL.
           
-          The most straightforward way to handle NOT IN would be to convert
-          it to "(t.key != c1) AND (t.key != c2) AND ..." and let the range
-          optimizer to build SEL_ARG graph from that. However that will cause
-          the range optimizer to use O(N^2) memory (it's a bug, not filed),
-          and people do use big NOT IN lists (see BUG#15872). Also, for big          
-          NOT IN lists constructing/using graph (*) does not make the query
-          faster.
-          
-          So, we will handle NOT IN manually in the following way:
-          * if the number of entries in the NOT IN list is less then 
-            NOT_IN_IGNORE_THRESHOLD, we will construct SEL_ARG graph (*)
-            manually.
-          * Otherwise, we will construct a smaller graph: for 
-            "t.key NOT IN (c1,...cN)" we construct a graph representing 
-            ($MIN < t.key) OR (cN < t.key)  // here sequence of c_i is
-                                            // ordered.
-
-          A note about partially-covering indexes: for those (e.g. for 
-          "a CHAR(10), KEY(a(5))") the handling is correct (albeit not very
-          efficient):
-          Instead of "t.key < c1" we get "t.key <= prefix-val(c1)".
-          Combining the intervals in (*) together, we get:
-          (-inf<=t.key<=c1) OR (c1<=t.key<=c2) OR (c2<=t.key<=c3) OR
...
-          i.e. actually we get intervals combined into one interval:
-          (-inf<=t.key<=+inf). This doesn't make much sense but it doesn't
-          cause any problems.
+          The most straightforward way to produce it is to convert NOT IN
+          into "(t.key != c1) AND (t.key != c2) AND ... " and let the range
+          analyzer to build SEL_TREE from that. The problem is that the
+          range analyzer will use O(N^2) memory (which is probably a bug),
+          and people do use big NOT IN lists (e.g. see BUG#15872, BUG#21282),
+          will run out of memory.
+
+          Another problem with big lists like (*) is that a big list is
+          unlikely to produce a good "range" access, while considering that
+          range access will require expensive CPU calculations (and for 
+          MyISAM even index accesses). In short, big NOT IN lists are rarely
+          worth analyzing.
+
+          Considering the above, we'll handle NOT IN as follows:
+          * if the number of entries in the NOT IN list is less than
+            NOT_IN_IGNORE_THRESHOLD, construct the SEL_TREE (*) manually.
+          * Otherwise, don't produce a SEL_TREE.
         */
+#define NOT_IN_IGNORE_THRESHOLD 1000
         MEM_ROOT *tmp_root= param->mem_root;
         param->thd->mem_root= param->old_root;
         /* 
@@ -4952,9 +4962,9 @@
         Item *value_item= func->array->create_item();
         param->thd->mem_root= tmp_root;
 
-        if (!value_item)
+        if (func->array->count > NOT_IN_IGNORE_THRESHOLD || !value_item)
           break;
-        
+
         /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval.  */
         uint i=0;
         do 
@@ -4973,45 +4983,39 @@
           tree= NULL;
           break;
         }
-#define NOT_IN_IGNORE_THRESHOLD 1000        
         SEL_TREE *tree2;
-        if (func->array->count < NOT_IN_IGNORE_THRESHOLD)
+        for (; i < func->array->count; i++)
         {
-          for (; i < func->array->count; i++)
+          if (func->array->compare_elems(i, i-1))
           {
-            if (func->array->compare_elems(i, i-1))
+            /* Get a SEL_TREE for "-inf < X < c_i" interval */
+            func->array->value_to_item(i, value_item);
+            tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
+                                value_item, cmp_type);
+            if (!tree2)
             {
-              /* Get a SEL_TREE for "-inf < X < c_i" interval */
-              func->array->value_to_item(i, value_item);
-              tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
-                                  value_item, cmp_type);
-              if (!tree2)
-              {
-                tree= NULL;
-                break;
-              }
+              tree= NULL;
+              break;
+            }
 
-              /* Change all intervals to be "c_{i-1} < X < c_i" */
-              for (uint idx= 0; idx < param->keys; idx++)
+            /* Change all intervals to be "c_{i-1} < X < c_i" */
+            for (uint idx= 0; idx < param->keys; idx++)
+            {
+              SEL_ARG *new_interval, *last_val;
+              if (((new_interval= tree2->keys[idx])) && 
+                  ((last_val= tree->keys[idx]->last())))
               {
-                SEL_ARG *new_interval, *last_val;
-                if (((new_interval= tree2->keys[idx])) && 
-                    ((last_val= tree->keys[idx]->last())))
-                {
-                  new_interval->min_value= last_val->max_value;
-                  new_interval->min_flag= NEAR_MIN;
-                }
+                new_interval->min_value= last_val->max_value;
+                new_interval->min_flag= NEAR_MIN;
               }
-              /* 
-                The following doesn't try to allocate memory so no need to
-                check for NULL.
-              */
-              tree= tree_or(param, tree, tree2);
             }
+            /* 
+              The following doesn't try to allocate memory so no need to
+              check for NULL.
+            */
+            tree= tree_or(param, tree, tree2);
           }
         }
-        else
-          func->array->value_to_item(func->array->count - 1, value_item);
         
         if (tree && tree->type != SEL_TREE::IMPOSSIBLE)
         {
@@ -5076,7 +5080,118 @@
   }
 
   DBUG_RETURN(tree);
+}
+
+
+/*
+  Build conjunction of all SEL_TREEs for a simple predicate applying equalities
+ 
+  SYNOPSIS
+    get_full_func_mm_tree()
+      param       PARAM from SQL_SELECT::test_quick_select
+      cond_func   item for the predicate
+      field_item  field in the predicate
+      value       constant in the predicate
+                  (for BETWEEN it contains the number of the field argument,
+                   for IN it's always 0) 
+      inv         TRUE <> NOT cond_func is considered
+                  (makes sense only when cond_func is BETWEEN or IN)
+
+  DESCRIPTION
+    For a simple SARGable predicate of the form (f op c), where f is a field and
+    c is a constant, the function builds a conjunction of all SEL_TREES that can
+    be obtained by the substitution of f for all different fields equal to f.
+
+  NOTES  
+    If the WHERE condition contains a predicate (fi op c),
+    then not only SELL_TREE for this predicate is built, but
+    the trees for the results of substitution of fi for
+    each fj belonging to the same multiple equality as fi
+    are built as well.
+    E.g. for WHERE t1.a=t2.a AND t2.a > 10 
+    a SEL_TREE for t2.a > 10 will be built for quick select from t2
+    and   
+    a SEL_TREE for t1.a > 10 will be built for quick select from t1.
+
+    A BETWEEN predicate of the form (fi [NOT] BETWEEN c1 AND c2) is treated
+    in a similar way: we build a conjuction of trees for the results
+    of all substitutions of fi for equal fj.
+    Yet a predicate of the form (c BETWEEN f1i AND f2i) is processed
+    differently. It is considered as a conjuction of two SARGable
+    predicates (f1i <= c) and (f2i <=c) and the function get_full_func_mm_tree
+    is called for each of them separately producing trees for 
+       AND j (f1j <=c ) and AND j (f2j <= c) 
+    After this these two trees are united in one conjunctive tree.
+    It's easy to see that the same tree is obtained for
+       AND j,k (f1j <=c AND f2k<=c)
+    which is equivalent to 
+       AND j,k (c BETWEEN f1j AND f2k).
+    The validity of the processing of the predicate (c NOT BETWEEN f1i AND f2i)
+    which equivalent to (f1i > c OR f2i < c) is not so obvious. Here the
+    function get_full_func_mm_tree is called for (f1i > c) and (f2i < c)
+    producing trees for AND j (f1j > c) and AND j (f2j < c). Then this two
+    trees are united in one OR-tree. The expression 
+      (AND j (f1j > c) OR AND j (f2j < c)
+    is equivalent to the expression
+      AND j,k (f1j > c OR f2k < c) 
+    which is just a translation of 
+      AND j,k (c NOT BETWEEN f1j AND f2k)
+
+    In the cases when one of the items f1, f2 is a constant c1 we do not create
+    a tree for it at all. It works for BETWEEN predicates but does not
+    work for NOT BETWEEN predicates as we have to evaluate the expression
+    with it. If it is TRUE then the other tree can be completely ignored.
+    We do not do it now and no trees are built in these cases for
+    NOT BETWEEN predicates.
+
+    As to IN predicates only ones of the form (f IN (c1,...,cn)),
+    where f1 is a field and c1,...,cn are constant, are considered as
+    SARGable. We never try to narrow the index scan using predicates of
+    the form (c IN (c1,...,f,...,cn)). 
+      
+  RETURN 
+    Pointer to the tree representing the built conjunction of SEL_TREEs
+*/
+
+static SEL_TREE *get_full_func_mm_tree(PARAM *param, Item_func *cond_func, 
+                                       Item_field *field_item, Item *value, 
+                                       bool inv)
+{
+  SEL_TREE *tree= 0;
+  SEL_TREE *ftree= 0;
+  table_map ref_tables= 0;
+  table_map param_comp= ~(param->prev_tables | param->read_tables |
+		          param->current_table);
+  DBUG_ENTER("get_full_func_mm_tree");
 
+  for (uint i= 0; i < cond_func->arg_count; i++)
+  {
+    Item *arg= cond_func->arguments()[i]->real_item();
+    if (arg != field_item)
+      ref_tables|= arg->used_tables();
+  }
+  Field *field= field_item->field;
+  Item_result cmp_type= field->cmp_type();
+  if (!((ref_tables | field->table->map) & param_comp))
+    ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv);
+  Item_equal *item_equal= field_item->item_equal;
+  if (item_equal)
+  {
+    Item_equal_iterator it(*item_equal);
+    Item_field *item;
+    while ((item= it++))
+    {
+      Field *f= item->field;
+      if (field->eq(f))
+        continue;
+      if (!((ref_tables | f->table->map) & param_comp))
+      {
+        tree= get_func_mm_tree(param, cond_func, f, value, cmp_type, inv);
+        ftree= !ftree ? tree : tree_and(param, ftree, tree);
+      }
+    }
+  }
+  DBUG_RETURN(ftree);
 }
 
 	/* make a select tree of all keys in condition */
@@ -5087,7 +5202,7 @@
   SEL_TREE *ftree= 0;
   Item_field *field_item= 0;
   bool inv= FALSE;
-  Item *value;
+  Item *value= 0;
   DBUG_ENTER("get_mm_tree");
 
   if (cond->type() == Item::COND_ITEM)
@@ -5167,10 +5282,37 @@
 
   switch (cond_func->functype()) {
   case Item_func::BETWEEN:
-    if (cond_func->arguments()[0]->real_item()->type() != Item::FIELD_ITEM)
-      DBUG_RETURN(0);
-    field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
-    value= NULL;
+    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
+    {
+      field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
+      ftree= get_full_func_mm_tree(param, cond_func, field_item, NULL, inv);
+    }
+
+    /*
+      Concerning the code below see the NOTES section in
+      the comments for the function get_full_func_mm_tree()
+    */
+    for (uint i= 1 ; i < cond_func->arg_count ; i++)
+    {
+     
+      if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
+      {
+        field_item= (Item_field*) (cond_func->arguments()[i]->real_item());
+        SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func, 
+                                    field_item, (Item*) i, inv);
+        if (inv)
+          tree= !tree ? tmp : tree_or(param, tree, tmp);
+        else 
+          tree= tree_and(param, tree, tmp);
+      }
+      else if (inv)
+      { 
+        tree= 0;
+        break;
+      }
+    }
+
+    ftree = tree_and(param, ftree, tree);
     break;
   case Item_func::IN_FUNC:
   {
@@ -5178,7 +5320,7 @@
     if (func->key_item()->real_item()->type() != Item::FIELD_ITEM)
       DBUG_RETURN(0);
     field_item= (Item_field*) (func->key_item()->real_item());
-    value= NULL;
+    ftree= get_full_func_mm_tree(param, cond_func, field_item, NULL, inv);
     break;
   }
   case Item_func::MULT_EQUAL_FUNC:
@@ -5217,47 +5359,9 @@
     }
     else
       DBUG_RETURN(0);
+    ftree= get_full_func_mm_tree(param, cond_func, field_item, value, inv);
   }
 
-  /* 
-     If the where condition contains a predicate (ti.field op const),
-     then not only SELL_TREE for this predicate is built, but
-     the trees for the results of substitution of ti.field for
-     each tj.field belonging to the same multiple equality as ti.field
-     are built as well.
-     E.g. for WHERE t1.a=t2.a AND t2.a > 10 
-     a SEL_TREE for t2.a > 10 will be built for quick select from t2
-     and   
-     a SEL_TREE for t1.a > 10 will be built for quick select from t1.
-  */
-     
-  for (uint i= 0; i < cond_func->arg_count; i++)
-  {
-    Item *arg= cond_func->arguments()[i]->real_item();
-    if (arg != field_item)
-      ref_tables|= arg->used_tables();
-  }
-  Field *field= field_item->field;
-  Item_result cmp_type= field->cmp_type();
-  if (!((ref_tables | field->table->map) & param_comp))
-    ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv);
-  Item_equal *item_equal= field_item->item_equal;
-  if (item_equal)
-  {
-    Item_equal_iterator it(*item_equal);
-    Item_field *item;
-    while ((item= it++))
-    {
-      Field *f= item->field;
-      if (field->eq(f))
-        continue;
-      if (!((ref_tables | f->table->map) & param_comp))
-      {
-        tree= get_func_mm_tree(param, cond_func, f, value, cmp_type, inv);
-        ftree= !ftree ? tree : tree_and(param, ftree, tree);
-      }
-    }
-  }
   DBUG_RETURN(ftree);
 }
 

--- 1.207/sql/sql_acl.cc	2006-08-29 18:58:58 +04:00
+++ 1.208/sql/sql_acl.cc	2006-08-29 18:58:58 +04:00
@@ -1006,6 +1006,7 @@
             sql_print_information("X509 issuer mismatch: should be '%s' "
 			      "but is '%s'", acl_user->x509_issuer, ptr);
           free(ptr);
+          user_access=NO_ACCESS;
           break;
         }
         user_access= acl_user->access;
@@ -1021,11 +1022,13 @@
         if (strcmp(acl_user->x509_subject,ptr))
         {
           if (global_system_variables.log_warnings)
-            sql_print_information("X509 subject mismatch: '%s' vs '%s'",
+            sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
                             acl_user->x509_subject, ptr);
+          free(ptr);
+          user_access=NO_ACCESS;
+          break;
         }
-        else
-          user_access= acl_user->access;
+        user_access= acl_user->access;
         free(ptr);
       }
       break;

--- 1.346/sql/sql_base.cc	2006-08-29 18:58:58 +04:00
+++ 1.347/sql/sql_base.cc	2006-08-29 18:58:58 +04:00
@@ -5482,9 +5482,11 @@
                                    TABLE_LIST *tables,
                                    TABLE_LIST **leaves,
                                    bool select_insert,
+                                   ulong_want_access_first,
                                    ulong want_access)
 {
   TABLE_LIST *leaves_tmp= NULL;
+  bool first_table= true;
 
   if (setup_tables(thd, context, from_clause, tables,
                    &leaves_tmp, select_insert))
@@ -5495,11 +5497,13 @@
   for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
   {
     if (leaves_tmp->belong_to_view && 
-        check_single_table_access(thd, want_access,  leaves_tmp))
+        check_single_table_access(thd, first_table ? want_access_first :
+                                  want_access,  leaves_tmp))
     {
       tables->hide_view_error(thd);
       return TRUE;
     }
+    first_table= 0;
   }
   return FALSE;
 }

--- 1.285/sql/sql_class.cc	2006-08-29 18:58:58 +04:00
+++ 1.286/sql/sql_class.cc	2006-08-29 18:58:58 +04:00
@@ -1983,7 +1983,7 @@
     {
       if ((xx=li++))
       {
-        xx->check();
+        xx->check(0);
 	xx->update();
       }
     }

--- 1.191/sql/sql_delete.cc	2006-08-29 18:58:58 +04:00
+++ 1.192/sql/sql_delete.cc	2006-08-29 18:58:58 +04:00
@@ -386,7 +386,7 @@
                                     &thd->lex->select_lex.top_join_list,
                                     table_list, 
                                     &select_lex->leaf_tables, FALSE, 
-                                    DELETE_ACL) ||
+                                    DELETE_ACL, SELECT_ACL) ||
       setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
       setup_ftfuncs(select_lex))
     DBUG_RETURN(TRUE);
@@ -449,7 +449,7 @@
                                     &thd->lex->select_lex.top_join_list,
                                     lex->query_tables,
                                     &lex->select_lex.leaf_tables, FALSE, 
-                                    DELETE_ACL))
+                                    DELETE_ACL, SELECT_ACL))
     DBUG_RETURN(TRUE);
 
 

--- 1.220/sql/sql_insert.cc	2006-08-29 18:58:58 +04:00
+++ 1.221/sql/sql_insert.cc	2006-08-29 18:58:58 +04:00
@@ -821,7 +821,7 @@
                                     &thd->lex->select_lex.top_join_list,
                                     table_list,
                                     &thd->lex->select_lex.leaf_tables,
-                                    select_insert, SELECT_ACL))
+                                    select_insert, INSERT_ACL, SELECT_ACL))
     DBUG_RETURN(TRUE);
 
   if (insert_into_view && !fields.elements)

--- 1.103/sql/sql_load.cc	2006-08-29 18:58:58 +04:00
+++ 1.104/sql/sql_load.cc	2006-08-29 18:58:58 +04:00
@@ -156,6 +156,7 @@
                                     &thd->lex->select_lex.top_join_list,
                                     table_list,
                                     &thd->lex->select_lex.leaf_tables, FALSE,
+                                    INSERT_ACL | UPDATE_ACL,
                                     INSERT_ACL | UPDATE_ACL))
      DBUG_RETURN(-1);
   if (!table_list->table ||               // do not suport join view

--- 1.580/sql/sql_parse.cc	2006-08-29 18:58:59 +04:00
+++ 1.581/sql/sql_parse.cc	2006-08-29 18:58:59 +04:00
@@ -5354,10 +5354,21 @@
     return 1;
 
   /* Check rights on tables of subselects and implictly opened tables */
-  TABLE_LIST *subselects_tables;
+  TABLE_LIST *subselects_tables, *view= all_tables->view ? all_tables : 0;
   if ((subselects_tables= all_tables->next_global))
   {
-    if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
+    /*
+      Access rights asked for the first table of a view should be the same
+      as for the view
+    */
+    if (view && subselects_tables->belong_to_view == view)
+    {
+      if (check_single_table_access (thd, privilege, subselects_tables))
+        return 1;
+      subselects_tables= subselects_tables->next_global;
+    }
+    if (subselects_tables &&
+        (check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
       return 1;
   }
   return 0;

--- 1.431/sql/sql_select.cc	2006-08-29 18:58:59 +04:00
+++ 1.432/sql/sql_select.cc	2006-08-29 18:58:59 +04:00
@@ -344,7 +344,7 @@
        setup_tables_and_check_access(thd, &select_lex->context, join_list,
                                      tables_list,
                                      &select_lex->leaf_tables, FALSE, 
-                                     SELECT_ACL)) ||
+                                     SELECT_ACL, SELECT_ACL)) ||
       setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
       select_lex->setup_ref_array(thd, og_num) ||
       setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ,
@@ -2233,6 +2233,7 @@
   int ref_changed;
   do
   {
+  more_const_tables_found:
     ref_changed = 0;
     found_ref=0;
 
@@ -2244,6 +2245,30 @@
     for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
     {
       table=s->table;
+
+      /* 
+        If equi-join condition by a key is null rejecting and after a
+        substitution of a const table the key value happens to be null
+        then we can state that there are no matches for this equi-join.
+      */  
+      if ((keyuse= s->keyuse) && *s->on_expr_ref)
+      {
+        while (keyuse->table == table)
+        {
+          if (!(keyuse->val->used_tables() & ~join->const_table_map)
&&
+              keyuse->val->is_null() && keyuse->null_rejecting)
+          {
+            s->type= JT_CONST;
+            mark_as_null_row(table);
+            found_const_table_map|= table->map;
+	    join->const_table_map|= table->map;
+	    set_position(join,const_count++,s,(KEYUSE*) 0);
+            goto more_const_tables_found;
+           }
+	  keyuse++;
+        }
+      }
+
       if (s->dependent)				// If dependent on some table
       {
 	// All dep. must be constants
@@ -2294,34 +2319,38 @@
 	  } while (keyuse->table == table && keyuse->key == key);
 
 	  if (eq_part.is_prefix(table->key_info[key].key_parts) &&
-	      ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
-	       HA_NOSAME) &&
               !table->fulltext_searched && 
               !table->pos_in_table_list->embedding)
 	  {
-	    if (const_ref == eq_part)
-	    {					// Found everything for ref.
-	      int tmp;
-	      ref_changed = 1;
-	      s->type= JT_CONST;
-	      join->const_table_map|=table->map;
-	      set_position(join,const_count++,s,start_keyuse);
-	      if (create_ref_for_key(join, s, start_keyuse,
-				     found_const_table_map))
-		DBUG_RETURN(1);
-	      if ((tmp=join_read_const_table(s,
-                                             join->positions+const_count-1)))
-	      {
-		if (tmp > 0)
-		  DBUG_RETURN(1);			// Fatal error
+            if ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY))
+                 == HA_NOSAME)
+            {
+	      if (const_ref == eq_part)
+	      {					// Found everything for ref.
+	        int tmp;
+	        ref_changed = 1;
+	        s->type= JT_CONST;
+	        join->const_table_map|=table->map;
+	        set_position(join,const_count++,s,start_keyuse);
+	        if (create_ref_for_key(join, s, start_keyuse,
+				       found_const_table_map))
+		  DBUG_RETURN(1);
+	        if ((tmp=join_read_const_table(s,
+                                               join->positions+const_count-1)))
+	        {
+		  if (tmp > 0)
+		    DBUG_RETURN(1);			// Fatal error
+	        }
+	        else
+		  found_const_table_map|= table->map;
+	        break;
 	      }
 	      else
-		found_const_table_map|= table->map;
-	      break;
+	        found_ref|= refs;      // Table is const if all refs are const
 	    }
-	    else
-	      found_ref|= refs;		// Table is const if all refs are const
-	  }
+            else if (const_ref == eq_part)
+              s->const_keys.set_bit(key);
+          }
 	}
       }
     }
@@ -2727,7 +2756,8 @@
     We use null_rejecting in add_not_null_conds() to add
     'othertbl.field IS NOT NULL' to tab->select_cond.
   */
-  (*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC)
&&
+  (*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC ||
+                                   cond->functype() == Item_func::MULT_EQUAL_FUNC)
&&
                                   ((*value)->type() == Item::FIELD_ITEM) &&
                                   ((Item_field*)*value)->field->maybe_null());
   (*key_fields)++;
@@ -2827,11 +2857,12 @@
     break;
   case Item_func::OPTIMIZE_KEY:
   {
+    Item **values;
     // BETWEEN, IN, NE
     if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM
&&
 	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
     {
-      Item **values= cond_func->arguments()+1;
+      values= cond_func->arguments()+1;
       if (cond_func->functype() == Item_func::NE_FUNC &&
         cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM
&&
 	     !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
@@ -2844,6 +2875,22 @@
                            cond_func->argument_count()-1,
                            usable_tables);
     }
+    if (cond_func->functype() == Item_func::BETWEEN)
+    {
+      values= cond_func->arguments();
+      for (uint i= 1 ; i < cond_func->argument_count() ; i++)
+      {
+        Item_field *field_item;
+        if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
+            &&
+            !(cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
+        {
+          field_item= (Item_field *) (cond_func->arguments()[i]->real_item());
+          add_key_equal_fields(key_fields, *and_level, cond_func,
+                               field_item, 0, values, 1, usable_tables);
+        }
+      }  
+    }
     break;
   }
   case Item_func::OPTIMIZE_OP:
@@ -3476,7 +3523,7 @@
                                                  keyuse->used_tables));
             if (tmp < best_prev_record_reads)
             {
-              best_part_found_ref= keyuse->used_tables;
+              best_part_found_ref= keyuse->used_tables &
~join->const_table_map;
               best_prev_record_reads= tmp;
             }
             if (rec > keyuse->ref_table_rows)
@@ -6034,7 +6081,8 @@
   if (tab->cached_eq_ref_table)			// If cached
     return tab->eq_ref_table;
   tab->cached_eq_ref_table=1;
-  if (tab->type == JT_CONST)			// We can skip const tables
+  /* We can skip const tables only if not an outer table */
+  if (tab->type == JT_CONST && !tab->first_inner)
     return (tab->eq_ref_table=1);		/* purecov: inspected */
   if (tab->type != JT_EQ_REF || tab->table->maybe_null)
     return (tab->eq_ref_table=0);		// We must use this
@@ -6556,6 +6604,7 @@
         field_item= (Item_field*) right_item;
         const_item= left_item;
       }
+
       if (const_item &&
           field_item->result_type() == const_item->result_type())
       {
@@ -7213,6 +7262,7 @@
   Item_func::Functype functype=  func->functype();
 
   if (right_item->eq(field,0) && left_item != value &&
+      right_item->cmp_context == field->cmp_context &&
       (left_item->result_type() != STRING_RESULT ||
        value->result_type() != STRING_RESULT ||
        left_item->collation.collation == value->collation.collation))
@@ -7234,6 +7284,7 @@
     }
   }
   else if (left_item->eq(field,0) && right_item != value &&
+           left_item->cmp_context == field->cmp_context &&
            (right_item->result_type() != STRING_RESULT ||
             value->result_type() != STRING_RESULT ||
             right_item->collation.collation == value->collation.collation))
@@ -11619,6 +11670,8 @@
     We must not try to use disabled keys.
   */
   usable_keys= table->s->keys_in_use;
+  /* we must not consider keys that are disabled by IGNORE INDEX */
+  usable_keys.intersect(table->keys_in_use_for_query);
 
   for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
   {
@@ -13489,7 +13542,9 @@
   {
     Field *field;
 
-    if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+    if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) ||
+        (item->type() == Item::FUNC_ITEM &&
+         ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC))
       item_field= item;
     else
     {

--- 1.204/sql/sql_update.cc	2006-08-29 18:58:59 +04:00
+++ 1.205/sql/sql_update.cc	2006-08-29 18:58:59 +04:00
@@ -746,7 +746,7 @@
                                     &select_lex->top_join_list,
                                     table_list,
                                     &select_lex->leaf_tables,
-                                    FALSE, UPDATE_ACL) ||
+                                    FALSE, UPDATE_ACL, SELECT_ACL) ||
       setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
       select_lex->setup_ref_array(thd, order_num) ||
       setup_order(thd, select_lex->ref_pointer_array,
@@ -841,7 +841,7 @@
                                     &lex->select_lex.top_join_list,
                                     table_list,
                                     &lex->select_lex.leaf_tables, FALSE,
-                                    UPDATE_ACL))
+                                    UPDATE_ACL, SELECT_ACL))
     DBUG_RETURN(TRUE);
 
   if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))

--- 1.7/mysql-test/r/innodb_mysql.result	2006-08-29 18:58:59 +04:00
+++ 1.8/mysql-test/r/innodb_mysql.result	2006-08-29 18:58:59 +04:00
@@ -89,6 +89,27 @@
 3	3
 3	3
 DROP TABLE t1, t2, t3;
+CREATE TABLE `t1` (`id1` INT) ;
+INSERT INTO `t1` (`id1`) VALUES (1),(5),(2);
+CREATE TABLE `t2` (
+`id1` INT,
+`id2` INT NOT NULL,
+`id3` INT,
+`id4` INT NOT NULL,
+UNIQUE (`id2`,`id4`),
+KEY (`id1`)
+) ENGINE=InnoDB;
+INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES 
+(1,1,1,0),
+(1,1,2,1),
+(5,1,2,2),
+(6,1,2,3),
+(1,2,2,2),
+(1,2,1,1);
+SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND
`id3` = 2);
+id1
+2
+DROP TABLE t1, t2;
 create table t1m (a int) engine=myisam;
 create table t1i (a int) engine=innodb;
 create table t2m (a int) engine=myisam;
@@ -303,6 +324,25 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	NULL	PRIMARY	5	NULL	3	Using index for group-by; Using temporary
 drop table t1;
+CREATE TABLE t1 (id int(11) NOT NULL PRIMARY KEY, name varchar(20),
+INDEX (name)) ENGINE=InnoDB;
+CREATE TABLE t2 (id int(11) NOT NULL PRIMARY KEY, fkey int(11),
+FOREIGN KEY (fkey) REFERENCES t2(id)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,'A1'),(2,'A2'),(3,'B');
+INSERT INTO t2 VALUES (1,1),(2,2),(3,2),(4,3),(5,3);
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id 
+WHERE t1.name LIKE 'A%';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	index	PRIMARY,name	name	23	NULL	3	Using where; Using index
+1	SIMPLE	t2	ref	fkey	fkey	5	test.t1.id	1	Using where; Using index
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id 
+WHERE t1.name LIKE 'A%' OR FALSE;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	index	NULL	fkey	5	NULL	5	Using index
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.fkey	1	Using where
+DROP TABLE t1,t2;
 set storage_engine=innodb;
 CREATE TABLE t1 (a int, b int);
 insert into t1 values (1,1),(1,2);

--- 1.7/mysql-test/t/innodb_mysql.test	2006-08-29 18:58:59 +04:00
+++ 1.8/mysql-test/t/innodb_mysql.test	2006-08-29 18:58:59 +04:00
@@ -98,6 +98,33 @@
   t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) 
   ORDER BY t1.b LIMIT 5;
 DROP TABLE t1, t2, t3;
+
+
+# BUG#21077 (The testcase is not deterministic so correct execution doesn't
+# prove anything) For proof one should track if sequence of ha_innodb::* func
+# calls is correct.
+CREATE TABLE `t1` (`id1` INT) ;
+INSERT INTO `t1` (`id1`) VALUES (1),(5),(2);
+
+CREATE TABLE `t2` (
+  `id1` INT,
+  `id2` INT NOT NULL,
+  `id3` INT,
+  `id4` INT NOT NULL,
+  UNIQUE (`id2`,`id4`),
+  KEY (`id1`)
+) ENGINE=InnoDB;
+
+INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES 
+(1,1,1,0),
+(1,1,2,1),
+(5,1,2,2),
+(6,1,2,3),
+(1,2,2,2),
+(1,2,1,1);
+
+SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND
`id3` = 2);
+DROP TABLE t1, t2;
 #
 # Bug #12882  	min/max inconsistent on empty table
 #
@@ -263,6 +290,26 @@
 explain select distinct f1, f2 from t1;
 drop table t1;
 
+#
+# Test for bug #17164: ORed FALSE blocked conversion of outer join into join
+# 
+
+CREATE TABLE t1 (id int(11) NOT NULL PRIMARY KEY, name varchar(20),
+                 INDEX (name)) ENGINE=InnoDB;
+CREATE TABLE t2 (id int(11) NOT NULL PRIMARY KEY, fkey int(11),
+                 FOREIGN KEY (fkey) REFERENCES t2(id)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,'A1'),(2,'A2'),(3,'B');
+INSERT INTO t2 VALUES (1,1),(2,2),(3,2),(4,3),(5,3);
+
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id 
+  WHERE t1.name LIKE 'A%';
+
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id 
+  WHERE t1.name LIKE 'A%' OR FALSE;
+
+DROP TABLE t1,t2;
 
 #
 # Test of behaviour with CREATE ... SELECT

--- 1.150/mysql-test/r/subselect.result	2006-08-29 18:58:59 +04:00
+++ 1.151/mysql-test/r/subselect.result	2006-08-29 18:58:59 +04:00
@@ -2915,6 +2915,28 @@
 s1
 2
 drop table t1;
+create table t1 (
+retailerID varchar(8) NOT NULL,
+statusID   int(10) unsigned NOT NULL,
+changed    datetime NOT NULL,
+UNIQUE KEY retailerID (retailerID, statusID, changed)
+);
+INSERT INTO t1 VALUES("0026", "1", "2005-12-06 12:18:56");
+INSERT INTO t1 VALUES("0026", "2", "2006-01-06 12:25:53");
+INSERT INTO t1 VALUES("0037", "1", "2005-12-06 12:18:56");
+INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53");
+INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50");
+INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50");
+select * from t1 r1 
+where (r1.retailerID,(r1.changed)) in 
+(SELECT r2.retailerId,(max(changed)) from t1 r2 
+group by r2.retailerId);
+retailerID	statusID	changed
+0026	2	2006-01-06 12:25:53
+0037	2	2006-01-06 12:25:53
+0048	1	2006-01-06 12:37:50
+0059	1	2006-01-06 12:37:50
+drop table t1;
 create table t1 (df decimal(5,1));
 insert into t1 values(1.1);
 insert into t1 values(2.2);

--- 1.172/mysql-test/r/view.result	2006-08-29 18:58:59 +04:00
+++ 1.173/mysql-test/r/view.result	2006-08-29 18:58:59 +04:00
@@ -2850,3 +2850,32 @@
 t1
 DROP TABLE t1;
 DROP VIEW IF EXISTS v1;
+CREATE DATABASE bug21261DB;
+USE bug21261DB;
+CREATE TABLE t1 (x INT);
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1;
+GRANT INSERT, UPDATE ON v1 TO 'user21261'@'localhost';
+GRANT INSERT, UPDATE ON t1 TO 'user21261'@'localhost';
+CREATE TABLE t2 (y INT);
+GRANT SELECT ON t2 TO 'user21261'@'localhost';
+INSERT INTO v1 (x) VALUES (5);
+UPDATE v1 SET x=1;
+GRANT SELECT ON v1 TO 'user21261'@'localhost';
+GRANT SELECT ON t1 TO 'user21261'@'localhost';
+UPDATE v1,t2 SET x=1 WHERE x=y;
+SELECT * FROM t1;
+x
+1
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user21261'@'localhost';
+DROP USER 'user21261'@'localhost';
+DROP VIEW v1;
+DROP TABLE t1;
+DROP DATABASE bug21261DB;
+USE test;
+create table t1 (f1 datetime);
+create view v1 as select * from t1 where f1 between now() and now() + interval 1 minute;
+show create view v1;
+View	Create View
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1`
AS select `t1`.`f1` AS `f1` from `t1` where (`t1`.`f1` between now() and (now() +
interval 1 minute))
+drop view v1;
+drop table t1;

--- 1.153/mysql-test/t/view.test	2006-08-29 18:58:59 +04:00
+++ 1.154/mysql-test/t/view.test	2006-08-29 18:58:59 +04:00
@@ -2723,3 +2723,45 @@
 --disable_warnings
 DROP VIEW IF EXISTS v1;
 --enable_warnings
+
+#
+# Bug #21261: Wrong access rights was required for an insert to a view
+#
+CREATE DATABASE bug21261DB;
+USE bug21261DB;
+CONNECT (root,localhost,root,,bug21261DB);
+CONNECTION root;
+
+CREATE TABLE t1 (x INT);
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1;
+GRANT INSERT, UPDATE ON v1 TO 'user21261'@'localhost';
+GRANT INSERT, UPDATE ON t1 TO 'user21261'@'localhost';
+CREATE TABLE t2 (y INT);
+GRANT SELECT ON t2 TO 'user21261'@'localhost';
+
+CONNECT (user21261, localhost, user21261,, bug21261DB);
+CONNECTION user21261;
+INSERT INTO v1 (x) VALUES (5);
+UPDATE v1 SET x=1;
+CONNECTION root;
+GRANT SELECT ON v1 TO 'user21261'@'localhost';
+GRANT SELECT ON t1 TO 'user21261'@'localhost';
+CONNECTION user21261;
+UPDATE v1,t2 SET x=1 WHERE x=y;
+CONNECTION root;
+SELECT * FROM t1;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user21261'@'localhost';
+DROP USER 'user21261'@'localhost';
+DROP VIEW v1;
+DROP TABLE t1;
+DROP DATABASE bug21261DB;
+USE test;
+
+#
+# Bug #15950: NOW() optimized away in VIEWs
+#
+create table t1 (f1 datetime);
+create view v1 as select * from t1 where f1 between now() and now() + interval 1 minute;
+show create view v1;
+drop view v1;
+drop table t1;

--- 1.128/sql/item_subselect.cc	2006-08-29 18:58:59 +04:00
+++ 1.129/sql/item_subselect.cc	2006-08-29 18:58:59 +04:00
@@ -1141,24 +1141,23 @@
         DBUG_RETURN(RES_ERROR);
       Item *item_eq=
         new Item_func_eq(new
-                         Item_direct_ref(&select_lex->context,
-                                         (*optimizer->get_cache())->
-                                         addr(i),
-                                         (char *)"<no matter>",
-                                         (char *)in_left_expr_name),
+                         Item_ref(&select_lex->context,
+                                  (*optimizer->get_cache())->
+                                  addr(i),
+                                  (char *)"<no matter>",
+                                  (char *)in_left_expr_name),
                          new
-                         Item_direct_ref(&select_lex->context,
-                                         select_lex->ref_pointer_array + i,
-                                         (char *)"<no matter>",
-                                         (char *)"<list ref>")
+                         Item_ref(&select_lex->context,
+                                  select_lex->ref_pointer_array + i,
+                                  (char *)"<no matter>",
+                                  (char *)"<list ref>")
                         );
       Item *item_isnull=
         new Item_func_isnull(new
-                             Item_direct_ref(&select_lex->context,
-                                             select_lex->
-                                             ref_pointer_array+i,
-                                             (char *)"<no matter>",
-                                             (char *)"<list ref>")
+                             Item_ref(&select_lex->context,
+                                      select_lex->ref_pointer_array+i,
+                                      (char *)"<no matter>",
+                                      (char *)"<list ref>")
                             );
       having_item=
         and_items(having_item,
@@ -1168,11 +1167,11 @@
                   new
                   Item_is_not_null_test(this,
                                         new
-                                        Item_direct_ref(&select_lex->context,
-                                                        select_lex->
-                                                        ref_pointer_array + i,
-                                                        (char *)"<no matter>",
-                                                        (char *)"<list ref>")
+                                        Item_ref(&select_lex->context,
+                                                 select_lex->
+                                                 ref_pointer_array + i,
+                                                 (char *)"<no matter>",
+                                                 (char *)"<list ref>")
                                        )
                  );
       item_having_part2->top_level_item();
@@ -1228,11 +1227,11 @@
                     new
                     Item_is_not_null_test(this,
                                           new
-                                          Item_direct_ref(&select_lex->context,
-                                                          select_lex->
-                                                          ref_pointer_array + i,
-                                                          (char *)"<no matter>",
-                                                          (char *)"<list ref>")
+                                          Item_ref(&select_lex->context,
+                                                   select_lex->
+                                                   ref_pointer_array + i,
+                                                   (char *)"<no matter>",
+                                                   (char *)"<list ref>")
                                          )
                   );
         item_isnull= new

--- 1.38.3.1/innobase/btr/btr0btr.c	2006-08-29 18:58:59 +04:00
+++ 1.45/storage/innobase/btr/btr0btr.c	2006-08-29 18:58:59 +04:00
@@ -5,7 +5,7 @@
 
 Created 6/2/1994 Heikki Tuuri
 *******************************************************/
- 
+
 #include "btr0btr.h"
 
 #ifdef UNIV_NONINL
@@ -56,7 +56,7 @@
 which are >= P in the alphabetical order, but < P1 if there is
 a next node pointer on the level, and P1 is its prefix.
 
-If a node pointer with a prefix P points to a non-leaf child, 
+If a node pointer with a prefix P points to a non-leaf child,
 then the leftmost record in the child must have the same
 prefix P. If it points to a leaf node, the child is not required
 to contain any record with a prefix equal to P. The leaf case
@@ -138,14 +138,14 @@
 	ulint	space;
 	ulint	root_page_no;
 	page_t*	root;
-	
+
 	space = dict_tree_get_space(tree);
 	root_page_no = dict_tree_get_page(tree);
 
 	root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
 	ut_a((ibool)!!page_is_comp(root) ==
-			UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
-	
+			dict_table_is_comp(tree->tree_index->table));
+
 	return(root);
 }
 
@@ -175,21 +175,25 @@
 			return(prev_rec);
 		}
 	}
-	
+
 	page = buf_frame_align(rec);
 	prev_page_no = btr_page_get_prev(page, mtr);
 	space = buf_frame_get_space_id(page);
-	
+
 	if (prev_page_no != FIL_NULL) {
 
 		prev_page = buf_page_get_with_no_latch(space, prev_page_no,
 									mtr);
 		/* The caller must already have a latch to the brother */
 		ut_ad((mtr_memo_contains(mtr, buf_block_align(prev_page),
-		      				MTR_MEMO_PAGE_S_FIX))
-		      || (mtr_memo_contains(mtr, buf_block_align(prev_page),
-		      				MTR_MEMO_PAGE_X_FIX)));
+						MTR_MEMO_PAGE_S_FIX))
+			|| (mtr_memo_contains(mtr, buf_block_align(prev_page),
+					MTR_MEMO_PAGE_X_FIX)));
 		ut_a(page_is_comp(prev_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_next(prev_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 
 		return(page_rec_get_prev(page_get_supremum_rec(prev_page)));
 	}
@@ -223,20 +227,24 @@
 			return(next_rec);
 		}
 	}
-	
+
 	page = buf_frame_align(rec);
 	next_page_no = btr_page_get_next(page, mtr);
 	space = buf_frame_get_space_id(page);
-	
+
 	if (next_page_no != FIL_NULL) {
 
 		next_page = buf_page_get_with_no_latch(space, next_page_no,
 									mtr);
 		/* The caller must already have a latch to the brother */
 		ut_ad((mtr_memo_contains(mtr, buf_block_align(next_page),
-		      				MTR_MEMO_PAGE_S_FIX))
-		      || (mtr_memo_contains(mtr, buf_block_align(next_page),
-		      				MTR_MEMO_PAGE_X_FIX)));
+						MTR_MEMO_PAGE_S_FIX))
+			|| (mtr_memo_contains(mtr, buf_block_align(next_page),
+						MTR_MEMO_PAGE_X_FIX)));
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_prev(next_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 
 		ut_a(page_is_comp(next_page) == page_is_comp(page));
 		return(page_rec_get_next(page_get_infimum_rec(next_page)));
@@ -257,11 +265,11 @@
 	mtr_t*		mtr)	/* in: mtr */
 {
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	page_create(page, mtr,
-			UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
+			dict_table_is_comp(tree->tree_index->table));
 	buf_block_align(page)->check_index_page_at_flush = TRUE;
-	
+
 	btr_page_set_index_id(page, tree->id, mtr);
 }
 
@@ -281,7 +289,7 @@
 	page_t*		new_page;
 
 	root = btr_root_get(tree, mtr);
-	
+
 	node_addr = flst_get_first(root + PAGE_HEADER
 					+ PAGE_BTR_IBUF_FREE_LIST, mtr);
 	ut_a(node_addr.page != FIL_NULL);
@@ -293,7 +301,7 @@
 #endif /* UNIV_SYNC_DEBUG */
 
 	flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
-		    new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
+		new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
 									mtr);
 	ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
 
@@ -328,7 +336,7 @@
 	}
 
 	root = btr_root_get(tree, mtr);
-		
+
 	if (level == 0) {
 		seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
 	} else {
@@ -338,7 +346,7 @@
 	/* Parameter TRUE below states that the caller has made the
 	reservation for free extents, and thus we know that a page can
 	be allocated: */
-	
+
 	new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
 						file_direction, TRUE, mtr);
 	if (new_page_no == FIL_NULL) {
@@ -351,9 +359,9 @@
 #ifdef UNIV_SYNC_DEBUG
 	buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW);
 #endif /* UNIV_SYNC_DEBUG */
-							
+
 	return(new_page);
-}	
+}
 
 /******************************************************************
 Gets the number of pages in a B-tree. */
@@ -376,20 +384,20 @@
 	mtr_s_lock(dict_tree_get_lock(index->tree), &mtr);
 
 	root = btr_root_get(index->tree, &mtr);
-		
+
 	if (flag == BTR_N_LEAF_PAGES) {
 		seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-		
+
 		fseg_n_reserved_pages(seg_header, &n, &mtr);
-		
+
 	} else if (flag == BTR_TOTAL_SIZE) {
 		seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
 
 		n = fseg_n_reserved_pages(seg_header, &dummy, &mtr);
-		
+
 		seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-		
-		n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);		
+
+		n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);
 	} else {
 		ut_error;
 	}
@@ -397,7 +405,7 @@
 	mtr_commit(&mtr);
 
 	return(n);
-}	
+}
 
 /******************************************************************
 Frees a page used in an ibuf tree. Puts the page to the free list of the
@@ -407,17 +415,17 @@
 btr_page_free_for_ibuf(
 /*===================*/
 	dict_tree_t*	tree,	/* in: index tree */
-	page_t*		page,	/* in: page to be freed, x-latched */	
+	page_t*		page,	/* in: page to be freed, x-latched */
 	mtr_t*		mtr)	/* in: mtr */
 {
 	page_t*		root;
 
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	root = btr_root_get(tree, mtr);
-	
+
 	flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
-		       page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
+		page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
 
 	ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
 									mtr));
@@ -432,7 +440,7 @@
 btr_page_free_low(
 /*==============*/
 	dict_tree_t*	tree,	/* in: index tree */
-	page_t*		page,	/* in: page to be freed, x-latched */	
+	page_t*		page,	/* in: page to be freed, x-latched */
 	ulint		level,	/* in: page level */
 	mtr_t*		mtr)	/* in: mtr */
 {
@@ -442,12 +450,12 @@
 	ulint		page_no;
 
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	/* The page gets invalid for optimistic searches: increment the frame
 	modify clock */
 
 	buf_frame_modify_clock_inc(page);
-	
+
 	if (tree->type & DICT_IBUF) {
 
 		btr_page_free_for_ibuf(tree, page, mtr);
@@ -456,7 +464,7 @@
 	}
 
 	root = btr_root_get(tree, mtr);
-	
+
 	if (level == 0) {
 		seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
 	} else {
@@ -465,9 +473,9 @@
 
 	space = buf_frame_get_space_id(page);
 	page_no = buf_frame_get_page_no(page);
-	
+
 	fseg_free_page(seg_header, space, page_no, mtr);
-}	
+}
 
 /******************************************************************
 Frees a file page used in an index tree. NOTE: cannot free field external
@@ -477,17 +485,17 @@
 btr_page_free(
 /*==========*/
 	dict_tree_t*	tree,	/* in: index tree */
-	page_t*		page,	/* in: page to be freed, x-latched */	
+	page_t*		page,	/* in: page to be freed, x-latched */
 	mtr_t*		mtr)	/* in: mtr */
 {
 	ulint		level;
 
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	level = btr_page_get_level(page, mtr);
-	
+
 	btr_page_free_low(tree, page, level, mtr);
-}	
+}
 
 /******************************************************************
 Sets the child node file address in a node pointer. */
@@ -507,12 +515,12 @@
 	ut_ad(0 < btr_page_get_level(buf_frame_align(rec), mtr));
 	ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
 
-	/* The child address is in the last field */	
+	/* The child address is in the last field */
 	field = rec_get_nth_field(rec, offsets,
 					rec_offs_n_fields(offsets) - 1, &len);
 
 	ut_ad(len == 4);
-	
+
 	mlog_write_ulint(field, page_no, MLOG_4BYTES, mtr);
 }
 
@@ -536,7 +544,7 @@
 	page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
 
 	page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
-	
+
 	return(page);
 }
 
@@ -567,14 +575,14 @@
 	ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
 							MTR_MEMO_X_LOCK));
 	ut_a(page_rec_is_user_rec(user_rec));
-	
+
 	ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page));
 
 	heap = mem_heap_create(100);
 
 	tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap,
 					 btr_page_get_level(page, mtr));
-	index = UT_LIST_GET_FIRST(tree->tree_indexes);
+	index = tree->tree_index;
 
 	/* In the following, we choose just any index from the tree as the
 	first parameter for btr_cur_search_to_nth_level. */
@@ -589,7 +597,7 @@
 						ULINT_UNDEFINED, &heap);
 
 	if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
-                                                buf_frame_get_page_no(page)) {
+						buf_frame_get_page_no(page)) {
 		rec_t*	print_rec;
 		fputs("InnoDB: Dump of the child page:\n", stderr);
 		buf_page_print(buf_frame_align(page));
@@ -597,9 +605,9 @@
 		buf_page_print(buf_frame_align(node_ptr));
 
 		fputs("InnoDB: Corruption of an index tree: table ", stderr);
-		ut_print_name(stderr, NULL, index->table_name);
+		ut_print_name(stderr, NULL, TRUE, index->table_name);
 		fputs(", index ", stderr);
-		ut_print_name(stderr, NULL, index->name);
+		ut_print_name(stderr, NULL, FALSE, index->name);
 		fprintf(stderr, ",\n"
 "InnoDB: father ptr page no %lu, child page no %lu\n",
 			(ulong)
@@ -677,13 +685,13 @@
 		buf_page_dbg_add_level(ibuf_hdr_frame, SYNC_TREE_NODE_NEW);
 #endif /* UNIV_SYNC_DEBUG */
 		ut_ad(buf_frame_get_page_no(ibuf_hdr_frame)
- 						== IBUF_HEADER_PAGE_NO);
+						== IBUF_HEADER_PAGE_NO);
 		/* Allocate then the next page to the segment: it will be the
- 		tree root page */
+		tree root page */
 
- 		page_no = fseg_alloc_free_page(
+		page_no = fseg_alloc_free_page(
 				ibuf_hdr_frame + IBUF_HEADER
- 				+ IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO,
+				+ IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO,
 				FSP_UP, mtr);
 		ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
 
@@ -692,14 +700,14 @@
 		frame = fseg_create(space, 0, PAGE_HEADER + PAGE_BTR_SEG_TOP,
 									mtr);
 	}
-	
+
 	if (frame == NULL) {
 
 		return(FIL_NULL);
 	}
 
 	page_no = buf_frame_get_page_no(frame);
-	
+
 #ifdef UNIV_SYNC_DEBUG
 	buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW);
 #endif /* UNIV_SYNC_DEBUG */
@@ -708,9 +716,9 @@
 		/* It is an insert buffer tree: initialize the free list */
 
 		ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
-		
+
 		flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
-	} else {	
+	} else {
 		/* It is a non-ibuf tree: create a file segment for leaf
 		pages */
 		fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF,
@@ -721,7 +729,7 @@
 		buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW);
 #endif /* UNIV_SYNC_DEBUG */
 	}
-	
+
 	/* Create a new index page on the the allocated segment page */
 	page = page_create(frame, mtr, comp);
 	buf_block_align(page)->check_index_page_at_flush = TRUE;
@@ -731,7 +739,7 @@
 
 	/* Set the level of the new index page */
 	btr_page_set_level(page, 0, mtr);
-	
+
 	/* Set the next node and previous node fields */
 	btr_page_set_next(page, FIL_NULL, mtr);
 	btr_page_set_prev(page, FIL_NULL, mtr);
@@ -739,7 +747,7 @@
 	/* We reset the free bits for the page to allow creation of several
 	trees in the same mtr, otherwise the latch on a bitmap page would
 	prevent it because of the latching order */
-	
+
 	ibuf_reset_free_bits_with_type(type, page);
 
 	/* In the following assertion we test that two records of maximum
@@ -765,10 +773,10 @@
 	page_t*	root;
 	mtr_t	mtr;
 
-leaf_loop:	
+leaf_loop:
 	mtr_start(&mtr);
-	
-	root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);	
+
+	root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);
 
 	/* NOTE: page hash indexes are dropped when a page is freed inside
 	fsp0fsp. */
@@ -783,8 +791,8 @@
 	}
 top_loop:
 	mtr_start(&mtr);
-	
-	root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);	
+
+	root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);
 
 	finished = fseg_free_step_not_header(
 				root + PAGE_HEADER + PAGE_BTR_SEG_TOP, &mtr);
@@ -793,7 +801,7 @@
 	if (!finished) {
 
 		goto top_loop;
-	}	
+	}
 }
 
 /****************************************************************
@@ -812,14 +820,14 @@
 
 	root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
 
-	btr_search_drop_page_hash_index(root);	
-top_loop:	
+	btr_search_drop_page_hash_index(root);
+top_loop:
 	finished = fseg_free_step(
 				root + PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
 	if (!finished) {
 
 		goto top_loop;
-	}	
+	}
 }
 
 /*****************************************************************
@@ -845,8 +853,8 @@
 	ulint	max_ins_size2;
 
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
-	ut_ad(!!page_is_comp(page) == index->table->comp);
+							MTR_MEMO_PAGE_X_FIX));
+	ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
 	data_size1 = page_get_data_size(page);
 	max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
 
@@ -872,7 +880,7 @@
 
 	page_create(page, mtr, page_is_comp(page));
 	buf_block_align(page)->check_index_page_at_flush = TRUE;
-	
+
 	/* Copy the records from the temporary space to the recreated page;
 	do not copy the lock bits yet */
 
@@ -880,7 +888,7 @@
 				page_get_infimum_rec(new_page), index, mtr);
 	/* Copy max trx id to recreated page */
 	page_set_max_trx_id(page, page_get_max_trx_id(new_page));
-	
+
 	if (!recovery) {
 		/* Update the record lock bitmaps */
 		lock_move_reorganize_page(page, new_page);
@@ -892,7 +900,7 @@
 	if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) {
 		buf_page_print(page);
 		buf_page_print(new_page);
-	        fprintf(stderr,
+		fprintf(stderr,
 "InnoDB: Error: page old data size %lu new data size %lu\n"
 "InnoDB: Error: page old max ins size %lu new max ins size %lu\n"
 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n",
@@ -955,7 +963,7 @@
 	mtr_t*	mtr)	/* in: mtr */
 {
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	btr_search_drop_page_hash_index(page);
 
 	/* Recreate the page: note that global data on page (possible
@@ -990,10 +998,10 @@
 	rec_t*		rec;
 	mem_heap_t*	heap;
 	dtuple_t*	node_ptr;
-	ulint		level;	
+	ulint		level;
 	rec_t*		node_ptr_rec;
 	page_cur_t*	page_cursor;
-	
+
 	root = btr_cur_get_page(cursor);
 	tree = btr_cur_get_tree(cursor);
 
@@ -1001,24 +1009,24 @@
 	ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
 							MTR_MEMO_X_LOCK));
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(root),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	btr_search_drop_page_hash_index(root);
 
 	/* Allocate a new page to the tree. Root splitting is done by first
 	moving the root records to the new page, emptying the root, putting
 	a node pointer to the new page, and then splitting the new page. */
-	
+
 	new_page = btr_page_alloc(tree, 0, FSP_NO_DIR,
 				  btr_page_get_level(root, mtr), mtr);
 
 	btr_page_create(new_page, tree, mtr);
 
 	level = btr_page_get_level(root, mtr);
-	
+
 	/* Set the levels of the new index page and root page */
 	btr_page_set_level(new_page, level, mtr);
 	btr_page_set_level(root, level + 1, mtr);
-	
+
 	/* Set the next node and previous node fields of new page */
 	btr_page_set_next(new_page, FIL_NULL, mtr);
 	btr_page_set_prev(new_page, FIL_NULL, mtr);
@@ -1031,7 +1039,7 @@
 	perform a pessimistic update then we have stored the lock
 	information of the record to be inserted on the infimum of the
 	root page: we cannot discard the lock structs on the root page */
-	
+
 	lock_update_root_raise(new_page, root);
 
 	/* Create a memory heap where the node pointer is stored */
@@ -1039,17 +1047,17 @@
 
 	rec = page_rec_get_next(page_get_infimum_rec(new_page));
 	new_page_no = buf_frame_get_page_no(new_page);
-	
+
 	/* Build the node pointer (= node key and page address) for the
 	child */
 
 	node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap,
-					                          level);
+								  level);
 	/* Reorganize the root to get free space */
 	btr_page_reorganize(root, cursor->index, mtr);
 
 	page_cursor = btr_cur_get_page_cur(cursor);
-	
+
 	/* Insert node pointer to the root */
 
 	page_cur_set_before_first(root, page_cursor);
@@ -1064,7 +1072,7 @@
 	node of a level: */
 
 	btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr);
-		
+
 	/* Free the memory heap */
 	mem_heap_free(heap);
 
@@ -1073,15 +1081,14 @@
 /*	fprintf(stderr, "Root raise new page no %lu\n",
 					buf_frame_get_page_no(new_page)); */
 
-	ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
-								new_page);
+	ibuf_reset_free_bits(tree->tree_index, new_page);
 	/* Reposition the cursor to the child node */
 	page_cur_search(new_page, cursor->index, tuple,
 				PAGE_CUR_LE, page_cursor);
-	
+
 	/* Split the child and insert tuple */
 	return(btr_page_split_and_insert(cursor, tuple, mtr));
-}	
+}
 
 /*****************************************************************
 Decides if the page should be split at the convergence point of inserts
@@ -1105,22 +1112,22 @@
 	insert_point = btr_cur_get_rec(cursor);
 
 	if (page_header_get_ptr(page, PAGE_LAST_INSERT)
-	    == page_rec_get_next(insert_point)) {
+		== page_rec_get_next(insert_point)) {
+
+		infimum = page_get_infimum_rec(page);
 
-	     	infimum = page_get_infimum_rec(page);
-		
 		/* If the convergence is in the middle of a page, include also
 		the record immediately before the new insert to the upper
 		page. Otherwise, we could repeatedly move from page to page
 		lots of records smaller than the convergence point. */
 
 		if (infimum != insert_point
-		    && page_rec_get_next(infimum) != insert_point) {
+			&& page_rec_get_next(infimum) != insert_point) {
 
 			*split_rec = insert_point;
 		} else {
-	     		*split_rec = page_rec_get_next(insert_point);
-	     	}
+			*split_rec = page_rec_get_next(insert_point);
+		}
 
 		return(TRUE);
 	}
@@ -1162,7 +1169,7 @@
 		if (page_rec_is_supremum(next_rec)) {
 split_at_new:
 			/* Split at the new record to insert */
-	     		*split_rec = NULL;
+			*split_rec = NULL;
 		} else {
 			rec_t*	next_next_rec = page_rec_get_next(next_rec);
 			if (page_rec_is_supremum(next_next_rec)) {
@@ -1176,7 +1183,7 @@
 			index, as they can do the necessary checks of the right
 			search position just by looking at the records on this
 			page. */
-		
+
 			*split_rec = next_next_rec;
 		}
 
@@ -1199,7 +1206,7 @@
 					upper half-page */
 	btr_cur_t*	cursor,		/* in: cursor at which insert
 					should be made */
-	dtuple_t*	tuple)		/* in: tuple to insert */	
+	dtuple_t*	tuple)		/* in: tuple to insert */
 {
 	page_t*	page;
 	ulint	insert_size;
@@ -1216,7 +1223,7 @@
 	ulint*	offsets;
 
 	page = btr_cur_get_page(cursor);
-	
+
 	insert_size = rec_get_converted_size(cursor->index, tuple);
 	free_space  = page_get_free_space_of_empty(page_is_comp(page));
 
@@ -1263,15 +1270,15 @@
 		}
 
 		n++;
-		
+
 		if (incl_data + page_dir_calc_reserved_space(n)
-                    >= total_space / 2) {
+			>= total_space / 2) {
 
-                    	if (incl_data + page_dir_calc_reserved_space(n)
-                    	    <= free_space) {
-                    	    	/* The next record will be the first on
-                    	    	the right half page if it is not the
-                    	    	supremum record of page */
+			if (incl_data + page_dir_calc_reserved_space(n)
+				<= free_space) {
+				/* The next record will be the first on
+				the right half page if it is not the
+				supremum record of page */
 
 				if (rec == ins_rec) {
 					rec = NULL;
@@ -1286,7 +1293,7 @@
 				if (!page_rec_is_supremum(next_rec)) {
 					rec = next_rec;
 				}
-                    	}
+			}
 
 func_exit:
 			if (UNIV_LIKELY_NULL(heap)) {
@@ -1295,7 +1302,7 @@
 			return(rec);
 		}
 	}
-}		
+}
 
 /*****************************************************************
 Returns TRUE if the insert fits on the appropriate half-page with the
@@ -1323,7 +1330,7 @@
 	rec_t*	rec;
 	rec_t*	end_rec;
 	ulint*	offs;
-	
+
 	page = btr_cur_get_page(cursor);
 
 	ut_ad(!split_rec == !offsets);
@@ -1339,11 +1346,11 @@
 
 	total_data   = page_get_data_size(page) + insert_size;
 	total_n_recs = page_get_n_recs(page) + 1;
-	
+
 	/* We determine which records (from rec to end_rec, not including
 	end_rec) will end up on the other half page from tuple when it is
 	inserted. */
-	
+
 	if (split_rec == NULL) {
 		rec = page_rec_get_next(page_get_infimum_rec(page));
 		end_rec = page_rec_get_next(btr_cur_get_rec(cursor));
@@ -1351,14 +1358,14 @@
 	} else if (cmp_dtuple_rec(tuple, split_rec, offsets) >= 0) {
 
 		rec = page_rec_get_next(page_get_infimum_rec(page));
- 		end_rec = split_rec;
+		end_rec = split_rec;
 	} else {
 		rec = split_rec;
 		end_rec = page_get_supremum_rec(page);
 	}
 
 	if (total_data + page_dir_calc_reserved_space(total_n_recs)
-	    <= free_space) {
+		<= free_space) {
 
 		/* Ok, there will be enough available space on the
 		half page where the tuple is inserted */
@@ -1379,7 +1386,7 @@
 		total_n_recs--;
 
 		if (total_data + page_dir_calc_reserved_space(total_n_recs)
-                    <= free_space) {
+			<= free_space) {
 
 			/* Ok, there will be enough available space on the
 			half page where the tuple is inserted */
@@ -1391,7 +1398,7 @@
 	}
 
 	return(FALSE);
-}		
+}
 
 /***********************************************************
 Inserts a data tuple to a tree on a non-leaf level. It is assumed
@@ -1406,25 +1413,22 @@
 	mtr_t*		mtr)	/* in: mtr */
 {
 	big_rec_t*	dummy_big_rec;
-	btr_cur_t	cursor;		
+	btr_cur_t	cursor;
 	ulint		err;
 	rec_t*		rec;
 
 	ut_ad(level > 0);
-	
+
 	/* In the following, choose just any index from the tree as the
 	first parameter for btr_cur_search_to_nth_level. */
 
-	btr_cur_search_to_nth_level(UT_LIST_GET_FIRST(tree->tree_indexes),
-				    level, tuple, PAGE_CUR_LE,
-				    BTR_CONT_MODIFY_TREE,
-				    &cursor, 0, mtr);
+	btr_cur_search_to_nth_level(tree->tree_index,
+		level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE,
+		&cursor, 0, mtr);
 
 	err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
-					| BTR_KEEP_SYS_FLAG
-					| BTR_NO_UNDO_LOG_FLAG,
-					&cursor, tuple,
-					&rec, &dummy_big_rec, NULL, mtr);
+		| BTR_KEEP_SYS_FLAG | BTR_NO_UNDO_LOG_FLAG,
+		&cursor, tuple, &rec, &dummy_big_rec, NULL, mtr);
 	ut_a(err == DB_SUCCESS);
 }
 
@@ -1455,12 +1459,12 @@
 	ulint		lower_page_no;
 	ulint		upper_page_no;
 	dtuple_t*	node_ptr_upper;
-	mem_heap_t* 	heap;
+	mem_heap_t*	heap;
 
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(new_page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	ut_a(page_is_comp(page) == page_is_comp(new_page));
 
 	/* Create a memory heap where the data tuple is stored */
@@ -1477,12 +1481,12 @@
 		/* Look from the tree for the node pointer to page */
 		node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
 
-		/* Replace the address of the old child node (= page) with the 
+		/* Replace the address of the old child node (= page) with the
 		address of the new lower half */
 
 		btr_node_ptr_set_child_page_no(node_ptr,
 			rec_get_offsets(node_ptr,
-					UT_LIST_GET_FIRST(tree->tree_indexes),
+					tree->tree_index,
 					NULL, ULINT_UNDEFINED, &heap),
 			lower_page_no, mtr);
 		mem_heap_empty(heap);
@@ -1492,7 +1496,7 @@
 		lower_page = page;
 		upper_page = new_page;
 	}
-				   
+
 	/* Get the level of the split pages */
 	level = btr_page_get_level(page, mtr);
 
@@ -1500,13 +1504,13 @@
 	half */
 
 	node_ptr_upper = dict_tree_build_node_ptr(tree, split_rec,
-					     upper_page_no, heap, level);
+		upper_page_no, heap, level);
 
 	/* Insert it next to the pointer to the lower half. Note that this
 	may generate recursion leading to a split on the higher level. */
 
 	btr_insert_on_non_leaf_level(tree, level + 1, node_ptr_upper, mtr);
-		
+
 	/* Free the memory heap */
 	mem_heap_free(heap);
 
@@ -1515,13 +1519,17 @@
 	prev_page_no = btr_page_get_prev(page, mtr);
 	next_page_no = btr_page_get_next(page, mtr);
 	space = buf_frame_get_space_id(page);
-	
+
 	/* Update page links of the level */
-	
+
 	if (prev_page_no != FIL_NULL) {
 
 		prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
 		ut_a(page_is_comp(prev_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_next(prev_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 
 		btr_page_set_next(prev_page, lower_page_no, mtr);
 	}
@@ -1533,7 +1541,7 @@
 
 		btr_page_set_prev(next_page, upper_page_no, mtr);
 	}
-	
+
 	btr_page_set_prev(lower_page, prev_page_no, mtr);
 	btr_page_set_next(lower_page, upper_page_no, mtr);
 	btr_page_set_level(lower_page, level, mtr);
@@ -1590,7 +1598,7 @@
 	mem_heap_empty(heap);
 	offsets = NULL;
 	tree = btr_cur_get_tree(cursor);
-	
+
 	ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
 							MTR_MEMO_X_LOCK));
 #ifdef UNIV_SYNC_DEBUG
@@ -1600,9 +1608,9 @@
 	page = btr_cur_get_page(cursor);
 
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	ut_ad(page_get_n_recs(page) >= 2);
-	
+
 	page_no = buf_frame_get_page_no(page);
 
 	/* 1. Decide the split record; split_rec == NULL means that the
@@ -1613,7 +1621,7 @@
 		direction = FSP_UP;
 		hint_page_no = page_no + 1;
 		split_rec = btr_page_get_sure_split_rec(cursor, tuple);
-		
+
 	} else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) {
 		direction = FSP_UP;
 		hint_page_no = page_no + 1;
@@ -1631,7 +1639,7 @@
 	new_page = btr_page_alloc(tree, hint_page_no, direction,
 					btr_page_get_level(page, mtr), mtr);
 	btr_page_create(new_page, tree, mtr);
-	
+
 	/* 3. Calculate the first record on the upper half-page, and the
 	first record (move_limit) on original page which ends up on the
 	upper half */
@@ -1646,7 +1654,7 @@
 							cursor->index, tuple);
 		move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
 	}
-	
+
 	/* 4. Do first the modifications in the tree structure */
 
 	btr_attach_half_pages(tree, page, first_rec, new_page, direction, mtr);
@@ -1670,7 +1678,7 @@
 		insert_will_fit = btr_page_insert_fits(cursor,
 					NULL, NULL, tuple, heap);
 	}
-	
+
 	if (insert_will_fit && (btr_page_get_level(page, mtr) == 0)) {
 
 		mtr_memo_release(mtr, dict_tree_get_lock(tree),
@@ -1737,7 +1745,7 @@
 		mem_heap_free(heap);
 		return(rec);
 	}
-	
+
 	/* 8. If insert did not fit, try page reorganization */
 
 	btr_page_reorganize(insert_page, cursor->index, mtr);
@@ -1749,7 +1757,7 @@
 	if (rec == NULL) {
 		/* The insert did not fit on the page: loop back to the
 		start of the function for a new split */
-		
+
 		/* We play safe and reset the free bits for new_page */
 		ibuf_reset_free_bits(cursor->index, new_page);
 
@@ -1771,8 +1779,8 @@
 				buf_frame_get_page_no(left_page),
 				buf_frame_get_page_no(right_page)); */
 
-	ut_ad(page_validate(left_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
-	ut_ad(page_validate(right_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
+	ut_ad(page_validate(left_page, tree->tree_index));
+	ut_ad(page_validate(right_page, tree->tree_index));
 
 	mem_heap_free(heap);
 	return(rec);
@@ -1787,28 +1795,32 @@
 	dict_tree_t*	tree __attribute__((unused)), /* in: index tree */
 	page_t*		page,	/* in: page to remove */
 	mtr_t*		mtr)	/* in: mtr */
-{	
+{
 	ulint	space;
 	ulint	prev_page_no;
 	page_t*	prev_page;
 	ulint	next_page_no;
 	page_t*	next_page;
-	
+
 	ut_ad(tree && page && mtr);
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	/* Get the previous and next page numbers of page */
 
 	prev_page_no = btr_page_get_prev(page, mtr);
 	next_page_no = btr_page_get_next(page, mtr);
 	space = buf_frame_get_space_id(page);
-	
+
 	/* Update page links of the level */
-	
+
 	if (prev_page_no != FIL_NULL) {
 
 		prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
 		ut_a(page_is_comp(prev_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_next(prev_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 
 		btr_page_set_next(prev_page, next_page_no, mtr);
 	}
@@ -1817,11 +1829,15 @@
 
 		next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr);
 		ut_a(page_is_comp(next_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_prev(next_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 
 		btr_page_set_prev(next_page, prev_page_no, mtr);
 	}
 }
-	
+
 /********************************************************************
 Writes the redo log record for setting an index record as the predefined
 minimum record. */
@@ -1906,15 +1922,14 @@
 	btr_cur_t	cursor;
 	ibool		compressed;
 	ulint		err;
-	
+
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
 							MTR_MEMO_PAGE_X_FIX));
 	/* Delete node pointer on father page */
 
 	node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
 
-	btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
-								&cursor);
+	btr_cur_position(tree->tree_index, node_ptr, &cursor);
 	compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, FALSE,
 									mtr);
 	ut_a(err == DB_SUCCESS);
@@ -1945,33 +1960,33 @@
 	ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL);
 	ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
-			      				MTR_MEMO_PAGE_X_FIX));
+							MTR_MEMO_PAGE_X_FIX));
 	father_page = buf_frame_align(
 			btr_page_get_father_node_ptr(tree, page, mtr));
-	
+
 	page_level = btr_page_get_level(page, mtr);
-	index = UT_LIST_GET_FIRST(tree->tree_indexes);
+	index = tree->tree_index;
 
 	btr_search_drop_page_hash_index(page);
-	
+
 	/* Make the father empty */
 	btr_page_empty(father_page, mtr);
 
 	/* Move records to the father */
- 	page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page),
+	page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page),
 								index, mtr);
 	lock_update_copy_and_discard(father_page, page);
 
 	btr_page_set_level(father_page, page_level, mtr);
 
 	/* Free the file page */
-	btr_page_free(tree, page, mtr);		
+	btr_page_free(tree, page, mtr);
 
 	/* We play safe and reset the free bits for the father */
 	ibuf_reset_free_bits(index, father_page);
 	ut_ad(page_validate(father_page, index));
 	ut_ad(btr_check_node_ptr(tree, father_page, mtr));
-}	
+}
 
 /*****************************************************************
 Tries to merge the page first to the left immediate brother if such a
@@ -2014,7 +2029,7 @@
 	page = btr_cur_get_page(cursor);
 	tree = btr_cur_get_tree(cursor);
 	comp = page_is_comp(page);
-	ut_a((ibool)!!comp == cursor->index->table->comp);
+	ut_a((ibool)!!comp == dict_table_is_comp(cursor->index->table));
 
 	ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
 							MTR_MEMO_X_LOCK));
@@ -2037,16 +2052,24 @@
 	/* Decide the page to which we try to merge and which will inherit
 	the locks */
 
-	if (left_page_no != FIL_NULL) {
+	is_left = left_page_no != FIL_NULL;
+
+	if (is_left) {
 
-		is_left = TRUE;
 		merge_page = btr_page_get(space, left_page_no, RW_X_LATCH,
 									mtr);
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_next(merge_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 	} else if (right_page_no != FIL_NULL) {
 
-		is_left = FALSE;
 		merge_page = btr_page_get(space, right_page_no, RW_X_LATCH,
 									mtr);
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_prev(merge_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 	} else {
 		/* The page is the only one on the level, lift the records
 		to the father */
@@ -2054,7 +2077,7 @@
 
 		return;
 	}
-	
+
 	n_recs = page_get_n_recs(page);
 	data_size = page_get_data_size(page);
 	ut_a(page_is_comp(merge_page) == comp);
@@ -2071,7 +2094,7 @@
 	ut_ad(page_validate(merge_page, cursor->index));
 
 	max_ins_size = page_get_max_insert_size(merge_page, n_recs);
-	
+
 	if (data_size > max_ins_size) {
 
 		/* We have to reorganize merge_page */
@@ -2103,7 +2126,7 @@
 		mem_heap_t*	heap		= NULL;
 		ulint		offsets_[REC_OFFS_NORMAL_SIZE];
 		*offsets_ = (sizeof offsets_) / sizeof *offsets_;
-		/* Replace the address of the old child node (= page) with the 
+		/* Replace the address of the old child node (= page) with the
 		address of the merge page to the right */
 
 		btr_node_ptr_set_child_page_no(node_ptr,
@@ -2115,7 +2138,7 @@
 		}
 		btr_node_ptr_delete(tree, merge_page, mtr);
 	}
-	
+
 	/* Move records to the merge page */
 	if (is_left) {
 		orig_pred = page_rec_get_prev(
@@ -2136,14 +2159,14 @@
 	/* We have added new records to merge_page: update its free bits */
 	ibuf_update_free_bits_if_full(cursor->index, merge_page,
 					UNIV_PAGE_SIZE, ULINT_UNDEFINED);
-					
+
 	ut_ad(page_validate(merge_page, cursor->index));
 
 	/* Free the file page */
-	btr_page_free(tree, page, mtr);		
+	btr_page_free(tree, page, mtr);
 
 	ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
-}	
+}
 
 /*****************************************************************
 Discards a page that is the only page on its level. */
@@ -2158,7 +2181,7 @@
 	rec_t*	node_ptr;
 	page_t*	father_page;
 	ulint	page_level;
-	
+
 	ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL);
 	ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
@@ -2175,7 +2198,7 @@
 	btr_page_set_level(father_page, page_level, mtr);
 
 	/* Free the file page */
-	btr_page_free(tree, page, mtr);		
+	btr_page_free(tree, page, mtr);
 
 	if (buf_frame_get_page_no(father_page) == dict_tree_get_page(tree)) {
 		/* The father is the root page */
@@ -2183,14 +2206,13 @@
 		btr_page_empty(father_page, mtr);
 
 		/* We play safe and reset the free bits for the father */
-		ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
-								father_page);
+		ibuf_reset_free_bits(tree->tree_index, father_page);
 	} else {
 		ut_ad(page_get_n_recs(father_page) == 1);
 
 		btr_discard_only_page_on_level(tree, father_page, mtr);
 	}
-}	
+}
 
 /*****************************************************************
 Discards a page from a B-tree. This is used to remove the last record from
@@ -2209,10 +2231,9 @@
 	ulint		left_page_no;
 	ulint		right_page_no;
 	page_t*		merge_page;
-	ibool		is_left;
 	page_t*		page;
 	rec_t*		node_ptr;
-	
+
 	page = btr_cur_get_page(cursor);
 	tree = btr_cur_get_tree(cursor);
 
@@ -2222,20 +2243,26 @@
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
 							MTR_MEMO_PAGE_X_FIX));
 	space = dict_tree_get_space(tree);
-	
+
 	/* Decide the page which will inherit the locks */
 
 	left_page_no = btr_page_get_prev(page, mtr);
 	right_page_no = btr_page_get_next(page, mtr);
 
 	if (left_page_no != FIL_NULL) {
-		is_left = TRUE;
 		merge_page = btr_page_get(space, left_page_no, RW_X_LATCH,
 									mtr);
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_next(merge_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 	} else if (right_page_no != FIL_NULL) {
-		is_left = FALSE;
 		merge_page = btr_page_get(space, right_page_no, RW_X_LATCH,
 									mtr);
+#ifdef UNIV_BTR_DEBUG
+		ut_a(btr_page_get_prev(merge_page, mtr)
+				== buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
 	} else {
 		btr_discard_only_page_on_level(tree, page, mtr);
 
@@ -2244,7 +2271,7 @@
 
 	ut_a(page_is_comp(merge_page) == page_is_comp(page));
 	btr_search_drop_page_hash_index(page);
-	
+
 	if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) {
 
 		/* We have to mark the leftmost node pointer on the right
@@ -2255,25 +2282,25 @@
 		ut_ad(page_rec_is_user_rec(node_ptr));
 
 		btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr);
-	}	
-	
+	}
+
 	btr_node_ptr_delete(tree, page, mtr);
 
 	/* Remove the page from the level list */
 	btr_level_list_remove(tree, page, mtr);
 
-	if (is_left) {
+	if (left_page_no != FIL_NULL) {
 		lock_update_discard(page_get_supremum_rec(merge_page), page);
 	} else {
 		lock_update_discard(page_rec_get_next(
-				    page_get_infimum_rec(merge_page)), page);
+				page_get_infimum_rec(merge_page)), page);
 	}
 
 	/* Free the file page */
-	btr_page_free(tree, page, mtr);		
+	btr_page_free(tree, page, mtr);
 
 	ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
-}	
+}
 
 #ifdef UNIV_BTR_PRINT
 /*****************************************************************
@@ -2297,7 +2324,7 @@
 	}
 
 	mtr_start(&mtr);
-	
+
 	root = btr_root_get(tree, &mtr);
 
 	seg = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
@@ -2313,7 +2340,7 @@
 		fseg_print(seg, &mtr);
 	}
 
-	mtr_commit(&mtr); 	
+	mtr_commit(&mtr);
 }
 
 /****************************************************************
@@ -2341,14 +2368,14 @@
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
 							MTR_MEMO_PAGE_X_FIX));
 	fprintf(stderr, "NODE ON LEVEL %lu page number %lu\n",
-	       (ulong) btr_page_get_level(page, mtr),
-	       (ulong) buf_frame_get_page_no(page));
-	
+		(ulong) btr_page_get_level(page, mtr),
+		(ulong) buf_frame_get_page_no(page));
+
 	index = UT_LIST_GET_FIRST(tree->tree_indexes);
 	page_print(page, index, width, width);
-	
+
 	n_recs = page_get_n_recs(page);
-	
+
 	page_cur_set_before_first(page, &cursor);
 	page_cur_move_to_next(&cursor);
 
@@ -2413,6 +2440,7 @@
 }
 #endif /* UNIV_BTR_PRINT */
 
+#ifdef UNIV_DEBUG
 /****************************************************************
 Checks that the node pointer to a page is appropriate. */
 
@@ -2436,28 +2464,29 @@
 	}
 
 	node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
- 
+
 	if (btr_page_get_level(page, mtr) == 0) {
 
 		return(TRUE);
 	}
-	
+
 	heap = mem_heap_create(256);
-		
+
 	node_ptr_tuple = dict_tree_build_node_ptr(
 				tree,
 				page_rec_get_next(page_get_infimum_rec(page)),
 				0, heap, btr_page_get_level(page, mtr));
-				
+
 	ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr,
 			rec_get_offsets(node_ptr,
-			dict_tree_find_index(tree, node_ptr),
+			tree->tree_index,
 			NULL, ULINT_UNDEFINED, &heap)) == 0);
 
 	mem_heap_free(heap);
 
 	return(TRUE);
 }
+#endif /* UNIV_DEBUG */
 
 /****************************************************************
 Display identification information for a record. */
@@ -2481,7 +2510,7 @@
 
 ibool
 btr_index_rec_validate(
-/*====================*/
+/*===================*/
 					/* out: TRUE if ok */
 	rec_t*		rec,		/* in: index record */
 	dict_index_t*	index,		/* in: index */
@@ -2501,18 +2530,20 @@
 	page = buf_frame_align(rec);
 
 	if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
-	        /* The insert buffer index tree can contain records from any
-	        other index: we cannot check the number of fields or
-	        their length */
+		/* The insert buffer index tree can contain records from any
+		other index: we cannot check the number of fields or
+		their length */
 
-	        return(TRUE);
+		return(TRUE);
 	}
 
-	if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) != index->table->comp)) {
+	if (UNIV_UNLIKELY((ibool)!!page_is_comp(page)
+			!= dict_table_is_comp(index->table))) {
 		btr_index_rec_validate_report(page, rec, index);
 		fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n",
 			(ulong) !!page_is_comp(page),
-			(ulong) index->table->comp);
+			(ulong) dict_table_is_comp(index->table));
+
 		return(FALSE);
 	}
 
@@ -2546,12 +2577,12 @@
 		their type is CHAR. */
 
 		if ((dict_index_get_nth_field(index, i)->prefix_len == 0
-		    && len != UNIV_SQL_NULL && fixed_size
-		    && len != fixed_size)
+				&& len != UNIV_SQL_NULL && fixed_size
+				&& len != fixed_size)
 		   ||
 		   (dict_index_get_nth_field(index, i)->prefix_len > 0
-		    && len != UNIV_SQL_NULL
-		    && len >
+			   && len != UNIV_SQL_NULL
+			   && len >
 			   dict_index_get_nth_field(index, i)->prefix_len)) {
 
 			btr_index_rec_validate_report(page, rec, index);
@@ -2576,7 +2607,7 @@
 	if (UNIV_LIKELY_NULL(heap)) {
 		mem_heap_free(heap);
 	}
-	return(TRUE);			
+	return(TRUE);
 }
 
 /****************************************************************
@@ -2590,9 +2621,9 @@
 	page_t*		page,	/* in: index page */
 	dict_index_t*	index)	/* in: index */
 {
-	page_cur_t 	cur;
+	page_cur_t	cur;
 	ibool		ret	= TRUE;
-	
+
 	page_cur_set_before_first(page, &cur);
 	page_cur_move_to_next(&cur);
 
@@ -2610,7 +2641,7 @@
 		page_cur_move_to_next(&cur);
 	}
 
-	return(ret);	
+	return(ret);
 }
 
 /****************************************************************
@@ -2686,12 +2717,12 @@
 	mtr_start(&mtr);
 
 	mtr_x_lock(dict_tree_get_lock(tree), &mtr);
-	
+
 	page = btr_root_get(tree, &mtr);
 
 	space = buf_frame_get_space_id(page);
 
-	index = UT_LIST_GET_FIRST(tree->tree_indexes);
+	index = tree->tree_index;
 
 	while (level != btr_page_get_level(page, &mtr)) {
 
@@ -2733,21 +2764,43 @@
 			ret = FALSE;
 		}
 	}
-	
+
 	ut_a(btr_page_get_level(page, &mtr) == level);
 
 	right_page_no = btr_page_get_next(page, &mtr);
 	left_page_no = btr_page_get_prev(page, &mtr);
 
 	ut_a((page_get_n_recs(page) > 0)
-	     || ((level == 0) &&
+		|| ((level == 0) &&
 		  (buf_frame_get_page_no(page) == dict_tree_get_page(tree))));
 
 	if (right_page_no != FIL_NULL) {
 		rec_t*	right_rec;
 		right_page = btr_page_get(space, right_page_no, RW_X_LATCH,
 									&mtr);
-		ut_a(page_is_comp(right_page) == page_is_comp(page));
+		if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
+				!= buf_frame_get_page_no(page))) {
+			btr_validate_report2(index, level, page, right_page);
+			fputs("InnoDB: broken FIL_PAGE_NEXT"
+				" or FIL_PAGE_PREV links\n", stderr);
+			buf_page_print(page);
+			buf_page_print(right_page);
+
+			ret = FALSE;
+		}
+
+		if (UNIV_UNLIKELY(page_is_comp(right_page)
+				!= page_is_comp(page))) {
+			btr_validate_report2(index, level, page, right_page);
+			fputs("InnoDB: 'compact' flag mismatch\n", stderr);
+			buf_page_print(page);
+			buf_page_print(right_page);
+
+			ret = FALSE;
+
+			goto node_ptr_fails;
+		}
+
 		rec = page_rec_get_prev(page_get_supremum_rec(page));
 		right_rec = page_rec_get_next(
 					page_get_infimum_rec(right_page));
@@ -2755,8 +2808,8 @@
 					offsets, ULINT_UNDEFINED, &heap);
 		offsets2 = rec_get_offsets(right_rec, index,
 					offsets2, ULINT_UNDEFINED, &heap);
-		if (cmp_rec_rec(rec, right_rec, offsets, offsets2, index)
-				>= 0) {
+		if (UNIV_UNLIKELY(cmp_rec_rec(rec, right_rec,
+				offsets, offsets2, index) >= 0)) {
 
 			btr_validate_report2(index, level, page, right_page);
 
@@ -2776,10 +2829,10 @@
 			rec_print(stderr, rec, index);
 			putc('\n', stderr);
 
-	  		ret = FALSE;
-	  	}
+			ret = FALSE;
+		}
 	}
-	
+
 	if (level > 0 && left_page_no == FIL_NULL) {
 		ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
 			page_rec_get_next(page_get_infimum_rec(page)),
@@ -2789,7 +2842,7 @@
 	if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) {
 
 		/* Check father node pointers */
-	
+
 		node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr);
 		father_page = buf_frame_align(node_ptr);
 		offsets	= rec_get_offsets(node_ptr, index,
@@ -2822,25 +2875,25 @@
 				&mtr);
 			rec_print(stderr, rec, index);
 			putc('\n', stderr);
-		   	ret = FALSE;
+			ret = FALSE;
 
-		   	goto node_ptr_fails;
+			goto node_ptr_fails;
 		}
 
 		if (btr_page_get_level(page, &mtr) > 0) {
 			offsets	= rec_get_offsets(node_ptr, index,
 					offsets, ULINT_UNDEFINED, &heap);
-		
+
 			node_ptr_tuple = dict_tree_build_node_ptr(
 					tree,
 					page_rec_get_next(
 						page_get_infimum_rec(page)),
 						0, heap,
-       					btr_page_get_level(page, &mtr));
+					btr_page_get_level(page, &mtr));
 
 			if (cmp_dtuple_rec(node_ptr_tuple, node_ptr,
 								offsets)) {
-			  	rec_t*	first_rec	= page_rec_get_next(
+				rec_t*	first_rec	= page_rec_get_next(
 					page_get_infimum_rec(page));
 
 				btr_validate_report1(index, level, page);
@@ -2855,9 +2908,9 @@
 				fputs("InnoDB: first rec ", stderr);
 				rec_print(stderr, first_rec, index);
 				putc('\n', stderr);
-		   		ret = FALSE;
+				ret = FALSE;
 
-		   		goto node_ptr_fails;
+				goto node_ptr_fails;
 			}
 		}
 
@@ -2871,10 +2924,7 @@
 			ut_a(node_ptr == page_rec_get_prev(
 				page_get_supremum_rec(father_page)));
 			ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL);
-		}
-
-		if (right_page_no != FIL_NULL) {
-
+		} else {
 			right_node_ptr = btr_page_get_father_node_ptr(tree,
 							right_page, &mtr);
 			if (page_rec_get_next(node_ptr) !=
@@ -2897,9 +2947,9 @@
 			} else {
 				right_father_page = buf_frame_align(
 							right_node_ptr);
-							
+
 				if (right_node_ptr != page_rec_get_next(
-					   		page_get_infimum_rec(
+							page_get_infimum_rec(
 							right_father_page))) {
 					ret = FALSE;
 					fputs(
@@ -2931,19 +2981,20 @@
 					buf_page_print(page);
 					buf_page_print(right_page);
 				}
-			}					
+			}
 		}
 	}
 
 node_ptr_fails:
+	/* Commit the mini-transaction to release the latch on 'page'.
+	Re-acquire the latch on right_page, which will become 'page'
+	on the next loop.  The page has already been checked. */
 	mtr_commit(&mtr);
 
 	if (right_page_no != FIL_NULL) {
-		ulint	comp = page_is_comp(page);
 		mtr_start(&mtr);
-	
+
 		page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
-		ut_a(page_is_comp(page) == comp);
 
 		goto loop;
 	}

--- 1.45.6.1/innobase/buf/buf0buf.c	2006-08-29 18:58:59 +04:00
+++ 1.54/storage/innobase/buf/buf0buf.c	2006-08-29 18:58:59 +04:00
@@ -1,14 +1,14 @@
 /*   Innobase relational database engine; Copyright (C) 2001 Innobase Oy
-     
+
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License 2
      as published by the Free Software Foundation in June 1991.
-     
+
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
-     
+
      You should have received a copy of the GNU General Public License 2
      along with this program (in file COPYING); if not, write to the Free
      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
@@ -42,7 +42,7 @@
 		IMPLEMENTATION OF THE BUFFER POOL
 		=================================
 
-Performance improvement: 
+Performance improvement:
 ------------------------
 Thread scheduling in NT may be so slow that the OS wait mechanism should
 not be used even in waiting for disk reads to complete.
@@ -239,33 +239,33 @@
 ulint
 buf_calc_page_new_checksum(
 /*=======================*/
-		       /* out: checksum */
-	byte*    page) /* in: buffer page */
+			/* out: checksum */
+	byte*	 page)	/* in: buffer page */
 {
-  	ulint checksum;
+	ulint checksum;
 
-        /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
-        ..._ARCH_LOG_NO, are written outside the buffer pool to the first
-        pages of data files, we have to skip them in the page checksum
-        calculation.
+	/* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
+	..._ARCH_LOG_NO, are written outside the buffer pool to the first
+	pages of data files, we have to skip them in the page checksum
+	calculation.
 	We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
 	checksum is stored, and also the last 8 bytes of page because
 	there we store the old formula checksum. */
-  	
-  	checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
+
+	checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
 				 FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
-  		   + ut_fold_binary(page + FIL_PAGE_DATA, 
-				           UNIV_PAGE_SIZE - FIL_PAGE_DATA
-				           - FIL_PAGE_END_LSN_OLD_CHKSUM);
-  	checksum = checksum & 0xFFFFFFFFUL;
+		   + ut_fold_binary(page + FIL_PAGE_DATA,
+					   UNIV_PAGE_SIZE - FIL_PAGE_DATA
+					   - FIL_PAGE_END_LSN_OLD_CHKSUM);
+	checksum = checksum & 0xFFFFFFFFUL;
 
-  	return(checksum);
+	return(checksum);
 }
 
 /************************************************************************
 In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
 looked at the first few bytes of the page. This calculates that old
-checksum. 
+checksum.
 NOTE: we must first store the new formula checksum to
 FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
 because this takes that field as an input! */
@@ -273,16 +273,16 @@
 ulint
 buf_calc_page_old_checksum(
 /*=======================*/
-		       /* out: checksum */
-	byte*    page) /* in: buffer page */
+			/* out: checksum */
+	byte*	 page)	/* in: buffer page */
 {
-  	ulint checksum;
-  	
-  	checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
+	ulint checksum;
+
+	checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
 
-  	checksum = checksum & 0xFFFFFFFFUL;
+	checksum = checksum & 0xFFFFFFFFUL;
 
-  	return(checksum);
+	return(checksum);
 }
 
 /************************************************************************
@@ -302,11 +302,11 @@
 	dulint	current_lsn;
 #endif
 	if (mach_read_from_4(read_buf + FIL_PAGE_LSN + 4)
-	     != mach_read_from_4(read_buf + UNIV_PAGE_SIZE
-				- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
+		!= mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+			- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
 
 		/* Stored log sequence numbers at the start and the end
-		of page do not match */
+		   of page do not match */
 
 		return(TRUE);
 	}
@@ -314,8 +314,8 @@
 #ifndef UNIV_HOTBACKUP
 	if (recv_lsn_checks_on && log_peek_lsn(&current_lsn)) {
 		if (ut_dulint_cmp(current_lsn,
-				  mach_read_from_8(read_buf + FIL_PAGE_LSN))
-				 < 0) {
+				mach_read_from_8(read_buf + FIL_PAGE_LSN))
+			< 0) {
 			ut_print_timestamp(stderr);
 
 			fprintf(stderr,
@@ -325,53 +325,58 @@
 "InnoDB: tablespace but not the InnoDB log files. See\n"
 "InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
 "InnoDB: for more information.\n",
-		        (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
-			(ulong) ut_dulint_get_high(
-				mach_read_from_8(read_buf + FIL_PAGE_LSN)),
-			(ulong) ut_dulint_get_low(
-				mach_read_from_8(read_buf + FIL_PAGE_LSN)),
-			(ulong) ut_dulint_get_high(current_lsn),
-			(ulong) ut_dulint_get_low(current_lsn));
+				(ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
+				(ulong) ut_dulint_get_high(
+					mach_read_from_8(read_buf + FIL_PAGE_LSN)),
+				(ulong) ut_dulint_get_low(
+					mach_read_from_8(read_buf + FIL_PAGE_LSN)),
+				(ulong) ut_dulint_get_high(current_lsn),
+				(ulong) ut_dulint_get_low(current_lsn));
 		}
 	}
 #endif
-  
-  /* If we use checksums validation, make additional check before returning
-  TRUE to ensure that the checksum is not equal to BUF_NO_CHECKSUM_MAGIC which
-  might be stored by InnoDB with checksums disabled.
-     Otherwise, skip checksum calculation and return FALSE */
-  
-  if (srv_use_checksums) {
-    old_checksum = buf_calc_page_old_checksum(read_buf); 
-
-    old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE
-					- FIL_PAGE_END_LSN_OLD_CHKSUM);
-
-    /* There are 2 valid formulas for old_checksum_field:
-	  1. Very old versions of InnoDB only stored 8 byte lsn to the start
-	  and the end of the page.
-	  2. Newer InnoDB versions store the old formula checksum there. */
-	
-    if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN)
-        && old_checksum_field != old_checksum
-        && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
-
-      return(TRUE);
-    }
-
-    checksum = buf_calc_page_new_checksum(read_buf);
-    checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
-
-    /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
-	  (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
-
-    if (checksum_field != 0 && checksum_field != checksum
-        && checksum_field != BUF_NO_CHECKSUM_MAGIC) {
-
-      return(TRUE);
-    }
-  }
-  
+
+	/* If we use checksums validation, make additional check before
+	returning TRUE to ensure that the checksum is not equal to
+	BUF_NO_CHECKSUM_MAGIC which might be stored by InnoDB with checksums
+	disabled. Otherwise, skip checksum calculation and return FALSE */
+
+	if (srv_use_checksums) {
+		old_checksum = buf_calc_page_old_checksum(read_buf);
+
+		old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+			- FIL_PAGE_END_LSN_OLD_CHKSUM);
+
+		/* There are 2 valid formulas for old_checksum_field:
+
+		1. Very old versions of InnoDB only stored 8 byte lsn to the
+		start and the end of the page.
+
+		2. Newer InnoDB versions store the old formula checksum
+		there. */
+
+		if (old_checksum_field != mach_read_from_4(read_buf
+				+ FIL_PAGE_LSN)
+			&& old_checksum_field != old_checksum
+			&& old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+			return(TRUE);
+		}
+
+		checksum = buf_calc_page_new_checksum(read_buf);
+		checksum_field = mach_read_from_4(read_buf +
+			FIL_PAGE_SPACE_OR_CHKSUM);
+
+		/* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+		(always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
+
+		if (checksum_field != 0 && checksum_field != checksum
+			&& checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+			return(TRUE);
+		}
+	}
+
 	return(FALSE);
 }
 
@@ -394,12 +399,12 @@
 	fputs("InnoDB: End of page dump\n", stderr);
 
 	checksum = srv_use_checksums ?
-    buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+		buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
 	old_checksum = srv_use_checksums ?
-    buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+		buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
 
 	ut_print_timestamp(stderr);
-	fprintf(stderr, 
+	fprintf(stderr,
 "  InnoDB: Page checksum %lu, prior-to-4.0.14-form checksum %lu\n"
 "InnoDB: stored checksum %lu, prior-to-4.0.14-form stored checksum %lu\n",
 			(ulong) checksum, (ulong) old_checksum,
@@ -418,18 +423,19 @@
 		(ulong) mach_read_from_4(read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
 
 	if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE)
-	    == TRX_UNDO_INSERT) {
-	    	fprintf(stderr,
+		== TRX_UNDO_INSERT) {
+		fprintf(stderr,
 			"InnoDB: Page may be an insert undo log page\n");
 	} else if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR
 						+ TRX_UNDO_PAGE_TYPE)
-	    	== TRX_UNDO_UPDATE) {
-	    	fprintf(stderr,
+		== TRX_UNDO_UPDATE) {
+		fprintf(stderr,
 			"InnoDB: Page may be an update undo log page\n");
 	}
 
-	if (fil_page_get_type(read_buf) == FIL_PAGE_INDEX) {
-	    	fprintf(stderr,
+	switch (fil_page_get_type(read_buf)) {
+	case FIL_PAGE_INDEX:
+		fprintf(stderr,
 "InnoDB: Page may be an index page where index id is %lu %lu\n",
 			(ulong) ut_dulint_get_high(btr_page_get_index_id(read_buf)),
 			(ulong) ut_dulint_get_low(btr_page_get_index_id(read_buf)));
@@ -439,19 +445,50 @@
 
 		if (dict_sys != NULL) {
 
-		        index = dict_index_find_on_id_low(
+			index = dict_index_find_on_id_low(
 					btr_page_get_index_id(read_buf));
-		        if (index) {
+			if (index) {
 				fputs("InnoDB: (", stderr);
 				dict_index_name_print(stderr, NULL, index);
 				fputs(")\n", stderr);
 			}
 		}
-	} else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
+		break;
+	case FIL_PAGE_INODE:
 		fputs("InnoDB: Page may be an 'inode' page\n", stderr);
-	} else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
+		break;
+	case FIL_PAGE_IBUF_FREE_LIST:
 		fputs("InnoDB: Page may be an insert buffer free list page\n",
 			stderr);
+		break;
+	case FIL_PAGE_TYPE_ALLOCATED:
+		fputs("InnoDB: Page may be a freshly allocated page\n",
+			stderr);
+		break;
+	case FIL_PAGE_IBUF_BITMAP:
+		fputs("InnoDB: Page may be an insert buffer bitmap page\n",
+			stderr);
+		break;
+	case FIL_PAGE_TYPE_SYS:
+		fputs("InnoDB: Page may be a system page\n",
+			stderr);
+		break;
+	case FIL_PAGE_TYPE_TRX_SYS:
+		fputs("InnoDB: Page may be a transaction system page\n",
+			stderr);
+		break;
+	case FIL_PAGE_TYPE_FSP_HDR:
+		fputs("InnoDB: Page may be a file space header page\n",
+			stderr);
+		break;
+	case FIL_PAGE_TYPE_XDES:
+		fputs("InnoDB: Page may be an extent descriptor page\n",
+			stderr);
+		break;
+	case FIL_PAGE_TYPE_BLOB:
+		fputs("InnoDB: Page may be a BLOB page\n",
+			stderr);
+		break;
 	}
 }
 
@@ -468,7 +505,7 @@
 	block->magic_n = 0;
 
 	block->state = BUF_BLOCK_NOT_USED;
-	
+
 	block->frame = frame;
 
 	block->awe_info = NULL;
@@ -477,7 +514,7 @@
 	block->io_fix = 0;
 
 	block->modify_clock = ut_dulint_zero;
-	
+
 	block->file_page_was_freed = FALSE;
 
 	block->check_index_page_at_flush = FALSE;
@@ -488,12 +525,11 @@
 
 	block->n_pointers = 0;
 
-	rw_lock_create(&(block->lock));
+	rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
 	ut_ad(rw_lock_validate(&(block->lock)));
 
 #ifdef UNIV_SYNC_DEBUG
-	rw_lock_create(&(block->debug_latch));
-	rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
+	rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
 #endif /* UNIV_SYNC_DEBUG */
 }
 
@@ -519,12 +555,12 @@
 	byte*		frame;
 	ulint		i;
 	buf_block_t*	block;
-	
+
 	ut_a(max_size == curr_size);
 	ut_a(srv_use_awe || n_frames == max_size);
-	
+
 	if (n_frames > curr_size) {
-	        fprintf(stderr,
+		fprintf(stderr,
 "InnoDB: AWE: Error: you must specify in my.cnf .._awe_mem_mb larger\n"
 "InnoDB: than .._buffer_pool_size. Now the former is %lu pages,\n"
 "InnoDB: the latter %lu pages.\n", (ulong) curr_size, (ulong) n_frames);
@@ -536,8 +572,7 @@
 
 	/* 1. Initialize general fields
 	   ---------------------------- */
-	mutex_create(&(buf_pool->mutex));
-	mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL);
+	mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
 
 	mutex_enter(&(buf_pool->mutex));
 
@@ -548,18 +583,18 @@
 
 		buf_pool->frame_mem = os_awe_allocate_virtual_mem_window(
 					UNIV_PAGE_SIZE * (n_frames + 1));
-					
+
 		/* Allocate the physical memory for AWE and the AWE info array
 		for buf_pool */
 
 		if ((curr_size % ((1024 * 1024) / UNIV_PAGE_SIZE)) != 0) {
 
-		        fprintf(stderr,
+			fprintf(stderr,
 "InnoDB: AWE: Error: physical memory must be allocated in full megabytes.\n"
-"InnoDB: Trying to allocate %lu database pages.\n", 
+"InnoDB: Trying to allocate %lu database pages.\n",
 			  (ulong) curr_size);
 
-		        return(NULL);
+			return(NULL);
 		}
 
 		if (!os_awe_allocate_physical_mem(&(buf_pool->awe_info),
@@ -611,7 +646,7 @@
 	}
 
 	buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames);
-	
+
 	if (buf_pool->blocks_of_frames == NULL) {
 
 		return(NULL);
@@ -632,7 +667,7 @@
 		} else {
 			frame = NULL;
 		}
-		
+
 		buf_block_init(block, frame);
 
 		if (srv_use_awe) {
@@ -653,14 +688,14 @@
 	buf_pool->n_pages_written = 0;
 	buf_pool->n_pages_created = 0;
 	buf_pool->n_pages_awe_remapped = 0;
-	
+
 	buf_pool->n_page_gets = 0;
 	buf_pool->n_page_gets_old = 0;
 	buf_pool->n_pages_read_old = 0;
 	buf_pool->n_pages_written_old = 0;
 	buf_pool->n_pages_created_old = 0;
 	buf_pool->n_pages_awe_remapped_old = 0;
-	
+
 	/* 2. Initialize flushing fields
 	   ---------------------------- */
 	UT_LIST_INIT(buf_pool->flush_list);
@@ -675,7 +710,7 @@
 
 	buf_pool->ulint_clock = 1;
 	buf_pool->freed_page_clock = 0;
-	
+
 	/* 3. Initialize LRU fields
 	   ---------------------------- */
 	UT_LIST_INIT(buf_pool->LRU);
@@ -701,7 +736,7 @@
 			if (srv_use_awe) {
 				/* Add to the list of blocks mapped to
 				frames */
-				
+
 				UT_LIST_ADD_LAST(awe_LRU_free_mapped,
 					buf_pool->awe_LRU_free_mapped, block);
 			}
@@ -714,15 +749,15 @@
 	mutex_exit(&(buf_pool->mutex));
 
 	if (srv_use_adaptive_hash_indexes) {
-	  	btr_search_sys_create(
+		btr_search_sys_create(
 			  curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64);
 	} else {
-	        /* Create only a small dummy system */
-	        btr_search_sys_create(1000);
+		/* Create only a small dummy system */
+		btr_search_sys_create(1000);
 	}
 
 	return(buf_pool);
-}	
+}
 
 /************************************************************************
 Maps the page of block to a frame, if not mapped yet. Unmaps some page
@@ -755,9 +790,9 @@
 
 	bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped);
 
-	while (bck) {	
+	while (bck) {
 		if (bck->state == BUF_BLOCK_FILE_PAGE
-	    	    && (bck->buf_fix_count != 0 || bck->io_fix != 0)) {
+			&& (bck->buf_fix_count != 0 || bck->io_fix != 0)) {
 
 			/* We have to skip this */
 			bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck);
@@ -776,7 +811,7 @@
 						- buf_pool->frame_zero))
 						>> UNIV_PAGE_SIZE_SHIFT))
 				= block;
-			
+
 			bck->frame = NULL;
 			UT_LIST_REMOVE(awe_LRU_free_mapped,
 					buf_pool->awe_LRU_free_mapped,
@@ -789,7 +824,7 @@
 			}
 
 			buf_pool->n_pages_awe_remapped++;
-			
+
 			return;
 		}
 	}
@@ -828,7 +863,7 @@
 /*=================*/
 	buf_block_t*	block)	/* in: block to make younger */
 {
-	if (buf_pool->freed_page_clock >= block->freed_page_clock 
+	if (buf_pool->freed_page_clock >= block->freed_page_clock
 				+ 1 + (buf_pool->curr_size / 1024)) {
 
 		/* There has been freeing activity in the LRU list:
@@ -845,11 +880,11 @@
 
 void
 buf_page_make_young(
-/*=================*/
+/*================*/
 	buf_frame_t*	frame)	/* in: buffer frame of a file page */
 {
 	buf_block_t*	block;
-	
+
 	mutex_enter(&(buf_pool->mutex));
 
 	block = buf_block_align(frame);
@@ -899,7 +934,7 @@
 {
 	buf_block_free(buf_block_align(frame));
 }
-	
+
 /************************************************************************
 Returns the buffer control block if the page can be found in the buffer
 pool. NOTE that it is possible that the page is not yet read
@@ -944,7 +979,7 @@
 	if (block) {
 		block->check_index_page_at_flush = FALSE;
 	}
-	
+
 	mutex_exit(&(buf_pool->mutex));
 }
 
@@ -1080,14 +1115,14 @@
 	ulint		fix_type;
 	ibool		success;
 	ibool		must_read;
-	
+
 	ut_ad(mtr);
 	ut_ad((rw_latch == RW_S_LATCH)
-	      || (rw_latch == RW_X_LATCH)
-	      || (rw_latch == RW_NO_LATCH));
+		|| (rw_latch == RW_X_LATCH)
+		|| (rw_latch == RW_NO_LATCH));
 	ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
 	ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
-	      || (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));
+		|| (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));
 #ifndef UNIV_LOG_DEBUG
 	ut_ad(!ibuf_inside() || ibuf_page(space, offset));
 #endif
@@ -1096,7 +1131,7 @@
 	mutex_enter_fast(&(buf_pool->mutex));
 
 	block = NULL;
-	
+
 	if (guess) {
 		block = buf_block_align(guess);
 
@@ -1136,7 +1171,7 @@
 	ut_a(block->state == BUF_BLOCK_FILE_PAGE);
 
 	must_read = FALSE;
-	
+
 	if (block->io_fix == BUF_IO_READ) {
 
 		must_read = TRUE;
@@ -1148,7 +1183,7 @@
 
 			return(NULL);
 		}
-	}		
+	}
 
 	/* If AWE is enabled and the page is not mapped to a frame, then
 	map it */
@@ -1159,10 +1194,10 @@
 		/* We set second parameter TRUE because the block is in the
 		LRU list and we must put it to awe_LRU_free_mapped list once
 		mapped to a frame */
-		
+
 		buf_awe_map_page_to_frame(block, TRUE);
 	}
-	
+
 #ifdef UNIV_SYNC_DEBUG
 	buf_block_buf_fix_inc_debug(block, file, line);
 #else
@@ -1178,7 +1213,7 @@
 
 #ifdef UNIV_DEBUG_FILE_ACCESSES
 	ut_a(block->file_page_was_freed == FALSE);
-#endif	
+#endif
 	mutex_exit(&(buf_pool->mutex));
 
 #ifdef UNIV_DEBUG
@@ -1209,7 +1244,7 @@
 			block->buf_fix_count--;
 #ifdef UNIV_SYNC_DEBUG
 			rw_lock_s_unlock(&(block->debug_latch));
-#endif			
+#endif
 			mutex_exit(&(buf_pool->mutex));
 
 			return(NULL);
@@ -1217,24 +1252,24 @@
 	} else if (rw_latch == RW_NO_LATCH) {
 
 		if (must_read) {
-		        /* Let us wait until the read operation
+			/* Let us wait until the read operation
 			completes */
 
-		        for (;;) {
-			        mutex_enter(&(buf_pool->mutex));
+			for (;;) {
+				mutex_enter(&(buf_pool->mutex));
+
+				if (block->io_fix == BUF_IO_READ) {
 
-		                if (block->io_fix == BUF_IO_READ) {
+					mutex_exit(&(buf_pool->mutex));
 
-				        mutex_exit(&(buf_pool->mutex));
-				  
-				        /* Sleep 20 milliseconds */
+					/* Sleep 20 milliseconds */
 
-				        os_thread_sleep(20000);
+					os_thread_sleep(20000);
 				} else {
-				  
-				       mutex_exit(&(buf_pool->mutex));
 
-				       break;
+					mutex_exit(&(buf_pool->mutex));
+
+					break;
 				}
 			}
 		}
@@ -1263,7 +1298,7 @@
 #ifdef UNIV_IBUF_DEBUG
 	ut_a(ibuf_count_get(block->space, block->offset) == 0);
 #endif
-	return(block->frame);		
+	return(block->frame);
 }
 
 /************************************************************************
@@ -1290,11 +1325,11 @@
 
 	ut_ad(mtr && block);
 	ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-	
+
 	mutex_enter(&(buf_pool->mutex));
 
 	/* If AWE is used, block may have a different frame now, e.g., NULL */
-	
+
 	if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE)
 			|| UNIV_UNLIKELY(block->frame != guess)) {
 	exit_func:
@@ -1332,7 +1367,7 @@
 
 	if (UNIV_UNLIKELY(!success)) {
 		mutex_enter(&(buf_pool->mutex));
-		
+
 		block->buf_fix_count--;
 #ifdef UNIV_SYNC_DEBUG
 		rw_lock_s_unlock(&(block->debug_latch));
@@ -1351,7 +1386,7 @@
 		}
 
 		mutex_enter(&(buf_pool->mutex));
-		
+
 		block->buf_fix_count--;
 #ifdef UNIV_SYNC_DEBUG
 		rw_lock_s_unlock(&(block->debug_latch));
@@ -1412,20 +1447,20 @@
 
 	ut_ad(mtr);
 	ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-	
+
 	mutex_enter(&(buf_pool->mutex));
 
 	block = buf_block_align(guess);
 
 	if (block->state == BUF_BLOCK_REMOVE_HASH) {
-	        /* Another thread is just freeing the block from the LRU list
-	        of the buffer pool: do not try to access this page; this
+		/* Another thread is just freeing the block from the LRU list
+		of the buffer pool: do not try to access this page; this
 		attempt to access the page can only come through the hash
 		index because when the buffer block state is ..._REMOVE_HASH,
 		we have already removed it from the page address hash table
 		of the buffer pool. */
 
-	        mutex_exit(&(buf_pool->mutex));
+		mutex_exit(&(buf_pool->mutex));
 
 		return(FALSE);
 	}
@@ -1454,14 +1489,14 @@
 								file, line);
 		fix_type = MTR_MEMO_PAGE_X_FIX;
 	}
-	
+
 	if (!success) {
 		mutex_enter(&(buf_pool->mutex));
-		
+
 		block->buf_fix_count--;
 #ifdef UNIV_SYNC_DEBUG
 		rw_lock_s_unlock(&(block->debug_latch));
-#endif		
+#endif
 		mutex_exit(&(buf_pool->mutex));
 
 		return(FALSE);
@@ -1505,27 +1540,27 @@
 	/* Set the state of the block */
 	block->magic_n		= BUF_BLOCK_MAGIC_N;
 
-	block->state 		= BUF_BLOCK_FILE_PAGE;
-	block->space 		= space;
-	block->offset 		= offset;
+	block->state		= BUF_BLOCK_FILE_PAGE;
+	block->space		= space;
+	block->offset		= offset;
 
 	block->lock_hash_val	= 0;
 	block->lock_mutex	= NULL;
-	
+
 	block->freed_page_clock = 0;
 
 	block->newest_modification = ut_dulint_zero;
 	block->oldest_modification = ut_dulint_zero;
-	
+
 	block->accessed		= FALSE;
-	block->buf_fix_count 	= 0;
+	block->buf_fix_count	= 0;
 	block->io_fix		= 0;
 
 	block->n_hash_helps	= 0;
 	block->is_hashed	= FALSE;
-	block->n_fields         = 1;
-	block->n_bytes          = 0;
-	block->side             = BTR_SEARCH_LEFT_SIDE;
+	block->n_fields		= 1;
+	block->n_bytes		= 0;
+	block->side		= BTR_SEARCH_LEFT_SIDE;
 
 	block->file_page_was_freed = FALSE;
 }
@@ -1549,31 +1584,31 @@
 	/* Set the state of the block */
 	block->magic_n		= BUF_BLOCK_MAGIC_N;
 
-	block->state 		= BUF_BLOCK_FILE_PAGE;
-	block->space 		= space;
-	block->offset 		= offset;
+	block->state		= BUF_BLOCK_FILE_PAGE;
+	block->space		= space;
+	block->offset		= offset;
 
 	block->check_index_page_at_flush = FALSE;
 	block->index		= NULL;
-	
+
 	block->lock_hash_val	= lock_rec_hash(space, offset);
 	block->lock_mutex	= NULL;
-	
+
 	/* Insert into the hash table of file pages */
 
-        if (buf_page_hash_get(space, offset)) {
-                fprintf(stderr,
+	if (buf_page_hash_get(space, offset)) {
+		fprintf(stderr,
 "InnoDB: Error: page %lu %lu already found from the hash table\n",
 			(ulong) space,
 			(ulong) offset);
 #ifdef UNIV_DEBUG
-                buf_print();
-                buf_LRU_print();
-                buf_validate();
-                buf_LRU_validate();
+		buf_print();
+		buf_LRU_print();
+		buf_validate();
+		buf_LRU_validate();
 #endif /* UNIV_DEBUG */
-                ut_a(0);
-        }
+		ut_a(0);
+	}
 
 	HASH_INSERT(buf_block_t, hash, buf_pool->page_hash,
 				buf_page_address_fold(space, offset), block);
@@ -1582,16 +1617,16 @@
 
 	block->newest_modification = ut_dulint_zero;
 	block->oldest_modification = ut_dulint_zero;
-	
+
 	block->accessed		= FALSE;
-	block->buf_fix_count 	= 0;
+	block->buf_fix_count	= 0;
 	block->io_fix		= 0;
 
 	block->n_hash_helps	= 0;
 	block->is_hashed	= FALSE;
-	block->n_fields         = 1;
-	block->n_bytes          = 0;
-	block->side             = BTR_SEARCH_LEFT_SIDE;
+	block->n_fields		= 1;
+	block->n_bytes		= 0;
+	block->side		= BTR_SEARCH_LEFT_SIDE;
 
 	block->file_page_was_freed = FALSE;
 }
@@ -1606,7 +1641,7 @@
 on the buffer frame. The io-handler must take care that the flag is cleared
 and the lock released later. This is one of the functions which perform the
 state transition NOT_USED => FILE_PAGE to a block (the other is
-buf_page_create). */ 
+buf_page_create). */
 
 buf_block_t*
 buf_page_init_for_read(
@@ -1632,9 +1667,9 @@
 
 		ut_ad(!ibuf_bitmap_page(offset));
 		ut_ad(ibuf_inside());
-	
+
 		mtr_start(&mtr);
-	
+
 		if (!ibuf_page_low(space, offset, &mtr)) {
 
 			mtr_commit(&mtr);
@@ -1644,7 +1679,7 @@
 	} else {
 		ut_ad(mode == BUF_READ_ANY_PAGE);
 	}
-	
+
 	block = buf_block_alloc();
 
 	ut_a(block);
@@ -1657,7 +1692,7 @@
 	}
 
 	if (*err == DB_TABLESPACE_DELETED
-	    || NULL != buf_page_hash_get(space, offset)) {
+		|| NULL != buf_page_hash_get(space, offset)) {
 
 		/* The page belongs to a space which has been deleted or is
 		being deleted, or the page is already in buf_pool, return */
@@ -1674,26 +1709,26 @@
 	}
 
 	ut_ad(block);
-	
+
 	buf_page_init(space, offset, block);
 
 	/* The block must be put to the LRU list, to the old blocks */
 
-	buf_LRU_add_block(block, TRUE); 	/* TRUE == to old blocks */
-	
+	buf_LRU_add_block(block, TRUE);		/* TRUE == to old blocks */
+
 	block->io_fix = BUF_IO_READ;
 	buf_pool->n_pend_reads++;
-	
+
 	/* We set a pass-type x-lock on the frame because then the same
 	thread which called for the read operation (and is running now at
 	this point of code) can wait for the read to complete by waiting
 	for the x-lock on the frame; if the x-lock were recursive, the
 	same thread would illegally get the x-lock before the page read
 	is completed. The x-lock is cleared by the io-handler thread. */
-	
+
 	rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ);
-	
- 	mutex_exit(&(buf_pool->mutex));
+
+	mutex_exit(&(buf_pool->mutex));
 
 	if (mode == BUF_READ_IBUF_PAGES_ONLY) {
 
@@ -1701,7 +1736,7 @@
 	}
 
 	return(block);
-}	
+}
 
 /************************************************************************
 Initializes a page to the buffer buf_pool. The page is usually not read
@@ -1721,11 +1756,11 @@
 	buf_frame_t*	frame;
 	buf_block_t*	block;
 	buf_block_t*	free_block	= NULL;
-	
+
 	ut_ad(mtr);
 
 	free_block = buf_LRU_get_free_block();
-	
+
 	mutex_enter(&(buf_pool->mutex));
 
 	block = buf_page_hash_get(space, offset);
@@ -1756,12 +1791,12 @@
 #endif /* UNIV_DEBUG */
 
 	block = free_block;
-	
+
 	buf_page_init(space, offset, block);
 
 	/* The block must be put to the LRU list */
 	buf_LRU_add_block(block, FALSE);
-		
+
 #ifdef UNIV_SYNC_DEBUG
 	buf_block_buf_fix_inc_debug(block, __FILE__, __LINE__);
 #else
@@ -1770,7 +1805,7 @@
 	mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
 
 	block->accessed = TRUE;
-	
+
 	buf_pool->n_pages_created++;
 
 	mutex_exit(&(buf_pool->mutex));
@@ -1785,6 +1820,10 @@
 
 	frame = block->frame;
 
+	memset(frame + FIL_PAGE_PREV, 0xff, 4);
+	memset(frame + FIL_PAGE_NEXT, 0xff, 4);
+	mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
+
 	/* Reset to zero the file flush lsn field in the page; if the first
 	page of an ibdata file is 'created' in this function into the buffer
 	pool then we lose the original contents of the file flush lsn stamp.
@@ -1816,8 +1855,7 @@
 	buf_block_t*	block)	/* in: pointer to the block in question */
 {
 	ulint		io_type;
-	ulint		read_page_no;
-	
+
 	ut_ad(block);
 
 	ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -1826,33 +1864,51 @@
 
 	if (io_type == BUF_IO_READ) {
 		/* If this page is not uninitialized and not in the
-		doublewrite buffer, then the page number should be the
-		same as in block */
-
-		read_page_no = mach_read_from_4((block->frame)
+		doublewrite buffer, then the page number and space id
+		should be the same as in block. */
+		ulint	read_page_no = mach_read_from_4((block->frame)
 						+ FIL_PAGE_OFFSET);
-		if (read_page_no != 0
-			&& !trx_doublewrite_page_inside(read_page_no)
-	    		&& read_page_no != block->offset) {
+		ulint	read_space_id = mach_read_from_4((block->frame)
+					 + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
 
+		if (!block->space && trx_doublewrite_page_inside(
+				block->offset)) {
+
+			ut_print_timestamp(stderr);
+			fprintf(stderr,
+"  InnoDB: Error: reading page %lu\n"
+"InnoDB: which is in the doublewrite buffer!\n",
+				(ulong) block->offset);
+		} else if (!read_space_id && !read_page_no) {
+			/* This is likely an uninitialized page. */
+		} else if ((block->space && block->space != read_space_id)
+				|| block->offset != read_page_no) {
+			/* We did not compare space_id to read_space_id
+			if block->space == 0, because the field on the
+			page may contain garbage in MySQL < 4.1.1,
+			which only supported block->space == 0. */
+
+			ut_print_timestamp(stderr);
 			fprintf(stderr,
-"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n",
-				(ulong) read_page_no, (ulong) block->offset);
+"  InnoDB: Error: space id and page n:o stored in the page\n"
+"InnoDB: read in are %lu:%lu, should be %lu:%lu!\n",
+				(ulong) read_space_id, (ulong) read_page_no,
+				(ulong) block->space, (ulong) block->offset);
 		}
 		/* From version 3.23.38 up we store the page checksum
 		   to the 4 first bytes of the page end lsn field */
 
 		if (buf_page_is_corrupted(block->frame)) {
-		  	fprintf(stderr,
+			fprintf(stderr,
 		"InnoDB: Database page corruption on disk or a failed\n"
 		"InnoDB: file read of page %lu.\n", (ulong) block->offset);
-			  
+
 			fputs(
 		"InnoDB: You may have to recover from a backup.\n", stderr);
 
 			buf_page_print(block->frame);
 
-		  	fprintf(stderr,
+			fprintf(stderr,
 		"InnoDB: Database page corruption on disk or a failed\n"
 		"InnoDB: file read of page %lu.\n", (ulong) block->offset);
 			fputs(
@@ -1870,13 +1926,13 @@
 		"InnoDB: See also "
 "InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
 		"InnoDB: about forcing recovery.\n", stderr);
-			  
+
 			if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
 				fputs(
 	"InnoDB: Ending processing because of a corrupt database page.\n",
 					stderr);
-		  		exit(1);
-		  	}
+				exit(1);
+			}
 		}
 
 		if (recv_recovery_is_on()) {
@@ -1889,24 +1945,24 @@
 					block->space, block->offset, TRUE);
 		}
 	}
-	
+
 #ifdef UNIV_IBUF_DEBUG
 	ut_a(ibuf_count_get(block->space, block->offset) == 0);
 #endif
 	mutex_enter(&(buf_pool->mutex));
-	
+
 	/* Because this thread which does the unlocking is not the same that
 	did the locking, we use a pass value != 0 in unlock, which simply
 	removes the newest lock debug record, without checking the thread
 	id. */
 
 	block->io_fix = 0;
-	
+
 	if (io_type == BUF_IO_READ) {
 		/* NOTE that the call to ibuf may have moved the ownership of
 		the x-latch to this OS thread: do not let this confuse you in
-		debugging! */		
-	
+		debugging! */
+
 		ut_ad(buf_pool->n_pend_reads > 0);
 		buf_pool->n_pend_reads--;
 		buf_pool->n_pages_read++;
@@ -1936,7 +1992,7 @@
 		}
 #endif /* UNIV_DEBUG */
 	}
-	
+
 	mutex_exit(&(buf_pool->mutex));
 
 #ifdef UNIV_DEBUG
@@ -1959,13 +2015,13 @@
 	ibool	freed;
 
 	ut_ad(buf_all_freed());
-	
+
 	freed = TRUE;
 
 	while (freed) {
 		freed = buf_LRU_search_and_free_block(100);
 	}
-	
+
 	mutex_enter(&(buf_pool->mutex));
 
 	ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
@@ -1990,7 +2046,7 @@
 	ulint		n_flush		= 0;
 	ulint		n_free		= 0;
 	ulint		n_page		= 0;
-	
+
 	ut_ad(buf_pool);
 
 	mutex_enter(&(buf_pool->mutex));
@@ -2007,8 +2063,8 @@
 
 #ifdef UNIV_IBUF_DEBUG
 			ut_a((block->io_fix == BUF_IO_READ)
-			     || ibuf_count_get(block->space, block->offset)
-								== 0);
+				|| ibuf_count_get(block->space, block->offset)
+				== 0);
 #endif
 			if (block->io_fix == BUF_IO_WRITE) {
 
@@ -2031,18 +2087,18 @@
 				ut_a(rw_lock_is_locked(&(block->lock),
 							RW_LOCK_EX));
 			}
-			
+
 			n_lru++;
 
 			if (ut_dulint_cmp(block->oldest_modification,
 						ut_dulint_zero) > 0) {
 					n_flush++;
-			}	
-		
+			}
+
 		} else if (block->state == BUF_BLOCK_NOT_USED) {
 			n_free++;
 		}
- 	}
+	}
 
 	if (n_lru + n_free > buf_pool->curr_size) {
 		fprintf(stderr, "n LRU %lu, n free %lu\n", (ulong) n_lru, (ulong) n_free);
@@ -2060,14 +2116,14 @@
 	ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
 	ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
 	ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
-	
+
 	mutex_exit(&(buf_pool->mutex));
 
 	ut_a(buf_LRU_validate());
 	ut_a(buf_flush_validate());
 
 	return(TRUE);
-}	
+}
 
 /*************************************************************************
 Prints info of the buffer buf_pool data structure. */
@@ -2083,9 +2139,9 @@
 	ulint		j;
 	dulint		id;
 	ulint		n_found;
-	buf_frame_t* 	frame;
+	buf_frame_t*	frame;
 	dict_index_t*	index;
-	
+
 	ut_ad(buf_pool);
 
 	size = buf_pool->curr_size;
@@ -2094,7 +2150,7 @@
 	counts = mem_alloc(sizeof(ulint) * size);
 
 	mutex_enter(&(buf_pool->mutex));
-	
+
 	fprintf(stderr,
 		"buf_pool size %lu\n"
 		"database pages %lu\n"
@@ -2115,7 +2171,7 @@
 		(ulong) buf_pool->n_pages_written);
 
 	/* Count the number of blocks belonging to each index in the buffer */
-	
+
 	n_found = 0;
 
 	for (i = 0; i < size; i++) {
@@ -2153,8 +2209,8 @@
 
 		fprintf(stderr,
 			"Block count for index %lu in buffer is about %lu",
-		       (ulong) ut_dulint_get_low(index_ids[i]),
-		       (ulong) counts[i]);
+			(ulong) ut_dulint_get_low(index_ids[i]),
+			(ulong) counts[i]);
 
 		if (index) {
 			putc(' ', stderr);
@@ -2163,12 +2219,12 @@
 
 		putc('\n', stderr);
 	}
-	
+
 	mem_free(index_ids);
 	mem_free(counts);
 
 	ut_a(buf_validate());
-}	
+}
 #endif /* UNIV_DEBUG */
 
 /*************************************************************************
@@ -2177,23 +2233,24 @@
 ulint
 buf_get_latched_pages_number(void)
 {
-        buf_block_t* block;
-        ulint i;
-        ulint fixed_pages_number = 0;
+	buf_block_t* block;
+	ulint i;
+	ulint fixed_pages_number = 0;
 
-        mutex_enter(&(buf_pool->mutex));
+	mutex_enter(&(buf_pool->mutex));
 
-        for (i = 0; i < buf_pool->curr_size; i++) {
+	for (i = 0; i < buf_pool->curr_size; i++) {
 
-               block = buf_pool_get_nth_block(buf_pool, i);
+		block = buf_pool_get_nth_block(buf_pool, i);
+
+		if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
+			block->magic_n == BUF_BLOCK_MAGIC_N )
+			fixed_pages_number++;
+	}
 
-               if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
-                    block->magic_n == BUF_BLOCK_MAGIC_N )
-                       fixed_pages_number++;
-        }
+	mutex_exit(&(buf_pool->mutex));
 
-        mutex_exit(&(buf_pool->mutex));
-        return fixed_pages_number;
+	return(fixed_pages_number);
 }
 
 /*************************************************************************
@@ -2222,10 +2279,10 @@
 	mutex_enter(&(buf_pool->mutex));
 
 	ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
-		     / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
-		        + UT_LIST_GET_LEN(buf_pool->free));
+		/ (1 + UT_LIST_GET_LEN(buf_pool->LRU)
+			+ UT_LIST_GET_LEN(buf_pool->free));
 
-		       /* 1 + is there to avoid division by zero */   
+	/* 1 + is there to avoid division by zero */
 
 	mutex_exit(&(buf_pool->mutex));
 
@@ -2243,17 +2300,17 @@
 	time_t	current_time;
 	double	time_elapsed;
 	ulint	size;
-	
+
 	ut_ad(buf_pool);
 	size = buf_pool->curr_size;
 
 	mutex_enter(&(buf_pool->mutex));
-	
+
 	if (srv_use_awe) {
 		fprintf(stderr,
 		"AWE: Buffer pool memory frames                        %lu\n",
 				(ulong) buf_pool->n_frames);
-		
+
 		fprintf(stderr,
 		"AWE: Database pages and free buffers mapped in frames %lu\n",
 				(ulong) UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
@@ -2300,13 +2357,12 @@
 				- buf_pool->n_pages_awe_remapped_old)
 			/ time_elapsed);
 	}
-		
+
 	if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
 		fprintf(file, "Buffer pool hit rate %lu / 1000\n",
-       (ulong) (1000
-		- ((1000 *
-		    (buf_pool->n_pages_read - buf_pool->n_pages_read_old))
-		/ (buf_pool->n_page_gets - buf_pool->n_page_gets_old))));
+			(ulong) (1000 -
+			((1000 * (buf_pool->n_pages_read - buf_pool->n_pages_read_old))
+			/ (buf_pool->n_page_gets - buf_pool->n_page_gets_old))));
 	} else {
 		fputs("No buffer pool page gets since the last printout\n",
 			file);
@@ -2328,12 +2384,12 @@
 buf_refresh_io_stats(void)
 /*======================*/
 {
-        buf_pool->last_printout_time = time(NULL);
+	buf_pool->last_printout_time = time(NULL);
 	buf_pool->n_page_gets_old = buf_pool->n_page_gets;
 	buf_pool->n_pages_read_old = buf_pool->n_pages_read;
 	buf_pool->n_pages_created_old = buf_pool->n_pages_created;
 	buf_pool->n_pages_written_old = buf_pool->n_pages_written;
-	buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped; 
+	buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
 }
 
 /*************************************************************************
@@ -2345,7 +2401,7 @@
 {
 	buf_block_t*	block;
 	ulint		i;
-	
+
 	ut_ad(buf_pool);
 
 	mutex_enter(&(buf_pool->mutex));
@@ -2361,15 +2417,15 @@
 				fprintf(stderr,
 					"Page %lu %lu still fixed or dirty\n",
 					(ulong) block->space, (ulong) block->offset);
-			    	ut_error;
+				ut_error;
 			}
 		}
- 	}
+	}
 
 	mutex_exit(&(buf_pool->mutex));
 
 	return(TRUE);
-}	
+}
 
 /*************************************************************************
 Checks that there currently are no pending i/o-operations for the buffer

--- 1.65.11.1/innobase/dict/dict0dict.c	2006-08-29 18:58:59 +04:00
+++ 1.84/storage/innobase/dict/dict0dict.c	2006-08-29 18:58:59 +04:00
@@ -26,6 +26,9 @@
 #include "pars0sym.h"
 #include "que0que.h"
 #include "rem0cmp.h"
+#ifndef UNIV_HOTBACKUP
+# include "m_ctype.h" /* my_isspace() */
+#endif /* !UNIV_HOTBACKUP */
 
 dict_sys_t*	dict_sys	= NULL;	/* the dictionary system */
 
@@ -55,6 +58,42 @@
 
 #ifndef UNIV_HOTBACKUP
 /**********************************************************************
+Converts an identifier to a table name.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_convert_from_table_id(
+/*===========================*/
+	char*		to,	/* out: converted identifier */
+	const char*	from,	/* in: identifier to convert */
+	ulint		len);	/* in: length of 'to', in bytes;
+				should be at least 5 * strlen(to) + 1 */
+/**********************************************************************
+Converts an identifier to UTF-8.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_convert_from_id(
+/*=====================*/
+	char*		to,	/* out: converted identifier */
+	const char*	from,	/* in: identifier to convert */
+	ulint		len);	/* in: length of 'to', in bytes;
+				should be at least 3 * strlen(to) + 1 */
+/**********************************************************************
+Removes the filename encoding of a table or database name.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_convert_from_filename(
+/*===========================*/
+	char*		s);	/* in: identifier; out: decoded identifier */
+/**********************************************************************
 Compares NUL-terminated UTF-8 strings case insensitively.
 
 NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
@@ -77,6 +116,17 @@
 innobase_casedn_str(
 /*================*/
 	char*	a);	/* in/out: string to put in lower case */
+
+/**************************************************************************
+Determines the connection character set.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+struct charset_info_st*
+innobase_get_charset(
+/*=================*/
+				/* out: connection character set */
+	void*	mysql_thd);	/* in: MySQL thread handle */
 #endif /* !UNIV_HOTBACKUP */
 
 /**************************************************************************
@@ -132,7 +182,7 @@
 /*=================*/
 				/* out: TRUE if success */
 	dict_table_t*	table,	/* in: table */
-	dict_index_t*	index);	/* in: index */	
+	dict_index_t*	index);	/* in: index */
 /***********************************************************************
 Builds the internal dictionary cache representation for a clustered
 index, containing also system fields not defined by the user. */
@@ -144,7 +194,7 @@
 				of the clustered index */
 	dict_table_t*	table,	/* in: table */
 	dict_index_t*	index);	/* in: user representation of a clustered
-				index */	
+				index */
 /***********************************************************************
 Builds the internal dictionary cache representation for a non-clustered
 index, containing also system fields not defined by the user. */
@@ -156,7 +206,7 @@
 				of the non-clustered index */
 	dict_table_t*	table,	/* in: table */
 	dict_index_t*	index);	/* in: user representation of a non-clustered
-				index */	
+				index */
 /**************************************************************************
 Removes a foreign constraint struct from the dictionary cache. */
 static
@@ -196,9 +246,10 @@
 /* Stream for storing detailed information about the latest foreign key
 and unique key errors */
 FILE*	dict_foreign_err_file		= NULL;
-mutex_t	dict_foreign_err_mutex; 	/* mutex protecting the foreign
+mutex_t	dict_foreign_err_mutex;		/* mutex protecting the foreign
 					and unique error buffers */
-	
+
+#ifndef UNIV_HOTBACKUP
 /**********************************************************************
 Makes all characters in a NUL-terminated UTF-8 string lower case. */
 
@@ -209,6 +260,7 @@
 {
 	innobase_casedn_str(a);
 }
+#endif /* !UNIV_HOTBACKUP */
 
 /************************************************************************
 Checks if the database name in two table names is the same. */
@@ -233,7 +285,7 @@
 
 /************************************************************************
 Return the end of table name where we have removed dbname and '/'. */
-static
+
 const char*
 dict_remove_db_name(
 /*================*/
@@ -241,11 +293,10 @@
 	const char*	name)	/* in: table name in the form
 				dbname '/' tablename */
 {
-	const char*	s;
-	s = strchr(name, '/');
+	const char*	s = strchr(name, '/');
 	ut_a(s);
-	if (s) s++;
-	return(s);
+
+	return(s + 1);
 }
 
 /************************************************************************
@@ -263,7 +314,7 @@
 	ut_a(s);
 	return(s - name);
 }
-	
+
 /************************************************************************
 Reserves the dictionary system mutex for MySQL. */
 
@@ -273,7 +324,7 @@
 {
 	mutex_enter(&(dict_sys->mutex));
 }
-	
+
 /************************************************************************
 Releases the dictionary system mutex for MySQL. */
 
@@ -283,7 +334,7 @@
 {
 	mutex_exit(&(dict_sys->mutex));
 }
-	
+
 /************************************************************************
 Decrements the count of open MySQL handles to a table. */
 
@@ -297,7 +348,7 @@
 	ut_a(table->n_mysql_handles_opened > 0);
 
 	table->n_mysql_handles_opened--;
-	
+
 	mutex_exit(&(dict_sys->mutex));
 }
 
@@ -350,7 +401,7 @@
 {
 	return(dict_table_get_index(table, name));
 }
-	
+
 /************************************************************************
 Initializes the autoinc counter. It is not an error to initialize an already
 initialized counter. */
@@ -390,7 +441,7 @@
 		value = table->autoinc;
 		table->autoinc = table->autoinc + 1;
 	}
-	
+
 	mutex_exit(&(table->autoinc_mutex));
 
 	return(value);
@@ -407,7 +458,7 @@
 	mutex_enter(&(table->autoinc_mutex));
 
 	table->autoinc = table->autoinc - 1;
-	
+
 	mutex_exit(&(table->autoinc_mutex));
 }
 
@@ -431,7 +482,7 @@
 	} else {
 		value = table->autoinc;
 	}
-	
+
 	mutex_exit(&(table->autoinc_mutex));
 
 	return(value);
@@ -476,7 +527,7 @@
 		if (value >= table->autoinc) {
 			table->autoinc = value + 1;
 		}
-	}	
+	}
 
 	mutex_exit(&(table->autoinc_mutex));
 }
@@ -497,7 +548,7 @@
 	dict_col_t*	col;
 	ulint		pos;
 	ulint		n_fields;
-	
+
 	ut_ad(index);
 	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
 
@@ -509,7 +560,7 @@
 	}
 
 	n_fields = dict_index_get_n_fields(index);
-	
+
 	for (pos = 0; pos < n_fields; pos++) {
 		field = dict_index_get_nth_field(index, pos);
 
@@ -537,7 +588,7 @@
 	dict_col_t*	col;
 	ulint		pos;
 	ulint		n_fields;
-	
+
 	ut_ad(index);
 	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
 
@@ -549,7 +600,7 @@
 	col = dict_table_get_nth_col(index->table, n);
 
 	n_fields = dict_index_get_n_fields(index);
-	
+
 	for (pos = 0; pos < n_fields; pos++) {
 		field = dict_index_get_nth_field(index, pos);
 
@@ -582,21 +633,21 @@
 	dict_field_t*	field2;
 	ulint		n_fields;
 	ulint		pos;
-	
+
 	ut_ad(index);
 	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
 
 	field2 = dict_index_get_nth_field(index2, n);
 
 	n_fields = dict_index_get_n_fields(index);
-	
+
 	for (pos = 0; pos < n_fields; pos++) {
 		field = dict_index_get_nth_field(index, pos);
 
 		if (field->col == field2->col
-		    && (field->prefix_len == 0
+			&& (field->prefix_len == 0
 			|| (field->prefix_len >= field2->prefix_len
-			    && field2->prefix_len != 0))) {
+				&& field2->prefix_len != 0))) {
 
 			return(pos);
 		}
@@ -606,7 +657,7 @@
 }
 
 /**************************************************************************
-Returns a table object, based on table id, and memoryfixes it. */
+Returns a table object based on table id. */
 
 dict_table_t*
 dict_table_get_on_id(
@@ -616,7 +667,7 @@
 	trx_t*	trx)		/* in: transaction handle */
 {
 	dict_table_t*	table;
-	
+
 	if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
 	   || trx->dict_operation_lock_mode == RW_X_LATCH) {
 		/* It is a system table which will always exist in the table
@@ -628,13 +679,13 @@
 		ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 
-		return(dict_table_get_on_id_low(table_id, trx));
+		return(dict_table_get_on_id_low(table_id));
 	}
 
 	mutex_enter(&(dict_sys->mutex));
 
-	table = dict_table_get_on_id_low(table_id, trx);
-	
+	table = dict_table_get_on_id_low(table_id);
+
 	mutex_exit(&(dict_sys->mutex));
 
 	return(table);
@@ -656,6 +707,19 @@
 }
 
 /************************************************************************
+Check whether the table uses the compact page format. */
+
+ibool
+dict_table_is_comp_noninline(
+/*=========================*/
+					/* out: TRUE if table uses the
+					compact page format */
+	const dict_table_t*	table)	/* in: table */
+{
+	return(dict_table_is_comp(table));
+}
+
+/************************************************************************
 Checks if a column is in the ordering columns of the clustered index of a
 table. Column prefixes are treated like whole columns. */
 
@@ -672,7 +736,7 @@
 	dict_col_t*	col;
 	ulint		pos;
 	ulint		n_fields;
-	
+
 	ut_ad(table);
 
 	col = dict_table_get_nth_col(table, n);
@@ -680,7 +744,7 @@
 	index = dict_table_get_first_index(table);
 
 	n_fields = dict_index_get_n_unique(index);
-	
+
 	for (pos = 0; pos < n_fields; pos++) {
 		field = dict_index_get_nth_field(index, pos);
 
@@ -702,8 +766,7 @@
 {
 	dict_sys = mem_alloc(sizeof(dict_sys_t));
 
-	mutex_create(&(dict_sys->mutex));
-	mutex_set_level(&(dict_sys->mutex), SYNC_DICT);
+	mutex_create(&dict_sys->mutex, SYNC_DICT);
 
 	dict_sys->table_hash = hash_create(buf_pool_get_max_size() /
 					(DICT_POOL_PER_TABLE_HASH *
@@ -718,44 +781,40 @@
 
 	UT_LIST_INIT(dict_sys->table_LRU);
 
-	rw_lock_create(&dict_operation_lock);
-	rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
+	rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
 
 	dict_foreign_err_file = os_file_create_tmpfile();
 	ut_a(dict_foreign_err_file);
-	mutex_create(&dict_foreign_err_mutex);
-	mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
+
+	mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
 }
 
 /**************************************************************************
-Returns a table object and memoryfixes it. NOTE! This is a high-level
-function to be used mainly from outside the 'dict' directory. Inside this
-directory dict_table_get_low is usually the appropriate function. */
+Returns a table object. NOTE! This is a high-level function to be used
+mainly from outside the 'dict' directory. Inside this directory
+dict_table_get_low is usually the appropriate function. */
 
 dict_table_t*
 dict_table_get(
 /*===========*/
 					/* out: table, NULL if
 					does not exist */
-	const char*	table_name,	/* in: table name */
-	trx_t*		trx)		/* in: transaction handle or NULL */
+	const char*	table_name)	/* in: table name */
 {
 	dict_table_t*	table;
 
-	UT_NOT_USED(trx);
-
 	mutex_enter(&(dict_sys->mutex));
-	
+
 	table = dict_table_get_low(table_name);
 
 	mutex_exit(&(dict_sys->mutex));
 
 	if (table != NULL) {
-	        if (!table->stat_initialized) {
+		if (!table->stat_initialized) {
 			dict_update_statistics(table);
 		}
 	}
-	
+
 	return(table);
 }
 
@@ -767,30 +826,27 @@
 /*======================================*/
 					/* out: table, NULL if
 					does not exist */
-	const char*	table_name,	/* in: table name */
-	trx_t*		trx)		/* in: transaction handle or NULL */
+	const char*	table_name)	/* in: table name */
 {
 	dict_table_t*	table;
 
-	UT_NOT_USED(trx);
-
 	mutex_enter(&(dict_sys->mutex));
-	
+
 	table = dict_table_get_low(table_name);
 
 	if (table != NULL) {
 
-	        table->n_mysql_handles_opened++;
+		table->n_mysql_handles_opened++;
 	}
 
 	mutex_exit(&(dict_sys->mutex));
 
 	if (table != NULL) {
-	        if (!table->stat_initialized && !table->ibd_file_missing) {
+		if (!table->stat_initialized && !table->ibd_file_missing) {
 			dict_update_statistics(table);
 		}
 	}
-	
+
 	return(table);
 }
 
@@ -805,7 +861,8 @@
 	ulint	fold;
 	ulint	id_fold;
 	ulint	i;
-	
+	ulint	row_len;
+
 	ut_ad(table);
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -813,12 +870,12 @@
 	ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
 	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
 	ut_ad(table->cached == FALSE);
-	
+
 	fold = ut_fold_string(table->name);
 	id_fold = ut_fold_dulint(table->id);
-	
+
 	table->cached = TRUE;
-	
+
 	/* NOTE: the system columns MUST be added in the following order
 	(so that they can be indexed by the numerical value of DATA_ROW_ID,
 	etc.) and as the last columns of the table memory object.
@@ -847,11 +904,29 @@
 #endif
 
 	/* This check reminds that if a new system column is added to
-	the program, it should be dealt with here */ 
+	the program, it should be dealt with here */
 #if DATA_N_SYS_COLS != 4
 #error "DATA_N_SYS_COLS != 4"
 #endif
 
+	row_len = 0;
+	for (i = 0; i < table->n_def; i++) {
+		ulint	col_len = dtype_get_max_size(
+			dict_col_get_type(dict_table_get_nth_col(table, i)));
+
+		/* If we have a single unbounded field, or several gigantic
+		fields, mark the maximum row size as ULINT_MAX. */
+		if (ut_max(col_len, row_len) >= (ULINT_MAX / 2)) {
+			row_len = ULINT_MAX;
+
+			break;
+		}
+
+		row_len += col_len;
+	}
+
+	table->max_row_size = row_len;
+
 	/* Look for a table with the same name: error if such exists */
 	{
 		dict_table_t*	table2;
@@ -868,13 +943,6 @@
 		ut_a(table2 == NULL);
 	}
 
-	if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
-		table->mix_id_len = mach_dulint_get_compressed_size(
-								table->mix_id);
-		mach_dulint_write_compressed(table->mix_id_buf, table->mix_id);
-	}
-
 	/* Add the columns to the column hash table */
 	for (i = 0; i < table->n_cols; i++) {
 		dict_col_add_to_cache(table, dict_table_get_nth_col(table, i));
@@ -890,10 +958,7 @@
 	/* Add table to LRU list of tables */
 	UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
 
-	/* If the dictionary cache grows too big, trim the table LRU list */
-
 	dict_sys->size += mem_heap_get_size(table->heap);
-	/* dict_table_LRU_trim(); */
 }
 
 /**************************************************************************
@@ -909,7 +974,7 @@
 {
 	dict_table_t*	table;
 	dict_index_t*	index;
-	
+
 	table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
 
 	while (table) {
@@ -951,16 +1016,16 @@
 	char*		old_name;
 	ibool		success;
 	ulint		i;
-	
+
 	ut_ad(table);
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 
 	old_size = mem_heap_get_size(table->heap);
-	
+
 	fold = ut_fold_string(new_name);
-	
+
 	/* Look for a table with the same name: error if such exists */
 	{
 		dict_table_t*	table2;
@@ -969,7 +1034,7 @@
 		if (table2) {
 			fprintf(stderr,
 "InnoDB: Error: dictionary cache already contains a table of name %s\n",
-	 							     new_name);
+				new_name);
 			return(FALSE);
 		}
 	}
@@ -1018,7 +1083,7 @@
 
 	while (index != NULL) {
 		index->table_name = table->name;
-		
+
 		index = dict_table_get_next_index(index);
 	}
 
@@ -1030,7 +1095,7 @@
 		constraints from the dictionary cache here. The foreign key
 		constraints will be inherited to the new table from the
 		system tables through a call of dict_load_foreigns. */
-	
+
 		/* Remove the foreign constraints from the cache */
 		foreign = UT_LIST_GET_LAST(table->foreign_list);
 
@@ -1046,14 +1111,14 @@
 		while (foreign != NULL) {
 			foreign->referenced_table = NULL;
 			foreign->referenced_index = NULL;
-		
+
 			foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
 		}
 
 		/* Make the list of referencing constraints empty */
 
 		UT_LIST_INIT(table->referenced_list);
-		
+
 		return(TRUE);
 	}
 
@@ -1085,10 +1150,10 @@
 			old_id = mem_strdup(foreign->id);
 
 			if (ut_strlen(foreign->id) > ut_strlen(old_name)
-						+ ((sizeof dict_ibfk) - 1)
-			    && 0 == ut_memcmp(foreign->id, old_name,
-						ut_strlen(old_name))
-			    && 0 == ut_memcmp(
+				+ ((sizeof dict_ibfk) - 1)
+				&& 0 == ut_memcmp(foreign->id, old_name,
+					ut_strlen(old_name))
+				&& 0 == ut_memcmp(
 					foreign->id + ut_strlen(old_name),
 					dict_ibfk, (sizeof dict_ibfk) - 1)) {
 
@@ -1096,11 +1161,11 @@
 
 				if (ut_strlen(table->name) > ut_strlen(old_name)) {
 					foreign->id = mem_heap_alloc(
-					     foreign->heap,
+						foreign->heap,
 						ut_strlen(table->name)
 						+ ut_strlen(old_id) + 1);
 				}
-				
+
 				/* Replace the prefix 'databasename/tablename'
 				with the new names */
 				strcpy(foreign->id, table->name);
@@ -1112,16 +1177,16 @@
 				db_len = dict_get_db_name_len(table->name) + 1;
 
 				if (dict_get_db_name_len(table->name)
-			    	    > dict_get_db_name_len(foreign->id)) {
+					> dict_get_db_name_len(foreign->id)) {
 
 					foreign->id = mem_heap_alloc(
-					     foreign->heap,
-				 	     db_len + ut_strlen(old_id) + 1);
+						foreign->heap,
+						db_len + ut_strlen(old_id) + 1);
 				}
 
 				/* Replace the database prefix in id with the
 				one from table->name */
-			
+
 				ut_memcpy(foreign->id, table->name, db_len);
 
 				strcpy(foreign->id + db_len,
@@ -1194,7 +1259,7 @@
 	dict_index_t*	index;
 	ulint		size;
 	ulint		i;
-	
+
 	ut_ad(table);
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1222,7 +1287,7 @@
 	while (foreign != NULL) {
 		foreign->referenced_table = NULL;
 		foreign->referenced_index = NULL;
-		
+
 		foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
 	}
 
@@ -1259,38 +1324,6 @@
 }
 
 /**************************************************************************
-Frees tables from the end of table_LRU if the dictionary cache occupies
-too much space. Currently not used! */
-
-void
-dict_table_LRU_trim(void)
-/*=====================*/
-{
-	dict_table_t*	table;
-	dict_table_t*	prev_table;
-
-	ut_error;
-
-#ifdef UNIV_SYNC_DEBUG
-	ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
-	table = UT_LIST_GET_LAST(dict_sys->table_LRU);
-
-	while (table && (dict_sys->size >
-			 buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) {
-
-		prev_table = UT_LIST_GET_PREV(table_LRU, table);
-
-		if (table->mem_fix == 0) {
-			dict_table_remove_from_cache(table);
-		}
-
-		table = prev_table;
-	}
-}
-
-/**************************************************************************
 Adds a column to the data dictionary hash table. */
 static
 void
@@ -1306,7 +1339,7 @@
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-	
+
 	fold = ut_fold_ulint_pair(ut_fold_string(table->name),
 				  ut_fold_string(col->name));
 
@@ -1316,7 +1349,7 @@
 		HASH_SEARCH(hash, dict_sys->col_hash, fold, col2,
 			(ut_strcmp(col->name, col2->name) == 0)
 			&& (ut_strcmp((col2->table)->name, table->name)
-							== 0));  
+							== 0));
 		ut_a(col2 == NULL);
 	}
 
@@ -1339,7 +1372,7 @@
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-	
+
 	fold = ut_fold_ulint_pair(ut_fold_string(table->name),
 				  ut_fold_string(col->name));
 
@@ -1364,7 +1397,7 @@
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-	
+
 	fold = ut_fold_ulint_pair(ut_fold_string(table->name),
 				  ut_fold_string(col->name));
 
@@ -1372,7 +1405,7 @@
 
 	fold = ut_fold_ulint_pair(ut_fold_string(new_name),
 				  ut_fold_string(col->name));
-				  
+
 	HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
 }
 
@@ -1422,21 +1455,21 @@
 {
 	dict_index_t*	new_index;
 	dict_tree_t*	tree;
-	dict_table_t*	cluster;
 	dict_field_t*	field;
 	ulint		n_ord;
 	ibool		success;
 	ulint		i;
-	
+
 	ut_ad(index);
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_ad(index->n_def == index->n_fields);
 	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-	
+
 	ut_ad(mem_heap_validate(index->heap));
 
+#ifdef UNIV_DEBUG
 	{
 		dict_index_t*	index2;
 		index2 = UT_LIST_GET_FIRST(table->indexes);
@@ -1446,10 +1479,11 @@
 
 			index2 = UT_LIST_GET_NEXT(indexes, index2);
 		}
-
-		ut_a(UT_LIST_GET_LEN(table->indexes) == 0
-	      			|| (index->type & DICT_CLUSTERED) == 0);
 	}
+#endif /* UNIV_DEBUG */
+
+	ut_a(!(index->type & DICT_CLUSTERED)
+			|| UT_LIST_GET_LEN(table->indexes) == 0);
 
 	success = dict_index_find_cols(table, index);
 
@@ -1458,7 +1492,7 @@
 
 		return(FALSE);
 	}
-	
+
 	/* Build the cache internal representation of the index,
 	containing also the added system fields */
 
@@ -1469,15 +1503,15 @@
 	}
 
 	new_index->search_info = btr_search_info_create(new_index->heap);
-	
+
 	/* Set the n_fields value in new_index to the actual defined
 	number of fields in the cache internal representation */
 
 	new_index->n_fields = new_index->n_def;
-	
+
 	/* Add the new index as the last index for the table */
 
-	UT_LIST_ADD_LAST(indexes, table->indexes, new_index);	
+	UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
 	new_index->table = table;
 	new_index->table_name = table->name;
 
@@ -1496,21 +1530,11 @@
 		dict_field_get_col(field)->ord_part++;
 	}
 
-	if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-		/* The index tree is found from the cluster object */
-	    
-		cluster = dict_table_get_low(table->cluster_name);
-
-		tree = dict_index_get_tree(
-					UT_LIST_GET_FIRST(cluster->indexes));
-		new_index->tree = tree;
-	} else {
-		/* Create an index tree memory object for the index */
-		tree = dict_tree_create(new_index, page_no);
-		ut_ad(tree);
+	/* Create an index tree memory object for the index */
+	tree = dict_tree_create(new_index, page_no);
+	ut_ad(tree);
 
-		new_index->tree = tree;
-	}
+	new_index->tree = tree;
 
 	if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
 
@@ -1526,14 +1550,11 @@
 			new_index->stat_n_diff_key_vals[i] = 100;
 		}
 	}
-	
+
 	/* Add the index to the list of indexes stored in the tree */
-	UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index); 
-	
-	/* If the dictionary cache grows too big, trim the table LRU list */
+	tree->tree_index = new_index;
 
 	dict_sys->size += mem_heap_get_size(new_index->heap);
-	/* dict_table_LRU_trim(); */
 
 	dict_mem_index_free(index);
 
@@ -1560,7 +1581,7 @@
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 
-	ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
+	ut_ad(index->tree->tree_index);
 	dict_tree_free(index->tree);
 
 	/* Decrement the ord_part counts in columns which are ordering */
@@ -1593,13 +1614,13 @@
 /*=================*/
 				/* out: TRUE if success */
 	dict_table_t*	table,	/* in: table */
-	dict_index_t*	index)	/* in: index */	
+	dict_index_t*	index)	/* in: index */
 {
 	dict_col_t*	col;
 	dict_field_t*	field;
 	ulint		fold;
 	ulint		i;
-	
+
 	ut_ad(table && index);
 	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
 #ifdef UNIV_SYNC_DEBUG
@@ -1610,15 +1631,15 @@
 		field = dict_index_get_nth_field(index, i);
 
 		fold = ut_fold_ulint_pair(ut_fold_string(table->name),
-				  	       ut_fold_string(field->name));
-			
+			ut_fold_string(field->name));
+
 		HASH_SEARCH(hash, dict_sys->col_hash, fold, col,
 				(ut_strcmp(col->name, field->name) == 0)
 				&& (ut_strcmp((col->table)->name, table->name)
-								== 0));  
+								== 0));
 		if (col == NULL) {
 
- 			return(FALSE);
+			return(FALSE);
 		} else {
 			field->col = col;
 		}
@@ -1626,7 +1647,7 @@
 
 	return(TRUE);
 }
-	
+
 /***********************************************************************
 Adds a column to index. */
 
@@ -1635,12 +1656,11 @@
 /*===============*/
 	dict_index_t*	index,		/* in: index */
 	dict_col_t*	col,		/* in: column */
-	ulint		order,		/* in: order criterion */
 	ulint		prefix_len)	/* in: column prefix length */
 {
 	dict_field_t*	field;
 
-	dict_mem_index_add_field(index, col->name, order, prefix_len);
+	dict_mem_index_add_field(index, col->name, prefix_len);
 
 	field = dict_index_get_nth_field(index, index->n_def - 1);
 
@@ -1662,17 +1682,6 @@
 	if (!(dtype_get_prtype(&col->type) & DATA_NOT_NULL)) {
 		index->n_nullable++;
 	}
-
-	if (index->n_def > 1) {
-		const dict_field_t*	field2 =
-			dict_index_get_nth_field(index, index->n_def - 2);
-		field->fixed_offs = (!field2->fixed_len ||
-					field2->fixed_offs == ULINT_UNDEFINED)
-				? ULINT_UNDEFINED
-				: field2->fixed_len + field2->fixed_offs;
-	} else {
-		field->fixed_offs = 0;
-	}
 }
 
 /***********************************************************************
@@ -1688,14 +1697,13 @@
 {
 	dict_field_t*	field;
 	ulint		i;
-	
+
 	/* Copy fields contained in index2 */
 
 	for (i = start; i < end; i++) {
 
 		field = dict_index_get_nth_field(index2, i);
-		dict_index_add_col(index1, field->col, field->order,
-						      field->prefix_len);
+		dict_index_add_col(index1, field->col, field->prefix_len);
 	}
 }
 
@@ -1740,8 +1748,6 @@
 	dtype_t*	type;
 	ulint		i;
 
-	ut_ad(!(table->type & DICT_UNIVERSAL));
-
 	for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
 
 		dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
@@ -1762,7 +1768,7 @@
 				of the clustered index */
 	dict_table_t*	table,	/* in: table */
 	dict_index_t*	index)	/* in: user representation of a clustered
-				index */	
+				index */
 {
 	dict_index_t*	new_index;
 	dict_field_t*	field;
@@ -1780,40 +1786,24 @@
 
 	/* Create a new index object with certainly enough fields */
 	new_index = dict_mem_index_create(table->name,
-				     index->name,
-				     table->space,
-				     index->type,
-				     index->n_fields + table->n_cols);
+		index->name, table->space, index->type,
+		index->n_fields + table->n_cols);
 
 	/* Copy other relevant data from the old index struct to the new
 	struct: it inherits the values */
 
 	new_index->n_user_defined_cols = index->n_fields;
-	
-	new_index->id = index->id;
 
-	if (table->type != DICT_TABLE_ORDINARY) {
-		/* The index is mixed: copy common key prefix fields */
-		
-		dict_index_copy(new_index, index, 0, table->mix_len);
-
-		/* Add the mix id column */
-		dict_index_add_col(new_index,
-			  dict_table_get_sys_col(table, DATA_MIX_ID), 0, 0);
+	new_index->id = index->id;
 
-		/* Copy the rest of fields */
-		dict_index_copy(new_index, index, table->mix_len,
-							index->n_fields);
-	} else {
-		/* Copy the fields of index */
-		dict_index_copy(new_index, index, 0, index->n_fields);
-	}
+	/* Copy the fields of index */
+	dict_index_copy(new_index, index, 0, index->n_fields);
 
 	if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
 		/* No fixed number of fields determines an entry uniquely */
 
 		new_index->n_uniq = ULINT_MAX;
-		
+
 	} else if (index->type & DICT_UNIQUE) {
 		/* Only the fields defined so far are needed to identify
 		the index entry uniquely */
@@ -1831,21 +1821,27 @@
 
 		trx_id_pos = new_index->n_def;
 
-		ut_ad(DATA_ROW_ID == 0);
-		ut_ad(DATA_TRX_ID == 1);
-		ut_ad(DATA_ROLL_PTR == 2);
+#if DATA_ROW_ID != 0
+# error "DATA_ROW_ID != 0"
+#endif
+#if DATA_TRX_ID != 1
+# error "DATA_TRX_ID != 1"
+#endif
+#if DATA_ROLL_PTR != 2
+# error "DATA_ROLL_PTR != 2"
+#endif
 
 		if (!(index->type & DICT_UNIQUE)) {
 			dict_index_add_col(new_index,
-			   dict_table_get_sys_col(table, DATA_ROW_ID), 0, 0);
+			   dict_table_get_sys_col(table, DATA_ROW_ID), 0);
 			trx_id_pos++;
 		}
 
 		dict_index_add_col(new_index,
-			   dict_table_get_sys_col(table, DATA_TRX_ID), 0, 0);
-	
+			   dict_table_get_sys_col(table, DATA_TRX_ID), 0);
+
 		dict_index_add_col(new_index,
-			   dict_table_get_sys_col(table, DATA_ROLL_PTR), 0, 0);
+			   dict_table_get_sys_col(table, DATA_ROLL_PTR), 0);
 
 		for (i = 0; i < trx_id_pos; i++) {
 
@@ -1859,7 +1855,7 @@
 			}
 
 			if (dict_index_get_nth_field(new_index, i)->prefix_len
-			    > 0) {
+				> 0) {
 				new_index->trx_id_offset = 0;
 
 				break;
@@ -1887,10 +1883,10 @@
 
 		if (field->prefix_len == 0) {
 
-		        field->col->aux = 0;
+			field->col->aux = 0;
 		}
 	}
-	
+
 	/* Add to new_index non-system columns of table not yet included
 	there */
 	for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) {
@@ -1899,7 +1895,7 @@
 		ut_ad(col->type.mtype != DATA_SYS);
 
 		if (col->aux == ULINT_UNDEFINED) {
-			dict_index_add_col(new_index, col, 0, 0);
+			dict_index_add_col(new_index, col, 0);
 		}
 	}
 
@@ -1914,14 +1910,14 @@
 
 		if (field->prefix_len == 0) {
 
-		        field->col->clust_pos = i;
+			field->col->clust_pos = i;
 		}
 	}
-	
+
 	new_index->cached = TRUE;
 
 	return(new_index);
-}	
+}
 
 /***********************************************************************
 Builds the internal dictionary cache representation for a non-clustered
@@ -1934,7 +1930,7 @@
 				of the non-clustered index */
 	dict_table_t*	table,	/* in: table */
 	dict_index_t*	index)	/* in: user representation of a non-clustered
-				index */	
+				index */
 {
 	dict_field_t*	field;
 	dict_index_t*	new_index;
@@ -1950,24 +1946,21 @@
 
 	/* The clustered index should be the first in the list of indexes */
 	clust_index = UT_LIST_GET_FIRST(table->indexes);
-	
+
 	ut_ad(clust_index);
 	ut_ad(clust_index->type & DICT_CLUSTERED);
 	ut_ad(!(clust_index->type & DICT_UNIVERSAL));
 
 	/* Create a new index */
 	new_index = dict_mem_index_create(table->name,
-				     index->name,
-				     index->space,
-				     index->type,
-				     index->n_fields
-				     + 1 + clust_index->n_uniq);
+		index->name, index->space, index->type,
+		index->n_fields	+ 1 + clust_index->n_uniq);
 
 	/* Copy other relevant data from the old index
 	struct to the new struct: it inherits the values */
 
 	new_index->n_user_defined_cols = index->n_fields;
-	
+
 	new_index->id = index->id;
 
 	/* Copy fields from index to new_index */
@@ -1991,7 +1984,7 @@
 
 		if (field->prefix_len == 0) {
 
-		        field->col->aux = 0;
+			field->col->aux = 0;
 		}
 	}
 
@@ -2003,8 +1996,8 @@
 		field = dict_index_get_nth_field(clust_index, i);
 
 		if (field->col->aux == ULINT_UNDEFINED) {
-			dict_index_add_col(new_index, field->col, 0,
-						      field->prefix_len);
+			dict_index_add_col(new_index, field->col,
+				field->prefix_len);
 		}
 	}
 
@@ -2022,7 +2015,7 @@
 	new_index->cached = TRUE;
 
 	return(new_index);
-}	
+}
 
 /*====================== FOREIGN KEY PROCESSING ========================*/
 
@@ -2037,7 +2030,7 @@
 	dict_table_t*	table)	/* in: InnoDB table */
 {
 	if (UT_LIST_GET_LEN(table->referenced_list) > 0) {
-		
+
 		return(TRUE);
 	}
 
@@ -2067,7 +2060,7 @@
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_a(foreign);
-	
+
 	if (foreign->referenced_table) {
 		UT_LIST_REMOVE(referenced_list,
 			foreign->referenced_table->referenced_list, foreign);
@@ -2108,7 +2101,7 @@
 
 		foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
 	}
-	
+
 	foreign = UT_LIST_GET_FIRST(table->referenced_list);
 
 	while (foreign) {
@@ -2121,8 +2114,9 @@
 	}
 
 	return(NULL);
-}	
+}
 
+#ifndef UNIV_HOTBACKUP
 /*************************************************************************
 Tries to find an index whose first fields are the columns in the array,
 in the same order. */
@@ -2140,11 +2134,10 @@
 					only has an effect if types_idx !=
 					NULL. */
 {
-#ifndef UNIV_HOTBACKUP
 	dict_index_t*	index;
 	const char*	col_name;
 	ulint		i;
-	
+
 	index = dict_table_get_first_index(table);
 
 	while (index != NULL) {
@@ -2157,22 +2150,22 @@
 						->prefix_len != 0) {
 					/* We do not accept column prefix
 					indexes here */
-					
+
 					break;
 				}
 
 				if (0 != innobase_strcasecmp(columns[i],
 								col_name)) {
-				  	break;
+					break;
 				}
 
 				if (types_idx && !cmp_types_are_equal(
-				     dict_index_get_nth_type(index, i),
-				     dict_index_get_nth_type(types_idx, i),
-				     check_charsets)) {
+					    dict_index_get_nth_type(index, i),
+					    dict_index_get_nth_type(types_idx, i),
+					    check_charsets)) {
 
-				  	break;
-				}		
+					break;
+				}
 			}
 
 			if (i == n_cols) {
@@ -2186,12 +2179,6 @@
 	}
 
 	return(NULL);
-#else /* UNIV_HOTBACKUP */
-	/* This function depends on MySQL code that is not included in
-	InnoDB Hot Backup builds.  Besides, this function should never
-	be called in InnoDB Hot Backup. */
-	ut_error;
-#endif /* UNIV_HOTBACKUP */
 }
 
 /**************************************************************************
@@ -2227,7 +2214,7 @@
 	putc('\n', file);
 	if (fk->foreign_index) {
 		fputs("The index in the foreign key in table is ", file);
-		ut_print_name(file, NULL, fk->foreign_index->name);
+		ut_print_name(file, NULL, FALSE, fk->foreign_index->name);
 		fputs("\n"
 "See http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html\n"
 "for correct foreign key definition.\n",
@@ -2255,7 +2242,7 @@
 	dict_foreign_t*	for_in_cache		= NULL;
 	dict_index_t*	index;
 	ibool		added_to_referenced_list= FALSE;
-	FILE*		ef 			= dict_foreign_err_file;
+	FILE*		ef			= dict_foreign_err_file;
 
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -2263,7 +2250,7 @@
 
 	for_table = dict_table_check_if_in_cache_low(
 					foreign->foreign_table_name);
-	
+
 	ref_table = dict_table_check_if_in_cache_low(
 					foreign->referenced_table_name);
 	ut_a(for_table || ref_table);
@@ -2299,7 +2286,7 @@
 				mem_heap_free(foreign->heap);
 			}
 
-		    	return(DB_CANNOT_ADD_CONSTRAINT);
+			return(DB_CANNOT_ADD_CONSTRAINT);
 		}
 
 		for_in_cache->referenced_table = ref_table;
@@ -2328,11 +2315,11 @@
 						ref_table->referenced_list,
 						for_in_cache);
 				}
-			
+
 				mem_heap_free(foreign->heap);
 			}
 
-		    	return(DB_CANNOT_ADD_CONSTRAINT);
+			return(DB_CANNOT_ADD_CONSTRAINT);
 		}
 
 		for_in_cache->foreign_table = for_table;
@@ -2390,12 +2377,13 @@
 
 /*************************************************************************
 Accepts a specified string. Comparisons are case-insensitive. */
-
+static
 const char*
 dict_accept(
 /*========*/
 				/* out: if string was accepted, the pointer
 				is moved after that, else ptr is returned */
+	struct charset_info_st*	cs,/* in: the character set of ptr */
 	const char*	ptr,	/* in: scan from this */
 	const char*	string,	/* in: accept only this string as the next
 				non-whitespace string */
@@ -2405,15 +2393,15 @@
 	const char*	old_ptr2;
 
 	*success = FALSE;
-	
-	while (isspace(*ptr)) {
+
+	while (my_isspace(cs, *ptr)) {
 		ptr++;
 	}
 
 	old_ptr2 = ptr;
-	
+
 	ptr = dict_scan_to(ptr, string);
-	
+
 	if (*ptr == '\0' || old_ptr2 != ptr) {
 		return(old_ptr);
 	}
@@ -2431,12 +2419,15 @@
 dict_scan_id(
 /*=========*/
 				/* out: scanned to */
+	struct charset_info_st*	cs,/* in: the character set of ptr */
 	const char*	ptr,	/* in: scanned to */
 	mem_heap_t*	heap,	/* in: heap where to allocate the id
 				(NULL=id will not be allocated, but it
 				will point to string near ptr) */
 	const char**	id,	/* out,own: the id; NULL if no id was
 				scannable */
+	ibool		table_id,/* in: TRUE=convert the allocated id
+				as a table name; FALSE=convert to UTF-8 */
 	ibool		accept_also_dot)
 				/* in: TRUE if also a dot can appear in a
 				non-quoted id; in a quoted id it can appear
@@ -2445,13 +2436,12 @@
 	char		quote	= '\0';
 	ulint		len	= 0;
 	const char*	s;
-	char*		d;
-	ulint		id_len;
-	byte*		b;
+	char*		str;
+	char*		dst;
 
 	*id = NULL;
 
-	while (isspace(*ptr)) {
+	while (my_isspace(cs, *ptr)) {
 		ptr++;
 	}
 
@@ -2482,9 +2472,9 @@
 			len++;
 		}
 	} else {
-		while (!isspace(*ptr) && *ptr != '(' && *ptr != ')'
-		       && (accept_also_dot || *ptr != '.')
-		       && *ptr != ',' && *ptr != '\0') {
+		while (!my_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')'
+			&& (accept_also_dot || *ptr != '.')
+			&& *ptr != ',' && *ptr != '\0') {
 
 			ptr++;
 		}
@@ -2492,43 +2482,50 @@
 		len = ptr - s;
 	}
 
-	if (quote && heap) {
-		*id = d = mem_heap_alloc(heap, len + 1);
+	if (UNIV_UNLIKELY(!heap)) {
+		/* no heap given: id will point to source string */
+		*id = s;
+		return(ptr);
+	}
+
+	if (quote) {
+		char*	d;
+		str = d = mem_heap_alloc(heap, len + 1);
 		while (len--) {
 			if ((*d++ = *s++) == quote) {
 				s++;
 			}
 		}
 		*d++ = 0;
-		ut_a(*s == quote);
-		ut_a(s + 1 == ptr);
-	} else if (heap) {
-		*id = mem_heap_strdupl(heap, s, len);
+		len = d - str;
+		ut_ad(*s == quote);
+		ut_ad(s + 1 == ptr);
 	} else {
-		/* no heap given: id will point to source string */
-		*id = s;
+		str = mem_heap_strdupl(heap, s, len);
 	}
 
-	if (heap && !quote) {
-		/* EMS MySQL Manager sometimes adds characters 0xA0 (in
-		latin1, a 'non-breakable space') to the end of a table name.
-		But isspace(0xA0) is not true, which confuses our foreign key
-		parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2
-		and 0xA0 are at the end of the string.
-
-		TODO: we should lex the string using thd->charset_info, and
-		my_isspace(). Only after that, convert id names to UTF-8. */
-
-		b = (byte*)(*id);
-		id_len = strlen((char*) b);
-		
-		if (id_len >= 3 && b[id_len - 1] == 0xA0
-			       && b[id_len - 2] == 0xC2) {
-
-			/* Strip the 2 last bytes */
+	if (!table_id) {
+convert_id:
+		/* Convert the identifier from connection character set
+		to UTF-8. */
+		len = 3 * len + 1;
+		*id = dst = mem_heap_alloc(heap, len);
+
+		innobase_convert_from_id(dst, str, len);
+	} else if (!strncmp(str, srv_mysql50_table_name_prefix,
+				sizeof srv_mysql50_table_name_prefix)) {
+		/* This is a pre-5.1 table name
+		containing chars other than [A-Za-z0-9].
+		Discard the prefix and use raw UTF-8 encoding. */
+		str += sizeof srv_mysql50_table_name_prefix;
+		len -= sizeof srv_mysql50_table_name_prefix;
+		goto convert_id;
+	} else {
+		/* Encode using filename-safe characters. */
+		len = 5 * len + 1;
+		*id = dst = mem_heap_alloc(heap, len);
 
-			b[id_len - 2] = '\0';
-		}
+		innobase_convert_from_table_id(dst, str, len);
 	}
 
 	return(ptr);
@@ -2541,6 +2538,7 @@
 dict_scan_col(
 /*==========*/
 				/* out: scanned to */
+	struct charset_info_st*	cs,/* in: the character set of ptr */
 	const char*	ptr,	/* in: scanned to */
 	ibool*		success,/* out: TRUE if success */
 	dict_table_t*	table,	/* in: table in which the column is */
@@ -2549,13 +2547,12 @@
 	const char**	name)	/* out,own: the column name; NULL if no name
 				was scannable */
 {
-#ifndef UNIV_HOTBACKUP
 	dict_col_t*	col;
 	ulint		i;
 
 	*success = FALSE;
 
-	ptr = dict_scan_id(ptr, heap, name, TRUE);
+	ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE);
 
 	if (*name == NULL) {
 
@@ -2566,29 +2563,23 @@
 		*success = TRUE;
 		*column = NULL;
 	} else {
-	    	for (i = 0; i < dict_table_get_n_cols(table); i++) {
+		for (i = 0; i < dict_table_get_n_cols(table); i++) {
 
 			col = dict_table_get_nth_col(table, i);
 
 			if (0 == innobase_strcasecmp(col->name, *name)) {
-		    		/* Found */
+				/* Found */
 
-		    		*success = TRUE;
-		    		*column = col;
-		    		strcpy((char*) *name, col->name);
+				*success = TRUE;
+				*column = col;
+				strcpy((char*) *name, col->name);
 
-		    		break;
+				break;
 			}
 		}
 	}
-	
+
 	return(ptr);
-#else /* UNIV_HOTBACKUP */
-	/* This function depends on MySQL code that is not included in
-	InnoDB Hot Backup builds.  Besides, this function should never
-	be called in InnoDB Hot Backup. */
-	ut_error;
-#endif /* UNIV_HOTBACKUP */
 }
 
 /*************************************************************************
@@ -2598,6 +2589,7 @@
 dict_scan_table_name(
 /*=================*/
 				/* out: scanned to */
+	struct charset_info_st*	cs,/* in: the character set of ptr */
 	const char*	ptr,	/* in: scanned to */
 	dict_table_t**	table,	/* out: table object or NULL */
 	const char*	name,	/* in: foreign key table name */
@@ -2606,7 +2598,6 @@
 	const char**	ref_name)/* out,own: the table name;
 				NULL if no name was scannable */
 {
-#ifndef UNIV_HOTBACKUP
 	const char*	database_name	= NULL;
 	ulint		database_name_len = 0;
 	const char*	table_name	= NULL;
@@ -2616,11 +2607,11 @@
 
 	*success = FALSE;
 	*table = NULL;
-	
-	ptr = dict_scan_id(ptr, heap, &scan_name, FALSE);	
+
+	ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE);
 
 	if (scan_name == NULL) {
-		
+
 		return(ptr);	/* Syntax error */
 	}
 
@@ -2632,7 +2623,7 @@
 		database_name = scan_name;
 		database_name_len = strlen(database_name);
 
-		ptr = dict_scan_id(ptr, heap, &table_name, FALSE);
+		ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE);
 
 		if (table_name == NULL) {
 
@@ -2688,12 +2679,6 @@
 	*table = dict_table_get_low(ref);
 
 	return(ptr);
-#else /* UNIV_HOTBACKUP */
-	/* This function depends on MySQL code that is not included in
-	InnoDB Hot Backup builds.  Besides, this function should never
-	be called in InnoDB Hot Backup. */
-	ut_error;
-#endif /* UNIV_HOTBACKUP */
 }
 
 /*************************************************************************
@@ -2703,20 +2688,21 @@
 dict_skip_word(
 /*===========*/
 				/* out: scanned to */
+	struct charset_info_st*	cs,/* in: the character set of ptr */
 	const char*	ptr,	/* in: scanned to */
 	ibool*		success)/* out: TRUE if success, FALSE if just spaces
 				left in string or a syntax error */
 {
 	const char*	start;
-	
+
 	*success = FALSE;
 
-	ptr = dict_scan_id(ptr, NULL, &start, TRUE);
+	ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE);
 
 	if (start) {
 		*success = TRUE;
 	}
-	
+
 	return(ptr);
 }
 
@@ -2738,8 +2724,8 @@
 	char*		str;
 	const char*	sptr;
 	char*		ptr;
- 	/* unclosed quote character (0 if none) */
- 	char		quote	= 0;
+	/* unclosed quote character (0 if none) */
+	char		quote	= 0;
 
 	str = mem_alloc(strlen(sql_string) + 1);
 
@@ -2767,15 +2753,15 @@
 			/* Starting quote: remember the quote character. */
 			quote = *sptr;
 		} else if (*sptr == '#'
-                           || (sptr[0] == '-' && sptr[1] == '-' &&
-                               sptr[2] == ' ')) {
+			|| (sptr[0] == '-' && sptr[1] == '-' &&
+				sptr[2] == ' ')) {
 			for (;;) {
 				/* In Unix a newline is 0x0A while in Windows
 				it is 0x0D followed by 0x0A */
 
 				if (*sptr == (char)0x0A
-				    || *sptr == (char)0x0D
-				    || *sptr == '\0') {
+					|| *sptr == (char)0x0D
+					|| *sptr == '\0') {
 
 					goto scan_more;
 				}
@@ -2786,7 +2772,7 @@
 			for (;;) {
 				if (*sptr == '*' && *(sptr + 1) == '/') {
 
-				     	sptr += 2;
+					sptr += 2;
 
 					goto scan_more;
 				}
@@ -2832,10 +2818,10 @@
 
 	while (foreign) {
 		if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
-		    && 0 == ut_memcmp(foreign->id, table->name, len)
-		    && 0 == ut_memcmp(foreign->id + len,
+			&& 0 == ut_memcmp(foreign->id, table->name, len)
+			&& 0 == ut_memcmp(foreign->id + len,
 				dict_ibfk, (sizeof dict_ibfk) - 1)
-		    && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
+			&& foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
 			/* It is of the >= 4.0.18 format */
 
 			id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),
@@ -2889,6 +2875,7 @@
 				/* out: error code or DB_SUCCESS */
 	trx_t*		trx,	/* in: transaction */
 	mem_heap_t*	heap,	/* in: memory heap */
+	struct charset_info_st*	cs,/* in: the character set of sql_string */
 	const char*	sql_string,
 				/* in: CREATE TABLE or ALTER TABLE statement
 				where foreign keys are declared like:
@@ -2909,7 +2896,7 @@
 	ulint		highest_id_so_far	= 0;
 	dict_index_t*	index;
 	dict_foreign_t*	foreign;
- 	const char*	ptr			= sql_string;
+	const char*	ptr			= sql_string;
 	const char*	start_of_latest_foreign	= sql_string;
 	FILE*		ef			= dict_foreign_err_file;
 	const char*	constraint_name;
@@ -2925,7 +2912,7 @@
 	dict_col_t*	columns[500];
 	const char*	column_names[500];
 	const char*	referenced_table_name;
-	
+
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
@@ -2946,14 +2933,14 @@
 	/* First check if we are actually doing an ALTER TABLE, and in that
 	case look for the table being altered */
 
-	ptr = dict_accept(ptr, "ALTER", &success);
+	ptr = dict_accept(cs, ptr, "ALTER", &success);
 
 	if (!success) {
 
 		goto loop;
 	}
 
-	ptr = dict_accept(ptr, "TABLE", &success);
+	ptr = dict_accept(cs, ptr, "TABLE", &success);
 
 	if (!success) {
 
@@ -2962,7 +2949,7 @@
 
 	/* We are doing an ALTER TABLE: scan the table name we are altering */
 
-	ptr = dict_scan_table_name(ptr, &table_to_alter, name,
+	ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
 				&success, heap, &referenced_table_name);
 	if (!success) {
 		fprintf(stderr,
@@ -3002,21 +2989,22 @@
 		of the constraint to system tables. */
 		ptr = ptr1;
 
-		ptr = dict_accept(ptr, "CONSTRAINT", &success);
+		ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
 
 		ut_a(success);
 
-		if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') {
-	        	goto loop;
+		if (!my_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') {
+			goto loop;
 		}
 
-		while (isspace(*ptr)) {
+		while (my_isspace(cs, *ptr)) {
 			ptr++;
 		}
 
 		/* read constraint name unless got "CONSTRAINT FOREIGN" */
 		if (ptr != ptr2) {
-			ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE);
+			ptr = dict_scan_id(cs, ptr, heap,
+					&constraint_name, FALSE, FALSE);
 		}
 	} else {
 		ptr = ptr2;
@@ -3030,15 +3018,15 @@
 		   command, determine if there are any foreign keys, and
 		   if so, immediately reject the command if the table is a
 		   temporary one. For now, this kludge will work. */
-		if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0))
-		{
-			return DB_CANNOT_ADD_CONSTRAINT;
+		if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
+
+			return(DB_CANNOT_ADD_CONSTRAINT);
 		}
-		
+
 		/**********************************************************/
 		/* The following call adds the foreign key constraints
 		to the data dictionary system tables on disk */
-		
+
 		error = dict_create_add_foreigns_to_dictionary(
 						highest_id_so_far, table, trx);
 		return(error);
@@ -3046,28 +3034,28 @@
 
 	start_of_latest_foreign = ptr;
 
-	ptr = dict_accept(ptr, "FOREIGN", &success);		
-	
+	ptr = dict_accept(cs, ptr, "FOREIGN", &success);
+
 	if (!success) {
 		goto loop;
 	}
 
-	if (!isspace(*ptr)) {
-	        goto loop;
+	if (!my_isspace(cs, *ptr)) {
+		goto loop;
 	}
 
-	ptr = dict_accept(ptr, "KEY", &success);
+	ptr = dict_accept(cs, ptr, "KEY", &success);
 
 	if (!success) {
 		goto loop;
 	}
 
-	ptr = dict_accept(ptr, "(", &success);
+	ptr = dict_accept(cs, ptr, "(", &success);
 
 	if (!success) {
 		/* MySQL allows also an index id before the '('; we
 		skip it */
-		ptr = dict_skip_word(ptr, &success);
+		ptr = dict_skip_word(cs, ptr, &success);
 
 		if (!success) {
 			dict_foreign_report_syntax_err(name,
@@ -3076,13 +3064,13 @@
 			return(DB_CANNOT_ADD_CONSTRAINT);
 		}
 
-		ptr = dict_accept(ptr, "(", &success);
+		ptr = dict_accept(cs, ptr, "(", &success);
 
 		if (!success) {
 			/* We do not flag a syntax error here because in an
 			ALTER TABLE we may also have DROP FOREIGN KEY abc */
 
-		        goto loop;
+			goto loop;
 		}
 	}
 
@@ -3091,7 +3079,7 @@
 	/* Scan the columns in the first list */
 col_loop1:
 	ut_a(i < (sizeof column_names) / sizeof *column_names);
-	ptr = dict_scan_col(ptr, &success, table, columns + i,
+	ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
 				heap, column_names + i);
 	if (!success) {
 		mutex_enter(&dict_foreign_err_mutex);
@@ -3104,14 +3092,14 @@
 	}
 
 	i++;
-	
-	ptr = dict_accept(ptr, ",", &success);
+
+	ptr = dict_accept(cs, ptr, ",", &success);
 
 	if (success) {
 		goto col_loop1;
 	}
-	
-	ptr = dict_accept(ptr, ")", &success);
+
+	ptr = dict_accept(cs, ptr, ")", &success);
 
 	if (!success) {
 		dict_foreign_report_syntax_err(name, start_of_latest_foreign,
@@ -3128,7 +3116,7 @@
 		mutex_enter(&dict_foreign_err_mutex);
 		dict_foreign_error_report_low(ef, name);
 		fputs("There is no index in table ", ef);
-		ut_print_name(ef, NULL, name);
+		ut_print_name(ef, NULL, TRUE, name);
 		fprintf(ef, " where the columns appear\n"
 "as the first columns. Constraint:\n%s\n"
 "See http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html\n"
@@ -3138,9 +3126,9 @@
 
 		return(DB_CANNOT_ADD_CONSTRAINT);
 	}
-	ptr = dict_accept(ptr, "REFERENCES", &success);
+	ptr = dict_accept(cs, ptr, "REFERENCES", &success);
 
-	if (!success || !isspace(*ptr)) {
+	if (!success || !my_isspace(cs, *ptr)) {
 		dict_foreign_report_syntax_err(name, start_of_latest_foreign,
 									ptr);
 		return(DB_CANNOT_ADD_CONSTRAINT);
@@ -3151,7 +3139,7 @@
 	foreign = dict_mem_foreign_create();
 
 	if (constraint_name) {
-		ulint	db_len;	
+		ulint	db_len;
 
 		/* Catenate 'databasename/' to the constraint name specified
 		by the user: we conceive the constraint as belonging to the
@@ -3179,8 +3167,8 @@
 		foreign->foreign_col_names[i] =
 			mem_heap_strdup(foreign->heap, columns[i]->name);
 	}
-	
-	ptr = dict_scan_table_name(ptr, &referenced_table, name,
+
+	ptr = dict_scan_table_name(cs, ptr, &referenced_table, name,
 				&success, heap, &referenced_table_name);
 
 	/* Note that referenced_table can be NULL if the user has suppressed
@@ -3198,8 +3186,8 @@
 
 		return(DB_CANNOT_ADD_CONSTRAINT);
 	}
-	
-	ptr = dict_accept(ptr, "(", &success);
+
+	ptr = dict_accept(cs, ptr, "(", &success);
 
 	if (!success) {
 		dict_foreign_free(foreign);
@@ -3212,10 +3200,10 @@
 	i = 0;
 
 col_loop2:
-	ptr = dict_scan_col(ptr, &success, referenced_table, columns + i,
+	ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
 				heap, column_names + i);
 	i++;
-	
+
 	if (!success) {
 		dict_foreign_free(foreign);
 
@@ -3229,17 +3217,17 @@
 		return(DB_CANNOT_ADD_CONSTRAINT);
 	}
 
-	ptr = dict_accept(ptr, ",", &success);
+	ptr = dict_accept(cs, ptr, ",", &success);
 
 	if (success) {
 		goto col_loop2;
 	}
-	
-	ptr = dict_accept(ptr, ")", &success);
+
+	ptr = dict_accept(cs, ptr, ")", &success);
 
 	if (!success || foreign->n_fields != i) {
 		dict_foreign_free(foreign);
-		
+
 		dict_foreign_report_syntax_err(name, start_of_latest_foreign,
 									ptr);
 		return(DB_CANNOT_ADD_CONSTRAINT);
@@ -3247,25 +3235,25 @@
 
 	n_on_deletes = 0;
 	n_on_updates = 0;
-	
+
 scan_on_conditions:
 	/* Loop here as long as we can find ON ... conditions */
 
-	ptr = dict_accept(ptr, "ON", &success);
+	ptr = dict_accept(cs, ptr, "ON", &success);
 
 	if (!success) {
 
 		goto try_find_index;
 	}
 
-	ptr = dict_accept(ptr, "DELETE", &success);
+	ptr = dict_accept(cs, ptr, "DELETE", &success);
 
 	if (!success) {
-		ptr = dict_accept(ptr, "UPDATE", &success);
+		ptr = dict_accept(cs, ptr, "UPDATE", &success);
 
 		if (!success) {
 			dict_foreign_free(foreign);
-		
+
 			dict_foreign_report_syntax_err(name,
 						start_of_latest_foreign, ptr);
 			return(DB_CANNOT_ADD_CONSTRAINT);
@@ -3278,13 +3266,13 @@
 		n_on_deletes++;
 	}
 
-	ptr = dict_accept(ptr, "RESTRICT", &success);
+	ptr = dict_accept(cs, ptr, "RESTRICT", &success);
 
 	if (success) {
 		goto scan_on_conditions;
 	}
 
-	ptr = dict_accept(ptr, "CASCADE", &success);
+	ptr = dict_accept(cs, ptr, "CASCADE", &success);
 
 	if (success) {
 		if (is_on_delete) {
@@ -3296,16 +3284,16 @@
 		goto scan_on_conditions;
 	}
 
-	ptr = dict_accept(ptr, "NO", &success);
+	ptr = dict_accept(cs, ptr, "NO", &success);
 
 	if (success) {
-		ptr = dict_accept(ptr, "ACTION", &success);
+		ptr = dict_accept(cs, ptr, "ACTION", &success);
 
 		if (!success) {
 			dict_foreign_free(foreign);
 			dict_foreign_report_syntax_err(name,
 					start_of_latest_foreign, ptr);
-		
+
 			return(DB_CANNOT_ADD_CONSTRAINT);
 		}
 
@@ -3318,7 +3306,7 @@
 		goto scan_on_conditions;
 	}
 
-	ptr = dict_accept(ptr, "SET", &success);
+	ptr = dict_accept(cs, ptr, "SET", &success);
 
 	if (!success) {
 		dict_foreign_free(foreign);
@@ -3327,7 +3315,7 @@
 		return(DB_CANNOT_ADD_CONSTRAINT);
 	}
 
-	ptr = dict_accept(ptr, "NULL", &success);
+	ptr = dict_accept(cs, ptr, "NULL", &success);
 
 	if (!success) {
 		dict_foreign_free(foreign);
@@ -3362,13 +3350,13 @@
 	} else {
 		foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
 	}
-	
+
 	goto scan_on_conditions;
 
 try_find_index:
 	if (n_on_deletes > 1 || n_on_updates > 1) {
 		/* It is an error to define more than 1 action */
-		
+
 		dict_foreign_free(foreign);
 
 		mutex_enter(&dict_foreign_err_mutex);
@@ -3416,7 +3404,7 @@
 
 	foreign->referenced_table_name = mem_heap_strdup(foreign->heap,
 						referenced_table_name);
-					
+
 	foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
 							i * sizeof(void*));
 	for (i = 0; i < foreign->n_fields; i++) {
@@ -3425,7 +3413,7 @@
 	}
 
 	/* We found an ok constraint definition: add to the lists */
-	
+
 	UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
 
 	if (referenced_table) {
@@ -3437,6 +3425,25 @@
 	goto loop;
 }
 
+/**************************************************************************
+Determines whether a string starts with the specified keyword. */
+
+ibool
+dict_str_starts_with_keyword(
+/*=========================*/
+					/* out: TRUE if str starts
+					with keyword */
+	void*		mysql_thd,	/* in: MySQL thread handle */
+	const char*	str,		/* in: string to scan for keyword */
+	const char*	keyword)	/* in: keyword to look for */
+{
+	struct charset_info_st*	cs	= innobase_get_charset(mysql_thd);
+	ibool			success;
+
+	dict_accept(cs, str, keyword, &success);
+	return(success);
+}
+
 /*************************************************************************
 Scans a table create SQL string and adds to the data dictionary the foreign
 key constraints declared in the string. This function should be called after
@@ -3464,20 +3471,23 @@
 					code DB_CANNOT_ADD_CONSTRAINT if
 					any foreign keys are found. */
 {
-	char*		str;
-	ulint		err;
-	mem_heap_t*	heap;
+	char*			str;
+	ulint			err;
+	mem_heap_t*		heap;
+
+	ut_a(trx && trx->mysql_thd);
 
 	str = dict_strip_comments(sql_string);
 	heap = mem_heap_create(10000);
 
-	err = dict_create_foreign_constraints_low(trx, heap, str, name,
-		reject_fks);
+	err = dict_create_foreign_constraints_low(trx, heap,
+			innobase_get_charset(trx->mysql_thd),
+			str, name, reject_fks);
 
 	mem_heap_free(heap);
 	mem_free(str);
 
-	return(err);	
+	return(err);
 }
 
 /**************************************************************************
@@ -3499,13 +3509,18 @@
 	const char***	constraints_to_drop)	/* out: id's of the
 						constraints to drop */
 {
-	dict_foreign_t*	foreign;
-	ibool		success;
-	char*		str;
-	const char*	ptr;
-	const char*	id;
-	FILE*		ef	= dict_foreign_err_file;
-	
+	dict_foreign_t*		foreign;
+	ibool			success;
+	char*			str;
+	const char*		ptr;
+	const char*		id;
+	FILE*			ef	= dict_foreign_err_file;
+	struct charset_info_st*	cs;
+
+	ut_a(trx && trx->mysql_thd);
+
+	cs = innobase_get_charset(trx->mysql_thd);
+
 	*n = 0;
 
 	*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
@@ -3521,32 +3536,32 @@
 
 	if (*ptr == '\0') {
 		mem_free(str);
-		
+
 		return(DB_SUCCESS);
 	}
 
-	ptr = dict_accept(ptr, "DROP", &success);
+	ptr = dict_accept(cs, ptr, "DROP", &success);
 
-	if (!isspace(*ptr)) {
+	if (!my_isspace(cs, *ptr)) {
 
-	        goto loop;
+		goto loop;
 	}
 
-	ptr = dict_accept(ptr, "FOREIGN", &success);
-	
+	ptr = dict_accept(cs, ptr, "FOREIGN", &success);
+
 	if (!success) {
 
-	        goto loop;
+		goto loop;
 	}
 
-	ptr = dict_accept(ptr, "KEY", &success);
+	ptr = dict_accept(cs, ptr, "KEY", &success);
 
 	if (!success) {
 
 		goto syntax_error;
 	}
 
-	ptr = dict_scan_id(ptr, heap, &id, TRUE);
+	ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE);
 
 	if (id == NULL) {
 
@@ -3556,20 +3571,20 @@
 	ut_a(*n < 1000);
 	(*constraints_to_drop)[*n] = id;
 	(*n)++;
-	
+
 	/* Look for the given constraint id */
 
 	foreign = UT_LIST_GET_FIRST(table->foreign_list);
 
 	while (foreign != NULL) {
 		if (0 == strcmp(foreign->id, id)
-		    || (strchr(foreign->id, '/')
-			&& 0 == strcmp(id,
+			|| (strchr(foreign->id, '/')
+				&& 0 == strcmp(id,
 					dict_remove_db_name(foreign->id)))) {
 			/* Found */
 			break;
 		}
-		
+
 		foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
 	}
 
@@ -3579,12 +3594,12 @@
 		ut_print_timestamp(ef);
 		fputs(
 	" Error in dropping of a foreign key constraint of table ", ef);
-		ut_print_name(ef, NULL, table->name);
+		ut_print_name(ef, NULL, TRUE, table->name);
 		fputs(",\n"
 			"in SQL command\n", ef);
 		fputs(str, ef);
 		fputs("\nCannot find a constraint with the given id ", ef);
-		ut_print_name(ef, NULL, id);
+		ut_print_name(ef, NULL, FALSE, id);
 		fputs(".\n", ef);
 		mutex_exit(&dict_foreign_err_mutex);
 
@@ -3593,7 +3608,7 @@
 		return(DB_CANNOT_DROP_CONSTRAINT);
 	}
 
-	goto loop;	
+	goto loop;
 
 syntax_error:
 	mutex_enter(&dict_foreign_err_mutex);
@@ -3601,7 +3616,7 @@
 	ut_print_timestamp(ef);
 	fputs(
 	" Syntax error in dropping of a foreign key constraint of table ", ef);
-	ut_print_name(ef, NULL, table->name);
+	ut_print_name(ef, NULL, TRUE, table->name);
 	fprintf(ef, ",\n"
 		"close to:\n%s\n in SQL command\n%s\n", ptr, str);
 	mutex_exit(&dict_foreign_err_mutex);
@@ -3610,6 +3625,7 @@
 
 	return(DB_CANNOT_DROP_CONSTRAINT);
 }
+#endif /* UNIV_HOTBACKUP */
 
 /*==================== END OF FOREIGN KEY PROCESSING ====================*/
 
@@ -3630,7 +3646,7 @@
 	}
 
 	mutex_enter(&(dict_sys->mutex));
-	
+
 	table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
 
 	while (table) {
@@ -3678,14 +3694,12 @@
 	tree->page = page_no;
 
 	tree->id = index->id;
-	
-	UT_LIST_INIT(tree->tree_indexes);
 
-	tree->magic_n = DICT_TREE_MAGIC_N;
+	tree->tree_index = NULL;
 
-	rw_lock_create(&(tree->lock));
+	tree->magic_n = DICT_TREE_MAGIC_N;
 
-	rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
+	rw_lock_create(&tree->lock, SYNC_INDEX_TREE);
 
 	return(tree);
 }
@@ -3705,135 +3719,7 @@
 	mem_free(tree);
 }
 
-/**************************************************************************
-In an index tree, finds the index corresponding to a record in the tree. */
-UNIV_INLINE
-dict_index_t*
-dict_tree_find_index_low(
-/*=====================*/
-				/* out: index */
-	dict_tree_t*	tree,	/* in: index tree */
-	rec_t*		rec)	/* in: record for which to find correct
-				index */
-{
-	dict_index_t*	index;
-	dict_table_t*	table;
-	dulint		mix_id;
-	ulint		len;
-	
-	index = UT_LIST_GET_FIRST(tree->tree_indexes);
-	ut_ad(index);
-	table = index->table;
-	
-	if ((index->type & DICT_CLUSTERED)
-			&& UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
-
-		/* Get the mix id of the record */
-		ut_a(!table->comp);
-
-		mix_id = mach_dulint_read_compressed(
-			rec_get_nth_field_old(rec, table->mix_len, &len));
-
-		while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
-			index = UT_LIST_GET_NEXT(tree_indexes, index);
-			table = index->table;
-			ut_ad(index);
-		}
-	}
-
-	return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a record in the tree. */
-
-dict_index_t*
-dict_tree_find_index(
-/*=================*/
-				/* out: index */
-	dict_tree_t*	tree,	/* in: index tree */
-	rec_t*		rec)	/* in: record for which to find correct
-				index */
-{
-	dict_index_t*	index;
-	
-	index = dict_tree_find_index_low(tree, rec);
-	
-	return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a dtuple which is used
-in a search to a tree. */
-
-dict_index_t*
-dict_tree_find_index_for_tuple(
-/*===========================*/
-				/* out: index; NULL if the tuple does not
-				contain the mix id field in a mixed tree */
-	dict_tree_t*	tree,	/* in: index tree */
-	dtuple_t*	tuple)	/* in: tuple for which to find index */
-{
-	dict_index_t*	index;
-	dict_table_t*	table;
-	dulint		mix_id;
-
-	ut_ad(dtuple_check_typed(tuple));
-	
-	if (UT_LIST_GET_LEN(tree->tree_indexes) == 1) {
-
-		return(UT_LIST_GET_FIRST(tree->tree_indexes));
-	}
-
-	index = UT_LIST_GET_FIRST(tree->tree_indexes);
-	ut_ad(index);
-	table = index->table;
-
-	if (dtuple_get_n_fields(tuple) <= table->mix_len) {
-
-		return(NULL);
-	}
-
-	/* Get the mix id of the record */
-
-	mix_id = mach_dulint_read_compressed(
-			dfield_get_data(
-				dtuple_get_nth_field(tuple, table->mix_len)));
-
-	while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
-		index = UT_LIST_GET_NEXT(tree_indexes, index);
-		table = index->table;
-		ut_ad(index);
-	}
-
-	return(index);
-}
-
-/***********************************************************************
-Checks if a table which is a mixed cluster member owns a record. */
-
-ibool
-dict_is_mixed_table_rec(
-/*====================*/
-				/* out: TRUE if the record belongs to this
-				table */
-	dict_table_t*	table,	/* in: table in a mixed cluster */
-	rec_t*		rec)	/* in: user record in the clustered index */
-{
-	byte*	mix_id_field;
-	ulint	len;
-
-	ut_ad(!table->comp);
-
-	mix_id_field = rec_get_nth_field_old(rec,
-					table->mix_len, &len);
-
-	return(len == table->mix_id_len
-		&& !ut_memcmp(table->mix_id_buf, mix_id_field, len));
-}
-
+#ifdef UNIV_DEBUG
 /**************************************************************************
 Checks that a tuple has n_fields_cmp value in a sensible range, so that
 no comparison can occur with the page number field in a node pointer. */
@@ -3845,19 +3731,14 @@
 	dict_tree_t*	tree,	/* in: index tree */
 	dtuple_t*	tuple)	/* in: tuple used in a search */
 {
-	dict_index_t*	index;
-
-	index = dict_tree_find_index_for_tuple(tree, tuple);
-
-	if (index == NULL) {
-
-		return(TRUE);
-	}
+	dict_index_t*	index	= tree->tree_index;
 
+	ut_a(index);
 	ut_a(dtuple_get_n_fields_cmp(tuple)
 				<= dict_index_get_n_unique_in_tree(index));
 	return(TRUE);
 }
+#endif /* UNIV_DEBUG */
 
 /**************************************************************************
 Builds a node pointer out of a physical record and a page number. */
@@ -3871,7 +3752,7 @@
 				pointer */
 	ulint		page_no,/* in: page number to put in node pointer */
 	mem_heap_t*	heap,	/* in: memory heap where pointer created */
-	ulint           level)  /* in: level of rec in tree: 0 means leaf
+	ulint		level)	/* in: level of rec in tree: 0 means leaf
 				level */
 {
 	dtuple_t*	tuple;
@@ -3880,22 +3761,22 @@
 	byte*		buf;
 	ulint		n_unique;
 
-	ind = dict_tree_find_index_low(tree, rec);
-	
+	ind = tree->tree_index;
+
 	if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
 		/* In a universal index tree, we take the whole record as
 		the node pointer if the reord is on the leaf level,
 		on non-leaf levels we remove the last field, which
 		contains the page number of the child page */
 
-		ut_a(!ind->table->comp);
+		ut_a(!dict_table_is_comp(ind->table));
 		n_unique = rec_get_n_fields_old(rec);
 
 		if (level > 0) {
-		        ut_a(n_unique > 1);
-		        n_unique--;
+			ut_a(n_unique > 1);
+			n_unique--;
 		}
-	} else {	
+	} else {
 		n_unique = dict_index_get_n_unique_in_tree(ind);
 	}
 
@@ -3906,15 +3787,15 @@
 	levels in the tree there may be identical node pointers with a
 	different page number; therefore, we set the n_fields_cmp to one
 	less: */
-	
+
 	dtuple_set_n_fields_cmp(tuple, n_unique);
 
 	dict_index_copy_types(tuple, ind, n_unique);
-	
+
 	buf = mem_heap_alloc(heap, 4);
 
 	mach_write_to_4(buf, page_no);
-	
+
 	field = dtuple_get_nth_field(tuple, n_unique);
 	dfield_set_data(field, buf, 4);
 
@@ -3927,8 +3808,8 @@
 	ut_ad(dtuple_check_typed(tuple));
 
 	return(tuple);
-}	
-	
+}
+
 /**************************************************************************
 Copies an initial segment of a physical record, long enough to specify an
 index entry uniquely. */
@@ -3948,10 +3829,10 @@
 	ulint		n;
 
 	UNIV_PREFETCH_R(rec);
-	index = dict_tree_find_index_low(tree, rec);
+	index = tree->tree_index;
 
 	if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
-		ut_a(!index->table->comp);
+		ut_a(!dict_table_is_comp(index->table));
 		n = rec_get_n_fields_old(rec);
 	} else {
 		n = dict_index_get_n_unique_in_tree(index);
@@ -3976,11 +3857,12 @@
 	dtuple_t*	tuple;
 	dict_index_t*	ind;
 
-	ind = dict_tree_find_index_low(tree, rec);
+	ind = tree->tree_index;
+
+	ut_ad(dict_table_is_comp(ind->table)
+		|| n_fields <= rec_get_n_fields_old(rec));
 
-	ut_ad(ind->table->comp || n_fields <= rec_get_n_fields_old(rec));
-	
-	tuple = dtuple_create(heap, n_fields); 
+	tuple = dtuple_create(heap, n_fields);
 
 	dict_index_copy_types(tuple, ind, n_fields);
 
@@ -3989,8 +3871,8 @@
 	ut_ad(dtuple_check_typed(tuple));
 
 	return(tuple);
-}	
-	
+}
+
 /*************************************************************************
 Calculates the minimum record length in an index. */
 
@@ -4002,7 +3884,7 @@
 	ulint	sum	= 0;
 	ulint	i;
 
-	if (UNIV_LIKELY(index->table->comp)) {
+	if (dict_table_is_comp(index->table)) {
 		ulint nullable = 0;
 		sum = REC_N_NEW_EXTRA_BYTES;
 		for (i = 0; i < dict_index_get_n_fields(index); i++) {
@@ -4047,8 +3929,8 @@
 /*=======================*/
 	dict_table_t*	table,		/* in: table */
 	ibool		has_dict_mutex __attribute__((unused)))
-                                        /* in: TRUE if the caller has the
-					dictionary mutex */	
+					/* in: TRUE if the caller has the
+					dictionary mutex */
 {
 	dict_index_t*	index;
 	ulint		size;
@@ -4076,11 +3958,11 @@
 	/* Find out the sizes of the indexes and how many different values
 	for the key they approximately have */
 
-	index = dict_table_get_first_index(table);	
+	index = dict_table_get_first_index(table);
 
 	if (index == NULL) {
 		/* Table definition is corrupt */
-	
+
 		return;
 	}
 
@@ -4099,7 +3981,7 @@
 		}
 
 		index->stat_n_leaf_pages = size;
-		
+
 		btr_estimate_number_of_different_key_vals(index);
 
 		index = dict_table_get_next_index(index);
@@ -4117,7 +3999,7 @@
 
 	table->stat_initialized = TRUE;
 
-        table->stat_modified_counter = 0;
+	table->stat_modified_counter = 0;
 }
 
 /*************************************************************************
@@ -4133,6 +4015,18 @@
 }
 
 /**************************************************************************
+A noninlined version of dict_table_get_low. */
+
+dict_table_t*
+dict_table_get_low_noninlined(
+/*==========================*/
+					/* out: table, NULL if not found */
+	const char*	table_name)	/* in: table name */
+{
+	return(dict_table_get_low(table_name));
+}
+
+/**************************************************************************
 Prints info of a foreign key constraint. */
 static
 void
@@ -4156,7 +4050,7 @@
 	fprintf(stderr, " )\n"
 		"             REFERENCES %s (",
 		foreign->referenced_table_name);
-	
+
 	for (i = 0; i < foreign->n_fields; i++) {
 		fprintf(stderr, " %s", foreign->referenced_col_names[i]);
 	}
@@ -4192,7 +4086,7 @@
 	table = dict_table_get_low(name);
 
 	ut_a(table);
-	
+
 	dict_table_print_low(table);
 	mutex_exit(&(dict_sys->mutex));
 }
@@ -4214,7 +4108,7 @@
 #endif /* UNIV_SYNC_DEBUG */
 
 	dict_update_statistics_low(table, TRUE);
-	
+
 	fprintf(stderr,
 "--------------------------------------\n"
 "TABLE: name %s, id %lu %lu, columns %lu, indexes %lu, appr.rows %lu\n"
@@ -4223,7 +4117,7 @@
 			(ulong) ut_dulint_get_high(table->id),
 			(ulong) ut_dulint_get_low(table->id),
 			(ulong) table->n_cols,
-		        (ulong) UT_LIST_GET_LEN(table->indexes),
+			(ulong) UT_LIST_GET_LEN(table->indexes),
 			(ulong) table->stat_n_rows);
 
 	for (i = 0; i < table->n_cols - 1; i++) {
@@ -4301,7 +4195,7 @@
 	}
 
 	fprintf(stderr,
-		"  INDEX: name %s, id %lu %lu, fields %lu/%lu, type %lu\n"
+		"  INDEX: name %s, id %lu %lu, fields %lu/%lu, uniq %lu, type %lu\n"
 		"   root page %lu, appr.key vals %lu,"
 		" leaf pages %lu, size pages %lu\n"
 		"   FIELDS: ",
@@ -4309,12 +4203,14 @@
 		(ulong) ut_dulint_get_high(tree->id),
 		(ulong) ut_dulint_get_low(tree->id),
 		(ulong) index->n_user_defined_cols,
-		(ulong) index->n_fields, (ulong) index->type,
+		(ulong) index->n_fields,
+		(ulong) index->n_uniq,
+		(ulong) index->type,
 		(ulong) tree->page,
 		(ulong) n_vals,
 		(ulong) index->stat_n_leaf_pages,
 		(ulong) index->stat_index_size);
-			
+
 	for (i = 0; i < index->n_fields; i++) {
 		dict_field_print_low(dict_index_get_nth_field(index, i));
 	}
@@ -4360,7 +4256,7 @@
 {
 	const char*	stripped_id;
 	ulint	i;
-	
+
 	if (strchr(foreign->id, '/')) {
 		/* Strip the preceding database name from the constraint id */
 		stripped_id = foreign->id + 1
@@ -4370,23 +4266,23 @@
 	}
 
 	putc(',', file);
-	
+
 	if (add_newline) {
 		/* SHOW CREATE TABLE wants constraints each printed nicely
 		on its own line, while error messages want no newlines
 		inserted. */
 		fputs("\n ", file);
 	}
-	
+
 	fputs(" CONSTRAINT ", file);
-	ut_print_name(file, trx, stripped_id);
+	ut_print_name(file, trx, FALSE, stripped_id);
 	fputs(" FOREIGN KEY (", file);
 
 	for (i = 0;;) {
-		ut_print_name(file, trx, foreign->foreign_col_names[i]);
+		ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]);
 		if (++i < foreign->n_fields) {
 			fputs(", ", file);
-	        } else {
+		} else {
 			break;
 		}
 	}
@@ -4396,7 +4292,7 @@
 	if (dict_tables_have_same_db(foreign->foreign_table_name,
 					foreign->referenced_table_name)) {
 		/* Do not print the database name of the referenced table */
-		ut_print_name(file, trx, dict_remove_db_name(
+		ut_print_name(file, trx, TRUE, dict_remove_db_name(
 					foreign->referenced_table_name));
 	} else {
 		/* Look for the '/' in the table name */
@@ -4406,9 +4302,10 @@
 			i++;
 		}
 
-		ut_print_namel(file, trx, foreign->referenced_table_name, i);
+		ut_print_namel(file, trx, TRUE,
+				foreign->referenced_table_name, i);
 		putc('.', file);
-		ut_print_name(file, trx,
+		ut_print_name(file, trx, TRUE,
 				foreign->referenced_table_name + i + 1);
 	}
 
@@ -4416,7 +4313,8 @@
 	putc('(', file);
 
 	for (i = 0;;) {
-		ut_print_name(file, trx, foreign->referenced_col_names[i]);
+		ut_print_name(file, trx, FALSE,
+				foreign->referenced_col_names[i]);
 		if (++i < foreign->n_fields) {
 			fputs(", ", file);
 		} else {
@@ -4429,7 +4327,7 @@
 	if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
 		fputs(" ON DELETE CASCADE", file);
 	}
-	
+
 	if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
 		fputs(" ON DELETE SET NULL", file);
 	}
@@ -4441,7 +4339,7 @@
 	if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
 		fputs(" ON UPDATE CASCADE", file);
 	}
-	
+
 	if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
 		fputs(" ON UPDATE SET NULL", file);
 	}
@@ -4490,12 +4388,12 @@
 					putc(' ', file);
 				}
 
-				ut_print_name(file, trx,
+				ut_print_name(file, trx, FALSE,
 					foreign->foreign_col_names[i]);
 			}
 
 			fputs(") REFER ", file);
-			ut_print_name(file, trx,
+			ut_print_name(file, trx, TRUE,
 					foreign->referenced_table_name);
 			putc('(', file);
 
@@ -4503,7 +4401,7 @@
 				if (i) {
 					putc(' ', file);
 				}
-				ut_print_name(file, trx,
+				ut_print_name(file, trx, FALSE,
 					foreign->referenced_col_names[i]);
 			}
 
@@ -4512,7 +4410,7 @@
 			if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
 				fputs(" ON DELETE CASCADE", file);
 			}
-	
+
 			if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
 				fputs(" ON DELETE SET NULL", file);
 			}
@@ -4524,7 +4422,7 @@
 			if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
 				fputs(" ON UPDATE CASCADE", file);
 			}
-	
+
 			if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
 				fputs(" ON UPDATE SET NULL", file);
 			}
@@ -4550,7 +4448,7 @@
 	const dict_index_t*	index)	/* in: index to print */
 {
 	fputs("index ", file);
-	ut_print_name(file, trx, index->name);
+	ut_print_name(file, trx, FALSE, index->name);
 	fputs(" of table ", file);
-	ut_print_name(file, trx, index->table_name);
+	ut_print_name(file, trx, TRUE, index->table_name);
 }

--- 1.54.11.1/innobase/fil/fil0fil.c	2006-08-29 18:58:59 +04:00
+++ 1.66/storage/innobase/fil/fil0fil.c	2006-08-29 18:58:59 +04:00
@@ -27,7 +27,7 @@
 #include "mtr0log.h"
 #include "dict0dict.h"
 
-	 
+
 /*
 		IMPLEMENTATION OF THE TABLESPACE MEMORY CACHE
 		=============================================
@@ -69,7 +69,7 @@
 certainly prevents the OS from fragmenting disk space, but it is not clear
 if it really adds speed. We measured on the Pentium 100 MHz + NT + NTFS file
 system + EIDE Conner disk only a negligible difference in speed when reading
-from a file, versus reading from a raw disk. 
+from a file, versus reading from a raw disk.
 
 To have fast access to a tablespace or a log file, we put the data structures
 to a hash table. Each tablespace and log file is given an unique 32-bit
@@ -90,7 +90,7 @@
 const char*	fil_path_to_mysql_datadir	= ".";
 
 /* The number of fsyncs done to the log */
-ulint	fil_n_log_flushes                       = 0;
+ulint	fil_n_log_flushes			= 0;
 
 ulint	fil_n_pending_log_flushes		= 0;
 ulint	fil_n_pending_tablespace_flushes	= 0;
@@ -117,7 +117,7 @@
 	ulint		n_pending_flushes;
 				/* count of pending flushes on this file;
 				closing of the file is not allowed if
-				this is > 0 */	
+				this is > 0 */
 	ib_longlong	modification_counter;/* when we write to the file we
 				increment this by one */
 	ib_longlong	flush_counter;/* up to what modification_counter value
@@ -165,7 +165,7 @@
 	ulint		size;	/* space size in pages; 0 if a single-table
 				tablespace whose size we do not know yet;
 				last incomplete megabytes in data files may be
-				ignored if space == 0 */ 
+				ignored if space == 0 */
 	ulint		n_reserved_extents;
 				/* number of reserved free extents for
 				ongoing operations like B-tree page split */
@@ -177,7 +177,7 @@
 				may need to access the ibuf bitmap page in the
 				tablespade: dropping of the tablespace is
 				forbidden if this is > 0 */
-	hash_node_t	hash; 	/* hash chain node */
+	hash_node_t	hash;	/* hash chain node */
 	hash_node_t	name_hash;/* hash chain the name_hash table */
 	rw_lock_t	latch;	/* latch protecting the file space storage
 				allocation */
@@ -251,6 +251,9 @@
 initialized. */
 fil_system_t*	fil_system	= NULL;
 
+/* The tablespace memory cache hash table size */
+#define	FIL_SYSTEM_HASH_SIZE	50 /* TODO: make bigger! */
+
 
 /************************************************************************
 NOTE: you must call fil_mutex_enter_and_prepare_for_io() first!
@@ -464,7 +467,7 @@
 
 	node->modification_counter = 0;
 	node->flush_counter = 0;
-	
+
 	HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
 
 	if (!space) {
@@ -488,7 +491,7 @@
 	node->space = space;
 
 	UT_LIST_ADD_LAST(chain, space->chain, node);
-				
+
 	mutex_exit(&(system->mutex));
 }
 
@@ -507,10 +510,12 @@
 	ulint		size_low;
 	ulint		size_high;
 	ibool		ret;
+	ibool		success;
+#ifndef UNIV_HOTBACKUP
 	byte*		buf2;
 	byte*		page;
-	ibool		success;
 	ulint		space_id;
+#endif /* !UNIV_HOTBACKUP */
 
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(system->mutex)));
@@ -543,24 +548,24 @@
 			ut_a(0);
 		}
 
-		ut_a(space->purpose != FIL_LOG);
-		ut_a(space->id != 0);
-
 		os_file_get_size(node->handle, &size_low, &size_high);
 
 		size_bytes = (((ib_longlong)size_high) << 32)
-				     		+ (ib_longlong)size_low;
+						+ (ib_longlong)size_low;
 #ifdef UNIV_HOTBACKUP
 		node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
 
 #else
+		ut_a(space->purpose != FIL_LOG);
+		ut_a(space->id != 0);
+
 		if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
-	        	fprintf(stderr,
+			fprintf(stderr,
 "InnoDB: Error: the size of single-table tablespace file %s\n"
 "InnoDB: is only %lu %lu, should be at least %lu!\n", node->name,
 			(ulong) size_high,
 			(ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE));
-			
+
 			ut_a(0);
 		}
 
@@ -576,22 +581,22 @@
 		space_id = fsp_header_get_space_id(page);
 
 		ut_free(buf2);
-		
+
 		/* Close the file now that we have read the space id from it */
 
 		os_file_close(node->handle);
 
 		if (space_id == ULINT_UNDEFINED || space_id == 0) {
-	        	fprintf(stderr,
+			fprintf(stderr,
 "InnoDB: Error: tablespace id %lu in file %s is not sensible\n",
 			(ulong) space_id,
 			node->name);
-			
-			ut_a(0);			
+
+			ut_a(0);
 		}
 
 		if (space_id != space->id) {
-	        	fprintf(stderr,
+			fprintf(stderr,
 "InnoDB: Error: tablespace id is %lu in the data dictionary\n"
 "InnoDB: but in file %s it is %lu!\n", space->id, node->name, space_id);
 
@@ -614,20 +619,20 @@
 	unbuffered async I/O mode, though global variables may make
 	os_file_create() to fall back to the normal file I/O mode. */
 
-	if (space->purpose == FIL_LOG) {	
+	if (space->purpose == FIL_LOG) {
 		node->handle = os_file_create(node->name, OS_FILE_OPEN,
 					OS_FILE_AIO, OS_LOG_FILE, &ret);
 	} else if (node->is_raw_disk) {
 		node->handle = os_file_create(node->name,
-				        OS_FILE_OPEN_RAW,
+					OS_FILE_OPEN_RAW,
 					OS_FILE_AIO, OS_DATA_FILE, &ret);
 	} else {
 		node->handle = os_file_create(node->name, OS_FILE_OPEN,
 					OS_FILE_AIO, OS_DATA_FILE, &ret);
 	}
-		
+
 	ut_a(ret);
-		
+
 	node->open = TRUE;
 
 	system->n_open++;
@@ -683,7 +688,7 @@
 fil_try_to_close_file_in_LRU(
 /*=========================*/
 				/* out: TRUE if success, FALSE if should retry
-				later; since i/o's generally complete in < 
+				later; since i/o's generally complete in <
 				100 ms, and as InnoDB writes at most 128 pages
 				from the buffer pool in a batch, and then
 				immediately flushes the files, there is a good
@@ -707,22 +712,22 @@
 
 	while (node != NULL) {
 		if (node->modification_counter == node->flush_counter
-		    && node->n_pending_flushes == 0) {
+			&& node->n_pending_flushes == 0) {
 
 			fil_node_close_file(node, system);
-			
+
 			return(TRUE);
 		}
-		
+
 		if (print_info && node->n_pending_flushes > 0) {
 			fputs("InnoDB: cannot close file ", stderr);
 			ut_print_filename(stderr, node->name);
 			fprintf(stderr, ", because n_pending_flushes %lu\n",
-				       (ulong) node->n_pending_flushes);
+				(ulong) node->n_pending_flushes);
 		}
 
 		if (print_info
-		    && node->modification_counter != node->flush_counter) {
+			&& node->modification_counter != node->flush_counter) {
 			fputs("InnoDB: cannot close file ", stderr);
 			ut_print_filename(stderr, node->name);
 			fprintf(stderr,
@@ -849,7 +854,7 @@
 	/* Flush tablespaces so that we can close modified files in the LRU
 	list */
 
-	fil_flush_file_spaces(FIL_TABLESPACE);		
+	fil_flush_file_spaces(FIL_TABLESPACE);
 
 	count++;
 
@@ -880,7 +885,7 @@
 		node->modification_counter = node->flush_counter;
 
 		if (space->is_in_unflushed_spaces
-		    && fil_space_is_flushed(space)) {
+			&& fil_space_is_flushed(space)) {
 
 			space->is_in_unflushed_spaces = FALSE;
 
@@ -893,7 +898,7 @@
 	}
 
 	space->size -= node->size;
-	
+
 	UT_LIST_REMOVE(chain, space->chain, node);
 
 	mem_free(node->name);
@@ -921,7 +926,7 @@
 	HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
 
 	ut_a(space);
-	
+
 	while (trunc_len > 0) {
 		node = UT_LIST_GET_FIRST(space->chain);
 
@@ -930,8 +935,8 @@
 		trunc_len -= node->size * UNIV_PAGE_SIZE;
 
 		fil_node_free(node, system, space);
-	}	
-				
+	}
+
 	mutex_exit(&(system->mutex));
 }
 
@@ -948,7 +953,7 @@
 	ulint		purpose)/* in: FIL_TABLESPACE, or FIL_LOG if log */
 {
 	fil_system_t*	system		= fil_system;
-	fil_space_t*	space;	
+	fil_space_t*	space;
 	ulint		namesake_id;
 try_again:
 	/*printf(
@@ -1036,7 +1041,7 @@
 	space->size = 0;
 
 	space->n_reserved_extents = 0;
-	
+
 	space->n_pending_flushes = 0;
 	space->n_pending_ibuf_merges = 0;
 
@@ -1044,10 +1049,9 @@
 	space->magic_n = FIL_SPACE_MAGIC_N;
 
 	space->ibuf_data = NULL;
-	
-	rw_lock_create(&(space->latch));
-	rw_lock_set_level(&(space->latch), SYNC_FSP);
-	
+
+	rw_lock_create(&space->latch, SYNC_FSP);
+
 	HASH_INSERT(fil_space_t, hash, system->spaces, id, space);
 
 	HASH_INSERT(fil_space_t, name_hash, system->name_hash,
@@ -1055,7 +1059,7 @@
 	space->is_in_unflushed_spaces = FALSE;
 
 	UT_LIST_ADD_LAST(space_list, system->space_list, space);
-				
+
 	mutex_exit(&(system->mutex));
 
 	return(TRUE);
@@ -1082,8 +1086,8 @@
 	id = system->max_assigned_id;
 
 	if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) {
-	        ut_print_timestamp(stderr);
-	        fprintf(stderr,
+		ut_print_timestamp(stderr);
+		fprintf(stderr,
 "InnoDB: Warning: you are running out of new single-table tablespace id's.\n"
 "InnoDB: Current counter is %lu and it must not exceed %lu!\n"
 "InnoDB: To reset the counter to zero you have to dump all your tables and\n"
@@ -1092,8 +1096,8 @@
 	}
 
 	if (id >= SRV_LOG_SPACE_FIRST_ID) {
-	        ut_print_timestamp(stderr);
-	        fprintf(stderr,
+		ut_print_timestamp(stderr);
+		fprintf(stderr,
 "InnoDB: You have run out of single-table tablespace id's!\n"
 "InnoDB: Current counter is %lu.\n"
 "InnoDB: To reset the counter to zero you have to dump all your tables and\n"
@@ -1135,14 +1139,14 @@
 "InnoDB: it is not there.\n", (ulong) id);
 
 		mutex_exit(&(system->mutex));
-		
+
 		return(FALSE);
 	}
 
 	HASH_DELETE(fil_space_t, hash, system->spaces, id, space);
 
 	HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(space->name),
-		    namespace, 0 == strcmp(space->name, namespace->name));
+		namespace, 0 == strcmp(space->name, namespace->name));
 	ut_a(namespace);
 	ut_a(space == namespace);
 
@@ -1167,8 +1171,8 @@
 		fil_node_free(fil_node, system, space);
 
 		fil_node = UT_LIST_GET_FIRST(space->chain);
-	}	
-	
+	}
+
 	ut_a(0 == UT_LIST_GET_LEN(space->chain));
 
 	mutex_exit(&(system->mutex));
@@ -1214,7 +1218,7 @@
 			/* out: space size, 0 if space not found */
 	ulint	id)	/* in: space id */
 {
-	fil_system_t*	system 		= fil_system;
+	fil_system_t*	system		= fil_system;
 	fil_node_t*	node;
 	fil_space_t*	space;
 	ulint		size;
@@ -1247,7 +1251,7 @@
 	}
 
 	size = space->size;
-	
+
 	mutex_exit(&(system->mutex));
 
 	return(size);
@@ -1270,7 +1274,7 @@
 	}
 
 	return(FALSE);
-}		
+}
 
 /********************************************************************
 Creates a the tablespace memory cache. */
@@ -1290,9 +1294,7 @@
 
 	system = mem_alloc(sizeof(fil_system_t));
 
-	mutex_create(&(system->mutex));
-
-	mutex_set_level(&(system->mutex), SYNC_ANY_LATCH);
+	mutex_create(&system->mutex, SYNC_ANY_LATCH);
 
 	system->spaces = hash_create(hash_size);
 	system->name_hash = hash_create(hash_size);
@@ -1321,17 +1323,11 @@
 /*=====*/
 	ulint	max_n_open)	/* in: max number of open files */
 {
-	ulint	hash_size;
-
 	ut_a(fil_system == NULL);
 
-	if (srv_file_per_table) {
-		hash_size = 50000;
-	} else {
-		hash_size = 5000;
-	}
-
-	fil_system = fil_system_create(hash_size, max_n_open);
+	/*printf("Initializing the tablespace cache with max %lu open files\n",
+	  max_n_open); */
+	fil_system = fil_system_create(FIL_SYSTEM_HASH_SIZE, max_n_open);
 }
 
 /***********************************************************************
@@ -1369,8 +1365,8 @@
 "InnoDB: tablespace files open for the whole time mysqld is running, and\n"
 "InnoDB: needs to open also some .ibd files if the file-per-table storage\n"
 "InnoDB: model is used. Current open files %lu, max allowed open files %lu.\n",
-				     (ulong) system->n_open,
-				     (ulong) system->max_n_open);
+						(ulong) system->n_open,
+						(ulong) system->max_n_open);
 				}
 				node = UT_LIST_GET_NEXT(chain, node);
 			}
@@ -1453,7 +1449,7 @@
 	space = UT_LIST_GET_FIRST(fil_system->space_list);
 
 	ut_a(space);
-        ut_a(space->purpose == FIL_TABLESPACE);	
+	ut_a(space->purpose == FIL_TABLESPACE);
 
 	space->ibuf_data = ibuf_data_init_for_space(space->id);
 }
@@ -1484,7 +1480,7 @@
 
 	fil_write(TRUE, space_id, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
 
-	return(DB_SUCCESS);	
+	return(DB_SUCCESS);
 }
 
 /********************************************************************
@@ -1504,9 +1500,9 @@
 	ulint		err;
 
 	mutex_enter(&(fil_system->mutex));
-	
+
 	space = UT_LIST_GET_FIRST(fil_system->space_list);
-	
+
 	while (space) {
 		/* We only write the lsn to all existing data files which have
 		been open during the lifetime of the mysqld process; they are
@@ -1515,7 +1511,7 @@
 		always open. */
 
 		if (space->purpose == FIL_TABLESPACE
-		    && space->id == 0) {
+			&& space->id == 0) {
 			sum_of_sizes = 0;
 
 			node = UT_LIST_GET_FIRST(space->chain);
@@ -1568,7 +1564,7 @@
 	buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
 	/* Align the memory for a possible read from a raw device */
 	buf = ut_align(buf2, UNIV_PAGE_SIZE);
-	
+
 	os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
 
 	flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
@@ -1616,7 +1612,7 @@
 {
 	fil_system_t*	system		= fil_system;
 	fil_space_t*	space;
-	
+
 	mutex_enter(&(system->mutex));
 
 	HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
@@ -1645,12 +1641,12 @@
 
 void
 fil_decr_pending_ibuf_merges(
-/*========================*/
+/*=========================*/
 	ulint	id)	/* in: space id */
 {
 	fil_system_t*	system		= fil_system;
 	fil_space_t*	space;
-	
+
 	mutex_enter(&(system->mutex));
 
 	HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
@@ -1711,7 +1707,7 @@
 	const char*	name,		/* in: table name in the familiar
 					'databasename/tablename' format, or
 					the file path in the case of
-					MLOG_FILE_DELETE */ 
+					MLOG_FILE_DELETE */
 	const char*	new_name,	/* in: if type is MLOG_FILE_RENAME,
 					the new table name in the
 					'databasename/tablename' format */
@@ -1770,13 +1766,13 @@
 byte*
 fil_op_log_parse_or_replay(
 /*=======================*/
-                        	/* out: end of log record, or NULL if the
+				/* out: end of log record, or NULL if the
 				record was not completely contained between
 				ptr and end_ptr */
-        byte*   ptr,    	/* in: buffer containing the log record body,
+	byte*	ptr,		/* in: buffer containing the log record body,
 				or an initial segment of it, if the record does
 				not fir completely between ptr and end_ptr */
-        byte*   end_ptr,	/* in: buffer end */
+	byte*	end_ptr,	/* in: buffer end */
 	ulint	type,		/* in: the type of this log record */
 	ibool	do_replay,	/* in: TRUE if we want to replay the
 				operation, and not just parse the log record */
@@ -1799,7 +1795,7 @@
 	ptr += 2;
 
 	if (end_ptr < ptr + name_len) {
-		
+
 		return(NULL);
 	}
 
@@ -1814,11 +1810,11 @@
 		}
 
 		new_name_len = mach_read_from_2(ptr);
-		
+
 		ptr += 2;
 
 		if (end_ptr < ptr + new_name_len) {
-		
+
 			return(NULL);
 		}
 
@@ -1844,7 +1840,7 @@
 	/* Let us try to perform the file operation, if sensible. Note that
 	ibbackup has at this stage already read in all space id info to the
 	fil0fil.c data structures.
-	
+
 	NOTE that our algorithm is not guaranteed to work correctly if there
 	were renames of tables during the backup. See ibbackup code for more
 	on the problem. */
@@ -1863,12 +1859,12 @@
 			/* Create the database directory for the new name, if
 			it does not exist yet */
 			fil_create_directory_for_tablename(new_name);
-	
+
 			/* Rename the table if there is not yet a tablespace
 			with the same name */
 
 			if (fil_get_space_id_for_table(new_name)
-			    == ULINT_UNDEFINED) {
+				== ULINT_UNDEFINED) {
 				/* We do not care of the old name, that is
 				why we pass NULL as the first argument */
 				ut_a(fil_rename_tablespace(NULL, space_id,
@@ -1890,7 +1886,7 @@
 
 			ut_a(space_id != 0);
 
-			ut_a(DB_SUCCESS == 
+			ut_a(DB_SUCCESS ==
 				fil_create_new_single_table_tablespace(
 						&space_id, name, FALSE,
 						FIL_IBD_FILE_INITIAL_SIZE));
@@ -1969,9 +1965,9 @@
 			(ulong) id);
 
 		mutex_exit(&(system->mutex));
-	
+
 		return(FALSE);
-	}	
+	}
 
 	ut_a(space);
 	ut_a(space->n_pending_ibuf_merges == 0);
@@ -2074,7 +2070,7 @@
 		fprintf(stderr,
 "InnoDB: Warning: cannot delete tablespace %lu in DISCARD TABLESPACE.\n"
 "InnoDB: But let us remove the insert buffer entries for this tablespace.\n",
-			(ulong) id); 
+			(ulong) id);
 	}
 
 	/* Remove all insert buffer entries for the tablespace */
@@ -2098,9 +2094,9 @@
 	fil_system_t*	system		= fil_system;
 	fil_space_t*	space2;
 	const char*	old_name	= space->name;
-	
+
 	HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(old_name),
-			       space2, 0 == strcmp(old_name, space2->name));
+		space2, 0 == strcmp(old_name, space2->name));
 	if (space != space2) {
 		fputs("InnoDB: Error: cannot find ", stderr);
 		ut_print_filename(stderr, old_name);
@@ -2110,12 +2106,12 @@
 	}
 
 	HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(path),
-			       space2, 0 == strcmp(path, space2->name));
+		space2, 0 == strcmp(path, space2->name));
 	if (space2 != NULL) {
 		fputs("InnoDB: Error: ", stderr);
 		ut_print_filename(stderr, path);
 		fputs(" is already in tablespace memory cache\n", stderr);
-		
+
 		return(FALSE);
 	}
 
@@ -2187,11 +2183,11 @@
 	fil_node_t*	node;
 	ulint		count		= 0;
 	char*		path;
-	ibool		old_name_was_specified 		= TRUE;
+	ibool		old_name_was_specified		= TRUE;
 	char*		old_path;
 
 	ut_a(id != 0);
-	
+
 	if (old_name == NULL) {
 		old_name = "(name not specified)";
 		old_name_was_specified = FALSE;
@@ -2300,7 +2296,7 @@
 
 	mutex_exit(&(system->mutex));
 
-#ifndef UNIV_HOTBACKUP	
+#ifndef UNIV_HOTBACKUP
 	if (success) {
 		mtr_t		mtr;
 
@@ -2338,7 +2334,7 @@
 					tablespace file in pages,
 					must be >= FIL_IBD_FILE_INITIAL_SIZE */
 {
-	os_file_t       file;
+	os_file_t	file;
 	ibool		ret;
 	ulint		err;
 	byte*		buf2;
@@ -2349,9 +2345,9 @@
 	ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
 
 	path = fil_make_ibd_name(tablename, is_temp);
-	
+
 	file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL,
-						    OS_DATA_FILE, &ret);
+		OS_DATA_FILE, &ret);
 	if (ret == FALSE) {
 		ut_print_timestamp(stderr);
 		fputs("  InnoDB: Error creating file ", stderr);
@@ -2359,11 +2355,11 @@
 		fputs(".\n", stderr);
 
 		/* The following call will print an error message */
-		 
+
 		err = os_file_get_last_error(TRUE);
-		
+
 		if (err == OS_FILE_ALREADY_EXISTS) {
-		        fputs(
+			fputs(
 "InnoDB: The file already exists though the corresponding table did not\n"
 "InnoDB: exist in the InnoDB data dictionary. Have you moved InnoDB\n"
 "InnoDB: .ibd files around without using the SQL commands\n"
@@ -2393,7 +2389,7 @@
 	page = ut_align(buf2, UNIV_PAGE_SIZE);
 
 	ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0);
-	
+
 	if (!ret) {
 		ut_free(buf2);
 		os_file_close(file);
@@ -2431,7 +2427,7 @@
 
 	memset(page, '\0', UNIV_PAGE_SIZE);
 
-	fsp_header_write_space_id(page, *space_id);		
+	fsp_header_write_space_id(page, *space_id);
 
 	buf_flush_init_for_writing(page, ut_dulint_zero, *space_id, 0);
 
@@ -2464,14 +2460,14 @@
 	}
 
 	success = fil_space_create(path, *space_id, FIL_TABLESPACE);
-	
+
 	if (!success) {
 		goto error_exit2;
-	}	
+	}
 
 	fil_node_create(path, size, *space_id, FALSE);
 
-#ifndef UNIV_HOTBACKUP	
+#ifndef UNIV_HOTBACKUP
 	{
 	mtr_t		mtr;
 
@@ -2527,7 +2523,7 @@
 
 		ut_print_timestamp(stderr);
 
-	        fputs(
+		fputs(
 "  InnoDB: Error: trying to open a table, but could not\n"
 "InnoDB: open the tablespace file ", stderr);
 		ut_print_filename(stderr, filepath);
@@ -2561,17 +2557,17 @@
 	}
 
 	space_id = fsp_header_get_space_id(page);
-	
+
 	ut_print_timestamp(stderr);
 	fprintf(stderr,
 " InnoDB: Flush lsn in the tablespace file %lu to be imported\n"
 "InnoDB: is %lu %lu, which exceeds current system lsn %lu %lu.\n"
 "InnoDB: We reset the lsn's in the file ",
-			    (ulong) space_id,
-			    (ulong) ut_dulint_get_high(flush_lsn),
-			    (ulong) ut_dulint_get_low(flush_lsn),
-			    (ulong) ut_dulint_get_high(current_lsn),
-			    (ulong) ut_dulint_get_low(current_lsn));
+		(ulong) space_id,
+		(ulong) ut_dulint_get_high(flush_lsn),
+		(ulong) ut_dulint_get_low(flush_lsn),
+		(ulong) ut_dulint_get_high(current_lsn),
+		(ulong) ut_dulint_get_low(current_lsn));
 	ut_print_filename(stderr, filepath);
 	fputs(".\n", stderr);
 
@@ -2594,9 +2590,9 @@
 			space_id = mach_read_from_4(page
 					+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
 			page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
-			
+
 			buf_flush_init_for_writing(page, current_lsn, space_id,
-								      page_no);
+				page_no);
 			success = os_file_write(filepath, file, page,
 				(ulint)(offset & 0xFFFFFFFFUL),
 				(ulint)(offset >> 32), UNIV_PAGE_SIZE);
@@ -2679,7 +2675,7 @@
 
 		ut_print_timestamp(stderr);
 
-	        fputs(
+		fputs(
 "  InnoDB: Error: trying to open a table, but could not\n"
 "InnoDB: open the tablespace file ", stderr);
 		ut_print_filename(stderr, filepath);
@@ -2720,7 +2716,7 @@
 	if (space_id != id) {
 		ut_print_timestamp(stderr);
 
-	        fputs(
+		fputs(
 "  InnoDB: Error: tablespace id in file ", stderr);
 		ut_print_filename(stderr, filepath);
 		fprintf(stderr, " is %lu, but in the InnoDB\n"
@@ -2799,13 +2795,14 @@
 #ifdef UNIV_HOTBACKUP
 	fil_space_t*	space;
 #endif
-	filepath = mem_alloc(strlen(dbname) + strlen(filename) 
+	filepath = mem_alloc(strlen(dbname) + strlen(filename)
 			+ strlen(fil_path_to_mysql_datadir) + 3);
 
 	sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname,
 								filename);
 	srv_normalize_path_for_win(filepath);
 #ifdef __WIN__
+# ifndef UNIV_HOTBACKUP
 	/* If lower_case_table_names is 0 or 2, then MySQL allows database
 	directory names with upper case letters. On Windows, all table and
 	database names in InnoDB are internally always in lower case. Put the
@@ -2813,6 +2810,7 @@
 	internal data dictionary. */
 
 	dict_casedn_str(filepath);
+# endif /* !UNIV_HOTBACKUP */
 #endif
 	file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN,
 						OS_FILE_READ_ONLY, &success);
@@ -2820,7 +2818,7 @@
 		/* The following call prints an error message */
 		os_file_get_last_error(TRUE);
 
-	        fprintf(stderr,
+		fprintf(stderr,
 "InnoDB: Error: could not open single-table tablespace file\n"
 "InnoDB: %s!\n"
 "InnoDB: We do not continue the crash recovery, because the table may become\n"
@@ -2854,7 +2852,7 @@
 		/* The following call prints an error message */
 		os_file_get_last_error(TRUE);
 
-	        fprintf(stderr,
+		fprintf(stderr,
 "InnoDB: Error: could not measure the size of single-table tablespace file\n"
 "InnoDB: %s!\n"
 "InnoDB: We do not continue crash recovery, because the table will become\n"
@@ -2892,7 +2890,7 @@
 	size = (((ib_longlong)size_high) << 32) + (ib_longlong)size_low;
 #ifndef UNIV_HOTBACKUP
 	if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
-	        fprintf(stderr,
+		fprintf(stderr,
 "InnoDB: Error: the size of single-table tablespace file %s\n"
 "InnoDB: is only %lu %lu, should be at least %lu!", filepath,
 			(ulong) size_high,
@@ -2921,7 +2919,7 @@
 
 #ifndef UNIV_HOTBACKUP
 	if (space_id == ULINT_UNDEFINED || space_id == 0) {
-	        fprintf(stderr,
+		fprintf(stderr,
 "InnoDB: Error: tablespace id %lu in file %s is not sensible\n",
 			(ulong) space_id,
 			filepath);
@@ -3031,7 +3029,7 @@
 
 			return(ret);
 		}
-		
+
 		fprintf(stderr,
 "InnoDB: Error: os_file_readdir_next_file() returned -1 in\n"
 "InnoDB: directory %s\n"
@@ -3063,7 +3061,7 @@
 	os_file_dir_t	dbdir;
 	os_file_stat_t	dbinfo;
 	os_file_stat_t	fileinfo;
-	ulint		err 		= DB_SUCCESS;
+	ulint		err		= DB_SUCCESS;
 
 	/* The datadir of MySQL is always the default directory of mysqld */
 
@@ -3086,9 +3084,9 @@
 		/* printf("Looking at %s in datadir\n", dbinfo.name); */
 
 		if (dbinfo.type == OS_FILE_TYPE_FILE
-		    || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
+			|| dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
 
-		        goto next_datadir_item;
+			goto next_datadir_item;
 		}
 
 		/* We found a symlink or a directory; try opening it to see
@@ -3121,19 +3119,19 @@
 								&fileinfo);
 			while (ret == 0) {
 				/* printf(
-"     Looking at file %s\n", fileinfo.name); */
+				   "     Looking at file %s\n", fileinfo.name); */
 
-			        if (fileinfo.type == OS_FILE_TYPE_DIR) {
+				if (fileinfo.type == OS_FILE_TYPE_DIR) {
 
-				        goto next_file_item;
+					goto next_file_item;
 				}
 
 				/* We found a symlink or a file */
 				if (strlen(fileinfo.name) > 4
-				    && 0 == strcmp(fileinfo.name + 
+					&& 0 == strcmp(fileinfo.name +
 						strlen(fileinfo.name) - 4,
 						".ibd")) {
-				        /* The name ends in .ibd; try opening
+					/* The name ends in .ibd; try opening
 					the file */
 					fil_load_single_table_tablespace(
 						dbinfo.name, fileinfo.name);
@@ -3153,7 +3151,7 @@
 				err = DB_ERROR;
 			}
 		}
-		
+
 next_datadir_item:
 		ret = fil_file_readdir_next_file(&err,
 						fil_path_to_mysql_datadir,
@@ -3183,7 +3181,7 @@
 fil_print_orphaned_tablespaces(void)
 /*================================*/
 {
-	fil_system_t*	system 		= fil_system;
+	fil_system_t*	system		= fil_system;
 	fil_space_t*	space;
 
 	mutex_enter(&(system->mutex));
@@ -3191,7 +3189,7 @@
 	space = UT_LIST_GET_FIRST(system->space_list);
 
 	while (space) {
-	        if (space->purpose == FIL_TABLESPACE && space->id != 0
+		if (space->purpose == FIL_TABLESPACE && space->id != 0
 							  && !space->mark) {
 			fputs("InnoDB: Warning: tablespace ", stderr);
 			ut_print_filename(stderr, space->name);
@@ -3202,7 +3200,7 @@
 		space = UT_LIST_GET_NEXT(space_list, space);
 	}
 
-	mutex_exit(&(system->mutex));	
+	mutex_exit(&(system->mutex));
 }
 
 /***********************************************************************
@@ -3326,7 +3324,7 @@
 					0 == strcmp(namespace->name, path));
 	if (space && space == namespace) {
 		/* Found */
-		
+
 		if (mark_space) {
 			space->mark = TRUE;
 		}
@@ -3338,16 +3336,16 @@
 	}
 
 	if (!print_error_if_does_not_exist) {
-		
+
 		mem_free(path);
 		mutex_exit(&(system->mutex));
-		
+
 		return(FALSE);
 	}
 
 	if (space == NULL) {
 		if (namespace == NULL) {
-		        ut_print_timestamp(stderr);
+			ut_print_timestamp(stderr);
 			fputs("  InnoDB: Error: table ", stderr);
 			ut_print_filename(stderr, name);
 			fprintf(stderr, "\n"
@@ -3359,7 +3357,7 @@
 "InnoDB: table still exists in the InnoDB internal data dictionary.\n",
 				(ulong) id);
 		} else {
-		        ut_print_timestamp(stderr);
+			ut_print_timestamp(stderr);
 			fputs("  InnoDB: Error: table ", stderr);
 			ut_print_filename(stderr, name);
 			fprintf(stderr, "\n"
@@ -3440,7 +3438,7 @@
 					0 == strcmp(namespace->name, path));
 	if (namespace) {
 		id = namespace->id;
-	}	
+	}
 
 	mem_free(path);
 
@@ -3489,11 +3487,11 @@
 
 		*actual_size = space->size;
 
-		mutex_exit(&(system->mutex));	
+		mutex_exit(&(system->mutex));
 
 		return(TRUE);
 	}
-	
+
 	node = UT_LIST_GET_LAST(space->chain);
 
 	fil_node_prepare_for_io(node, system, space);
@@ -3517,7 +3515,7 @@
 				/ (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE));
 		offset_low  = ((start_page_no - file_start_page_no)
 				% (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE)))
-			      * UNIV_PAGE_SIZE;
+			* UNIV_PAGE_SIZE;
 #ifdef UNIV_HOTBACKUP
 		success = os_file_write(node->name, node->handle, buf,
 					offset_low, offset_high,
@@ -3537,7 +3535,7 @@
 		} else {
 			/* Let us measure the size of the file to determine
 			how much we were able to extend it */
-			
+
 			n_pages = ((ulint)
 				(os_file_get_size_as_iblonglong(node->handle)
 				/ UNIV_PAGE_SIZE)) - node->size;
@@ -3570,9 +3568,9 @@
 #endif /* !UNIV_HOTBACKUP */
 
 	/*
-        printf("Extended %s to %lu, actual size %lu pages\n", space->name,
-                                        size_after_extend, *actual_size); */
-	mutex_exit(&(system->mutex));	
+	printf("Extended %s to %lu, actual size %lu pages\n", space->name,
+					size_after_extend, *actual_size); */
+	mutex_exit(&(system->mutex));
 
 	fil_flush(space_id);
 
@@ -3590,7 +3588,7 @@
 fil_extend_tablespaces_to_stored_len(void)
 /*======================================*/
 {
-	fil_system_t*	system 		= fil_system;
+	fil_system_t*	system		= fil_system;
 	fil_space_t*	space;
 	byte*		buf;
 	ulint		actual_size;
@@ -3605,11 +3603,11 @@
 	space = UT_LIST_GET_FIRST(system->space_list);
 
 	while (space) {
-	        ut_a(space->purpose == FIL_TABLESPACE);
+		ut_a(space->purpose == FIL_TABLESPACE);
 
 		mutex_exit(&(system->mutex)); /* no need to protect with a
-					      mutex, because this is a single-
-					      threaded operation */
+					      mutex, because this is a
+					      single-threaded operation */
 		error = fil_read(TRUE, space->id, 0, 0, UNIV_PAGE_SIZE, buf,
 									NULL);
 		ut_a(error == DB_SUCCESS);
@@ -3625,7 +3623,7 @@
 "InnoDB: size after extension %lu pages\n"
 "InnoDB: Check that you have free disk space and retry!\n", space->name,
 					size_in_header, actual_size);
-			exit(1);				
+			exit(1);
 		}
 
 		mutex_enter(&(system->mutex));
@@ -3670,7 +3668,7 @@
 		space->n_reserved_extents += n_to_reserve;
 		success = TRUE;
 	}
-	
+
 	mutex_exit(&(system->mutex));
 
 	return(success);
@@ -3696,9 +3694,9 @@
 
 	ut_a(space);
 	ut_a(space->n_reserved_extents >= n_reserved);
-	
+
 	space->n_reserved_extents -= n_reserved;
-	
+
 	mutex_exit(&(system->mutex));
 }
 
@@ -3720,11 +3718,11 @@
 	mutex_enter(&(system->mutex));
 
 	HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
-	
+
 	ut_a(space);
 
 	n = space->n_reserved_extents;
-	
+
 	mutex_exit(&(system->mutex));
 
 	return(n);
@@ -3751,7 +3749,7 @@
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&(system->mutex)));
 #endif /* UNIV_SYNC_DEBUG */
-	
+
 	if (system->n_open > system->max_n_open + 5) {
 		ut_print_timestamp(stderr);
 		fprintf(stderr,
@@ -3768,7 +3766,7 @@
 	}
 
 	if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
-						      && space->id != 0) {
+		&& space->id != 0) {
 		/* The node is in the LRU list, remove it */
 
 		ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
@@ -3799,7 +3797,7 @@
 #endif /* UNIV_SYNC_DEBUG */
 
 	ut_a(node->n_pending > 0);
-	
+
 	node->n_pending--;
 
 	if (type == OS_FILE_WRITE) {
@@ -3814,7 +3812,7 @@
 					node->space);
 		}
 	}
-	
+
 	if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
 					&& node->space->id != 0) {
 		/* The node must be put back to the LRU list */
@@ -3889,13 +3887,13 @@
 	ibool		ret;
 	ulint		is_log;
 	ulint		wake_later;
-	
+
 	is_log = type & OS_FILE_LOG;
 	type = type & ~OS_FILE_LOG;
 
 	wake_later = type & OS_AIO_SIMULATED_WAKE_LATER;
 	type = type & ~OS_AIO_SIMULATED_WAKE_LATER;
-	
+
 	ut_ad(byte_offset < UNIV_PAGE_SIZE);
 	ut_ad(buf);
 	ut_ad(len > 0);
@@ -3921,17 +3919,17 @@
 		mode = OS_AIO_NORMAL;
 	}
 
-        if (type == OS_FILE_READ) {
-                srv_data_read+= len;
-        } else if (type == OS_FILE_WRITE) {
-                srv_data_written+= len;
-        }
+	if (type == OS_FILE_READ) {
+		srv_data_read+= len;
+	} else if (type == OS_FILE_WRITE) {
+		srv_data_written+= len;
+	}
 
 	/* Reserve the fil_system mutex and make sure that we can open at
 	least one file while holding it, if the file is not already open */
 
 	fil_mutex_enter_and_prepare_for_io(space_id);
-	
+
 	HASH_SEARCH(hash, system->spaces, space_id, space,
 							space->id == space_id);
 	if (!space) {
@@ -3955,7 +3953,7 @@
 		if (node == NULL) {
 			fil_report_invalid_page_access(block_offset, space_id,
 				space->name, byte_offset, len, type);
- 			
+
 			ut_error;
 		}
 
@@ -3973,15 +3971,15 @@
 			block_offset -= node->size;
 			node = UT_LIST_GET_NEXT(chain, node);
 		}
-	}		
-	
+	}
+
 	/* Open file if closed */
 	fil_node_prepare_for_io(node, system, space);
 
 	/* Check that at least the start offset is within the bounds of a
 	single-table tablespace */
 	if (space->purpose == FIL_TABLESPACE && space->id != 0
-	    && node->size <= block_offset) {
+		&& node->size <= block_offset) {
 
 		fil_report_invalid_page_access(block_offset, space_id,
 			space->name, byte_offset, len, type);
@@ -3999,7 +3997,7 @@
 			+ byte_offset;
 
 	ut_a(node->size - block_offset >=
- 		(byte_offset + len + (UNIV_PAGE_SIZE - 1)) / UNIV_PAGE_SIZE);
+		(byte_offset + len + (UNIV_PAGE_SIZE - 1)) / UNIV_PAGE_SIZE);
 
 	/* Do aio */
 
@@ -4025,7 +4023,7 @@
 	if (mode == OS_AIO_SYNC) {
 		/* The i/o operation is already completed when we return from
 		os_aio: */
-		
+
 		mutex_enter(&(system->mutex));
 
 		fil_node_complete_io(node, system, type);
@@ -4104,21 +4102,21 @@
 fil_aio_wait(
 /*=========*/
 	ulint	segment)	/* in: the number of the segment in the aio
-				array to wait for */ 
+				array to wait for */
 {
 	fil_system_t*	system		= fil_system;
-	ibool		ret;		
+	ibool		ret;
 	fil_node_t*	fil_node;
 	void*		message;
 	ulint		type;
-	
+
 	ut_ad(fil_validate());
 
 	if (os_aio_use_native_aio) {
 		srv_set_io_thread_op_info(segment, "native aio handle");
 #ifdef WIN_ASYNC_IO
 		ret = os_aio_windows_handle(segment, 0, &fil_node,
-					    &message, &type);
+			&message, &type);
 #elif defined(POSIX_ASYNC_IO)
 		ret = os_aio_posix_handle(segment, &fil_node, &message);
 #else
@@ -4129,9 +4127,9 @@
 		srv_set_io_thread_op_info(segment, "simulated aio handle");
 
 		ret = os_aio_simulated_handle(segment, &fil_node,
-	                                               &message, &type);
+			&message, &type);
 	}
-	
+
 	ut_a(ret);
 
 	srv_set_io_thread_op_info(segment, "complete io for fil node");
@@ -4176,7 +4174,7 @@
 	ib_longlong	old_mod_counter;
 
 	mutex_enter(&(system->mutex));
-	
+
 	HASH_SEARCH(hash, system->spaces, space_id, space,
 							space->id == space_id);
 	if (!space || space->is_being_deleted) {
@@ -4209,7 +4207,7 @@
 				goto skip_flush;
 			}
 #endif
-retry:			
+retry:
 			if (node->n_pending_flushes > 0) {
 				/* We want to avoid calling os_file_flush() on
 				the file twice at the same time, because we do
@@ -4239,7 +4237,7 @@
 			/* fprintf(stderr, "Flushing to file %s\n",
 				node->name); */
 
-			os_file_flush(file);		
+			os_file_flush(file);
 
 			mutex_enter(&(system->mutex));
 
@@ -4249,7 +4247,7 @@
 				node->flush_counter = old_mod_counter;
 
 				if (space->is_in_unflushed_spaces
-				    && fil_space_is_flushed(space)) {
+					&& fil_space_is_flushed(space)) {
 
 					space->is_in_unflushed_spaces = FALSE;
 
@@ -4267,7 +4265,7 @@
 		}
 
 		node = UT_LIST_GET_NEXT(chain, node);
-	}		
+	}
 
 	space->n_pending_flushes--;
 
@@ -4293,8 +4291,8 @@
 	while (space) {
 		if (space->purpose == purpose && !space->is_being_deleted) {
 
-			space->n_pending_flushes++; /* prevent dropping of the
-						    space while we are
+			space->n_pending_flushes++; /* prevent dropping of
+						    the space while we are
 						    flushing */
 			mutex_exit(&(system->mutex));
 
@@ -4306,7 +4304,7 @@
 		}
 		space = UT_LIST_GET_NEXT(unflushed_spaces, space);
 	}
-	
+
 	mutex_exit(&(system->mutex));
 }
 
@@ -4317,13 +4315,13 @@
 fil_validate(void)
 /*==============*/
 			/* out: TRUE if ok */
-{	
+{
 	fil_system_t*	system		= fil_system;
 	fil_space_t*	space;
 	fil_node_t*	fil_node;
 	ulint		n_open		= 0;
 	ulint		i;
-	
+
 	mutex_enter(&(system->mutex));
 
 	/* Look for spaces in the hash table */
@@ -4331,9 +4329,9 @@
 	for (i = 0; i < hash_get_n_cells(system->spaces); i++) {
 
 		space = HASH_GET_FIRST(system->spaces, i);
-	
+
 		while (space != NULL) {
-			UT_LIST_VALIDATE(chain, fil_node_t, space->chain); 
+			UT_LIST_VALIDATE(chain, fil_node_t, space->chain);
 
 			fil_node = UT_LIST_GET_FIRST(space->chain);
 
@@ -4365,7 +4363,7 @@
 
 		fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
 	}
-	
+
 	mutex_exit(&(system->mutex));
 
 	return(TRUE);
@@ -4408,13 +4406,13 @@
 void
 fil_page_set_type(
 /*==============*/
-	byte* 	page,	/* in: file page */
+	byte*	page,	/* in: file page */
 	ulint	type)	/* in: type */
 {
 	ut_ad(page);
 
 	mach_write_to_2(page + FIL_PAGE_TYPE, type);
-}	
+}
 
 /*************************************************************************
 Gets the file page type. */
@@ -4424,7 +4422,7 @@
 /*==============*/
 			/* out: type; NOTE that if the type has not been
 			written to page, the return value not defined */
-	byte* 	page)	/* in: file page */
+	byte*	page)	/* in: file page */
 {
 	ut_ad(page);
 

--- 1.25.2.1/innobase/fsp/fsp0fsp.c	2006-08-29 18:58:59 +04:00
+++ 1.29/storage/innobase/fsp/fsp0fsp.c	2006-08-29 18:58:59 +04:00
@@ -33,9 +33,9 @@
 
 /* The data structures in files are defined just as byte strings in C */
 typedef	byte	fsp_header_t;
-typedef	byte	xdes_t;		
+typedef	byte	xdes_t;
 
-/*			SPACE HEADER		
+/*			SPACE HEADER
 			============
 
 File space header data structure: this data structure is contained in the
@@ -92,7 +92,7 @@
 #define	FSP_FREE_ADD		4	/* this many free extents are added
 					to the free list from above
 					FSP_FREE_LIMIT at a time */
-					
+
 /*			FILE SEGMENT INODE
 			==================
 
@@ -142,7 +142,7 @@
 				single page */
 
 #define FSEG_MAGIC_N_VALUE	97937874
-					
+
 #define	FSEG_FILLFACTOR		8	/* If this value is x, then if
 					the number of unused but reserved
 					pages in a segment is less than
@@ -152,7 +152,7 @@
 					be added to the segment in
 					fseg_alloc_free_page. Otherwise, we
 					use unused pages of the segment. */
-					
+
 #define FSEG_FRAG_LIMIT		FSEG_FRAG_ARR_N_SLOTS
 					/* If the segment has >= this many
 					used pages, it may be expanded by
@@ -166,7 +166,7 @@
 					list of the extent: at most
 					FSEG_FREE_LIST_MAX_LEN many */
 #define	FSEG_FREE_LIST_MAX_LEN	4
-					
+
 
 /*			EXTENT DESCRIPTOR
 			=================
@@ -186,7 +186,7 @@
 					/* Descriptor bitmap of the pages
 					in the extent */
 /*-------------------------------------*/
-					
+
 #define	XDES_BITS_PER_PAGE	2	/* How many bits are there per page */
 #define	XDES_FREE_BIT		0	/* Index of the bit which tells if
 					the page is free */
@@ -208,7 +208,7 @@
 
 /* Offset of the descriptor array on a descriptor page */
 #define	XDES_ARR_OFFSET		(FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
-					
+
 /**************************************************************************
 Returns an extent to the free list of a space. */
 static
@@ -236,7 +236,7 @@
 fseg_n_reserved_pages_low(
 /*======================*/
 				/* out: number of reserved pages */
-	fseg_inode_t* 	header,	/* in: segment inode */
+	fseg_inode_t*	header,	/* in: segment inode */
 	ulint*		used,	/* out: number of pages used (<= reserved) */
 	mtr_t*		mtr);	/* in: mtr handle */
 /************************************************************************
@@ -290,7 +290,7 @@
 				/* out: the allocated page number, FIL_NULL
 				if no page could be allocated */
 	ulint		space,	/* in: space */
-	fseg_inode_t* 	seg_inode, /* in: segment inode */
+	fseg_inode_t*	seg_inode, /* in: segment inode */
 	ulint		hint,	/* in: hint of which page would be desirable */
 	byte		direction, /* in: if the new page is needed because
 				of an index page split, and records are
@@ -354,17 +354,17 @@
 						MTR_MEMO_PAGE_X_FIX));
 	ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
 	ut_ad(offset < FSP_EXTENT_SIZE);
-	
+
 	index = bit + XDES_BITS_PER_PAGE * offset;
 
 	byte_index = index / 8;
 	bit_index = index % 8;
-		
+
 	return(ut_bit_get_nth(
 		   mtr_read_ulint(descr + XDES_BITMAP + byte_index,
 							MLOG_1BYTE, mtr),
-		   bit_index));	  
-}	
+		   bit_index));
+}
 
 /**************************************************************************
 Sets a descriptor bit of a page. */
@@ -383,7 +383,7 @@
 	ulint	byte_index;
 	ulint	bit_index;
 	ulint	descr_byte;
-	
+
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
 							MTR_MEMO_PAGE_X_FIX));
 	ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
@@ -400,7 +400,7 @@
 
 	mlog_write_ulint(descr + XDES_BITMAP + byte_index, descr_byte,
 							MLOG_1BYTE, mtr);
-}	
+}
 
 /**************************************************************************
 Looks for a descriptor bit having the desired value. Starts from hint
@@ -419,7 +419,7 @@
 	mtr_t*	mtr)	/* in: mtr */
 {
 	ulint	i;
-	
+
 	ut_ad(descr && mtr);
 	ut_ad(val <= TRUE);
 	ut_ad(hint < FSP_EXTENT_SIZE);
@@ -438,9 +438,9 @@
 			return(i);
 		}
 	}
-	
-	return(ULINT_UNDEFINED);			
-}	
+
+	return(ULINT_UNDEFINED);
+}
 
 /**************************************************************************
 Looks for a descriptor bit having the desired value. Scans the extent in
@@ -458,7 +458,7 @@
 	mtr_t*	mtr)	/* in: mtr */
 {
 	ulint	i;
-	
+
 	ut_ad(descr && mtr);
 	ut_ad(val <= TRUE);
 	ut_ad(hint < FSP_EXTENT_SIZE);
@@ -477,9 +477,9 @@
 			return(i);
 		}
 	}
-	
-	return(ULINT_UNDEFINED);			
-}	
+
+	return(ULINT_UNDEFINED);
+}
 
 /**************************************************************************
 Returns the number of used pages in a descriptor. */
@@ -493,7 +493,7 @@
 {
 	ulint	i;
 	ulint	count	= 0;
-	
+
 	ut_ad(descr && mtr);
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
 							MTR_MEMO_PAGE_X_FIX));
@@ -503,8 +503,8 @@
 		}
 	}
 
-	return(count);		
-}	
+	return(count);
+}
 
 /**************************************************************************
 Returns true if extent contains no used pages. */
@@ -558,7 +558,7 @@
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
 							MTR_MEMO_PAGE_X_FIX));
 
-	mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr); 
+	mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
 }
 
 /**************************************************************************
@@ -575,7 +575,7 @@
 	ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
 							MTR_MEMO_PAGE_X_FIX));
 
-	return(mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr)); 
+	return(mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr));
 }
 
 /**************************************************************************
@@ -599,7 +599,7 @@
 	}
 
 	xdes_set_state(descr, XDES_FREE, mtr);
-}	
+}
 
 /************************************************************************
 Calculates the page where the descriptor of a page resides. */
@@ -610,8 +610,10 @@
 				/* out: descriptor page offset */
 	ulint	offset)		/* in: page offset */
 {
-	ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET
-		+ (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE) * XDES_SIZE);
+#if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \
+		+ (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE) * XDES_SIZE
+# error
+#endif
 
 	return(ut_2pow_round(offset, XDES_DESCRIBED_PER_PAGE));
 }
@@ -644,7 +646,7 @@
 				space or if offset > free limit */
 	fsp_header_t*	sp_header,/* in: space header, x-latched */
 	ulint		space,	/* in: space id */
-	ulint		offset,	/* in: page offset; 
+	ulint		offset,	/* in: page offset;
 				if equal to the free limit,
 				we try to add new extents to
 				the space free list */
@@ -687,10 +689,10 @@
 #ifdef UNIV_SYNC_DEBUG
 		buf_page_dbg_add_level(descr_page, SYNC_FSP_PAGE);
 #endif /* UNIV_SYNC_DEBUG */
-	}	
+	}
 
 	return(descr_page + XDES_ARR_OFFSET
-	       + XDES_SIZE * xdes_calc_descriptor_index(offset));
+		+ XDES_SIZE * xdes_calc_descriptor_index(offset));
 }
 
 /************************************************************************
@@ -718,7 +720,7 @@
 				+ buf_page_get(space, 0, RW_X_LATCH, mtr);
 #ifdef UNIV_SYNC_DEBUG
 	buf_page_dbg_add_level(sp_header, SYNC_FSP_PAGE);
-#endif /* UNIV_SYNC_DEBUG */	
+#endif /* UNIV_SYNC_DEBUG */
 	return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset,
 									mtr));
 }
@@ -789,13 +791,13 @@
 static
 void
 fsp_init_file_page_low(
-/*=====================*/
+/*===================*/
 	byte*	ptr)	/* in: pointer to a page */
 {
 	page_t*	page;
 	page = buf_frame_align(ptr);
 
-	buf_block_align(page)->check_index_page_at_flush = FALSE;	
+	buf_block_align(page)->check_index_page_at_flush = FALSE;
 
 #ifdef UNIV_BASIC_LOG_DEBUG
 	memset(page, 0xff, UNIV_PAGE_SIZE);
@@ -807,7 +809,6 @@
 
 /***************************************************************
 Inits a file page whose prior contents should be ignored. */
-
 static
 void
 fsp_init_file_page(
@@ -816,10 +817,10 @@
 	mtr_t*	mtr)	/* in: mtr */
 {
 	fsp_init_file_page_low(page);
-		
+
 	mlog_write_initial_log_record(page, MLOG_INIT_FILE_PAGE, mtr);
 }
-	
+
 /***************************************************************
 Parses a redo log record of a file page init. */
 
@@ -836,7 +837,7 @@
 	if (page) {
 		fsp_init_file_page_low(page);
 	}
-	
+
 	return(ptr);
 }
 
@@ -872,11 +873,11 @@
 /*============*/
 	ulint	space,	/* in: space id */
 	ulint	size,	/* in: current size in blocks */
-	mtr_t*	mtr)	/* in: mini-transaction handle */	
+	mtr_t*	mtr)	/* in: mini-transaction handle */
 {
 	fsp_header_t*	header;
 	page_t*		page;
-	
+
 	ut_ad(mtr);
 
 	mtr_x_lock(fil_space_get_latch(space), mtr);
@@ -891,22 +892,26 @@
 
 	fsp_init_file_page(page, mtr);
 
+	mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_FSP_HDR,
+					MLOG_2BYTES, mtr);
+
 	header = FSP_HEADER_OFFSET + page;
 
 	mlog_write_ulint(header + FSP_SPACE_ID, space, MLOG_4BYTES, mtr);
+	mlog_write_ulint(header + FSP_NOT_USED, 0, MLOG_4BYTES, mtr);
+
+	mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
+	mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
+	mlog_write_ulint(header + FSP_LOWEST_NO_WRITE, 0, MLOG_4BYTES, mtr);
+	mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);
 
-	mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr); 
-	mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr); 
-	mlog_write_ulint(header + FSP_LOWEST_NO_WRITE, 0, MLOG_4BYTES, mtr); 
-	mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr); 
-	
 	flst_init(header + FSP_FREE, mtr);
 	flst_init(header + FSP_FREE_FRAG, mtr);
 	flst_init(header + FSP_FULL_FRAG, mtr);
 	flst_init(header + FSP_SEG_INODES_FULL, mtr);
 	flst_init(header + FSP_SEG_INODES_FREE, mtr);
 
-	mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr); 
+	mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
 	if (space == 0) {
 		fsp_fill_free_list(FALSE, space, header, mtr);
 		btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, space,
@@ -933,10 +938,10 @@
 	id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
 
 	if (id != fsp_id) {
-	        fprintf(stderr,
+		fprintf(stderr,
 "InnoDB: Error: space id in fsp header %lu, but in the page header %lu\n",
-							    (ulong) fsp_id,
-							    (ulong) id);
+			(ulong) fsp_id, (ulong) id);
+
 		return(ULINT_UNDEFINED);
 	}
 
@@ -951,21 +956,21 @@
 /*================*/
 	ulint	space,	/* in: space id */
 	ulint	size_inc,/* in: size increment in pages */
-	mtr_t*	mtr)	/* in: mini-transaction handle */	
+	mtr_t*	mtr)	/* in: mini-transaction handle */
 {
 	fsp_header_t*	header;
 	ulint		size;
-	
+
 	ut_ad(mtr);
 
-	mtr_x_lock(fil_space_get_latch(space), mtr);	
+	mtr_x_lock(fil_space_get_latch(space), mtr);
 
 	header = fsp_get_space_header(space, mtr);
 
 	size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
 
 	mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES,
-									mtr); 
+									mtr);
 }
 
 /**************************************************************************
@@ -985,17 +990,17 @@
 	mtr_t		mtr;
 
 	ut_a(space == 0); /* We have only one log_fsp_current_... variable */
-	
+
 	mtr_start(&mtr);
 
-	mtr_x_lock(fil_space_get_latch(space), &mtr);	
+	mtr_x_lock(fil_space_get_latch(space), &mtr);
 
 	header = fsp_get_space_header(space, &mtr);
 
 	limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr);
 
 	limit = limit / ((1024 * 1024) / UNIV_PAGE_SIZE);
-	
+
 	log_fsp_current_free_limit_set_and_checkpoint(limit);
 
 	mtr_commit(&mtr);
@@ -1019,10 +1024,10 @@
 	mtr_t		mtr;
 
 	ut_a(space == 0); /* We have only one log_fsp_current_... variable */
-	
+
 	mtr_start(&mtr);
 
-	mtr_x_lock(fil_space_get_latch(space), &mtr);	
+	mtr_x_lock(fil_space_get_latch(space), &mtr);
 
 	header = fsp_get_space_header(space, &mtr);
 
@@ -1053,14 +1058,14 @@
 	ut_a(space != 0);
 
 	size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
-	
+
 	ut_a(page_no >= size);
 
 	success = fil_extend_space_to_desired_size(&actual_size, space,
 								page_no + 1);
 	/* actual_size now has the space size in pages; it may be less than
 	we wanted if we ran out of disk space */
-	
+
 	mlog_write_ulint(header + FSP_SIZE, actual_size, MLOG_4BYTES, mtr);
 
 	return(success);
@@ -1116,10 +1121,10 @@
 			size_increase = SRV_AUTO_EXTEND_INCREMENT;
 		}
 	} else {
-	        if (space == 0) {
+		if (space == 0) {
 			size_increase = SRV_AUTO_EXTEND_INCREMENT;
 		} else {
-		        /* We extend single-table tablespaces first one extent
+			/* We extend single-table tablespaces first one extent
 			at a time, but for bigger tablespaces more. It is not
 			enough to extend always by one extent, because some
 			extents are frag page extents. */
@@ -1135,14 +1140,14 @@
 
 					*actual_increase = new_size - old_size;
 
-				        return(FALSE);
+					return(FALSE);
 				}
 
 				size = FSP_EXTENT_SIZE;
 			}
 
 			if (size < 32 * FSP_EXTENT_SIZE) {
-			        size_increase = FSP_EXTENT_SIZE;
+				size_increase = FSP_EXTENT_SIZE;
 			} else {
 				/* Below in fsp_fill_free_list() we assume
 				that we add at most FSP_FREE_ADD extents at
@@ -1151,18 +1156,18 @@
 			}
 		}
 	}
-				
+
 	if (size_increase == 0) {
 
 		return(TRUE);
 	}
-	
+
 	success = fil_extend_space_to_desired_size(&actual_size, space,
 							size + size_increase);
 	/* We ignore any fragments of a full megabyte when storing the size
 	to the space header */
 
-	mlog_write_ulint(header + FSP_SIZE, 
+	mlog_write_ulint(header + FSP_SIZE,
 	   ut_calc_align_down(actual_size, (1024 * 1024) / UNIV_PAGE_SIZE),
 							MLOG_4BYTES, mtr);
 	new_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
@@ -1192,7 +1197,7 @@
 	ulint	limit;
 	ulint	size;
 	xdes_t*	descr;
-	ulint	count 		= 0;
+	ulint	count		= 0;
 	ulint	frag_n_used;
 	page_t*	descr_page;
 	page_t*	ibuf_page;
@@ -1201,7 +1206,7 @@
 	mtr_t	ibuf_mtr;
 
 	ut_ad(header && mtr);
-	
+
 	/* Check if we can fill free list from above the free list limit */
 	size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
 	limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
@@ -1223,17 +1228,17 @@
 	}
 
 	i = limit;
-		
+
 	while ((init_space && i < 1)
-	       || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
+		|| ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
 
 		mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
-							MLOG_4BYTES, mtr); 
+							MLOG_4BYTES, mtr);
 
 		/* Update the free limit info in the log system and make
 		a checkpoint */
 		if (space == 0) {
-		        log_fsp_current_free_limit_set_and_checkpoint(
+			log_fsp_current_free_limit_set_and_checkpoint(
 				(i + FSP_EXTENT_SIZE)
 				/ ((1024 * 1024) / UNIV_PAGE_SIZE));
 		}
@@ -1252,13 +1257,15 @@
 								SYNC_FSP_PAGE);
 #endif /* UNIV_SYNC_DEBUG */
 				fsp_init_file_page(descr_page, mtr);
+				mlog_write_ulint(descr_page + FIL_PAGE_TYPE,
+					FIL_PAGE_TYPE_XDES, MLOG_2BYTES, mtr);
 			}
 
 			/* Initialize the ibuf bitmap page in a separate
 			mini-transaction because it is low in the latching
 			order, and we must be able to release its latch
 			before returning from the fsp routine */
-			
+
 			mtr_start(&ibuf_mtr);
 
 			ibuf_page = buf_page_create(space,
@@ -1279,7 +1286,9 @@
 									mtr);
 		xdes_init(descr, mtr);
 
-		ut_ad(XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE == 0);
+#if XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE
+# error "XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE != 0"
+#endif
 
 		if (0 == i % XDES_DESCRIBED_PER_PAGE) {
 
@@ -1289,24 +1298,24 @@
 
 			xdes_set_bit(descr, XDES_FREE_BIT, 0, FALSE, mtr);
 			xdes_set_bit(descr, XDES_FREE_BIT,
-					FSP_IBUF_BITMAP_OFFSET, FALSE, mtr);
+				FSP_IBUF_BITMAP_OFFSET, FALSE, mtr);
 			xdes_set_state(descr, XDES_FREE_FRAG, mtr);
 
 			flst_add_last(header + FSP_FREE_FRAG,
-					descr + XDES_FLST_NODE, mtr);
+				descr + XDES_FLST_NODE, mtr);
 			frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
-						     MLOG_4BYTES, mtr);
+				MLOG_4BYTES, mtr);
 			mlog_write_ulint(header + FSP_FRAG_N_USED,
-					frag_n_used + 2, MLOG_4BYTES, mtr);
+				frag_n_used + 2, MLOG_4BYTES, mtr);
 		} else {
 			flst_add_last(header + FSP_FREE,
-						descr + XDES_FLST_NODE, mtr);
+				descr + XDES_FLST_NODE, mtr);
 			count++;
 		}
 
 		i += FSP_EXTENT_SIZE;
 	}
-}	
+}
 
 /**************************************************************************
 Allocates a new free extent. */
@@ -1325,7 +1334,7 @@
 	fsp_header_t*	header;
 	fil_addr_t	first;
 	xdes_t*		descr;
-	
+
 	ut_ad(mtr);
 
 	header = fsp_get_space_header(space, mtr);
@@ -1334,7 +1343,7 @@
 
 	if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) {
 		/* Ok, we can take this extent */
-	} else {	
+	} else {
 		/* Take the first extent in the free list */
 		first = flst_get_first(header + FSP_FREE, mtr);
 
@@ -1348,7 +1357,7 @@
 
 			return(NULL);	/* No free extents left */
 		}
-	
+
 		descr = xdes_lst_get_descriptor(space, first, mtr);
 	}
 
@@ -1378,7 +1387,7 @@
 	ulint		page_no;
 	ulint		space_size;
 	ibool		success;
-	
+
 	ut_ad(mtr);
 
 	header = fsp_get_space_header(space, mtr);
@@ -1399,7 +1408,7 @@
 			extent containing a descriptor page is added to the
 			FREE_FRAG list. But we will allocate our page from the
 			the free extent anyway. */
-			
+
 			descr = fsp_alloc_free_extent(space, hint, mtr);
 
 			if (descr == NULL) {
@@ -1436,22 +1445,22 @@
 	space_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
 
 	if (space_size <= page_no) {
-	        /* It must be that we are extending a single-table tablespace
+		/* It must be that we are extending a single-table tablespace
 		whose size is still < 64 pages */
 
 		ut_a(space != 0);
 		if (page_no >= FSP_EXTENT_SIZE) {
-		        fprintf(stderr,
+			fprintf(stderr,
 "InnoDB: Error: trying to extend a single-table tablespace %lu\n"
 "InnoDB: by single page(s) though the space size %lu. Page no %lu.\n",
 			   (ulong) space, (ulong) space_size, (ulong) page_no);
 			return(FIL_NULL);
 		}
 		success = fsp_try_extend_data_file_with_pages(space, page_no,
-							      header, mtr);
+			header, mtr);
 		if (!success) {
 			/* No disk space left */
-		        return(FIL_NULL);
+			return(FIL_NULL);
 		}
 	}
 
@@ -1468,7 +1477,7 @@
 		flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
 									mtr);
 		xdes_set_state(descr, XDES_FULL_FRAG, mtr);
-		
+
 		flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
 									mtr);
 		mlog_write_ulint(header + FSP_FRAG_N_USED,
@@ -1479,17 +1488,17 @@
 	/* Initialize the allocated page to the buffer pool, so that it can
 	be obtained immediately with buf_page_get without need for a disk
 	read. */
-	
+
 	buf_page_create(space, page_no, mtr);
 
-	page = buf_page_get(space, page_no, RW_X_LATCH, mtr);	
+	page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
 #ifdef UNIV_SYNC_DEBUG
 	buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
 #endif /* UNIV_SYNC_DEBUG */
 
 	/* Prior contents of the page should be ignored */
 	fsp_init_file_page(page, mtr);
-	
+
 	return(page_no);
 }
 
@@ -1507,7 +1516,7 @@
 	xdes_t*		descr;
 	ulint		state;
 	ulint		frag_n_used;
-	
+
 	ut_ad(mtr);
 
 /*	fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */
@@ -1517,7 +1526,7 @@
 	descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
 
 	state = xdes_get_state(descr, mtr);
-	
+
 	if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) {
 		fprintf(stderr,
 "InnoDB: Error: File space extent descriptor of page %lu has state %lu\n",
@@ -1526,7 +1535,7 @@
 		fputs("InnoDB: Dump of descriptor: ", stderr);
 		ut_print_buf(stderr, ((byte*)descr) - 50, 200);
 		putc('\n', stderr);
-		
+
 		if (state == XDES_FREE) {
 			/* We put here some fault tolerance: if the page
 			is already free, return without doing anything! */
@@ -1572,11 +1581,11 @@
 	}
 
 	if (xdes_is_free(descr, mtr)) {
-	    	/* The extent has become free: move it to another list */
+		/* The extent has become free: move it to another list */
 		flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
 									mtr);
 		fsp_free_extent(space, page, mtr);
-	}		
+	}
 }
 
 /**************************************************************************
@@ -1591,7 +1600,7 @@
 {
 	fsp_header_t*	header;
 	xdes_t*		descr;
-	
+
 	ut_ad(mtr);
 
 	header = fsp_get_space_header(space, mtr);
@@ -1629,7 +1638,7 @@
 }
 
 /**************************************************************************
-Looks for a used segment inode on a segment inode page. */ 
+Looks for a used segment inode on a segment inode page. */
 static
 ulint
 fsp_seg_inode_page_find_used(
@@ -1649,7 +1658,7 @@
 		if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID),
 						ut_dulint_zero) != 0) {
 			/* This is used */
-			
+
 			return(i);
 		}
 	}
@@ -1658,7 +1667,7 @@
 }
 
 /**************************************************************************
-Looks for an unused segment inode on a segment inode page. */ 
+Looks for an unused segment inode on a segment inode page. */
 static
 ulint
 fsp_seg_inode_page_find_free(
@@ -1679,7 +1688,7 @@
 		if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID),
 						ut_dulint_zero) == 0) {
 			/* This is unused */
-			
+
 			return(i);
 		}
 	}
@@ -1704,7 +1713,7 @@
 	ulint		i;
 
 	space = buf_frame_get_space_id(space_header);
-	
+
 	page_no = fsp_alloc_free_page(space, 0, mtr);
 
 	if (page_no == FIL_NULL) {
@@ -1712,11 +1721,12 @@
 		return(FALSE);
 	}
 
-	page = buf_page_get(space, page_no, RW_X_LATCH, mtr);	
+	page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
 
 	buf_block_align(page)->check_index_page_at_flush = FALSE;
 
-	fil_page_set_type(page, FIL_PAGE_INODE);
+	mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_INODE,
+						MLOG_2BYTES, mtr);
 #ifdef UNIV_SYNC_DEBUG
 	buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
 #endif /* UNIV_SYNC_DEBUG */
@@ -1749,7 +1759,7 @@
 	fseg_inode_t*	inode;
 	ibool		success;
 	ulint		n;
-	
+
 	if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) {
 		/* Allocate a new segment inode page */
 
@@ -1776,7 +1786,7 @@
 	inode = fsp_seg_inode_page_get_nth_inode(page, n, mtr);
 
 	if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
-								    mtr)) {
+			mtr)) {
 		/* There are no other unused headers left on the page: move it
 		to another list */
 
@@ -1787,7 +1797,7 @@
 				page + FSEG_INODE_PAGE_NODE, mtr);
 	}
 
-	return(inode);	
+	return(inode);
 }
 
 /**************************************************************************
@@ -1802,7 +1812,7 @@
 {
 	page_t*		page;
 	fsp_header_t*	space_header;
-	
+
 	page = buf_frame_align(inode);
 
 	space_header = fsp_get_space_header(space, mtr);
@@ -1820,9 +1830,9 @@
 				page + FSEG_INODE_PAGE_NODE, mtr);
 	}
 
-	mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr); 
-	mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr); 
-	
+	mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
+	mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr);
+
 	if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(page, mtr)) {
 
 		/* There are no other used headers left on the page: free it */
@@ -1849,10 +1859,10 @@
 
 	inode_addr.page = mach_read_from_4(header + FSEG_HDR_PAGE_NO);
 	inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET);
-	
+
 	inode = fut_get_ptr(mach_read_from_4(header + FSEG_HDR_SPACE),
 						inode_addr, RW_X_LATCH, mtr);
-	
+
 	ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
 
 	return(inode);
@@ -1865,7 +1875,7 @@
 fseg_get_nth_frag_page_no(
 /*======================*/
 				/* out: page number, FIL_NULL if not in use */
-	fseg_inode_t* 	inode,	/* in: segment inode */
+	fseg_inode_t*	inode,	/* in: segment inode */
 	ulint		n,	/* in: slot index */
 	mtr_t*		mtr __attribute__((unused))) /* in: mtr handle */
 {
@@ -1883,7 +1893,7 @@
 void
 fseg_set_nth_frag_page_no(
 /*======================*/
-	fseg_inode_t* 	inode,	/* in: segment inode */
+	fseg_inode_t*	inode,	/* in: segment inode */
 	ulint		n,	/* in: slot index */
 	ulint		page_no,/* in: page number to set */
 	mtr_t*		mtr)	/* in: mtr handle */
@@ -1905,7 +1915,7 @@
 /*==========================*/
 				/* out: slot index; ULINT_UNDEFINED if none
 				found */
-	fseg_inode_t* 	inode,	/* in: segment inode */
+	fseg_inode_t*	inode,	/* in: segment inode */
 	mtr_t*		mtr)	/* in: mtr handle */
 {
 	ulint	i;
@@ -1933,7 +1943,7 @@
Thread
bk commit into 5.1 tree (evgen:1.2286)eugene30 Aug