List:Internals« Previous MessageNext Message »
From:antony Date:August 30 2005 8:34pm
Subject:bk commit into 5.0 tree (acurtis:1.1915)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of antony. When antony does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1915 05/08/30 21:34:06 acurtis@stripped +16 -0
  WL#2645
    CHECK ... FOR UPGRADE

  sql/table.h
    1.112 05/08/30 21:33:22 acurtis@stripped +1 -0
    wl2645 support for-upgrade

  sql/table.cc
    1.184 05/08/30 21:33:21 acurtis@stripped +13 -45
    wl2645 support for-upgrade

  sql/sql_yacc.yy
    1.416 05/08/30 21:33:21 acurtis@stripped +21 -14
    wl2645 support for-upgrade

  sql/sql_table.cc
    1.272 05/08/30 21:33:21 acurtis@stripped +177 -18
    wl2645 support for-upgrade

  sql/sql_base.cc
    1.294 05/08/30 21:33:20 acurtis@stripped +28 -2
    wl2645 support for-upgrade

  sql/share/errmsg.txt
    1.41 05/08/30 21:33:20 acurtis@stripped +2 -0
    wl2645 support for-upgrade

  sql/mysql_priv.h
    1.346 05/08/30 21:33:19 acurtis@stripped +1 -0
    wl2645 support for-upgrade

  sql/lex.h
    1.142 05/08/30 21:33:19 acurtis@stripped +1 -0
    wl2645 support for-upgrade

  sql/handler.h
    1.150 05/08/30 21:33:18 acurtis@stripped +11 -2
    wl2645 support for-upgrade

  sql/handler.cc
    1.186 05/08/30 21:33:18 acurtis@stripped +136 -0
    wl2645 support for-upgrade

  sql/ha_myisam.cc
    1.157 05/08/30 21:33:17 acurtis@stripped +5 -0
    wl2645 support for-upgrade

  sql/ha_innodb.cc
    1.250 05/08/30 21:33:17 acurtis@stripped +4 -0
    wl2645 support for-upgrade

  sql/ha_berkeley.cc
    1.156 05/08/30 21:33:17 acurtis@stripped +5 -1
    wl2645 support for-upgrade

  include/myisam.h
    1.68 05/08/30 21:33:17 acurtis@stripped +3 -0
    wl2645 support for-upgrade

  include/my_base.h
    1.71 05/08/30 21:33:17 acurtis@stripped +3 -1
    wl2645 support for-upgrade

  client/mysqlcheck.c
    1.50 05/08/30 21:33:16 acurtis@stripped +19 -4
    wl2645 support for-upgrade

# 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:	acurtis
# Host:	ltantony.xiphis.org
# Root:	/usr/home/antony/work2/wl2645.2

--- 1.70/include/my_base.h	2005-06-24 18:34:50 +01:00
+++ 1.71/include/my_base.h	2005-08-30 21:33:17 +01:00
@@ -51,6 +51,7 @@
 #define HA_OPEN_DELAY_KEY_WRITE		8	/* Don't update index  */
 #define HA_OPEN_ABORT_IF_CRASHED	16
 #define HA_OPEN_FOR_REPAIR		32	/* open even if crashed */
+#define HA_OPEN_FOR_UPGRADE		64	/* open even if old vers */
 
 	/* The following is parameter to ha_rkey() how to use key */
 
@@ -313,8 +314,9 @@
 #define HA_ERR_NO_CONNECTION     157  /* Could not connect to storage engine */
 #define HA_ERR_NULL_IN_SPATIAL   158  /* NULLs are not supported in spatial index */
 #define HA_ERR_TABLE_DEF_CHANGED 159  /* The table changed in storage engine */
+#define HA_ERR_TABLE_NEEDS_UPGRADE 160  /* The table changed in storage engine */
 
-#define HA_ERR_LAST              159  /*Copy last error nr.*/
+#define HA_ERR_LAST              160  /*Copy last error nr.*/
 /* Add error numbers before HA_ERR_LAST and change it accordingly. */
 #define HA_ERR_ERRORS            (HA_ERR_LAST - HA_ERR_FIRST + 1)
 

--- 1.67/include/myisam.h	2005-07-19 13:13:36 +01:00
+++ 1.68/include/myisam.h	2005-08-30 21:33:17 +01:00
@@ -365,6 +365,9 @@
 */
 
 #define TT_USEFRM               1
+#ifndef TT_FOR_UPGRADE
+#define TT_FOR_UPGRADE          2
+#endif
 
 #define O_NEW_INDEX	1		/* Bits set in out_flag */
 #define O_NEW_DATA	2

--- 1.155/sql/ha_berkeley.cc	2005-08-15 16:31:00 +01:00
+++ 1.156/sql/ha_berkeley.cc	2005-08-30 21:33:17 +01:00
@@ -2332,7 +2332,7 @@
 {
   DBUG_ENTER("ha_berkeley::check");
 
-  DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
+  DBUG_RETURN(handler::check(thd, check_opt));
 
 #ifdef NOT_YET
   char name_buff[FN_REFLEN];
@@ -2344,6 +2344,10 @@
     locking for this.
   */
 
+  if (check_opt->sql_flags & TT_FOR_UPGRADE)
+  {
+    DBUG_RETURN(handler::check(thd, check_opt));
+  }
   /* We must open the file again to be able to check it! */
   if ((error=db_create(&tmp_file, db_env, 0)))
   {

--- 1.156/sql/ha_myisam.cc	2005-07-20 17:02:25 +01:00
+++ 1.157/sql/ha_myisam.cc	2005-08-30 21:33:17 +01:00
@@ -317,6 +317,11 @@
   MYISAM_SHARE* share = file->s;
   const char *old_proc_info=thd->proc_info;
 
+  if (check_opt->sql_flags & TT_FOR_UPGRADE)
+  {
+    return(handler::check(thd, check_opt));
+  }
+
   thd->proc_info="Checking table";
   myisamchk_init(&param);
   param.thd = thd;

--- 1.185/sql/handler.cc	2005-08-25 07:37:10 +01:00
+++ 1.186/sql/handler.cc	2005-08-30 21:33:18 +01:00
@@ -318,6 +318,7 @@
   SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
   SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
   SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
+  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
 
   /* Register the error messages for use with my_error(). */
   return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@@ -1703,6 +1704,9 @@
   case HA_ERR_TABLE_DEF_CHANGED:
     textno=ER_TABLE_DEF_CHANGED;
     break;
+  case HA_ERR_TABLE_NEEDS_UPGRADE:
+    textno=ER_TABLE_NEEDS_UPGRADE;
+    break;
   case HA_ERR_NO_SUCH_TABLE:
   {
     /*
@@ -1769,6 +1773,138 @@
       error == HA_ERR_NULL_IN_SPATIAL)
     info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
   DBUG_RETURN(table->file->errkey);
+}
+
+
+/*
+  Perform compatibility checks involving DECIMAL
+*/
+static bool upgrade_check_bad_decimal(TABLE *table)
+{
+  bool needs_upgrade= 0;
+  if (table && table->s)
+  {
+    Field** field;
+    KEY *keyinfo;
+    KEY_PART_INFO *keypart;
+    uint i,j;
+
+    for (field= table->field, i=0; 
+         i < table->s->fields && !needs_upgrade;
+         i++,field++)
+    {
+      if ((*field)->type() == FIELD_TYPE_NEWDECIMAL && 
+          table->s->mysql_version == 0)
+      {
+        Field_new_decimal *fld= (Field_new_decimal *)(*field);
+        needs_upgrade= 1;
+        /*
+          Fix pack length of old decimal values from 5.0.3 -> 5.0.4
+          The difference is that in the old version we stored precision
+          in the .frm table while we now store the display_length
+        */
+        fld->field_length= my_decimal_precision_to_length(fld->field_length,
+                                                fld->dec, fld->unsigned_flag);
+        fld->precision= my_decimal_length_to_precision(fld->field_length,
+                                                fld->dec, fld->unsigned_flag);
+        fld->bin_size= my_decimal_get_binary_size(fld->precision, fld->dec);
+      }
+    }
+    
+    keyinfo= table->key_info;
+    for (i=0; i < table->s->keys; i++, keyinfo++)
+    {
+      keypart= keyinfo->key_part;
+      for (j=0 ; j < keyinfo->key_parts ; j++, keypart++)
+      {
+        if (!keypart->fieldnr)
+          continue;
+        Field *fld= table->field[keypart->fieldnr-1];
+        if (fld->type() == FIELD_TYPE_NEWDECIMAL &&
+            fld->key_length() != keypart->length)
+        {
+          needs_upgrade= 1;
+          /*
+            Fix a fatal error in decimal key handling that causes crashes
+            on Innodb. We fix it by reducing the key length so that
+            InnoDB never gets a too big key when searching.
+            This allows the end user to do an ALTER TABLE to fix the
+            error.
+          */
+	  keyinfo->key_length-= (keypart->length - fld->key_length());
+	  keypart->store_length-= (keypart->length - fld->key_length());
+          keypart->length= fld->key_length();
+          keypart->key_part_flag&= ~HA_PART_KEY_SEG;
+          keypart->field= fld;
+        }
+      }
+    }    
+  }
+  return needs_upgrade;
+}
+
+
+/*
+  Performs checks upon the table. 
+
+  SYNOPSIS
+    check()
+    thd			thread doing CHECK TABLE operation
+    check_opt		options from the parser
+
+  NOTES
+    Subclasses which override ::check() should call the
+    superclass implementation instead of returning 
+    HA_ADMIN_OK or HA_ADMIN_NOT_IMPLEMENTED
+
+  RETURN
+    HA_ADMIN_OK                 Successful upgrade
+    HA_ADMIN_NEEDS_UPGRADE      Table has structures requiring upgrade
+    HA_ADMIN_NOT_IMPLEMENTED    
+*/
+int handler::check(THD* thd, HA_CHECK_OPT* check_opt)
+{
+  if (check_opt->sql_flags & TT_FOR_UPGRADE)
+  {
+    bool need_upgrade= 0;
+    
+    if (upgrade_check_bad_decimal(table))
+      need_upgrade= 1;
+    
+    return need_upgrade || table->s->needs_upgrade 
+        ? HA_ADMIN_NEEDS_UPGRADE : HA_ADMIN_OK;
+  }
+  return HA_ADMIN_NOT_IMPLEMENTED;
+}
+
+
+/*
+  Performs upgrade of table. 
+
+  SYNOPSIS
+    upgrade()
+    thd			thread doing REPAIR TABLE operation
+    check_opt		options from the parser
+
+  NOTES
+    Subclasses which override ::upgrade() should call the
+    superclass implementation instead of returning HA_ADMIN_OK
+
+  RETURN
+    HA_ADMIN_OK                 Successful upgrade
+    HA_ADMIN_ALREADY_DONE       Already done, nothing to do
+    HA_ADMIN_TRY_ALTER_FORCE    ALTER TABLE xxx FORCE is required
+*/
+int handler::upgrade(THD *thd, HA_CHECK_OPT* check_opt)
+{
+  bool needs_alter_force= 0;
+  if (table && table->s->mysql_version >= MYSQL_VERSION_ID)
+    return HA_ADMIN_ALREADY_DONE;
+
+  if (upgrade_check_bad_decimal(table))
+    needs_alter_force= 1;
+
+  return needs_alter_force ? HA_ADMIN_TRY_ALTER_FORCE : HA_ADMIN_OK;
 }
 
 

--- 1.149/sql/handler.h	2005-08-30 10:39:17 +01:00
+++ 1.150/sql/handler.h	2005-08-30 21:33:18 +01:00
@@ -45,6 +45,8 @@
 #define HA_ADMIN_REJECT          -6
 #define HA_ADMIN_TRY_ALTER       -7
 #define HA_ADMIN_WRONG_CHECKSUM  -8
+#define HA_ADMIN_NEEDS_UPGRADE   -9
+#define HA_ADMIN_TRY_ALTER_FORCE -10
 
 /* Bits in table_flags() to show what database can do */
 
@@ -417,6 +419,10 @@
 /* Forward declaration for condition pushdown to storage engine */
 typedef class Item COND;
 
+#ifndef TT_FOR_UPGRADE
+#define TT_FOR_UPGRADE          2
+#endif
+
 typedef struct st_ha_check_opt
 {
   ulong sort_buffer_size;
@@ -663,8 +669,8 @@
   virtual void update_create_info(HA_CREATE_INFO *create_info) {}
 
   /* admin commands - called from mysql_admin_table */
-  virtual int check(THD* thd, HA_CHECK_OPT* check_opt)
-  { return HA_ADMIN_NOT_IMPLEMENTED; }
+  virtual int check(THD* thd, HA_CHECK_OPT* check_opt);
+  virtual int upgrade(THD* thd, HA_CHECK_OPT* check_opt);
   virtual int backup(THD* thd, HA_CHECK_OPT* check_opt)
   { return HA_ADMIN_NOT_IMPLEMENTED; }
   /*
@@ -686,6 +692,7 @@
   /* end of the list of admin commands */
 
   virtual bool check_and_repair(THD *thd) { return HA_ERR_WRONG_COMMAND; }
+  virtual bool check_and_upgrade(THD *thd) { return HA_ERR_WRONG_COMMAND; }
   virtual int dump(THD* thd, int fd = -1) { return HA_ERR_WRONG_COMMAND; }
   virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
   virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
@@ -743,6 +750,8 @@
   virtual uint checksum() const { return 0; }
   virtual bool is_crashed() const  { return 0; }
   virtual bool auto_repair() const { return 0; }
+  virtual bool auto_upgrade() const { return 0; }
+  virtual bool needs_upgrade() const  { return 0; }
 
   /*
     default rename_table() and delete_table() rename/delete files with a

--- 1.141/sql/lex.h	2005-08-25 14:39:00 +01:00
+++ 1.142/sql/lex.h	2005-08-30 21:33:19 +01:00
@@ -513,6 +513,7 @@
   { "UNSIGNED",		SYM(UNSIGNED)},
   { "UNTIL",		SYM(UNTIL_SYM)},
   { "UPDATE",		SYM(UPDATE_SYM)},
+  { "UPGRADE",		SYM(UPGRADE_SYM)},
   { "USAGE",		SYM(USAGE)},
   { "USE",		SYM(USE_SYM)},
   { "USER",		SYM(USER)},

--- 1.345/sql/mysql_priv.h	2005-08-30 10:39:17 +01:00
+++ 1.346/sql/mysql_priv.h	2005-08-30 21:33:19 +01:00
@@ -706,6 +706,7 @@
                        bool ignore,
                        ALTER_INFO *alter_info, bool do_send_ok);
 bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
+bool mysql_alter_table_force(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
 bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
                              HA_CREATE_INFO *create_info,
                              Table_ident *src_table);

--- 1.293/sql/sql_base.cc	2005-08-24 22:22:52 +01:00
+++ 1.294/sql/sql_base.cc	2005-08-30 21:33:20 +01:00
@@ -1275,6 +1275,13 @@
     table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
   table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
   DBUG_ASSERT(table->key_read == 0);
+  if (table->s->needs_upgrade)
+  {
+    sql_print_error(ER(ER_TABLE_NEEDS_UPGRADE), table->s->table_name);
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                        ER_TABLE_NEEDS_UPGRADE,
+                        ER(ER_TABLE_NEEDS_UPGRADE), table->s->table_name);
+  }
   DBUG_RETURN(table);
 }
 
@@ -1677,7 +1684,7 @@
                      thd->open_options, entry, table_desc, mem_root))))
 
   {
-    if (!entry->s || !entry->s->crashed)
+    if (!entry->s || !(entry->s->crashed || entry->s->needs_upgrade))
     {
       /*
         Frm file could not be found on disk
@@ -1728,7 +1735,26 @@
     pthread_mutex_unlock(&LOCK_open);
     thd->clear_error();				// Clear error message
     error= 0;
-    if (openfrm(thd, path, alias,
+    if (entry->s->needs_upgrade && 
+        openfrm(thd, path, alias,
+		(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
+			 HA_TRY_READ_ONLY),
+		READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
+		ha_open_options | HA_OPEN_FOR_UPGRADE,
+		entry) || ! entry->file ||
+	(entry->file->needs_upgrade() && entry->file->check_and_upgrade(thd)))
+    {
+      /* Give right error message */
+      thd->clear_error();
+      my_error(ER_NOT_KEYFILE, MYF(0), name, my_errno);
+      sql_print_error("Couldn't upgrade table: %s.%s",db,name);
+      if (entry->file)
+	closefrm(entry);
+      error=1;
+    }
+    else
+    if (!entry->s->needs_upgrade &&
+        openfrm(thd, path, alias,
 		(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
 			 HA_TRY_READ_ONLY),
 		READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,

--- 1.271/sql/sql_table.cc	2005-08-30 07:18:12 +01:00
+++ 1.272/sql/sql_table.cc	2005-08-30 21:33:21 +01:00
@@ -43,6 +43,8 @@
 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);                             
+static int post_upgrade_check(THD *thd, TABLE_LIST *tables,
+                              HA_CHECK_OPT *check_opt);
 
 
 /*
@@ -2108,7 +2110,9 @@
                                                   HA_CHECK_OPT *),
                               int (handler::*operator_func)(THD *,
                                                             HA_CHECK_OPT *),
-                              int (view_operator_func)(THD *, TABLE_LIST*))
+                              int (view_operator_func)(THD *, TABLE_LIST*),
+                              int (*post_func)(THD *, TABLE_LIST *,
+                                               HA_CHECK_OPT *))
 {
   TABLE_LIST *table, *save_next_global, *save_next_local;
   SELECT_LEX *select= &thd->lex->select_lex;
@@ -2386,6 +2390,53 @@
                       system_charset_info);
       break;
     }
+    case HA_ADMIN_NEEDS_UPGRADE:
+      protocol->store("error", 5, system_charset_info);
+      protocol->store("Table upgrade required",22, system_charset_info);
+      fatal_error=1;
+      break;
+    case HA_ADMIN_TRY_ALTER_FORCE:
+    {
+      /*
+        This is used when handler::upgrade() answers
+        "try with alter force", so here we close the table, 
+        then do an ALTER TABLE FORCE,
+      */
+      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;
+      tmp_disable_binlog(thd); // binlogging is done by caller if wanted
+      result_code= mysql_alter_table_force(thd, table, 0);
+      reenable_binlog(thd);
+      if (result_code) // either mysql_alter_table_force failed
+      {
+        const char *err_msg;
+        if ((err_msg= thd->net.last_error))
+        {
+          if (!thd->vio_ok())
+          {
+            sql_print_error(err_msg);
+          }
+          else
+          {
+            /* Hijack the row already in-progress. */
+            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 */
+            protocol->prepare_for_resend();
+            protocol->store(table_name, system_charset_info);
+            protocol->store(operator_name, system_charset_info);
+          }
+        }
+      }
+      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
+      table->next_local= save_next_local;
+      table->next_global= save_next_global;
+      goto send_result_message;
+    }
+
 
     default:				// Probably HA_ADMIN_INTERNAL_ERROR
       protocol->store("error", 5, system_charset_info);
@@ -2394,6 +2445,21 @@
       fatal_error=1;
       break;
     }
+
+    if (post_func && result_code == HA_ADMIN_OK)
+    {
+      switch (post_func(thd, table, check_opt))
+      {
+      case  1:           // error, message written to net
+        close_thread_tables(thd);
+        continue;
+      case -1:           // error, message could be written to net
+        goto err;
+      default:           // should be 0 otherwise
+        ;
+      }
+    }
+
     if (fatal_error)
       table->table->s->version=0;               // Force close of table
     else if (open_for_modify)
@@ -2426,7 +2492,7 @@
   DBUG_ENTER("mysql_backup_table");
   DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
 				"backup", TL_READ, 0, 0, 0, 0,
-				&handler::backup, 0));
+				&handler::backup, 0, 0));
 }
 
 
@@ -2436,19 +2502,27 @@
   DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
 				"restore", TL_WRITE, 1, 1, 0,
 				&prepare_for_restore,
-				&handler::restore, 0));
+				&handler::restore, 0, 0));
 }
 
 
 bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 {
+  bool result;
   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,
-				&prepare_for_repair,
-				&handler::repair, 0));
+  
+  if (test(check_opt->sql_flags & TT_FOR_UPGRADE))
+    result= mysql_admin_table(thd, tables, check_opt,
+			      "upgrade", TL_WRITE, 1, 0,
+                              HA_OPEN_FOR_UPGRADE, 0,
+			      &handler::upgrade, 0, &post_upgrade_check);
+  else
+    result= mysql_admin_table(thd, tables, check_opt,
+			      "repair", TL_WRITE, 1,
+                              test(check_opt->sql_flags & TT_USEFRM),
+                              HA_OPEN_FOR_REPAIR, &prepare_for_repair,
+		              &handler::repair, 0, 0);
+  DBUG_RETURN(result);
 }
 
 
@@ -2457,7 +2531,7 @@
   DBUG_ENTER("mysql_optimize_table");
   DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 				"optimize", TL_WRITE, 1,0,0,0,
-				&handler::optimize, 0));
+				&handler::optimize, 0, 0));
 }
 
 
@@ -2493,7 +2567,7 @@
   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));
+				0, 0, &handler::assign_to_keycache, 0, 0));
 }
 
 
@@ -2554,7 +2628,7 @@
   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));
+				&handler::preload_keys, 0, 0));
 }
 
 
@@ -2742,7 +2816,46 @@
   DBUG_ENTER("mysql_analyze_table");
   DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 				"analyze", lock_type, 1, 0, 0, 0,
-				&handler::analyze, 0));
+				&handler::analyze, 0, 0));
+}
+
+
+/*
+  If the upgrade checks do not signal any error, this function
+  is called and will silently update the frm mysql version.
+*/
+static int post_upgrade_check(THD *thd, TABLE_LIST *tables,
+                              HA_CHECK_OPT *check_opt)
+{
+  TABLE *table= tables->table;
+  Protocol *protocol= thd->protocol;
+  int error= 0;
+  if (table && table->s->mysql_version != MYSQL_VERSION_ID)
+  {
+    char path[IO_SIZE];
+    pthread_mutex_lock(&LOCK_open);
+    if (build_table_path(path, sizeof(path), tables->db,
+                         (lower_case_table_names == 2) ?
+                         tables->alias : tables->table_name,
+                         reg_ext) != 0)
+    {
+      File file;
+      uchar fileinfo[64];
+      if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
+      {
+        uint tmp= MYSQL_VERSION_ID;
+        if (!my_pread(file,(byte*) fileinfo,64,0L,MYF(MY_NABP)))
+        { 
+          int4store(fileinfo+51, tmp);
+          if (!my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW))
+            table->s->mysql_version= MYSQL_VERSION_ID;
+        }
+        VOID(my_close(file,MYF(MY_WME)));
+      }
+    }
+    pthread_mutex_unlock(&LOCK_open);
+  }
+  return(error);
 }
 
 
@@ -2753,12 +2866,22 @@
 #else
   thr_lock_type lock_type = TL_READ_NO_INSERT;
 #endif
-
+  bool result;
   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::check, &view_checksum));
+  
+  if (test(check_opt->sql_flags & TT_FOR_UPGRADE))
+    result= mysql_admin_table(thd, tables, check_opt,
+			      "check", lock_type,
+			      0, HA_OPEN_FOR_UPGRADE, 0, 0,
+			      &handler::check,
+                              0, &post_upgrade_check);
+  else
+    result= mysql_admin_table(thd, tables, check_opt,
+			      "check", lock_type,
+			      0, HA_OPEN_FOR_REPAIR, 0, 0,
+			      &handler::check,
+                              &view_checksum, 0);
+  DBUG_RETURN(result);
 }
 
 
@@ -4029,6 +4152,42 @@
                                 table_list, lex->create_list,
                                 lex->key_list, 0, (ORDER *) 0,
                                 DUP_ERROR, 0, &lex->alter_info, do_send_ok));
+}
+
+
+/*
+  Simulates an invocation of "ALTER TABLE xxx FORCE"
+  by calling mysql_alter_table().
+
+  SYNOPSIS
+    mysql_alter_table_force()
+    thd			Thread handler
+    tables		Tables to recreate
+    do_send_ok          If we should send_ok() or leave it to caller
+
+ RETURN
+    Like mysql_alter_table().
+*/
+bool mysql_alter_table_force(THD *thd, TABLE_LIST *table_list,
+                             bool do_send_ok)
+{
+  HA_CREATE_INFO create_info;
+  ALTER_INFO alter_info;
+  List<create_field> fld_list;
+  List<Key> key_list;
+  DBUG_ENTER("mysql_recreate_table");
+
+  bzero((char*) &create_info,sizeof(create_info));
+  create_info.db_type= DB_TYPE_DEFAULT;
+  create_info.default_table_charset= NULL;
+  create_info.row_type= ROW_TYPE_NOT_USED;
+  alter_info.reset();
+  alter_info.flags= ALTER_FORCE;
+   
+  DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
+                                table_list, fld_list,
+                                key_list, 0, (ORDER *)0, 
+                                DUP_ERROR, 0, &alter_info, do_send_ok));
 }
 
 

--- 1.415/sql/sql_yacc.yy	2005-08-29 20:10:49 +01:00
+++ 1.416/sql/sql_yacc.yy	2005-08-30 21:33:21 +01:00
@@ -626,7 +626,7 @@
 %token  UNTIL_SYM
 %token  UNTIL_SYM
 %token  UPDATE_SYM
-%token  UPDATE_SYM
+%token  UPGRADE_SYM
 %token  USAGE
 %token  USER
 %token  USE_FRM
@@ -699,7 +699,7 @@
 	type int_type real_type order_dir lock_option
 	udf_type if_exists opt_local opt_table_options table_options
         table_option opt_if_not_exists opt_no_write_to_binlog
-        delete_option opt_temporary all_or_any opt_distinct
+        on_delete_option opt_temporary all_or_any opt_distinct
         opt_ignore_leaves fulltext_options spatial_type union_option
         start_transaction_opts opt_chain opt_release
         union_opt select_derived_init option_type2
@@ -808,8 +808,8 @@
 	grant revoke set lock unlock string_list field_options field_option
 	field_opt_list opt_binary table_lock_list table_lock
 	ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use
-	opt_delete_options opt_delete_option varchar nchar nvarchar
-	opt_outer table_list table_name opt_option opt_place
+	opt_delete_options delete_options_list delete_option varchar nchar
+	nvarchar opt_outer table_list table_name opt_option opt_place
 	opt_attribute opt_attribute_list attribute column_list column_list_id
 	opt_column_list grant_privileges grant_ident grant_list grant_option
 	object_privilege object_privilege_list user_list rename_list
@@ -2653,12 +2653,12 @@
 
 create_table_options_space_separated:
 	create_table_option
-	| create_table_option create_table_options_space_separated;
+	| create_table_options_space_separated create_table_option;
 
 create_table_options:
 	create_table_option
-	| create_table_option     create_table_options
-	| create_table_option ',' create_table_options;
+	| create_table_options     create_table_option
+	| create_table_options ',' create_table_option;
 
 create_table_option:
 	ENGINE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
@@ -3260,13 +3260,13 @@
 	| opt_on_delete_item {};
 
 opt_on_delete_item:
-	ON DELETE_SYM delete_option   { Lex->fk_delete_opt= $3; }
-	| ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; }
+	ON DELETE_SYM on_delete_option   { Lex->fk_delete_opt= $3; }
+	| ON UPDATE_SYM on_delete_option { Lex->fk_update_opt= $3; }
 	| MATCH FULL	{ Lex->fk_match_option= foreign_key::FK_MATCH_FULL; }
 	| MATCH PARTIAL { Lex->fk_match_option= foreign_key::FK_MATCH_PARTIAL; }
 	| MATCH SIMPLE_SYM { Lex->fk_match_option= foreign_key::FK_MATCH_SIMPLE; };
 
-delete_option:
+on_delete_option:
 	RESTRICT	 { $$= (int) foreign_key::FK_OPTION_RESTRICT; }
 	| CASCADE	 { $$= (int) foreign_key::FK_OPTION_CASCADE; }
 	| SET NULL_SYM   { $$= (int) foreign_key::FK_OPTION_SET_NULL; }
@@ -3792,11 +3792,12 @@
 
 opt_mi_repair_type:
 	/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
+        | UPGRADE_SYM { Lex->check_opt.sql_flags= TT_FOR_UPGRADE; }
 	| mi_repair_types {};
 
 mi_repair_types:
 	mi_repair_type {}
-	| mi_repair_type mi_repair_types {};
+	| mi_repair_types mi_repair_type {};
 
 mi_repair_type:
 	QUICK          { Lex->check_opt.flags|= T_QUICK; }
@@ -3834,11 +3835,12 @@
 
 opt_mi_check_type:
 	/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
+        | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags |= TT_FOR_UPGRADE; }
 	| mi_check_types {};
 
 mi_check_types:
 	mi_check_type {}
-	| mi_check_type mi_check_types {};
+	| mi_check_types mi_check_type {};
 
 mi_check_type:
 	QUICK      { Lex->check_opt.flags|= T_QUICK; }
@@ -6344,9 +6346,13 @@
 
 opt_delete_options:
 	/* empty */	{}
-	| opt_delete_option opt_delete_options {};
+	| delete_options_list {};
+
+delete_options_list:
+	delete_option	{}
+	| delete_options_list delete_option {};
 
-opt_delete_option:
+delete_option:
 	QUICK		{ Select->options|= OPTION_QUICK; }
 	| LOW_PRIORITY	{ Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
 	| IGNORE_SYM	{ Lex->ignore= 1; };
@@ -7722,6 +7728,7 @@
 	| UNDEFINED_SYM		{}
 	| UNKNOWN_SYM		{}
 	| UNTIL_SYM		{}
+	| UPGRADE_SYM		{}
 	| USER			{}
 	| USE_FRM		{}
 	| VARIABLES		{}

--- 1.183/sql/table.cc	2005-08-23 16:15:46 +01:00
+++ 1.184/sql/table.cc	2005-08-30 21:33:21 +01:00
@@ -554,26 +554,6 @@
       unhex_type2(interval);
     }
     
-#ifndef TO_BE_DELETED_ON_PRODUCTION
-    if (field_type == FIELD_TYPE_NEWDECIMAL && !share->mysql_version)
-    {
-      /*
-        Fix pack length of old decimal values from 5.0.3 -> 5.0.4
-        The difference is that in the old version we stored precision
-        in the .frm table while we now store the display_length
-      */
-      uint decimals= f_decimals(pack_flag);
-      field_length= my_decimal_precision_to_length(field_length,
-                                                   decimals,
-                                                   f_is_dec(pack_flag) == 0);
-      sql_print_error("Found incompatible DECIMAL field '%s' in %s; Please do \"ALTER TABLE '%s' FORCE\" to fix it!", share->fieldnames.type_names[i], name, share->table_name);
-      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                          ER_CRASHED_ON_USAGE,
-                          "Found incompatible DECIMAL field '%s' in %s; Please do \"ALTER TABLE '%s' FORCE\" to fix it!", share->fieldnames.type_names[i], name, share->table_name);
-      share->crashed= 1;                        // Marker for CHECK TABLE
-    }
-#endif
-
     *field_ptr=reg_field=
       make_field(record+recpos,
 		 (uint32) field_length,
@@ -734,29 +714,6 @@
 	  }
 	  if (field->key_length() != key_part->length)
 	  {
-#ifndef TO_BE_DELETED_ON_PRODUCTION
-            if (field->type() == FIELD_TYPE_NEWDECIMAL)
-            {
-              /*
-                Fix a fatal error in decimal key handling that causes crashes
-                on Innodb. We fix it by reducing the key length so that
-                InnoDB never gets a too big key when searching.
-                This allows the end user to do an ALTER TABLE to fix the
-                error.
-              */
-	      keyinfo->key_length-= (key_part->length - field->key_length());
-	      key_part->store_length-= (uint16)(key_part->length -
-                                                field->key_length());
-              key_part->length= (uint16)field->key_length();
-              sql_print_error("Found wrong key definition in %s; Please do \"ALTER TABLE '%s' FORCE \" to fix it!", name, share->table_name);
-              push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                                  ER_CRASHED_ON_USAGE,
-                                  "Found wrong key definition in %s; Please do \"ALTER TABLE '%s' FORCE\" to fix it!", name, share->table_name);
-
-              share->crashed= 1;                // Marker for CHECK TABLE
-	      goto to_be_deleted;
-            }
-#endif
 	    key_part->key_part_flag|= HA_PART_KEY_SEG;
 	    if (!(field->flags & BLOB_FLAG))
 	    {					// Create a new field
@@ -766,8 +723,6 @@
 	    }
 	  }
 
-	to_be_deleted:
-
 	  /*
 	    If the field can be NULL, don't optimize away the test
 	    key_part_column = expression from the WHERE clause
@@ -876,6 +831,11 @@
       share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
                        outparam->file->auto_repair() &&
                        !(ha_open_flags & HA_OPEN_FOR_REPAIR));
+      /* Set a flag if the table needs upgrade and it can be auto. upgraded */
+      share->needs_upgrade=
+                      ((ha_err == HA_ERR_TABLE_NEEDS_UPGRADE) &&
+                       outparam->file->auto_upgrade() &&
+                       !(ha_open_flags & HA_OPEN_FOR_UPGRADE));
 
       if (ha_err == HA_ERR_NO_SUCH_TABLE)
       {
@@ -894,6 +854,14 @@
   }
   share->db_low_byte_first= outparam->file->low_byte_first();
 
+  if (share->mysql_version != MYSQL_VERSION_ID)
+  {
+    HA_CHECK_OPT check_opt;
+    bzero(&check_opt, sizeof(check_opt));
+    check_opt.sql_flags= TT_FOR_UPGRADE;
+    if (outparam->file->check(thd, &check_opt) == HA_ADMIN_NEEDS_UPGRADE)
+      share->needs_upgrade= TRUE;
+  }
   *root_ptr= old_root;
   thd->status_var.opened_tables++;
 #ifndef DBUG_OFF

--- 1.111/sql/table.h	2005-08-26 10:24:52 +01:00
+++ 1.112/sql/table.h	2005-08-30 21:33:22 +01:00
@@ -165,6 +165,7 @@
   my_bool crypted;                      /* If .frm file is crypted */
   my_bool db_low_byte_first;		/* Portable row format */
   my_bool crashed;
+  my_bool needs_upgrade;                /* Set if table data fmt is old */
   my_bool is_view;
   my_bool name_lock, replace_with_name_lock;
   /*

--- 1.40/sql/share/errmsg.txt	2005-08-23 06:15:00 +01:00
+++ 1.41/sql/share/errmsg.txt	2005-08-30 21:33:20 +01:00
@@ -5399,3 +5399,5 @@
         eng "Datetime function: %-.32s field overflow"
 ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
         eng "Can't update table '%-.64s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger."
+ER_TABLE_NEEDS_UPGRADE
+	eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s` UPGRADE\" to fix it!"

--- 1.49/client/mysqlcheck.c	2005-08-26 13:45:18 +01:00
+++ 1.50/client/mysqlcheck.c	2005-08-30 21:33:16 +01:00
@@ -34,7 +34,7 @@
                opt_compress = 0, opt_databases = 0, opt_fast = 0,
                opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
                opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
-               tty_password = 0, opt_frm = 0;
+               tty_password = 0, opt_frm = 0, opt_upgrade = 0;
 static uint verbose = 0, opt_mysql_port=0;
 static my_string opt_mysql_unix_port = 0;
 static char *opt_password = 0, *current_user = 0, 
@@ -98,6 +98,9 @@
   {"fast",'F', "Check only tables that haven't been closed properly.",
    (gptr*) &opt_fast, (gptr*) &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
    0},
+  {"for-upgrade", 'U',
+   "Check the table for version dependent changes. May be used with auto-repair to correct tables requiring version dependent updates.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"force", 'f', "Continue even if we get an sql-error.",
    (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
    0, 0, 0, 0},
@@ -233,12 +236,14 @@
   case 'a':
     what_to_do = DO_ANALYZE;
     break;
+  case 'C':
+    opt_check_only_changed = 1;
   case 'c':
     what_to_do = DO_CHECK;
     break;
-  case 'C':
+  case 'U':
     what_to_do = DO_CHECK;
-    opt_check_only_changed = 1;
+    opt_upgrade = 1;
     break;
   case 'I': /* Fall through */
   case '?':
@@ -517,6 +522,11 @@
   switch (what_to_do) {
   case DO_CHECK:
     op = "CHECK";
+    if (opt_upgrade)
+    {
+      end = strmov(end, " FOR UPGRADE");
+      break;
+    }
     if (opt_quick)              end = strmov(end, " QUICK");
     if (opt_fast)               end = strmov(end, " FAST");
     if (opt_medium_check)       end = strmov(end, " MEDIUM"); /* Default */
@@ -525,6 +535,11 @@
     break;
   case DO_REPAIR:
     op = "REPAIR";
+    if (opt_upgrade)
+    {
+      end = strmov(end, " UPGRADE");
+      break;
+    }
     if (opt_quick)              end = strmov(end, " QUICK");
     if (opt_extended)           end = strmov(end, " EXTENDED");
     if (opt_frm)                end = strmov(end, " USE_FRM");
@@ -712,7 +727,7 @@
     uint i;
 
     if (!opt_silent && tables4repair.elements)
-      puts("\nRepairing tables");
+      puts(opt_upgrade ? "\nUpgrading tables" :"\nRepairing tables");
     what_to_do = DO_REPAIR;
     for (i = 0; i < tables4repair.elements ; i++)
     {

--- 1.249/sql/ha_innodb.cc	2005-08-30 10:39:17 +01:00
+++ 1.250/sql/ha_innodb.cc	2005-08-30 21:33:17 +01:00
@@ -5588,6 +5588,10 @@
 	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 	ulint		ret;
 
+        if (check_opt->sql_flags & TT_FOR_UPGRADE)
+        {
+                return(handler::check(thd, check_opt));
+        }
 	ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
 	ut_a(prebuilt->trx ==
                 (trx_t*) current_thd->ha_data[innobase_hton.slot]);
Thread
bk commit into 5.0 tree (acurtis:1.1915)antony30 Aug