summaryrefslogtreecommitdiff
path: root/sql/sql_partition_admin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_partition_admin.cc')
-rw-r--r--sql/sql_partition_admin.cc99
1 files changed, 77 insertions, 22 deletions
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index 795760c855c..cadfc587c1c 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -15,10 +15,13 @@
#include "sql_parse.h" // check_one_table_access
#include "sql_table.h" // mysql_alter_table, etc.
-#include "sql_truncate.h" // mysql_truncate_table,
- // Truncate_statement
+#include "sql_lex.h" // Sql_statement
#include "sql_admin.h" // Analyze/Check/.._table_statement
#include "sql_partition_admin.h" // Alter_table_*_partition
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+#include "ha_partition.h" // ha_partition
+#endif
+#include "sql_base.h" // open_and_lock_tables
#ifndef WITH_PARTITION_STORAGE_ENGINE
@@ -45,7 +48,7 @@ bool Alter_table_analyze_partition_statement::execute(THD *thd)
m_lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
res= Analyze_table_statement::execute(thd);
-
+
DBUG_RETURN(res);
}
@@ -103,36 +106,88 @@ bool Alter_table_repair_partition_statement::execute(THD *thd)
bool Alter_table_truncate_partition_statement::execute(THD *thd)
{
+ int error;
+ ha_partition *partition;
+ ulong timeout= thd->variables.lock_wait_timeout;
TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
- bool res;
- enum_sql_command original_sql_command;
+ bool binlog_stmt;
DBUG_ENTER("Alter_table_truncate_partition_statement::execute");
/*
- Execute TRUNCATE PARTITION just like TRUNCATE TABLE.
- Some storage engines (InnoDB, partition) checks thd_sql_command,
- so we set it to SQLCOM_TRUNCATE during the execution.
- */
- original_sql_command= m_lex->sql_command;
- m_lex->sql_command= SQLCOM_TRUNCATE;
-
- /*
Flag that it is an ALTER command which administrates partitions, used
by ha_partition.
*/
- m_lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
-
+ m_lex->alter_info.flags|= ALTER_ADMIN_PARTITION |
+ ALTER_TRUNCATE_PARTITION;
+
+ /* Fix the lock types (not the same as ordinary ALTER TABLE). */
+ first_table->lock_type= TL_WRITE;
+ first_table->mdl_request.set_type(MDL_EXCLUSIVE);
+
/*
- Fix the lock types (not the same as ordinary ALTER TABLE).
+ Check table permissions and open it with a exclusive lock.
+ Ensure it is a partitioned table and finally, upcast the
+ handler and invoke the partition truncate method. Lastly,
+ write the statement to the binary log if necessary.
*/
- first_table->lock_type= TL_WRITE;
- first_table->mdl_request.set_type(MDL_SHARED_NO_READ_WRITE);
- /* execute as a TRUNCATE TABLE */
- res= Truncate_statement::execute(thd);
+ if (check_one_table_access(thd, DROP_ACL, first_table))
+ DBUG_RETURN(TRUE);
- m_lex->sql_command= original_sql_command;
- DBUG_RETURN(res);
+ if (open_and_lock_tables(thd, first_table, FALSE, 0))
+ DBUG_RETURN(TRUE);
+
+ /*
+ TODO: Add support for TRUNCATE PARTITION for NDB and other
+ engines supporting native partitioning.
+ */
+ if (first_table->table->s->db_type() != partition_hton)
+ {
+ my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ Under locked table modes this might still not be an exclusive
+ lock. Hence, upgrade the lock since the handler truncate method
+ mandates an exclusive metadata lock.
+ */
+ MDL_ticket *ticket= first_table->table->mdl_ticket;
+ if (thd->mdl_context.upgrade_shared_lock_to_exclusive(ticket, timeout))
+ DBUG_RETURN(TRUE);
+
+ tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, first_table->db,
+ first_table->table_name, FALSE);
+
+ partition= (ha_partition *) first_table->table->file;
+
+ /* Invoke the handler method responsible for truncating the partition. */
+ if ((error= partition->truncate_partition(&thd->lex->alter_info,
+ &binlog_stmt)))
+ first_table->table->file->print_error(error, MYF(0));
+
+ /*
+ All effects of a truncate operation are committed even if the
+ operation fails. Thus, the query must be written to the binary
+ log. The exception is a unimplemented truncate method or failure
+ before any call to handler::truncate() is done.
+ Also, it is logged in statement format, regardless of the binlog format.
+ */
+ if (error != HA_ERR_WRONG_COMMAND && binlog_stmt)
+ error|= write_bin_log(thd, !error, thd->query(), thd->query_length());
+
+ /*
+ A locked table ticket was upgraded to a exclusive lock. After the
+ the query has been written to the binary log, downgrade the lock
+ to a shared one.
+ */
+ if (thd->locked_tables_mode)
+ ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+
+ if (! error)
+ my_ok(thd);
+
+ DBUG_RETURN(error);
}
#endif /* WITH_PARTITION_STORAGE_ENGINE */