List:Internals« Previous MessageNext Message »
From:mikael Date:September 16 2005 6:41am
Subject:bk commit into 5.1 tree (mronstrom:1.2015)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mikron. When mikron 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.2015 05/09/16 08:40:53 mronstrom@stripped +7 -0
  WL 2604: Partition Management
  Changed interfaces, moved some code, some error handlings

  sql/sql_table.cc
    1.235 05/09/16 08:40:42 mronstrom@stripped +15 -8
    Mutex around writing of frm file

  sql/sql_partition.cc
    1.8 05/09/16 08:40:42 mronstrom@stripped +145 -23
    Changed interface
    Moved ndb specific functions into public domain

  sql/mysql_priv.h
    1.304 05/09/16 08:40:42 mronstrom@stripped +4 -0
    Made public

  sql/handler.h
    1.147 05/09/16 08:40:42 mronstrom@stripped +24 -25
    Changed interface

  sql/ha_partition.h
    1.4 05/09/16 08:40:42 mronstrom@stripped +7 -2
    Changed interface

  sql/ha_partition.cc
    1.5 05/09/16 08:40:42 mronstrom@stripped +35 -12
    Some error handlings

  sql/ha_ndbcluster.cc
    1.153 05/09/16 08:40:41 mronstrom@stripped +10 -110
    Moved packfrm to "public" place
    Fixed compiler issue

# 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:	mronstrom
# Host:	c-dc0ae253.1238-1-64736c10.cust.bredbandsbolaget.se
# Root:	/Users/mikron/wl2498

--- 1.146/sql/handler.h	2005-09-15 18:53:38 +02:00
+++ 1.147/sql/handler.h	2005-09-16 08:40:42 +02:00
@@ -110,6 +110,7 @@
 #define HA_ONLINE_COALESCE_PARTITION 8
 #define HA_ONLINE_REORG_PARTITION 16
 #define HA_ONLINE_DOUBLE_WRITE 32
+#define HA_ONLINE_PARTITION_ONE_PHASE 64
 
 /* operations for disable/enable indexes */
 #define HA_KEY_SWITCH_NONUNIQ      0
@@ -1330,21 +1331,35 @@
 
   /*
     SYNOPSIS
-      add_partitions()
-      table                       Table object where partitions are added
-      create_info                 HA_CREATE_INFO object describing all fields
-                                  and indexes in table
+      change_partitions()
+      create_info                 HA_CREATE_INFO object describing all
+                                  fields and indexes in table
       path                        Complete path of db and table name
+      copied                      Output parameter where number of copied
+                                  records are added
+      deleted                     Output parameter where number of deleted
+                                  records are added
+      pack_frm_data               Reference to packed frm file
+      pack_frm_len                Length of packed frm file
     RETURN VALUE
       TRUE                        Failure
       FALSE                       Success
     DESCRIPTION
-      Add a number of partitions, during this operation no other operation
-      is ongoing in the server. This is used by ADD PARTITION all types
-      as well as by REORGANISE PARTITION.
+      Add and copy if needed a number of partitions, during this operation
+      no other operation is ongoing in the server. This is used by
+      ADD PARTITION all types as well as by REORGANISE PARTITION. For
+      one-phased implementations it is used also by DROP and COALESCE
+      PARTITIONs.
+      One-phased implementation needs the new frm file, other handlers will
+      get zero length and a NULL reference here.
   */
-  virtual int add_partitions(HA_CREATE_INFO *create_info,
-                             const char *path)
+
+  virtual int change_partitions(HA_CREATE_INFO *create_info,
+                                const char *path,
+                                ulonglong *copied,
+                                ulonglong *deleted,
+                                const void *pack_frm_data,
+                                uint pack_frm_len)
   { return HA_ERR_WRONG_COMMAND; }
 
   /*
@@ -1374,22 +1389,6 @@
       an exclusive lock on the table.
   */
   virtual int rename_partitions(const char *path)
-  { return HA_ERR_WRONG_COMMAND; }
-
-  /*
-    SYNOPSIS
-      copy_partitions()
-      copied                      Output parameter where number of copied
-                                  records are added
-      deleted                     Output parameter where number of deleted
-                                  records are added
-    RETURN VALUES
-      TRUE                        Failure
-      FALSE                       Success
-    DESCRIPTION
-      Copy from reorged partitions to the new partitions
-  */
-  virtual int copy_partitions(ulonglong &copied, ulonglong &deleted)
   { return HA_ERR_WRONG_COMMAND; }
 
   /* lock_count() can be more than one if the table is a MERGE */

--- 1.303/sql/mysql_priv.h	2005-09-15 18:53:39 +02:00
+++ 1.304/sql/mysql_priv.h	2005-09-16 08:40:42 +02:00
@@ -1039,6 +1039,10 @@
 } LOCK_PARAM_TYPE;
 
 void mem_alloc_error();
+int packfrm(const void *data, uint len, 
+            const void **pack_data, uint *pack_len);
+int unpackfrm(const void **unpack_data, uint *unpack_len,
+              const void *pack_data);
 bool mysql_write_frm(LOCK_PARAM_TYPE *lpt, bool initial_write,
                      bool create_handler_files, bool pack_frm);
 bool abort_and_upgrade_lock(LOCK_PARAM_TYPE *lpt);

--- 1.234/sql/sql_table.cc	2005-09-15 18:53:39 +02:00
+++ 1.235/sql/sql_table.cc	2005-09-16 08:40:42 +02:00
@@ -104,6 +104,7 @@
     Prepare table to prepare for writing a new frm file where the
     partitions in add/drop state have temporarily changed their state
   */
+  int error= 0;
   char path[FN_REFLEN+1];
   DBUG_ENTER("mysql_write_frm");
 
@@ -134,6 +135,11 @@
     }
   }
 #endif
+  /*
+    We write the frm file with the LOCK_open mutex since otherwise we could
+    overwrite the frm file as another is reading it in open_table.
+  */
+  VOID(pthread_mutex_lock(&LOCK_open));
   build_table_path(path, sizeof(path), lpt->db, lpt->table_name, reg_ext);
   if ((mysql_create_frm(lpt->thd, path, lpt->db, lpt->table_name,
                         lpt->create_info, *lpt->create_list, lpt->key_count,
@@ -141,7 +147,8 @@
       (create_handler_files &&
        lpt->table->file->create_handler_files(path)))
   {
-    DBUG_RETURN(TRUE);
+    error= 1;
+    goto end;
   }
 #ifdef HAVE_PARTITION_DB
   /*
@@ -164,17 +171,17 @@
         packfrm(data, length, &lpt->pack_frm_data, &lpt->pack_frm_len))
     {
       my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
-      my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
+      my_free((char*)lpt->pack_frm_data, MYF(MY_ALLOW_ZERO_PTR));
       mem_alloc_error();
-      DBUG_RETURN(TRUE);
-    }
-    if ((error= my_delete(path, MYF(WME))))
-    {
-      DBUG_RETURN(TRUE);
+      error= 1;
+      goto end;
     }
+    error= my_delete(path, MYF(MY_WME));
   }
   /* Frm file have been updated to reflect the change about to happen.  */
-  DBUG_RETURN(FALSE);
+end:
+  VOID(pthread_mutex_unlock(&LOCK_open));
+  DBUG_RETURN(error);
 }
 
 

--- 1.152/sql/ha_ndbcluster.cc	2005-09-14 15:58:25 +02:00
+++ 1.153/sql/ha_ndbcluster.cc	2005-09-16 08:40:41 +02:00
@@ -109,10 +109,6 @@
 static NDB_SHARE *get_share(const char *table_name);
 static void free_share(NDB_SHARE *share);
 
-static int packfrm(const void *data, uint len, const void **pack_data, uint *pack_len);
-static int unpackfrm(const void **data, uint *len,
-                     const void* pack_data);
-
 static int ndb_get_table_statistics(Ndb*, const char *, 
                                     struct Ndb_statistics *);
 
@@ -5268,102 +5264,6 @@
 
 
 
-/*
-  Internal representation of the frm blob
-   
-*/
-
-struct frm_blob_struct 
-{
-  struct frm_blob_header 
-  {
-    uint ver;      // Version of header
-    uint orglen;   // Original length of compressed data
-    uint complen;  // Compressed length of data, 0=uncompressed
-  } head;
-  char data[1];  
-};
-
-
-
-static int packfrm(const void *data, uint len, 
-                   const void **pack_data, uint *pack_len)
-{
-  int error;
-  ulong org_len, comp_len;
-  uint blob_len;
-  frm_blob_struct* blob;
-  DBUG_ENTER("packfrm");
-  DBUG_PRINT("enter", ("data: %x, len: %d", data, len));
-  
-  error= 1;
-  org_len= len;
-  if (my_compress((byte*)data, &org_len, &comp_len))
-    goto err;
-  
-  DBUG_PRINT("info", ("org_len: %d, comp_len: %d", org_len, comp_len));
-  DBUG_DUMP("compressed", (char*)data, org_len);
-  
-  error= 2;
-  blob_len= sizeof(frm_blob_struct::frm_blob_header)+org_len;
-  if (!(blob= (frm_blob_struct*) my_malloc(blob_len,MYF(MY_WME))))
-    goto err;
-  
-  // Store compressed blob in machine independent format
-  int4store((char*)(&blob->head.ver), 1);
-  int4store((char*)(&blob->head.orglen), comp_len);
-  int4store((char*)(&blob->head.complen), org_len);
-  
-  // Copy frm data into blob, already in machine independent format
-  memcpy(blob->data, data, org_len);  
-  
-  *pack_data= blob;
-  *pack_len= blob_len;
-  error= 0;
-  
-  DBUG_PRINT("exit", ("pack_data: %x, pack_len: %d", *pack_data, *pack_len));
-err:
-  DBUG_RETURN(error);
-  
-}
-
-
-static int unpackfrm(const void **unpack_data, uint *unpack_len,
-                    const void *pack_data)
-{
-   const frm_blob_struct *blob= (frm_blob_struct*)pack_data;
-   byte *data;
-   ulong complen, orglen, ver;
-   DBUG_ENTER("unpackfrm");
-   DBUG_PRINT("enter", ("pack_data: %x", pack_data));
-
-   complen=     uint4korr((char*)&blob->head.complen);
-   orglen=      uint4korr((char*)&blob->head.orglen);
-   ver=         uint4korr((char*)&blob->head.ver);
- 
-   DBUG_PRINT("blob",("ver: %d complen: %d orglen: %d",
-                     ver,complen,orglen));
-   DBUG_DUMP("blob->data", (char*) blob->data, complen);
- 
-   if (ver != 1)
-     DBUG_RETURN(1);
-   if (!(data= my_malloc(max(orglen, complen), MYF(MY_WME))))
-     DBUG_RETURN(2);
-   memcpy(data, blob->data, complen);
- 
-   if (my_uncompress(data, &complen, &orglen))
-   {
-     my_free((char*)data, MYF(0));
-     DBUG_RETURN(3);
-   }
-
-   *unpack_data= data;
-   *unpack_len= complen;
-
-   DBUG_PRINT("exit", ("frmdata: %x, len: %d", *unpack_data, *unpack_len));
-
-   DBUG_RETURN(0);
-}
 
 static 
 int
@@ -7436,14 +7336,14 @@
       {
         DBUG_RETURN(1);
       }
-      if (error= dict->createTablespace(ndb_ts))
+      if ((error= dict->createTablespace(ndb_ts)))
       {
         DBUG_PRINT("error", ("createTablespace returned %d", error));
         my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "TABLESPACE");
         DBUG_RETURN(1);
       }
       DBUG_PRINT("info", ("Successfully created Tablespace"));
-      if (error= dict->createDatafile(ndb_df))
+      if ((error= dict->createDatafile(ndb_df)))
       {
         DBUG_PRINT("error", ("createDatafile returned %d", error));
         my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "DATAFILE");
@@ -7458,7 +7358,7 @@
       {
         DBUG_RETURN(1);
       }
-      if (error= dict->createDatafile(ndb_df))
+      if ((error= dict->createDatafile(ndb_df)))
       {
         DBUG_PRINT("error", ("createDatafile returned %d", error));
         my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "DATAFILE");
@@ -7481,7 +7381,7 @@
       {
         DBUG_RETURN(1);
       }
-      if (error= dict->createLogfileGroup(ndb_lg))
+      if ((error= dict->createLogfileGroup(ndb_lg)))
       {
         DBUG_PRINT("error", ("createLogfileGroup returned %d", error));
         my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "LOGFILE GROUP");
@@ -7492,7 +7392,7 @@
       {
         DBUG_RETURN(1);
       }
-      if (error= dict->createUndofile(ndb_uf))
+      if ((error= dict->createUndofile(ndb_uf)))
       {
         DBUG_PRINT("error", ("createUndofile returned %d", error));
         my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "UNDOFILE");
@@ -7514,7 +7414,7 @@
       {
         DBUG_RETURN(1);
       }
-      if (error= dict->createUndofile(ndb_uf))
+      if ((error= dict->createUndofile(ndb_uf)))
       {
         DBUG_PRINT("error", ("createUndofile returned %d", error));
         my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "UNDOFILE");
@@ -7524,8 +7424,8 @@
     }
     case (DROP_TABLESPACE):
     {
-      if (error= dict->dropTablespace(
-            dict->getTablespace(info->tablespace_name)))
+      if ((error= dict->dropTablespace(
+            dict->getTablespace(info->tablespace_name))))
       {
         DBUG_PRINT("error", ("dropTablespace returned %d", error));
         my_error(ER_DROP_TABLESPACE_FAILED, MYF(0), "TABLESPACE");
@@ -7535,8 +7435,8 @@
     }
     case (DROP_LOGFILE_GROUP):
     {
-      if (error= dict->dropLogfileGroup(
-            dict->getLogfileGroup(info->tablespace_name)))
+      if ((error= dict->dropLogfileGroup(
+            dict->getLogfileGroup(info->tablespace_name))))
       {
         DBUG_PRINT("error", ("dropLogfileGroup returned %d", error));
         my_error(ER_DROP_TABLESPACE_FAILED, MYF(0), "LOGFILE GROUP");

--- 1.4/sql/ha_partition.cc	2005-09-13 15:53:14 +02:00
+++ 1.5/sql/ha_partition.cc	2005-09-16 08:40:42 +02:00
@@ -581,10 +581,12 @@
                                   handler *file, const char *part_name)
 {
   int error;
+  bool create_flag= FALSE, open_flag= FALSE;
   DBUG_ENTER("prepare_handler");
 
   if ((error= file->create(part_name, table, create_info)))
     goto error;
+  create_flag= TRUE;
   if ((error= file->ha_open(part_name, m_mode, m_open_test_lock)))
     goto error;
   if ((error= file->external_lock(current_thd, m_lock_type)))
@@ -592,10 +594,21 @@
 
   DBUG_RETURN(FALSE);
 error:
+  if (create_flag)
+    VOID(file->delete_table(part_name));
   DBUG_RETURN(TRUE);
 }
 
 
+/*
+  TODO:
+  We must ensure that in the case that we get an error during the process
+  that we call external_lock with F_UNLCK, close the table and delete the
+  table in the case where we have been successful with prepare_handler.
+  We solve this by keeping an array of successful calls to prepare_handler
+  which can then be used to undo the call.
+*/
+
 void ha_partition::handler_cleanup(uint part_count)
 {
   DBUG_ENTER("ha_partition::handler_cleanup");
@@ -603,8 +616,12 @@
 }
 
 
-int ha_partition::add_partitions(HA_CREATE_INFO *create_info,
-                                 const char *path)
+int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
+                                    const char *path,
+                                    ulonglong *copied,
+                                    ulonglong *deleted,
+                                    const void *pack_frm_data,
+                                    uint pack_frm_len)
 {
   List_iterator<partition_element> part_it(m_part_info->partitions);
   List_iterator_fast <partition_element> t_it(m_part_info->temp_partitions);
@@ -614,9 +631,12 @@
   uint no_remain_partitions, part_count;
   handler **new_file_array;
   int error= 1;
-  bool first;
+  bool first, copy_parts= FALSE;
   uint temp_partitions= m_part_info->temp_partitions.elements;
-  DBUG_ENTER("ha_partition::add_partitions");
+  DBUG_ENTER("ha_partition::change_partitions");
+
+  (void)pack_frm_data; /* Compiler happy */
+  (void)pack_frm_len;  /* Compiler happy */
 
   m_reorged_parts= 0;
   if (!is_sub_partitioned(m_part_info))
@@ -828,21 +848,23 @@
     DBUG_ASSERT(part_elem->part_state == PART_TO_BE_REORGED);
     part_elem->part_state= PART_TO_BE_DROPPED;
   } while (++i < temp_partitions);
-  DBUG_RETURN(error);
+  m_file= new_file_array;
+  DBUG_RETURN(copy_partitions(copied, deleted));
 }
 
 
 /*
-  add_partitions has done all the preparations, now it is time to actually
-  copy the data from the reorganised partitions to the new partitions.
+  change_partitions has done all the preparations, now it is time to
+  actually copy the data from the reorganised partitions to the new
+  partitions.
 */
-int ha_partition::copy_partitions(ulonglong &copied, ulonglong &deleted)
+int ha_partition::copy_partitions(ulonglong *copied, ulonglong *deleted)
 {
   uint reorg_part= 0;
   int result;
-  DBUG_ENTER("ha_partition::copy_partition");
+  DBUG_ENTER("ha_partition::copy_partitions");
 
-  do
+  while (reorg_part < m_reorged_parts)
   {
     handler *file= m_reorged_file[reorg_part];
     uint32 new_part;
@@ -883,8 +905,9 @@
       }
     }
     late_extra_no_cache(reorg_part);
-    file->rnd_end(); 
-  } while (++reorg_part < m_reorged_parts);
+    file->rnd_end();
+    reorg_part++;
+  }
   DBUG_RETURN(FALSE);
 error:
   DBUG_RETURN(TRUE);

--- 1.3/sql/ha_partition.h	2005-09-13 15:53:14 +02:00
+++ 1.4/sql/ha_partition.h	2005-09-16 08:40:42 +02:00
@@ -171,11 +171,16 @@
   virtual int create_handler_files(const char *name);
   virtual void update_create_info(HA_CREATE_INFO *create_info);
   virtual char *update_table_comment(const char *comment);
-  virtual int add_partitions(HA_CREATE_INFO *create_info, const char *path);
+  virtual int change_partitions(HA_CREATE_INFO *create_info,
+                                const char *path,
+                                ulonglong *copied,
+                                ulonglong *deleted,
+                                const void *pack_frm_data,
+                                uint pack_frm_len);
   virtual int drop_partitions(const char *path);
   virtual int rename_partitions(const char *path);
-  virtual int copy_partitions(ulonglong &copied, ulonglong &deleted);
 private:
+  int copy_partitions(ulonglong *copied, ulonglong *deleted);
   void handler_cleanup(uint part_count);
   int prepare_handler(TABLE *table, HA_CREATE_INFO *create_info,
                       handler *file, const char *part_name);

--- 1.7/sql/sql_partition.cc	2005-09-15 18:53:39 +02:00
+++ 1.8/sql/sql_partition.cc	2005-09-16 08:40:42 +02:00
@@ -3947,10 +3947,14 @@
 
 /*
   SYNOPSIS
-    mysql_add_partitions()
+    mysql_change_partitions()
     create_info                Create information used to create partitions
     db                         Database name
     table_name                 Table name
+    copied                     Output parameter where number of copied
+                               records are added
+    deleted                    Output parameter where number of deleted
+                               records are added
     All parameters passed through the write_frm_type object
   RETURN VALUES
     TRUE                          Failure
@@ -3959,13 +3963,17 @@
     Request handler to add partitions as set in states of the partition
 */
 
-static bool mysql_add_partitions(LOCK_PARAM_TYPE *lpt)
+static bool mysql_change_partitions(LOCK_PARAM_TYPE *lpt)
 {
   char path[FN_REFLEN+1];
-  DBUG_ENTER("mysql_add_partitions");
+  DBUG_ENTER("mysql_change_partitions");
 
   build_table_path(path, sizeof(path), lpt->db, lpt->table_name, "");
-  DBUG_RETURN(lpt->table->file->add_partitions(lpt->create_info, path));
+  DBUG_RETURN(lpt->table->file->change_partitions(lpt->create_info, path,
+                                                  &lpt->copied,
+                                                  &lpt->deleted,
+                                                  lpt->pack_frm_data,
+                                                  lpt->pack_frm_len));
 }
 
 
@@ -4096,7 +4104,7 @@
   thd->lex->part_info= part_info;
   DBUG_ENTER("online_alter_part_table");
 
-  if (table->file->alter_table_flags & HA_ONLINE_PARTITION_ONE_PHASE)
+  if (table->file->alter_table_flags() & HA_ONLINE_PARTITION_ONE_PHASE)
   {
     /*
       In the case where the engine supports one phase online partition
@@ -4135,7 +4143,7 @@
     if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
       mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE);
     if ((mysql_write_frm(lpt, TRUE, FALSE, TRUE)) ||
-        (table->file->change_partitions(lpt, copied, deleted)))
+        (mysql_change_partitions(lpt)))
     {
       DBUG_RETURN(FALSE);
     }
@@ -4172,10 +4180,10 @@
          remaining locks).
     */
     if ((abort_and_upgrade_lock(lpt)) ||
-        (mysql_write_frm(lpt, TRUE, FALSE)) ||
+        (mysql_write_frm(lpt, TRUE, FALSE, FALSE)) ||
         (close_open_tables_and_downgrade(lpt), FALSE) || 
         (mysql_drop_partitions(lpt)) ||
-        (mysql_write_frm(lpt, FALSE, TRUE)) ||
+        (mysql_write_frm(lpt, FALSE, TRUE, FALSE)) ||
         (mysql_wait_completed_table(lpt, table), FALSE))
     {
       online_alter_part_error_handler(lpt);
@@ -4217,10 +4225,10 @@
     */
     if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
       mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE);
-    if ((mysql_write_frm(lpt, TRUE, FALSE)) ||
-        (mysql_add_partitions(lpt)) ||
+    if ((mysql_write_frm(lpt, TRUE, FALSE, FALSE)) ||
+        (mysql_change_partitions(lpt)) ||
         (abort_and_upgrade_lock(lpt)) ||
-        (mysql_write_frm(lpt, FALSE, TRUE)) ||
+        (mysql_write_frm(lpt, FALSE, TRUE, FALSE)) ||
         (close_open_tables_and_downgrade(lpt), FALSE))
     {
       online_alter_part_error_handler(lpt);
@@ -4286,15 +4294,14 @@
       if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
         mysql_lock_downgrade_write(lpt->thd, lpt->table,
                                    TL_WRITE_ALLOW_WRITE);
-      if ((mysql_write_frm(lpt, TRUE, FALSE)) ||
-          (mysql_add_partitions(lpt)) ||
-          (table->file->copy_partitions(copied, deleted)) ||
+      if ((mysql_write_frm(lpt, TRUE, FALSE, FALSE)) ||
+          (mysql_change_partitions(lpt)) ||
           (abort_and_upgrade_lock(lpt)) ||
-          (mysql_write_frm(lpt, FALSE, TRUE)) ||
+          (mysql_write_frm(lpt, FALSE, TRUE, FALSE)) ||
           (mysql_rename_partitions(lpt)) ||
           (close_open_tables_and_downgrade(lpt), FALSE) ||
           (mysql_drop_partitions(lpt)) ||
-          (mysql_write_frm(lpt, FALSE, FALSE)) ||
+          (mysql_write_frm(lpt, FALSE, FALSE, FALSE)) ||
           (mysql_wait_completed_table(lpt, table), FALSE))
       {
         online_alter_part_error_handler(lpt);
@@ -4303,15 +4310,14 @@
     }
     else
     {
-      if ((mysql_write_frm(lpt, TRUE, FALSE)) ||
-          (mysql_add_partitions(lpt)) ||
-          (table->file->copy_partitions(copied, deleted)) ||
+      if ((mysql_write_frm(lpt, TRUE, FALSE, FALSE)) ||
+          (mysql_change_partitions(lpt)) ||
           (abort_and_upgrade_lock(lpt)) ||
-          (mysql_write_frm(lpt, FALSE, TRUE)) ||
+          (mysql_write_frm(lpt, FALSE, TRUE, FALSE)) ||
           (mysql_rename_partitions(lpt)) ||
           (close_open_tables_and_downgrade(lpt), FALSE) ||
           (mysql_drop_partitions(lpt)) ||
-          (mysql_write_frm(lpt, FALSE, FALSE)))
+          (mysql_write_frm(lpt, FALSE, FALSE, FALSE)))
       {
         online_alter_part_error_handler(lpt);
         DBUG_RETURN(TRUE);
@@ -4332,17 +4338,133 @@
       error= 1;
     if (!error)
     {
+      char tmp_name[80];
       write_bin_log(thd, FALSE);
       close_thread_tables(thd);
-      send_ok(thd);
+      my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
+                  (ulong) (lpt->copied + lpt->deleted),
+                  (ulong) lpt->deleted,
+                  (ulong) 0);
+      send_ok(thd,lpt->copied+lpt->deleted,0L,tmp_name);
       DBUG_RETURN(FALSE);
     }
     online_alter_part_error_handler(lpt);
     DBUG_RETURN(TRUE);
   }
 }
-
 #endif
+
+/*
+  Internal representation of the frm blob
+   
+*/
+
+struct frm_blob_struct 
+{
+  struct frm_blob_header 
+  {
+    uint ver;      // Version of header
+    uint orglen;   // Original length of compressed data
+    uint complen;  // Compressed length of data, 0=uncompressed
+  } head;
+  char data[1];  
+};
+
+
+/*
+  packfrm is a method used to compress the frm file for storage in a
+  handler. This method was developed for the NDB handler and has been moved
+  here to serve also other uses.
+  SYNOPSIS
+    packfrm()
+    data                    Data reference to frm file data
+    len                     Length of frm file data
+    pack_data               Reference to the pointer to the packed frm data
+    pack_len                Length of packed frm file data
+    0                       Success
+    >0                      Failure
+*/
+
+int packfrm(const void *data, uint len, 
+            const void **pack_data, uint *pack_len)
+{
+  int error;
+  ulong org_len, comp_len;
+  uint blob_len;
+  frm_blob_struct* blob;
+  DBUG_ENTER("packfrm");
+  DBUG_PRINT("enter", ("data: %x, len: %d", data, len));
+  
+  error= 1;
+  org_len= len;
+  if (my_compress((byte*)data, &org_len, &comp_len))
+    goto err;
+  
+  DBUG_PRINT("info", ("org_len: %d, comp_len: %d", org_len, comp_len));
+  DBUG_DUMP("compressed", (char*)data, org_len);
+  
+  error= 2;
+  blob_len= sizeof(frm_blob_struct::frm_blob_header)+org_len;
+  if (!(blob= (frm_blob_struct*) my_malloc(blob_len,MYF(MY_WME))))
+    goto err;
+  
+  // Store compressed blob in machine independent format
+  int4store((char*)(&blob->head.ver), 1);
+  int4store((char*)(&blob->head.orglen), comp_len);
+  int4store((char*)(&blob->head.complen), org_len);
+  
+  // Copy frm data into blob, already in machine independent format
+  memcpy(blob->data, data, org_len);  
+  
+  *pack_data= blob;
+  *pack_len= blob_len;
+  error= 0;
+  
+  DBUG_PRINT("exit", ("pack_data: %x, pack_len: %d", *pack_data, *pack_len));
+err:
+  DBUG_RETURN(error);
+  
+}
+
+
+int unpackfrm(const void **unpack_data, uint *unpack_len,
+              const void *pack_data)
+{
+   const frm_blob_struct *blob= (frm_blob_struct*)pack_data;
+   byte *data;
+   ulong complen, orglen, ver;
+   DBUG_ENTER("unpackfrm");
+   DBUG_PRINT("enter", ("pack_data: %x", pack_data));
+
+   complen=     uint4korr((char*)&blob->head.complen);
+   orglen=      uint4korr((char*)&blob->head.orglen);
+   ver=         uint4korr((char*)&blob->head.ver);
+ 
+   DBUG_PRINT("blob",("ver: %d complen: %d orglen: %d",
+                     ver,complen,orglen));
+   DBUG_DUMP("blob->data", (char*) blob->data, complen);
+ 
+   if (ver != 1)
+     DBUG_RETURN(1);
+   if (!(data= my_malloc(max(orglen, complen), MYF(MY_WME))))
+     DBUG_RETURN(2);
+   memcpy(data, blob->data, complen);
+ 
+   if (my_uncompress(data, &complen, &orglen))
+   {
+     my_free((char*)data, MYF(0));
+     DBUG_RETURN(3);
+   }
+
+   *unpack_data= data;
+   *unpack_len= complen;
+
+   DBUG_PRINT("exit", ("frmdata: %x, len: %d", *unpack_data, *unpack_len));
+
+   DBUG_RETURN(0);
+}
+
 
 /*
   Prepare for calling val_int on partition function by setting fields to
Thread
bk commit into 5.1 tree (mronstrom:1.2015)mikael16 Sep