diff --git a/sql/handler.cc b/sql/handler.cc
index e74103489ebb2a6baa9f3f52f57373fbe432630b..5bfd008ea194e8363bba9f934149149b3b1af945 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -785,7 +785,7 @@ bool ha_flush_logs()
 int ha_delete_table(enum db_type table_type, const char *path)
 {
   char tmp_path[FN_REFLEN];
-  handler *file=get_new_handler((TABLE*) 0, table_type);
+  handler *file=(table_type== DB_TYPE_UNKNOWN ? 0 : get_new_handler((TABLE*) 0, table_type));
   if (!file)
     return ENOENT;
   if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
diff --git a/sql/handler.h b/sql/handler.h
index 9a08b8ed78c5649c8800f5ee99ed991228fa2ede..c07fef34753112d0b5c0234ae159a670c72b41de 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -139,16 +139,16 @@
 #define HA_CACHE_TBL_TRANSACT    4
 
 
-enum db_type 
-{ 
+enum db_type
+{
   DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
   DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
   DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
   DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
-  DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB, 
+  DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
   DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
   DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
-	       
+
   DB_TYPE_DEFAULT // Must be last
 };
 
@@ -165,16 +165,24 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
 /* struct to hold information about the table that should be created */
 
 /* Bits in used_fields */
-#define HA_CREATE_USED_AUTO		1
-#define HA_CREATE_USED_RAID		2
-#define HA_CREATE_USED_UNION		4
-#define HA_CREATE_USED_INSERT_METHOD	8
-#define HA_CREATE_USED_MIN_ROWS		16
-#define HA_CREATE_USED_MAX_ROWS		32
-#define HA_CREATE_USED_AVG_ROW_LENGTH	64
-#define HA_CREATE_USED_PACK_KEYS	128
-#define HA_CREATE_USED_CHARSET		256
-#define HA_CREATE_USED_DEFAULT_CHARSET	512
+#define HA_CREATE_USED_AUTO             (1L << 0)
+#define HA_CREATE_USED_RAID             (1L << 1)
+#define HA_CREATE_USED_UNION            (1L << 2)
+#define HA_CREATE_USED_INSERT_METHOD    (1L << 3)
+#define HA_CREATE_USED_MIN_ROWS         (1L << 4)
+#define HA_CREATE_USED_MAX_ROWS         (1L << 5)
+#define HA_CREATE_USED_AVG_ROW_LENGTH   (1L << 6)
+#define HA_CREATE_USED_PACK_KEYS        (1L << 7)
+#define HA_CREATE_USED_CHARSET          (1L << 8)
+#define HA_CREATE_USED_DEFAULT_CHARSET  (1L << 9)
+#define HA_CREATE_USED_DATADIR          (1L << 10)
+#define HA_CREATE_USED_INDEXDIR         (1L << 11)
+#define HA_CREATE_USED_ENGINE           (1L << 12)
+#define HA_CREATE_USED_CHECKSUM         (1L << 13)
+#define HA_CREATE_USED_DELAY_KEY_WRITE  (1L << 14)
+#define HA_CREATE_USED_ROW_FORMAT       (1L << 15)
+#define HA_CREATE_USED_COMMENT          (1L << 16)
+#define HA_CREATE_USED_PASSWORD         (1L << 17)
 
 typedef struct st_thd_trans {
   void *bdb_tid;
@@ -205,6 +213,7 @@ typedef struct st_ha_create_information
   uint raid_type,raid_chunks;
   uint merge_insert_method;
   bool table_existed;			/* 1 in create if table existed */
+  bool frm_only;                        /* 1 if no ha_create_table() */
 } HA_CREATE_INFO;
 
 
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index af5b0896fa51ea688dfbde04de51585b24ff7fa0..74686dbbce870854aae934a75b9b535fac66255f 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -593,6 +593,9 @@ typedef class st_select_lex SELECT_LEX;
 #define ALTER_RENAME		32
 #define ALTER_ORDER		64
 #define ALTER_OPTIONS		128
+#define ALTER_CHANGE_COLUMN_DEFAULT 256
+#define ALTER_KEYS_ONOFF        512
+#define ALTER_CONVERT          1024
 
 typedef struct st_alter_info
 {
@@ -601,7 +604,6 @@ typedef struct st_alter_info
   uint                        flags;
   enum enum_enable_or_disable keys_onoff;
   enum tablespace_op_type     tablespace_op;
-  bool                        is_simple;
 
   st_alter_info(){clear();}
   void clear(){keys_onoff= LEAVE_AS_IS;tablespace_op= NO_TABLESPACE_OP;}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f93aaf099333e2d28993e2e25a09a87a81e70cdf..b97e96a7987e358317249b95772516ff5215d549 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5862,7 +5862,6 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
   List<create_field> fields;
   ALTER_INFO alter_info;
   alter_info.flags= ALTER_ADD_INDEX;
-  alter_info.is_simple= 0;
   HA_CREATE_INFO create_info;
   DBUG_ENTER("mysql_create_index");
   bzero((char*) &create_info,sizeof(create_info));
@@ -5886,7 +5885,6 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
   create_info.default_table_charset= thd->variables.collation_database;
   alter_info->clear();
   alter_info->flags= ALTER_DROP_INDEX;
-  alter_info->is_simple= 0;
   DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
 				&create_info, table_list,
 				fields, keys, 0, (ORDER*)0,
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 399fed00040153adbb480d725de3c0af4ee24a59..d96474c8fdaa817a22ed2e9eb82622643c1dc1b4 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1093,7 +1093,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
 			(From ALTER TABLE)
 
   DESCRIPTION
-    If one creates a temporary table, this is automaticly opened
+    If one creates a temporary table, this is automatically opened
 
     no_log is needed for the case of CREATE ... SELECT,
     as the logging will be done later in sql_insert.cc
@@ -1424,11 +1424,12 @@ mysql_rename_table(enum db_type base,
 {
   char from[FN_REFLEN], to[FN_REFLEN];
   char tmp_from[NAME_LEN+1], tmp_to[NAME_LEN+1];
-  handler *file=get_new_handler((TABLE*) 0, base);
+  handler *file=(base == DB_TYPE_UNKNOWN ? 0 : get_new_handler((TABLE*) 0, base));
   int error=0;
   DBUG_ENTER("mysql_rename_table");
 
-  if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
+  if (lower_case_table_names == 2 && file &&
+      !(file->table_flags() & HA_FILE_BASED))
   {
     /* Table handler expects to get all file names as lower case */
     strmov(tmp_from, old_name);
@@ -1446,13 +1447,15 @@ mysql_rename_table(enum db_type base,
   fn_format(from,from,"","",4);
   fn_format(to,to,    "","",4);
 
-  if (!(error=file->rename_table((const char*) from,(const char *) to)))
+  if (!file ||
+      !(error=file->rename_table((const char*) from,(const char *) to)))
   {
     if (rename_file_ext(from,to,reg_ext))
     {
       error=my_errno;
       /* Restore old file name */
-      file->rename_table((const char*) to,(const char *) from);
+      if (file)
+        file->rename_table((const char*) to,(const char *) from);
     }
   }
   delete file;
@@ -2536,7 +2539,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
 		      enum enum_duplicates handle_duplicates,
 		      ALTER_INFO *alter_info, bool do_send_ok)
 {
-  TABLE *table,*new_table;
+  TABLE *table,*new_table=0;
   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;
@@ -2545,6 +2548,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
   ulonglong next_insert_id;
   uint db_create_options, used_fields;
   enum db_type old_db_type,new_db_type;
+  bool need_copy_table;
   DBUG_ENTER("mysql_alter_table");
 
   thd->proc_info="init";
@@ -2633,7 +2637,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
     create_info->row_type=table->row_type;
 
   thd->proc_info="setup";
-  if (alter_info->is_simple && !table->tmp_table)
+  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
+      !table->tmp_table) // no need to touch frm
   {
     error=0;
     if (new_name != table_name || new_db != db)
@@ -2661,23 +2666,24 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
     {
       switch (alter_info->keys_onoff) {
       case LEAVE_AS_IS:
-	break;
+        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;
+        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;
+        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,
@@ -2708,7 +2714,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
 
   /* 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->min_rows;
   if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
@@ -2968,6 +2974,16 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
   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
+  */
+  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->tmp_table);
+  create_info->frm_only= !need_copy_table;
+
   /*
     Handling of symlinked tables:
     If no rename:
@@ -3022,45 +3038,49 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
                                   create_list,key_list,1,0)))
       DBUG_RETURN(error);
   }
-  if (table->tmp_table)
-  {
-    TABLE_LIST tbl;
-    bzero((void*) &tbl, sizeof(tbl));
-    tbl.db= new_db;
-    tbl.real_name= tbl.alias= tmp_name;
-    new_table= open_table(thd, &tbl, &thd->mem_root, 0);
-  }
-  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)
+  if (need_copy_table)
   {
-    VOID(quick_rm_table(new_db_type,new_db,tmp_name));
-    goto err;
+    if (table->tmp_table)
+    {
+      TABLE_LIST tbl;
+      bzero((void*) &tbl, sizeof(tbl));
+      tbl.db= new_db;
+      tbl.real_name= tbl.alias= tmp_name;
+      new_table= open_table(thd, &tbl, &thd->mem_root, 0);
+    }
+    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;
+    }
   }
 
-
   /*
     We don't want update TIMESTAMP fields during ALTER TABLE
     and copy_data_between_tables uses only write_row() for new_table so
     don't need to set up timestamp_on_update_now member.
   */
-  new_table->timestamp_default_now= 0;
-  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 loggin
+  next_insert_id=thd->next_insert_id;		// Remember for logging
   copied=deleted=0;
-  if (!new_table->is_view)
+  if (new_table && !new_table->is_view)
+  {
+    new_table->timestamp_default_now= 0;
+    new_table->next_number_field=new_table->found_next_number_field;
     error=copy_data_between_tables(table,new_table,create_list,
 				   handle_duplicates,
 				   order_num, order, &copied, &deleted);
+  }
   thd->last_insert_id=next_insert_id;		// Needed for correct log
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
@@ -3099,8 +3119,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
     goto end_temporary;
   }
 
-  intern_close_table(new_table);		/* close temporary table */
-  my_free((gptr) new_table,MYF(0));
+  if (new_table)
+  {
+    intern_close_table(new_table);              /* close temporary table */
+    my_free((gptr) new_table,MYF(0));
+  }
   VOID(pthread_mutex_lock(&LOCK_open));
   if (error)
   {
@@ -3112,7 +3135,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
   /*
     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 cash, free all locks, close the old table and remove it.
+    from the cache, free all locks, close the old table and remove it.
   */
 
   thd->proc_info="rename result table";
@@ -3151,6 +3174,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
 
 
   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;
@@ -3443,7 +3468,6 @@ int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
   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_DEFAULT;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d2964df008b0e8e0011d05df6bc3fd507bf78385..256ecf84dcb7e927192cdfe7f0ba078bf0cc325f 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2499,19 +2499,19 @@ create_table_options:
 	| create_table_option ',' create_table_options;
 
 create_table_option:
-	ENGINE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; }
-	| TYPE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); }
+	ENGINE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
+	| TYPE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine");   Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
 	| MAX_ROWS opt_equal ulonglong_num	{ Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
 	| MIN_ROWS opt_equal ulonglong_num	{ Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
 	| AVG_ROW_LENGTH opt_equal ULONG_NUM	{ Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
-	| PASSWORD opt_equal TEXT_STRING_sys	{ Lex->create_info.password=$3.str; }
-	| COMMENT_SYM opt_equal TEXT_STRING_sys	{ Lex->create_info.comment=$3.str; }
+	| PASSWORD opt_equal TEXT_STRING_sys	{ Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; }
+	| COMMENT_SYM opt_equal TEXT_STRING_sys	{ Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; }
 	| AUTO_INC opt_equal ulonglong_num	{ Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
 	| PACK_KEYS_SYM opt_equal ULONG_NUM	{ Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
 	| PACK_KEYS_SYM opt_equal DEFAULT	{ Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
-	| CHECKSUM_SYM opt_equal ULONG_NUM	{ Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; }
-	| DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; }
-	| ROW_FORMAT_SYM opt_equal row_types	{ Lex->create_info.row_type= $3; }
+	| CHECKSUM_SYM opt_equal ULONG_NUM	{ Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; }
+	| DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE;  Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; }
+	| ROW_FORMAT_SYM opt_equal row_types	{ Lex->create_info.row_type= $3;  Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT; }
 	| RAID_TYPE opt_equal raid_types	{ Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
 	| RAID_CHUNKS opt_equal ULONG_NUM	{ Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
 	| RAID_CHUNKSIZE opt_equal ULONG_NUM	{ Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
@@ -2533,9 +2533,9 @@ create_table_option:
 	| default_charset
 	| default_collation
 	| INSERT_METHOD opt_equal merge_insert_types   { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
-	| DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
-	  { Lex->create_info.data_file_name= $4.str; }
-	| INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; };
+	| DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.data_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR; }
+	| INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str;  Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR; }
+        ;
 
 default_charset:
         opt_default charset opt_equal charset_name_or_default
@@ -3173,8 +3173,7 @@ alter:
 	  lex->create_info.db_type= DB_TYPE_DEFAULT;
 	  lex->create_info.default_table_charset= NULL;
 	  lex->create_info.row_type= ROW_TYPE_NOT_USED;
-	  lex->alter_info.reset();          
-	  lex->alter_info.is_simple= 1;
+	  lex->alter_info.reset();
 	  lex->alter_info.flags= 0;
 	}
 	alter_list
@@ -3241,27 +3240,27 @@ alter_list:
 	| alter_list ',' alter_list_item;
 
 add_column:
-	ADD opt_column 
+	ADD opt_column
 	{
 	  LEX *lex=Lex;
-	  lex->change=0; 
-	  lex->alter_info.flags|= ALTER_ADD_COLUMN; 
+	  lex->change=0;
+	  lex->alter_info.flags|= ALTER_ADD_COLUMN;
 	};
 
 alter_list_item:
-	add_column column_def opt_place { Lex->alter_info.is_simple= 0; }
-	| ADD key_def 
-	  { 
-	    LEX *lex=Lex;
-	    lex->alter_info.is_simple= 0; 
-	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
+	add_column column_def opt_place { }
+	| ADD key_def
+	  {
+	    Lex->alter_info.flags|= ALTER_ADD_INDEX;
 	  }
-	| add_column '(' field_list ')'      { Lex->alter_info.is_simple= 0; }
+	| add_column '(' field_list ')'
+          {
+	    Lex->alter_info.flags|= ALTER_ADD_COLUMN | ALTER_ADD_INDEX;
+          }
 	| CHANGE opt_column field_ident
 	  {
 	     LEX *lex=Lex;
-	     lex->change= $3.str; 
-	     lex->alter_info.is_simple= 0;
+	     lex->change= $3.str;
 	     lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
 	  }
           field_spec opt_place
@@ -3272,7 +3271,6 @@ alter_list_item:
             lex->default_value= lex->on_update_value= 0;
 	    lex->comment=0;
 	    lex->charset= NULL;
-            lex->alter_info.is_simple= 0;
 	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
           }
           type opt_attribute
@@ -3292,17 +3290,18 @@ alter_list_item:
 	  {
 	    LEX *lex=Lex;
 	    lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
-	    			                               $3.str)); 
-	    lex->alter_info.is_simple= 0;
+                                                               $3.str));
 	    lex->alter_info.flags|= ALTER_DROP_COLUMN;
 	  }
-	| DROP FOREIGN KEY_SYM opt_ident { Lex->alter_info.is_simple= 0; }
+	| DROP FOREIGN KEY_SYM opt_ident
+          {
+	    Lex->alter_info.flags|= ALTER_DROP_INDEX;
+          }
 	| DROP PRIMARY_SYM KEY_SYM
 	  {
 	    LEX *lex=Lex;
 	    lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
 				               primary_key_name));
-	    lex->alter_info.is_simple= 0;
 	    lex->alter_info.flags|= ALTER_DROP_INDEX;
 	  }
 	| DROP key_or_index field_ident
@@ -3310,25 +3309,32 @@ alter_list_item:
 	    LEX *lex=Lex;
 	    lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
 					                       $3.str));
-	    lex->alter_info.is_simple= 0;
 	    lex->alter_info.flags|= ALTER_DROP_INDEX;
 	  }
-	| DISABLE_SYM KEYS { Lex->alter_info.keys_onoff= DISABLE; }
-	| ENABLE_SYM KEYS  { Lex->alter_info.keys_onoff= ENABLE; }
+	| DISABLE_SYM KEYS
+          {
+	    LEX *lex=Lex;
+            lex->alter_info.keys_onoff= DISABLE;
+	    lex->alter_info.flags|= ALTER_KEYS_ONOFF;
+          }
+	| ENABLE_SYM KEYS
+          {
+	    LEX *lex=Lex;
+            lex->alter_info.keys_onoff= ENABLE;
+	    lex->alter_info.flags|= ALTER_KEYS_ONOFF;
+          }
 	| ALTER opt_column field_ident SET DEFAULT signed_literal
 	  {
 	    LEX *lex=Lex;
 	    lex->alter_info.alter_list.push_back(new Alter_column($3.str,$6));
-	    lex->alter_info.is_simple= 0;
-	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
 	  }
 	| ALTER opt_column field_ident DROP DEFAULT
 	  {
 	    LEX *lex=Lex;
 	    lex->alter_info.alter_list.push_back(new Alter_column($3.str,
                                                                   (Item*) 0));
-	    lex->alter_info.is_simple= 0;
-	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
 	  }
 	| RENAME opt_to table_ident
 	  {
@@ -3358,22 +3364,20 @@ alter_list_item:
 	      YYABORT;
 	    }
 	    LEX *lex= Lex;
-	    lex->create_info.table_charset= 
+	    lex->create_info.table_charset=
 	      lex->create_info.default_table_charset= $5;
 	    lex->create_info.used_fields|= (HA_CREATE_USED_CHARSET |
 					    HA_CREATE_USED_DEFAULT_CHARSET);
-	    lex->alter_info.is_simple= 0;
+	    lex->alter_info.flags|= ALTER_CONVERT;
 	  }
-        | create_table_options_space_separated 
+        | create_table_options_space_separated
 	  {
 	    LEX *lex=Lex;
-	    lex->alter_info.is_simple= 0; 
 	    lex->alter_info.flags|= ALTER_OPTIONS;
 	  }
-	| order_clause         
+	| order_clause
 	  {
 	    LEX *lex=Lex;
-	    lex->alter_info.is_simple= 0; 
 	    lex->alter_info.flags|= ALTER_ORDER;
 	  };
 
@@ -3407,7 +3411,7 @@ opt_to:
 */
 
 slave:
-	  START_SYM SLAVE slave_thread_opts 
+	  START_SYM SLAVE slave_thread_opts
           {
 	    LEX *lex=Lex;
             lex->sql_command = SQLCOM_SLAVE_START;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 2a6abdb1cfd1678ef7112f0f29c35a0e0d70d27c..decac2a054931dd899bf97dfe8db1a6f6c8f84ed 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -199,7 +199,7 @@ err3:
     keys		number of keys to create
     key_info		Keys to create
     db_file		Handler to use. May be zero, in which case we use
-    			create_info->db_type
+                        create_info->db_type
   RETURN
     0  ok
     1  error
@@ -213,11 +213,11 @@ int rea_create_table(THD *thd, my_string file_name,
   DBUG_ENTER("rea_create_table");
 
   if (mysql_create_frm(thd, file_name, create_info,
-  		       create_fields, keys, key_info, NULL))
+                       create_fields, keys, key_info, NULL))
     DBUG_RETURN(1);
-  if (ha_create_table(file_name,create_info,0))
+  if (!create_info->frm_only && ha_create_table(file_name,create_info,0))
   {
-    my_delete(file_name,MYF(0));    
+    my_delete(file_name,MYF(0));
     DBUG_RETURN(1);
   }
   DBUG_RETURN(0);