From 14d959f7ff697047bfb92444090bd086a1fd8dd4 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Fri, 15 Jan 2010 17:52:46 +0000 Subject: BUG#49562: SBR out of sync when using numeric data types + user variable The User_var_log_event was not serializing the unsigned flag. This would cause the slave to always assume signed values. We fix this by extending the User_var_log_event to also contain information on the unsigned_flag, meaning that it gets into the binlog as well, therefore the slave will get this information as well. Events without information on unsigned flag (old events) are treated as they were before (always signed: unsigned_flag= FALSE). The information on the unsigned_flag, is shipped in an extra byte appended to the end of the User_var_log_event and added by this patch. This extra byte holds values for general purpose User_var_log_event flags which are now packed in the binlog as well. One of these flags contains information about whether the value is signed or unsigned (currently this extra byte is only used to hold data on the unsigned flag, in the future we can use it to pack extra flags if there is the need to). --- sql/log.cc | 9 ++++++++- sql/log_event.cc | 40 +++++++++++++++++++++++++++++++++++----- sql/log_event.h | 10 ++++++++-- 3 files changed, 51 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/log.cc b/sql/log.cc index 8781fb03031..ba3aed64f21 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4455,12 +4455,19 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) { BINLOG_USER_VAR_EVENT *user_var_event; get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i); + + /* setting flags for user var log event */ + uchar flags= User_var_log_event::UNDEF_F; + if (user_var_event->user_var_event->unsigned_flag) + flags|= User_var_log_event::UNSIGNED_F; + User_var_log_event e(thd, user_var_event->user_var_event->name.str, user_var_event->user_var_event->name.length, user_var_event->value, user_var_event->length, user_var_event->type, - user_var_event->charset_number); + user_var_event->charset_number, + flags); if (e.write(file)) goto err; } diff --git a/sql/log_event.cc b/sql/log_event.cc index ed47675d06a..e29eedb7611 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5460,7 +5460,9 @@ void User_var_log_event::pack_info(Protocol* protocol) case INT_RESULT: if (!(buf= (char*) my_malloc(val_offset + 22, MYF(MY_WME)))) return; - event_len= longlong10_to_str(uint8korr(val), buf + val_offset,-10)-buf; + event_len= longlong10_to_str(uint8korr(val), buf + val_offset, + ((flags & User_var_log_event::UNSIGNED_F) ? + 10 : -10))-buf; break; case DECIMAL_RESULT: { @@ -5518,12 +5520,14 @@ User_var_log_event(const char* buf, :Log_event(buf, description_event) { /* The Post-Header is empty. The Variable Data part begins immediately. */ + const char *start= buf; buf+= description_event->common_header_len + description_event->post_header_len[USER_VAR_EVENT-1]; name_len= uint4korr(buf); name= (char *) buf + UV_NAME_LEN_SIZE; buf+= UV_NAME_LEN_SIZE + name_len; is_null= (bool) *buf; + flags= User_var_log_event::UNDEF_F; // defaults to UNDEF_F if (is_null) { type= STRING_RESULT; @@ -5539,6 +5543,27 @@ User_var_log_event(const char* buf, UV_CHARSET_NUMBER_SIZE); val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE); + + /** + We need to check if this is from an old server + that did not pack information for flags. + We do this by checking if there are extra bytes + after the packed value. If there are we take the + extra byte and it's value is assumed to contain + the flags value. + + Old events will not have this extra byte, thence, + we keep the flags set to UNDEF_F. + */ + uint bytes_read= ((val + val_len) - start); + DBUG_ASSERT(bytes_read==data_written || + bytes_read==(data_written-1)); + if ((data_written - bytes_read) > 0) + { + flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE + + val_len); + } } } @@ -5550,6 +5575,7 @@ bool User_var_log_event::write(IO_CACHE* file) char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE]; uchar buf2[max(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos= buf2; + uint unsigned_len= 0; uint buf1_length; ulong event_length; @@ -5571,6 +5597,7 @@ bool User_var_log_event::write(IO_CACHE* file) break; case INT_RESULT: int8store(buf2, *(longlong*) val); + unsigned_len= 1; break; case DECIMAL_RESULT: { @@ -5595,13 +5622,14 @@ bool User_var_log_event::write(IO_CACHE* file) } /* Length of the whole event */ - event_length= sizeof(buf)+ name_len + buf1_length + val_len; + event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len; return (write_header(file, event_length) || my_b_safe_write(file, (uchar*) buf, sizeof(buf)) || my_b_safe_write(file, (uchar*) name, name_len) || my_b_safe_write(file, (uchar*) buf1, buf1_length) || - my_b_safe_write(file, pos, val_len)); + my_b_safe_write(file, pos, val_len) || + my_b_safe_write(file, (uchar*) &flags, unsigned_len)); } #endif @@ -5642,7 +5670,8 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) break; case INT_RESULT: char int_buf[22]; - longlong10_to_str(uint8korr(val), int_buf, -10); + longlong10_to_str(uint8korr(val), int_buf, + ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10)); my_b_printf(&cache, ":=%s%s\n", int_buf, print_event_info->delimiter); break; case DECIMAL_RESULT: @@ -5789,7 +5818,8 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli) a single record and with a single column. Thus, like a column value, it could always have IMPLICIT derivation. */ - e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0); + e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, + (flags & User_var_log_event::UNSIGNED_F)); free_root(thd->mem_root,0); return 0; diff --git a/sql/log_event.h b/sql/log_event.h index cba0264f4ae..9b91d826da7 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2483,6 +2483,10 @@ private: class User_var_log_event: public Log_event { public: + enum { + UNDEF_F= 0, + UNSIGNED_F= 1 + }; char *name; uint name_len; char *val; @@ -2490,12 +2494,14 @@ public: Item_result type; uint charset_number; bool is_null; + uchar flags; #ifndef MYSQL_CLIENT User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg, char *val_arg, ulong val_len_arg, Item_result type_arg, - uint charset_number_arg) + uint charset_number_arg, uchar flags_arg) :Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg), - val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg) + val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg), + flags(flags_arg) { is_null= !val; } void pack_info(Protocol* protocol); #else -- cgit v1.2.1 From d4ae3e28d6c11144ec911f263f788e0fe74a939f Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 18 Jan 2010 09:11:28 +0000 Subject: BUG#49562: SBR out of sync when using numeric data types + user variable Incremental commit: 1. Moved part of the test case to binlog suite. 2. Removed cast set when writing the flags field. --- sql/log_event.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/log_event.cc b/sql/log_event.cc index e29eedb7611..c085815b777 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5629,7 +5629,7 @@ bool User_var_log_event::write(IO_CACHE* file) my_b_safe_write(file, (uchar*) name, name_len) || my_b_safe_write(file, (uchar*) buf1, buf1_length) || my_b_safe_write(file, pos, val_len) || - my_b_safe_write(file, (uchar*) &flags, unsigned_len)); + my_b_safe_write(file, &flags, unsigned_len)); } #endif -- cgit v1.2.1 From 0c906be9a00bf4ae93a5b5713504352a554659bc Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 21 Jan 2010 00:41:32 +0000 Subject: BUG#50474: rpl_slave_load_remove_tmpfile failed on windows debug enabled binary The test case injects an error in the server by deleting the temporary file that it uses during the load data statement execution. The error consisted of closing, deleting and setting the file descriptor to -1 right before calling mysql_file_write. Although, this error injection seems to work OK in Unix like environments, in Windows, this would cause the server to hit an assertion in 'my_get_open_flags': DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit) We fix this by changing the error injection to just call the macro my_delete_allow_opened, instead of the close + delete + set fd=-1. The macro deletes the file and is platform independent. Additionally, this required some changes to how the assertion is handled in the test case to make it cope with this change. --- sql/log_event.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/log_event.cc b/sql/log_event.cc index 985d2110c9b..758d0aad06f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6355,9 +6355,7 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) DBUG_EXECUTE_IF("remove_slave_load_file_before_write", { - mysql_file_close(fd, MYF(0)); - fd= -1; - mysql_file_delete(0, fname, MYF(0)); + my_delete_allow_opened(fname, MYF(0)); }); if (mysql_file_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) -- cgit v1.2.1 From 8da3fea266b14fa8734f163108dac4edf240346c Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 21 Jan 2010 13:10:34 +0000 Subject: BUG#46364 MyISAM transbuffer problems (NTM problem) It is well-known that due to concurrency issues, a slave can become inconsistent when a transaction contains updates to both transaction and non-transactional tables. In a nutshell, the current code-base tries to preserve causality among the statements by writing non-transactional statements to the txn-cache which is flushed upon commit. However, modifications done to non-transactional tables on behalf of a transaction become immediately visible to other connections but may not immediately get into the binary log and therefore consistency may be broken. In general, it is impossible to automatically detect causality/dependency among statements by just analyzing the statements sent to the server. This happen because dependency may be hidden in the application code and it is necessary to know a priori all the statements processed in the context of a transaction such as in a procedure. Moreover, even for the few cases that we could automatically address in the server, the computation effort required could make the approach infeasible. So, in this patch we introduce the option - "--binlog-direct-non-transactional-updates" that can be used to bypass the current behavior in order to write directly to binary log statements that change non-transactional tables. Besides, it is used to enable the WL#2687 which is disabled by default. --- sql/log.cc | 150 ++++++++++++++++++++++------------------------ sql/log.h | 5 +- sql/share/errmsg-utf8.txt | 5 ++ sql/share/errmsg.txt | 4 ++ sql/sql_class.h | 1 + sql/sys_vars.cc | 42 +++++++++++++ 6 files changed, 127 insertions(+), 80 deletions(-) (limited to 'sql') diff --git a/sql/log.cc b/sql/log.cc index 72d0ed43463..24a5caa9234 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -199,7 +199,7 @@ private: class binlog_cache_data { public: - binlog_cache_data(): m_pending(0), before_stmt_pos (MY_OFF_T_UNDEF), + binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF), incident(FALSE) { cache_log.end_of_file= max_binlog_cache_size; @@ -1760,7 +1760,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) binlog_flush_stmt_cache(thd, cache_mngr); } - if (cache_mngr->trx_cache.empty()) + if (cache_mngr->trx_cache.empty()) { /* we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid() @@ -1769,7 +1769,6 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) DBUG_RETURN(0); } - if (mysql_bin_log.check_write_error(thd)) { /* @@ -1909,7 +1908,7 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ - if (unlikely(thd->transaction.all.modified_non_trans_table || + if (unlikely(thd->transaction.all.modified_non_trans_table || (thd->variables.option_bits & OPTION_KEEP_LOG))) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); @@ -4191,6 +4190,66 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param) query_id_param >= thd->binlog_evt_union.first_query_id); } +/** + This function checks if a transactional talbe was updated by the + current transaction. + + @param thd The client thread that executed the current statement. + @return + @c true if a transactional table was updated, @c false otherwise. +*/ +bool +trans_has_updated_trans_table(const THD* thd) +{ + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + return (cache_mngr ? my_b_tell (&cache_mngr->trx_cache.cache_log) : 0); +} + +/** + This function checks if a transactional talbe was updated by the + current statement. + + @param thd The client thread that executed the current statement. + @return + @c true if a transactional table was updated, @c false otherwise. +*/ +bool +stmt_has_updated_trans_table(const THD *thd) +{ + Ha_trx_info *ha_info; + + for (ha_info= thd->transaction.stmt.ha_list; ha_info; ha_info= ha_info->next()) + { + if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) + return (TRUE); + } + return (FALSE); +} + +/** + This function checks if either a trx-cache or a non-trx-cache should + be used. If @c bin_log_direct_non_trans_update is active, the cache + to be used depends on the flag @c is_transactional. + + Otherswise, we use the trx-cache if either the @c is_transactional + is true or the trx-cache is not empty. + + @param thd The client thread. + @param is_transactional The changes are related to a trx-table. + @return + @c true if a trx-cache should be used, @c false otherwise. +*/ +bool use_trans_cache(const THD* thd, bool is_transactional) +{ + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + return + (thd->variables.binlog_direct_non_trans_update ? is_transactional : + (cache_mngr->trx_cache.empty() && !is_transactional ? FALSE : TRUE)); +} /* These functions are placed in this file since they need access to @@ -4223,44 +4282,6 @@ int THD::binlog_setup_trx_data() DBUG_RETURN(0); } -/** - This function checks if a transactional talbe was updated by the - current transaction. - - @param thd The client thread that executed the current statement. - @return - @c true if a transactional table was updated, @false otherwise. -*/ -bool -trans_has_updated_trans_table(THD* thd) -{ - binlog_cache_mngr *const cache_mngr= - (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - - return (cache_mngr ? my_b_tell (&cache_mngr->trx_cache.cache_log) : 0); -} - -/** - This function checks if a transactional talbe was updated by the - current statement. - - @param thd The client thread that executed the current statement. - @return - @c true if a transactional table was updated, @false otherwise. -*/ -bool -stmt_has_updated_trans_table(THD *thd) -{ - Ha_trx_info *ha_info; - - for (ha_info= thd->transaction.stmt.ha_list; ha_info; ha_info= ha_info->next()) - { - if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) - return (TRUE); - } - return (FALSE); -} - /* Function to start a statement and optionally a transaction for the binary log. @@ -4369,8 +4390,8 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional) binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); - IO_CACHE *file= cache_mngr->get_binlog_cache_log(is_transactional); - + IO_CACHE *file= + cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional)); if ((error= the_event.write(file))) DBUG_RETURN(error); @@ -4405,7 +4426,7 @@ THD::binlog_get_pending_rows_event(bool is_transactional) const if (cache_mngr) { binlog_cache_data *cache_data= - cache_mngr->get_binlog_cache_data(is_transactional); + cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional)); rows= cache_data->pending(); } @@ -4434,7 +4455,7 @@ THD::binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional) DBUG_ASSERT(cache_mngr); binlog_cache_data *cache_data= - cache_mngr->get_binlog_cache_data(is_transactional); + cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional)); cache_data->set_pending(ev); } @@ -4460,7 +4481,7 @@ MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd, bool is_transactional) DBUG_ASSERT(cache_mngr); binlog_cache_data *cache_data= - cache_mngr->get_binlog_cache_data(is_transactional); + cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional)); if (Rows_log_event* pending= cache_data->pending()) { @@ -4497,7 +4518,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, DBUG_ASSERT(cache_mngr); binlog_cache_data *cache_data= - cache_mngr->get_binlog_cache_data(is_transactional); + cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional)); DBUG_PRINT("info", ("cache_mngr->pending(): 0x%lx", (long) cache_data->pending())); @@ -4608,35 +4629,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - /* - If we are about to use write rows, we just need to check the type of - the event (either transactional or non-transactional) in order to - choose the cache. - */ - if (thd->is_current_stmt_binlog_format_row()) - { - file= cache_mngr->get_binlog_cache_log(event_info->use_trans_cache()); - cache_data= cache_mngr->get_binlog_cache_data(event_info->use_trans_cache()); - } - /* - However, if we are about to write statements we need to consider other - things. We use the non-transactional cache when: - - . the transactional cache is empty which means that there were no - early statement on behalf of the transaction. - . the respective event is tagged as non-transactional. - */ - else if (cache_mngr->trx_cache.empty() && - !event_info->use_trans_cache()) - { - file= &cache_mngr->stmt_cache.cache_log; - cache_data= &cache_mngr->stmt_cache; - } - else - { - file= &cache_mngr->trx_cache.cache_log; - cache_data= &cache_mngr->trx_cache; - } + bool is_trans_cache= use_trans_cache(thd, event_info->use_trans_cache()); + file= cache_mngr->get_binlog_cache_log(is_trans_cache); + cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache); thd->binlog_start_trans_and_stmt(); } @@ -4898,7 +4893,6 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log) do { - /* if we only got a partial header in the last iteration, get the other half now and process a full header. diff --git a/sql/log.h b/sql/log.h index 5e13d153db8..e9429067a34 100644 --- a/sql/log.h +++ b/sql/log.h @@ -20,8 +20,9 @@ class Relay_log_info; class Format_description_log_event; -bool trans_has_updated_trans_table(THD* thd); -bool stmt_has_updated_trans_table(THD *thd); +bool trans_has_updated_trans_table(const THD* thd); +bool stmt_has_updated_trans_table(const THD *thd); +bool use_trans_cache(const THD* thd, bool is_transactional); /* Transaction Coordinator log - a base abstract class diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index dc07fb563e6..92c86cf6e00 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6311,3 +6311,8 @@ ER_WRONG_NATIVE_TABLE_STRUCTURE ER_WRONG_PERFSCHEMA_USAGE eng "Invalid performance_schema usage." + +ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT + eng "Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction" +ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT + eng "Cannot change the binlog direct flag inside a stored function or trigger" diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 4ee0cf9d758..51bb83f07b9 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6305,3 +6305,7 @@ ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT eng "The syntax '%s' is deprecated and will be removed in MySQL %s." ger "Die Syntax '%s' ist veraltet und wird in MySQL %s entfernt." +ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT + eng "Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction" +ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT + eng "Cannot change the binlog direct flag inside a stored function or trigger" diff --git a/sql/sql_class.h b/sql/sql_class.h index d413202a8da..9db58b50f7a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -373,6 +373,7 @@ typedef struct system_variables ulong group_concat_max_len; uint binlog_format; ///< binlog format for this thd (see enum_binlog_format) + my_bool binlog_direct_non_trans_update; uint completion_type; uint query_cache_type; uint tx_isolation; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 0d6c3327f24..fe3114c9d50 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -299,6 +299,48 @@ static Sys_var_enum Sys_binlog_format( NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(binlog_format_check), ON_UPDATE(fix_binlog_format_after_update)); +static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var) +{ + /* + Makes the session variable 'binlog_direct_non_transactional_updates' + read-only inside a transaction. + */ + if (thd->active_transaction() && (var->type == OPT_SESSION)) + { + my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); + return 1; + } + /* + Makes the session variable 'binlog_direct_non_transactional_updates' + read-only if within a procedure, trigger or function. + */ + if (thd->in_sub_stmt) + { + my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); + return 1; + } + + if (check_has_super(self, thd, var)) + return true; + if (var->type == OPT_GLOBAL || + (thd->variables.binlog_direct_non_trans_update == + var->save_result.ulonglong_value)) + return false; + + return false; +} + +static Sys_var_mybool Sys_binlog_direct( + "binlog_direct_non_transactional_updates", + "Causes updates to non-transactional engines using statement format to " + "be written directly to binary log. Before using this option make sure " + "that there are no dependencies between transactional and " + "non-transactional tables such as in the statement INSERT INTO t_myisam " + "SELECT * FROM t_innodb; otherwise, slaves may diverge from the master.", + SESSION_VAR(binlog_direct_non_trans_update), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(binlog_direct_check)); + static Sys_var_ulong Sys_bulk_insert_buff_size( "bulk_insert_buffer_size", "Size of tree cache used in bulk " "insert optimisation. Note that this is a limit per thread!", -- cgit v1.2.1 From cc8caa7d9ef6376bb41fa5262695538de70c075f Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Thu, 21 Jan 2010 11:06:03 -0700 Subject: Bug#50513 Build failure with ifdef HAVE_OPENSSL + ifndef HAVE_YASSL When compiling wiht ./configure --with-ssl=/usr, which used OPEN_SSL but not YASSL, the code in sql/mysqld.cc failed to build because of an incomplete performance schema instrumentation. This fix implements properly the instrumentation for the rwlock used in openssl_lock_t. Verified that the code builds, and the ssl + performance schema tests do pass. --- sql/mysqld.cc | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6a9fd8ee37b..ba61eaa62df 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -316,6 +316,10 @@ static PSI_thread_key key_thread_handle_con_sockets; #ifdef __WIN__ static PSI_thread_key key_thread_handle_shutdown; #endif /* __WIN__ */ + +#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL) +static PSI_rwlock_key key_rwlock_openssl; +#endif #endif /* HAVE_PSI_INTERFACE */ /* the default log output is log tables */ @@ -1538,7 +1542,7 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_des_key_file); #ifndef HAVE_YASSL for (int i= 0; i < CRYPTO_num_locks(); ++i) - rwlock_destroy(&openssl_stdlocks[i].lock); + mysql_rwlock_destroy(&openssl_stdlocks[i].lock); OPENSSL_free(openssl_stdlocks); #endif #endif @@ -3737,7 +3741,7 @@ static int init_thread_environment() openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(openssl_lock_t)); for (int i= 0; i < CRYPTO_num_locks(); ++i) - my_rwlock_init(&openssl_stdlocks[i].lock, NULL); + mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock); CRYPTO_set_dynlock_create_callback(openssl_dynlock_create); CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy); CRYPTO_set_dynlock_lock_callback(openssl_lock); @@ -3791,7 +3795,7 @@ static unsigned long openssl_id_function() static openssl_lock_t *openssl_dynlock_create(const char *file, int line) { openssl_lock_t *lock= new openssl_lock_t; - my_rwlock_init(&lock->lock, NULL); + mysql_rwlock_init(key_rwlock_openssl, &lock->lock); return lock; } @@ -3799,7 +3803,7 @@ static openssl_lock_t *openssl_dynlock_create(const char *file, int line) static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file, int line) { - rwlock_destroy(&lock->lock); + mysql_rwlock_destroy(&lock->lock); delete lock; } @@ -3825,16 +3829,16 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, switch (mode) { case CRYPTO_LOCK|CRYPTO_READ: what = "read lock"; - err = rw_rdlock(&lock->lock); + err= mysql_rwlock_rdlock(&lock->lock); break; case CRYPTO_LOCK|CRYPTO_WRITE: what = "write lock"; - err = rw_wrlock(&lock->lock); + err= mysql_rwlock_wrlock(&lock->lock); break; case CRYPTO_UNLOCK|CRYPTO_READ: case CRYPTO_UNLOCK|CRYPTO_WRITE: what = "unlock"; - err = rw_unlock(&lock->lock); + err= mysql_rwlock_unlock(&lock->lock); break; default: /* Unknown locking mode. */ @@ -7975,6 +7979,9 @@ PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, static PSI_rwlock_info all_server_rwlocks[]= { +#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL) + { &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0}, +#endif { &key_rwlock_LOCK_grant, "LOCK_grant", PSI_FLAG_GLOBAL}, { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0}, { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL}, -- cgit v1.2.1 From 8976595d827e7c29000d02b2f4431d4177d8e427 Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Fri, 22 Jan 2010 17:08:49 +0100 Subject: Backport from mysql-6.0-codebase of: ------------------------------------------------------------ revno: 2630.22.42 committer: Konstantin Osipov branch nick: mysql-6.0-runtime timestamp: Fri 2008-10-17 14:36:55 +0400 message: Update old wording (table engine -> storage engine). --- sql/share/errmsg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 51bb83f07b9..31e630d5fea 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5015,7 +5015,7 @@ ER_WARN_HOSTNAME_WONT_WORK por "MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar" spa "MySQL esta inicializado en modo --skip-name-resolve. Usted necesita reinicializarlo sin esta opción para este derecho funcionar" ER_UNKNOWN_STORAGE_ENGINE 42000 - eng "Unknown table engine '%s'" + eng "Unknown storage engine '%s'" ger "Unbekannte Speicher-Engine '%s'" por "Motor de tabela desconhecido '%s'" spa "Desconocido motor de tabla '%s'" -- cgit v1.2.1 From dba07c73960eba1dc1e961a22a07eb6e1998e532 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Fri, 22 Jan 2010 19:00:19 -0700 Subject: Bug#11714 Non-sensical ALTER TABLE ADD CONSTRAINT allowed Bug#35578 Parser allows useless/illegal CREATE TABLE syntax Bug#38696 CREATE TABLE ... CHECK ... allows illegal syntax Backport from 6.0 to mysql-next-mr. --- sql/sql_yacc.yy | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ab128a9b701..aebf80e340f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -765,10 +765,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there are 172 shift/reduce conflicts. + Currently there are 169 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 172 +%expect 169 /* Comments for TOKENS. @@ -5282,10 +5282,6 @@ key_def: /* Only used for ALTER TABLE. Ignored otherwise. */ lex->alter_info.flags|= ALTER_FOREIGN_KEY; } - | constraint opt_check_constraint - { - Lex->col_list.empty(); /* Alloced by sql_alloc */ - } | opt_constraint check_constraint { Lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -5298,7 +5294,7 @@ opt_check_constraint: ; check_constraint: - CHECK_SYM expr + CHECK_SYM '(' expr ')' ; opt_constraint: -- cgit v1.2.1 From 4428409ddb337eb4c8a290656aeb56e64d8d8de6 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 25 Jan 2010 04:55:31 -0700 Subject: Bug#34455 Ambiguous foreign keys syntax is accepted Backport from 6.0 to 5.5 --- sql/sql_lex.h | 4 ++- sql/sql_yacc.yy | 93 ++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 31 deletions(-) (limited to 'sql') diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 800a16cf2b6..7eb72bc5358 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1903,7 +1903,9 @@ struct LEX: public Query_tables_list uint profile_options; uint uint_geom_type; uint grant, grant_tot_col, which_columns; - uint fk_delete_opt, fk_update_opt, fk_match_option; + enum Foreign_key::fk_match_opt fk_match_option; + enum Foreign_key::fk_option fk_update_opt; + enum Foreign_key::fk_option fk_delete_opt; uint slave_thd_opt, start_transaction_opt; int nest_level; /* diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index aebf80e340f..5e900b69aa3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -756,6 +756,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type, struct p_elem_val *p_elem_value; enum index_hint_type index_hint; enum enum_filetype filetype; + enum Foreign_key::fk_option m_fk_option; Diag_condition_item_name diag_condition_item_name; } @@ -1422,7 +1423,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); type type_with_opt_collate int_type real_type order_dir lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_no_write_to_binlog - delete_option opt_temporary all_or_any opt_distinct + opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option start_transaction_opts opt_chain opt_release union_opt select_derived_init option_type2 @@ -1430,6 +1431,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt +%type + delete_option + %type ulong_num real_ulong_num merge_insert_types @@ -1544,7 +1548,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_precision opt_ignore opt_column opt_restrict grant revoke set lock unlock string_list field_options field_option field_opt_list opt_binary ascii unicode table_lock_list table_lock - ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use + ref_list opt_match_clause opt_on_update_delete use opt_delete_options opt_delete_option varchar nchar nvarchar opt_outer table_list table_name table_alias_ref_list table_alias_ref opt_option opt_place @@ -5833,21 +5837,20 @@ opt_primary: ; references: - REFERENCES table_ident - { - LEX *lex=Lex; - lex->fk_delete_opt= lex->fk_update_opt= lex->fk_match_option= 0; - lex->ref_list.empty(); - } + REFERENCES + table_ident opt_ref_list + opt_match_clause + opt_on_update_delete { $$=$2; } ; opt_ref_list: - /* empty */ opt_on_delete {} - | '(' ref_list ')' opt_on_delete {} + /* empty */ + { Lex->ref_list.empty(); } + | '(' ref_list ')' ; ref_list: @@ -5863,34 +5866,64 @@ ref_list: Key_part_spec *key= new Key_part_spec($1, 0); if (key == NULL) MYSQL_YYABORT; - Lex->ref_list.push_back(key); + LEX *lex= Lex; + lex->ref_list.empty(); + lex->ref_list.push_back(key); } ; -opt_on_delete: - /* empty */ {} - | opt_on_delete_list {} - ; - -opt_on_delete_list: - opt_on_delete_list opt_on_delete_item {} - | opt_on_delete_item {} +opt_match_clause: + /* empty */ + { Lex->fk_match_option= Foreign_key::FK_MATCH_UNDEF; } + | MATCH FULL + { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; } + | MATCH PARTIAL + { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; } + | MATCH SIMPLE_SYM + { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; } ; -opt_on_delete_item: - ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; } - | ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; } - | MATCH FULL { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; } - | MATCH PARTIAL { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; } - | MATCH SIMPLE_SYM { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; } +opt_on_update_delete: + /* empty */ + { + LEX *lex= Lex; + lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF; + lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF; + } + | ON UPDATE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= $3; + lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF; + } + | ON DELETE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF; + lex->fk_delete_opt= $3; + } + | ON UPDATE_SYM delete_option + ON DELETE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= $3; + lex->fk_delete_opt= $6; + } + | ON DELETE_SYM delete_option + ON UPDATE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= $6; + lex->fk_delete_opt= $3; + } ; delete_option: - RESTRICT { $$= (int) Foreign_key::FK_OPTION_RESTRICT; } - | CASCADE { $$= (int) Foreign_key::FK_OPTION_CASCADE; } - | SET NULL_SYM { $$= (int) Foreign_key::FK_OPTION_SET_NULL; } - | NO_SYM ACTION { $$= (int) Foreign_key::FK_OPTION_NO_ACTION; } - | SET DEFAULT { $$= (int) Foreign_key::FK_OPTION_DEFAULT; } + RESTRICT { $$= Foreign_key::FK_OPTION_RESTRICT; } + | CASCADE { $$= Foreign_key::FK_OPTION_CASCADE; } + | SET NULL_SYM { $$= Foreign_key::FK_OPTION_SET_NULL; } + | NO_SYM ACTION { $$= Foreign_key::FK_OPTION_NO_ACTION; } + | SET DEFAULT { $$= Foreign_key::FK_OPTION_DEFAULT; } ; normal_key_type: -- cgit v1.2.1 From 51af6729f242aab68937ac73c3401d5c5a3983c2 Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Mon, 25 Jan 2010 22:34:34 +0100 Subject: Patch to eliminate warnings in mysql-next-mr-bugteam. --- sql/repl_failsafe.cc | 2 +- sql/repl_failsafe.h | 2 +- sql/rpl_injector.cc | 12 ++++++------ sql/rpl_mi.cc | 4 ++-- sql/slave.cc | 12 ++++++------ sql/sql_class.cc | 6 +++--- sql/sql_db.cc | 2 +- sql/sql_parse.cc | 2 +- sql/sql_repl.cc | 4 ++-- sql/sql_table.cc | 2 +- sql/sys_vars.cc | 2 +- 11 files changed, 25 insertions(+), 25 deletions(-) (limited to 'sql') diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 5bf87dea90e..29443eb6e65 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -38,7 +38,7 @@ #define SLAVE_ERRMSG_SIZE (FN_REFLEN+64) -uint rpl_status=RPL_NULL; +RPL_STATUS rpl_status=RPL_NULL; mysql_mutex_t LOCK_rpl_status; mysql_cond_t COND_rpl_status; HASH slave_list; diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h index dd6770be0b4..94b151aaee7 100644 --- a/sql/repl_failsafe.h +++ b/sql/repl_failsafe.h @@ -26,7 +26,7 @@ typedef enum {RPL_AUTH_MASTER=0,RPL_IDLE_SLAVE,RPL_ACTIVE_SLAVE, RPL_LOST_SOLDIER,RPL_TROOP_SOLDIER, RPL_RECOVERY_CAPTAIN,RPL_NULL /* inactive */, RPL_ANY /* wild card used by change_rpl_status */ } RPL_STATUS; -extern uint rpl_status; +extern RPL_STATUS rpl_status; extern mysql_mutex_t LOCK_rpl_status; extern mysql_cond_t COND_rpl_status; diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index ac879b5033f..64f79092057 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -112,8 +112,8 @@ int injector::transaction::write_row (server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::write_row(...)"); - int error= 0; - if (error= check_state(ROW_STATE)) + int error= check_state(ROW_STATE); + if (error) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; @@ -131,8 +131,8 @@ int injector::transaction::delete_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::delete_row(...)"); - int error= 0; - if (error= check_state(ROW_STATE)) + int error= check_state(ROW_STATE); + if (error) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; @@ -150,8 +150,8 @@ int injector::transaction::update_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::update_row(...)"); - int error= 0; - if (error= check_state(ROW_STATE)) + int error= check_state(ROW_STATE); + if (error) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 38382fd2a0e..7f81834c1d3 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -33,8 +33,8 @@ int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f); Master_info::Master_info(bool is_slave_recovery) :Slave_reporting_capability("I/O"), ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), - port(MYSQL_PORT), connect_retry(DEFAULT_CONNECT_RETRY), inited(0), - rli(is_slave_recovery), abort_slave(0), + rli(is_slave_recovery), port(MYSQL_PORT), + connect_retry(DEFAULT_CONNECT_RETRY), inited(0), abort_slave(0), slave_running(0), slave_run_id(0), sync_counter(0), heartbeat_period(0), received_heartbeats(0), master_id(0) { diff --git a/sql/slave.cc b/sql/slave.cc index a4f16f6ed28..af43b39c63b 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1111,7 +1111,7 @@ int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f) memcpy(buf_act, buf, read_size); snd_size= my_b_gets(f, buf_act + read_size, max_size - read_size); if (snd_size == 0 || - (snd_size + 1 == max_size - read_size) && buf[max_size - 2] != '\n') + ((snd_size + 1 == max_size - read_size) && buf[max_size - 2] != '\n')) { /* failure to make the 2nd read or short read again @@ -3943,8 +3943,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) /* everything is filtered out from non-master */ (s_id != mi->master_id || /* for the master meta information is necessary */ - buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && - buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT))) + (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && + buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT)))) { /* Do not write it to the relay log. @@ -3964,9 +3964,9 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) as well as rli->group_relay_log_pos. */ if (!(s_id == ::server_id && !mi->rli.replicate_same_server_id) || - buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && - buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT && - buf[EVENT_TYPE_OFFSET] != STOP_EVENT) + (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && + buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT && + buf[EVENT_TYPE_OFFSET] != STOP_EVENT)) { mi->master_log_pos+= inc_pos; memcpy(rli->ign_master_log_name_end, mi->master_log_name, FN_REFLEN); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 28e5e56d8b9..d02d69aca0c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3531,7 +3531,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) { DBUG_ENTER("THD::decide_logging_format"); DBUG_PRINT("info", ("query: %s", query())); - DBUG_PRINT("info", ("variables.binlog_format: %ld", + DBUG_PRINT("info", ("variables.binlog_format: %u", variables.binlog_format)); DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x", lex->get_stmt_unsafe_flags())); @@ -3672,7 +3672,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) lock history on the slave will be different from the master. */ if (mixed_engine || - trans_has_updated_trans_table(this) && !all_trans_engines) + (trans_has_updated_trans_table(this) && !all_trans_engines)) lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS); DBUG_PRINT("info", ("flags_all_set: 0x%llx", flags_all_set)); @@ -3802,7 +3802,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) DBUG_PRINT("info", ("decision: no logging since " "mysql_bin_log.is_open() = %d " "and (options & OPTION_BIN_LOG) = 0x%llx " - "and binlog_format = %ld " + "and binlog_format = %u " "and binlog_filter->db_ok(db) = %d", mysql_bin_log.is_open(), (variables.option_bits & OPTION_BIN_LOG), diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 9fef7114898..4cb47c7b2df 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -854,7 +854,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - if (error= mysql_bin_log.write(&qinfo)) + if ((error= mysql_bin_log.write(&qinfo))) goto exit; } my_ok(thd, result); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5c272353664..bef00b13978 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3887,7 +3887,7 @@ end_with_restore_list: */ if (!lex->no_write_to_binlog && write_to_binlog) { - if (res= write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + if ((res= write_bin_log(thd, FALSE, thd->query(), thd->query_length()))) break; } my_ok(thd); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 00cc28e6213..1fb0fcaf6dd 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -828,11 +828,11 @@ impossible position"; { if (coord) { - DBUG_ASSERT(heartbeat_ts && heartbeat_period != LL(0)); + DBUG_ASSERT(heartbeat_ts && heartbeat_period != 0); set_timespec_nsec(*heartbeat_ts, heartbeat_period); } ret= mysql_bin_log.wait_for_update_bin_log(thd, heartbeat_ts); - DBUG_ASSERT(ret == 0 || heartbeat_period != LL(0) && coord != NULL); + DBUG_ASSERT(ret == 0 || (heartbeat_period != 0 && coord != NULL)); if (ret == ETIMEDOUT || ret == ETIME) { #ifndef DBUG_OFF diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e87e52d5819..1e06b070494 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6533,7 +6533,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->clear_error(); Query_log_event qinfo(thd, thd->query(), thd->query_length(), FALSE, TRUE, FALSE, 0); - if (error= mysql_bin_log.write(&qinfo)) + if ((error= mysql_bin_log.write(&qinfo))) goto view_err_unlock; } my_ok(thd); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index fe3114c9d50..eb7781be5b9 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -324,7 +324,7 @@ static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var) return true; if (var->type == OPT_GLOBAL || (thd->variables.binlog_direct_non_trans_update == - var->save_result.ulonglong_value)) + static_cast(var->save_result.ulonglong_value))) return false; return false; -- cgit v1.2.1 From bc5479101045014d2a2c9c6cc7c7d358e87a6530 Mon Sep 17 00:00:00 2001 From: Guilhem Bichot Date: Mon, 25 Jan 2010 23:19:34 +0100 Subject: fixes for gcc 4.4.1 warnings --- sql/mysql_priv.h | 1 + sql/mysqld.cc | 25 +++++++++++++------------ sql/sql_select.cc | 2 +- sql/sql_yacc.yy | 4 ++-- sql/sys_vars.cc | 4 ++-- 5 files changed, 19 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4d5490e8219..6e35291b1c7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -235,6 +235,7 @@ typedef struct my_locale_errmsgs extern char err_shared_dir[]; +/** @note Keep this a POD-type because we use offsetof() on it */ typedef struct my_locale_st { uint number; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 756ce7be5dc..05442643e23 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -928,8 +928,6 @@ static bool add_terminator(DYNAMIC_ARRAY *options); extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *); static void set_server_version(void); static int init_thread_environment(); -static void init_error_log_mutex(); -static void clean_up_error_log_mutex(); static char *get_relative_path(const char *path); static int fix_paths(void); void handle_connections_sockets(); @@ -1346,6 +1344,18 @@ extern "C" sig_handler print_signal_warning(int sig) #ifndef EMBEDDED_LIBRARY +static void init_error_log_mutex() +{ + mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST); +} + + +static void clean_up_error_log_mutex() +{ + mysql_mutex_destroy(&LOCK_error_log); +} + + /** cleanup all memory and end program nicely. @@ -3360,7 +3370,7 @@ static int init_common_variables() set the def_value member to 0 in my_long_options and initialize it to the correct value here. */ - default_storage_engine="MyISAM"; + default_storage_engine= const_cast("MyISAM"); /* Add server status variables to the dynamic list of @@ -3701,15 +3711,6 @@ You should consider changing lower_case_table_names to 1 or 2", return 0; } -static void init_error_log_mutex() -{ - mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST); -} - -static void clean_up_error_log_mutex() -{ - mysql_mutex_destroy(&LOCK_error_log); -} static int init_thread_environment() { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4775a297b0c..030c12de897 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4378,7 +4378,7 @@ best_access_path(JOIN *join, */ if (table->quick_keys.is_set(key) && (const_part & ((1 << table->quick_key_parts[key])-1)) == - ((1 << table->quick_key_parts[key])-1) && + (((key_part_map)1 << table->quick_key_parts[key])-1) && table->quick_n_ranges[key] == 1 && records > (double) table->quick_rows[key]) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ab128a9b701..5ee6f292204 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9218,8 +9218,8 @@ table_factor: lex->pop_context(); lex->nest_level--; } - else if ($3->select_lex && - $3->select_lex->master_unit()->is_union() || $5) + else if (($3->select_lex && + $3->select_lex->master_unit()->is_union()) || $5) { /* simple nested joins cannot have aliases or unions */ my_parse_error(ER(ER_SYNTAX_ERROR)); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index fe3114c9d50..e4dc0026128 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2956,14 +2956,14 @@ static bool check_locale(sys_var *self, THD *thd, set_var *var) static Sys_var_struct Sys_lc_messages( "lc_messages", "Set the language used for the error messages", SESSION_VAR(lc_messages), NO_CMD_LINE, - offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_messages), + my_offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_messages), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_locale)); static Sys_var_struct Sys_lc_time_names( "lc_time_names", "Set the language used for the month " "names and the days of the week", SESSION_VAR(lc_time_names), NO_CMD_LINE, - offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_time_names), + my_offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_time_names), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_locale)); static Sys_var_tz Sys_time_zone( -- cgit v1.2.1 From 0c4b0e9a3aad7550da2980af0db06a277687e1c7 Mon Sep 17 00:00:00 2001 From: Date: Tue, 26 Jan 2010 17:41:15 +0800 Subject: Bug #45855 row events in binlog after switch from binlog_fmt=mix to stmt with open tmp tbl Bug #45856 can't switch from binlog_format=row to mix with open tmp tbl If binlog_format=MIXED, there are open temporary tables, an unsafe statement is executed, and the user issues 'SET @@session.binlog_format = STATEMENT', then subsequent DML statements will be written in row format despite binlog_format=STATEMENT. Because the binlog format can't be reset to statement based by 'reset_current_stmt_binlog_row_based' function. If binlog_format=ROW, there are open temporary tables, and an unsafe statement is executed, then the statement 'SET @@session.binlog_format = MIXED' generates the error: "Cannot switch out of the row-based binary log format when the session has open temporary tables" However, it is safe to switch to MIXED mode because events in row format are allowed. To fix the above two problems, generate ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR and forbid switching from MIXED or ROW to STATEMENT when there are open temp tables and we are logging in row format. There is no error in any other case. --- sql/set_var.cc | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/set_var.cc b/sql/set_var.cc index d9bd14564bf..9dfbf2c7a6c 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1294,32 +1294,34 @@ bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) { bool result= sys_var_thd_enum::check(thd, var); if (!result) result= check_log_update(thd, var); - return result; -} - -bool sys_var_thd_binlog_format::is_readonly() const -{ - /* - Under certain circumstances, the variable is read-only (unchangeable): - */ - THD *thd= current_thd; /* If RBR and open temporary tables, their CREATE TABLE may not be in the binlog, so we can't toggle to SBR in this connection. - The test below will also prevent SET GLOBAL, well it was not easy to test - if global or not here. - And this test will also prevent switching from RBR to RBR (a no-op which - should not happen too often). - If we don't have row-based replication compiled in, the variable - is always read-only. + If binlog_format=MIXED, there are open temporary tables, and an unsafe + statement is executed, then subsequent statements are logged in row + format and hence changes to temporary tables may be lost. So we forbid + switching @@SESSION.binlog_format from MIXED to STATEMENT when there are + open temp tables and we are logging in row format. */ - if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) && - thd->temporary_tables) + if (thd->temporary_tables && var->type == OPT_SESSION && + var->save_result.ulong_value == BINLOG_FORMAT_STMT && + ((thd->variables.binlog_format == BINLOG_FORMAT_MIXED && + thd->is_current_stmt_binlog_format_row()) || + thd->variables.binlog_format == BINLOG_FORMAT_ROW)) { my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0)); return 1; } + return result; +} + +bool sys_var_thd_binlog_format::is_readonly() const +{ + /* + Under certain circumstances, the variable is read-only (unchangeable): + */ + THD *thd= current_thd; /* if in a stored function/trigger, it's too late to change mode */ -- cgit v1.2.1 From 7db8e764714ddb7901400000fa1dfe45263b4773 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Fri, 29 Jan 2010 15:55:35 +0200 Subject: Bug #50192 Strange effect in replication test, trigger, auto_increment The auto-inc unsafe warning makes sense even though it's just one auto-inc table could be involved via a trigger or a stored function. However its content was not updated by bug@45677 fixes continuing to mention two tables whereas the fixes refined semantics of replication of auto_increment in stored routine. Fixed with updating the error message, renaming the error and an internal unsafe-condition constants. A documentation notice ====================== Inserting into an autoincrement column in a stored function or a trigger is unsafe for replication. Even with just one autoincrement column, if the routine is invoked more than once slave is not guaranteed to execute the statement graph same way as the master. And since it's impossible to estimate how many times a routine can be invoked at the query pre-execution phase (see lock_tables), the statement is marked pessimistically unsafe. --- sql/share/errmsg-utf8.txt | 4 ++-- sql/share/errmsg.txt | 4 ++-- sql/sql_base.cc | 2 +- sql/sql_lex.cc | 2 +- sql/sql_lex.h | 14 ++++++++------ 5 files changed, 14 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 92c86cf6e00..f7094e8734d 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6280,8 +6280,8 @@ ER_BINLOG_UNSAFE_INSERT_DELAYED eng "Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted." ER_BINLOG_UNSAFE_SYSTEM_TABLE eng "Statement uses the general_log, slow_log or performance_schema table(s). This is unsafe because system tables may differ on slave." -ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS - eng "Statement updates two AUTO_INCREMENT columns. This is unsafe because the generated value cannot be predicted by slave." +ER_BINLOG_UNSAFE_AUTOINC_COLUMNS + eng "Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically." ER_BINLOG_UNSAFE_UDF eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave." ER_BINLOG_UNSAFE_SYSTEM_VARIABLE diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 31e630d5fea..60be5723559 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6221,8 +6221,8 @@ ER_BINLOG_UNSAFE_INSERT_DELAYED eng "Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted." ER_BINLOG_UNSAFE_SYSTEM_TABLE eng "Statement uses the general_log, slow_log or performance_schema table(s). This is unsafe because system tables may differ on slave." -ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS - eng "Statement updates two AUTO_INCREMENT columns. This is unsafe because the generated value cannot be predicted by slave." +ER_BINLOG_UNSAFE_AUTOINC_COLUMNS + eng "Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically." ER_BINLOG_UNSAFE_UDF eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave." ER_BINLOG_UNSAFE_SYSTEM_VARIABLE diff --git a/sql/sql_base.cc b/sql/sql_base.cc index eb59600b360..e7f014d39a5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5181,7 +5181,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && has_write_table_with_auto_increment(thd->lex->first_not_own_table())) { - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_TWO_AUTOINC_COLUMNS); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); thd->set_current_stmt_binlog_format_row_if_mixed(); } } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0d423ba85eb..6da734592dc 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -48,7 +48,7 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] = ER_BINLOG_UNSAFE_LIMIT, ER_BINLOG_UNSAFE_INSERT_DELAYED, ER_BINLOG_UNSAFE_SYSTEM_TABLE, - ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS, + ER_BINLOG_UNSAFE_AUTOINC_COLUMNS, ER_BINLOG_UNSAFE_UDF, ER_BINLOG_UNSAFE_SYSTEM_VARIABLE, ER_BINLOG_UNSAFE_SYSTEM_FUNCTION, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 800a16cf2b6..923e924dfbc 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1101,13 +1101,15 @@ public: */ BINLOG_STMT_UNSAFE_SYSTEM_TABLE, /** - Update of two autoincrement columns is unsafe. With one - autoincrement column, we store the counter in the binlog so that - slave can restore the correct value. But we can only store one - such counter per statement, so updating more than one - autoincrement column is not safe. + Inserting into an autoincrement column in a stored routine is unsafe. + Even with just one autoincrement column, if the routine is invoked more than + once slave is not guaranteed to execute the statement graph same way as + the master. + And since it's impossible to estimate how many times a routine can be invoked at + the query pre-execution phase (see lock_tables), the statement is marked + pessimistically unsafe. */ - BINLOG_STMT_UNSAFE_TWO_AUTOINC_COLUMNS, + BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS, /** Using a UDF (user-defined function) is unsafe. */ -- cgit v1.2.1 From 85589577e728fa3ada5591a6988c1017c105be83 Mon Sep 17 00:00:00 2001 From: Date: Sun, 31 Jan 2010 02:26:51 +0800 Subject: BUG#50157 Assertion !active_tranxs_->is_tranx_end_pos(..) in ReplSemiSyncMaster::commitTrx The root cause of the crash is that a TranxNode is freed before it is used. A TranxNode is allocated and inserted into the active list each time a log event is written and flushed into the binlog file. The memory for TranxNode is allocated with thd_alloc and will be freed at the end of the statement. The after_commit/after_rollback callback was supposed to be called before the end of each statement and remove the node from the active list. However this assumption is not correct in all cases(e.g. call 'CREATE TEMPORARY TABLE myisam_t SELECT * FROM innodb_t' in a transaction and delete all temporary tables automatically when a session closed), and can cause the memory allocated for TranxNode be freed before it was removed from the active list. So The TranxNode pointer in the active list would become a wild pointer and cause the crash. After this patch, We have a class called a TranxNodeAllocate which manages the memory for allocating and freeing TranxNode. It uses my_malloc to allocate memory. --- sql/rpl_handler.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc index c4b55e3d068..b347b7c751d 100644 --- a/sql/rpl_handler.cc +++ b/sql/rpl_handler.cc @@ -190,8 +190,8 @@ int Trans_delegate::after_commit(THD *thd, bool all) { Trans_param param; bool is_real_trans= (all || thd->transaction.all.ha_list == 0); - if (is_real_trans) - param.flags |= TRANS_IS_REAL_TRANS; + + param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0; Trans_binlog_info *log_info= my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO); @@ -218,8 +218,8 @@ int Trans_delegate::after_rollback(THD *thd, bool all) { Trans_param param; bool is_real_trans= (all || thd->transaction.all.ha_list == 0); - if (is_real_trans) - param.flags |= TRANS_IS_REAL_TRANS; + + param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0; Trans_binlog_info *log_info= my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO); @@ -228,7 +228,7 @@ int Trans_delegate::after_rollback(THD *thd, bool all) param.log_pos= log_info ? log_info->log_pos : 0; int ret= 0; - FOREACH_OBSERVER(ret, after_commit, thd, (¶m)); + FOREACH_OBSERVER(ret, after_rollback, thd, (¶m)); /* This is the end of a real transaction or autocommit statement, we -- cgit v1.2.1 From d0ffa8e51b104839a9e397aacda8ca1f110e3fad Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 3 Feb 2010 16:56:17 +0000 Subject: BUG#50364: FLUSH LOGS crashes the server (rpl.rpl_heartbeat_basic fails in PB sporadically) The IO thread can concurrently access the relay log IO_CACHE while another thread is performing an FLUSH LOGS procedure. FLUSH LOGS closes and reopens the relay log and while doing so it (re)initializes its IO_CACHE. During this procedure the IO_CACHE mutex is also reinitialized, which can cause problems if some other thread (namely the IO THREAD) is concurrently accessing it at the time . This patch fixes the problem by extending the interface of the flush_master_info function to also include a second paramater, "need_relay_log_lock", stating whether the thread should grab the relay log lock or not before actually flushing the relay log. Also, IO thread now calls flush_master_info with this flag set when it flushes master info with in the event read_event loop. Finally, we also increase loop time in rpl_heartbeat_basic test case, so that the number of calls to flush logs doubles, stressing this part of the code a little more. --- sql/repl_failsafe.cc | 2 +- sql/rpl_mi.cc | 19 ++++++++++++++++--- sql/rpl_mi.h | 4 +++- sql/rpl_rli.cc | 2 +- sql/slave.cc | 4 ++-- sql/sql_repl.cc | 2 +- 6 files changed, 24 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 7a941b1d99b..275571c2158 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -977,7 +977,7 @@ bool load_master_data(THD* thd) host was specified; there could have been a problem when replication started, which led to relay log's IO_CACHE to not be inited. */ - if (flush_master_info(active_mi, 0)) + if (flush_master_info(active_mi, FALSE, FALSE)) sql_print_error("Failed to flush master info file"); } mysql_free_result(master_status_res); diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index e83e0ad0ba9..28b0af441f8 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -387,7 +387,7 @@ file '%s')", fname); mi->rli.is_relay_log_recovery= FALSE; // now change cache READ -> WRITE - must do this before flush_master_info reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1); - if ((error=test(flush_master_info(mi, 1)))) + if ((error=test(flush_master_info(mi, TRUE, TRUE)))) sql_print_error("Failed to flush master info file"); pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); @@ -413,7 +413,9 @@ err: 1 - flush master info failed 0 - all ok */ -int flush_master_info(Master_info* mi, bool flush_relay_log_cache) +int flush_master_info(Master_info* mi, + bool flush_relay_log_cache, + bool need_lock_relay_log) { IO_CACHE* file = &mi->file; char lbuf[22]; @@ -436,8 +438,19 @@ int flush_master_info(Master_info* mi, bool flush_relay_log_cache) */ if (flush_relay_log_cache) { + pthread_mutex_t *log_lock= mi->rli.relay_log.get_log_lock(); IO_CACHE *log_file= mi->rli.relay_log.get_log_file(); - if (flush_io_cache(log_file)) + + if (need_lock_relay_log) + pthread_mutex_lock(log_lock); + + safe_mutex_assert_owner(log_lock); + err= flush_io_cache(log_file); + + if (need_lock_relay_log) + pthread_mutex_unlock(log_lock); + + if (err) DBUG_RETURN(2); } diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index f822a6bc1b1..363c8d4e0b3 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -120,7 +120,9 @@ int init_master_info(Master_info* mi, const char* master_info_fname, bool abort_if_no_master_info_file, int thread_mask); void end_master_info(Master_info* mi); -int flush_master_info(Master_info* mi, bool flush_relay_log_cache); +int flush_master_info(Master_info* mi, + bool flush_relay_log_cache, + bool need_lock_relay_log); int change_master_server_id_cmp(ulong *id1, ulong *id2); #endif /* HAVE_REPLICATION */ diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 4bbafa0253a..fa979fe9a21 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -121,7 +121,7 @@ int init_relay_log_info(Relay_log_info* rli, /* The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. Note that the I/O thread flushes it to disk after writing every - event, in flush_master_info(mi, 1). + event, in flush_master_info(mi, 1, ?). */ /* diff --git a/sql/slave.cc b/sql/slave.cc index 27f87d18800..3678c2497de 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1726,7 +1726,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) " to the relay log, SHOW SLAVE STATUS may be" " inaccurate"); rli->relay_log.harvest_bytes_written(&rli->log_space_total); - if (flush_master_info(mi, 1)) + if (flush_master_info(mi, TRUE, FALSE)) sql_print_error("Failed to flush master info file"); delete ev; } @@ -3047,7 +3047,7 @@ Stopping slave I/O thread due to out-of-memory error from master"); goto err; } - if (flush_master_info(mi, 1)) + if (flush_master_info(mi, TRUE, TRUE)) { sql_print_error("Failed to flush master info file"); goto err; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 4e5ce08ab5d..d28a336e5d2 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1532,7 +1532,7 @@ bool change_master(THD* thd, Master_info* mi) Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never a slave before). */ - if (flush_master_info(mi, 0)) + if (flush_master_info(mi, FALSE, FALSE)) { my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file"); ret= TRUE; -- cgit v1.2.1 From b7289d6dc5b8de6573903f55994a4483f3ece389 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Thu, 4 Feb 2010 12:14:32 +0800 Subject: Bug#49894 shifted MYSQL_REPLICATION_PLUGIN number The number for MYSQL_REPLICATION_PLUGIN was shifted when backporting because MYSQL_AUDIT_PLUGIN was not backported. This problem is fixed by backporting only the number of audit plugin and print an error when trying to load audit plugins. Note that replication plugins compiled against old MYSQL_REPLICATION_PLUGIN number will also be recognized as audit plugin and be rejected. --- sql/sql_plugin.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sql') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 8cf8c4cb81f..c977a30b37b 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -47,6 +47,7 @@ const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= { C_STRING_WITH_LEN("FTPARSER") }, { C_STRING_WITH_LEN("DAEMON") }, { C_STRING_WITH_LEN("INFORMATION SCHEMA") }, + { C_STRING_WITH_LEN("AUDIT") }, { C_STRING_WITH_LEN("REPLICATION") }, }; @@ -87,6 +88,7 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= MYSQL_FTPARSER_INTERFACE_VERSION, MYSQL_DAEMON_INTERFACE_VERSION, MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION, + 0x0000, /* place holder for audit plugin */ MYSQL_REPLICATION_INTERFACE_VERSION, }; static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= @@ -96,6 +98,7 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= MYSQL_FTPARSER_INTERFACE_VERSION, MYSQL_DAEMON_INTERFACE_VERSION, MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION, + 0x0000, /* place holder for audit plugin */ MYSQL_REPLICATION_INTERFACE_VERSION, }; @@ -738,6 +741,14 @@ static bool plugin_add(MEM_ROOT *tmp_root, name_len)) { struct st_plugin_int *tmp_plugin_ptr; + + if (plugin->type == MYSQL_AUDIT_PLUGIN) + { + /* Bug#49894 */ + sql_print_error("Plugin type 'AUDIT' not supported by this server."); + goto err; + } + if (*(int*)plugin->info < min_plugin_info_interface_version[plugin->type] || ((*(int*)plugin->info) >> 8) > -- cgit v1.2.1 From fe6f55d6a2e3fdfceb7344fb40e1a742c8373c2e Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 5 Feb 2010 13:57:15 +0100 Subject: Bug#50057: 'SHOW PROFILE CPU' port for Windows. Patch contributed by Alex Budovski. --- sql/sql_profile.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ sql/sql_profile.h | 2 ++ 2 files changed, 45 insertions(+) (limited to 'sql') diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 84ee0768b25..f8c11cb71b9 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -134,6 +134,26 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) #define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec) #define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2))) +#ifdef _WIN32 +static ULONGLONG FileTimeToQuadWord(FILETIME *ft) +{ + // Overlay FILETIME onto a ULONGLONG. + union { + ULONGLONG qwTime; + FILETIME ft; + } u; + + u.ft = *ft; + return u.qwTime; +} + + +// Get time difference between to FILETIME objects in seconds. +static double GetTimeDiffInSeconds(FILETIME *a, FILETIME *b) +{ + return ((FileTimeToQuadWord(a) - FileTimeToQuadWord(b)) / 1e7); +} +#endif PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg) @@ -224,6 +244,12 @@ void PROF_MEASUREMENT::collect() time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */ #ifdef HAVE_GETRUSAGE getrusage(RUSAGE_SELF, &rusage); +#elif defined(_WIN32) + FILETIME ftDummy; + // NOTE: Get{Process|Thread}Times has a granularity of the clock interval, + // which is typically ~15ms. So intervals shorter than that will not be + // measurable by this function. + GetProcessTimes(GetCurrentProcess(), &ftDummy, &ftDummy, &ftKernel, &ftUser); #endif } @@ -589,6 +615,23 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) (1000.0*1000), &cpu_stime_decimal); + table->field[4]->store_decimal(&cpu_utime_decimal); + table->field[5]->store_decimal(&cpu_stime_decimal); + table->field[4]->set_notnull(); + table->field[5]->set_notnull(); +#elif defined(_WIN32) + my_decimal cpu_utime_decimal, cpu_stime_decimal; + + double2my_decimal(E_DEC_FATAL_ERROR, + GetTimeDiffInSeconds(&entry->ftUser, + &previous->ftUser), + &cpu_utime_decimal); + double2my_decimal(E_DEC_FATAL_ERROR, + GetTimeDiffInSeconds(&entry->ftKernel, + &previous->ftKernel), + &cpu_stime_decimal); + + // Store the result. table->field[4]->store_decimal(&cpu_utime_decimal); table->field[5]->store_decimal(&cpu_stime_decimal); table->field[4]->set_notnull(); diff --git a/sql/sql_profile.h b/sql/sql_profile.h index bffe1cb576b..31e2f1a7c50 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -173,6 +173,8 @@ private: char *status; #ifdef HAVE_GETRUSAGE struct rusage rusage; +#elif defined(_WIN32) + FILETIME ftKernel, ftUser; #endif char *function; -- cgit v1.2.1 From 9ba558302bbe95595c10175d34d4bf733da76fd7 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Tue, 9 Feb 2010 17:22:31 +0000 Subject: BUG#51021: current_stmt_binlog_row_based not removed in next-mr As part of BUG@39934 fix, the public: - THD::current_stmt_binlog_row_based variable had been removed and replaced by a private variable: - THD::current_stmt_binlog_format. THD was refactored and some modifiers and accessors were implemented for the new variable. However, due to a bad merge, the THD::current_stmt_binlog_row_based variable is back as a public member of THD. This in itself is already potentially harmful. What's even worse is that while merging some more patches and resolving conflicts, the variable started being used again, which is obviously wrong. To fix this we: 1. remove the extraneous variable from sql_class.h 2. revert a bad merge for BUG#49132 3. merge BUG#49132 properly again (actually, making use of the cset used to merge the original patch to mysql-pe). --- sql/event_db_repository.cc | 7 ++-- sql/events.cc | 24 +++++++------ sql/sp.cc | 21 ++++++----- sql/sql_acl.cc | 86 ++++++++++++++++++++++++++++------------------ sql/sql_class.h | 1 - sql/sql_udf.cc | 26 ++++++++------ 6 files changed, 98 insertions(+), 67 deletions(-) (limited to 'sql') diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index fd2c5a556a8..50e556af84f 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -1053,8 +1053,8 @@ update_timing_fields_for_event(THD *thd, Turn off row binlogging of event timing updates. These are not used for RBR of events replicated to the slave. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL); @@ -1097,7 +1097,8 @@ end: if (table) close_thread_tables(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(test(ret)); } diff --git a/sql/events.cc b/sql/events.cc index 73f3427607d..b5855401368 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -335,8 +335,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE EVENT command. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); mysql_mutex_lock(&LOCK_event_metadata); @@ -377,7 +377,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, sql_print_error("Event Error: An error occurred while creating query string, " "before writing it into binary log."); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); } /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER @@ -387,7 +388,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, } mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } @@ -471,8 +473,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for UPDATE EVENT command. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); mysql_mutex_lock(&LOCK_event_metadata); @@ -509,7 +511,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, } mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } @@ -570,8 +573,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP EVENT command. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); mysql_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ @@ -585,7 +588,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) } mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } diff --git a/sql/sp.cc b/sql/sp.cc index cbc0d003c9f..de379e7e725 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -927,8 +927,8 @@ sp_create_routine(THD *thd, int type, sp_head *sp) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); saved_count_cuted_fields= thd->count_cuted_fields; thd->count_cuted_fields= CHECK_FIELD_WARN; @@ -1136,7 +1136,8 @@ done: close_thread_tables(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } @@ -1174,8 +1175,8 @@ sp_drop_routine(THD *thd, int type, sp_name *name) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); if (!(table= open_proc_table_for_update(thd))) DBUG_RETURN(SP_OPEN_TABLE_FAILED); @@ -1194,7 +1195,8 @@ sp_drop_routine(THD *thd, int type, sp_name *name) close_thread_tables(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } @@ -1233,8 +1235,8 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); if (!(table= open_proc_table_for_update(thd))) DBUG_RETURN(SP_OPEN_TABLE_FAILED); @@ -1269,7 +1271,8 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) close_thread_tables(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 012542a9467..f0499cb3a5b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3119,8 +3119,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); #ifdef HAVE_REPLICATION /* @@ -3137,7 +3137,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(FALSE); } } @@ -3153,7 +3154,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); /* purecov: deadcode */ } @@ -3281,7 +3283,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, /* Tables are automatically closed */ thd->lex->restore_backup_query_tables_list(&backup); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); } @@ -3346,8 +3349,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); #ifdef HAVE_REPLICATION /* @@ -3364,7 +3367,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(FALSE); } } @@ -3374,7 +3378,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, { // Should never happen close_thread_tables(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); } @@ -3452,7 +3457,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, mysql_rwlock_unlock(&LOCK_grant); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); /* Tables are automatically closed */ DBUG_RETURN(result); @@ -3496,8 +3502,8 @@ bool mysql_grant(THD *thd, const char *db, List &list, row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); #ifdef HAVE_REPLICATION /* @@ -3514,7 +3520,8 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(FALSE); } } @@ -3524,7 +3531,8 @@ bool mysql_grant(THD *thd, const char *db, List &list, { // This should never happen close_thread_tables(thd); /* purecov: deadcode */ /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); /* purecov: deadcode */ } @@ -3585,7 +3593,8 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!result) my_ok(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); } @@ -5797,14 +5806,15 @@ bool mysql_create_user(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); /* CREATE USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); } @@ -5850,7 +5860,8 @@ bool mysql_create_user(THD *thd, List &list) mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); } @@ -5885,14 +5896,15 @@ bool mysql_drop_user(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); /* DROP USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); } @@ -5932,7 +5944,8 @@ bool mysql_drop_user(THD *thd, List &list) close_thread_tables(thd); thd->variables.sql_mode= old_sql_mode; /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); } @@ -5967,14 +5980,15 @@ bool mysql_rename_user(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); /* RENAME USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); } @@ -6024,7 +6038,8 @@ bool mysql_rename_user(THD *thd, List &list) mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); } @@ -6057,13 +6072,14 @@ bool mysql_revoke_all(THD *thd, List &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); } @@ -6219,7 +6235,8 @@ bool mysql_revoke_all(THD *thd, List &list) if (result && !binlog_error) my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result || binlog_error); } @@ -6328,8 +6345,8 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); /* Remove procedure access */ do @@ -6366,7 +6383,8 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, thd->pop_internal_handler(); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(error_handler.has_errors()); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 7bebc639c37..7e17480e780 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1723,7 +1723,6 @@ public: bool slave_thread, one_shot_set; /* tells if current statement should binlog row-based(1) or stmt-based(0) */ - bool current_stmt_binlog_row_based; bool locked, some_tables_deleted; bool last_cuted_field; bool no_errors, password; diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index d0e446fb157..10ef34e0b3a 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -461,8 +461,8 @@ int mysql_create_function(THD *thd,udf_func *udf) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE FUNCTION command. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); mysql_rwlock_wrlock(&THR_LOCK_udf); if ((my_hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length))) @@ -533,11 +533,13 @@ int mysql_create_function(THD *thd,udf_func *udf) if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); } /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(0); err: @@ -545,7 +547,8 @@ int mysql_create_function(THD *thd,udf_func *udf) dlclose(dl); mysql_rwlock_unlock(&THR_LOCK_udf); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); } @@ -573,8 +576,8 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP FUNCTION command. */ - save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); - thd->clear_current_stmt_binlog_format_row(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); mysql_rwlock_wrlock(&THR_LOCK_udf); if (!(udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) udf_name->str, @@ -617,16 +620,19 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) { /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); } /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(0); err: mysql_rwlock_unlock(&THR_LOCK_udf); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); } -- cgit v1.2.1 From 84c205f9eea9d6f645da6ba32793883fd8dc66da Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 10 Feb 2010 10:47:14 +0100 Subject: Bug#50201: Server crashes in explain_filename on an InnoDB partitioned table Problem was that in mysql-trunk the ER() macro is now dependent on current_thd and the innodb monitor thread has no binding to that thd object. This cause the crash because of bad derefencing. Solution was to add a new macro which take the thd as an argument (which the innodb thread uses for the call). (Updated according to reviewers comments, i.e. added ER_THD_OR_DEFAULT and moved test to suite parts.) --- sql/sql_table.cc | 17 +++++++++++------ sql/unireg.h | 3 +++ 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b17edbdd234..6006c818725 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -291,7 +291,8 @@ uint explain_filename(THD* thd, { if (explain_mode == EXPLAIN_ALL_VERBOSE) { - to_p= strnmov(to_p, ER(ER_DATABASE_NAME), end_p - to_p); + to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_DATABASE_NAME), + end_p - to_p); *(to_p++)= ' '; to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len); to_p= strnmov(to_p, ", ", end_p - to_p); @@ -304,7 +305,7 @@ uint explain_filename(THD* thd, } if (explain_mode == EXPLAIN_ALL_VERBOSE) { - to_p= strnmov(to_p, ER(ER_TABLE_NAME), end_p - to_p); + to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_TABLE_NAME), end_p - to_p); *(to_p++)= ' '; to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len); } @@ -321,18 +322,22 @@ uint explain_filename(THD* thd, if (name_type != NORMAL) { if (name_type == TEMP) - to_p= strnmov(to_p, ER(ER_TEMPORARY_NAME), end_p - to_p); + to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_TEMPORARY_NAME), + end_p - to_p); else - to_p= strnmov(to_p, ER(ER_RENAMED_NAME), end_p - to_p); + to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_RENAMED_NAME), + end_p - to_p); to_p= strnmov(to_p, " ", end_p - to_p); } - to_p= strnmov(to_p, ER(ER_PARTITION_NAME), end_p - to_p); + to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_PARTITION_NAME), + end_p - to_p); *(to_p++)= ' '; to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len); if (subpart_name) { to_p= strnmov(to_p, ", ", end_p - to_p); - to_p= strnmov(to_p, ER(ER_SUBPARTITION_NAME), end_p - to_p); + to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_SUBPARTITION_NAME), + end_p - to_p); *(to_p++)= ' '; to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len); } diff --git a/sql/unireg.h b/sql/unireg.h index a390b755772..e915b234a6b 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -46,6 +46,9 @@ #define ER(X) CURRENT_THD_ERRMSGS[(X) - ER_ERROR_FIRST] #define ER_DEFAULT(X) DEFAULT_ERRMSGS[(X) - ER_ERROR_FIRST] #define ER_SAFE(X) (((X) >= ER_ERROR_FIRST && (X) <= ER_ERROR_LAST) ? ER(X) : "Invalid error code") +#define ER_THD(thd,X) ((thd)->variables.lc_messages->errmsgs->errmsgs[(X) - \ + ER_ERROR_FIRST]) +#define ER_THD_OR_DEFAULT(thd,X) ((thd) ? ER_THD(thd, X) : ER_DEFAULT(X)) #define ERRMAPP 1 /* Errormap f|r my_error */ -- cgit v1.2.1 From 7d213e8314d210e7ef975a9743f2dfa38ff1f6a6 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 10 Feb 2010 16:01:31 +0000 Subject: BUG#51021: current_stmt_binlog_row_based not removed in next-mr Deployed DBUG_ASSERT before the conditional binlog format restore. --- sql/event_db_repository.cc | 1 + sql/events.cc | 4 ++++ sql/sp.cc | 3 +++ sql/sql_acl.cc | 18 ++++++++++++++++++ sql/sql_udf.cc | 6 ++++++ 5 files changed, 32 insertions(+) (limited to 'sql') diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 50e556af84f..ff74dd0ab84 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -1097,6 +1097,7 @@ end: if (table) close_thread_tables(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); diff --git a/sql/events.cc b/sql/events.cc index b5855401368..340ef8c7bd2 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -377,6 +377,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, sql_print_error("Event Error: An error occurred while creating query string, " "before writing it into binary log."); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); @@ -388,6 +389,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, } mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); @@ -511,6 +513,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, } mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); @@ -588,6 +591,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) } mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); diff --git a/sql/sp.cc b/sql/sp.cc index de379e7e725..aae825c6c0d 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1136,6 +1136,7 @@ done: close_thread_tables(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); @@ -1195,6 +1196,7 @@ sp_drop_routine(THD *thd, int type, sp_name *name) close_thread_tables(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); @@ -1271,6 +1273,7 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) close_thread_tables(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f0499cb3a5b..334d6474169 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3137,6 +3137,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(FALSE); @@ -3154,6 +3155,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); /* purecov: deadcode */ @@ -3283,6 +3285,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, /* Tables are automatically closed */ thd->lex->restore_backup_query_tables_list(&backup); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); @@ -3367,6 +3370,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(FALSE); @@ -3378,6 +3382,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, { // Should never happen close_thread_tables(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); @@ -3457,6 +3462,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, mysql_rwlock_unlock(&LOCK_grant); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); @@ -3520,6 +3526,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!(thd->spcont || rpl_filter->tables_ok(0, tables))) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(FALSE); @@ -3531,6 +3538,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, { // This should never happen close_thread_tables(thd); /* purecov: deadcode */ /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); /* purecov: deadcode */ @@ -3593,6 +3601,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!result) my_ok(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); @@ -5813,6 +5822,7 @@ bool mysql_create_user(THD *thd, List &list) if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); @@ -5860,6 +5870,7 @@ bool mysql_create_user(THD *thd, List &list) mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); @@ -5903,6 +5914,7 @@ bool mysql_drop_user(THD *thd, List &list) if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); @@ -5944,6 +5956,7 @@ bool mysql_drop_user(THD *thd, List &list) close_thread_tables(thd); thd->variables.sql_mode= old_sql_mode; /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); @@ -5987,6 +6000,7 @@ bool mysql_rename_user(THD *thd, List &list) if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); @@ -6038,6 +6052,7 @@ bool mysql_rename_user(THD *thd, List &list) mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); @@ -6078,6 +6093,7 @@ bool mysql_revoke_all(THD *thd, List &list) if ((result= open_grant_tables(thd, tables))) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result != 1); @@ -6235,6 +6251,7 @@ bool mysql_revoke_all(THD *thd, List &list) if (result && !binlog_error) my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); @@ -6383,6 +6400,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, thd->pop_internal_handler(); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 10ef34e0b3a..80c4791ab21 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -533,11 +533,13 @@ int mysql_create_function(THD *thd,udf_func *udf) if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); } /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(0); @@ -547,6 +549,7 @@ int mysql_create_function(THD *thd,udf_func *udf) dlclose(dl); mysql_rwlock_unlock(&THR_LOCK_udf); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); @@ -620,17 +623,20 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) { /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); } /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(0); err: mysql_rwlock_unlock(&THR_LOCK_udf); /* Restore the state of binlog format */ + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(1); -- cgit v1.2.1 From f4f4a2c780166cb93414839bc87fc5ff14b3e38f Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 10 Feb 2010 21:57:07 +0000 Subject: BUG#51021: current_stmt_binlog_row_based not removed in next-mr A closely related problem, hardly worth a new bug report: Removed a spurious call to: thd->set_current_stmt_binlog_format_row_if_mixed() in sql_base.cc:lock_tables(). --- sql/sql_base.cc | 3 --- 1 file changed, 3 deletions(-) (limited to 'sql') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index eb59600b360..ff330d1b5bb 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5180,10 +5180,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) */ if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && has_write_table_with_auto_increment(thd->lex->first_not_own_table())) - { thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_TWO_AUTOINC_COLUMNS); - thd->set_current_stmt_binlog_format_row_if_mixed(); - } } DEBUG_SYNC(thd, "before_lock_tables_takes_lock"); -- cgit v1.2.1 From b2ddac55637dc0552cb98b5ac21912f7ffaeb231 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Thu, 11 Feb 2010 18:02:41 +0100 Subject: Bug#50542 5.5.x doesn't check length of key prefixes: corruption and crash results An index creation statement where the index key is larger/wider than the column it references should throw an error. A statement like: CREATE TABLE t1 (a CHAR(1), PRIMARY KEY (A(255))) did not error, but a segmentation fault followed when an insertion was attempted on the table The partial key validiation clause has been restructured to (hopefully) better document which uses of partial keys are valid. --- sql/sql_table.cc | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6006c818725..04bd2d4c976 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3292,22 +3292,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } } } + // Catch invalid use of partial keys else if (!f_is_geom(sql_field->pack_flag) && - ((column->length > length && - !Field::type_can_have_key_part (sql_field->sql_type)) || - ((f_is_packed(sql_field->pack_flag) || - ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) && - (key_info->flags & HA_NOSAME))) && - column->length != length))) - { - /* Catch invalid uses of partial keys. - A key is identified as 'partial' if column->length != length. - A partial key is invalid if they data type does - not allow it, or the field is packed (as in MyISAM), - or the storage engine doesn't allow prefixed search and - the key is primary key. - */ - + // is the key partial? + column->length != length && + // is prefix length bigger than field length? + (column->length > length || + // can the field have a partial key? + !Field::type_can_have_key_part (sql_field->sql_type) || + // a packed field can't be used in a partial key + f_is_packed(sql_field->pack_flag) || + // does the storage engine allow prefixed search? + ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) && + // and is this a 'unique' key? + (key_info->flags & HA_NOSAME)))) + { my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0)); DBUG_RETURN(TRUE); } -- cgit v1.2.1 From 5f2c8caea958e6e0375f2e468d9f430e52697404 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Thu, 11 Feb 2010 18:25:34 +0100 Subject: Bug#50574 5.5.x allows spatial indexes on non-spatial columns, causing crashes! Adding a SPATIAL INDEX on a non-geometrical column caused a segmentation fault when the table was subsequently inserted into. A test was added in mysql_prepare_create_table to explicitly check whether non-geometrical columns are used in a spatial index, and throw an error if so. --- sql/share/errmsg-utf8.txt | 2 ++ sql/sql_table.cc | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index db99890235a..d4f3cce805f 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6260,3 +6260,5 @@ ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD eng "Field '%-.192s' is of a not allowed type for this type of partitioning" ER_PARTITION_FIELDS_TOO_LONG eng "The total length of the partitioning fields is too large" +ER_SPATIAL_MUST_HAVE_GEOM_COL 42000 + eng "A SPATIAL index may only contain a geometrical type column" diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 04bd2d4c976..e89edb4fcfe 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3193,11 +3193,19 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, { column->length*= sql_field->charset->mbmaxlen; - if (key->type == Key::SPATIAL && column->length) + if (key->type == Key::SPATIAL) { - my_error(ER_WRONG_SUB_KEY, MYF(0)); - DBUG_RETURN(TRUE); - } + if (column->length) + { + my_error(ER_WRONG_SUB_KEY, MYF(0)); + DBUG_RETURN(TRUE); + } + if (!f_is_geom(sql_field->pack_flag)) + { + my_error(ER_SPATIAL_MUST_HAVE_GEOM_COL, MYF(0)); + DBUG_RETURN(TRUE); + } + } if (f_is_blob(sql_field->pack_flag) || (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL)) -- cgit v1.2.1 From 6bad45745cec8ce9047508677d2fadd05edb8195 Mon Sep 17 00:00:00 2001 From: Date: Fri, 12 Feb 2010 12:04:57 +0800 Subject: Bug #43913 rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm The MDL_SHARED lock was introduced for an object in 5.4, but the 'TABLE_LIST' object was not initialized with the MDL_SHARED lock when applying event with LOAD DATA INFILE into table. So the failure is caused when checking the MDL_SHARED lock for the object. To fix the problem, the 'TABLE_LIST' object was initialized with the MDL_SHARED lock when applying event with LOAD DATA INFILE into table. --- sql/log_event.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/log_event.cc b/sql/log_event.cc index b6c84dd95f4..fbfffb592bf 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4634,10 +4634,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, thd->warning_info->opt_clear_warning_info(thd->query_id); TABLE_LIST tables; - bzero((char*) &tables,sizeof(tables)); - tables.db= thd->strmake(thd->db, thd->db_length); - tables.alias = tables.table_name = (char*) table_name; - tables.lock_type = TL_WRITE; + tables.init_one_table(thd->db, table_name, TL_WRITE); tables.updating= 1; // the table will be opened in mysql_load -- cgit v1.2.1 From b5f40f34543f61213af694711bfa5e123bce4ba6 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Fri, 12 Feb 2010 11:51:52 +0300 Subject: Bug#50539: Wrong result when loose index scan is used for an aggregate function with distinct. Loose index scan is used to find MIN/MAX values using appropriate index and thus allow to avoid grouping. For each found row it updates non-aggregated fields with values from row with found MIN/MAX value. Without loose index scan non-aggregated fields are copied by end_send_group function. With loose index scan there is no need in end_send_group and end_send is used instead. Non-aggregated fields still need to be copied and this was wrongly implemented in QUICK_GROUP_MIN_MAX_SELECT::get_next. WL#3220 added a case when loose index scan can be used with end_send_group to optimize calculation of aggregate functions with distinct. In this case the row found by QUICK_GROUP_MIN_MAX_SELECT::get_next might belong to a next group and copying it will produce wrong result. Update of non-aggregated fields is moved to the end_send function from QUICK_GROUP_MIN_MAX_SELECT::get_next. --- sql/opt_range.cc | 12 +----------- sql/sql_select.cc | 6 ++++++ 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ac5b1f575de..5c64a6a64ee 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -10959,17 +10959,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() } while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) && is_last_prefix != 0); - if (result == 0) - { - /* - Partially mimic the behavior of end_select_send. Copy the - field data from Item_field::field into Item_field::result_field - of each non-aggregated field (the group fields, and optionally - other fields in non-ANSI SQL mode). - */ - copy_fields(&join->tmp_table_param); - } - else if (result == HA_ERR_KEY_NOT_FOUND) + if (result == HA_ERR_KEY_NOT_FOUND) result= HA_ERR_END_OF_FILE; DBUG_RETURN(result); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7119650a7a6..e09bd6cab5d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12255,6 +12255,12 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (!end_of_records) { int error; + if (join->tables && + join->join_tab->is_using_loose_index_scan()) + { + /* Copy non-aggregated fields when loose index scan is used. */ + copy_fields(&join->tmp_table_param); + } if (join->having && join->having->val_int() == 0) DBUG_RETURN(NESTED_LOOP_OK); // Didn't match having error=0; -- cgit v1.2.1