diff options
Diffstat (limited to 'sql/sql_partition_admin.cc')
-rw-r--r-- | sql/sql_partition_admin.cc | 93 |
1 files changed, 71 insertions, 22 deletions
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index fee33303a04..98750314a4a 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -16,10 +16,10 @@ #include "sql_parse.h" // check_one_table_access #include "sql_table.h" // mysql_alter_table, etc. #include "sql_lex.h" // Sql_statement -#include "sql_truncate.h" // mysql_truncate_table, - // Truncate_statement #include "sql_admin.h" // Analyze/Check/.._table_statement #include "sql_partition_admin.h" // Alter_table_*_partition +#include "ha_partition.h" // ha_partition +#include "sql_base.h" // open_and_lock_tables #ifndef WITH_PARTITION_STORAGE_ENGINE @@ -46,7 +46,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); } @@ -104,36 +104,85 @@ 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; 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))) + 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 only exception is a unimplemented truncate method. Also, + it is logged in statement format, regardless of the binlog format. + */ + if (error != HA_ERR_WRONG_COMMAND) + 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 */ |