List:Internals« Previous MessageNext Message »
From:antony Date:September 7 2005 3:58am
Subject:bk commit into 5.0 tree (acurtis:1.1971)
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.1971 05/09/07 02:58:26 acurtis@stripped +16 -0
  WL#2645
    CHECK TABLES ... FOR UPGRADE

  sql/table.h
    1.112 05/09/07 02:57:58 acurtis@stripped +1 -0
    WL2645
      Changes for upgrade

  sql/table.cc
    1.186 05/09/07 02:57:58 acurtis@stripped +13 -45
    WL2645
      Changes for upgrade

  sql/sql_yacc.yy
    1.418 05/09/07 02:57:57 acurtis@stripped +21 -14
    WL2645
      Changes for upgrade

  sql/sql_table.cc
    1.270 05/09/07 02:57:57 acurtis@stripped +177 -18
    WL2645
      Changes for upgrade

  sql/sql_base.cc
    1.297 05/09/07 02:57:57 acurtis@stripped +28 -2
    WL2645
      Changes for upgrade

  sql/share/errmsg.txt
    1.43 05/09/07 02:57:57 acurtis@stripped +2 -0
    WL2645
      New error message for upgrade

  sql/mysql_priv.h
    1.348 05/09/07 02:57:56 acurtis@stripped +1 -0
    WL2645
      new func mysql_alter_table_force()

  sql/lex.h
    1.142 05/09/07 02:57:56 acurtis@stripped +1 -0
    WL2645
      new token

  sql/handler.h
    1.151 05/09/07 02:57:56 acurtis@stripped +11 -2
    WL2645
      change for upgrade checks

  sql/handler.cc
    1.186 05/09/07 02:57:56 acurtis@stripped +136 -0
    WL2645
      implement for upgrade checks

  sql/ha_myisam.cc
    1.157 05/09/07 02:57:56 acurtis@stripped +5 -0
    WL2645
      ::check() needs to call super for upgrade

  sql/ha_innodb.cc
    1.255 05/09/07 02:57:56 acurtis@stripped +4 -0
    WL2645
      ::check() needs to call super for upgrade

  sql/ha_berkeley.cc
    1.156 05/09/07 02:57:55 acurtis@stripped +5 -1
    WL2645
      ::check() needs to call super for upgrade

  include/myisam.h
    1.68 05/09/07 02:57:55 acurtis@stripped +3 -0
    WL2645
      New flag for check

  include/my_base.h
    1.71 05/09/07 02:57:55 acurtis@stripped +3 -1
    WL2645
      New flags and storage engine errors

  client/mysqlcheck.c
    1.50 05/09/07 02:57:55 acurtis@stripped +19 -4
    WL2645
      --for-upgrade command line option

# 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.3

--- 1.70/include/my_base.h	2005-06-24 18:34:50 +01:00
+++ 1.71/include/my_base.h	2005-09-07 02:57:55 +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-09-07 02:57:55 +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-09-07 02:57:55 +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-09-07 02:57:56 +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-09-07 02:57:56 +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.150/sql/handler.h	2005-08-30 16:28:42 +01:00
+++ 1.151/sql/handler.h	2005-09-07 02:57:56 +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-09-07 02:57:56 +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.347/sql/mysql_priv.h	2005-09-06 10:34:02 +01:00
+++ 1.348/sql/mysql_priv.h	2005-09-07 02:57:56 +01:00
@@ -705,6 +705,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.296/sql/sql_base.cc	2005-09-02 15:06:09 +01:00
+++ 1.297/sql/sql_base.cc	2005-09-07 02:57:57 +01:00
@@ -1329,6 +1329,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);
 }
 
@@ -1731,7 +1738,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
@@ -1782,7 +1789,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.269/sql/sql_table.cc	2005-09-01 08:05:39 +01:00
+++ 1.270/sql/sql_table.cc	2005-09-07 02:57:57 +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
       {
@@ -2399,6 +2450,21 @@
         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)
@@ -2431,7 +2497,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));
 }
 
 
@@ -2441,19 +2507,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);
 }
 
 
@@ -2462,7 +2536,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));
 }
 
 
@@ -2498,7 +2572,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));
 }
 
 
@@ -2559,7 +2633,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));
 }
 
 
@@ -2747,7 +2821,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);
 }
 
 
@@ -2758,12 +2871,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);
 }
 
 
@@ -4034,6 +4157,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.417/sql/sql_yacc.yy	2005-09-06 18:42:42 +01:00
+++ 1.418/sql/sql_yacc.yy	2005-09-07 02:57:57 +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
@@ -2628,12 +2628,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; }
@@ -3235,13 +3235,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; }
@@ -3767,11 +3767,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; }
@@ -3809,11 +3810,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; }
@@ -6324,9 +6326,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; };
@@ -7702,6 +7708,7 @@
 	| UNDEFINED_SYM		{}
 	| UNKNOWN_SYM		{}
 	| UNTIL_SYM		{}
+	| UPGRADE_SYM		{}
 	| USER			{}
 	| USE_FRM		{}
 	| VARIABLES		{}

--- 1.185/sql/table.cc	2005-09-02 15:06:10 +01:00
+++ 1.186/sql/table.cc	2005-09-07 02:57:58 +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-09-01 20:42:22 +01:00
+++ 1.112/sql/table.h	2005-09-07 02:57:58 +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.42/sql/share/errmsg.txt	2005-09-03 00:25:41 +01:00
+++ 1.43/sql/share/errmsg.txt	2005-09-07 02:57:57 +01:00
@@ -5403,3 +5403,5 @@
         eng "The definition of table '%-.64s' prevents operation %s on table '%-.64s'."
 ER_PS_NO_RECURSION
         eng "The prepared statement contains a stored routine call that refers to that
same statement. It's not allowed to execute a prepared statement in such a recursive
manner"
+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-09-07 02:57:55 +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.254/sql/ha_innodb.cc	2005-09-04 23:12:53 +01:00
+++ 1.255/sql/ha_innodb.cc	2005-09-07 02:57:56 +01:00
@@ -5612,6 +5612,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.1971)antony7 Sep