List:Commits« Previous MessageNext Message »
From:ahristov Date:November 16 2006 1:31pm
Subject:bk commit into 5.0 tree (andrey:1.2335)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of andrey. When andrey 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-11-16 13:31:35+01:00, andrey@stripped +3 -0
  Merge example.com:/work/bug24219/my41
  into  example.com:/work/bug24219/my50
  MERGE: 1.1616.2697.89

  mysql-test/r/alter_table.result@stripped, 2006-11-16 13:31:32+01:00, andrey@stripped +21
-21
    manual merge
    MERGE: 1.40.1.10

  mysql-test/t/alter_table.test@stripped, 2006-11-16 13:31:32+01:00, andrey@stripped +21
-20
    manual merge
    MERGE: 1.29.1.11

  sql/sql_table.cc@stripped, 2006-11-16 13:30:55+01:00, andrey@stripped +718 -1185
    manual-merge
    MERGE: 1.157.2.153

# 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:	andrey
# Host:	example.com
# Root:	/work/bug24219/my50/RESYNC

--- 1.324/sql/sql_table.cc	2006-11-16 13:31:47 +01:00
+++ 1.325/sql/sql_table.cc	2006-11-16 13:31:47 +01:00
@@ -14,6 +14,7 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+
 /* drop and alter of tables */
 
 #include "mysql_priv.h"
@@ -23,8 +24,6 @@
 #include <hash.h>
 #include <myisam.h>
 #include <my_dir.h>
-#include "sp_head.h"
-#include "sql_trigger.h"
 
 #ifdef __WIN__
 #include <io.h>
@@ -35,12 +34,11 @@ const char *primary_key_name="PRIMARY";
 static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
 static int copy_data_between_tables(TABLE *from,TABLE *to,
-                                    List<create_field> &create, bool ignore,
+				    List<create_field> &create,
+				    enum enum_duplicates handle_duplicates,
+                                    bool ignore,
 				    uint order_num, ORDER *order,
 				    ha_rows *copied,ha_rows *deleted);
-static bool prepare_blob_field(THD *thd, create_field *sql_field);
-static bool check_engine(THD *thd, const char *table_name,
-                         enum db_type *new_engine);                             
 
 
 /*
@@ -88,41 +86,41 @@ static uint build_table_path(char *buff,
     Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
 
   RETURN
-    FALSE OK.  In this case ok packet is sent to user
-    TRUE  Error
+    0		ok.  In this case ok packet is sent to user
+    -1		Error  (Error message given but not sent to user)
 
 */
 
-bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
-                    my_bool drop_temporary)
+int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+		   my_bool drop_temporary)
 {
-  bool error= FALSE, need_start_waiters= FALSE;
+  int error= 0;
   DBUG_ENTER("mysql_rm_table");
 
   /* mark for close and remove all cached entries */
 
-  if (!drop_temporary)
-  {
-    if ((error= wait_if_global_read_lock(thd, 0, 1)))
-    {
-      my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
-      DBUG_RETURN(TRUE);
-    }
-    else
-      need_start_waiters= TRUE;
-  }
-
-  /*
-    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
-    LOCK_open during wait_if_global_read_lock(), other threads could not
-    close their tables. This would make a pretty deadlock.
-  */
   thd->mysys_var->current_mutex= &LOCK_open;
   thd->mysys_var->current_cond= &COND_refresh;
   VOID(pthread_mutex_lock(&LOCK_open));
 
-  error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
+  if (!drop_temporary && global_read_lock)
+  {
+    if (thd->global_read_lock)
+    {
+      my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
+	       tables->real_name);
+      error= 1;
+      goto err;
+    }
+    while (global_read_lock && ! thd->killed)
+    {
+      (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+    }
 
+  }
+  error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, 0);
+
+ err:
   pthread_mutex_unlock(&LOCK_open);
 
   pthread_mutex_lock(&thd->mysys_var->mutex);
@@ -130,13 +128,10 @@ bool mysql_rm_table(THD *thd,TABLE_LIST 
   thd->mysys_var->current_cond= 0;
   pthread_mutex_unlock(&thd->mysys_var->mutex);
 
-  if (need_start_waiters)
-    start_waiting_global_read_lock(thd);
-
   if (error)
-    DBUG_RETURN(TRUE);
+    DBUG_RETURN(-1);
   send_ok(thd);
-  DBUG_RETURN(FALSE);
+  DBUG_RETURN(0);
 }
 
 
@@ -144,12 +139,11 @@ bool mysql_rm_table(THD *thd,TABLE_LIST 
  delete (drop) tables.
 
   SYNOPSIS
-    mysql_rm_table_part2_with_lock()
-    thd			Thread handle
-    tables		List of tables to delete
-    if_exists		If 1, don't give error if one table doesn't exists
-    dont_log_query	Don't write query to log files. This will also not
-                        generate warnings if the handler files doesn't exists
+   mysql_rm_table_part2_with_lock()
+   thd			Thread handle
+   tables		List of tables to delete
+   if_exists		If 1, don't give error if one table doesn't exists
+   dont_log_query	Don't write query to log files
 
  NOTES
    Works like documented in mysql_rm_table(), but don't check
@@ -169,8 +163,8 @@ int mysql_rm_table_part2_with_lock(THD *
   thd->mysys_var->current_cond= &COND_refresh;
   VOID(pthread_mutex_lock(&LOCK_open));
 
-  error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 1,
-			      dont_log_query);
+  error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary,
+			     dont_log_query);
 
   pthread_mutex_unlock(&LOCK_open);
 
@@ -192,9 +186,7 @@ int mysql_rm_table_part2_with_lock(THD *
     if_exists		If set, don't give an error if table doesn't exists.
 			In this case we give an warning of level 'NOTE'
     drop_temporary	Only drop temporary tables
-    drop_view		Allow to delete VIEW .frm
-    dont_log_query	Don't write query to log files. This will also not
-			generate warnings if the handler files doesn't exists  
+    dont_log_query	Don't log the query
 
   TODO:
     When logging to the binary log, we should log
@@ -213,30 +205,23 @@ int mysql_rm_table_part2_with_lock(THD *
 */
 
 int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
-			 bool drop_temporary, bool drop_view,
-			 bool dont_log_query)
+			 bool drop_temporary, bool dont_log_query)
 {
   TABLE_LIST *table;
   char	path[FN_REFLEN], *alias;
   String wrong_tables;
   int error;
   bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
-
   DBUG_ENTER("mysql_rm_table_part2");
 
   if (!drop_temporary && lock_table_names(thd, tables))
     DBUG_RETURN(1);
 
-  /* Don't give warnings for not found errors, as we already generate notes */
-  thd->no_warnings_for_error= 1;
-
-  for (table= tables; table; table= table->next_local)
+  for (table=tables ; table ; table=table->next)
   {
     char *db=table->db;
-    db_type table_type= DB_TYPE_UNKNOWN;
-
     mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
-    if (!close_temporary_table(thd, db, table->table_name))
+    if (!close_temporary_table(thd, db, table->real_name))
     {
       tmp_table_deleted=1;
       continue;					// removed temporary table
@@ -245,69 +230,55 @@ int mysql_rm_table_part2(THD *thd, TABLE
     error=0;
     if (!drop_temporary)
     {
-      abort_locked_tables(thd, db, table->table_name);
-      remove_table_from_cache(thd, db, table->table_name,
-	                      RTFC_WAIT_OTHER_THREAD_FLAG |
-			      RTFC_CHECK_KILLED_FLAG);
-      drop_locked_tables(thd, db, table->table_name);
+      abort_locked_tables(thd,db,table->real_name);
+      remove_table_from_cache(thd,db,table->real_name,
+                              RTFC_WAIT_OTHER_THREAD_FLAG |
+                              RTFC_CHECK_KILLED_FLAG);
+      drop_locked_tables(thd,db,table->real_name);
       if (thd->killed)
-      {
-        thd->no_warnings_for_error= 0;
 	DBUG_RETURN(-1);
-      }
-      alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
+      alias= (lower_case_table_names == 2) ? table->alias : table->real_name;
       /* remove form file and isam files */
       build_table_path(path, sizeof(path), db, alias, reg_ext);
     }
     if (drop_temporary ||
-       (access(path,F_OK) &&
-         ha_create_table_from_engine(thd,db,alias)) ||
-        (!drop_view &&
-	 mysql_frm_type(thd, path, &table_type) != FRMTYPE_TABLE))
+	(access(path,F_OK) &&
+         ha_create_table_from_engine(thd, db, alias)))
     {
       // Table was not found on disk and table can't be created from engine
       if (if_exists)
 	push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 			    ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
-			    table->table_name);
+			    table->real_name);
       else
         error= 1;
     }
     else
     {
       char *end;
-      if (table_type == DB_TYPE_UNKNOWN)
-	mysql_frm_type(thd, path, &table_type);
+      db_type table_type= get_table_type(path);
       *(end=fn_ext(path))=0;			// Remove extension for delete
-      error= ha_delete_table(thd, table_type, path, table->table_name,
-                             !dont_log_query);
-      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && 
-	  (if_exists || table_type == DB_TYPE_UNKNOWN))
-	error= 0;
+      error=ha_delete_table(table_type, path);
+      if (error == ENOENT && if_exists)
+	error = 0;
       if (error == HA_ERR_ROW_IS_REFERENCED)
       {
 	/* the table is referenced by a foreign key constraint */
 	foreign_key_error=1;
       }
-      if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
+      if (!error || error == ENOENT)
       {
-        int new_error;
 	/* Delete the table definition file */
 	strmov(end,reg_ext);
-	if (!(new_error=my_delete(path,MYF(MY_WME))))
-        {
+	if (!(error=my_delete(path,MYF(MY_WME))))
 	  some_tables_deleted=1;
-          new_error= Table_triggers_list::drop_all_triggers(thd, db,
-                                                            table->table_name);
-        }
-        error|= new_error;
       }
     }
     if (error)
     {
       if (wrong_tables.length())
 	wrong_tables.append(',');
-      wrong_tables.append(String(table->table_name,system_charset_info));
+      wrong_tables.append(String(table->real_name,system_charset_info));
     }
   }
   thd->tmp_table_used= tmp_table_deleted;
@@ -316,27 +287,32 @@ int mysql_rm_table_part2(THD *thd, TABLE
   {
     if (!foreign_key_error)
       my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
-                      wrong_tables.c_ptr());
+                     wrong_tables.c_ptr());
     else
-      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
+      my_error(ER_ROW_IS_REFERENCED, MYF(0));
     error= 1;
   }
 
   if (some_tables_deleted || tmp_table_deleted || !error)
   {
     query_cache_invalidate3(thd, tables, 0);
-    if (!dont_log_query && mysql_bin_log.is_open())
+    if (!dont_log_query)
     {
-      if (!error)
-        thd->clear_error();
-      Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
-      mysql_bin_log.write(&qinfo);
+      mysql_update_log.write(thd, thd->query,thd->query_length);
+      if (mysql_bin_log.is_open())
+      {
+        if (!error)
+          thd->clear_error();
+	Query_log_event qinfo(thd, thd->query, thd->query_length,
+			      tmp_table_deleted && !some_tables_deleted, 
+			      FALSE);
+	mysql_bin_log.write(&qinfo);
+      }
     }
   }
 
   if (!drop_temporary)
-    unlock_table_names(thd, tables, (TABLE_LIST*) 0);
-  thd->no_warnings_for_error= 0;
+    unlock_table_names(thd, tables);
   DBUG_RETURN(error);
 }
 
@@ -350,7 +326,7 @@ int quick_rm_table(enum db_type base,con
   if (my_delete(path,MYF(0)))
     error=1; /* purecov: inspected */
   *fn_ext(path)= 0;                             // Remove reg_ext
-  return ha_delete_table(current_thd, base, path, table_name, 0) || error;
+  return ha_delete_table(base,path) || error;
 }
 
 /*
@@ -473,171 +449,6 @@ void calculate_interval_lengths(CHARSET_
 
 
 /*
-  Prepare a create_table instance for packing
-
-  SYNOPSIS
-    prepare_create_field()
-    sql_field     field to prepare for packing
-    blob_columns  count for BLOBs
-    timestamps    count for timestamps
-    table_flags   table flags
-
-  DESCRIPTION
-    This function prepares a create_field instance.
-    Fields such as pack_flag are valid after this call.
-
-  RETURN VALUES
-   0	ok
-   1	Error
-*/
-
-int prepare_create_field(create_field *sql_field, 
-			 uint *blob_columns, 
-			 int *timestamps, int *timestamps_with_niladic,
-			 uint table_flags)
-{
-  DBUG_ENTER("prepare_field");
-
-  /*
-    This code came from mysql_prepare_table.
-    Indent preserved to make patching easier
-  */
-  DBUG_ASSERT(sql_field->charset);
-
-  switch (sql_field->sql_type) {
-  case FIELD_TYPE_BLOB:
-  case FIELD_TYPE_MEDIUM_BLOB:
-  case FIELD_TYPE_TINY_BLOB:
-  case FIELD_TYPE_LONG_BLOB:
-    sql_field->pack_flag=FIELDFLAG_BLOB |
-      pack_length_to_packflag(sql_field->pack_length -
-                              portable_sizeof_char_ptr);
-    if (sql_field->charset->state & MY_CS_BINSORT)
-      sql_field->pack_flag|=FIELDFLAG_BINARY;
-    sql_field->length=8;			// Unireg field length
-    sql_field->unireg_check=Field::BLOB_FIELD;
-    (*blob_columns)++;
-    break;
-  case FIELD_TYPE_GEOMETRY:
-#ifdef HAVE_SPATIAL
-    if (!(table_flags & HA_CAN_GEOMETRY))
-    {
-      my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
-                      MYF(0), "GEOMETRY");
-      DBUG_RETURN(1);
-    }
-    sql_field->pack_flag=FIELDFLAG_GEOM |
-      pack_length_to_packflag(sql_field->pack_length -
-                              portable_sizeof_char_ptr);
-    if (sql_field->charset->state & MY_CS_BINSORT)
-      sql_field->pack_flag|=FIELDFLAG_BINARY;
-    sql_field->length=8;			// Unireg field length
-    sql_field->unireg_check=Field::BLOB_FIELD;
-    (*blob_columns)++;
-    break;
-#else
-    my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
-                    sym_group_geom.name, sym_group_geom.needed_define);
-    DBUG_RETURN(1);
-#endif /*HAVE_SPATIAL*/
-  case MYSQL_TYPE_VARCHAR:
-#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
-    if (table_flags & HA_NO_VARCHAR)
-    {
-      /* convert VARCHAR to CHAR because handler is not yet up to date */
-      sql_field->sql_type=    MYSQL_TYPE_VAR_STRING;
-      sql_field->pack_length= calc_pack_length(sql_field->sql_type,
-                                               (uint) sql_field->length);
-      if ((sql_field->length / sql_field->charset->mbmaxlen) >
-          MAX_FIELD_CHARLENGTH)
-      {
-        my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
-                        MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
-        DBUG_RETURN(1);
-      }
-    }
-#endif
-    /* fall through */
-  case FIELD_TYPE_STRING:
-    sql_field->pack_flag=0;
-    if (sql_field->charset->state & MY_CS_BINSORT)
-      sql_field->pack_flag|=FIELDFLAG_BINARY;
-    break;
-  case FIELD_TYPE_ENUM:
-    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
-      FIELDFLAG_INTERVAL;
-    if (sql_field->charset->state & MY_CS_BINSORT)
-      sql_field->pack_flag|=FIELDFLAG_BINARY;
-    sql_field->unireg_check=Field::INTERVAL_FIELD;
-    check_duplicates_in_interval("ENUM",sql_field->field_name,
-                                 sql_field->interval,
-                                 sql_field->charset);
-    break;
-  case FIELD_TYPE_SET:
-    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
-      FIELDFLAG_BITFIELD;
-    if (sql_field->charset->state & MY_CS_BINSORT)
-      sql_field->pack_flag|=FIELDFLAG_BINARY;
-    sql_field->unireg_check=Field::BIT_FIELD;
-    check_duplicates_in_interval("SET",sql_field->field_name,
-                                 sql_field->interval,
-                                 sql_field->charset);
-    break;
-  case FIELD_TYPE_DATE:			// Rest of string types
-  case FIELD_TYPE_NEWDATE:
-  case FIELD_TYPE_TIME:
-  case FIELD_TYPE_DATETIME:
-  case FIELD_TYPE_NULL:
-    sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
-    break;
-  case FIELD_TYPE_BIT:
-    /* 
-      We have sql_field->pack_flag already set here, see mysql_prepare_table().
-    */
-    break;
-  case FIELD_TYPE_NEWDECIMAL:
-    sql_field->pack_flag=(FIELDFLAG_NUMBER |
-                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
-                           FIELDFLAG_DECIMAL) |
-                          (sql_field->flags & ZEROFILL_FLAG ?
-                           FIELDFLAG_ZEROFILL : 0) |
-                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
-    break;
-  case FIELD_TYPE_TIMESTAMP:
-    /* We should replace old TIMESTAMP fields with their newer analogs */
-    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
-    {
-      if (!*timestamps)
-      {
-        sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
-        (*timestamps_with_niladic)++;
-      }
-      else
-        sql_field->unireg_check= Field::NONE;
-    }
-    else if (sql_field->unireg_check != Field::NONE)
-      (*timestamps_with_niladic)++;
-
-    (*timestamps)++;
-    /* fall-through */
-  default:
-    sql_field->pack_flag=(FIELDFLAG_NUMBER |
-                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
-                           FIELDFLAG_DECIMAL) |
-                          (sql_field->flags & ZEROFILL_FLAG ?
-                           FIELDFLAG_ZEROFILL : 0) |
-                          f_settype((uint) sql_field->sql_type) |
-                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
-    break;
-  }
-  if (!(sql_field->flags & NOT_NULL_FLAG))
-    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
-  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
-    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
-  DBUG_RETURN(0);
-}
-
-/*
   Preparation for table creation
 
   SYNOPSIS
@@ -650,43 +461,34 @@ int prepare_create_field(create_field *s
   DESCRIPTION
     Prepares the table and key structures for table creation.
 
-  NOTES
-    sets create_info->varchar if the table has a varchar
-
   RETURN VALUES
     0	ok
     -1	error
 */
 
-static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
-                               List<create_field> *fields,
-                               List<Key> *keys, bool tmp_table,
-                               uint *db_options,
-                               handler *file, KEY **key_info_buffer,
-                               uint *key_count, int select_field_count)
+int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
+			List<create_field> &fields,
+			List<Key> &keys, bool tmp_table, uint &db_options,
+			handler *file, KEY *&key_info_buffer,
+			uint *key_count, int select_field_count)
 {
   const char	*key_name;
   create_field	*sql_field,*dup_field;
-  uint		field,null_fields,blob_columns,max_key_length;
+  uint		field,null_fields,blob_columns;
   ulong		record_offset= 0;
   KEY		*key_info;
   KEY_PART_INFO *key_part_info;
   int		timestamps= 0, timestamps_with_niladic= 0;
   int		field_no,dup_no;
   int		select_field_pos,auto_increment=0;
-  List_iterator<create_field> it(*fields),it2(*fields);
-  uint total_uneven_bit_length= 0;
   DBUG_ENTER("mysql_prepare_table");
 
-  select_field_pos= fields->elements - select_field_count;
+  List_iterator<create_field> it(fields),it2(fields);
+  select_field_pos=fields.elements - select_field_count;
   null_fields=blob_columns=0;
-  create_info->varchar= 0;
-  max_key_length= file->max_key_length();
 
   for (field_no=0; (sql_field=it++) ; field_no++)
   {
-    CHARSET_INFO *save_cs;
-
     /*
       Initialize length from its original value (number of characters),
       which was set in the parser. This is necessary if we're
@@ -704,43 +506,42 @@ static int mysql_prepare_table(THD *thd,
     if (create_info->table_charset && sql_field->charset !=
&my_charset_bin)
       sql_field->charset= create_info->table_charset;
 
-    save_cs= sql_field->charset;
+    CHARSET_INFO *savecs= sql_field->charset;
     if ((sql_field->flags & BINCMP_FLAG) &&
 	!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
 						    MY_CS_BINSORT,MYF(0))))
     {
       char tmp[64];
-      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
-              STRING_WITH_LEN("_bin"));
+      strmake(strmake(tmp, savecs->csname, sizeof(tmp)-4), "_bin", 4);
       my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
       DBUG_RETURN(-1);
     }
 
     /*
-      Convert the default value from client character
+      Convert the default value character
       set into the column character set if necessary.
     */
     if (sql_field->def && 
-        save_cs != sql_field->def->collation.collation &&
+        savecs != sql_field->def->collation.collation &&
         (sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
          sql_field->sql_type == FIELD_TYPE_STRING ||
          sql_field->sql_type == FIELD_TYPE_SET ||
          sql_field->sql_type == FIELD_TYPE_ENUM))
     {
-      Query_arena backup_arena;
-      bool need_to_change_arena= !thd->stmt_arena->is_conventional();
+      Item_arena backup_arena;
+      bool need_to_change_arena=
+        !thd->current_arena->is_conventional_execution();
       if (need_to_change_arena)
       {
-        /* Asser that we don't do that at every PS execute */
-        DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() ||
-                    thd->stmt_arena->is_first_sp_execute());
-        thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena);
+        /* Assert that we don't do that at every PS execute */
+        DBUG_ASSERT(thd->current_arena->is_first_stmt_execute());
+        thd->set_n_backup_item_arena(thd->current_arena, &backup_arena);
       }
 
-      sql_field->def= sql_field->def->safe_charset_converter(save_cs);
+      sql_field->def= sql_field->def->safe_charset_converter(savecs);
 
       if (need_to_change_arena)
-        thd->restore_active_arena(thd->stmt_arena, &backup_arena);
+        thd->restore_backup_item_arena(thd->current_arena, &backup_arena);
 
       if (sql_field->def == NULL)
       {
@@ -768,7 +569,7 @@ static int mysql_prepare_table(THD *thd,
           Create the typelib in prepared statement memory if we're
           executing one.
         */
-        MEM_ROOT *stmt_root= thd->stmt_arena->mem_root;
+        MEM_ROOT *stmt_root= thd->current_arena->mem_root;
 
         interval= sql_field->interval= typelib(stmt_root,
                                                sql_field->interval_list);
@@ -781,20 +582,21 @@ static int mysql_prepare_table(THD *thd,
         DBUG_ASSERT(comma_length > 0);
         for (uint i= 0; (tmp= it++); i++)
         {
-          uint lengthsp;
           if (String::needs_conversion(tmp->length(), tmp->charset(),
                                        cs, &dummy))
           {
             uint cnv_errs;
             conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs,
&cnv_errs);
-            interval->type_names[i]= strmake_root(stmt_root, conv.ptr(),
-                                                  conv.length());
+            char *buf= (char*) alloc_root(stmt_root, conv.length()+1);
+            memcpy(buf, conv.ptr(), conv.length());
+            buf[conv.length()]= '\0';
+            interval->type_names[i]= buf;
             interval->type_lengths[i]= conv.length();
           }
 
           // Strip trailing spaces.
-          lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
-                                       interval->type_lengths[i]);
+          uint lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
+                                            interval->type_lengths[i]);
           interval->type_lengths[i]= lengthsp;
           ((uchar *)interval->type_names[i])[lengthsp]= '\0';
           if (sql_field->sql_type == FIELD_TYPE_SET)
@@ -803,7 +605,9 @@ static int mysql_prepare_table(THD *thd,
                                 interval->type_lengths[i], 
                                 comma_buf, comma_length, NULL, 0))
             {
-              my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
+              my_printf_error(ER_UNKNOWN_ERROR,
+                              "Illegal %s '%-.64s' value found during parsing",
+                              MYF(0), "set", tmp->ptr());
               DBUG_RETURN(-1);
             }
           }
@@ -813,7 +617,6 @@ static int mysql_prepare_table(THD *thd,
 
       if (sql_field->sql_type == FIELD_TYPE_SET)
       {
-        uint32 field_length;
         if (sql_field->def != NULL)
         {
           char *not_used;
@@ -844,12 +647,11 @@ static int mysql_prepare_table(THD *thd,
             DBUG_RETURN(-1);
           }
         }
-        calculate_interval_lengths(cs, interval, &dummy, &field_length);
-        sql_field->length= field_length + (interval->count - 1);
+        calculate_interval_lengths(cs, interval, &dummy, &sql_field->length);
+        sql_field->length+= (interval->count - 1);
       }
       else  /* FIELD_TYPE_ENUM */
       {
-        uint32 field_length;
         DBUG_ASSERT(sql_field->sql_type == FIELD_TYPE_ENUM);
         if (sql_field->def != NULL)
         {
@@ -874,25 +676,20 @@ static int mysql_prepare_table(THD *thd,
             }
           }
         }
-        calculate_interval_lengths(cs, interval, &field_length, &dummy);
-        sql_field->length= field_length;
+        calculate_interval_lengths(cs, interval, &sql_field->length, &dummy);
       }
       set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
     }
 
-    if (sql_field->sql_type == FIELD_TYPE_BIT)
-    { 
-      sql_field->pack_flag= FIELDFLAG_NUMBER;
-      if (file->table_flags() & HA_CAN_BIT_FIELD)
-        total_uneven_bit_length+= sql_field->length & 7;
-      else
-        sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
-    }
-
     sql_field->create_length_to_internal_length();
-    if (prepare_blob_field(thd, sql_field))
-      DBUG_RETURN(-1);
 
+    /* Don't pack keys in old tables if the user has requested this */
+    if ((sql_field->flags & BLOB_FLAG) ||
+	sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
+	create_info->row_type != ROW_TYPE_FIXED)
+    {
+      db_options|=HA_OPTION_PACK_RECORD;
+    }
     if (!(sql_field->flags & NOT_NULL_FLAG))
       null_fields++;
 
@@ -915,7 +712,7 @@ static int mysql_prepare_table(THD *thd,
 	*/
 	if (field_no < select_field_pos || dup_no >= select_field_pos)
 	{
-	  my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
+	  my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name);
 	  DBUG_RETURN(-1);
 	}
 	else
@@ -928,7 +725,6 @@ static int mysql_prepare_table(THD *thd,
 					 create_info->default_table_charset);
 	  sql_field->length=		dup_field->char_length;
           sql_field->pack_length=	dup_field->pack_length;
-          sql_field->key_length=	dup_field->key_length;
 	  sql_field->create_length_to_internal_length();
 	  sql_field->decimals=		dup_field->decimals;
 	  sql_field->unireg_check=	dup_field->unireg_check;
@@ -947,29 +743,115 @@ static int mysql_prepare_table(THD *thd,
 	}
       }
     }
-    /* Don't pack rows in old tables if the user has requested this */
-    if ((sql_field->flags & BLOB_FLAG) ||
-	sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
-	create_info->row_type != ROW_TYPE_FIXED)
-      (*db_options)|= HA_OPTION_PACK_RECORD;
     it2.rewind();
   }
 
   /* record_offset will be increased with 'length-of-null-bits' later */
   record_offset= 0;
-  null_fields+= total_uneven_bit_length;
 
   it.rewind();
   while ((sql_field=it++))
   {
-    DBUG_ASSERT(sql_field->charset != 0);
+    DBUG_ASSERT(sql_field->charset);
 
-    if (prepare_create_field(sql_field, &blob_columns, 
-			     &timestamps, &timestamps_with_niladic,
-			     file->table_flags()))
+    switch (sql_field->sql_type) {
+    case FIELD_TYPE_BLOB:
+    case FIELD_TYPE_MEDIUM_BLOB:
+    case FIELD_TYPE_TINY_BLOB:
+    case FIELD_TYPE_LONG_BLOB:
+      sql_field->pack_flag=FIELDFLAG_BLOB |
+	pack_length_to_packflag(sql_field->pack_length -
+				portable_sizeof_char_ptr);
+      if (sql_field->charset->state & MY_CS_BINSORT)
+	sql_field->pack_flag|=FIELDFLAG_BINARY;
+      sql_field->length=8;			// Unireg field length
+      sql_field->unireg_check=Field::BLOB_FIELD;
+      blob_columns++;
+      break;
+    case FIELD_TYPE_GEOMETRY:
+#ifdef HAVE_SPATIAL
+      if (!(file->table_flags() & HA_CAN_GEOMETRY))
+      {
+	my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
+			MYF(0), "GEOMETRY");
+	DBUG_RETURN(-1);
+      }
+      sql_field->pack_flag=FIELDFLAG_GEOM |
+	pack_length_to_packflag(sql_field->pack_length -
+				portable_sizeof_char_ptr);
+      if (sql_field->charset->state & MY_CS_BINSORT)
+	sql_field->pack_flag|=FIELDFLAG_BINARY;
+      sql_field->length=8;			// Unireg field length
+      sql_field->unireg_check=Field::BLOB_FIELD;
+      blob_columns++;
+      break;
+#else
+      my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
+		      sym_group_geom.name, sym_group_geom.needed_define);
       DBUG_RETURN(-1);
-    if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
-      create_info->varchar= 1;
+#endif /*HAVE_SPATIAL*/
+    case FIELD_TYPE_VAR_STRING:
+    case FIELD_TYPE_STRING:
+      sql_field->pack_flag=0;
+      if (sql_field->charset->state & MY_CS_BINSORT)
+	sql_field->pack_flag|=FIELDFLAG_BINARY;
+      break;
+    case FIELD_TYPE_ENUM:
+      sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
+	FIELDFLAG_INTERVAL;
+      if (sql_field->charset->state & MY_CS_BINSORT)
+	sql_field->pack_flag|=FIELDFLAG_BINARY;
+      sql_field->unireg_check=Field::INTERVAL_FIELD;
+      check_duplicates_in_interval("ENUM",sql_field->field_name,
+                                   sql_field->interval,
+                                   sql_field->charset);
+      break;
+    case FIELD_TYPE_SET:
+      sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
+	FIELDFLAG_BITFIELD;
+      if (sql_field->charset->state & MY_CS_BINSORT)
+	sql_field->pack_flag|=FIELDFLAG_BINARY;
+      sql_field->unireg_check=Field::BIT_FIELD;
+      check_duplicates_in_interval("SET",sql_field->field_name,
+                                   sql_field->interval,
+                                   sql_field->charset);
+      break;
+    case FIELD_TYPE_DATE:			// Rest of string types
+    case FIELD_TYPE_NEWDATE:
+    case FIELD_TYPE_TIME:
+    case FIELD_TYPE_DATETIME:
+    case FIELD_TYPE_NULL:
+      sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
+      break;
+    case FIELD_TYPE_TIMESTAMP:
+      /* We should replace old TIMESTAMP fields with their newer analogs */
+      if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
+      {
+	if (!timestamps)
+	{
+	  sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
+	  timestamps_with_niladic++;
+	}
+	else
+	  sql_field->unireg_check= Field::NONE;
+      }
+      else if (sql_field->unireg_check != Field::NONE)
+	timestamps_with_niladic++;
+
+      timestamps++;
+      /* fall-through */
+    default:
+      sql_field->pack_flag=(FIELDFLAG_NUMBER |
+			    (sql_field->flags & UNSIGNED_FLAG ? 0 :
+			     FIELDFLAG_DECIMAL) |
+			    (sql_field->flags & ZEROFILL_FLAG ?
+			     FIELDFLAG_ZEROFILL : 0) |
+			    f_settype((uint) sql_field->sql_type) |
+			    (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
+      break;
+    }
+    if (!(sql_field->flags & NOT_NULL_FLAG))
+      sql_field->pack_flag|=FIELDFLAG_MAYBE_NULL;
     sql_field->offset= record_offset;
     if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
       auto_increment++;
@@ -977,33 +859,30 @@ static int mysql_prepare_table(THD *thd,
   }
   if (timestamps_with_niladic > 1)
   {
-    my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
-               ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
+    my_error(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,MYF(0));
     DBUG_RETURN(-1);
   }
   if (auto_increment > 1)
   {
-    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
+    my_error(ER_WRONG_AUTO_KEY,MYF(0));
     DBUG_RETURN(-1);
   }
   if (auto_increment &&
       (file->table_flags() & HA_NO_AUTO_INCREMENT))
   {
-    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
-               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
+    my_error(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,MYF(0));
     DBUG_RETURN(-1);
   }
 
   if (blob_columns && (file->table_flags() & HA_NO_BLOBS))
   {
-    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
-               MYF(0));
+    my_error(ER_TABLE_CANT_HANDLE_BLOB,MYF(0));
     DBUG_RETURN(-1);
   }
 
   /* Create keys */
 
-  List_iterator<Key> key_iterator(*keys), key_iterator2(*keys);
+  List_iterator<Key> key_iterator(keys), key_iterator2(keys);
   uint key_parts=0, fk_key_count=0;
   bool primary_key=0,unique_key=0;
   Key *key, *key2;
@@ -1023,9 +902,9 @@ static int mysql_prepare_table(THD *thd,
       if (fk_key->ref_columns.elements &&
 	  fk_key->ref_columns.elements != fk_key->columns.elements)
       {
-        my_error(ER_WRONG_FK_DEF, MYF(0),
-                 (fk_key->name ?  fk_key->name : "foreign key without name"),
-                 ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
+	my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name :
+		 "foreign key without name",
+		 ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
 	DBUG_RETURN(-1);
       }
       continue;
@@ -1090,9 +969,9 @@ static int mysql_prepare_table(THD *thd,
     DBUG_RETURN(-1);
   }
 
-  (*key_info_buffer) = key_info= (KEY*) sql_calloc(sizeof(KEY)* *key_count);
+  key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)* *key_count);
   key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
-  if (!*key_info_buffer || ! key_part_info)
+  if (!key_info_buffer || ! key_part_info)
     DBUG_RETURN(-1);				// Out of memory
 
   key_iterator.rewind();
@@ -1124,8 +1003,8 @@ static int mysql_prepare_table(THD *thd,
 	key_info->flags= HA_SPATIAL;
 	break;
 #else
-	my_error(ER_FEATURE_DISABLED, MYF(0),
-                 sym_group_geom.name, sym_group_geom.needed_define);
+	my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
+			sym_group_geom.name, sym_group_geom.needed_define);
 	DBUG_RETURN(-1);
 #endif
     case Key::FOREIGN_KEY:
@@ -1147,8 +1026,7 @@ static int mysql_prepare_table(THD *thd,
     {
       if (!(file->table_flags() & HA_CAN_FULLTEXT))
       {
-	my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
-                   MYF(0));
+	my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
 	DBUG_RETURN(-1);
       }
     }
@@ -1163,15 +1041,10 @@ static int mysql_prepare_table(THD *thd,
     /* TODO: Add proper checks if handler supports key_type and algorithm */
     if (key_info->flags & HA_SPATIAL)
     {
-      if (!(file->table_flags() & HA_CAN_RTREEKEYS))
-      {
-        my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
-                   MYF(0));
-        DBUG_RETURN(-1);
-      }
       if (key_info->key_parts != 1)
       {
-	my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
+	my_printf_error(ER_WRONG_ARGUMENTS,
+			ER(ER_WRONG_ARGUMENTS),MYF(0),"SPATIAL INDEX");
 	DBUG_RETURN(-1);
       }
     }
@@ -1180,15 +1053,17 @@ static int mysql_prepare_table(THD *thd,
 #ifdef HAVE_RTREE_KEYS
       if ((key_info->key_parts & 1) == 1)
       {
-	my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
+	my_printf_error(ER_WRONG_ARGUMENTS,
+			ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
 	DBUG_RETURN(-1);
       }
       /* TODO: To be deleted */
-      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
+      my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
+		      MYF(0), "RTREE INDEX");
       DBUG_RETURN(-1);
 #else
-      my_error(ER_FEATURE_DISABLED, MYF(0),
-               sym_group_rtree.name, sym_group_rtree.needed_define);
+      my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
+		      sym_group_rtree.name, sym_group_rtree.needed_define);
       DBUG_RETURN(-1);
 #endif
     }
@@ -1197,7 +1072,6 @@ static int mysql_prepare_table(THD *thd,
     CHARSET_INFO *ft_key_charset=0;  // for FULLTEXT
     for (uint column_nr=0 ; (column=cols++) ; column_nr++)
     {
-      uint length;
       key_part_spec *dup_column;
 
       it.rewind();
@@ -1209,7 +1083,9 @@ static int mysql_prepare_table(THD *thd,
 	field++;
       if (!sql_field)
       {
-	my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
+	my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS,
+			ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0),
+			column->field_name);
 	DBUG_RETURN(-1);
       }
       while ((dup_column= cols2++) != column)
@@ -1226,14 +1102,15 @@ static int mysql_prepare_table(THD *thd,
       cols2.rewind();
       if (key->type == Key::FULLTEXT)
       {
-	if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
-	     sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
+	if ((sql_field->sql_type != FIELD_TYPE_STRING &&
+	     sql_field->sql_type != FIELD_TYPE_VAR_STRING &&
 	     !f_is_blob(sql_field->pack_flag)) ||
 	    sql_field->charset == &my_charset_bin ||
 	    sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
 	    (ft_key_charset && sql_field->charset != ft_key_charset))
 	{
-	    my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
+	    my_printf_error(ER_BAD_FT_COLUMN,ER(ER_BAD_FT_COLUMN),MYF(0),
+			    column->field_name);
 	    DBUG_RETURN(-1);
 	}
 	ft_key_charset=sql_field->charset;
@@ -1250,33 +1127,32 @@ static int mysql_prepare_table(THD *thd,
       {
 	column->length*= sql_field->charset->mbmaxlen;
 
-	if (f_is_blob(sql_field->pack_flag) ||
-            (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
+	if (f_is_blob(sql_field->pack_flag))
 	{
 	  if (!(file->table_flags() & HA_CAN_INDEX_BLOBS))
 	  {
-	    my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
+	    my_printf_error(ER_BLOB_USED_AS_KEY,ER(ER_BLOB_USED_AS_KEY),MYF(0),
+			    column->field_name);
 	    DBUG_RETURN(-1);
 	  }
-          if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
-              Field::GEOM_POINT)
-            column->length= 21;
 	  if (!column->length)
 	  {
-	    my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
+	    my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
+			    ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
+			    column->field_name);
 	    DBUG_RETURN(-1);
 	  }
 	}
 #ifdef HAVE_SPATIAL
-	if (key->type == Key::SPATIAL)
+	if (key->type  == Key::SPATIAL)
 	{
-	  if (!column->length)
+	  if (!column->length )
 	  {
 	    /*
-              4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
-              Lately we'll extend this code to support more dimensions
+	    BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
+		 Lately we'll extend this code to support more dimensions
 	    */
-	    column->length= 4*sizeof(double);
+	    column->length=4*sizeof(double);
 	  }
 	}
 #endif
@@ -1293,13 +1169,13 @@ static int mysql_prepare_table(THD *thd,
 	     key_info->flags|= HA_NULL_PART_KEY;
 	  if (!(file->table_flags() & HA_NULL_IN_KEY))
 	  {
-	    my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
+	    my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
+			    MYF(0),column->field_name);
 	    DBUG_RETURN(-1);
 	  }
 	  if (key->type == Key::SPATIAL)
 	  {
-	    my_message(ER_SPATIAL_CANT_HAVE_NULL,
-                       ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
+	    my_error(ER_SPATIAL_CANT_HAVE_NULL, MYF(0));
 	    DBUG_RETURN(-1);
 	  }
 	}
@@ -1313,16 +1189,15 @@ static int mysql_prepare_table(THD *thd,
       key_part_info->fieldnr= field;
       key_part_info->offset=  (uint16) sql_field->offset;
       key_part_info->key_type=sql_field->pack_flag;
-      length= sql_field->key_length;
-
+      uint length=sql_field->pack_length;
       if (column->length)
       {
 	if (f_is_blob(sql_field->pack_flag))
 	{
-	  if ((length=column->length) > max_key_length ||
+	  if ((length=column->length) > file->max_key_length() ||
 	      length > file->max_key_part_length())
 	  {
-	    length=min(max_key_length, file->max_key_part_length());
+	    length=min(file->max_key_length(), file->max_key_part_length());
 	    if (key->type == Key::MULTIPLE)
 	    {
 	      /* not a critical problem */
@@ -1346,7 +1221,7 @@ static int mysql_prepare_table(THD *thd,
 		      (key_info->flags & HA_NOSAME))) &&
 		    column->length != length)))
 	{
-	  my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
+	  my_error(ER_WRONG_SUB_KEY,MYF(0));
 	  DBUG_RETURN(-1);
 	}
 	else if (!(file->table_flags() & HA_NO_PREFIX_CHAR_KEYS))
@@ -1354,14 +1229,13 @@ static int mysql_prepare_table(THD *thd,
       }
       else if (length == 0)
       {
-	my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
+	my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0),
+			column->field_name);
 	  DBUG_RETURN(-1);
       }
-      if (length > file->max_key_part_length() && key->type !=
Key::FULLTEXT)
+      if (length > file->max_key_part_length())
       {
-        length= file->max_key_part_length();
-        /* Align key length to multibyte char boundary */
-        length-= length % sql_field->charset->mbmaxlen;
+	length=file->max_key_part_length();
 	if (key->type == Key::MULTIPLE)
 	{
 	  /* not a critical problem */
@@ -1379,15 +1253,14 @@ static int mysql_prepare_table(THD *thd,
       }
       key_part_info->length=(uint16) length;
       /* Use packed keys for long strings on the first column */
-      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
+      if (!(db_options & HA_OPTION_NO_PACK_KEYS) &&
 	  (length >= KEY_DEFAULT_PACK_LENGTH &&
-	   (sql_field->sql_type == MYSQL_TYPE_STRING ||
-	    sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
+	   (sql_field->sql_type == FIELD_TYPE_STRING ||
+	    sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
 	    sql_field->pack_flag & FIELDFLAG_BLOB)))
       {
-	if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) ||
-            sql_field->sql_type == MYSQL_TYPE_VARCHAR)
-	  key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
+	if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB))
+	  key_info->flags|= HA_BINARY_PACK_KEY;
 	else
 	  key_info->flags|= HA_PACK_KEY;
       }
@@ -1401,8 +1274,7 @@ static int mysql_prepare_table(THD *thd,
 	{
 	  if (primary_key)
 	  {
-	    my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
-                       MYF(0));
+	    my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
 	    DBUG_RETURN(-1);
 	  }
 	  key_name=primary_key_name;
@@ -1410,10 +1282,10 @@ static int mysql_prepare_table(THD *thd,
 	}
 	else if (!(key_name = key->name))
 	  key_name=make_unique_key_name(sql_field->field_name,
-					*key_info_buffer, key_info);
-	if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
+					key_info_buffer,key_info);
+	if (check_if_keyname_exists(key_name,key_info_buffer,key_info))
 	{
-	  my_error(ER_DUP_KEYNAME, MYF(0), key_name);
+	  my_error(ER_DUP_KEYNAME,MYF(0),key_name);
 	  DBUG_RETURN(-1);
 	}
 	key_info->name=(char*) key_name;
@@ -1427,6 +1299,7 @@ static int mysql_prepare_table(THD *thd,
     if (!(key_info->flags & HA_NULL_PART_KEY))
       unique_key=1;
     key_info->key_length=(uint16) key_length;
+    uint max_key_length= file->max_key_length();
     if (key_length > max_key_length && key->type != Key::FULLTEXT)
     {
       my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
@@ -1437,16 +1310,16 @@ static int mysql_prepare_table(THD *thd,
   if (!unique_key && !primary_key &&
       (file->table_flags() & HA_REQUIRE_PRIMARY_KEY))
   {
-    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
+    my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0));
     DBUG_RETURN(-1);
   }
   if (auto_increment > 0)
   {
-    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
+    my_error(ER_WRONG_AUTO_KEY,MYF(0));
     DBUG_RETURN(-1);
   }
   /* Sort keys in optimized order */
-  qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY),
+  qsort((gptr) key_info_buffer, *key_count, sizeof(KEY),
 	(qsort_cmp) sort_keys);
   create_info->null_bits= null_fields;
 
@@ -1455,109 +1328,6 @@ static int mysql_prepare_table(THD *thd,
 
 
 /*
-  Extend long VARCHAR fields to blob & prepare field if it's a blob
-
-  SYNOPSIS
-    prepare_blob_field()
-    sql_field		Field to check
-
-  RETURN
-    0	ok
-    1	Error (sql_field can't be converted to blob)
-        In this case the error is given
-*/
-
-static bool prepare_blob_field(THD *thd, create_field *sql_field)
-{
-  DBUG_ENTER("prepare_blob_field");
-
-  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
-      !(sql_field->flags & BLOB_FLAG))
-  {
-    /* Convert long VARCHAR columns to TEXT or BLOB */
-    char warn_buff[MYSQL_ERRMSG_SIZE];
-
-    if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES
|
-                                                      MODE_STRICT_ALL_TABLES)))
-    {
-      my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
-               MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
-      DBUG_RETURN(1);
-    }
-    sql_field->sql_type= FIELD_TYPE_BLOB;
-    sql_field->flags|= BLOB_FLAG;
-    sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
-            (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
-            (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
-    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
-                 warn_buff);
-  }
-    
-  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
-  {
-    if (sql_field->sql_type == FIELD_TYPE_BLOB)
-    {
-      /* The user has given a length to the blob column */
-      sql_field->sql_type= get_blob_type_from_length(sql_field->length);
-      sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
-    }
-    sql_field->length= 0;
-  }
-  DBUG_RETURN(0);
-}
-
-
-/*
-  Preparation of create_field for SP function return values.
-  Based on code used in the inner loop of mysql_prepare_table() above
-
-  SYNOPSIS
-    sp_prepare_create_field()
-    thd			Thread object
-    sql_field		Field to prepare
-
-  DESCRIPTION
-    Prepares the field structures for field creation.
-
-*/
-
-void sp_prepare_create_field(THD *thd, create_field *sql_field)
-{
-  if (sql_field->sql_type == FIELD_TYPE_SET ||
-      sql_field->sql_type == FIELD_TYPE_ENUM)
-  {
-    uint32 field_length, dummy;
-    if (sql_field->sql_type == FIELD_TYPE_SET)
-    {
-      calculate_interval_lengths(sql_field->charset,
-                                 sql_field->interval, &dummy, 
-                                 &field_length);
-      sql_field->length= field_length + 
-                         (sql_field->interval->count - 1);
-    }
-    else /* FIELD_TYPE_ENUM */
-    {
-      calculate_interval_lengths(sql_field->charset,
-                                 sql_field->interval,
-                                 &field_length, &dummy);
-      sql_field->length= field_length;
-    }
-    set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
-  }
-
-  if (sql_field->sql_type == FIELD_TYPE_BIT)
-  {
-    sql_field->pack_flag= FIELDFLAG_NUMBER |
-                          FIELDFLAG_TREAT_BIT_AS_CHAR;
-  }
-  sql_field->create_length_to_internal_length();
-  DBUG_ASSERT(sql_field->def == 0);
-  /* Can't go wrong as sql_field->def is not defined */
-  (void) prepare_blob_field(thd, sql_field);
-}
-
-
-/*
   Create a table
 
   SYNOPSIS
@@ -1568,11 +1338,11 @@ void sp_prepare_create_field(THD *thd, c
     create_info		Create information (like MAX_ROWS)
     fields		List of fields to create
     keys		List of keys to create
-    internal_tmp_table  Set to 1 if this is an internal temporary table
+    tmp_table		Set to 1 if this is an internal temporary table
 			(From ALTER TABLE)
 
   DESCRIPTION
-    If one creates a temporary table, this is automatically opened
+    If one creates a temporary table, this is automaticly opened
 
     no_log is needed for the case of CREATE ... SELECT,
     as the logging will be done later in sql_insert.cc
@@ -1580,38 +1350,46 @@ void sp_prepare_create_field(THD *thd, c
     and must be zero for standard create of table.
 
   RETURN VALUES
-    FALSE OK
-    TRUE  error
+    0	ok
+    -1	error
 */
 
-bool mysql_create_table(THD *thd,const char *db, const char *table_name,
-                        HA_CREATE_INFO *create_info,
-                        List<create_field> &fields,
-                        List<Key> &keys,bool internal_tmp_table,
-                        uint select_field_count)
+int mysql_create_table(THD *thd,const char *db, const char *table_name,
+		       HA_CREATE_INFO *create_info,
+		       List<create_field> &fields,
+		       List<Key> &keys,bool tmp_table,
+		       uint select_field_count)
 {
   char		path[FN_REFLEN];
   const char	*alias;
+  int		error= -1;
   uint		db_options, key_count;
   KEY		*key_info_buffer;
   handler	*file;
-  bool		error= TRUE;
+  enum db_type	new_db_type;
   DBUG_ENTER("mysql_create_table");
 
   /* Check for duplicate fields and check type of table to create */
   if (!fields.elements)
   {
-    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
-               MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-  if (check_engine(thd, table_name, &create_info->db_type))
-    DBUG_RETURN(TRUE);
-  db_options= create_info->table_options;
+    my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
+    DBUG_RETURN(-1);
+  }
+  if ((new_db_type= ha_checktype(create_info->db_type)) !=
+      create_info->db_type)
+  {
+    create_info->db_type= new_db_type;
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+			ER_WARN_USING_OTHER_HANDLER,
+			ER(ER_WARN_USING_OTHER_HANDLER),
+			ha_get_storage_engine(new_db_type),
+			table_name);
+  }
+  db_options=create_info->table_options;
   if (create_info->row_type == ROW_TYPE_DYNAMIC)
     db_options|=HA_OPTION_PACK_RECORD;
   alias= table_case_name(create_info, table_name);
-  file= get_new_handler((TABLE*) 0, thd->mem_root, create_info->db_type);
+  file=get_new_handler((TABLE*) 0, create_info->db_type);
 
 #ifdef NOT_USED
   /*
@@ -1624,8 +1402,8 @@ bool mysql_create_table(THD *thd,const c
   if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
       (file->table_flags() & HA_NO_TEMP_TABLES))
   {
-    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
-    DBUG_RETURN(TRUE);
+    my_error(ER_ILLEGAL_HA,MYF(0),table_name);
+    DBUG_RETURN(-1);
   }
 #endif
 
@@ -1637,17 +1415,18 @@ bool mysql_create_table(THD *thd,const c
   if (!create_info->default_table_charset)
   {
     HA_CREATE_INFO db_info;
-
-    load_db_opt_by_name(thd, db, &db_info);
-
+    char  path[FN_REFLEN];
+    /* Abuse build_table_path() to build the path to the db.opt file */
+    build_table_path(path, sizeof(path), db, MY_DB_OPT_FILE, "");
+    load_db_opt(thd, path, &db_info);
     create_info->default_table_charset= db_info.default_table_charset;
   }
 
-  if (mysql_prepare_table(thd, create_info, &fields,
-			  &keys, internal_tmp_table, &db_options, file,
-			  &key_info_buffer, &key_count,
+  if (mysql_prepare_table(thd, create_info, fields,
+			  keys, tmp_table, db_options, file,
+			  key_info_buffer, &key_count,
 			  select_field_count))
-    DBUG_RETURN(TRUE);
+    DBUG_RETURN(-1);
 
       /* Check if table exists */
   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1659,23 +1438,8 @@ bool mysql_create_table(THD *thd,const c
       my_casedn_str(files_charset_info, path);
     create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
   }
-  else  
-  {
-	#ifdef FN_DEVCHAR
-	  /* check if the table name contains FN_DEVCHAR when defined */
-	  const char *start= alias;
-	  while (*start != '\0')
-	  {
-		  if (*start == FN_DEVCHAR)
-		  {
-			  my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
-			  DBUG_RETURN(TRUE);
-		  }
-		  start++;
-	  }	  
-	#endif
+  else
     build_table_path(path, sizeof(path), db, alias, reg_ext);
-  }
 
   /* Check if table already exists */
   if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1687,13 +1451,15 @@ bool mysql_create_table(THD *thd,const c
       push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
                           ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
                           alias);
-      DBUG_RETURN(FALSE);
+      DBUG_RETURN(0);
     }
     my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
-    DBUG_RETURN(TRUE);
+    DBUG_RETURN(-1);
   }
+  if (wait_if_global_read_lock(thd, 0, 1))
+    DBUG_RETURN(error);
   VOID(pthread_mutex_lock(&LOCK_open));
-  if (!internal_tmp_table && !(create_info->options &
HA_LEX_CREATE_TMP_TABLE))
+  if (!tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
   {
     if (!access(path,F_OK))
     {
@@ -1749,26 +1515,35 @@ bool mysql_create_table(THD *thd,const c
     }
     thd->tmp_table_used= 1;
   }
-  if (!internal_tmp_table && mysql_bin_log.is_open())
+  if (!tmp_table)
   {
-    thd->clear_error();
-    Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
-    mysql_bin_log.write(&qinfo);
+    // Must be written before unlock
+    mysql_update_log.write(thd,thd->query, thd->query_length);
+    if (mysql_bin_log.is_open())
+    {
+      thd->clear_error();
+      Query_log_event qinfo(thd, thd->query, thd->query_length,
+			    test(create_info->options &
+				 HA_LEX_CREATE_TMP_TABLE),
+			    FALSE);
+      mysql_bin_log.write(&qinfo);
+    }
   }
-  error= FALSE;
-
-end:
-  VOID(pthread_mutex_unlock(&LOCK_open));
-  thd->proc_info="After create";
-  DBUG_RETURN(error);
+  error=0;
+  goto end;
 
 warn:
-  error= FALSE;
+  error= 0;
   push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
                       ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
                       alias);
   create_info->table_existed= 1;		// Mark that table existed
-  goto end;
+
+end:
+  VOID(pthread_mutex_unlock(&LOCK_open));
+  start_waiting_global_read_lock(thd);
+  thd->proc_info="After create";
+  DBUG_RETURN(error);
 }
 
 /*
@@ -1811,6 +1586,84 @@ make_unique_key_name(const char *field_n
 
 
 /****************************************************************************
+** Create table from a list of fields and items
+****************************************************************************/
+
+TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
+			       const char *db, const char *name,
+			       List<create_field> *extra_fields,
+			       List<Key> *keys,
+			       List<Item> *items,
+			       MYSQL_LOCK **lock)
+{
+  TABLE tmp_table;		// Used during 'create_field()'
+  TABLE *table= 0;
+  tmp_table.table_name=0;
+  uint select_field_count= items->elements;
+  DBUG_ENTER("create_table_from_items");
+
+  /* Add selected items to field list */
+  List_iterator_fast<Item> it(*items);
+  Item *item;
+  Field *tmp_field;
+  tmp_table.db_create_options=0;
+  tmp_table.null_row=tmp_table.maybe_null=0;
+  tmp_table.blob_ptr_size=portable_sizeof_char_ptr;
+  tmp_table.db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
+				    create_info->db_type == DB_TYPE_HEAP);
+
+  while ((item=it++))
+  {
+    create_field *cr_field;
+    Field *field;
+    if (item->type() == Item::FUNC_ITEM)
+      field=item->tmp_table_field(&tmp_table);
+    else
+      field=create_tmp_field(thd, &tmp_table, item, item->type(),
+				  (Item ***) 0, &tmp_field, 0, 0, 0, 0);
+    if (!field ||
+	!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
+					   ((Item_field *)item)->field :
+					   (Field*) 0))))
+      DBUG_RETURN(0);
+    extra_fields->push_back(cr_field);
+  }
+  /* create and lock table */
+  /* QQ: create and open should be done atomic ! */
+  /*
+    We don't log the statement, it will be logged later.
+    If this is a HEAP table, the automatic DELETE FROM which is written to the
+    binlog when a HEAP table is opened for the first time since startup, must
+    not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
+    don't want to delete from it) 2) it would be written before the CREATE
+    TABLE, which is a wrong order. So we keep binary logging disabled when we
+    open_table().
+  */
+  tmp_disable_binlog(thd);
+  if (!mysql_create_table(thd,db,name,create_info,*extra_fields,
+			 *keys,0,select_field_count))
+  {
+    if (!(table=open_table(thd,db,name,name,(bool*) 0)))
+      quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
+  }
+  reenable_binlog(thd);
+  if (!table)
+    DBUG_RETURN(0);
+  table->reginfo.lock_type=TL_WRITE;
+  if (! ((*lock)= mysql_lock_tables(thd, &table, 1, MYSQL_LOCK_IGNORE_FLUSH)))
+  {
+    VOID(pthread_mutex_lock(&LOCK_open));
+    hash_delete(&open_cache,(byte*) table);
+    VOID(pthread_mutex_unlock(&LOCK_open));
+    quick_rm_table(create_info->db_type,db,table_case_name(create_info, name));
+    DBUG_RETURN(0);
+  }
+  table->file->extra(HA_EXTRA_WRITE_CACHE);
+  DBUG_RETURN(table);
+}
+
+
+/****************************************************************************
 ** Alter a table definition
 ****************************************************************************/
 
@@ -1821,12 +1674,10 @@ mysql_rename_table(enum db_type base,
 		   const char *new_db,
 		   const char *new_name)
 {
-  THD *thd= current_thd;
   char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
   char *from_base= from, *to_base= to;
   char tmp_name[NAME_LEN+1];
-  handler *file= (base == DB_TYPE_UNKNOWN ? 0 :
-                  get_new_handler((TABLE*) 0, thd->mem_root, base));
+  handler *file=get_new_handler((TABLE*) 0, base);
   int error=0;
   DBUG_ENTER("mysql_rename_table");
 
@@ -1838,8 +1689,7 @@ mysql_rename_table(enum db_type base,
     file system) and the storage is not HA_FILE_BASED, we need to provide
     a lowercase file name, but we leave the .frm in mixed case.
    */
-  if (lower_case_table_names == 2 && file &&
-      !(file->table_flags() & HA_FILE_BASED))
+  if (lower_case_table_names == 2 && !(file->table_flags() &
HA_FILE_BASED))
   {
     strmov(tmp_name, old_name);
     my_casedn_str(files_charset_info, tmp_name);
@@ -1852,14 +1702,13 @@ mysql_rename_table(enum db_type base,
     to_base= lc_to;
   }
 
-  if (!file || !(error=file->rename_table(from_base, to_base)))
+  if (!(error=file->rename_table(from_base, to_base)))
   {
     if (rename_file_ext(from,to,reg_ext))
     {
       error=my_errno;
       /* Restore old file name */
-      if (file)
-        file->rename_table(to_base, from_base);
+      file->rename_table(to_base, from_base);
     }
   }
   delete file;
@@ -1892,7 +1741,7 @@ mysql_rename_table(enum db_type base,
 static void wait_while_table_is_used(THD *thd,TABLE *table,
 				     enum ha_extra_function function)
 {
-  DBUG_PRINT("enter",("table: %s", table->s->table_name));
+  DBUG_PRINT("enter",("table: %s", table->real_name));
   DBUG_ENTER("wait_while_table_is_used");
   safe_mutex_assert_owner(&LOCK_open);
 
@@ -1901,8 +1750,8 @@ static void wait_while_table_is_used(THD
   mysql_lock_abort(thd, table);			// end threads waiting on lock
 
   /* Wait until all there are no other threads that has this table open */
-  remove_table_from_cache(thd, table->s->db,
-                          table->s->table_name, RTFC_WAIT_OTHER_THREAD_FLAG);
+  remove_table_from_cache(thd,table->table_cache_key,
+                          table->real_name, RTFC_WAIT_OTHER_THREAD_FLAG);
   DBUG_VOID_RETURN;
 }
 
@@ -1923,7 +1772,7 @@ static void wait_while_table_is_used(THD
     Win32 clients must also have a WRITE LOCK on the table !
 */
 
-void close_cached_table(THD *thd, TABLE *table)
+static bool close_cached_table(THD *thd, TABLE *table)
 {
   DBUG_ENTER("close_cached_table");
 
@@ -1938,8 +1787,8 @@ void close_cached_table(THD *thd, TABLE 
   thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
 
   /* When lock on LOCK_open is freed other threads can continue */
-  broadcast_refresh();
-  DBUG_VOID_RETURN;
+  pthread_cond_broadcast(&COND_refresh);
+  DBUG_RETURN(0);
 }
 
 static int send_check_errmsg(THD *thd, TABLE_LIST* table,
@@ -1950,9 +1799,9 @@ static int send_check_errmsg(THD *thd, T
   protocol->prepare_for_resend();
   protocol->store(table->alias, system_charset_info);
   protocol->store((char*) operator_name, system_charset_info);
-  protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+  protocol->store("error", 5, system_charset_info);
   protocol->store(errmsg, system_charset_info);
-  thd->clear_error();
+  thd->net.last_error[0]=0;
   if (protocol->write())
     return -1;
   return 1;
@@ -1974,8 +1823,8 @@ static int prepare_for_restore(THD* thd,
   {
     char* backup_dir= thd->lex->backup_dir;
     char src_path[FN_REFLEN], dst_path[FN_REFLEN];
-    char* table_name= table->table_name;
-    char* db= table->db;
+    char* table_name = table->real_name;
+    char* db = thd->db ? thd->db : table->db;
 
     if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
 					reg_ext))
@@ -2011,15 +1860,12 @@ static int prepare_for_restore(THD* thd,
     Now we should be able to open the partially restored table
     to finish the restore in the handler later on
   */
-  pthread_mutex_lock(&LOCK_open);
-  if (reopen_name_locked_table(thd, table))
+  if (!(table->table = reopen_name_locked_table(thd, table)))
   {
+    pthread_mutex_lock(&LOCK_open);
     unlock_table_name(thd, table);
     pthread_mutex_unlock(&LOCK_open);
-    DBUG_RETURN(send_check_errmsg(thd, table, "restore",
-                                  "Failed to open partially restored table"));
   }
-  pthread_mutex_unlock(&LOCK_open);
   DBUG_RETURN(0);
 }
 
@@ -2038,8 +1884,8 @@ static int prepare_for_repair(THD* thd, 
   {
     char name[FN_REFLEN];
     build_table_path(name, sizeof(name), table_list->db,
-                     table_list->table_name, "");
-    if (openfrm(thd, name, "", 0, 0, 0, &tmp_table))
+                     table_list->real_name, "");
+    if (openfrm(name, "", 0, 0, 0, &tmp_table))
       DBUG_RETURN(0);				// Can't open frm file
     table= &tmp_table;
   }
@@ -2065,7 +1911,7 @@ static int prepare_for_repair(THD* thd, 
   if (!ext[0] || !ext[1])
     goto end;					// No data file
 
-  strxmov(from, table->s->path, ext[1], NullS);	// Name of data file
+  strxmov(from, table->path, ext[1], NullS);	// Name of data file
   if (!my_stat(from, &stat_info, MYF(0)))
     goto end;				// Can't use USE_FRM flag
 
@@ -2116,16 +1962,12 @@ static int prepare_for_repair(THD* thd, 
     Now we should be able to open the partially repaired table
     to finish the repair in the handler later on.
   */
-  pthread_mutex_lock(&LOCK_open);
-  if (reopen_name_locked_table(thd, table_list))
+  if (!(table_list->table = reopen_name_locked_table(thd, table_list)))
   {
+    pthread_mutex_lock(&LOCK_open);
     unlock_table_name(thd, table_list);
     pthread_mutex_unlock(&LOCK_open);
-    error= send_check_errmsg(thd, table_list, "repair",
-                             "Failed to open partially repaired table");
-    goto end;
   }
-  pthread_mutex_unlock(&LOCK_open);
 
 end:
   if (table == &tmp_table)
@@ -2134,33 +1976,27 @@ end:
 }
 
 
-
 /*
   RETURN VALUES
-    FALSE Message sent to net (admin operation went ok)
-    TRUE  Message should be sent by caller 
-          (admin operation or network communication failed)
-*/
-static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
-                              HA_CHECK_OPT* check_opt,
-                              const char *operator_name,
-                              thr_lock_type lock_type,
-                              bool open_for_modify,
-                              bool no_warnings_for_error,
-                              uint extra_open_options,
-                              int (*prepare_func)(THD *, TABLE_LIST *,
-                                                  HA_CHECK_OPT *),
-                              int (handler::*operator_func)(THD *,
-                                                            HA_CHECK_OPT *),
-                              int (view_operator_func)(THD *, TABLE_LIST*))
+    0   Message sent to net (admin operation went ok)
+   -1   Message should be sent by caller 
+        (admin operation or network communication failed)
+*/
+static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
+			     HA_CHECK_OPT* check_opt,
+			     const char *operator_name,
+			     thr_lock_type lock_type,
+			     bool open_for_modify,
+			     uint extra_open_options,
+			     int (*prepare_func)(THD *, TABLE_LIST *,
+						 HA_CHECK_OPT *),
+			     int (handler::*operator_func)
+			     (THD *, HA_CHECK_OPT *))
 {
-  TABLE_LIST *table, *save_next_global, *save_next_local;
-  SELECT_LEX *select= &thd->lex->select_lex;
+  TABLE_LIST *table;
   List<Item> field_list;
   Item *item;
   Protocol *protocol= thd->protocol;
-  LEX *lex= thd->lex;
-  int result_code;
   DBUG_ENTER("mysql_admin_table");
 
   field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
@@ -2171,42 +2007,22 @@ static bool mysql_admin_table(THD* thd, 
   item->maybe_null = 1;
   field_list.push_back(item = new Item_empty_string("Msg_text", 255));
   item->maybe_null = 1;
-  if (protocol->send_fields(&field_list,
-                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
-    DBUG_RETURN(TRUE);
+  if (protocol->send_fields(&field_list, 1))
+    DBUG_RETURN(-1);
 
   mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE);
-  for (table= tables; table; table= table->next_local)
+  for (table = tables; table; table = table->next)
   {
     char table_name[NAME_LEN*2+2];
     char* db = table->db;
     bool fatal_error=0;
+    strxmov(table_name, db, ".", table->real_name, NullS);
 
-    strxmov(table_name, db, ".", table->table_name, NullS);
     thd->open_options|= extra_open_options;
-    table->lock_type= lock_type;
-    /* open only one table from local list of command */
-    save_next_global= table->next_global;
-    table->next_global= 0;
-    save_next_local= table->next_local;
-    table->next_local= 0;
-    select->table_list.first= (byte*)table;
-    /*
-      Time zone tables and SP tables can be add to lex->query_tables list,
-      so it have to be prepared.
-      TODO: Investigate if we can put extra tables into argument instead of
-      using lex->query_tables
-    */
-    lex->query_tables= table;
-    lex->query_tables_last= &table->next_global;
-    lex->query_tables_own_last= 0;
-    thd->no_warnings_for_error= no_warnings_for_error;
-    if (view_operator_func == NULL)
-      table->required_type=FRMTYPE_TABLE;
-    open_and_lock_tables(thd, table);
-    thd->no_warnings_for_error= 0;
-    table->next_global= save_next_global;
-    table->next_local= save_next_local;
+    table->table = open_ltable(thd, table, lock_type);
+#ifdef EMBEDDED_LIBRARY
+    thd->net.last_errno= 0;  // these errors shouldn't get client
+#endif
     thd->open_options&= ~extra_open_options;
 
     if (prepare_func)
@@ -2222,63 +2038,31 @@ static bool mysql_admin_table(THD* thd, 
       }
     }
 
-    /*
-      CHECK TABLE command is only command where VIEW allowed here and this
-      command use only temporary teble method for VIEWs resolving => there
-      can't be VIEW tree substitition of join view => if opening table
-      succeed then table->table will have real TABLE pointer as value (in
-      case of join view substitution table->table can be 0, but here it is
-      impossible)
-    */
     if (!table->table)
     {
-      char buf[ERRMSGSIZE+ERRMSGSIZE+2];
       const char *err_msg;
       protocol->prepare_for_resend();
       protocol->store(table_name, system_charset_info);
       protocol->store(operator_name, system_charset_info);
-      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+      protocol->store("error",5, system_charset_info);
       if (!(err_msg=thd->net.last_error))
 	err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
-      /* if it was a view will check md5 sum */
-      if (table->view &&
-          view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
-      {
-        strxmov(buf, err_msg, "; ", ER(ER_VIEW_CHECKSUM), NullS);
-        err_msg= (const char *)buf;
-      }
       protocol->store(err_msg, system_charset_info);
-      lex->cleanup_after_one_table_open();
-      thd->clear_error();
-      /*
-        View opening can be interrupted in the middle of process so some
-        tables can be left opening
-      */
-      close_thread_tables(thd);
-      lex->reset_query_tables_list(FALSE);
+      thd->net.last_error[0]=0;
       if (protocol->write())
 	goto err;
       continue;
     }
-
-    if (table->view)
-    {
-      result_code= (*view_operator_func)(thd, table);
-      goto send_result;
-    }
-
     table->table->pos_in_table_list= table;
     if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
     {
       char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
-      uint length;
       protocol->prepare_for_resend();
       protocol->store(table_name, system_charset_info);
       protocol->store(operator_name, system_charset_info);
-      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
-      length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
-                          table_name);
-      protocol->store(buff, length, system_charset_info);
+      protocol->store("error", 5, system_charset_info);
+      my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY), table_name);
+      protocol->store(buff, system_charset_info);
       close_thread_tables(thd);
       table->table=0;				// For query cache
       if (protocol->write())
@@ -2287,14 +2071,14 @@ static bool mysql_admin_table(THD* thd, 
     }
 
     /* Close all instances of the table to allow repair to rename files */
-    if (lock_type == TL_WRITE && table->table->s->version)
+    if (lock_type == TL_WRITE && table->table->version)
     {
       pthread_mutex_lock(&LOCK_open);
       const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
 					      "Waiting to get writelock");
       mysql_lock_abort(thd,table->table);
-      remove_table_from_cache(thd, table->table->s->db,
-                              table->table->s->table_name,
+      remove_table_from_cache(thd, table->table->table_cache_key,
+                              table->table->real_name,
                               RTFC_WAIT_OTHER_THREAD_FLAG |
                               RTFC_CHECK_KILLED_FLAG);
       thd->exit_cond(old_message);
@@ -2305,39 +2089,10 @@ static bool mysql_admin_table(THD* thd, 
       open_for_modify= 0;
     }
 
-    if (table->table->s->crashed && operator_func ==
&handler::ha_check)
-    {
-      protocol->prepare_for_resend();
-      protocol->store(table_name, system_charset_info);
-      protocol->store(operator_name, system_charset_info);
-      protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
-      protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
-                      system_charset_info);
-      if (protocol->write())
-        goto err;
-    }
-
-    if (operator_func == &handler::ha_repair)
-    {
-      if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
-          (table->table->file->ha_check_for_upgrade(check_opt) ==
-           HA_ADMIN_NEEDS_ALTER))
-      {
-        close_thread_tables(thd);
-        tmp_disable_binlog(thd); // binlogging is done by caller if wanted
-        result_code= mysql_recreate_table(thd, table, 0);
-        reenable_binlog(thd);
-        goto send_result;
-      }
-
-    }
-
-    result_code = (table->table->file->*operator_func)(thd, check_opt);
-
-send_result:
-
-    lex->cleanup_after_one_table_open();
-    thd->clear_error();  // these errors shouldn't get client
+    int result_code = (table->table->file->*operator_func)(thd, check_opt);
+#ifdef EMBEDDED_LIBRARY
+    thd->net.last_errno= 0;  // these errors shouldn't get client
+#endif
     protocol->prepare_for_resend();
     protocol->store(table_name, system_charset_info);
     protocol->store(operator_name, system_charset_info);
@@ -2351,55 +2106,41 @@ send_result_message:
 	char buf[ERRMSGSIZE+20];
 	uint length=my_snprintf(buf, ERRMSGSIZE,
 				ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
-	protocol->store(STRING_WITH_LEN("note"), system_charset_info);
+	protocol->store("note", 4, system_charset_info);
 	protocol->store(buf, length, system_charset_info);
       }
       break;
 
-    case HA_ADMIN_NOT_BASE_TABLE:
-      {
-        char buf[ERRMSGSIZE+20];
-        uint length= my_snprintf(buf, ERRMSGSIZE,
-                                 ER(ER_BAD_TABLE_ERROR), table_name);
-        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
-        protocol->store(buf, length, system_charset_info);
-      }
-      break;
-
     case HA_ADMIN_OK:
-      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
-      protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
+      protocol->store("status", 6, system_charset_info);
+      protocol->store("OK",2, system_charset_info);
       break;
 
     case HA_ADMIN_FAILED:
-      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
-      protocol->store(STRING_WITH_LEN("Operation failed"),
-                      system_charset_info);
+      protocol->store("status", 6, system_charset_info);
+      protocol->store("Operation failed",16, system_charset_info);
       break;
 
     case HA_ADMIN_REJECT:
-      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
-      protocol->store(STRING_WITH_LEN("Operation need committed state"),
-                      system_charset_info);
+      protocol->store("status", 6, system_charset_info);
+      protocol->store("Operation need committed state",30, system_charset_info);
       open_for_modify= FALSE;
       break;
 
     case HA_ADMIN_ALREADY_DONE:
-      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
-      protocol->store(STRING_WITH_LEN("Table is already up to date"),
-                      system_charset_info);
+      protocol->store("status", 6, system_charset_info);
+      protocol->store("Table is already up to date", 27, system_charset_info);
       break;
 
     case HA_ADMIN_CORRUPT:
-      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
-      protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
+      protocol->store("error", 5, system_charset_info);
+      protocol->store("Corrupt", 7, system_charset_info);
       fatal_error=1;
       break;
 
     case HA_ADMIN_INVALID:
-      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
-      protocol->store(STRING_WITH_LEN("Invalid argument"),
-                      system_charset_info);
+      protocol->store("error", 5, system_charset_info);
+      protocol->store("Invalid argument",16, system_charset_info);
       break;
 
     case HA_ADMIN_TRY_ALTER:
@@ -2410,9 +2151,8 @@ send_result_message:
         reopen the table and do ha_innobase::analyze() on it.
       */
       close_thread_tables(thd);
-      TABLE_LIST *save_next_local= table->next_local,
-                 *save_next_global= table->next_global;
-      table->next_local= table->next_global= 0;
+      TABLE_LIST *save_next= table->next;
+      table->next= 0;
       tmp_disable_binlog(thd); // binlogging is done by caller if wanted
       result_code= mysql_recreate_table(thd, table, 0);
       reenable_binlog(thd);
@@ -2435,7 +2175,7 @@ send_result_message:
           else
           {
             /* Hijack the row already in-progress. */
-            protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+            protocol->store("error", 5, system_charset_info);
             protocol->store(err_msg, system_charset_info);
             (void)protocol->write();
             /* Start off another row for HA_ADMIN_FAILED */
@@ -2446,116 +2186,84 @@ send_result_message:
         }
       }
       result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
-      table->next_local= save_next_local;
-      table->next_global= save_next_global;
+      table->next= save_next;
       goto send_result_message;
     }
-    case HA_ADMIN_WRONG_CHECKSUM:
-    {
-      protocol->store(STRING_WITH_LEN("note"), system_charset_info);
-      protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
-                      system_charset_info);
-      break;
-    }
-
-    case HA_ADMIN_NEEDS_UPGRADE:
-    case HA_ADMIN_NEEDS_ALTER:
-    {
-      char buf[ERRMSGSIZE];
-      uint length;
 
-      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
-      length=my_snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE),
table->table_name);
-      protocol->store(buf, length, system_charset_info);
+    default:				// Probably HA_ADMIN_INTERNAL_ERROR
+      protocol->store("error", 5, system_charset_info);
+      protocol->store("Unknown - internal error during operation", 41
+		      , system_charset_info);
       fatal_error=1;
       break;
     }
-
-    default:				// Probably HA_ADMIN_INTERNAL_ERROR
+    if (fatal_error)
+      table->table->version=0;			// Force close of table
+    else if (open_for_modify)
+    {
+      if (table->table->tmp_table)
+        table->table->file->info(HA_STATUS_CONST);
+      else
       {
-        char buf[ERRMSGSIZE+20];
-        uint length=my_snprintf(buf, ERRMSGSIZE,
-                                "Unknown - internal error %d during operation",
-                                result_code);
-        protocol->store(STRING_WITH_LEN("error"), system_charset_info);
-        protocol->store(buf, length, system_charset_info);
-        fatal_error=1;
-        break;
-      }
-    }
-    if (table->table)
-    {
-      if (fatal_error)
-        table->table->s->version=0;               // Force close of table
-      else if (open_for_modify)
-      {
-        if (table->table->s->tmp_table)
-          table->table->file->info(HA_STATUS_CONST);
-        else
-        {
-          pthread_mutex_lock(&LOCK_open);
-          remove_table_from_cache(thd, table->table->s->db,
-                                  table->table->s->table_name, RTFC_NO_FLAG);
-          pthread_mutex_unlock(&LOCK_open);
-        }
-        /* May be something modified consequently we have to invalidate cache */
-        query_cache_invalidate3(thd, table->table, 0);
+        pthread_mutex_lock(&LOCK_open);
+        remove_table_from_cache(thd, table->table->table_cache_key,
+                                table->table->real_name, RTFC_NO_FLAG);
+        pthread_mutex_unlock(&LOCK_open);
       }
+      /* May be something modified consequently we have to invalidate cache */
+      query_cache_invalidate3(thd, table->table, 0);
     }
     close_thread_tables(thd);
-    lex->reset_query_tables_list(FALSE);
     table->table=0;				// For query cache
     if (protocol->write())
       goto err;
   }
 
   send_eof(thd);
-  DBUG_RETURN(FALSE);
+  DBUG_RETURN(0);
  err:
   close_thread_tables(thd);			// Shouldn't be needed
   if (table)
     table->table=0;
-  DBUG_RETURN(TRUE);
+  DBUG_RETURN(-1);
 }
 
 
-bool mysql_backup_table(THD* thd, TABLE_LIST* table_list)
+int mysql_backup_table(THD* thd, TABLE_LIST* table_list)
 {
   DBUG_ENTER("mysql_backup_table");
   DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
-				"backup", TL_READ, 0, 0, 0, 0,
-				&handler::backup, 0));
+				"backup", TL_READ, 0, 0, 0,
+				&handler::backup));
 }
 
 
-bool mysql_restore_table(THD* thd, TABLE_LIST* table_list)
+int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
 {
   DBUG_ENTER("mysql_restore_table");
   DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
-				"restore", TL_WRITE, 1, 1, 0,
+				"restore", TL_WRITE, 1, 0,
 				&prepare_for_restore,
-				&handler::restore, 0));
+				&handler::restore));
 }
 
 
-bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 {
   DBUG_ENTER("mysql_repair_table");
   DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
-				"repair", TL_WRITE, 1,
-                                test(check_opt->sql_flags & TT_USEFRM),
-                                HA_OPEN_FOR_REPAIR,
+				"repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR,
 				&prepare_for_repair,
-				&handler::ha_repair, 0));
+				&handler::repair));
 }
 
 
-bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 {
   DBUG_ENTER("mysql_optimize_table");
   DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
-				"optimize", TL_WRITE, 1,0,0,0,
-				&handler::optimize, 0));
+				"optimize", TL_WRITE, 1,0,0,
+				&handler::optimize));
 }
 
 
@@ -2568,11 +2276,11 @@ bool mysql_optimize_table(THD* thd, TABL
     tables	Table list (one table only)
 
   RETURN VALUES
-   FALSE ok
-   TRUE  error
+    0	  ok
+   -1	  error
 */
 
-bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
+int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
 			     LEX_STRING *key_cache_name)
 {
   HA_CHECK_OPT check_opt;
@@ -2585,13 +2293,13 @@ bool mysql_assign_to_keycache(THD* thd, 
   {
     pthread_mutex_unlock(&LOCK_global_system_variables);
     my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
-    DBUG_RETURN(TRUE);
+    DBUG_RETURN(-1);
   }
   pthread_mutex_unlock(&LOCK_global_system_variables);
   check_opt.key_cache= key_cache;
   DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
-				"assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
-				0, 0, &handler::assign_to_keycache, 0));
+				"assign_to_keycache", TL_READ_NO_INSERT, 0,
+				0, 0, &handler::assign_to_keycache));
 }
 
 
@@ -2643,16 +2351,16 @@ int reassign_keycache_tables(THD *thd, K
     tables	Table list (one table only)
 
   RETURN VALUES
-    FALSE ok
-    TRUE  error
+    0	  ok
+   -1	  error
 */
 
-bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
+int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
 {
   DBUG_ENTER("mysql_preload_keys");
   DBUG_RETURN(mysql_admin_table(thd, tables, 0,
-				"preload_keys", TL_READ, 0, 0, 0, 0,
-				&handler::preload_keys, 0));
+				"preload_keys", TL_READ, 0, 0, 0,
+				&handler::preload_keys));
 }
 
 
@@ -2667,28 +2375,24 @@ bool mysql_preload_keys(THD* thd, TABLE_
     table_ident Src table_ident
 
   RETURN VALUES
-    FALSE OK
-    TRUE  error
+    0	  ok
+    -1	error
 */
 
-bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
-                             HA_CREATE_INFO *create_info,
-                             Table_ident *table_ident)
+int mysql_create_like_table(THD* thd, TABLE_LIST* table,
+			    HA_CREATE_INFO *create_info,
+			    Table_ident *table_ident)
 {
   TABLE **tmp_table;
   char src_path[FN_REFLEN], dst_path[FN_REFLEN];
   char *db= table->db;
-  char *table_name= table->table_name;
+  char *table_name= table->real_name;
   char *src_db;
   char *src_table= table_ident->table.str;
-  int  err;
-  bool res= TRUE;
-  db_type not_used;
-
+  int  err, res= -1;
   TABLE_LIST src_tables_list;
   DBUG_ENTER("mysql_create_like_table");
-  DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */
-  src_db= table_ident->db.str;
+  src_db= table_ident->db.str ? table_ident->db.str : thd->db;
 
   /*
     Validate the source table
@@ -2698,7 +2402,7 @@ bool mysql_create_like_table(THD* thd, T
        check_table_name(src_table,table_ident->table.length)))
   {
     my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
-    DBUG_RETURN(TRUE);
+    DBUG_RETURN(-1);
   }
   if (!src_db || check_db_name(src_db))
   {
@@ -2706,15 +2410,15 @@ bool mysql_create_like_table(THD* thd, T
     DBUG_RETURN(-1);
   }
 
-  bzero((gptr)&src_tables_list, sizeof(src_tables_list));
   src_tables_list.db= src_db;
-  src_tables_list.table_name= src_table;
+  src_tables_list.real_name= src_table;
+  src_tables_list.next= 0;
 
   if (lock_and_wait_for_table_name(thd, &src_tables_list))
     goto err;
 
   if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
-    strxmov(src_path, (*tmp_table)->s->path, reg_ext, NullS);
+    strxmov(src_path, (*tmp_table)->path, reg_ext, NullS);
   else
   {
     strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
@@ -2730,15 +2434,6 @@ bool mysql_create_like_table(THD* thd, T
     }
   }
 
-  /* 
-     create like should be not allowed for Views, Triggers, ... 
-  */
-  if (mysql_frm_type(thd, src_path, &not_used) != FRMTYPE_TABLE)
-  {
-    my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE");
-    goto err;
-  }
-
   /*
     Validate the destination table
 
@@ -2802,13 +2497,17 @@ bool mysql_create_like_table(THD* thd, T
   }
 
   // Must be written before unlock
+  mysql_update_log.write(thd,thd->query, thd->query_length);
   if (mysql_bin_log.is_open())
   {
     thd->clear_error();
-    Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+    Query_log_event qinfo(thd, thd->query, thd->query_length,
+			  test(create_info->options &
+			       HA_LEX_CREATE_TMP_TABLE), 
+			  FALSE);
     mysql_bin_log.write(&qinfo);
   }
-  res= FALSE;
+  res= 0;
   goto err;
 
 table_exists:
@@ -2817,9 +2516,9 @@ table_exists:
     char warn_buff[MYSQL_ERRMSG_SIZE];
     my_snprintf(warn_buff, sizeof(warn_buff),
 		ER(ER_TABLE_EXISTS_ERROR), table_name);
-    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 		 ER_TABLE_EXISTS_ERROR,warn_buff);
-    res= FALSE;
+    res= 0;
   }
   else
     my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
@@ -2832,7 +2531,7 @@ err:
 }
 
 
-bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 {
 #ifdef OS2
   thr_lock_type lock_type = TL_WRITE;
@@ -2842,12 +2541,12 @@ bool mysql_analyze_table(THD* thd, TABLE
 
   DBUG_ENTER("mysql_analyze_table");
   DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
-				"analyze", lock_type, 1, 0, 0, 0,
-				&handler::analyze, 0));
+				"analyze", lock_type, 1,0,0,
+				&handler::analyze));
 }
 
 
-bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
+int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
 {
 #ifdef OS2
   thr_lock_type lock_type = TL_WRITE;
@@ -2858,8 +2557,8 @@ bool mysql_check_table(THD* thd, TABLE_L
   DBUG_ENTER("mysql_check_table");
   DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 				"check", lock_type,
-				0, HA_OPEN_FOR_REPAIR, 0, 0,
-				&handler::ha_check, &view_checksum));
+				0, HA_OPEN_FOR_REPAIR, 0,
+				&handler::check));
 }
 
 
@@ -2913,23 +2612,24 @@ mysql_discard_or_import_tablespace(THD *
     error=1;
   if (error)
     goto err;
+  mysql_update_log.write(thd, thd->query,thd->query_length);
   if (mysql_bin_log.is_open())
   {
-    Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+    Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
     mysql_bin_log.write(&qinfo);
   }
 err:
   close_thread_tables(thd);
   thd->tablespace_op=FALSE;
-  
   if (error == 0)
   {
     send_ok(thd);
     DBUG_RETURN(0);
   }
 
-  table->file->print_error(error, MYF(0));
-    
+  if (error == HA_ERR_ROW_IS_REFERENCED)
+    my_error(ER_ROW_IS_REFERENCED, MYF(0));
+  
   DBUG_RETURN(-1);
 }
 
@@ -2984,9 +2684,9 @@ int mysql_create_indexes(THD *thd, TABLE
   create_info.db_type=DB_TYPE_DEFAULT;
   create_info.default_table_charset= thd->variables.collation_database;
   db_options= 0;
-  if (mysql_prepare_table(thd, &create_info, &fields,
-			  &keys, /*tmp_table*/ 0, &db_options, table->file,
-			  &key_info_buffer, key_count,
+  if (mysql_prepare_table(thd, &create_info, fields,
+			  keys, /*tmp_table*/ 0, db_options, table->file,
+			  key_info_buffer, key_count,
 			  /*select_field_count*/ 0))
     DBUG_RETURN(-1);
 
@@ -3009,7 +2709,7 @@ int mysql_create_indexes(THD *thd, TABLE
     create_info.default_table_charset= thd->variables.collation_database;
     /* Cleanup the fields list. We do not want to create existing fields. */
     fields.delete_elements();
-    if (real_alter_table(thd, table_list->db, table_list->table_name,
+    if (real_alter_table(thd, table_list->db, table_list->real_name,
 			 &create_info, table_list, table,
 			 fields, keys, drop, alter, 0, (ORDER*)0,
 			 ALTER_ADD_INDEX, DUP_ERROR))
@@ -3021,7 +2721,7 @@ int mysql_create_indexes(THD *thd, TABLE
     if (table->file->add_index(table, key_info_buffer, key_count)||
         build_table_path(path, sizeof(path), table_list->db,
                          (lower_case_table_names == 2) ?
-                         table_list->alias : table_list->table_name,
+                         table_list->alias : table_list->real_name,
                          reg_ext) == 0 ||
 	mysql_create_frm(thd, path, &create_info,
 			 fields, key_count, key_info_buffer, table->file))
@@ -3105,7 +2805,7 @@ int mysql_drop_indexes(THD *thd, TABLE_L
 
   if ((drop_key)|| (drop.elements<= 0))
   {
-    if (real_alter_table(thd, table_list->db, table_list->table_name,
+    if (real_alter_table(thd, table_list->db, table_list->real_name,
 			 &create_info, table_list, table,
 			 fields, keys, drop, alter, 0, (ORDER*)0,
 			 ALTER_DROP_INDEX, DUP_ERROR))
@@ -3116,13 +2816,13 @@ int mysql_drop_indexes(THD *thd, TABLE_L
   {
     db_options= 0;
     if (table->file->drop_index(table, key_numbers, key_count)||
-	mysql_prepare_table(thd, &create_info, &fields,
-			    &keys, /*tmp_table*/ 0, &db_options, table->file,
-			    &key_info_buffer, key_count,
+	mysql_prepare_table(thd, &create_info, fields,
+			    keys, /*tmp_table*/ 0, db_options, table->file,
+			    key_info_buffer, key_count,
 			    /*select_field_count*/ 0)||
         build_table_path(path, sizeof(path), table_list->db,
                          (lower_case_table_names == 2) ?
-                         table_list->alias : table_list->table_name,
+                         table_list->alias : table_list->real_name,
                          reg_ext) == 0 ||
 	mysql_create_frm(thd, path, &create_info,
 			 fields, key_count, key_info_buffer, table->file))
@@ -3140,14 +2840,15 @@ int mysql_drop_indexes(THD *thd, TABLE_L
   Alter table
 */
 
-bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
-                       HA_CREATE_INFO *create_info,
-                       TABLE_LIST *table_list,
-                       List<create_field> &fields, List<Key> &keys,
-                       uint order_num, ORDER *order, bool ignore,
-                       ALTER_INFO *alter_info, bool do_send_ok)
+int mysql_alter_table(THD *thd,char *new_db, char *new_name,
+		      HA_CREATE_INFO *create_info,
+		      TABLE_LIST *table_list,
+		      List<create_field> &fields, List<Key> &keys,
+		      uint order_num, ORDER *order,
+		      enum enum_duplicates handle_duplicates, bool ignore,
+		      ALTER_INFO *alter_info, bool do_send_ok)
 {
-  TABLE *table,*new_table=0;
+  TABLE *table,*new_table;
   int error;
   char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
   char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
@@ -3155,14 +2856,11 @@ bool mysql_alter_table(THD *thd,char *ne
   ha_rows copied,deleted;
   ulonglong next_insert_id;
   uint db_create_options, used_fields;
-  enum db_type old_db_type, new_db_type, table_type;
-  bool need_copy_table;
-  bool no_table_reopen= FALSE, varchar= FALSE;
-  frm_type_enum frm_type;
+  enum db_type old_db_type,new_db_type;
   DBUG_ENTER("mysql_alter_table");
 
   thd->proc_info="init";
-  table_name=table_list->table_name;
+  table_name=table_list->real_name;
   alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
 
   db=table_list->db;
@@ -3174,56 +2872,10 @@ bool mysql_alter_table(THD *thd,char *ne
 
   /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
   if (alter_info->tablespace_op != NO_TABLESPACE_OP)
-    /* Conditionally writes to binlog. */
     DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
 						   alter_info->tablespace_op));
-  sprintf(new_name_buff,"%s/%s/%s%s",mysql_data_home, db, table_name, reg_ext);
-  unpack_filename(new_name_buff, new_name_buff);
-  if (lower_case_table_names != 2)
-    my_casedn_str(files_charset_info, new_name_buff);
-  frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
-  /* Rename a view */
-  if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
-  {
-    /*
-      Avoid problems with a rename on a table that we have locked or
-      if the user is trying to to do this in a transcation context
-    */
-
-    if (thd->locked_tables || thd->active_transaction())
-    {
-      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
-                 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
-      DBUG_RETURN(1);
-    }
-
-    if (wait_if_global_read_lock(thd,0,1))
-      DBUG_RETURN(1);
-    VOID(pthread_mutex_lock(&LOCK_open));
-    if (lock_table_names(thd, table_list))
-      goto view_err;
-    
-    error=0;
-    if (!do_rename(thd, table_list, new_db, new_name, new_name, 1))
-    {
-      if (mysql_bin_log.is_open())
-      {
-        thd->clear_error();
-        Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
-        mysql_bin_log.write(&qinfo);
-      }
-      send_ok(thd);
-    }
-
-    unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
-
-view_err:
-    pthread_mutex_unlock(&LOCK_open);
-    start_waiting_global_read_lock(thd);
-    DBUG_RETURN(error);
-  }
   if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
-    DBUG_RETURN(TRUE);
+    DBUG_RETURN(-1);
 
   /* Check that we are not trying to rename to an existing table */
   if (new_name)
@@ -3250,12 +2902,12 @@ view_err:
     }
     else
     {
-      if (table->s->tmp_table)
+      if (table->tmp_table)
       {
 	if (find_temporary_table(thd,new_db,new_name_buff))
 	{
-	  my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
-	  DBUG_RETURN(TRUE);
+	  my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
+	  DBUG_RETURN(-1);
 	}
       }
       else
@@ -3266,8 +2918,8 @@ view_err:
 		    F_OK))
 	{
 	  /* Table will be closed in do_command() */
-	  my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
-	  DBUG_RETURN(TRUE);
+	  my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
+	  DBUG_RETURN(-1);
 	}
       }
     }
@@ -3278,38 +2930,62 @@ view_err:
     new_name= table_name;
   }
 
-  old_db_type= table->s->db_type;
+  old_db_type=table->db_type;
   if (create_info->db_type == DB_TYPE_DEFAULT)
-    create_info->db_type= old_db_type;
-  if (check_engine(thd, new_name, &create_info->db_type))
-    DBUG_RETURN(TRUE);
-  new_db_type= create_info->db_type;
+    create_info->db_type=old_db_type;
+  if ((new_db_type= ha_checktype(create_info->db_type)) !=
+      create_info->db_type)
+  {
+    create_info->db_type= new_db_type;
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+			ER_WARN_USING_OTHER_HANDLER,
+			ER(ER_WARN_USING_OTHER_HANDLER),
+			ha_get_storage_engine(new_db_type),
+			new_name);
+  }
   if (create_info->row_type == ROW_TYPE_NOT_USED)
-    create_info->row_type= table->s->row_type;
+    create_info->row_type=table->row_type;
 
-  DBUG_PRINT("info", ("old type: %d  new type: %d", old_db_type, new_db_type));
-  if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
-      ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
-  {
-    DBUG_PRINT("info", ("doesn't support alter"));
-    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
-    DBUG_RETURN(TRUE);
-  }
-  
   thd->proc_info="setup";
-  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
-      !table->s->tmp_table) // no need to touch frm
+  if (alter_info->is_simple && !table->tmp_table)
   {
-    error=0;
-    VOID(pthread_mutex_lock(&LOCK_open));
-    if (new_name != table_name || new_db != db)
+    switch (alter_info->keys_onoff) {
+    case LEAVE_AS_IS:
+      error= 0;
+      break;
+    case ENABLE:
+      VOID(pthread_mutex_lock(&LOCK_open));
+      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+      VOID(pthread_mutex_unlock(&LOCK_open));
+      error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+      /* COND_refresh will be signaled in close_thread_tables() */
+      break;
+    case DISABLE:
+      VOID(pthread_mutex_lock(&LOCK_open));
+      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+      VOID(pthread_mutex_unlock(&LOCK_open));
+      error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+      /* COND_refresh will be signaled in close_thread_tables() */
+      break;
+    }
+
+    if (error == HA_ERR_WRONG_COMMAND)
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+			  ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
+			  table->table_name);
+      error= 0;
+    }
+
+    if (!error && (new_name != table_name || new_db != db))
     {
       thd->proc_info="rename";
+      VOID(pthread_mutex_lock(&LOCK_open));
       /* Then do a 'simple' rename of the table */
       error=0;
       if (!access(new_name_buff,F_OK))
       {
-	my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
+	my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
 	error= -1;
       }
       else
@@ -3318,47 +2994,25 @@ view_err:
 	close_cached_table(thd, table);
 	if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias))
 	  error= -1;
-        else if (Table_triggers_list::change_table_name(thd, db, table_name,
-                                                        new_db, new_alias))
-        {
-          VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
-                                  table_name));
-          error= -1;
-        }
-      }
-    }
-
-    if (!error)
-    {
-      switch (alter_info->keys_onoff) {
-      case LEAVE_AS_IS:
-        break;
-      case ENABLE:
-        wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
-        error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
-        /* COND_refresh will be signaled in close_thread_tables() */
-        break;
-      case DISABLE:
-        wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
-        error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
-        /* COND_refresh will be signaled in close_thread_tables() */
-        break;
       }
+      VOID(pthread_mutex_unlock(&LOCK_open));
     }
 
     if (error == HA_ERR_WRONG_COMMAND)
     {
       push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 			  ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
-			  table->alias);
+			  table->table_name);
       error=0;
     }
+
     if (!error)
     {
+      mysql_update_log.write(thd, thd->query, thd->query_length);
       if (mysql_bin_log.is_open())
       {
 	thd->clear_error();
-	Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+	Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
 	mysql_bin_log.write(&qinfo);
       }
       if (do_send_ok)
@@ -3369,7 +3023,6 @@ view_err:
       table->file->print_error(error, MYF(0));
       error= -1;
     }
-    VOID(pthread_mutex_unlock(&LOCK_open));
     table_list->table=0;				// For query cache
     query_cache_invalidate3(thd, table_list, 0);
     DBUG_RETURN(error);
@@ -3377,17 +3030,17 @@ view_err:
 
   /* Full alter table */
 
-  /* Let new create options override the old ones */
+  /* let new create options override the old ones */
   if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
-    create_info->min_rows= table->s->min_rows;
+    create_info->min_rows=table->min_rows;
   if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
-    create_info->max_rows= table->s->max_rows;
+    create_info->max_rows=table->max_rows;
   if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
-    create_info->avg_row_length= table->s->avg_row_length;
+    create_info->avg_row_length=table->avg_row_length;
   if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
-    create_info->default_table_charset= table->s->table_charset;
+    create_info->default_table_charset= table->table_charset;
 
-  restore_record(table, s->default_values);     // Empty record for DEFAULT
+  restore_record(table,default_values);		// Empty record for DEFAULT
   List_iterator<Alter_drop> drop_it(alter_info->drop_list);
   List_iterator<create_field> def_it(fields);
   List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -3402,8 +3055,6 @@ view_err:
   Field **f_ptr,*field;
   for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
   {
-    if (field->type() == MYSQL_TYPE_STRING)
-      varchar= TRUE;
     /* Check if field should be dropped */
     Alter_drop *drop;
     drop_it.rewind();
@@ -3458,13 +3109,10 @@ view_err:
       {
 	if (def->sql_type == FIELD_TYPE_BLOB)
 	{
-	  my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
-	  DBUG_RETURN(TRUE);
+	  my_error(ER_BLOB_CANT_HAVE_DEFAULT,MYF(0),def->change);
+	  DBUG_RETURN(-1);
 	}
-	if ((def->def=alter->def))              // Use new default
-          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
-        else
-          def->flags|= NO_DEFAULT_VALUE_FLAG;
+	def->def=alter->def;			// Use new default
 	alter_it.remove();
       }
     }
@@ -3475,8 +3123,8 @@ view_err:
   {
     if (def->change && ! def->field)
     {
-      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name);
-      DBUG_RETURN(TRUE);
+      my_error(ER_BAD_FIELD_ERROR,MYF(0),def->change,table_name);
+      DBUG_RETURN(-1);
     }
     if (!def->after)
       create_list.push_back(def);
@@ -3493,23 +3141,22 @@ view_err:
       }
       if (!find)
       {
-	my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table_name);
-	DBUG_RETURN(TRUE);
+	my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name);
+	DBUG_RETURN(-1);
       }
       find_it.after(def);			// Put element after this
     }
   }
   if (alter_info->alter_list.elements)
   {
-    my_error(ER_BAD_FIELD_ERROR, MYF(0),
-             alter_info->alter_list.head()->name, table_name);
-    DBUG_RETURN(TRUE);
+    my_error(ER_BAD_FIELD_ERROR,MYF(0),alter_info->alter_list.head()->name,
+	     table_name);
+    DBUG_RETURN(-1);
   }
   if (!create_list.elements)
   {
-    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
-               MYF(0));
-    DBUG_RETURN(TRUE);
+    my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
+    DBUG_RETURN(-1);
   }
 
   /*
@@ -3522,7 +3169,7 @@ view_err:
   List<key_part_spec> key_parts;
 
   KEY *key_info=table->key_info;
-  for (uint i=0 ; i < table->s->keys ; i++,key_info++)
+  for (uint i=0 ; i < table->keys ; i++,key_info++)
   {
     char *key_name= key_info->name;
     Alter_drop *drop;
@@ -3564,26 +3211,12 @@ view_err:
 	continue;				// Field is removed
       uint key_part_length=key_part->length;
       if (cfield->field)			// Not new field
-      {
-        /*
-          If the field can't have only a part used in a key according to its
-          new type, or should not be used partially according to its
-          previous type, or the field length is less than the key part
-          length, unset the key part length.
-
-          We also unset the key part length if it is the same as the
-          old field's length, so the whole new field will be used.
-
-          BLOBs may have cfield->length == 0, which is why we test it before
-          checking whether cfield->length < key_part_length (in chars).
-         */
-        if (!Field::type_can_have_key_part(cfield->field->type()) ||
-            !Field::type_can_have_key_part(cfield->sql_type) ||
-            (cfield->field->field_length == key_part_length &&
-             !f_is_blob(key_part->key_type)) ||
-	    (cfield->length && (cfield->length < key_part_length /
-                                key_part->field->charset()->mbmaxlen)))
-	  key_part_length= 0;			// Use whole field
+      {						// Check if sub key
+	if (cfield->field->type() != FIELD_TYPE_BLOB &&
+	    (cfield->field->pack_length() == key_part_length ||
+	     cfield->length <= key_part_length /
+			       key_part->field->charset()->mbmaxlen))
+	  key_part_length=0;			// Use whole field
       }
       key_part_length /= key_part->field->charset()->mbmaxlen;
       key_parts.push_back(new key_part_spec(cfield->field_name,
@@ -3612,25 +3245,25 @@ view_err:
 	  !my_strcasecmp(system_charset_info,key->name,primary_key_name))
       {
 	my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
-	DBUG_RETURN(TRUE);
+	DBUG_RETURN(-1);
       }
     }
   }
 
   if (alter_info->drop_list.elements)
   {
-    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
-             alter_info->drop_list.head()->name);
+    my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
+	     alter_info->drop_list.head()->name);
     goto err;
   }
   if (alter_info->alter_list.elements)
   {
-    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
-             alter_info->alter_list.head()->name);
+    my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
+	     alter_info->alter_list.head()->name);
     goto err;
   }
 
-  db_create_options= table->s->db_create_options & ~(HA_OPTION_PACK_RECORD);
+  db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
   my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
 	      current_pid, thd->thread_id);
   /* Safety fix for innodb */
@@ -3641,11 +3274,8 @@ view_err:
     goto err;
   }
   create_info->db_type=new_db_type;
-  if (!create_info->comment.str)
-  {
-    create_info->comment.str= table->s->comment.str;
-    create_info->comment.length= table->s->comment.length;
-  }
+  if (!create_info->comment)
+    create_info->comment=table->comment;
 
   table->file->update_create_info(create_info);
   if ((create_info->table_options &
@@ -3661,37 +3291,10 @@ view_err:
 			  HA_OPTION_NO_DELAY_KEY_WRITE);
   create_info->table_options|= db_create_options;
 
-  if (table->s->tmp_table)
+  if (table->tmp_table)
     create_info->options|=HA_LEX_CREATE_TMP_TABLE;
 
   /*
-    better have a negative test here, instead of positive, like
-    alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|...
-    so that ALTER TABLE won't break when somebody will add new flag
-
-    MySQL uses frm version to determine the type of the data fields and
-    their layout. See Field_string::type() for details.
-    Thus, if the table is too old we may have to rebuild the data to
-    update the layout.
-
-    There was a bug prior to mysql-4.0.25. Number of null fields was
-    calculated incorrectly. As a result frm and data files gets out of
-    sync after fast alter table. There is no way to determine by which
-    mysql version (in 4.0 and 4.1 branches) table was created, thus we
-    disable fast alter table for all tables created by mysql versions
-    prior to 5.0 branch.
-    See BUG#6236.
-  */
-  need_copy_table= (alter_info->flags &
-                    ~(ALTER_CHANGE_COLUMN_DEFAULT|ALTER_OPTIONS) ||
-                    (create_info->used_fields &
-                     ~(HA_CREATE_USED_COMMENT|HA_CREATE_USED_PASSWORD)) ||
-                    table->s->tmp_table ||
-                    !table->s->mysql_version ||
-                    (table->s->frm_version < FRM_VER_TRUE_VARCHAR &&
varchar));
-  create_info->frm_only= !need_copy_table;
-
-  /*
     Handling of symlinked tables:
     If no rename:
       Create new data file and index file on the same disk as the
@@ -3737,9 +3340,8 @@ view_err:
   }
   else
     create_info->data_file_name=create_info->index_file_name=0;
-
-  /* We don't log the statement, it will be logged later. */
   {
+    /* We don't log the statement, it will be logged later. */
     tmp_disable_binlog(thd);
     error= mysql_create_table(thd, new_db, tmp_name,
                               create_info,create_list,key_list,1,0);
@@ -3747,49 +3349,37 @@ view_err:
     if (error)
       DBUG_RETURN(error);
   }
-  if (need_copy_table)
+  if (table->tmp_table)
+    new_table=open_table(thd,new_db,tmp_name,tmp_name,0);
+  else
   {
-    if (table->s->tmp_table)
-    {
-      TABLE_LIST tbl;
-      bzero((void*) &tbl, sizeof(tbl));
-      tbl.db= new_db;
-      tbl.table_name= tbl.alias= tmp_name;
-      new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
-                            MYSQL_LOCK_IGNORE_FLUSH);
-    }
-    else
-    {
-      char path[FN_REFLEN];
-      my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
-                  new_db, tmp_name);
-      fn_format(path,path,"","",4);
-      new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
-    }
-    if (!new_table)
-    {
-      VOID(quick_rm_table(new_db_type,new_db,tmp_name));
-      goto err;
-    }
+    char path[FN_REFLEN];
+    build_table_path(path, sizeof(path), new_db, tmp_name, "");
+    new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
   }
+  if (!new_table)
+  {
+    VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+    goto err;
+  }
+
 
   /* We don't want update TIMESTAMP fields during ALTER TABLE. */
+  new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+  new_table->next_number_field=new_table->found_next_number_field;
   thd->count_cuted_fields= CHECK_FIELD_WARN;	// calc cuted fields
   thd->cuted_fields=0L;
   thd->proc_info="copy to tmp table";
-  next_insert_id=thd->next_insert_id;		// Remember for logging
+  next_insert_id=thd->next_insert_id;		// Remember for loggin
   copied=deleted=0;
-  if (new_table && !new_table->s->is_view)
-  {
-    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-    new_table->next_number_field=new_table->found_next_number_field;
-    error=copy_data_between_tables(table, new_table, create_list, ignore,
+  if (!new_table->is_view)
+    error=copy_data_between_tables(table,new_table,create_list,
+				   handle_duplicates, ignore,
 				   order_num, order, &copied, &deleted);
-  }
   thd->last_insert_id=next_insert_id;		// Needed for correct log
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
-  if (table->s->tmp_table)
+  if (table->tmp_table)
   {
     /* We changed a temporary table */
     if (error)
@@ -3808,7 +3398,7 @@ view_err:
       thd->lock=0;
     }
     /* Remove link to old table and rename the new one */
-    close_temporary_table(thd, table->s->db, table_name);
+    close_temporary_table(thd,table->table_cache_key,table_name);
     /* Should pass the 'new_name' as we store table name in the cache */
     if (rename_temporary_table(thd, new_table, new_db, new_name))
     {						// Fatal error
@@ -3816,24 +3406,18 @@ view_err:
       my_free((gptr) new_table,MYF(0));
       goto err;
     }
-    /* 
-     Writing to the binlog does not need to be synchronized for temporary tables, 
-     which are thread-specific. 
-    */
+    mysql_update_log.write(thd, thd->query,thd->query_length);
     if (mysql_bin_log.is_open())
     {
       thd->clear_error();
-      Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+      Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
       mysql_bin_log.write(&qinfo);
     }
     goto end_temporary;
   }
 
-  if (new_table)
-  {
-    intern_close_table(new_table);              /* close temporary table */
-    my_free((gptr) new_table,MYF(0));
-  }
+  intern_close_table(new_table);		/* close temporary table */
+  my_free((gptr) new_table,MYF(0));
   VOID(pthread_mutex_lock(&LOCK_open));
   if (error)
   {
@@ -3845,7 +3429,7 @@ view_err:
   /*
     Data is copied.  Now we rename the old table to a temp name,
     rename the new one to the old name, remove all entries from the old table
-    from the cache, free all locks, close the old table and remove it.
+    from the cash, free all locks, close the old table and remove it.
   */
 
   thd->proc_info="rename result table";
@@ -3858,7 +3442,7 @@ view_err:
     if (!access(new_name_buff,F_OK))
     {
       error=1;
-      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
+      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
       VOID(quick_rm_table(new_db_type,new_db,tmp_name));
       VOID(pthread_mutex_unlock(&LOCK_open));
       goto err;
@@ -3873,9 +3457,14 @@ view_err:
       Win32 and InnoDB can't drop a table that is in use, so we must
       close the original table at before doing the rename
     */
-    close_cached_table(thd, table);
+    table_name=thd->strdup(table_name);		// must be saved
+    if (close_cached_table(thd, table))
+    {						// Aborted
+      VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+      VOID(pthread_mutex_unlock(&LOCK_open));
+      goto err;
+    }
     table=0;					// Marker that table is closed
-    no_table_reopen= TRUE;
   }
 #if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
   else
@@ -3884,19 +3473,13 @@ view_err:
 
 
   error=0;
-  if (!need_copy_table)
-    new_db_type=old_db_type=DB_TYPE_UNKNOWN; // this type cannot happen in regular ALTER
   if (mysql_rename_table(old_db_type,db,table_name,db,old_name))
   {
     error=1;
     VOID(quick_rm_table(new_db_type,new_db,tmp_name));
   }
   else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db,
-			      new_alias) ||
-           (new_name != table_name || new_db != db) && // we also do rename
-           Table_triggers_list::change_table_name(thd, db, table_name,
-                                                  new_db, new_alias))
-       
+			      new_alias))
   {						// Try to get everything back
     error=1;
     VOID(quick_rm_table(new_db_type,new_db,new_alias));
@@ -3914,7 +3497,7 @@ view_err:
     VOID(pthread_mutex_unlock(&LOCK_open));
     goto err;
   }
-  if (thd->lock || new_name != table_name || no_table_reopen)  // True if WIN32
+  if (thd->lock || new_name != table_name)	// True if WIN32
   {
     /*
       Not table locking or alter table with rename
@@ -3956,17 +3539,18 @@ view_err:
   if (error)
   {
     VOID(pthread_mutex_unlock(&LOCK_open));
-    broadcast_refresh();
+    VOID(pthread_cond_broadcast(&COND_refresh));
     goto err;
   }
   thd->proc_info="end";
+  mysql_update_log.write(thd, thd->query,thd->query_length);
   if (mysql_bin_log.is_open())
   {
     thd->clear_error();
-    Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+    Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
     mysql_bin_log.write(&qinfo);
   }
-  broadcast_refresh();
+  VOID(pthread_cond_broadcast(&COND_refresh));
   VOID(pthread_mutex_unlock(&LOCK_open));
 #ifdef HAVE_BERKELEY_DB
   if (old_db_type == DB_TYPE_BERKELEY_DB)
@@ -4000,16 +3584,17 @@ end_temporary:
   if (do_send_ok)
     send_ok(thd,copied+deleted,0L,tmp_name);
   thd->some_tables_deleted=0;
-  DBUG_RETURN(FALSE);
+  DBUG_RETURN(0);
 
-err:
-  DBUG_RETURN(TRUE);
+ err:
+  DBUG_RETURN(-1);
 }
 
 
 static int
 copy_data_between_tables(TABLE *from,TABLE *to,
 			 List<create_field> &create,
+			 enum enum_duplicates handle_duplicates,
                          bool ignore,
 			 uint order_num, ORDER *order,
 			 ha_rows *copied,
@@ -4040,18 +3625,11 @@ copy_data_between_tables(TABLE *from,TAB
   if (error)
     DBUG_RETURN(-1);
   
-  if (!(copy= new Copy_field[to->s->fields]))
+  if (!(copy= new Copy_field[to->fields]))
     DBUG_RETURN(-1);				/* purecov: inspected */
 
   if (to->file->external_lock(thd, F_WRLCK))
     DBUG_RETURN(-1);
-
-  /* We can abort alter table for any table type */
-  thd->no_trans_update= 0;
-  thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
-                                         (MODE_STRICT_TRANS_TABLES |
-                                          MODE_STRICT_ALL_TABLES));
-
   from->file->info(HA_STATUS_VARIABLE);
   to->file->start_bulk_insert(from->file->records);
 
@@ -4089,38 +3667,36 @@ copy_data_between_tables(TABLE *from,TAB
     from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
 					      MYF(MY_FAE | MY_ZEROFILL));
     bzero((char*) &tables,sizeof(tables));
-    tables.table= from;
-    tables.alias= tables.table_name= (char*) from->s->table_name;
-    tables.db=    (char*) from->s->db;
+    tables.table = from;
+    tables.alias = tables.real_name= from->real_name;
+    tables.db	 = from->table_cache_key;
     error=1;
 
     if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
 	setup_order(thd, thd->lex->select_lex.ref_pointer_array,
 		    &tables, fields, all_fields, order) ||
-	!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
+	!(sortorder=make_unireg_sortorder(order, &length)) ||
 	(from->sort.found_records = filesort(thd, from, sortorder, length,
 					     (SQL_SELECT *) 0, HA_POS_ERROR,
-					     &examined_rows)) ==
-	HA_POS_ERROR)
+					     &examined_rows))
+	== HA_POS_ERROR)
       goto err;
   };
 
-  /*
-    Handler must be told explicitly to retrieve all columns, because
-    this function does not set field->query_id in the columns to the
-    current query id
-  */
+  /* Handler must be told explicitly to retrieve all columns, because
+     this function does not set field->query_id in the columns to the
+     current query id */
   from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
   init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
-  if (ignore)
+  if (ignore ||
+      handle_duplicates == DUP_REPLACE)
     to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
   thd->row_count= 0;
-  restore_record(to, s->default_values);        // Create empty record
   while (!(error=info.read_record(&info)))
   {
     if (thd->killed)
     {
-      thd->send_kill_message();
+      my_error(ER_SERVER_SHUTDOWN,MYF(0));
       error= 1;
       break;
     }
@@ -4132,21 +3708,20 @@ copy_data_between_tables(TABLE *from,TAB
       else
         to->next_number_field->reset();
     }
-    
     for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
     {
       copy_ptr->do_copy(copy_ptr);
     }
     if ((error=to->file->write_row((byte*) to->record[0])))
     {
-      if (!ignore ||
+      if ((!ignore &&
+	   handle_duplicates != DUP_REPLACE) ||
 	  (error != HA_ERR_FOUND_DUPP_KEY &&
 	   error != HA_ERR_FOUND_DUPP_UNIQUE))
       {
 	to->file->print_error(error,MYF(0));
 	break;
       }
-      to->file->restore_auto_increment();
       delete_count++;
     }
     else
@@ -4156,7 +3731,7 @@ copy_data_between_tables(TABLE *from,TAB
   free_io_cache(from);
   delete [] copy;				// This is never 0
 
-  if (to->file->end_bulk_insert() && error <= 0)
+  if (to->file->end_bulk_insert() && !error)
   {
     to->file->print_error(my_errno,MYF(0));
     error=1;
@@ -4176,7 +3751,6 @@ copy_data_between_tables(TABLE *from,TAB
 
  err:
   thd->variables.sql_mode= save_sql_mode;
-  thd->abort_on_warning= 0;
   free_io_cache(from);
   *copied= found_count;
   *deleted=delete_count;
@@ -4198,8 +3772,8 @@ copy_data_between_tables(TABLE *from,TAB
  RETURN
     Like mysql_alter_table().
 */
-bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
-                          bool do_send_ok)
+int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
+                         bool do_send_ok)
 {
   DBUG_ENTER("mysql_recreate_table");
   LEX *lex= thd->lex;
@@ -4208,20 +3782,19 @@ bool mysql_recreate_table(THD *thd, TABL
   lex->key_list.empty();
   lex->col_list.empty();
   lex->alter_info.reset();
+  lex->alter_info.is_simple= 0;                 // Force full recreate
   bzero((char*) &create_info,sizeof(create_info));
   create_info.db_type=DB_TYPE_DEFAULT;
-  create_info.row_type=ROW_TYPE_NOT_USED;
+  create_info.row_type=ROW_TYPE_DEFAULT;
   create_info.default_table_charset=default_charset_info;
-  /* Force alter table to recreate table */
-  lex->alter_info.flags= ALTER_CHANGE_COLUMN;
   DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
                                 table_list, lex->create_list,
                                 lex->key_list, 0, (ORDER *) 0,
-                                0, &lex->alter_info, do_send_ok));
+                                DUP_ERROR, 0, &lex->alter_info, do_send_ok));
 }
 
 
-bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
+int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
 {
   TABLE_LIST *table;
   List<Item> field_list;
@@ -4233,18 +3806,17 @@ bool mysql_checksum_table(THD *thd, TABL
   item->maybe_null= 1;
   field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
   item->maybe_null= 1;
-  if (protocol->send_fields(&field_list,
-                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
-    DBUG_RETURN(TRUE);
+  if (protocol->send_fields(&field_list, 1))
+    DBUG_RETURN(-1);
 
-  for (table= tables; table; table= table->next_local)
+  for (table= tables; table; table= table->next)
   {
     char table_name[NAME_LEN*2+2];
     TABLE *t;
 
-    strxmov(table_name, table->db ,".", table->table_name, NullS);
+    strxmov(table_name, table->db ,".", table->real_name, NullS);
 
-    t= table->table= open_ltable(thd, table, TL_READ);
+    t= table->table= open_ltable(thd, table, TL_READ_NO_INSERT);
     thd->clear_error();			// these errors shouldn't get client
 
     protocol->prepare_for_resend();
@@ -4254,7 +3826,7 @@ bool mysql_checksum_table(THD *thd, TABL
     {
       /* Table didn't exist */
       protocol->store_null();
-      thd->clear_error();
+      thd->net.last_error[0]=0;
     }
     else
     {
@@ -4270,7 +3842,6 @@ bool mysql_checksum_table(THD *thd, TABL
       {
 	/* calculating table's checksum */
 	ha_checksum crc= 0;
-        uchar null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
 	/* InnoDB must be told explicitly to retrieve all columns, because
 	this function does not set field->query_id in the columns to the
@@ -4291,21 +3862,14 @@ bool mysql_checksum_table(THD *thd, TABL
                 continue;
               break;
             }
-	    if (t->s->null_bytes)
-            {
-              /* fix undefined null bits */
-              t->record[0][t->s->null_bytes-1] |= null_mask;
-              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
-                t->record[0][0] |= 1;
-
-	      row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
-            }
+	    if (t->record[0] != (byte*) t->field[0]->ptr)
+	      row_crc= my_checksum(row_crc, t->record[0],
+				   ((byte*) t->field[0]->ptr) - t->record[0]);
 
-	    for (uint i= 0; i < t->s->fields; i++ )
+	    for (uint i= 0; i < t->fields; i++ )
 	    {
 	      Field *f= t->field[i];
-	      if ((f->type() == FIELD_TYPE_BLOB) ||
-                  (f->type() == MYSQL_TYPE_VARCHAR))
+	      if (f->type() == FIELD_TYPE_BLOB)
 	      {
 		String tmp;
 		f->val_str(&tmp);
@@ -4331,32 +3895,11 @@ bool mysql_checksum_table(THD *thd, TABL
   }
 
   send_eof(thd);
-  DBUG_RETURN(FALSE);
+  DBUG_RETURN(0);
 
  err:
   close_thread_tables(thd);			// Shouldn't be needed
   if (table)
     table->table=0;
-  DBUG_RETURN(TRUE);
-}
-
-static bool check_engine(THD *thd, const char *table_name,
-                         enum db_type *new_engine)
-{
-  enum db_type req_engine= *new_engine;
-  bool no_substitution=
-        test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
-  if ((*new_engine=
-       ha_checktype(thd, req_engine, no_substitution, 1)) == DB_TYPE_UNKNOWN)
-    return TRUE;
-
-  if (req_engine != *new_engine)
-  {
-    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                       ER_WARN_USING_OTHER_HANDLER,
-                       ER(ER_WARN_USING_OTHER_HANDLER),
-                       ha_get_storage_engine(*new_engine),
-                       table_name);
-  }
-  return FALSE;
+  DBUG_RETURN(-1);
 }

--- 1.56/mysql-test/r/alter_table.result	2006-11-16 13:31:47 +01:00
+++ 1.57/mysql-test/r/alter_table.result	2006-11-16 13:31:47 +01:00
@@ -428,42 +428,42 @@ t1	MyISAM	10	Fixed	1	37	X	X	X	X	X	X	X	X	
 drop table t1;
 set names koi8r;
 create table t1 (a char(10) character set koi8r);
-insert into t1 values ('ΤΕΣΤ');
+insert into t1 values ('ÔÅÓÔ');
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	D4C5D3D4
+ÔÅÓÔ	D4C5D3D4
 alter table t1 change a a char(10) character set cp1251;
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	F2E5F1F2
+ÔÅÓÔ	F2E5F1F2
 alter table t1 change a a binary(4);
 select a,hex(a) from t1;
 a	hex(a)
-ςερς	F2E5F1F2
+òåñò	F2E5F1F2
 alter table t1 change a a char(10) character set cp1251;
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	F2E5F1F2
+ÔÅÓÔ	F2E5F1F2
 alter table t1 change a a char(10) character set koi8r;
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	D4C5D3D4
+ÔÅÓÔ	D4C5D3D4
 alter table t1 change a a varchar(10) character set cp1251;
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	F2E5F1F2
+ÔÅÓÔ	F2E5F1F2
 alter table t1 change a a char(10) character set koi8r;
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	D4C5D3D4
+ÔÅÓÔ	D4C5D3D4
 alter table t1 change a a text character set cp1251;
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	F2E5F1F2
+ÔÅÓÔ	F2E5F1F2
 alter table t1 change a a char(10) character set koi8r;
 select a,hex(a) from t1;
 a	hex(a)
-ΤΕΣΤ	D4C5D3D4
+ÔÅÓÔ	D4C5D3D4
 delete from t1;
 show create table t1;
 Table	Create Table
@@ -528,7 +528,7 @@ ALTER TABLE T12207 DISCARD TABLESPACE;
 ERROR HY000: Table storage engine for 'T12207' doesn't have this option
 DROP TABLE T12207;
 create table t1 (a text) character set koi8r;
-insert into t1 values (_koi8r'ΤΕΣΤ');
+insert into t1 values (_koi8r'ÔÅÓÔ');
 select hex(a) from t1;
 hex(a)
 D4C5D3D4
@@ -566,3 +566,14 @@ create table t1 (t varchar(255) default 
 engine=myisam default charset=latin1;
 alter table t1 change t t text;
 drop table t1;
+DROP TABLE IF EXISTS bug24219;
+DROP TABLE IF EXISTS bug24219_2;
+CREATE TABLE bug24219 (a INT, INDEX(a));
+SHOW INDEX FROM bug24219;
+Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
+bug24219	1	a	1	a	A	NULL	NULL	NULL	YES	BTREE	
+ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;
+SHOW INDEX FROM bug24219_2;
+Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
+bug24219_2	1	a	1	a	A	NULL	NULL	NULL	YES	BTREE	disabled
+DROP TABLE bug24219_2;

--- 1.44/mysql-test/t/alter_table.test	2006-11-16 13:31:47 +01:00
+++ 1.45/mysql-test/t/alter_table.test	2006-11-16 13:31:47 +01:00
@@ -274,7 +274,7 @@ drop table t1;
 #
 set names koi8r;
 create table t1 (a char(10) character set koi8r);
-insert into t1 values ('ΤΕΣΤ');
+insert into t1 values ('ÔÅÓÔ');
 select a,hex(a) from t1;
 alter table t1 change a a char(10) character set cp1251;
 select a,hex(a) from t1;
@@ -354,7 +354,7 @@ DROP TABLE T12207;
 # modified. In other words, the values were reinterpreted
 # as UTF8 instead of being converted.
 create table t1 (a text) character set koi8r;
-insert into t1 values (_koi8r'ΤΕΣΤ');
+insert into t1 values (_koi8r'ÔÅÓÔ');
 select hex(a) from t1;
 alter table t1 convert to character set cp1251;
 select hex(a) from t1;
@@ -402,8 +402,6 @@ alter table test.t1 rename test.t1;
 use test;
 drop table t1;
 
-# End of 4.1 tests
-
 #
 # Bug #14693 (ALTER SET DEFAULT doesn't work)
 #
@@ -422,3 +420,24 @@ create table t1 (t varchar(255) default 
 engine=myisam default charset=latin1;
 alter table t1 change t t text;
 drop table t1;
+
+#
+# Bug#24219 - ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash
+#
+--disable_warnings
+DROP TABLE IF EXISTS bug24219;
+DROP TABLE IF EXISTS bug24219_2;
+--enable_warnings
+
+CREATE TABLE bug24219 (a INT, INDEX(a));
+
+SHOW INDEX FROM bug24219;
+
+ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;
+
+SHOW INDEX FROM bug24219_2;
+
+DROP TABLE bug24219_2;
+
+# End of 4.1 tests
+
Thread
bk commit into 5.0 tree (andrey:1.2335)ahristov16 Nov