List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:June 10 2010 3:52am
Subject:bzr commit into mysql-next-mr branch (davi:3154) WL#4445
View as plain text  
# At a local mysql-next-mr repository of davi

 3154 Davi Arnaut	2010-06-10
      WL#4445: EXCHANGE PARTITION WITH TABLE
      
      Review changes: prepare ground for unifying partition related
      alter statements and for the move of Alter_info. Also, some
      minor some minor changes to hopefully increase quality.
     @ client/mysqltest.cc
        Allow the result of the list_files commands to be replaced.
     @ mysql-test/suite/parts/inc/partition_crash.inc
        Use list_files in conjunction with replace_regex.
     @ mysql-test/suite/parts/t/partition_exchange_myisam.test
        Test case uses debug syncs. TODO: propagate to other test cases.
     @ sql/sql_alter_table.cc
        Fix coding style and aid debugging by not placing function calls
        within a DBUG_RETURN macro.
     @ sql/sql_alter_table.h
        Move Alter_table_exchange_partition_statement to sql_partition_admin.cc
     @ sql/sql_lex.cc
        Reset pointer to SQL statement.
     @ sql/sql_lex.h
        Workaround the fact that enums can't be forward declared.
     @ sql/sql_parse.cc
        Reset of the Sql_statement pointer must be done within its owner.
     @ sql/sql_partition_admin.cc
        Introduce a home for administrative statements operating upon
        partitioned tables. TODO: Move partition truncate to here, etc.
     @ sql/sql_partition_admin.h
        Introduce a common class to return errors when the partition
        storage engine is disabled.
     @ sql/sql_table.cc
        Move functions related to partition tables to sql_partition_admin.cc
     @ sql/sql_table.h
        Export functions for use by the partitioning code.
     @ sql/sql_yacc.yy
        Remove assigment, done within the lexer.

    added:
      sql/sql_partition_admin.cc
      sql/sql_partition_admin.h
    modified:
      client/mysqltest.cc
      libmysqld/CMakeLists.txt
      libmysqld/Makefile.am
      mysql-test/suite/parts/inc/partition_crash.inc
      mysql-test/suite/parts/t/partition_debug.test
      mysql-test/suite/parts/t/partition_exchange_myisam.test
      sql/CMakeLists.txt
      sql/Makefile.am
      sql/sql_alter_table.cc
      sql/sql_alter_table.h
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_parse.cc
      sql/sql_table.cc
      sql/sql_table.h
      sql/sql_yacc.yy
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc	2010-04-13 15:04:45 +0000
+++ b/client/mysqltest.cc	2010-06-10 03:52:16 +0000
@@ -3264,7 +3264,7 @@ static int get_list_files(DYNAMIC_STRING
     if (ds_wild && ds_wild->length &&
         wild_compare(file->name, ds_wild->str, 0))
       continue;
-    dynstr_append(ds, file->name);
+    replace_dynstr_append(ds, file->name);
     dynstr_append(ds, "\n");
   }
   my_dirend(dir_info);

=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt	2010-06-07 11:29:54 +0000
+++ b/libmysqld/CMakeLists.txt	2010-06-10 03:52:16 +0000
@@ -79,7 +79,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc l
            ../sql/sql_time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
            ../sql/partition_info.cc ../sql/sql_connect.cc 
            ../sql/scheduler.cc ../sql/sql_audit.cc
-           ../sql/sql_alter_table.cc
+           ../sql/sql_alter_table.cc ../sql/sql_partition_admin.cc
            ../sql/event_parse_data.cc
            ../sql/sql_signal.cc ../sql/rpl_handler.cc
 	       ../sql/rpl_utility.cc

=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am	2010-06-07 11:29:54 +0000
+++ b/libmysqld/Makefile.am	2010-06-10 03:52:16 +0000
@@ -80,7 +80,8 @@ sqlsources = derror.cc field.cc field_co
 	debug_sync.cc sql_tablespace.cc transaction.cc \
 	rpl_injector.cc my_user.c partition_info.cc sql_alter_table.cc \
 	sql_servers.cc event_parse_data.cc sql_signal.cc \
-	rpl_handler.cc mdl.cc keycaches.cc sql_audit.cc
+	rpl_handler.cc mdl.cc keycaches.cc sql_audit.cc \
+	sql_partition_admin.cc
 
 libmysqld_int_a_SOURCES= $(libmysqld_sources)
 nodist_libmysqld_int_a_SOURCES= $(libmysqlsources) $(sqlsources)

=== modified file 'mysql-test/suite/parts/inc/partition_crash.inc'
--- a/mysql-test/suite/parts/inc/partition_crash.inc	2010-06-03 21:00:55 +0000
+++ b/mysql-test/suite/parts/inc/partition_crash.inc	2010-06-10 03:52:16 +0000
@@ -7,29 +7,15 @@
 SHOW CREATE TABLE t1;
 --sorted_result
 SELECT * FROM t1;
---write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-wait
-EOF
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--disable_reconnect
 # CR_SERVER_LOST
 --error 2013
 --eval $crash_statement
 --echo # State after crash (before recovery)
---list_files_write_file $MYSQLTEST_VARDIR/tmp/ls_of_crash.txt $DATADIR/test
---let LS_FILE=$MYSQLTEST_VARDIR/tmp/ls_of_crash.txt
---let EXPECT_FILE=$MYSQLTEST_VARDIR/tmp/mysqld.1.expect
---perl
-open(FH, "<", $ENV{'LS_FILE'}) or die "Failed to open ls file";
-while (<FH>)
-{
-  s/sqlx.*\./sqlx-nnnn_nnnn./;
-  print;
-}
-close(FH);
-unlink $ENV{'LS_FILE'};
-open(FH, ">", $ENV{'EXPECT_FILE'}) or die "Failed to open expect file";
-print FH "restart";
-close(FH);
-EOF
+--replace_regex /sqlx.*\./sqlx-nnnn_nnnn./
+--list_files $DATADIR/test
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
 --enable_reconnect
 --source include/wait_until_connected_again.inc
 --echo # State after crash recovery

=== modified file 'mysql-test/suite/parts/t/partition_debug.test'
--- a/mysql-test/suite/parts/t/partition_debug.test	2010-05-19 19:40:56 +0000
+++ b/mysql-test/suite/parts/t/partition_debug.test	2010-06-10 03:52:16 +0000
@@ -3,6 +3,8 @@
 
 --source include/have_debug.inc
 --source include/have_partition.inc
+# Don't test this under valgrind, memory leaks will occur
+--source include/not_valgrind.inc
 
 --disable_warnings
 DROP TABLE IF EXISTS t1;

=== modified file 'mysql-test/suite/parts/t/partition_exchange_myisam.test'
--- a/mysql-test/suite/parts/t/partition_exchange_myisam.test	2010-04-13 00:07:15 +0000
+++ b/mysql-test/suite/parts/t/partition_exchange_myisam.test	2010-06-10 03:52:16 +0000
@@ -1,4 +1,5 @@
 --source include/have_partition.inc
+--source include/have_debug_sync.inc
 
 let $engine= 'MyISAM';
 --source suite/parts/inc/partition_exchange.inc

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2010-06-07 11:29:54 +0000
+++ b/sql/CMakeLists.txt	2010-06-10 03:52:16 +0000
@@ -72,7 +72,7 @@ SET (SQL_SOURCE
                sql_tablespace.cc events.cc ../sql-common/my_user.c 
                partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
                rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc
-               sql_connect.cc scheduler.cc 
+               sql_connect.cc scheduler.cc sql_partition_admin.cc
                sql_profile.cc event_parse_data.cc sql_alter_table.cc
                sql_signal.cc rpl_handler.cc mdl.cc
                transaction.cc sys_vars.cc

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2010-06-07 11:29:54 +0000
+++ b/sql/Makefile.am	2010-06-10 03:52:16 +0000
@@ -118,7 +118,7 @@ noinst_HEADERS =	item.h item_func.h item
 			sql_plugin.h authors.h event_parse_data.h \
 			event_data_objects.h event_scheduler.h \
 			sql_partition.h partition_info.h partition_element.h \
-			sql_audit.h sql_alter_table.h \
+			sql_audit.h sql_alter_table.h sql_partition_admin.h \
 			contributors.h sql_servers.h sql_signal.h records.h \
 			sql_prepare.h rpl_handler.h replication.h mdl.h \
 			sql_plist.h transaction.h sys_vars.h
@@ -168,7 +168,8 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			sql_builtin.cc sql_tablespace.cc partition_info.cc \
 			sql_servers.cc event_parse_data.cc sql_signal.cc \
 			rpl_handler.cc mdl.cc transaction.cc sql_audit.cc  \
-			sql_alter_table.cc sha2.cc
+			sql_alter_table.cc sql_partition_admin.cc sha2.cc \
+			sql_partition_admin.cc
 
 nodist_mysqld_SOURCES =	mini_client_errors.c pack.c client.c my_time.c my_user.c 
 

=== modified file 'sql/sql_alter_table.cc'
--- a/sql/sql_alter_table.cc	2010-06-07 11:29:54 +0000
+++ b/sql/sql_alter_table.cc	2010-06-10 03:52:16 +0000
@@ -11,7 +11,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 #include "sql_parse.h"                       // check_access,
                                              // check_merge_table_access
@@ -21,7 +21,6 @@
 
 bool Alter_table_statement::execute(THD *thd)
 {
-  /* Moved from mysql_execute_command */
   LEX *lex= thd->lex;
   /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
   SELECT_LEX *select_lex= &lex->select_lex;
@@ -38,6 +37,7 @@ bool Alter_table_statement::execute(THD 
   Alter_info alter_info(lex->alter_info, thd->mem_root);
   ulong priv=0;
   ulong priv_needed= ALTER_ACL;
+  bool result;
 
   DBUG_ENTER("Alter_table_statement::execute");
 
@@ -68,16 +68,18 @@ bool Alter_table_statement::execute(THD 
 
   if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
     DBUG_RETURN(TRUE);                  /* purecov: inspected */
-  if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
-  { // Rename of table
-      TABLE_LIST tmp_table;
-      bzero((char*) &tmp_table,sizeof(tmp_table));
-      tmp_table.table_name= lex->name.str;
-      tmp_table.db=select_lex->db;
-      tmp_table.grant.privilege=priv;
-      if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, FALSE,
-          UINT_MAX, FALSE))
-    DBUG_RETURN(TRUE);                  /* purecov: inspected */
+
+  if (lex->name.str && !test_all_bits(priv, INSERT_ACL | CREATE_ACL))
+  {
+    // Rename of table
+    TABLE_LIST tmp_table;
+    bzero((char*) &tmp_table,sizeof(tmp_table));
+    tmp_table.table_name= lex->name.str;
+    tmp_table.db=select_lex->db;
+    tmp_table.grant.privilege=priv;
+    if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table,
+                    FALSE, UINT_MAX, FALSE))
+      DBUG_RETURN(TRUE);                  /* purecov: inspected */
   }
 
   /* Don't yet allow changing of symlinks with ALTER TABLE */
@@ -92,68 +94,12 @@ bool Alter_table_statement::execute(THD 
   create_info.data_file_name= create_info.index_file_name= NULL;
 
   thd->enable_slow_log= opt_log_slow_admin_statements;
-  DBUG_RETURN(mysql_alter_table(thd, select_lex->db, lex->name.str,
-                                &create_info,
-                                first_table,
-                                &alter_info,
-                                select_lex->order_list.elements,
-                                (ORDER *) select_lex->order_list.first,
-                                lex->ignore));
-}
-
-
-bool Alter_table_exchange_partition_statement::execute(THD *thd)
-{
-  /* Moved from mysql_execute_command */
-  LEX *lex= thd->lex;
-  /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
-  SELECT_LEX *select_lex= &lex->select_lex;
-  /* first table of first SELECT_LEX */
-  TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
-  /*
-    Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
-    so we have to use a copy of this structure to make execution
-    prepared statement- safe. A shallow copy is enough as no memory
-    referenced from this structure will be modified.
-    @todo move these into constructor...
-  */
-  HA_CREATE_INFO create_info(lex->create_info);
-  Alter_info alter_info(lex->alter_info, thd->mem_root);
-  ulong priv_needed= ALTER_ACL | DROP_ACL | INSERT_ACL | CREATE_ACL;
-
-  DBUG_ENTER("Alter_table_exchange_partition_statement::execute");
-
-  if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
-    DBUG_RETURN(TRUE);
-
-  /* Must be set in the parser */
-  DBUG_ASSERT(select_lex->db);
-#ifdef WITH_PARTITION_STORAGE_ENGINE
-  /* also check the table to be exchanged with the partition */
-  DBUG_ASSERT(alter_info.flags & ALTER_EXCHANGE_PARTITION);
 
-  if (check_access(thd, priv_needed, first_table->db,
-                   &first_table->grant.privilege,
-                   &first_table->grant.m_internal,
-                   0, 0) ||
-      check_access(thd, priv_needed, first_table->next_local->db,
-                   &first_table->next_local->grant.privilege,
-                   &first_table->next_local->grant.m_internal,
-                   0, 0))
-    DBUG_RETURN(TRUE);
-  if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
-    DBUG_RETURN(TRUE);
+  result= mysql_alter_table(thd, select_lex->db, lex->name.str, &create_info,
+                            first_table, &alter_info,
+                            select_lex->order_list.elements,
+                            (ORDER *) select_lex->order_list.first,
+                            lex->ignore);
 
-  /* Not allowed with EXCHANGE PARTITION */
-  DBUG_ASSERT(!create_info.data_file_name && !create_info.index_file_name);
-
-  thd->enable_slow_log= opt_log_slow_admin_statements;
-  DBUG_RETURN(mysql_exchange_partition(thd, first_table, &alter_info,
-                                       lex->ignore));
-#else
-  /* error, partitioning support not compiled in... */
-  my_error(ER_FEATURE_DISABLED, MYF(0), "partitioning",
-      "--with-plugin-partition");
-  DBUG_RETURN(TRUE);
-#endif
+  DBUG_RETURN(result);
 }

=== modified file 'sql/sql_alter_table.h'
--- a/sql/sql_alter_table.h	2010-06-07 11:29:54 +0000
+++ b/sql/sql_alter_table.h	2010-06-10 03:52:16 +0000
@@ -11,7 +11,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 #ifndef SQL_ALTER_TABLE_H
 #define SQL_ALTER_TABLE_H
@@ -63,31 +63,4 @@ public:
   bool execute(THD *thd);
 };
 
-/**
-  Alter_table_exchange_partition_statement represents the 
-  ALTER TABLE t EXCHANGE PARTITION p WITH TABLE t2 statement.
-*/
-class Alter_table_exchange_partition_statement : public Alter_table_common
-{
-public:
-  /**
-    Constructor, used to represent a ALTER TABLE EXCHANGE PARTITION statement.
-    @param lex the LEX structure for this statement.
-  */
-  Alter_table_exchange_partition_statement(LEX *lex)
-    : Alter_table_common(lex)
-  {}
-
-  ~Alter_table_exchange_partition_statement()
-  {}
-
-  /**
-    Execute a ALTER TABLE EXCHANGE PARTITION statement at runtime.
-    @param thd the current thread.
-    @return false on success.
-  */
-  bool execute(THD *thd);
-};
-
-
 #endif

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2010-05-14 18:38:28 +0000
+++ b/sql/sql_lex.cc	2010-06-10 03:52:16 +0000
@@ -396,6 +396,7 @@ void lex_start(THD *thd)
   lex->spname= NULL;
   lex->sphead= NULL;
   lex->spcont= NULL;
+  lex->m_stmt= NULL;
   lex->proc_list.first= 0;
   lex->escape_used= FALSE;
   lex->query_tables= 0;

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-05-21 09:49:46 +0000
+++ b/sql/sql_lex.h	2010-06-10 03:52:16 +0000
@@ -927,6 +927,24 @@ enum enum_alter_table_change_level
   ALTER_TABLE_INDEX_CHANGED= 2
 };
 
+
+/**
+  Temporary hack to enable a class bound forward declaration
+  of the enum_alter_table_change_level enumeration. To be
+  removed once Alter_info is moved ta the sql_alter_table.h
+  header.
+*/
+class Alter_table_change_level
+{
+private:
+  typedef enum enum_alter_table_change_level enum_type;
+  enum_type value;
+public:
+  void operator = (enum_type v) { value = v; }
+  operator enum_type () { return value; }
+};
+
+
 /**
   @brief Parsing data for CREATE or ALTER TABLE.
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-06-07 11:29:54 +0000
+++ b/sql/sql_parse.cc	2010-06-10 03:52:16 +0000
@@ -1460,8 +1460,6 @@ bool dispatch_command(enum enum_server_c
   dec_thread_running();
   thd_proc_info(thd, 0);
   thd->packet.shrink(thd->variables.net_buffer_length);	// Reclaim some memory
-  /* if there was a Sql_statment, it will be released in free_root */
-  thd->lex->m_stmt= NULL;
   free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
 
 #if defined(ENABLED_PROFILING)
@@ -7706,6 +7704,7 @@ bool parse_sql(THD *thd,
 {
   bool ret_value;
   DBUG_ASSERT(thd->m_parser_state == NULL);
+  DBUG_ASSERT(thd->lex->m_stmt == NULL);
 
   MYSQL_QUERY_PARSE_START(thd->query());
   /* Backup creation context. */

=== added file 'sql/sql_partition_admin.cc'
--- a/sql/sql_partition_admin.cc	1970-01-01 00:00:00 +0000
+++ b/sql/sql_partition_admin.cc	2010-06-10 03:52:16 +0000
@@ -0,0 +1,632 @@
+/* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+#include "sql_parse.h"                      // check_access,
+                                            // check_merge_table_access
+#include "sql_table.h"                      // mysql_alter_table, etc.
+#include "sql_alter_table.h"                // Alter_table_statement
+#include "sql_partition_admin.h"            // Alter_table_exchange_*
+#include "sql_partition.h"                  // struct partition_info, etc.
+#include "sql_handler.h"                    // mysql_ha_rm_tables
+#include "sql_base.h"                       // open_and_lock_tables, etc
+#include "lock.h"                           // MYSQL_OPEN_TAKE_UPGRADABLE_MDL
+#include "debug_sync.h"                     // DEBUG_SYNC
+
+#ifndef WITH_PARTITION_STORAGE_ENGINE
+
+bool Partition_statement_unsupported::execute(THD *)
+{
+  /* error, partitioning support not compiled in... */
+  my_error(ER_FEATURE_DISABLED, MYF(0), "partitioning",
+           "--with-plugin-partition");
+  DBUG_RETURN(TRUE);
+}
+
+#else
+
+bool Alter_table_exchange_partition_statement::execute(THD *thd)
+{
+  /* Moved from mysql_execute_command */
+  LEX *lex= thd->lex;
+  /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
+  SELECT_LEX *select_lex= &lex->select_lex;
+  /* first table of first SELECT_LEX */
+  TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
+  /*
+    Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
+    so we have to use a copy of this structure to make execution
+    prepared statement- safe. A shallow copy is enough as no memory
+    referenced from this structure will be modified.
+    @todo move these into constructor...
+  */
+  HA_CREATE_INFO create_info(lex->create_info);
+  Alter_info alter_info(lex->alter_info, thd->mem_root);
+  ulong priv_needed= ALTER_ACL | DROP_ACL | INSERT_ACL | CREATE_ACL;
+
+  DBUG_ENTER("Alter_table_exchange_partition_statement::execute");
+
+  if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
+    DBUG_RETURN(TRUE);
+
+  /* Must be set in the parser */
+  DBUG_ASSERT(select_lex->db);
+  /* also check the table to be exchanged with the partition */
+  DBUG_ASSERT(alter_info.flags & ALTER_EXCHANGE_PARTITION);
+
+  if (check_access(thd, priv_needed, first_table->db,
+                   &first_table->grant.privilege,
+                   &first_table->grant.m_internal,
+                   0, 0) ||
+      check_access(thd, priv_needed, first_table->next_local->db,
+                   &first_table->next_local->grant.privilege,
+                   &first_table->next_local->grant.m_internal,
+                   0, 0))
+    DBUG_RETURN(TRUE);
+
+  if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
+    DBUG_RETURN(TRUE);
+
+  /* Not allowed with EXCHANGE PARTITION */
+  DBUG_ASSERT(!create_info.data_file_name && !create_info.index_file_name);
+
+  thd->enable_slow_log= opt_log_slow_admin_statements;
+  DBUG_RETURN(exchange_partition(thd, first_table, &alter_info));
+}
+
+
+/**
+  @brief Checks that the tables will be able to be used for EXCHANGE PARTITION.
+  @param table      Non partitioned table.
+  @param part_table Partitioned table.
+
+  @retval FALSE if OK, otherwise error is reported and TRUE is returned.
+*/
+static bool check_exchange_partition(TABLE *table, TABLE *part_table)
+{
+  DBUG_ENTER("check_exchange_partition");
+
+  /* Both tables must exist */
+  if (!part_table || !table)
+  {
+    my_error(ER_CHECK_NO_SUCH_TABLE, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  /* The first table must be partitioned, and the second must not */
+  if (!part_table->part_info)
+  {
+    my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+  if (table->part_info)
+  {
+    my_error(ER_PARTITION_EXCHANGE_PART_TABLE, MYF(0),
+             table->s->table_name.str);
+    DBUG_RETURN(TRUE);
+  }
+
+  if (part_table->file->ht != partition_hton)
+  {
+    /*
+      Only allowed on partitioned tables throught the generic ha_partition
+      handler, i.e not yet for native partitioning (NDB).
+    */
+    my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  if (table->file->ht != part_table->part_info->default_engine_type)
+  {
+    my_error(ER_MIX_HANDLER_ERROR, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  /* Verify that table is not tmp table, partitioned tables cannot be tmp. */
+  if (table->s->tmp_table != NO_TMP_TABLE)
+  {
+    my_error(ER_PARTITION_EXCHANGE_TEMP_TABLE, MYF(0),
+             table->s->table_name.str);
+    DBUG_RETURN(TRUE);
+  }
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  @brief Compare table structure/options between a non partitioned table
+  and a specific partition of a partitioned table.
+
+  @param thd        Thread object.
+  @param table      Non partitioned table.
+  @param part_table Partitioned table.
+  @param part_elem  Partition element to use for partition specific compare.
+*/
+static bool compare_table_with_partition(THD *thd, TABLE *table,
+                                         TABLE *part_table,
+                                         partition_element *part_elem)
+{
+  HA_CREATE_INFO table_create_info, part_create_info;
+  Alter_info part_alter_info;
+  Alter_table_change_level alter_change_level;
+  /* Unused */
+  KEY *key_info_buffer;
+  uint *index_drop_buffer, index_drop_count;
+  uint *index_add_buffer, index_add_count;
+  uint candidate_key_count= 0;
+  DBUG_ENTER("compare_table_with_partition");
+
+  alter_change_level= ALTER_TABLE_METADATA_ONLY;
+  bzero(&part_create_info, sizeof(HA_CREATE_INFO));
+  bzero(&table_create_info, sizeof(HA_CREATE_INFO));
+
+  update_create_info_from_table(&table_create_info, table);
+  /* get the current auto_increment value */
+  table->file->update_create_info(&table_create_info);
+  if (mysql_prepare_alter_table(thd, part_table, &part_create_info,
+                                &part_alter_info))
+  {
+    my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+  /* db_type is not set in prepare_alter_table */
+  part_create_info.db_type= part_table->part_info->default_engine_type;
+  /*
+    Since we exchange the partition with the table, allow exchanging
+    auto_increment value as well.
+  */
+  part_create_info.auto_increment_value=
+                                table_create_info.auto_increment_value;
+
+  /*
+    NOTE: ha_blackhole does not support check_if_compatible_data,
+    so this always fail for blackhole tables.
+    ha_myisam compares pointers to verify that DATA/INDEX DIRECTORY is
+    the same, so any table using data/index_file_name will fail.
+  */
+  if (mysql_compare_tables(table, &part_alter_info, &part_create_info,
+                           0, &alter_change_level, &key_info_buffer,
+                           &index_drop_buffer, &index_drop_count,
+                           &index_add_buffer, &index_add_count,
+                           &candidate_key_count, TRUE))
+  {
+    my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  DEBUG_SYNC(thd, "swap_partition_after_compare_tables");
+  if (alter_change_level != ALTER_TABLE_METADATA_ONLY)
+  {
+    my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  if (table_create_info.avg_row_length != part_create_info.avg_row_length)
+  {
+    my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0),
+             "AVG_ROW_LENGTH");
+    DBUG_RETURN(TRUE);
+  }
+
+  if (table_create_info.table_options != part_create_info.table_options)
+  {
+    my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0),
+             "TABLE OPTION");
+    DBUG_RETURN(TRUE);
+  }
+
+  if (table->s->table_charset != part_table->s->table_charset)
+  {
+    my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0),
+             "CHARACTER SET");
+    DBUG_RETURN(TRUE);
+  }
+
+  /*
+    NOTE: We do not support update of frm-file, i.e. change
+    max/min_rows, data/index_file_name etc.
+    The workaround is to use REORGANIZE PARTITION to rewrite
+    the frm file and then use EXCHANGE PARTITION when they are the same.
+  */
+  if (compare_partition_options(&table_create_info, part_elem))
+    DBUG_RETURN(TRUE);
+
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  @brief Exchange partition/table with ddl log.
+
+  @details How to handle a crash in the middle of the rename (break on error):
+  1) register in ddl_log that we are going to exchange swap_table with part.
+  2) do the first rename (swap_table -> tmp-name) and sync the ddl_log.
+  3) do the second rename (part -> swap_table) and sync the ddl_log.
+  4) do the last rename (tmp-name -> part).
+  5) mark the entry done.
+
+  Recover by:
+    5) is done, All completed. Nothing to recover.
+    4) is done see 3). (No mark or sync in the ddl_log...)
+    3) is done -> try rename part -> tmp-name (ignore failure) goto 2).
+    2) is done -> try rename swap_table -> part (ignore failure) goto 1).
+    1) is done -> try rename tmp-name -> swap_table (ignore failure).
+    before 1) Nothing to recover...
+
+  @param thd        Thread handle
+  @param name       name of table/partition 1 (to be exchanged with 2)
+  @param from_name  name of table/partition 2 (to be exchanged with 1)
+  @param tmp_name   temporary name to use while exchaning
+  @param ht         handlerton of the table/partitions
+
+  @return Operation status
+    @retval TRUE    Error
+    @retval FALSE   Success
+
+  @note ha_heap always succeeds in rename (since it is created upon usage).
+  This is OK when to recover from a crash since all heap are empty and the
+  recover is done early in the startup of the server (right before
+  read_init_file which can populate the tables).
+
+  And if no crash we can trust the syncs in the ddl_log.
+
+  What about if the rename is put into a background thread? That will cause
+  corruption and is avoided by the exlusive metadata lock.
+*/
+static bool exchange_name_with_ddl_log(THD *thd,
+                                       const char *name,
+                                       const char *from_name,
+                                       const char *tmp_name,
+                                       handlerton *ht)
+{
+  DDL_LOG_ENTRY exchange_entry;
+  DDL_LOG_MEMORY_ENTRY *log_entry= NULL;
+  DDL_LOG_MEMORY_ENTRY *exec_log_entry= NULL;
+  bool error= TRUE;
+  bool error_set= FALSE;
+  handler *file= NULL;
+  DBUG_ENTER("exchange_name_with_ddl_log");
+
+  if (!(file= get_new_handler(NULL, thd->mem_root, ht)))
+  {
+    mem_alloc_error(sizeof(handler));
+    DBUG_RETURN(TRUE);
+  }
+
+  /* prepare the action entry */
+  exchange_entry.entry_type=   DDL_LOG_ENTRY_CODE;
+  exchange_entry.action_type=  DDL_LOG_EXCHANGE_ACTION;
+  exchange_entry.next_entry=   0;
+  exchange_entry.name=         name;
+  exchange_entry.from_name=    from_name;
+  exchange_entry.tmp_name=     tmp_name;
+  exchange_entry.handler_name= ha_resolve_storage_engine_name(ht);
+  exchange_entry.phase=        EXCH_PHASE_NAME_TO_TEMP;
+
+  mysql_mutex_lock(&LOCK_gdl);
+  /*
+    write to the ddl log what to do by:
+    1) write the action entry (i.e. which names to be exchanged)
+    2) write the execution entry with a link to the action entry
+  */
+  DBUG_EXECUTE_IF("exchange_partition_fail_1", goto err_no_action_written;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_1", abort(););
+  if (write_ddl_log_entry(&exchange_entry, &log_entry))
+    goto err_no_action_written;
+
+  DBUG_EXECUTE_IF("exchange_partition_fail_2", goto err_no_execute_written;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_2", abort(););
+  if (write_execute_ddl_log_entry(log_entry->entry_pos, FALSE, &exec_log_entry))
+    goto err_no_execute_written;
+  /* ddl_log is written and synced */
+
+  mysql_mutex_unlock(&LOCK_gdl);
+  /*
+    Execute the name exchange.
+    Do one rename, increase the phase, update the action entry and sync.
+    In case of errors in the ddl_log we must fail and let the ddl_log try
+    to revert the changes, since otherwise it could revert the command after
+    we sent OK to the client.
+  */
+  /* call rename table from table to tmp-name */
+  DBUG_EXECUTE_IF("exchange_partition_fail_3",
+                  my_error(ER_ERROR_ON_RENAME, MYF(0),
+                           name, tmp_name);
+                  error_set= TRUE;
+                  goto err_rename;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_3", abort(););
+  if (file->ha_rename_table(name, tmp_name))
+  {
+    my_error(ER_ERROR_ON_RENAME, MYF(0),
+             name, tmp_name);
+    error_set= TRUE;
+    goto err_rename;
+  }
+  DBUG_EXECUTE_IF("exchange_partition_fail_4", goto err_rename;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_4", abort(););
+  if (deactivate_ddl_log_entry(log_entry->entry_pos))
+    goto err_rename;
+
+  /* call rename table from partition to table */
+  DBUG_EXECUTE_IF("exchange_partition_fail_5",
+                  my_error(ER_ERROR_ON_RENAME, MYF(0),
+                           from_name, name);
+                  error_set= TRUE;
+                  goto err_rename;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_5", abort(););
+  if (file->ha_rename_table(from_name, name))
+  {
+    my_error(ER_ERROR_ON_RENAME, MYF(0),
+             from_name, name);
+    error_set= TRUE;
+    goto err_rename;
+  }
+  DBUG_EXECUTE_IF("exchange_partition_fail_6", goto err_rename;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_6", abort(););
+  if (deactivate_ddl_log_entry(log_entry->entry_pos))
+    goto err_rename;
+
+  /* call rename table from tmp-nam to partition */
+  DBUG_EXECUTE_IF("exchange_partition_fail_7",
+                  my_error(ER_ERROR_ON_RENAME, MYF(0),
+                           tmp_name, from_name);
+                  error_set= TRUE;
+                  goto err_rename;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_7", abort(););
+  if (file->ha_rename_table(tmp_name, from_name))
+  {
+    my_error(ER_ERROR_ON_RENAME, MYF(0),
+             tmp_name, from_name);
+    error_set= TRUE;
+    goto err_rename;
+  }
+  DBUG_EXECUTE_IF("exchange_partition_fail_8", goto err_rename;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_8", abort(););
+  if (deactivate_ddl_log_entry(log_entry->entry_pos))
+    goto err_rename;
+
+  /* The exchange is complete and ddl_log is deactivated */
+  DBUG_EXECUTE_IF("exchange_partition_fail_9", goto err_rename;);
+  DBUG_EXECUTE_IF("exchange_partition_abort_9", abort(););
+  /* all OK */
+  error= FALSE;
+  delete file;
+  DBUG_RETURN(error);
+err_rename:
+  /*
+    Nothing to do if any of these commands fails :( the commands itselfs
+    will log to the error log about the failures...
+  */
+  /* execute the ddl log entry to revert the renames */
+  (void) execute_ddl_log_entry(current_thd, log_entry->entry_pos);
+  mysql_mutex_lock(&LOCK_gdl);
+  /* mark the execute log entry done */
+  (void) write_execute_ddl_log_entry(0, TRUE, &exec_log_entry);
+  /* release the execute log entry */
+  (void) release_ddl_log_memory_entry(exec_log_entry);
+err_no_execute_written:
+  /* release the action log entry */
+  (void) release_ddl_log_memory_entry(log_entry);
+err_no_action_written:
+  mysql_mutex_unlock(&LOCK_gdl);
+  delete file;
+  if (!error_set)
+    my_error(ER_DDL_LOG_ERROR, MYF(0));
+  DBUG_RETURN(error);
+}
+
+
+/**
+  @brief Swap places between a partition and a table.
+
+  @details Verify that the tables are compatible (same engine, definition etc),
+  if not IGNORE is given, verify that all rows in the table will fit in the
+  partition, if all OK, rename table to tmp name, rename partition to table
+  and finally rename tmp name to partition.
+
+  1) Take upgradable mdl, open tables and then lock them (inited in parse)
+  2) Verify that metadata matches
+  3) If not ignore, verify data
+  4) Upgrade to exclusive mdl for both tables
+  5) Rename table <-> partition
+  6) Rely on close_thread_tables to release mdl and table locks
+
+  @param thd            Thread handle
+  @param table_list     Table where the partition exists as first table,
+                        Table to swap with the partition as second table
+  @param alter_info     Contains partition name to swap
+  @param ignore         flag to skip verification of partition values
+
+  @note This is a DDL operation so triggers will not be used.
+*/
+bool Alter_table_exchange_partition_statement::
+  exchange_partition(THD *thd, TABLE_LIST *table_list, Alter_info *alter_info)
+{
+  TABLE *part_table, *swap_table;
+  TABLE_LIST *swap_table_list;
+  handlerton *table_hton;
+  partition_element *part_elem;
+  char *partition_name;
+  char temp_name[FN_REFLEN+1];
+  char part_file_name[FN_REFLEN+1];
+  char swap_file_name[FN_REFLEN+1];
+  char temp_file_name[FN_REFLEN+1];
+  uint swap_part_id;
+  uint part_file_name_len;
+  Alter_table_prelocking_strategy alter_prelocking_strategy(alter_info);
+  MDL_ticket *swap_table_mdl_ticket= NULL;
+  MDL_ticket *part_table_mdl_ticket= NULL;
+  bool error= TRUE, ignore= m_lex->ignore;
+  DBUG_ENTER("mysql_exchange_partition");
+  DBUG_ASSERT(alter_info->flags & ALTER_EXCHANGE_PARTITION);
+
+  partition_name= alter_info->partition_names.head();
+
+  /* Clear open tables from the threads table handler cache */
+  mysql_ha_rm_tables(thd, table_list);
+
+  /* Don't allow to exchange with log table */
+  swap_table_list= table_list->next_local;
+  if (check_if_log_table(swap_table_list->db_length, swap_table_list->db,
+                         swap_table_list->table_name_length,
+                         swap_table_list->table_name, 0))
+  {
+    my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
+    DBUG_RETURN(TRUE);
+  }
+
+  /*
+    Currently no MDL lock that allows both read and write and is upgradeable
+    to exclusive, so leave the lock type to TL_WRITE_ALLOW_READ also on the
+    partitioned table.
+
+    TODO: add MDL lock that allows both read and write and is upgradable to
+    exclusive lock. This would allow to continue using the partitioned table
+    also with update/insert/delete while the verification of the swap table
+    is running.
+  */
+
+  /*
+    NOTE: It is not possible to exchange a crashed partition/table since
+    we need some info from the engine, which we can only access after open,
+    to be able to verify the structure/metadata.
+  */
+  if (open_and_lock_tables(thd, table_list, FALSE,
+                           MYSQL_OPEN_TAKE_UPGRADABLE_MDL,
+                           &alter_prelocking_strategy))
+    DBUG_RETURN(TRUE);
+
+  part_table= table_list->table;
+  swap_table= swap_table_list->table;
+  table_hton= swap_table->file->ht;
+
+  if (check_exchange_partition(swap_table, part_table))
+    DBUG_RETURN(TRUE);
+
+  thd_proc_info(thd, "verifying table");
+
+  /* Will append the partition name later in part_info->get_part_elem() */
+  part_file_name_len= build_table_filename(part_file_name,
+                                           sizeof(part_file_name),
+                                           table_list->db,
+                                           table_list->table_name,
+                                           "", 0);
+  build_table_filename(swap_file_name,
+                       sizeof(swap_file_name),
+                       swap_table_list->db,
+                       swap_table_list->table_name,
+                       "", 0);
+  /* create a unique temp name #sqlx-nnnn_nnnn, x for eXchange */
+  my_snprintf(temp_name, sizeof(temp_name), "%sx-%lx_%lx",
+              tmp_file_prefix, current_pid, thd->thread_id);
+  if (lower_case_table_names)
+    my_casedn_str(files_charset_info, temp_name);
+  build_table_filename(temp_file_name, sizeof(temp_file_name),
+                       table_list->next_local->db,
+                       temp_name, "", FN_IS_TMP);
+
+  if (!(part_elem= part_table->part_info->get_part_elem(partition_name,
+                                                        part_file_name +
+                                                          part_file_name_len,
+                                                        &swap_part_id)))
+  {
+    my_error(ER_UNKNOWN_PARTITION, MYF(0), partition_name,
+             part_table->alias);
+    DBUG_RETURN(TRUE);
+  }
+
+  if (swap_part_id == NOT_A_PARTITION_ID)
+  {
+    DBUG_ASSERT(part_table->part_info->is_sub_partitioned());
+    my_error(ER_PARTITION_INSTEAD_OF_SUBPARTITION, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
+  if (compare_table_with_partition(thd, swap_table, part_table, part_elem))
+    DBUG_RETURN(TRUE);
+
+  /* Table and partition has same structure/options, OK to exchange */
+
+  if (!ignore)
+  {
+    if (verify_data_with_partition(swap_table, part_table, swap_part_id))
+      DBUG_RETURN(TRUE);
+  }
+
+  /*
+    Get exclusive mdl lock on both tables, alway the non partitioned table
+    first. Remember the tickets for downgrading locks later.
+  */
+  swap_table_mdl_ticket= swap_table->mdl_ticket;
+  part_table_mdl_ticket= part_table->mdl_ticket;
+
+  /*
+    No need to set used_partitions to only propagate
+    HA_EXTRA_PREPARE_FOR_RENAME to one part since no built in engine uses
+    that flag. And the action would probably be to force close all other
+    instances which is what we are doing any way.
+  */
+  if (wait_while_table_is_used(thd, swap_table, HA_EXTRA_PREPARE_FOR_RENAME) ||
+      wait_while_table_is_used(thd, part_table, HA_EXTRA_PREPARE_FOR_RENAME))
+    goto err;
+
+  DEBUG_SYNC(thd, "swap_partition_after_wait");
+
+  close_all_tables_for_name(thd, swap_table->s, FALSE);
+  close_all_tables_for_name(thd, part_table->s, FALSE);
+
+  DEBUG_SYNC(thd, "swap_partition_before_rename");
+
+  if (exchange_name_with_ddl_log(thd, swap_file_name, part_file_name,
+                                 temp_file_name, table_hton))
+    goto err;
+
+  /*
+    Reopen tables under LOCK TABLES. Ignore the return value for now. It's
+    better to keep master/slave in consistent state. Alternative would be to
+    try to revert the exchange operation and issue error.
+  */
+  (void) thd->locked_tables_list.reopen_tables(thd);
+
+  if ((error= write_bin_log(thd, TRUE, thd->query(), thd->query_length())))
+  {
+    /*
+      The error is reported in write_bin_log().
+      We try to revert to make it easier to keep the master/slave in sync.
+    */
+    (void) exchange_name_with_ddl_log(thd, part_file_name, swap_file_name,
+                                      temp_file_name, table_hton);
+  }
+
+err:
+  if (thd->locked_tables_mode)
+  {
+    if (swap_table_mdl_ticket)
+      swap_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+    if (part_table_mdl_ticket)
+      part_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+  }
+
+  if (!error)
+    my_ok(thd);
+
+  // For query cache
+  table_list->table= NULL;
+  table_list->next_local->table= NULL;
+  query_cache_invalidate3(thd, table_list, FALSE);
+
+  DBUG_RETURN(error);
+}
+
+#endif /* WITH_PARTITION_STORAGE_ENGINE */

=== added file 'sql/sql_partition_admin.h'
--- a/sql/sql_partition_admin.h	1970-01-01 00:00:00 +0000
+++ b/sql/sql_partition_admin.h	2010-06-10 03:52:16 +0000
@@ -0,0 +1,82 @@
+/* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+#ifndef SQL_PARTITION_ADMIN_H
+#define SQL_PARTITION_ADMIN_H
+
+#ifndef WITH_PARTITION_STORAGE_ENGINE
+
+/**
+  Stub class that returns a error if the partition storage engine is
+  not supported.
+*/
+class Partition_statement_unsupported : public Alter_table_common
+{
+public:
+  Partition_statement_unsupported(LEX *lex)
+    : Alter_table_common(lex)
+  {}
+
+  ~Partition_statement_unsupported()
+  {}
+
+  bool execute(THD *thd);
+};
+
+class Alter_table_exchange_partition_statement :
+  public Partition_statement_unsupported
+{
+public:
+  Alter_table_exchange_partition_statement(LEX *lex)
+    : Partition_statement_unsupported(lex)
+  {}
+
+  ~Alter_table_exchange_partition_statement()
+  {}
+};
+
+#else
+
+/**
+  Class that represents the ALTER TABLE t1 EXCHANGE PARTITION p
+                            WITH TABLE t2 statement.
+*/
+class Alter_table_exchange_partition_statement : public Alter_table_common
+{
+public:
+  /**
+    Constructor, used to represent a ALTER TABLE EXCHANGE PARTITION statement.
+    @param lex the LEX structure for this statement.
+  */
+  Alter_table_exchange_partition_statement(LEX *lex)
+    : Alter_table_common(lex)
+  {}
+
+  ~Alter_table_exchange_partition_statement()
+  {}
+
+  /**
+    Execute a ALTER TABLE EXCHANGE PARTITION statement at runtime.
+    @param thd the current thread.
+    @return false on success.
+  */
+  bool execute(THD *thd);
+
+private:
+  bool exchange_partition(THD *thd, TABLE_LIST *, Alter_info *);
+};
+
+#endif /* WITH_PARTITION_STORAGE_ENGINE */
+#endif /* SQL_PARTITION_ADMIN_H */

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-06-03 21:00:55 +0000
+++ b/sql/sql_table.cc	2010-06-10 03:52:16 +0000
@@ -80,10 +80,6 @@ mysql_prepare_create_table(THD *thd, HA_
                            uint *db_options,
                            handler *file, KEY **key_info_buffer,
                            uint *key_count, int select_field_count);
-static bool
-mysql_prepare_alter_table(THD *thd, TABLE *table,
-                          HA_CREATE_INFO *create_info,
-                          Alter_info *alter_info);
 
 #ifndef DBUG_OFF
 
@@ -5194,7 +5190,7 @@ send_result_message:
         /* Clear the ticket released in close_thread_tables(). */
         table->mdl_request.ticket= NULL;
         DEBUG_SYNC(thd, "ha_admin_open_ltable");
-        if (table->table= open_ltable(thd, table, lock_type, 0))
+        if ((table->table= open_ltable(thd, table, lock_type, 0)))
         {
           result_code= table->table->file->ha_analyze(thd, check_opt);
           if (result_code == HA_ADMIN_ALREADY_DONE)
@@ -5756,17 +5752,16 @@ is_index_maintenance_unique (TABLE *tabl
     FALSE  success
 */
 
-static
 bool
-compare_tables(TABLE *table,
-               Alter_info *alter_info,
-               HA_CREATE_INFO *create_info,
-               uint order_num,
-               enum_alter_table_change_level *need_copy_table,
-               KEY **key_info_buffer,
-               uint **index_drop_buffer, uint *index_drop_count,
-               uint **index_add_buffer, uint *index_add_count,
-               uint *candidate_key_count, bool exact_match)
+mysql_compare_tables(TABLE *table,
+                     Alter_info *alter_info,
+                     HA_CREATE_INFO *create_info,
+                     uint order_num,
+                     Alter_table_change_level *need_copy_table,
+                     KEY **key_info_buffer,
+                     uint **index_drop_buffer, uint *index_drop_count,
+                     uint **index_add_buffer, uint *index_add_count,
+                     uint *candidate_key_count, bool exact_match)
 {
   Field **f_ptr, *field;
   uint changes= 0, tmp;
@@ -5782,7 +5777,7 @@ compare_tables(TABLE *table,
   */
   bool varchar= create_info->varchar;
   bool not_nullable= true;
-  DBUG_ENTER("compare_tables");
+  DBUG_ENTER("mysql_compare_tables");
 
   /*
     Create a copy of alter_info.
@@ -6185,7 +6180,7 @@ blob_length_by_type(enum_field_types typ
   @retval FALSE  success
 */
 
-static bool
+bool
 mysql_prepare_alter_table(THD *thd, TABLE *table,
                           HA_CREATE_INFO *create_info,
                           Alter_info *alter_info)
@@ -6561,558 +6556,6 @@ err:
 }
 
 
-#ifdef WITH_PARTITION_STORAGE_ENGINE
-/**
-  @brief Checks that the tables will be able to be used for EXCHANGE PARTITION.
-  @param table      Non partitioned table.
-  @param part_table Partitioned table.
-
-  @retval FALSE if OK, otherwise error is reported and TRUE is returned.
-*/
-static bool check_exchange_partition(TABLE *table, TABLE *part_table)
-{
-  DBUG_ENTER("check_exchange_partition");
-
-  /* Both tables must exist */
-  if (!part_table || !table)
-  {
-    my_error(ER_CHECK_NO_SUCH_TABLE, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-
-  /* The first table must be partitioned, and the second must not */
-  if (!part_table->part_info)
-  {
-    my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-  if (table->part_info)
-  {
-    my_error(ER_PARTITION_EXCHANGE_PART_TABLE, MYF(0),
-             table->s->table_name.str);
-    DBUG_RETURN(TRUE);
-  }
-
-  if (part_table->file->ht != partition_hton)
-  {
-    /*
-      Only allowed on partitioned tables throught the generic ha_partition
-      handler, i.e not yet for native partitioning (NDB).
-    */
-    my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-
-  if (table->file->ht != part_table->part_info->default_engine_type)
-  {
-    my_error(ER_MIX_HANDLER_ERROR, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-
-  /* Verify that table is not tmp table, partitioned tables cannot be tmp. */
-  if (table->s->tmp_table != NO_TMP_TABLE)
-  {
-    my_error(ER_PARTITION_EXCHANGE_TEMP_TABLE, MYF(0),
-             table->s->table_name.str);
-    DBUG_RETURN(TRUE);
-  }
-  DBUG_RETURN(FALSE);
-}
-
-
-/**
-  @brief Compare table structure/options between a non partitioned table
-  and a specific partition of a partitioned table.
-
-  @param thd        Thread object.
-  @param table      Non partitioned table.
-  @param part_table Partitioned table.
-  @param part_elem  Partition element to use for partition specific compare.
-*/
-static bool compare_table_with_partition(THD *thd, TABLE *table,
-                                         TABLE *part_table,
-                                         partition_element *part_elem)
-{
-  HA_CREATE_INFO table_create_info, part_create_info;
-  Alter_info part_alter_info;
-  enum_alter_table_change_level alter_change_level;
-  /* Unused */
-  KEY *key_info_buffer;
-  uint *index_drop_buffer, index_drop_count;
-  uint *index_add_buffer, index_add_count;
-  uint candidate_key_count= 0;
-  DBUG_ENTER("compare_table_with_partition");
-
-  alter_change_level= ALTER_TABLE_METADATA_ONLY;
-  part_alter_info.change_level= alter_change_level;
-  bzero(&part_create_info, sizeof(HA_CREATE_INFO));
-  bzero(&table_create_info, sizeof(HA_CREATE_INFO));
-  
-  update_create_info_from_table(&table_create_info, table);
-  /* get the current auto_increment value */
-  table->file->update_create_info(&table_create_info);
-  if (mysql_prepare_alter_table(thd, part_table, &part_create_info,
-                                &part_alter_info))
-  {
-    my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-  /* db_type is not set in prepare_alter_table */
-  part_create_info.db_type= part_table->part_info->default_engine_type;
-  /*
-    Since we exchange the partition with the table, allow exchanging
-    auto_increment value as well.
-  */
-  part_create_info.auto_increment_value=
-                                table_create_info.auto_increment_value;
-
-  /*
-    NOTE: ha_blackhole does not support check_if_compatible_data,
-    so this always fail for blackhole tables.
-    ha_myisam compares pointers to verify that DATA/INDEX DIRECTORY is
-    the same, so any table using data/index_file_name will fail.
-  */
-  if (compare_tables(table, &part_alter_info, &part_create_info,
-                     0, &alter_change_level, &key_info_buffer,
-                     &index_drop_buffer, &index_drop_count,
-                     &index_add_buffer, &index_add_count,
-                     &candidate_key_count, TRUE))
-  {
-    my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-
-  DEBUG_SYNC(thd, "swap_partition_after_compare_tables");
-  if (alter_change_level != ALTER_TABLE_METADATA_ONLY)
-  {
-    my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-
-  if (table_create_info.avg_row_length != part_create_info.avg_row_length)
-  {
-    my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0),
-             "AVG_ROW_LENGTH");
-    DBUG_RETURN(TRUE);
-  }
-
-  if (table_create_info.table_options != part_create_info.table_options)
-  {
-    my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0),
-             "TABLE OPTION");
-    DBUG_RETURN(TRUE);
-  }
-
-  if (table->s->table_charset != part_table->s->table_charset)
-  {
-    my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0),
-             "CHARACTER SET");
-    DBUG_RETURN(TRUE);
-  }
- 
-  /*
-    NOTE: We do not support update of frm-file, i.e. change
-    max/min_rows, data/index_file_name etc.
-    The workaround is to use REORGANIZE PARTITION to rewrite
-    the frm file and then use EXCHANGE PARTITION when they are the same.
-  */
-  if (compare_partition_options(&table_create_info, part_elem))
-    DBUG_RETURN(TRUE);
-
-  DBUG_RETURN(FALSE);
-}
-
-
-/**
-  @brief Exchange partition/table with ddl log.
-
-  @details How to handle a crash in the middle of the rename (break on error):
-  1) register in ddl_log that we are going to exchange swap_table with part.
-  2) do the first rename (swap_table -> tmp-name) and sync the ddl_log.
-  3) do the second rename (part -> swap_table) and sync the ddl_log.
-  4) do the last rename (tmp-name -> part).
-  5) mark the entry done.
-
-  Recover by:
-    5) is done, All completed. Nothing to recover.
-    4) is done see 3). (No mark or sync in the ddl_log...)
-    3) is done -> try rename part -> tmp-name (ignore failure) goto 2).
-    2) is done -> try rename swap_table -> part (ignore failure) goto 1).
-    1) is done -> try rename tmp-name -> swap_table (ignore failure).
-    before 1) Nothing to recover...
-
-  @param thd        Thread handle
-  @param name       name of table/partition 1 (to be exchanged with 2)
-  @param from_name  name of table/partition 2 (to be exchanged with 1)
-  @param tmp_name   temporary name to use while exchaning
-  @param ht         handlerton of the table/partitions
-
-  @return Operation status
-    @retval TRUE    Error
-    @retval FALSE   Success
-
-  @note ha_heap always succeeds in rename (since it is created upon usage).
-  This is OK when to recover from a crash since all heap are empty and the
-  recover is done early in the startup of the server (right before
-  read_init_file which can populate the tables).
-
-  And if no crash we can trust the syncs in the ddl_log.
-
-  What about if the rename is put into a background thread? That will cause
-  corruption and is avoided by the exlusive metadata lock.
-*/
-static bool exchange_name_with_ddl_log(THD *thd,
-                                       const char *name,
-                                       const char *from_name,
-                                       const char *tmp_name,
-                                       handlerton *ht)
-{
-  DDL_LOG_ENTRY exchange_entry;
-  DDL_LOG_MEMORY_ENTRY *log_entry= NULL;
-  DDL_LOG_MEMORY_ENTRY *exec_log_entry= NULL;
-  bool error= TRUE;
-  bool error_set= FALSE;
-  handler *file= NULL;
-  DBUG_ENTER("exchange_name_with_ddl_log");
-
-  if (!(file= get_new_handler(NULL, thd->mem_root, ht)))
-  {
-    mem_alloc_error(sizeof(handler));
-    DBUG_RETURN(TRUE);
-  }
-
-  /* prepare the action entry */
-  exchange_entry.entry_type=   DDL_LOG_ENTRY_CODE;
-  exchange_entry.action_type=  DDL_LOG_EXCHANGE_ACTION;
-  exchange_entry.next_entry=   0;
-  exchange_entry.name=         name;
-  exchange_entry.from_name=    from_name;
-  exchange_entry.tmp_name=     tmp_name;
-  exchange_entry.handler_name= ha_resolve_storage_engine_name(ht);
-  exchange_entry.phase=        EXCH_PHASE_NAME_TO_TEMP;
-
-  mysql_mutex_lock(&LOCK_gdl);
-  /*
-    write to the ddl log what to do by:
-    1) write the action entry (i.e. which names to be exchanged)
-    2) write the execution entry with a link to the action entry
-  */
-  DBUG_EXECUTE_IF("exchange_partition_fail_1", goto err_no_action_written;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_1", abort(););
-  if (write_ddl_log_entry(&exchange_entry, &log_entry))
-    goto err_no_action_written;
-
-  DBUG_EXECUTE_IF("exchange_partition_fail_2", goto err_no_execute_written;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_2", abort(););
-  if (write_execute_ddl_log_entry(log_entry->entry_pos, FALSE, &exec_log_entry))
-    goto err_no_execute_written;
-  /* ddl_log is written and synced */
-
-  mysql_mutex_unlock(&LOCK_gdl);
-  /*
-    Execute the name exchange.
-    Do one rename, increase the phase, update the action entry and sync.
-    In case of errors in the ddl_log we must fail and let the ddl_log try
-    to revert the changes, since otherwise it could revert the command after
-    we sent OK to the client.
-  */
-  /* call rename table from table to tmp-name */
-  DBUG_EXECUTE_IF("exchange_partition_fail_3",
-                  my_error(ER_ERROR_ON_RENAME, MYF(0),
-                           name, tmp_name);
-                  error_set= TRUE;
-                  goto err_rename;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_3", abort(););
-  if (file->ha_rename_table(name, tmp_name))
-  {
-    my_error(ER_ERROR_ON_RENAME, MYF(0),
-             name, tmp_name);
-    error_set= TRUE;
-    goto err_rename;
-  }
-  DBUG_EXECUTE_IF("exchange_partition_fail_4", goto err_rename;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_4", abort(););
-  if (deactivate_ddl_log_entry(log_entry->entry_pos))
-    goto err_rename;
-
-  /* call rename table from partition to table */
-  DBUG_EXECUTE_IF("exchange_partition_fail_5",
-                  my_error(ER_ERROR_ON_RENAME, MYF(0),
-                           from_name, name);
-                  error_set= TRUE;
-                  goto err_rename;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_5", abort(););
-  if (file->ha_rename_table(from_name, name))
-  {
-    my_error(ER_ERROR_ON_RENAME, MYF(0),
-             from_name, name);
-    error_set= TRUE;
-    goto err_rename;
-  }
-  DBUG_EXECUTE_IF("exchange_partition_fail_6", goto err_rename;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_6", abort(););
-  if (deactivate_ddl_log_entry(log_entry->entry_pos))
-    goto err_rename;
-
-  /* call rename table from tmp-nam to partition */
-  DBUG_EXECUTE_IF("exchange_partition_fail_7",
-                  my_error(ER_ERROR_ON_RENAME, MYF(0),
-                           tmp_name, from_name);
-                  error_set= TRUE;
-                  goto err_rename;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_7", abort(););
-  if (file->ha_rename_table(tmp_name, from_name))
-  {
-    my_error(ER_ERROR_ON_RENAME, MYF(0),
-             tmp_name, from_name);
-    error_set= TRUE;
-    goto err_rename;
-  }
-  DBUG_EXECUTE_IF("exchange_partition_fail_8", goto err_rename;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_8", abort(););
-  if (deactivate_ddl_log_entry(log_entry->entry_pos))
-    goto err_rename;
-
-  /* The exchange is complete and ddl_log is deactivated */
-  DBUG_EXECUTE_IF("exchange_partition_fail_9", goto err_rename;);
-  DBUG_EXECUTE_IF("exchange_partition_abort_9", abort(););
-  /* all OK */
-  error= FALSE;
-  delete file;
-  DBUG_RETURN(error);
-err_rename:
-  /*
-    Nothing to do if any of these commands fails :( the commands itselfs
-    will log to the error log about the failures...
-  */
-  /* execute the ddl log entry to revert the renames */
-  (void) execute_ddl_log_entry(current_thd, log_entry->entry_pos);
-  mysql_mutex_lock(&LOCK_gdl);
-  /* mark the execute log entry done */
-  (void) write_execute_ddl_log_entry(0, TRUE, &exec_log_entry);
-  /* release the execute log entry */
-  (void) release_ddl_log_memory_entry(exec_log_entry);
-err_no_execute_written:
-  /* release the action log entry */
-  (void) release_ddl_log_memory_entry(log_entry);
-err_no_action_written:
-  mysql_mutex_unlock(&LOCK_gdl);
-  delete file;
-  if (!error_set)
-    my_error(ER_DDL_LOG_ERROR, MYF(0));
-  DBUG_RETURN(error);
-}
-
-
-/**
-  @brief Swap places between a partition and a table.
-
-  @details Verify that the tables are compatible (same engine, definition etc),
-  if not IGNORE is given, verify that all rows in the table will fit in the
-  partition, if all OK, rename table to tmp name, rename partition to table
-  and finally rename tmp name to partition.
-
-  1) Take upgradable mdl, open tables and then lock them (inited in parse)
-  2) Verify that metadata matches
-  3) If not ignore, verify data
-  4) Upgrade to exclusive mdl for both tables
-  5) Rename table <-> partition
-  6) Rely on close_thread_tables to release mdl and table locks
-
-  @param thd            Thread handle
-  @param table_list     Table where the partition exists as first table,
-                        Table to swap with the partition as second table
-  @param alter_info     Contains partition name to swap
-  @param ignore         flag to skip verification of partition values
-
-  @note This is a DDL operation so triggers will not be used.
-*/
-bool mysql_exchange_partition(THD *thd,
-                              TABLE_LIST *table_list,
-                              Alter_info *alter_info,
-                              bool ignore)
-{
-  TABLE  *part_table, *swap_table;
-  TABLE_LIST *swap_table_list;
-  handlerton *table_hton;
-  partition_element *part_elem;
-  char *partition_name;
-  char temp_name[FN_REFLEN+1];
-  char part_file_name[FN_REFLEN+1];
-  char swap_file_name[FN_REFLEN+1];
-  char temp_file_name[FN_REFLEN+1];
-  uint swap_part_id;
-  uint part_file_name_len;
-  Alter_table_prelocking_strategy alter_prelocking_strategy(alter_info);
-  MDL_ticket *swap_table_mdl_ticket= NULL;
-  MDL_ticket *part_table_mdl_ticket= NULL;
-  DBUG_ENTER("mysql_exchange_partition");
-  DBUG_ASSERT(alter_info->flags & ALTER_EXCHANGE_PARTITION);
-
-  partition_name= alter_info->partition_names.head();
-
-  /* Clear open tables from the threads table handler cache */
-  mysql_ha_rm_tables(thd, table_list);
-
-  /* Don't allow to exchange with log table */
-  swap_table_list= table_list->next_local;
-  if (check_if_log_table(swap_table_list->db_length, swap_table_list->db,
-                         swap_table_list->table_name_length,
-                         swap_table_list->table_name, 0))
-  {
-    my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
-    DBUG_RETURN(TRUE);
-  }
-
-  /*
-    Currently no MDL lock that allows both read and write and is upgradeable
-    to exclusive, so leave the lock type to TL_WRITE_ALLOW_READ also on the 
-    partitioned table.
-
-    TODO: add MDL lock that allows both read and write and is upgradable to
-    exclusive lock. This would allow to continue using the partitioned table
-    also with update/insert/delete while the verification of the swap table
-    is running.
-  */
-
-  /*
-    NOTE: It is not possible to exchange a crashed partition/table since
-    we need some info from the engine, which we can only access after open,
-    to be able to verify the structure/metadata.
-  */
-  if (open_and_lock_tables(thd, table_list, FALSE,
-                           MYSQL_OPEN_TAKE_UPGRADABLE_MDL,
-                           &alter_prelocking_strategy))
-    goto err;
-
-  part_table= table_list->table;
-  swap_table= swap_table_list->table;
-  table_hton= swap_table->file->ht;
-
-  if (check_exchange_partition(swap_table, part_table))
-    goto err;
-
-
-  thd_proc_info(thd, "verifying table");
-
-  /* Will append the partition name later in part_info->get_part_elem() */
-  part_file_name_len= build_table_filename(part_file_name,
-                                           sizeof(part_file_name),
-                                           table_list->db,
-                                           table_list->table_name,
-                                           "", 0);
-  build_table_filename(swap_file_name,
-                       sizeof(swap_file_name),
-                       swap_table_list->db,
-                       swap_table_list->table_name,
-                       "", 0);
-  /* create a unique temp name #sqlx-nnnn_nnnn, x for eXchange */
-  my_snprintf(temp_name, sizeof(temp_name), "%sx-%lx_%lx",
-              tmp_file_prefix, current_pid, thd->thread_id);
-  if (lower_case_table_names)
-    my_casedn_str(files_charset_info, temp_name);
-  build_table_filename(temp_file_name, sizeof(temp_file_name),
-                       table_list->next_local->db,
-                       temp_name, "", FN_IS_TMP);
-
-  if (!(part_elem= part_table->part_info->get_part_elem(partition_name,
-                                                        part_file_name +
-                                                          part_file_name_len,
-                                                        &swap_part_id)))
-  {
-    my_error(ER_UNKNOWN_PARTITION, MYF(0), partition_name,
-             part_table->alias);
-    DBUG_RETURN(TRUE);
-  }
-
-  if (swap_part_id == NOT_A_PARTITION_ID)
-  {
-    DBUG_ASSERT(part_table->part_info->is_sub_partitioned());
-    my_error(ER_PARTITION_INSTEAD_OF_SUBPARTITION, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-
-  if (compare_table_with_partition(thd, swap_table, part_table, part_elem))
-    DBUG_RETURN(TRUE);
-
-  /* Table and partition has same structure/options, OK to exchange */
-
-  if (!ignore)
-  {
-    if (verify_data_with_partition(swap_table, part_table, swap_part_id))
-      DBUG_RETURN(TRUE);
-  }
-
-  /*
-    Get exclusive mdl lock on both tables, alway the non partitioned table
-    first. Remember the tickets for downgrading locks later.
-  */
-  swap_table_mdl_ticket= swap_table->mdl_ticket;
-  part_table_mdl_ticket= part_table->mdl_ticket;
-
-  /*
-    No need to set used_partitions to only propagate
-    HA_EXTRA_PREPARE_FOR_RENAME to one part since no built in engine uses
-    that flag. And the action would probably be to force close all other
-    instances which is what we are doing any way.
-  */
-  if (wait_while_table_is_used(thd, swap_table, HA_EXTRA_PREPARE_FOR_RENAME) ||
-      wait_while_table_is_used(thd, part_table, HA_EXTRA_PREPARE_FOR_RENAME))
-    goto err;
-
-  DEBUG_SYNC(thd, "swap_partition_after_wait");
-
-  close_all_tables_for_name(thd, swap_table->s, FALSE);
-  close_all_tables_for_name(thd, part_table->s, FALSE);
-  DEBUG_SYNC(thd, "swap_partition_before_rename");
-  if (exchange_name_with_ddl_log(thd, swap_file_name, part_file_name,
-                                 temp_file_name, table_hton))
-    goto err;
-  /* Skip ha_binlog_log_query since this function is not supported by NDB */
-
-  /*
-    Reopen tables under LOCK TABLES. Ignore the return value for now. It's
-    better to keep master/slave in consistent state. Alternative would be to
-    try to revert the exchange operation and issue error.
-  */
-  (void) thd->locked_tables_list.reopen_tables(thd);
-
-  if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
-  {
-    /*
-      The error is reported in write_bin_log().
-      We try to revert to make it easier to keep the master/slave in sync.
-    */
-    (void) exchange_name_with_ddl_log(thd, part_file_name, swap_file_name,
-                                      temp_file_name, table_hton);
-    goto err;
-  }
-  if (thd->locked_tables_mode)
-  {
-    if (swap_table_mdl_ticket)
-      swap_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
-    if (part_table_mdl_ticket)
-      part_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
-  }
-  my_ok(thd);
-  table_list->table= NULL;			// For query cache
-  table_list->next_local->table= NULL;
-  query_cache_invalidate3(thd, table_list, 0);
-  DBUG_RETURN(FALSE);
-err:
-  if (thd->locked_tables_mode)
-  {
-    if (swap_table_mdl_ticket)
-      swap_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
-    if (part_table_mdl_ticket)
-      part_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
-  }
-
-  DBUG_RETURN(TRUE);
-}
-#endif
-
-
 /*
   Alter table
 
@@ -7653,7 +7096,7 @@ view_err:
 
   if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
     goto err;
-  
+
   if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
     need_copy_table= alter_info->change_level;
 
@@ -7668,15 +7111,15 @@ view_err:
     need_copy_table= ALTER_TABLE_DATA_CHANGED;
   else
   {
-    enum_alter_table_change_level need_copy_table_res;
+    Alter_table_change_level need_copy_table_res;
     /* Check how much the tables differ. */
-    if (compare_tables(table, alter_info,
-                       create_info, order_num,
-                       &need_copy_table_res,
-                       &key_info_buffer,
-                       &index_drop_buffer, &index_drop_count,
-                       &index_add_buffer, &index_add_count,
-                       &candidate_key_count, FALSE))
+    if (mysql_compare_tables(table, alter_info,
+                             create_info, order_num,
+                             &need_copy_table_res,
+                             &key_info_buffer,
+                             &index_drop_buffer, &index_drop_count,
+                             &index_add_buffer, &index_add_count,
+                             &candidate_key_count, FALSE))
       goto err;
 
     if (need_copy_table == ALTER_TABLE_METADATA_ONLY)

=== modified file 'sql/sql_table.h'
--- a/sql/sql_table.h	2010-06-07 11:29:54 +0000
+++ b/sql/sql_table.h	2010-06-10 03:52:16 +0000
@@ -27,10 +27,12 @@ struct TABLE;
 struct handlerton;
 typedef struct st_ha_check_opt HA_CHECK_OPT;
 typedef struct st_ha_create_information HA_CREATE_INFO;
+typedef struct st_key KEY;
 typedef struct st_key_cache KEY_CACHE;
 typedef struct st_lock_param_type ALTER_PARTITION_PARAM_TYPE;
 typedef struct st_mysql_lex_string LEX_STRING;
 typedef struct st_order ORDER;
+class Alter_table_change_level;
 
 enum ddl_log_entry_code
 {
@@ -131,10 +133,6 @@ enum enum_explain_filename_mode
 #define NO_FRM_RENAME   (1 << 2)
 #define FRM_ONLY        (1 << 3)
 
-#ifdef WITH_PARTITION_STORAGE_ENGINE
-bool mysql_exchange_partition(THD *thd, TABLE_LIST *table_list,
-                              Alter_info *alter_info, bool ignore);
-#endif /* WITH_PARTITION_STORAGE_ENGINE */
 uint filename_to_tablename(const char *from, char *to, uint to_length);
 uint tablename_to_filename(const char *from, char *to, uint to_length);
 uint check_n_cut_mysql50_prefix(const char *from, char *to, uint to_length);
@@ -150,12 +148,23 @@ bool mysql_create_table_no_lock(THD *thd
                                 HA_CREATE_INFO *create_info,
                                 Alter_info *alter_info,
                                 bool tmp_table, uint select_field_count);
-
+bool mysql_prepare_alter_table(THD *thd, TABLE *table,
+                               HA_CREATE_INFO *create_info,
+                               Alter_info *alter_info);
 bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
                        HA_CREATE_INFO *create_info,
                        TABLE_LIST *table_list,
                        Alter_info *alter_info,
                        uint order_num, ORDER *order, bool ignore);
+bool mysql_compare_tables(TABLE *table,
+                          Alter_info *alter_info,
+                          HA_CREATE_INFO *create_info,
+                          uint order_num,
+                          Alter_table_change_level *need_copy_table,
+                          KEY **key_info_buffer,
+                          uint **index_drop_buffer, uint *index_drop_count,
+                          uint **index_add_buffer, uint *index_add_count,
+                          uint *candidate_key_count, bool exact_match);
 bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list);
 bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
                              TABLE_LIST *src_table,

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2010-06-07 11:29:54 +0000
+++ b/sql/sql_yacc.yy	2010-06-10 03:52:16 +0000
@@ -51,6 +51,7 @@
 #include "sp_rcontext.h"
 #include "sp.h"
 #include "sql_alter_table.h"                   // Alter_table*_statement
+#include "sql_partition_admin.h"               // Alter_table_*_partition_statement
 #include "sql_signal.h"
 #include "event_parse_data.h"
 #include <myisam.h>
@@ -6170,7 +6171,6 @@ alter:
             lex->create_info.storage_media= HA_SM_DEFAULT;
             lex->create_last_non_select_table= lex->last_table();
             DBUG_ASSERT(!lex->m_stmt);
-            lex->m_stmt= NULL;
           }
           alter_commands
           {


Attachment: [text/bzr-bundle] bzr/davi.arnaut@sun.com-20100610035216-32kxvo7inphursow.bundle
Thread
bzr commit into mysql-next-mr branch (davi:3154) WL#4445Davi Arnaut10 Jun