diff options
author | Sergei Golubchik <serg@mariadb.org> | 2016-08-25 12:40:09 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-08-25 12:40:09 +0200 |
commit | 6b1863b8304662189a3b9a4aef1e1bebef035b86 (patch) | |
tree | 48ba2cbdda863b644108e93ace3668333ae0d193 /sql | |
parent | ea91bb6801b1b619d64fa137ea351eca9de683ec (diff) | |
parent | 5bbe929d706e26cb3f9b291da6009526a17b1545 (diff) | |
download | mariadb-git-6b1863b8304662189a3b9a4aef1e1bebef035b86.tar.gz |
Merge branch '10.0' into 10.1
Diffstat (limited to 'sql')
-rw-r--r-- | sql/contributors.h | 21 | ||||
-rw-r--r-- | sql/derror.cc | 2 | ||||
-rw-r--r-- | sql/handler.cc | 14 | ||||
-rw-r--r-- | sql/handler.h | 1 | ||||
-rw-r--r-- | sql/item_func.cc | 7 | ||||
-rw-r--r-- | sql/item_subselect.cc | 8 | ||||
-rw-r--r-- | sql/item_subselect.h | 5 | ||||
-rw-r--r-- | sql/item_sum.cc | 4 | ||||
-rw-r--r-- | sql/mdl.cc | 67 | ||||
-rw-r--r-- | sql/multi_range_read.cc | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 49 | ||||
-rw-r--r-- | sql/mysqld.h | 5 | ||||
-rw-r--r-- | sql/net_serv.cc | 97 | ||||
-rw-r--r-- | sql/opt_range.cc | 5 | ||||
-rw-r--r-- | sql/protocol.cc | 15 | ||||
-rw-r--r-- | sql/rpl_mi.cc | 7 | ||||
-rw-r--r-- | sql/rpl_rli.cc | 6 | ||||
-rw-r--r-- | sql/slave.cc | 5 | ||||
-rw-r--r-- | sql/sql_base.cc | 32 | ||||
-rw-r--r-- | sql/sql_class.cc | 10 | ||||
-rw-r--r-- | sql/sql_class.h | 16 | ||||
-rw-r--r-- | sql/sql_delete.cc | 3 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_load.cc | 75 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_plugin.h | 2 | ||||
-rw-r--r-- | sql/sql_rename.cc | 31 | ||||
-rw-r--r-- | sql/sql_table.cc | 10 | ||||
-rw-r--r-- | sql/sql_table.h | 3 | ||||
-rw-r--r-- | sql/sql_union.cc | 6 | ||||
-rw-r--r-- | sql/sql_update.cc | 8 | ||||
-rw-r--r-- | sql/sys_vars.cc | 46 |
32 files changed, 386 insertions, 180 deletions
diff --git a/sql/contributors.h b/sql/contributors.h index 76674d654e5..f52d3243453 100644 --- a/sql/contributors.h +++ b/sql/contributors.h @@ -36,17 +36,16 @@ struct show_table_contributors_st { */ struct show_table_contributors_st show_table_contributors[]= { - /* MariaDB foundation members, in contribution, size , time order */ - {"Booking.com", "http://www.booking.com", "Founding member of the MariaDB Foundation"}, - {"MariaDB Corporation", "https://mariadb.com", "Founding member of the MariaDB Foundation"}, - {"Auttomattic", "http://automattic.com", "Member of the MariaDB Foundation"}, - {"Visma", "http://visma.com", "Member of the MariaDB Foundation"}, - {"Nexedi", "http://www.nexedi.com", "Member of the MariaDB Foundation"}, - {"Acronis", "http://www.acronis.com", "Member of the MariaDB Foundation"}, - - /* Smaller sponsors, newer per year */ - {"Verkkokauppa.com", "Finland", "Sponsor of the MariaDB Foundation"}, - {"Virtuozzo", "https://virtuozzo.com/", "Sponsor of the MariaDB Foundation"}, + /* MariaDB foundation sponsors, in contribution, size , time order */ + {"Booking.com", "http://www.booking.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"}, + {"MariaDB Corporation", "https://mariadb.com", "Founding member, Gold Sponsor of the MariaDB Foundation"}, + {"Visma", "http://visma.com", "Gold Sponsor of the MariaDB Foundation"}, + {"DBS", "http://dbs.com", "Gold Sponsor of the MariaDB Foundation"}, + {"Nexedi", "https://www.nexedi.com", "Silver Sponsor of the MariaDB Foundation"}, + {"Acronis", "http://www.acronis.com", "Silver Sponsor of the MariaDB Foundation"}, + {"Auttomattic", "https://automattic.com", "Bronze Sponsor of the MariaDB Foundation"}, + {"Verkkokauppa.com", "https://virtuozzo.com", "Bronze Sponsor of the MariaDB Foundation"}, + {"Virtuozzo", "https://virtuozzo.com/", "Bronze Sponsor of the MariaDB Foundation"}, /* Sponsors of important features */ {"Google", "USA", "Sponsoring encryption, parallel replication and GTID"}, diff --git a/sql/derror.cc b/sql/derror.cc index bc4b89493aa..5f0bc455caf 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -35,7 +35,7 @@ static void init_myfunc_errs(void); C_MODE_START -static const char **get_server_errmsgs() +static const char **get_server_errmsgs(void) { if (!current_thd) return DEFAULT_ERRMSGS; diff --git a/sql/handler.cc b/sql/handler.cc index e4aa1660c82..b862a0e5b0b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -296,7 +296,7 @@ handler *get_ha_partition(partition_info *part_info) static const char **handler_errmsgs; C_MODE_START -static const char **get_handler_errmsgs() +static const char **get_handler_errmsgs(void) { return handler_errmsgs; } @@ -1360,7 +1360,8 @@ int ha_commit_trans(THD *thd, bool all) uint rw_ha_count= ha_check_and_coalesce_trx_read_only(thd, ha_info, all); /* rw_trans is TRUE when we in a transaction changing data */ - bool rw_trans= is_real_trans && (rw_ha_count > 0); + bool rw_trans= is_real_trans && + (rw_ha_count > !thd->is_current_stmt_binlog_disabled()); MDL_request mdl_request; DBUG_PRINT("info", ("is_real_trans: %d rw_trans: %d rw_ha_count: %d", is_real_trans, rw_trans, rw_ha_count)); @@ -2736,6 +2737,15 @@ int handler::ha_index_next_same(uchar *buf, const uchar *key, uint keylen) return result; } + +bool handler::ha_was_semi_consistent_read() +{ + bool result= was_semi_consistent_read(); + if (result) + increment_statistics(&SSV::ha_read_retry_count); + return result; +} + /* Initialize handler for random reading, with error handling */ int handler::ha_rnd_init_with_error(bool scan) diff --git a/sql/handler.h b/sql/handler.h index 9b9480556e3..dad2b81b39c 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3214,6 +3214,7 @@ public: If this method returns nonzero, it will also signal the storage engine that the next read will be a locking re-read of the row. */ + bool ha_was_semi_consistent_read(); virtual bool was_semi_consistent_read() { return 0; } /** Tell the engine whether it should avoid unnecessary lock waits. diff --git a/sql/item_func.cc b/sql/item_func.cc index 47ad756144a..a1c5835d525 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3916,7 +3916,7 @@ longlong Item_master_pos_wait::val_int() longlong timeout = (arg_count>=3) ? args[2]->val_int() : 0 ; String connection_name_buff; LEX_STRING connection_name; - Master_info *mi; + Master_info *mi= NULL; if (arg_count >= 4) { String *con; @@ -3936,8 +3936,9 @@ longlong Item_master_pos_wait::val_int() connection_name= thd->variables.default_master_connection; mysql_mutex_lock(&LOCK_active_mi); - mi= master_info_index->get_master_info(&connection_name, - Sql_condition::WARN_LEVEL_WARN); + if (master_info_index) // master_info_index is set to NULL on shutdown. + mi= master_info_index->get_master_info(&connection_name, + Sql_condition::WARN_LEVEL_WARN); mysql_mutex_unlock(&LOCK_active_mi); if (!mi) goto err; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 2999e01d166..42f17065cfe 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -3850,7 +3850,7 @@ int subselect_uniquesubquery_engine::scan_table() } table->file->extra_opt(HA_EXTRA_CACHE, - current_thd->variables.read_buff_size); + get_thd()->variables.read_buff_size); table->null_row= 0; for (;;) { @@ -4288,7 +4288,7 @@ table_map subselect_union_engine::upper_select_const_tables() void subselect_single_select_engine::print(String *str, enum_query_type query_type) { - select_lex->print(thd, str, query_type); + select_lex->print(get_thd(), str, query_type); } @@ -4819,6 +4819,7 @@ my_bitmap_init_memroot(MY_BITMAP *map, uint n_bits, MEM_ROOT *mem_root) bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id) { + THD *thd= get_thd(); select_union *result_sink; /* Options to create_tmp_table. */ ulonglong tmp_create_options= thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS; @@ -6053,6 +6054,7 @@ bool subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts, MY_BITMAP *partial_match_key_parts) { + THD *thd= get_thd(); /* The length in bytes of the rowids (positions) of tmp_table. */ uint rowid_length= tmp_table->file->ref_length; ha_rows row_count= tmp_table->file->stats.records; @@ -6591,7 +6593,7 @@ bool subselect_table_scan_engine::partial_match() } tmp_table->file->extra_opt(HA_EXTRA_CACHE, - current_thd->variables.read_buff_size); + get_thd()->variables.read_buff_size); for (;;) { error= tmp_table->file->ha_rnd_next(tmp_table->record[0]); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 54848c4ebf7..d18db4aab86 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -751,7 +751,8 @@ public: ROWID_MERGE_ENGINE, TABLE_SCAN_ENGINE}; subselect_engine(Item_subselect *si, - select_result_interceptor *res) + select_result_interceptor *res): + thd(NULL) { result= res; item= si; @@ -767,7 +768,7 @@ public: Should be called before prepare(). */ void set_thd(THD *thd_arg); - THD * get_thd() { return thd; } + THD * get_thd() { return thd ? thd : current_thd; } virtual int prepare(THD *)= 0; virtual void fix_length_and_dec(Item_cache** row)= 0; /* diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 1cfee1a9241..5220521b95a 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1450,7 +1450,7 @@ my_decimal *Item_sum_sum::val_decimal(my_decimal *val) if (aggr) aggr->endup(); if (hybrid_type == DECIMAL_RESULT) - return (dec_buffs + curr_dec_buff); + return null_value ? NULL : (dec_buffs + curr_dec_buff); return val_decimal_from_real(val); } @@ -1753,6 +1753,8 @@ double Item_sum_std::val_real() { DBUG_ASSERT(fixed == 1); double nr= Item_sum_variance::val_real(); + if (my_isinf(nr)) + return DBL_MAX; DBUG_ASSERT(nr >= 0.0); return sqrt(nr); } diff --git a/sql/mdl.cc b/sql/mdl.cc index 61591ec9f57..d1f4cb7e5c7 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -17,6 +17,7 @@ #include "sql_class.h" #include "debug_sync.h" #include "sql_array.h" +#include "rpl_rli.h" #include <lf.h> #include <mysqld_error.h> #include <mysql/plugin.h> @@ -506,6 +507,10 @@ public: bitmap_t hog_lock_types_bitmap() const { return m_strategy->hog_lock_types_bitmap(); } +#ifndef DBUG_OFF + bool check_if_conflicting_replication_locks(MDL_context *ctx); +#endif + /** List of granted tickets for this lock. */ Ticket_list m_granted; /** Tickets for contexts waiting to acquire a lock. */ @@ -1977,6 +1982,55 @@ MDL_context::clone_ticket(MDL_request *mdl_request) /** + Check if there is any conflicting lock that could cause this thread + to wait for another thread which is not ready to commit. + This is always an error, as the upper level of parallel replication + should not allow a scheduling of a conflicting DDL until all earlier + transactions has commited. + + This function is only called for a slave using parallel replication + and trying to get an exclusive lock for the table. +*/ + +#ifndef DBUG_OFF +bool MDL_lock::check_if_conflicting_replication_locks(MDL_context *ctx) +{ + Ticket_iterator it(m_granted); + MDL_ticket *conflicting_ticket; + rpl_group_info *rgi_slave= ctx->get_thd()->rgi_slave; + + if (!rgi_slave->gtid_sub_id) + return 0; + + while ((conflicting_ticket= it++)) + { + if (conflicting_ticket->get_ctx() != ctx) + { + MDL_context *conflicting_ctx= conflicting_ticket->get_ctx(); + rpl_group_info *conflicting_rgi_slave; + conflicting_rgi_slave= conflicting_ctx->get_thd()->rgi_slave; + + /* + If the conflicting thread is another parallel replication + thread for the same master and it's not in commit stage, then + the current transaction has started too early and something is + seriously wrong. + */ + if (conflicting_rgi_slave && + conflicting_rgi_slave->gtid_sub_id && + conflicting_rgi_slave->rli == rgi_slave->rli && + conflicting_rgi_slave->current_gtid.domain_id == + rgi_slave->current_gtid.domain_id && + !conflicting_rgi_slave->did_mark_start_commit) + return 1; // Fatal error + } + } + return 0; +} +#endif + + +/** Acquire one lock with waiting for conflicting locks to go away if needed. @param mdl_request [in/out] Lock request object for lock to be acquired @@ -2036,6 +2090,19 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) if (lock->needs_notification(ticket) && lock_wait_timeout) lock->notify_conflicting_locks(this); + /* + Ensure that if we are trying to get an exclusive lock for a slave + running parallel replication, then we are not blocked by another + parallel slave thread that is not committed. This should never happen as + the parallel replication scheduler should never schedule a DDL while + DML's are still running. + */ + DBUG_ASSERT((mdl_request->type != MDL_INTENTION_EXCLUSIVE && + mdl_request->type != MDL_EXCLUSIVE) || + !(get_thd()->rgi_slave && + get_thd()->rgi_slave->is_parallel_exec && + lock->check_if_conflicting_replication_locks(this))); + mysql_prlock_unlock(&lock->m_rwlock); will_wait_for(ticket); diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index 6e8428f1aad..5de9b4a9eec 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -261,7 +261,7 @@ int handler::multi_range_read_next(range_id_t *range_info) } else { - if (was_semi_consistent_read()) + if (ha_was_semi_consistent_read()) { /* The following assignment is redundant, but for extra safety and to diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a19ac8aa968..8ff01a3c056 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2676,26 +2676,17 @@ static void network_init(void) saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor; saPipeSecurity.bInheritHandle = FALSE; if ((hPipe= CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | - PIPE_READMODE_BYTE | - PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - (int) global_system_variables.net_buffer_length, - (int) global_system_variables.net_buffer_length, - NMPWAIT_USE_DEFAULT_WAIT, - &saPipeSecurity)) == INVALID_HANDLE_VALUE) - { - LPVOID lpMsgBuf; - int error=GetLastError(); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, 0, NULL ); - sql_perror((char *)lpMsgBuf); - LocalFree(lpMsgBuf); - unireg_abort(1); - } + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + (int) global_system_variables.net_buffer_length, + (int) global_system_variables.net_buffer_length, + NMPWAIT_USE_DEFAULT_WAIT, + &saPipeSecurity)) == INVALID_HANDLE_VALUE) + { + sql_perror("Create named pipe failed"); + unireg_abort(1); + } } #endif @@ -7728,7 +7719,10 @@ static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff) var->value= buff; mysql_mutex_lock(&LOCK_active_mi); - *((longlong *)buff)= master_info_index->any_slave_sql_running(); + if (master_info_index) + *((longlong *)buff)= master_info_index->any_slave_sql_running(); + else + *((longlong *)buff)= 0; mysql_mutex_unlock(&LOCK_active_mi); return 0; @@ -8362,6 +8356,7 @@ SHOW_VAR status_vars[]= { {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG}, {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH}, {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG}, + {"Delete_scan", (char*) offsetof(STATUS_VAR, delete_scan_count), SHOW_LONG_STATUS}, {"Empty_queries", (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS}, {"Executed_events", (char*) &executed_events, SHOW_LONG_NOFLUSH }, {"Executed_triggers", (char*) offsetof(STATUS_VAR, executed_triggers), SHOW_LONG_STATUS}, @@ -8390,6 +8385,7 @@ SHOW_VAR status_vars[]= { {"Handler_read_last", (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONG_STATUS}, {"Handler_read_next", (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS}, {"Handler_read_prev", (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS}, + {"Handler_read_retry", (char*) offsetof(STATUS_VAR, ha_read_retry_count), SHOW_LONG_STATUS}, {"Handler_read_rnd", (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS}, {"Handler_read_rnd_deleted", (char*) offsetof(STATUS_VAR, ha_read_rnd_deleted_count), SHOW_LONG_STATUS}, {"Handler_read_rnd_next", (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS}, @@ -8511,6 +8507,7 @@ SHOW_VAR status_vars[]= { {"Threads_connected", (char*) &connection_count, SHOW_INT}, {"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH}, {"Threads_running", (char*) &thread_running, SHOW_INT}, + {"Update_scan", (char*) offsetof(STATUS_VAR, update_scan_count), SHOW_LONG_STATUS}, {"Uptime", (char*) &show_starttime, SHOW_SIMPLE_FUNC}, #ifdef ENABLED_PROFILING {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_SIMPLE_FUNC}, @@ -10120,11 +10117,6 @@ PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0}; PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0}; PSI_stage_info stage_waiting_to_get_readlock= { 0, "Waiting to get readlock", 0}; -PSI_stage_info stage_slave_waiting_workers_to_exit= { 0, "Waiting for workers to exit", 0}; -PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting for Slave Worker to release partition", 0}; -PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0}; -PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0}; -PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0}; PSI_stage_info stage_binlog_waiting_background_tasks= { 0, "Waiting for background binlog tasks", 0}; PSI_stage_info stage_binlog_processing_checkpoint_notify= { 0, "Processing binlog checkpoint notification", 0}; PSI_stage_info stage_binlog_stopping_background_thread= { 0, "Stopping binlog background thread", 0}; @@ -10220,11 +10212,6 @@ PSI_stage_info *all_server_stages[]= & stage_setup, & stage_show_explain, & stage_slave_has_read_all_relay_log, - & stage_slave_waiting_event_from_coordinator, - & stage_slave_waiting_worker_queue, - & stage_slave_waiting_worker_to_free_events, - & stage_slave_waiting_worker_to_release_partition, - & stage_slave_waiting_workers_to_exit, & stage_sorting, & stage_sorting_for_group, & stage_sorting_for_order, diff --git a/sql/mysqld.h b/sql/mysqld.h index 8454f2410dc..8c6c4ea1524 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -474,11 +474,6 @@ extern PSI_stage_info stage_waiting_for_the_next_event_in_relay_log; extern PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position; extern PSI_stage_info stage_waiting_to_finalize_termination; extern PSI_stage_info stage_waiting_to_get_readlock; -extern PSI_stage_info stage_slave_waiting_worker_to_release_partition; -extern PSI_stage_info stage_slave_waiting_worker_to_free_events; -extern PSI_stage_info stage_slave_waiting_worker_queue; -extern PSI_stage_info stage_slave_waiting_event_from_coordinator; -extern PSI_stage_info stage_slave_waiting_workers_to_exit; extern PSI_stage_info stage_binlog_waiting_background_tasks; extern PSI_stage_info stage_binlog_processing_checkpoint_notify; extern PSI_stage_info stage_binlog_stopping_background_thread; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index d81c89fe534..ef7a46a7109 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -541,7 +541,7 @@ net_write_buff(NET *net, const uchar *packet, ulong len) left_length= (ulong) (net->buff_end - net->write_pos); #ifdef DEBUG_DATA_PACKETS - DBUG_DUMP("data", packet, len); + DBUG_DUMP("data_written", packet, len); #endif if (len > left_length) { @@ -630,7 +630,8 @@ net_real_write(NET *net,const uchar *packet, size_t len) } memcpy(b+header_length,packet,len); - if (my_compress(b+header_length, &len, &complen)) + /* Don't compress error packets (compress == 2) */ + if (net->compress == 2 || my_compress(b+header_length, &len, &complen)) complen=0; int3store(&b[NET_HEADER_SIZE],complen); int3store(b,len); @@ -641,7 +642,7 @@ net_real_write(NET *net,const uchar *packet, size_t len) #endif /* HAVE_COMPRESS */ #ifdef DEBUG_DATA_PACKETS - DBUG_DUMP("data", packet, len); + DBUG_DUMP("data_written", packet, len); #endif #ifndef NO_ALARM @@ -831,6 +832,7 @@ my_real_read(NET *net, size_t *complen, size_t length; uint i,retry_count=0; ulong len=packet_error; + my_bool expect_error_packet __attribute__((unused))= 0; thr_alarm_t alarmed; #ifndef NO_ALARM ALARM alarm_buff; @@ -879,6 +881,7 @@ my_real_read(NET *net, size_t *complen, if (i== 0 && thd_net_is_killed()) { + DBUG_PRINT("info", ("thd is killed")); len= packet_error; net->error= 0; net->last_errno= ER_CONNECTION_KILLED; @@ -948,39 +951,34 @@ my_real_read(NET *net, size_t *complen, pos+= length; update_statistics(thd_increment_bytes_received(net->thd, length)); } + +#ifdef DEBUG_DATA_PACKETS + DBUG_DUMP("data_read", net->buff+net->where_b, length); +#endif if (i == 0) { /* First parts is packet length */ ulong helping; +#ifndef DEBUG_DATA_PACKETS DBUG_DUMP("packet_header", net->buff+net->where_b, NET_HEADER_SIZE); +#endif if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr) - { - if (net->buff[net->where_b] != (uchar) 255) - { - DBUG_PRINT("error", - ("Packets out of order (Found: %d, expected %u)", - (int) net->buff[net->where_b + 3], - net->pkt_nr)); - /* - We don't make noise server side, since the client is expected - to break the protocol for e.g. --send LOAD DATA .. LOCAL where - the server expects the client to send a file, but the client - may reply with a new command instead. - */ + { #ifndef MYSQL_SERVER - EXTRA_DEBUG_fflush(stdout); - EXTRA_DEBUG_fprintf(stderr,"Error: Packets out of order (Found: %d, expected %d)\n", - (int) net->buff[net->where_b + 3], - (uint) (uchar) net->pkt_nr); - EXTRA_DEBUG_fflush(stderr); + if (net->buff[net->where_b + 3] == (uchar) (net->pkt_nr -1)) + { + /* + If the server was killed then the server may have missed the + last sent client packet and the packet numbering may be one off. + */ + DBUG_PRINT("warning", ("Found possible out of order packets")); + expect_error_packet= 1; + } + else #endif - } - len= packet_error; - /* Not a NET error on the client. XXX: why? */ - MYSQL_SERVER_my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0)); - goto end; - } - net->compress_pkt_nr= ++net->pkt_nr; + goto packets_out_of_order; + } + net->compress_pkt_nr= ++net->pkt_nr; #ifdef HAVE_COMPRESS if (net->compress) { @@ -1028,6 +1026,21 @@ my_real_read(NET *net, size_t *complen, } #endif } +#ifndef MYSQL_SERVER + else if (expect_error_packet) + { + /* + This check is safe both for compressed and not compressed protocol + as for the compressed protocol errors are not compressed anymore. + */ + if (net->buff[net->where_b] != (uchar) 255) + { + /* Restore pkt_nr to original value */ + net->pkt_nr--; + goto packets_out_of_order; + } + } +#endif } end: @@ -1041,7 +1054,7 @@ end: net->reading_or_writing=0; #ifdef DEBUG_DATA_PACKETS if (len != packet_error) - DBUG_DUMP("data", net->buff+net->where_b, len); + DBUG_DUMP("data_read", net->buff+net->where_b, len); #endif #ifdef MYSQL_SERVER if (server_extension != NULL) @@ -1052,9 +1065,35 @@ end: } #endif return(len); + +packets_out_of_order: + { + DBUG_PRINT("error", + ("Packets out of order (Found: %d, expected %u)", + (int) net->buff[net->where_b + 3], + net->pkt_nr)); + DBUG_ASSERT(0); + /* + We don't make noise server side, since the client is expected + to break the protocol for e.g. --send LOAD DATA .. LOCAL where + the server expects the client to send a file, but the client + may reply with a new command instead. + */ +#ifndef MYSQL_SERVER + EXTRA_DEBUG_fflush(stdout); + EXTRA_DEBUG_fprintf(stderr,"Error: Packets out of order (Found: %d, expected %d)\n", + (int) net->buff[net->where_b + 3], + (uint) (uchar) net->pkt_nr); + EXTRA_DEBUG_fflush(stderr); +#endif + len= packet_error; + MYSQL_SERVER_my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0)); + goto end; + } } + /* Old interface. See my_net_read_packet() for function description */ #undef my_net_read diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0d92d434762..1a0d12a8dee 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2426,8 +2426,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, scan_time= read_time= DBL_MAX; if (limit < records) read_time= (double) records + scan_time + 1; // Force to use index - else if (read_time <= 2.0 && !force_quick_range) - DBUG_RETURN(0); /* No need for quick select */ possible_keys.clear_all(); @@ -2697,7 +2695,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, thd->no_errors=0; } - DBUG_EXECUTE("info", print_quick(quick, &needed_reg);); /* @@ -10376,8 +10373,10 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, KEY *table_key=quick->head->key_info+quick->index; flag=EQ_RANGE; if ((table_key->flags & HA_NOSAME) && + min_part == key_tree->part && key_tree->part == table_key->user_defined_key_parts-1) { + DBUG_ASSERT(min_part == max_part); if ((table_key->flags & HA_NULL_PART_KEY) && null_part_in_key(key, param->min_key, diff --git a/sql/protocol.cc b/sql/protocol.cc index fa42915f5a9..4ae9497c039 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -373,7 +373,8 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, uint error; char converted_err[MYSQL_ERRMSG_SIZE]; char buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos; - + my_bool ret; + uint8 save_compress; DBUG_ENTER("send_error_packet"); if (net->vio == 0) @@ -401,8 +402,16 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, /* Converted error message is always null-terminated. */ length= (uint) (strmake(pos, converted_err, MYSQL_ERRMSG_SIZE - 1) - buff); - DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) buff, - length)); + /* + Ensure that errors are not compressed. This is to ensure we can + detect out of bands error messages in the client + */ + if ((save_compress= net->compress)) + net->compress= 2; + ret= net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) buff, + length); + net->compress= save_compress; + DBUG_RETURN(ret); } #endif /* EMBEDDED_LIBRARY */ diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 02dbac46eb5..6048d26998b 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -1233,8 +1233,6 @@ Master_info_index::get_master_info(const LEX_STRING *connection_name, connection_name->str)); mysql_mutex_assert_owner(&LOCK_active_mi); - if (!this) // master_info_index is set to NULL on server shutdown - DBUG_RETURN(NULL); /* Make name lower case for comparison */ res= strmake(buff, connection_name->str, connection_name->length); @@ -1388,8 +1386,6 @@ bool Master_info_index::give_error_if_slave_running() { DBUG_ENTER("give_error_if_slave_running"); mysql_mutex_assert_owner(&LOCK_active_mi); - if (!this) // master_info_index is set to NULL on server shutdown - DBUG_RETURN(TRUE); for (uint i= 0; i< master_info_hash.records; ++i) { @@ -1420,8 +1416,7 @@ uint Master_info_index::any_slave_sql_running() { uint count= 0; DBUG_ENTER("any_slave_sql_running"); - if (!this) // master_info_index is set to NULL on server shutdown - DBUG_RETURN(count); + mysql_mutex_assert_owner(&LOCK_active_mi); for (uint i= 0; i< master_info_hash.records; ++i) { diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 2dd6f7d7afc..31dd24a038d 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1906,8 +1906,8 @@ rpl_group_info::mark_start_commit_no_lock() { if (did_mark_start_commit) return; - mark_start_commit_inner(parallel_entry, gco, this); did_mark_start_commit= true; + mark_start_commit_inner(parallel_entry, gco, this); } @@ -1918,12 +1918,12 @@ rpl_group_info::mark_start_commit() if (did_mark_start_commit) return; + did_mark_start_commit= true; e= this->parallel_entry; mysql_mutex_lock(&e->LOCK_parallel_entry); mark_start_commit_inner(e, gco, this); mysql_mutex_unlock(&e->LOCK_parallel_entry); - did_mark_start_commit= true; } @@ -1966,12 +1966,12 @@ rpl_group_info::unmark_start_commit() if (!did_mark_start_commit) return; + did_mark_start_commit= false; e= this->parallel_entry; mysql_mutex_lock(&e->LOCK_parallel_entry); --e->count_committing_event_groups; mysql_mutex_unlock(&e->LOCK_parallel_entry); - did_mark_start_commit= false; } diff --git a/sql/slave.cc b/sql/slave.cc index a670e335d8d..fc857d8c7c2 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -651,6 +651,7 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) mysql_mutex_unlock(log_lock); } if (opt_slave_parallel_threads > 0 && + master_info_index &&// master_info_index is set to NULL on server shutdown !master_info_index->any_slave_sql_running()) rpl_parallel_inactivate_pool(&global_rpl_thread_pool); if (thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) @@ -6218,9 +6219,9 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, #ifndef DBUG_OFF mi->events_till_disconnect = disconnect_slave_event_count; #endif - ulong client_flag= 0; + ulong client_flag= CLIENT_REMEMBER_OPTIONS; if (opt_slave_compressed_protocol) - client_flag=CLIENT_COMPRESS; /* We will use compression */ + client_flag|= CLIENT_COMPRESS; /* We will use compression */ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout); mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8c1c32e28f6..9ea5b20dce6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify @@ -691,7 +691,6 @@ bool close_cached_connection_tables(THD *thd, LEX_STRING *connection) static void mark_temp_tables_as_free_for_reuse(THD *thd) { - rpl_group_info *rgi_slave; DBUG_ENTER("mark_temp_tables_as_free_for_reuse"); if (thd->query_id == 0) @@ -700,9 +699,7 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd) DBUG_VOID_RETURN; } - rgi_slave=thd->rgi_slave; - if ((!rgi_slave && thd->temporary_tables) || - (rgi_slave && unlikely(rgi_slave->rli->save_temporary_tables))) + if (thd->have_temporary_tables()) { thd->lock_temporary_tables(); for (TABLE *table= thd->temporary_tables ; table ; table= table->next) @@ -710,15 +707,7 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd) if ((table->query_id == thd->query_id) && ! table->open_by_handler) mark_tmp_table_for_reuse(table); } - thd->unlock_temporary_tables(); - if (rgi_slave) - { - /* - Temporary tables are shared with other by sql execution threads. - As a safety messure, clear the pointer to the common area. - */ - thd->temporary_tables= 0; - } + thd->unlock_temporary_tables(1); } DBUG_VOID_RETURN; } @@ -1686,7 +1675,7 @@ TABLE *find_temporary_table(THD *thd, break; } } - thd->unlock_temporary_tables(); + thd->unlock_temporary_tables(0); return result; } @@ -1789,7 +1778,7 @@ void close_temporary_table(THD *thd, TABLE *table, thread_safe_decrement32(&slave_open_temp_tables); table->in_use= 0; // No statistics } - thd->unlock_temporary_tables(); + thd->unlock_temporary_tables(0); close_temporary(table, free_share, delete_table); DBUG_VOID_RETURN; } @@ -4888,6 +4877,15 @@ handle_view(THD *thd, Query_tables_list *prelocking_ctx, &table_list->view->sroutines_list, table_list->top_table()); } + + /* + If a trigger was defined on one of the associated tables then assign the + 'trg_event_map' value of the view to the next table in table_list. When a + Stored function is invoked, all the associated tables including the tables + associated with the trigger are prelocked. + */ + if (table_list->trg_event_map && table_list->next_global) + table_list->next_global->trg_event_map= table_list->trg_event_map; return FALSE; } @@ -5746,7 +5744,7 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton, { thread_safe_increment32(&slave_open_temp_tables); } - thd->unlock_temporary_tables(); + thd->unlock_temporary_tables(0); } tmp_table->pos_in_table_list= 0; DBUG_PRINT("tmptable", ("opened table: '%s'.'%s' 0x%lx", tmp_table->s->db.str, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 16773ab3018..0ae95ef5de1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -6942,10 +6942,18 @@ void THD::rgi_lock_temporary_tables() temporary_tables= rgi_slave->rli->save_temporary_tables; } -void THD::rgi_unlock_temporary_tables() +void THD::rgi_unlock_temporary_tables(bool clear) { rgi_slave->rli->save_temporary_tables= temporary_tables; mysql_mutex_unlock(&rgi_slave->rli->data_lock); + if (clear) + { + /* + Temporary tables are shared with other by sql execution threads. + As a safety messure, clear the pointer to the common area. + */ + temporary_tables= 0; + } } bool THD::rgi_have_temporary_tables() diff --git a/sql/sql_class.h b/sql/sql_class.h index 8bfc243977f..2841fcbe7eb 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -713,9 +713,11 @@ typedef struct system_status_var ulong ha_read_key_count; ulong ha_read_next_count; ulong ha_read_prev_count; + ulong ha_read_retry_count; ulong ha_read_rnd_count; ulong ha_read_rnd_next_count; ulong ha_read_rnd_deleted_count; + /* This number doesn't include calls to the default implementation and calls made by range access. The intent is to count only calls made by @@ -749,6 +751,8 @@ typedef struct system_status_var ulong select_range_count_; ulong select_range_check_count_; ulong select_scan_count_; + ulong update_scan_count; + ulong delete_scan_count; ulong executed_triggers; ulong long_query_count; ulong filesort_merge_passes_; @@ -3082,12 +3086,12 @@ public: set_start_time(); start_utime= utime_after_lock= microsecond_interval_timer(); } - inline void set_time(my_hrtime_t t) + inline void set_time(my_hrtime_t t) { user_time= t; set_time(); } - inline void set_time(my_time_t t, ulong sec_part) + inline void set_time(my_time_t t, ulong sec_part) { my_hrtime_t hrtime= { hrtime_from_time(t) + sec_part }; set_time(hrtime); @@ -3940,7 +3944,7 @@ private: /* Protect against add/delete of temporary tables in parallel replication */ void rgi_lock_temporary_tables(); - void rgi_unlock_temporary_tables(); + void rgi_unlock_temporary_tables(bool clear); bool rgi_have_temporary_tables(); public: /* @@ -3964,15 +3968,15 @@ public: if (rgi_slave) rgi_lock_temporary_tables(); } - inline void unlock_temporary_tables() + inline void unlock_temporary_tables(bool clear) { if (rgi_slave) - rgi_unlock_temporary_tables(); + rgi_unlock_temporary_tables(clear); } inline bool have_temporary_tables() { return (temporary_tables || - (rgi_slave && rgi_have_temporary_tables())); + (rgi_slave && unlikely(rgi_have_temporary_tables()))); } LF_PINS *tdc_hash_pins; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 3252e403226..5b8896aa37f 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -483,6 +483,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_EXECUTE_IF("show_explain_probe_delete_exec_start", dbug_serve_apcs(thd, 1);); + if (!(select && select->quick)) + status_var_increment(thd->status_var.delete_scan_count); + if (query_plan.using_filesort) { ha_rows examined_rows; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b97bae6b23c..ac7fd93f0c0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3338,6 +3338,7 @@ bool Delayed_insert::handle_inserts(void) max_rows= 0; // For DBUG output #endif /* Remove all not used rows */ + mysql_mutex_lock(&mutex); while ((row=rows.get())) { if (table->s->blob_fields) @@ -3354,7 +3355,6 @@ bool Delayed_insert::handle_inserts(void) } DBUG_PRINT("error", ("dropped %lu rows after an error", max_rows)); thread_safe_increment(delayed_insert_errors, &LOCK_delayed_status); - mysql_mutex_lock(&mutex); DBUG_RETURN(1); } #endif /* EMBEDDED_LIBRARY */ diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 4e6d91b9c1f..c2c97a37633 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1387,7 +1387,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, set_if_bigger(length,line_start.length()); stack=stack_pos=(int*) sql_alloc(sizeof(int)*length); - if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(MY_THREAD_SPECIFIC)))) + if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(MY_WME | MY_THREAD_SPECIFIC)))) error=1; /* purecov: inspected */ else { @@ -1573,37 +1573,50 @@ int READ_INFO::read_field() } } #ifdef USE_MB - if (my_mbcharlen(read_charset, chr) > 1 && - to + my_mbcharlen(read_charset, chr) <= end_of_buff) - { - uchar* p= to; - int ml, i; - *to++ = chr; - - ml= my_mbcharlen(read_charset, chr); + uint ml= my_mbcharlen(read_charset, chr); + if (ml == 0) + { + *to= '\0'; + my_error(ER_INVALID_CHARACTER_STRING, MYF(0), + read_charset->csname, buffer); + error= true; + return 1; + } - for (i= 1; i < ml; i++) + if (ml > 1 && + to + ml <= end_of_buff) { - chr= GET; - if (chr == my_b_EOF) + uchar* p= to; + *to++ = chr; + + for (uint i= 1; i < ml; i++) { - /* - Need to back up the bytes already ready from illformed - multi-byte char - */ - to-= i; - goto found_eof; + chr= GET; + if (chr == my_b_EOF) + { + /* + Need to back up the bytes already ready from illformed + multi-byte char + */ + to-= i; + goto found_eof; + } + *to++ = chr; } - *to++ = chr; - } - if (my_ismbchar(read_charset, + if (my_ismbchar(read_charset, (const char *)p, (const char *)to)) - continue; - for (i= 0; i < ml; i++) - PUSH(*--to); - chr= GET; - } + continue; + for (uint i= 0; i < ml; i++) + PUSH(*--to); + chr= GET; + } + else if (ml > 1) + { + // Buffer is too small, exit while loop, and reallocate. + PUSH(chr); + break; + } #endif *to++ = (uchar) chr; } @@ -1847,7 +1860,15 @@ int READ_INFO::read_value(int delim, String *val) for (chr= GET; my_tospace(chr) != delim && chr != my_b_EOF;) { #ifdef USE_MB - if (my_mbcharlen(read_charset, chr) > 1) + uint ml= my_mbcharlen(read_charset, chr); + if (ml == 0) + { + chr= my_b_EOF; + val->length(0); + return chr; + } + + if (ml > 1) { DBUG_PRINT("read_xml",("multi byte")); int i, ml= my_mbcharlen(read_charset, chr); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3c0bf523c2c..7238e439392 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -529,6 +529,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_INSERT_SELECT]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_DELETE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_DELETE_MULTI]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_RENAME_TABLE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_REPLACE_SELECT]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_SELECT]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_SET_OPTION]|= CF_PREOPEN_TMP_TABLES; @@ -6793,6 +6794,7 @@ bool check_stack_overrun(THD *thd, long margin, if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= (long) (my_thread_stack_size - margin)) { + thd->is_fatal_error= 1; /* Do not use stack for the message buffer to ensure correct behaviour in cases we have close to no stack left. diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 9483fc8d9b3..77ec24bbe9c 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -187,6 +187,8 @@ typedef my_bool (plugin_foreach_func)(THD *thd, #define plugin_foreach(A,B,C,D) plugin_foreach_with_mask(A,B,C,PLUGIN_IS_READY,D) extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int type, uint state_mask, void *arg); +extern void sync_dynamic_session_variables(THD* thd, bool global_lock); + extern bool plugin_dl_foreach(THD *thd, const LEX_STRING *dl, plugin_foreach_func *func, void *arg); diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index b795f5d7f22..35222bce949 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -212,6 +212,28 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list) } +static bool +do_rename_temporary(THD *thd, TABLE_LIST *ren_table, TABLE_LIST *new_table, + bool skip_error) +{ + const char *new_alias; + DBUG_ENTER("do_rename_temporary"); + + new_alias= (lower_case_table_names == 2) ? new_table->alias : + new_table->table_name; + + if (is_temporary_table(new_table)) + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); + DBUG_RETURN(1); // This can't be skipped + } + + + DBUG_RETURN(rename_temporary_table(thd, ren_table->table, + new_table->db, new_alias)); +} + + /* Rename a single table or a view @@ -317,6 +339,8 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, DBUG_RETURN(0); } + + /* Rename all tables in list; Return pointer to wrong entry if something goes wrong. Note that the table_list may be empty! @@ -351,8 +375,11 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) for (ren_table= table_list; ren_table; ren_table= new_table->next_local) { new_table= ren_table->next_local; - if (do_rename(thd, ren_table, new_table->db, new_table->table_name, - new_table->alias, skip_error)) + + if (is_temporary_table(ren_table) ? + do_rename_temporary(thd, ren_table, new_table, skip_error) : + do_rename(thd, ren_table, new_table->db, new_table->table_name, + new_table->alias, skip_error)) DBUG_RETURN(ren_table); } DBUG_RETURN(0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dae3b7ad827..2e639f3d072 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2687,14 +2687,15 @@ bool log_drop_table(THD *thd, const char *db_name, size_t db_name_length, */ bool quick_rm_table(THD *thd, handlerton *base, const char *db, - const char *table_name, uint flags) + const char *table_name, uint flags, const char *table_path) { char path[FN_REFLEN + 1]; bool error= 0; DBUG_ENTER("quick_rm_table"); - uint path_length= build_table_filename(path, sizeof(path) - 1, - db, table_name, reg_ext, flags); + uint path_length= table_path ? + (strxnmov(path, sizeof(path) - 1, table_path, reg_ext, NullS) - path) : + build_table_filename(path, sizeof(path)-1, db, table_name, reg_ext, flags); if (mysql_file_delete(key_file_frm, path, MYF(0))) error= 1; /* purecov: inspected */ path[path_length - reg_ext_length]= '\0'; // Remove reg_ext @@ -9254,7 +9255,8 @@ err_new_table_cleanup: else (void) quick_rm_table(thd, new_db_type, alter_ctx.new_db, alter_ctx.tmp_name, - (FN_IS_TMP | (no_ha_table ? NO_HA_TABLE : 0))); + (FN_IS_TMP | (no_ha_table ? NO_HA_TABLE : 0)), + alter_ctx.get_tmp_path()); /* No default value was provided for a DATE/DATETIME field, the diff --git a/sql/sql_table.h b/sql/sql_table.h index a8124177840..474fe9cd90b 100644 --- a/sql/sql_table.h +++ b/sql/sql_table.h @@ -247,7 +247,8 @@ bool log_drop_table(THD *thd, const char *db_name, size_t db_name_length, const char *table_name, size_t table_name_length, bool temporary_table); bool quick_rm_table(THD *thd, handlerton *base, const char *db, - const char *table_name, uint flags); + const char *table_name, uint flags, + const char *table_path=0); void close_cached_table(THD *thd, TABLE *table); void sp_prepare_create_field(THD *thd, Create_field *sql_field); int prepare_create_field(Create_field *sql_field, diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8145cec5f25..2086d1d6c03 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1043,6 +1043,12 @@ bool st_select_lex_unit::cleanup() join->tables_list= 0; join->table_count= 0; join->top_join_tab_count= 0; + if (join->tmp_join && join->tmp_join != join) + { + join->tmp_join->tables_list= 0; + join->tmp_join->table_count= 0; + join->tmp_join->top_join_tab_count= 0; + } } error|= fake_select_lex->cleanup(); /* diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a23f71977aa..04aea060543 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -534,6 +534,9 @@ int mysql_update(THD *thd, DBUG_EXECUTE_IF("show_explain_probe_update_exec_start", dbug_serve_apcs(thd, 1);); + if (!(select && select->quick)) + status_var_increment(thd->status_var.update_scan_count); + if (query_plan.using_filesort || query_plan.using_io_buffer) { /* @@ -604,6 +607,7 @@ int mysql_update(THD *thd, close_cached_file(&tempfile); goto err; } + table->file->try_semi_consistent_read(1); /* @@ -642,7 +646,7 @@ int mysql_update(THD *thd, thd->inc_examined_row_count(1); if (!select || (error= select->skip_record(thd)) > 0) { - if (table->file->was_semi_consistent_read()) + if (table->file->ha_was_semi_consistent_read()) continue; /* repeat the read of the same row if it still exists */ explain->buf_tracker.on_record_after_where(); @@ -760,7 +764,7 @@ int mysql_update(THD *thd, thd->inc_examined_row_count(1); if (!select || select->skip_record(thd) > 0) { - if (table->file->was_semi_consistent_read()) + if (table->file->ha_was_semi_consistent_read()) continue; /* repeat the read of the same row if it still exists */ explain->tracker.on_record_after_where(); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 1943408678c..7d479266403 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1597,7 +1597,8 @@ Sys_var_gtid_slave_pos::do_check(THD *thd, set_var *var) } mysql_mutex_lock(&LOCK_active_mi); - running= master_info_index->give_error_if_slave_running(); + running= (!master_info_index || + master_info_index->give_error_if_slave_running()); mysql_mutex_unlock(&LOCK_active_mi); if (running) return true; @@ -1637,7 +1638,7 @@ Sys_var_gtid_slave_pos::global_update(THD *thd, set_var *var) mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - if (master_info_index->give_error_if_slave_running()) + if (!master_info_index || master_info_index->give_error_if_slave_running()) err= true; else err= rpl_gtid_pos_update(thd, var->save_result.string_value.str, @@ -1826,7 +1827,8 @@ check_slave_parallel_threads(sys_var *self, THD *thd, set_var *var) bool running; mysql_mutex_lock(&LOCK_active_mi); - running= master_info_index->give_error_if_slave_running(); + running= (!master_info_index || + master_info_index->give_error_if_slave_running()); mysql_mutex_unlock(&LOCK_active_mi); if (running) return true; @@ -1841,7 +1843,8 @@ fix_slave_parallel_threads(sys_var *self, THD *thd, enum_var_type type) mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - err= master_info_index->give_error_if_slave_running(); + err= (!master_info_index || + master_info_index->give_error_if_slave_running()); mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_global_system_variables); @@ -1868,7 +1871,8 @@ check_slave_domain_parallel_threads(sys_var *self, THD *thd, set_var *var) bool running; mysql_mutex_lock(&LOCK_active_mi); - running= master_info_index->give_error_if_slave_running(); + running= (!master_info_index || + master_info_index->give_error_if_slave_running()); mysql_mutex_unlock(&LOCK_active_mi); if (running) return true; @@ -1883,7 +1887,8 @@ fix_slave_domain_parallel_threads(sys_var *self, THD *thd, enum_var_type type) mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - running= master_info_index->give_error_if_slave_running(); + running= (!master_info_index || + master_info_index->give_error_if_slave_running()); mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_global_system_variables); @@ -2033,7 +2038,8 @@ check_gtid_ignore_duplicates(sys_var *self, THD *thd, set_var *var) bool running; mysql_mutex_lock(&LOCK_active_mi); - running= master_info_index->give_error_if_slave_running(); + running= (!master_info_index || + master_info_index->give_error_if_slave_running()); mysql_mutex_unlock(&LOCK_active_mi); if (running) return true; @@ -2048,7 +2054,8 @@ fix_gtid_ignore_duplicates(sys_var *self, THD *thd, enum_var_type type) mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - running= master_info_index->give_error_if_slave_running(); + running= (!master_info_index || + master_info_index->give_error_if_slave_running()); mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_global_system_variables); @@ -2962,7 +2969,7 @@ Sys_var_replicate_events_marked_for_skip::global_update(THD *thd, set_var *var) mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - if (!master_info_index->give_error_if_slave_running()) + if (master_info_index && !master_info_index->give_error_if_slave_running()) result= Sys_var_enum::global_update(thd, var); mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_global_system_variables); @@ -3987,14 +3994,16 @@ static bool check_log_path(sys_var *self, THD *thd, set_var *var) if (!var->save_result.string_value.str) return true; - if (var->save_result.string_value.length > FN_REFLEN) + LEX_STRING *val= &var->save_result.string_value; + + if (val->length > FN_REFLEN) { // path is too long my_error(ER_PATH_LENGTH, MYF(0), self->name.str); return true; } char path[FN_REFLEN]; - size_t path_length= unpack_filename(path, var->save_result.string_value.str); + size_t path_length= unpack_filename(path, val->str); if (!path_length) return true; @@ -4007,6 +4016,17 @@ static bool check_log_path(sys_var *self, THD *thd, set_var *var) return true; } + static const LEX_CSTRING my_cnf= { STRING_WITH_LEN("my.cnf") }; + static const LEX_CSTRING my_ini= { STRING_WITH_LEN("my.ini") }; + if (path_length >= my_cnf.length) + { + if (strcasecmp(path + path_length - my_cnf.length, my_cnf.str) == 0) + return true; // log file name ends with "my.cnf" + DBUG_ASSERT(my_cnf.length == my_ini.length); + if (strcasecmp(path + path_length - my_ini.length, my_ini.str) == 0) + return true; // log file name ends with "my.ini" + } + MY_STAT f_stat; if (my_stat(path, &f_stat, MYF(0))) @@ -4016,9 +4036,9 @@ static bool check_log_path(sys_var *self, THD *thd, set_var *var) return false; } - (void) dirname_part(path, var->save_result.string_value.str, &path_length); + (void) dirname_part(path, val->str, &path_length); - if (var->save_result.string_value.length - path_length >= FN_LEN) + if (val->length - path_length >= FN_LEN) { // filename is too long my_error(ER_PATH_LENGTH, MYF(0), self->name.str); return true; |