diff options
Diffstat (limited to 'sql/sql_partition_admin.cc')
-rw-r--r-- | sql/sql_partition_admin.cc | 92 |
1 files changed, 81 insertions, 11 deletions
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 90019d071a1..3a22c9f6201 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -46,6 +46,16 @@ bool Sql_cmd_partition_unsupported::execute(THD *) #else +static bool return_with_logging(THD *thd) +{ + if (thd->slave_thread && + write_bin_log_with_if_exists(thd, true, false, true)) + return(true); + my_ok(thd); + return(false); +} + + bool Sql_cmd_alter_table_exchange_partition::execute(THD *thd) { /* Moved from mysql_execute_command */ @@ -63,7 +73,7 @@ bool Sql_cmd_alter_table_exchange_partition::execute(THD *thd) */ IF_DBUG(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; + privilege_t priv_needed(ALTER_ACL | DROP_ACL | INSERT_ACL | CREATE_ACL); DBUG_ENTER("Sql_cmd_alter_table_exchange_partition::execute"); @@ -506,7 +516,8 @@ bool Sql_cmd_alter_table_exchange_partition:: MDL_ticket *swap_table_mdl_ticket= NULL; MDL_ticket *part_table_mdl_ticket= NULL; uint table_counter; - bool error= TRUE; + bool error= TRUE, force_if_exists= 0; + ulonglong save_option_bits= thd->variables.option_bits; DBUG_ENTER("mysql_exchange_partition"); DBUG_ASSERT(alter_info->partition_flags & ALTER_PARTITION_EXCHANGE); @@ -534,7 +545,25 @@ bool Sql_cmd_alter_table_exchange_partition:: table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE); if (unlikely(open_tables(thd, &table_list, &table_counter, 0, &alter_prelocking_strategy))) + { + if (thd->lex->if_exists() && + thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE) + { + /* + ALTER TABLE IF EXISTS was used on not existing table + We have to log the query on a slave as the table may be a shared one + from the master and we need to ensure that the next slave can see + the statement as this slave may not have the table shared + */ + thd->clear_error(); + if (thd->slave_thread && + write_bin_log(thd, true, thd->query(), thd->query_length())) + DBUG_RETURN(true); + my_ok(thd); + DBUG_RETURN(false); + } DBUG_RETURN(true); + } part_table= table_list->table; swap_table= swap_table_list->table; @@ -550,6 +579,14 @@ bool Sql_cmd_alter_table_exchange_partition:: if (unlikely(check_exchange_partition(swap_table, part_table))) DBUG_RETURN(TRUE); + if (part_table->file->check_if_updates_are_ignored("ALTER")) + DBUG_RETURN(return_with_logging(thd)); + + /* Add IF EXISTS to binlog if shared table */ + if (part_table->file->partition_ht()->flags & + HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE) + force_if_exists= 1; + /* set lock pruning on first table */ partition_name= alter_info->partition_names.head(); if (unlikely(table_list->table->part_info-> @@ -576,8 +613,8 @@ bool Sql_cmd_alter_table_exchange_partition:: swap_table_list->db.str, swap_table_list->table_name.str, "", 0); - /* create a unique temp name #sqlx-nnnn_nnnn, x for eXchange */ - my_snprintf(temp_name, sizeof(temp_name), "%sx-%lx_%llx", + /* create a unique temp name */ + my_snprintf(temp_name, sizeof(temp_name), "%s-exchange-%lx-%llx", tmp_file_prefix, current_pid, thd->thread_id); if (lower_case_table_names) my_casedn_str(files_charset_info, temp_name); @@ -651,6 +688,9 @@ bool Sql_cmd_alter_table_exchange_partition:: */ (void) thd->locked_tables_list.reopen_tables(thd, false); + if (force_if_exists) + thd->variables.option_bits|= OPTION_IF_EXISTS; + if (unlikely((error= write_bin_log(thd, TRUE, thd->query(), thd->query_length())))) { @@ -661,6 +701,7 @@ bool Sql_cmd_alter_table_exchange_partition:: (void) exchange_name_with_ddl_log(thd, part_file_name, swap_file_name, temp_file_name, table_hton); } + thd->variables.option_bits= save_option_bits; err: if (thd->locked_tables_mode) @@ -759,7 +800,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) Alter_info *alter_info= &thd->lex->alter_info; uint table_counter, i; List<String> partition_names_list; - bool binlog_stmt; + bool binlog_stmt, force_if_exists= 0; DBUG_ENTER("Sql_cmd_alter_table_truncate_partition::execute"); /* @@ -797,16 +838,41 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) #endif /* WITH_WSREP */ if (open_tables(thd, &first_table, &table_counter, 0)) - DBUG_RETURN(true); + { + if (thd->lex->if_exists() && + thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE) + { + /* + ALTER TABLE IF EXISTS was used on not existing table + We have to log the query on a slave as the table may be a shared one + from the master and we need to ensure that the next slave can see + the statement as this slave may not have the table shared + */ + thd->clear_error(); + DBUG_RETURN(return_with_logging(thd)); + } + DBUG_RETURN(TRUE); + } - if (!first_table->table || first_table->view || - first_table->table->s->db_type() != partition_hton) + if (!first_table->table || first_table->view) { my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0)); DBUG_RETURN(TRUE); } - + if (first_table->table->file->check_if_updates_are_ignored("ALTER")) + DBUG_RETURN(return_with_logging(thd)); + + if (first_table->table->s->db_type() != partition_hton) + { + my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0)); + DBUG_RETURN(TRUE); + } + + if (first_table->table->file->partition_ht()->flags & + HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE) + force_if_exists= 1; + /* Prune all, but named partitions, to avoid excessive calls to external_lock(). @@ -838,8 +904,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) if (thd->mdl_context.upgrade_shared_lock(ticket, MDL_EXCLUSIVE, timeout)) DBUG_RETURN(TRUE); - tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, first_table->db.str, - first_table->table_name.str, FALSE); + first_table->table->s->tdc->flush(thd, true); partition= (ha_partition*) first_table->table->file; /* Invoke the handler method responsible for truncating the partition. */ @@ -859,9 +924,14 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) */ if (likely(error != HA_ERR_WRONG_COMMAND)) { + ulonglong save_option_bits= thd->variables.option_bits; + if (force_if_exists) + thd->variables.option_bits|= OPTION_IF_EXISTS; + query_cache_invalidate3(thd, first_table, FALSE); if (binlog_stmt) error|= write_bin_log(thd, !error, thd->query(), thd->query_length()); + thd->variables.option_bits= save_option_bits; } /* |