From c1a36d80ef50b7cd23da893a08e7610d9e9dd02e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Nov 2007 15:11:58 -0500 Subject: [PATCH 001/115] Push history-limiting code until after the code that adds new history entries. Lazy deletion isn't smart or useful here. Backport from 5.1 . include/my_sys.h: Prepare for rename in 5.1. mysql-test/r/profiling.result: Backport tests from 5.1. mysql-test/t/profiling.test: Backport tests from 5.1. sql/mysql_priv.h: Backport changes from 5.1 . sql/sp_head.cc: Backport changes from 5.1 . sql/sql_class.cc: Backport changes from 5.1 . sql/sql_parse.cc: Backport changes from 5.1 . sql/sql_profile.cc: Push history-limiting code until after the code that adds new history entries. Lazy deletion isn't smart or useful here. Correct for 5.0 member existance and execution. sql/sql_profile.h: Backport changes from 5.1 . sql/sql_show.cc: Backport changes from 5.1 . --- include/my_sys.h | 1 + mysql-test/r/profiling.result | 47 ++++ mysql-test/t/profiling.test | 66 +++++- sql/mysql_priv.h | 14 ++ sql/sp_head.cc | 29 +++ sql/sql_class.cc | 14 ++ sql/sql_parse.cc | 44 +++- sql/sql_profile.cc | 429 +++++++++++++++++----------------- sql/sql_profile.h | 82 ++----- sql/sql_show.cc | 21 ++ 10 files changed, 464 insertions(+), 283 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 7df2718c7b1..5bfd43d41ef 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -162,6 +162,7 @@ extern char *my_strdup_with_length(const char *from, uint length, #define ORIG_CALLER_INFO /* nothing */ #define TRASH(A,B) /* nothing */ #endif +#define my_strndup(A,B,C) my_strdup_with_length((A), (B), (C)) #ifdef HAVE_LARGE_PAGES extern uint my_get_large_page_size(void); diff --git a/mysql-test/r/profiling.result b/mysql-test/r/profiling.result index b99870e3564..a9ada576b4b 100644 --- a/mysql-test/r/profiling.result +++ b/mysql-test/r/profiling.result @@ -300,6 +300,53 @@ id select @@profiling; @@profiling 1 +set session profiling = OFF; +drop table if exists profile_log; +Warnings: +Note 1051 Unknown table 'profile_log' +create table profile_log (how_many int); +drop procedure if exists p1; +drop procedure if exists p2; +drop procedure if exists p3; +create procedure p1 () +modifies sql data +begin +set profiling = ON; +select 'This p1 should show up in profiling'; +insert into profile_log select count(*) from information_schema.profiling; +end// +create procedure p2() +deterministic +begin +set profiling = ON; +call p1(); +select 'This p2 should show up in profiling'; +end// +create procedure p3 () +reads sql data +begin +set profiling = ON; +select 'This p3 should show up in profiling'; +show profile; +end// +first call to p1 +call p1; +select * from profile_log; +second call to p1 +call p1; +select * from profile_log; +third call to p1 +call p1; +select * from profile_log; +set session profiling = OFF; +call p2; +set session profiling = OFF; +call p3; +show profiles; +drop procedure if exists p1; +drop procedure if exists p2; +drop procedure if exists p3; +drop table if exists profile_log; set session profiling = ON; drop table if exists t2; create table t2 (id int not null); diff --git a/mysql-test/t/profiling.test b/mysql-test/t/profiling.test index 960aa496731..ffd38caf781 100644 --- a/mysql-test/t/profiling.test +++ b/mysql-test/t/profiling.test @@ -136,7 +136,7 @@ show profiles; ## Verify that the various juggling of THD contexts doesn't affect profiling. -## Functions +## Functions and procedures set session profiling = ON; select @@profiling; create function f1() returns varchar(50) return 'hello'; @@ -144,6 +144,64 @@ select @@profiling; select * from t1 where id <> f1(); select @@profiling; +set session profiling = OFF; +drop table if exists profile_log; +create table profile_log (how_many int); + +--disable_warnings +drop procedure if exists p1; +drop procedure if exists p2; +drop procedure if exists p3; +--enable_warnings + +delimiter //; +create procedure p1 () + modifies sql data +begin + set profiling = ON; + select 'This p1 should show up in profiling'; + insert into profile_log select count(*) from information_schema.profiling; +end// +create procedure p2() + deterministic +begin + set profiling = ON; + call p1(); + select 'This p2 should show up in profiling'; +end// +create procedure p3 () + reads sql data +begin + set profiling = ON; + select 'This p3 should show up in profiling'; + show profile; +end// +delimiter ;// + +--disable_result_log +--echo first call to p1 +call p1; +select * from profile_log; +--echo second call to p1 +call p1; +select * from profile_log; +--echo third call to p1 +call p1; +select * from profile_log; +set session profiling = OFF; +call p2; +set session profiling = OFF; +call p3; + +--replace_column 1 # 2 # +show profiles; +--enable_result_log + +drop procedure if exists p1; +drop procedure if exists p2; +drop procedure if exists p3; +drop table if exists profile_log; + ## Triggers set session profiling = ON; drop table if exists t2; @@ -193,6 +251,12 @@ drop table if exists t1, t2, t3; drop view if exists v1; drop function if exists f1; +## Multiple queries in one packet. Combo statements don't work with ps-proto. +#--eval select 1; select 2; select 3; +## two continuations, one starting +#select state from information_schema.profiling where seq=1 order by query_id desc limit 3; + + ## last thing in the file set session profiling = OFF; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3482cfe9a70..20e4dacaded 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -495,6 +495,8 @@ enum enum_parsing_place struct st_table; class THD; +#define thd_proc_info(thd, msg) set_thd_proc_info(thd, msg, __func__, __FILE__, __LINE__) + /* Struct to handle simple linked lists */ typedef struct st_sql_list { @@ -580,6 +582,16 @@ typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); #include "item.h" extern my_decimal decimal_zero; +/** + The meat of thd_proc_info(THD*, char*), a macro that packs the last + three calling-info parameters. +*/ +extern "C" +const char *set_thd_proc_info(THD *thd, const char *info, + const char *calling_func, + const char *calling_file, + const unsigned int calling_line); + /* sql_parse.cc */ void free_items(Item *item); void cleanup_items(Item *item); @@ -978,6 +990,8 @@ bool get_schema_tables_result(JOIN *join, enum enum_schema_table_state executed_place); enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table); +bool schema_table_store_record(THD *thd, TABLE *table); + #define is_schema_db(X) \ !my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str, (X)) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index c659b222628..2c02b07206f 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1057,15 +1057,36 @@ sp_head::execute(THD *thd) */ thd->spcont->callers_arena= &backup_arena; +#if defined(ENABLED_PROFILING) + /* Discard the initial part of executing routines. */ + thd->profiling.discard_current_query(); +#endif do { sp_instr *i; uint hip; // Handler ip +#if defined(ENABLED_PROFILING) + /* + Treat each "instr" of a routine as discrete unit that could be profiled. + Profiling only records information for segments of code that set the + source of the query, and almost all kinds of instructions in s-p do not. + */ + thd->profiling.finish_current_query(); + thd->profiling.start_new_query("continuing inside routine"); +#endif + i = get_instr(ip); // Returns NULL when we're done. if (i == NULL) + { +#if defined(ENABLED_PROFILING) + thd->profiling.discard_current_query(); +#endif break; + } + DBUG_PRINT("execute", ("Instruction %u", ip)); + /* Don't change NOW() in FUNCTION or TRIGGER */ if (!thd->in_sub_stmt) thd->set_time(); // Make current_time() et al work @@ -1142,6 +1163,10 @@ sp_head::execute(THD *thd) } } while (!err_status && !thd->killed); +#if defined(ENABLED_PROFILING) + thd->profiling.finish_current_query(); + thd->profiling.start_new_query("tail end of routine"); +#endif thd->restore_active_arena(&execute_arena, &backup_arena); thd->spcont->pop_all_cursors(); // To avoid memory leaks after an error @@ -2539,6 +2564,10 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) query= thd->query; query_length= thd->query_length; +#if defined(ENABLED_PROFILING) + /* This s-p instr is profilable and will be captured. */ + thd->profiling.set_query_source(m_query.str, m_query.length); +#endif if (!(res= alloc_query(thd, m_query.str, m_query.length+1)) && !(res=subst_spvars(thd, this, &m_query))) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ebce723d577..a8725923624 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -165,6 +165,20 @@ Open_tables_state::Open_tables_state(ulong version_arg) reset_open_tables_state(); } +extern "C" +const char *set_thd_proc_info(THD *thd, const char *info, + const char *calling_function, + const char *calling_file, + const unsigned int calling_line) +{ + const char *old_info= thd->proc_info; + DBUG_PRINT("proc_info", ("%s:%d %s", calling_file, calling_line, info)); +#if defined(ENABLED_PROFILING) + thd->profiling.status_change(info, calling_function, calling_file, calling_line); +#endif + thd->proc_info= info; + return old_info; +} THD::THD() diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7e105689d22..e3166c07cbd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1313,6 +1313,10 @@ pthread_handler_t handle_bootstrap(void *arg) thd->db_length+1+QUERY_CACHE_FLAGS_SIZE); thd->query[length] = '\0'; DBUG_PRINT("query",("%-.4096s",thd->query)); +#if defined(ENABLED_PROFILING) + thd->profiling.set_query_source(thd->query, length); +#endif + /* We don't need to obtain LOCK_thread_count here because in bootstrap mode we have only one thread. @@ -1522,6 +1526,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) bool do_command(THD *thd) { + bool return_value; char *packet= 0; ulong packet_length; NET *net= &thd->net; @@ -1545,7 +1550,12 @@ bool do_command(THD *thd) thd->clear_error(); // Clear error message net_new_transaction(net); - if ((packet_length=my_net_read(net)) == packet_error) + + packet_length= my_net_read(net); +#if defined(ENABLED_PROFILING) + thd->profiling.start_new_query(); +#endif + if (packet_length == packet_error) { DBUG_PRINT("info",("Got error %d reading command from socket %s", net->error, @@ -1554,11 +1564,13 @@ bool do_command(THD *thd) if (net->error != 3) { statistic_increment(aborted_threads,&LOCK_status); - DBUG_RETURN(TRUE); // We have to close it. + return_value= TRUE; // We have to close it. + goto out; } net_send_error(thd, net->last_errno, NullS); net->error= 0; - DBUG_RETURN(FALSE); + return_value= FALSE; + goto out; } else { @@ -1583,7 +1595,13 @@ bool do_command(THD *thd) command == packet[0] == COM_SLEEP). In dispatch_command packet[packet_length] points beyond the end of packet. */ - DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length)); + return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length)); + +out: +#if defined(ENABLED_PROFILING) + thd->profiling.finish_current_query(); +#endif + DBUG_RETURN(return_value); } #endif /* EMBEDDED_LIBRARY */ @@ -1805,6 +1823,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_log.write(thd,command, format, thd->query_length, thd->query); DBUG_PRINT("query",("%-.4096s",thd->query)); +#if defined(ENABLED_PROFILING) + thd->profiling.set_query_source(thd->query, thd->query_length); +#endif if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),QUERY_PRIOR); @@ -1831,6 +1852,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, next_packet++; length--; } + +#if defined(ENABLED_PROFILING) + thd->profiling.finish_current_query(); + thd->profiling.start_new_query("continuing"); + thd->profiling.set_query_source(next_packet, length); +#endif + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_length= length; thd->query= next_packet; @@ -2325,7 +2353,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, wish to have SHOW commands show up in profiling. */ #ifdef ENABLED_PROFILING - thd->profiling.discard(); + thd->profiling.discard_current_query(); #endif break; case SCH_OPEN_TABLES: @@ -2762,8 +2790,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_PROFILES: { #ifdef ENABLED_PROFILING - thd->profiling.store(); - thd->profiling.discard(); + thd->profiling.discard_current_query(); res= thd->profiling.show_profiles(); if (res) goto error; @@ -5887,9 +5914,6 @@ void mysql_reset_thd_for_next_command(THD *thd) thd->total_warn_count=0; // Warnings for this query thd->rand_used= 0; thd->sent_row_count= thd->examined_row_count= 0; -#ifdef ENABLED_PROFILING - thd->profiling.reset(); -#endif } DBUG_VOID_RETURN; } diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 30bedcfc813..6ae70ab1d13 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -14,13 +14,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/** + @file + + Implement query profiling as as list of metaphorical fences, with one fence + per query, and each fencepost a change of thd->proc_info state (with a + snapshot of system statistics). When asked, we can then iterate over the + fenceposts and calculate the distance between them, to inform the user what + happened during a particular query or thd->proc_info state. + + User variables that inform profiling behavior: + - "profiling", boolean, session only, "Are queries profiled?" + - "profiling_history_size", integer, session + global, "Num queries stored?" +*/ + + #include "mysql_priv.h" #include "my_sys.h" #define TIME_FLOAT_DIGITS 9 -#define MAX_QUERY_LENGTH 300 +/** two vals encoded: (dec*100)+len */ +#define TIME_I_S_DECIMAL_SIZE (TIME_FLOAT_DIGITS*100)+(TIME_FLOAT_DIGITS-3) -bool schema_table_store_record(THD *thd, TABLE *table); +#define MAX_QUERY_LENGTH 300 /* Reserved for systems that can't record the function name in source. */ const char * const _unknown_func_ = ""; @@ -28,25 +44,26 @@ const char * const _unknown_func_ = ""; /** Connects Information_Schema and Profiling. */ -int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, +int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) { -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) return(thd->profiling.fill_statistics_info(thd, tables, cond)); #else + my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILE", "enable-profiling"); return(1); #endif } ST_FIELD_INFO query_profile_statistics_info[]= { - /* name, length, type, value, maybe_null, old_name */ + /* name, length, type, value, maybe_null, old_name, open_method */ {"QUERY_ID", 20, MYSQL_TYPE_LONG, 0, false, "Query_id"}, {"SEQ", 20, MYSQL_TYPE_LONG, 0, false, "Seq"}, {"STATE", 30, MYSQL_TYPE_STRING, 0, false, "Status"}, - {"DURATION", TIME_FLOAT_DIGITS, MYSQL_TYPE_DECIMAL, 0, false, "Duration"}, - {"CPU_USER", TIME_FLOAT_DIGITS, MYSQL_TYPE_DECIMAL, 0, true, "CPU_user"}, - {"CPU_SYSTEM", TIME_FLOAT_DIGITS, MYSQL_TYPE_DECIMAL, 0, true, "CPU_system"}, + {"DURATION", TIME_I_S_DECIMAL_SIZE, MYSQL_TYPE_DECIMAL, 0, false, "Duration"}, + {"CPU_USER", TIME_I_S_DECIMAL_SIZE, MYSQL_TYPE_DECIMAL, 0, true, "CPU_user"}, + {"CPU_SYSTEM", TIME_I_S_DECIMAL_SIZE, MYSQL_TYPE_DECIMAL, 0, true, "CPU_system"}, {"CONTEXT_VOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, "Context_voluntary"}, {"CONTEXT_INVOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, "Context_involuntary"}, {"BLOCK_OPS_IN", 20, MYSQL_TYPE_LONG, 0, true, "Block_ops_in"}, @@ -59,7 +76,7 @@ ST_FIELD_INFO query_profile_statistics_info[]= {"SOURCE_FUNCTION", 30, MYSQL_TYPE_STRING, 0, true, "Source_function"}, {"SOURCE_FILE", 20, MYSQL_TYPE_STRING, 0, true, "Source_file"}, {"SOURCE_LINE", 20, MYSQL_TYPE_LONG, 0, true, "Source_line"}, - {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL} + {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL} }; @@ -112,45 +129,41 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) } -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) #define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec) #define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2))) -PROFILE_ENTRY::PROFILE_ENTRY() - :profile(NULL), status(NULL), function(NULL), file(NULL), line(0), - time_usecs(0.0), allocated_status_memory(NULL) -{ - collect(); - /* The beginning of the query, before any state is set. */ - set_status("(initialization)", NULL, NULL, 0); -} - -PROFILE_ENTRY::PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg) +PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char + *status_arg) :profile(profile_arg) { collect(); - set_status(status_arg, NULL, NULL, 0); + set_label(status_arg, NULL, NULL, 0); } -PROFILE_ENTRY::PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg, - const char *function_arg, - const char *file_arg, unsigned int line_arg) +PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, + const char *status_arg, + const char *function_arg, + const char *file_arg, + unsigned int line_arg) :profile(profile_arg) { collect(); - set_status(status_arg, function_arg, file_arg, line_arg); + set_label(status_arg, function_arg, file_arg, line_arg); } -PROFILE_ENTRY::~PROFILE_ENTRY() +PROF_MEASUREMENT::~PROF_MEASUREMENT() { if (allocated_status_memory != NULL) my_free(allocated_status_memory, MYF(0)); status= function= file= NULL; } - -void PROFILE_ENTRY::set_status(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg) + +void PROF_MEASUREMENT::set_label(const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg) { size_t sizes[3]; /* 3 == status+function+file */ char *cursor; @@ -162,7 +175,7 @@ void PROFILE_ENTRY::set_status(const char *status_arg, const char *function_arg, sizes[0]= (status_arg == NULL) ? 0 : strlen(status_arg) + 1; sizes[1]= (function_arg == NULL) ? 0 : strlen(function_arg) + 1; sizes[2]= (file_arg == NULL) ? 0 : strlen(file_arg) + 1; - + allocated_status_memory= (char *) my_malloc(sizes[0] + sizes[1] + sizes[2], MYF(0)); DBUG_ASSERT(allocated_status_memory != NULL); @@ -198,7 +211,15 @@ void PROFILE_ENTRY::set_status(const char *status_arg, const char *function_arg, line= line_arg; } -void PROFILE_ENTRY::collect() +/** + This updates the statistics for this moment of time. It captures the state + of the running system, so later we can compare points in time and infer what + happened in the mean time. It should only be called immediately upon + instantiation of this PROF_MEASUREMENT. + + @todo Implement resource capture for OSes not like BSD. +*/ +void PROF_MEASUREMENT::collect() { time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */ #ifdef HAVE_GETRUSAGE @@ -206,28 +227,13 @@ void PROFILE_ENTRY::collect() #endif } -QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg, - uint query_length_arg) - :profiling(profiling_arg), server_query_id(0), profiling_query_id(0), - query_source(NULL) + +QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg) + :profiling(profiling_arg), profiling_query_id(0), query_source(NULL) { - profile_end= &profile_start; - set_query_source(query_source_arg, query_length_arg); -} - -void QUERY_PROFILE::set_query_source(char *query_source_arg, - uint query_length_arg) -{ - if (! profiling->enabled) - return; - - /* Truncate to avoid DoS attacks. */ - uint length= min(MAX_QUERY_LENGTH, query_length_arg); - /* TODO?: Provide a way to include the full text, as in SHOW PROCESSLIST. */ - - DBUG_ASSERT(query_source == NULL); - if (query_source_arg != NULL) - query_source= my_strdup_with_length(query_source_arg, length, MYF(0)); + profile_start= new PROF_MEASUREMENT(this, status_arg); + entries.push_back(profile_start); + profile_end= profile_start; } QUERY_PROFILE::~QUERY_PROFILE() @@ -239,61 +245,44 @@ QUERY_PROFILE::~QUERY_PROFILE() my_free(query_source, MYF(0)); } -void QUERY_PROFILE::status(const char *status_arg, - const char *function_arg= NULL, - const char *file_arg= NULL, unsigned int line_arg= 0) +/** + @todo Provide a way to include the full text, as in SHOW PROCESSLIST. +*/ +void QUERY_PROFILE::set_query_source(char *query_source_arg, + uint query_length_arg) { - THD *thd= profiling->thd; - PROFILE_ENTRY *prof; + /* Truncate to avoid DoS attacks. */ + uint length= min(MAX_QUERY_LENGTH, query_length_arg); + + DBUG_ASSERT(query_source == NULL); /* we don't leak memory */ + if (query_source_arg != NULL) + query_source= my_strndup(query_source_arg, length, MYF(0)); +} + +void QUERY_PROFILE::new_status(const char *status_arg, + const char *function_arg, const char *file_arg, + unsigned int line_arg) +{ + PROF_MEASUREMENT *prof; DBUG_ENTER("QUERY_PROFILE::status"); - /* Blank status. Just return, and thd->proc_info will be set blank later. */ - if (unlikely(status_arg == NULL)) - DBUG_VOID_RETURN; + DBUG_ASSERT(status_arg != NULL); - /* If thd->proc_info is currently set to status_arg, don't profile twice. */ - if (likely((thd->proc_info != NULL) && - ((thd->proc_info == status_arg) || - (strcmp(thd->proc_info, status_arg) == 0)))) - { - DBUG_VOID_RETURN; - } + if ((function_arg != NULL) && (file_arg != NULL)) + prof= new PROF_MEASUREMENT(this, status_arg, function_arg, file_arg, line_arg); + else + prof= new PROF_MEASUREMENT(this, status_arg); - /* Is this the same query as our profile currently contains? */ - if (unlikely((thd->query_id != server_query_id) && !thd->spcont)) - reset(); - - if (function_arg && file_arg) - { - if ((profile_end= prof= new PROFILE_ENTRY(this, status_arg, function_arg, - file_arg, line_arg))) - entries.push_back(prof); - } - else - { - if ((profile_end= prof= new PROFILE_ENTRY(this, status_arg))) - entries.push_back(prof); - } + profile_end= prof; + entries.push_back(prof); DBUG_VOID_RETURN; } -void QUERY_PROFILE::reset() -{ - DBUG_ENTER("QUERY_PROFILE::reset"); - if (likely(profiling->thd->query_id != server_query_id)) - { - server_query_id= profiling->thd->query_id; /* despite name, is global */ - profile_start.collect(); - while (! entries.is_empty()) - delete entries.pop(); - } - DBUG_VOID_RETURN; -} PROFILING::PROFILING() - :profile_id_counter(1), keeping(TRUE), enabled(FALSE), current(NULL), last(NULL) + :profile_id_counter(1), current(NULL), last(NULL) { } @@ -306,95 +295,110 @@ PROFILING::~PROFILING() delete current; } +/** + A new state is given, and that signals the profiler to start a new + timed step for the current query's profile. + + @param status_arg name of this step + @param function_arg calling function (usually supplied from compiler) + @param function_arg calling file (usually supplied from compiler) + @param function_arg calling line number (usually supplied from compiler) +*/ void PROFILING::status_change(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg) { DBUG_ENTER("PROFILING::status_change"); - + + if (status_arg == NULL) /* We don't know how to handle that */ + DBUG_VOID_RETURN; + + if (current == NULL) /* This profile was already discarded. */ + DBUG_VOID_RETURN; + if (unlikely(enabled)) - { - if (unlikely(current == NULL)) - reset(); + current->new_status(status_arg, function_arg, file_arg, line_arg); - DBUG_ASSERT(current != NULL); - - current->status(status_arg, function_arg, file_arg, line_arg); - } - - thd->proc_info= status_arg; DBUG_VOID_RETURN; } -void PROFILING::store() -{ - DBUG_ENTER("PROFILING::store"); +/** + Prepare to start processing a new query. It is an error to do this + if there's a query already in process; nesting is not supported. - /* Already stored */ - if (unlikely((last != NULL) && - (current != NULL) && - (last->server_query_id == current->server_query_id))) + @param initial_state (optional) name of period before first state change +*/ +void PROFILING::start_new_query(const char *initial_state) +{ + DBUG_ENTER("PROFILING::start_new_query"); + + /* This should never happen unless the server is radically altered. */ + if (unlikely(current != NULL)) { - DBUG_VOID_RETURN; + DBUG_PRINT("warning", ("profiling code was asked to start a new query " + "before the old query was finished. This is " + "probably a bug.")); + finish_current_query(); } - while (history.elements > thd->variables.profiling_history_size) - delete history.pop(); + enabled= (((thd)->options & OPTION_PROFILING) != 0); - if (likely(((thd)->options & OPTION_PROFILING) == 0)) - DBUG_VOID_RETURN; + if (! enabled) DBUG_VOID_RETURN; + DBUG_ASSERT(current == NULL); + current= new QUERY_PROFILE(this, initial_state); + + DBUG_VOID_RETURN; +} + +/** + Throw away the current profile, because it's useless or unwanted + or corrupted. +*/ +void PROFILING::discard_current_query() +{ + DBUG_ENTER("PROFILING::discard_current_profile"); + + delete current; + current= NULL; + + DBUG_VOID_RETURN; +} + +/** + Try to save the current profile entry, clean up the data if it shouldn't be + saved, and maintain the profile history size. Naturally, this may not + succeed if the profile was previously discarded, and that's expected. +*/ +void PROFILING::finish_current_query() +{ + DBUG_ENTER("PROFILING::finish_current_profile"); if (current != NULL) { - if (keeping && - (enabled) && /* ON at start? */ - (((thd)->options & OPTION_PROFILING) != 0) && /* and ON at end? */ - (current->query_source != NULL) && - (current->query_source[0] != '\0') && - (!current->entries.is_empty())) + /* The last fence-post, so we can support the span before this. */ + status_change("ending", NULL, NULL, 0); + + if ((enabled) && /* ON at start? */ + ((thd->options & OPTION_PROFILING) != 0) && /* and ON at end? */ + (current->query_source != NULL) && + (! current->entries.is_empty())) { current->profiling_query_id= next_profile_id(); /* assign an id */ - last= current; /* never contains something that is not in the history. */ history.push_back(current); + last= current; /* never contains something that is not in the history. */ current= NULL; - } + } else { delete current; current= NULL; } } - - DBUG_ASSERT(current == NULL); - if (enabled) - current= new QUERY_PROFILE(this, thd->query, thd->query_length); - DBUG_VOID_RETURN; -} - -/** - Store and clean up the old information and get ready to hold info about this - new query. This is called very often so it must be very lightweight if - profiling is not active. -*/ -void PROFILING::reset() -{ - DBUG_ENTER("PROFILING::reset"); - - store(); - - if (likely(((thd)->options & OPTION_PROFILING) == 0)) - { - enabled= FALSE; - DBUG_VOID_RETURN; - } - else - enabled= TRUE; - - if (current != NULL) - current->reset(); - keep(); + /* Maintain the history size. */ + while (history.elements > thd->variables.profiling_history_size) + delete history.pop(); DBUG_VOID_RETURN; } @@ -410,29 +414,29 @@ bool PROFILING::show_profiles() field_list.push_back(new Item_return_int("Duration", TIME_FLOAT_DIGITS-1, MYSQL_TYPE_DOUBLE)); field_list.push_back(new Item_empty_string("Query", 40)); - + if (thd->protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - + SELECT_LEX *sel= &thd->lex->select_lex; SELECT_LEX_UNIT *unit= &thd->lex->unit; ha_rows idx= 0; Protocol *protocol= thd->protocol; unit->set_limit(sel); - + void *iterator; - for (iterator= history.new_iterator(); - iterator != NULL; + for (iterator= history.new_iterator(); + iterator != NULL; iterator= history.iterator_next(iterator)) { prof= history.iterator_value(iterator); String elapsed; - PROFILE_ENTRY *ps= &prof->profile_start; - PROFILE_ENTRY *pe= prof->profile_end; + PROF_MEASUREMENT *ps= prof->profile_start; + PROF_MEASUREMENT *pe= prof->profile_end; if (++idx <= unit->offset_limit_cnt) continue; @@ -441,14 +445,14 @@ bool PROFILING::show_profiles() protocol->prepare_for_resend(); protocol->store((uint32)(prof->profiling_query_id)); - protocol->store((double)(pe->time_usecs - ps->time_usecs)/(1000.0*1000), + protocol->store((double)(pe->time_usecs - ps->time_usecs)/(1000.0*1000), (uint32) TIME_FLOAT_DIGITS-1, &elapsed); if (prof->query_source != NULL) - protocol->store(prof->query_source, strlen(prof->query_source), + protocol->store(prof->query_source, strlen(prof->query_source), system_charset_info); else protocol->store_null(); - + if (protocol->write()) DBUG_RETURN(TRUE); } @@ -456,16 +460,18 @@ bool PROFILING::show_profiles() DBUG_RETURN(FALSE); } -/* - This is an awful hack to let prepared statements tell us the query - that they're executing. +/** + At a point in execution where we know the query source, save the text + of it in the query profile. + + This must be called exactly once per descrete statement. */ void PROFILING::set_query_source(char *query_source_arg, uint query_length_arg) { DBUG_ENTER("PROFILING::set_query_source"); - /* We can't get this query source through normal means. */ - DBUG_ASSERT((thd->query == NULL) || (thd->query_length == 0)); + if (! enabled) + DBUG_VOID_RETURN; if (current != NULL) current->set_query_source(query_source_arg, query_length_arg); @@ -474,11 +480,10 @@ void PROFILING::set_query_source(char *query_source_arg, uint query_length_arg) DBUG_VOID_RETURN; } - /** Fill the information schema table, "query_profile", as defined in show.cc . There are two ways to get to this function: Selecting from the information - schema, and a SHOW command. + schema, and a SHOW command. */ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) { @@ -489,12 +494,11 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) QUERY_PROFILE *query; /* Go through each query in this thread's stored history... */ void *history_iterator; - for (history_iterator= history.new_iterator(); - history_iterator != NULL; + for (history_iterator= history.new_iterator(); + history_iterator != NULL; history_iterator= history.iterator_next(history_iterator)) { query= history.iterator_value(history_iterator); - PROFILE_ENTRY *previous= &(query->profile_start); /* Because we put all profiling info into a table that may be reordered, let @@ -504,18 +508,21 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) ulonglong seq; void *entry_iterator; - PROFILE_ENTRY *entry; + PROF_MEASUREMENT *entry, *previous= NULL; /* ...and for each query, go through all its state-change steps. */ - for (seq= 0, entry_iterator= query->entries.new_iterator(); - entry_iterator != NULL; + for (seq= 0, entry_iterator= query->entries.new_iterator(); + entry_iterator != NULL; entry_iterator= query->entries.iterator_next(entry_iterator), seq++, previous=entry, row_number++) { entry= query->entries.iterator_value(entry_iterator); + /* Skip the first. We count spans of fence, not fence-posts. */ + if (previous == NULL) continue; + if (thd->lex->orig_sql_command == SQLCOM_SHOW_PROFILE) { - /* + /* We got here via a SHOW command. That means that we stored information about the query we wish to show and that isn't in a WHERE clause at a higher level to filter out rows we @@ -555,43 +562,46 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) time that a status phrase took T(n)-T(n-1), this line must describe the previous status. */ - table->field[2]->store(previous->status, strlen(previous->status), + table->field[2]->store(previous->status, strlen(previous->status), system_charset_info); - my_decimal duration; - double2my_decimal(E_DEC_FATAL_ERROR, + my_decimal duration_decimal; + double2my_decimal(E_DEC_FATAL_ERROR, (entry->time_usecs-previous->time_usecs)/(1000.0*1000), - &duration); - table->field[3]->store_decimal(&duration); + &duration_decimal); + + table->field[3]->store_decimal(&duration_decimal); + #ifdef HAVE_GETRUSAGE - my_decimal cpu_utime, cpu_stime; - double2my_decimal(E_DEC_FATAL_ERROR, - RUSAGE_DIFF_USEC(entry->rusage.ru_utime, + my_decimal cpu_utime_decimal, cpu_stime_decimal; + + double2my_decimal(E_DEC_FATAL_ERROR, + RUSAGE_DIFF_USEC(entry->rusage.ru_utime, previous->rusage.ru_utime) / (1000.0*1000), - &cpu_utime); + &cpu_utime_decimal); - double2my_decimal(E_DEC_FATAL_ERROR, + double2my_decimal(E_DEC_FATAL_ERROR, RUSAGE_DIFF_USEC(entry->rusage.ru_stime, - previous->rusage.ru_stime) / + previous->rusage.ru_stime) / (1000.0*1000), - &cpu_stime); + &cpu_stime_decimal); - table->field[4]->store_decimal(&cpu_utime); - table->field[5]->store_decimal(&cpu_stime); + 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(); #else /* TODO: Add CPU-usage info for non-BSD systems */ #endif - + #ifdef HAVE_GETRUSAGE - table->field[6]->store((uint32)(entry->rusage.ru_nvcsw - + table->field[6]->store((uint32)(entry->rusage.ru_nvcsw - previous->rusage.ru_nvcsw)); table->field[6]->set_notnull(); - table->field[7]->store((uint32)(entry->rusage.ru_nivcsw - + table->field[7]->store((uint32)(entry->rusage.ru_nivcsw - previous->rusage.ru_nivcsw)); table->field[7]->set_notnull(); #else @@ -599,32 +609,32 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) #endif #ifdef HAVE_GETRUSAGE - table->field[8]->store((uint32)(entry->rusage.ru_inblock - + table->field[8]->store((uint32)(entry->rusage.ru_inblock - previous->rusage.ru_inblock)); table->field[8]->set_notnull(); - table->field[9]->store((uint32)(entry->rusage.ru_oublock - + table->field[9]->store((uint32)(entry->rusage.ru_oublock - previous->rusage.ru_oublock)); table->field[9]->set_notnull(); #else /* TODO: Add block IO info for non-BSD systems */ #endif - + #ifdef HAVE_GETRUSAGE - table->field[10]->store((uint32)(entry->rusage.ru_msgsnd - + table->field[10]->store((uint32)(entry->rusage.ru_msgsnd - previous->rusage.ru_msgsnd), true); table->field[10]->set_notnull(); - table->field[11]->store((uint32)(entry->rusage.ru_msgrcv - + table->field[11]->store((uint32)(entry->rusage.ru_msgrcv - previous->rusage.ru_msgrcv), true); table->field[11]->set_notnull(); #else /* TODO: Add message info for non-BSD systems */ #endif - + #ifdef HAVE_GETRUSAGE - table->field[12]->store((uint32)(entry->rusage.ru_majflt - + table->field[12]->store((uint32)(entry->rusage.ru_majflt - previous->rusage.ru_majflt), true); table->field[12]->set_notnull(); - table->field[13]->store((uint32)(entry->rusage.ru_minflt - + table->field[13]->store((uint32)(entry->rusage.ru_minflt - previous->rusage.ru_minflt), true); table->field[13]->set_notnull(); #else @@ -632,21 +642,22 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) #endif #ifdef HAVE_GETRUSAGE - table->field[14]->store((uint32)(entry->rusage.ru_nswap - + table->field[14]->store((uint32)(entry->rusage.ru_nswap - previous->rusage.ru_nswap), true); table->field[14]->set_notnull(); #else /* TODO: Add swap info for non-BSD systems */ #endif - - if ((entry->function != NULL) && (entry->file != NULL)) + + /* Emit the location that started this step, not that ended it. */ + if ((previous->function != NULL) && (previous->file != NULL)) { - table->field[15]->store(entry->function, strlen(entry->function), - system_charset_info); + table->field[15]->store(previous->function, strlen(previous->function), + system_charset_info); table->field[15]->set_notnull(); - table->field[16]->store(entry->file, strlen(entry->file), system_charset_info); + table->field[16]->store(previous->file, strlen(previous->file), system_charset_info); table->field[16]->set_notnull(); - table->field[17]->store(entry->line, true); + table->field[17]->store(previous->line, true); table->field[17]->set_notnull(); } diff --git a/sql/sql_profile.h b/sql/sql_profile.h index 5a28bc32442..022422fbb81 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -54,24 +54,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); #define PROFILE_ALL (~0) -#ifndef ENABLED_PROFILING - -# define thd_proc_info(thd, msg) do { (thd)->proc_info= (msg); } while (0) - -#else - -# define thd_proc_info(thd, msg) \ - do { \ - if (unlikely(((thd)->options & OPTION_PROFILING) != 0)) \ - { \ - (thd)->profiling.status_change((msg), __func__, __FILE__, __LINE__); \ - } \ - else \ - { \ - (thd)->proc_info= (msg); \ - } \ - } while (0) - +#if defined(ENABLED_PROFILING) #include "mysql_priv.h" #ifdef HAVE_SYS_RESOURCE_H @@ -79,7 +62,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); #endif -class PROFILE_ENTRY; +class PROF_MEASUREMENT; class QUERY_PROFILE; class PROFILING; @@ -193,7 +176,7 @@ public: /** A single entry in a single profile. */ -class PROFILE_ENTRY +class PROF_MEASUREMENT { private: friend class QUERY_PROFILE; @@ -212,22 +195,22 @@ private: double time_usecs; char *allocated_status_memory; - void set_status(const char *status_arg, const char *function_arg, + void set_label(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg); void clean_up(); - PROFILE_ENTRY(); - PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg); - PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg, + PROF_MEASUREMENT(); + PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg); + PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg); - ~PROFILE_ENTRY(); + ~PROF_MEASUREMENT(); void collect(); }; /** - The full profile for a single query, and includes multiple PROFILE_ENTRY + The full profile for a single query, and includes multiple PROF_MEASUREMENT objects. */ class QUERY_PROFILE @@ -237,21 +220,21 @@ private: PROFILING *profiling; - query_id_t server_query_id; /* Global id. */ query_id_t profiling_query_id; /* Session-specific id. */ char *query_source; - PROFILE_ENTRY profile_start; - PROFILE_ENTRY *profile_end; - Queue entries; + + PROF_MEASUREMENT *profile_start; + PROF_MEASUREMENT *profile_end; + Queue entries; - QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg, uint query_length_arg); + QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg); ~QUERY_PROFILE(); void set_query_source(char *query_source_arg, uint query_length_arg); /* Add a profile status change to the current profile. */ - void status(const char *status_arg, + void new_status(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg); @@ -269,7 +252,7 @@ private: class PROFILING { private: - friend class PROFILE_ENTRY; + friend class PROF_MEASUREMENT; friend class QUERY_PROFILE; /* @@ -291,39 +274,12 @@ public: ~PROFILING(); void set_query_source(char *query_source_arg, uint query_length_arg); - /** Reset the current profile and state of profiling for the next query. */ - void reset(); + void start_new_query(const char *initial_state= "starting"); - /** - Do we intend to keep the currently collected profile? - - We don't keep profiles for some commands, such as SHOW PROFILE, SHOW - PROFILES, and some SQLCOM commands which aren't useful to profile. The - keep() and discard() functions can be called many times, only the final - setting when the query finishes is used to decide whether to discard the - profile. - - The default is to keep the profile for all queries. - */ - inline void keep() { keeping= true; }; + void discard_current_query(); - /** - Do we intend to keep the currently collected profile? - @see keep() - */ - inline void discard() { keeping= false; }; + void finish_current_query(); - /** - Stash this profile in the profile history and remove the oldest - profile if the history queue is full, as defined by the - profiling_history_size system variable. - */ - void store(); - - /** - Called with every update of the status via thd_proc_info() , and is - therefore the main hook into the profiling code. - */ void status_change(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cd5b537996d..1eb6838d98e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3622,6 +3622,14 @@ ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx) /* Create information_schema table using schema_table data + @note + For MYSQL_TYPE_DECIMAL fields only, the field_length member has encoded + into it two numbers, based on modulus of base-10 numbers. In the ones + position is the number of decimals. Tens position is unused. In the + hundreds and thousands position is a two-digit decimal number representing + length. Encode this value with (decimals*100)+length , where + 0value, false))) + { + DBUG_RETURN(0); + } + item->decimals= fields_info->field_length%10; + item->max_length= (fields_info->field_length/100)%100; + if (item->unsigned_flag == 0) + item->max_length+= 1; + if (item->decimals > 0) + item->max_length+= 1; + item->set_name(fields_info->field_name, + strlen(fields_info->field_name), cs); + break; case MYSQL_TYPE_STRING: default: /* Don't let unimplemented types pass through. Could be a grave error. */ From f48c09e96faf73b032500b11385f25a780e22fa9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 15 Nov 2007 10:00:39 +0100 Subject: [PATCH 002/115] Revert a premature version upgrade - this is 5.0.51 still. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 64d02dd95d6..05a6620965b 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.53) +AM_INIT_AUTOMAKE(mysql, 5.0.51) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=53 +NDB_VERSION_BUILD=51 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 0679860358d42f2e6bb4c018c982549b9a09586f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 15 Nov 2007 10:55:47 +0100 Subject: [PATCH 003/115] BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE RENAME TABLE against a table with DATA/INDEX DIRECTORY overwrites the file to which the symlink points. This is security issue, because it is possible to create a table with some name in some non-system database and set DATA/INDEX DIRECTORY to mysql system database. Renaming this table to one of mysql system tables (e.g. user, host) would overwrite the system table. Return an error when the file to which the symlink points exist. (This is a copy of changeset 2007/11/06 18:09:33+04:00 svoj@mysql.com and its merge changesets on the way from 4.0 up to 5.0) mysql-test/r/symlink.result: A test case for BUG#32111, with after merge fix, and using proper variable. mysql-test/t/symlink.test: A test case for BUG#32111, with after merge fix, and using proper variable. mysys/my_symlink2.c: Return an error when the file to which the symlink points exist. --- mysql-test/r/symlink.result | 6 ++++++ mysql-test/t/symlink.test | 12 ++++++++++++ mysys/my_symlink2.c | 11 ++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 18299bf4298..833adbeb851 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -99,6 +99,12 @@ t1 CREATE TABLE `t1` ( `b` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE t1(a INT) +DATA DIRECTORY='TEST_DIR/master-data/mysql' +INDEX DIRECTORY='TEST_DIR/master-data/mysql'; +RENAME TABLE t1 TO user; +ERROR HY000: Can't create/write to file 'TEST_DIR/master-data/mysql/user.MYI' (Errcode: 17) +DROP TABLE t1; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 8c67a4c1048..7eaeaa00c0a 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -124,6 +124,18 @@ enable_query_log; show create table t1; drop table t1; +# +# BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE +# +--replace_result $MYSQLTEST_VARDIR TEST_DIR +eval CREATE TABLE t1(a INT) +DATA DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql' +INDEX DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql'; +--replace_result $MYSQLTEST_VARDIR TEST_DIR +--error 1 +RENAME TABLE t1 TO user; +DROP TABLE t1; + # # Test specifying DATA DIRECTORY that is the same as what would normally # have been chosen. (Bug #8707) diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index e2493874097..ee0a45cf93b 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -126,6 +126,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) int was_symlink= (!my_disable_symlinks && !my_readlink(link_name, from, MYF(0))); int result=0; + int name_is_different; DBUG_ENTER("my_rename_with_symlink"); if (!was_symlink) @@ -134,6 +135,14 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) /* Change filename that symlink pointed to */ strmov(tmp_name, to); fn_same(tmp_name,link_name,1); /* Copy dir */ + name_is_different= strcmp(link_name, tmp_name); + if (name_is_different && !access(tmp_name, F_OK)) + { + my_errno= EEXIST; + if (MyFlags & MY_WME) + my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST); + DBUG_RETURN(1); + } /* Create new symlink */ if (my_symlink(tmp_name, to, MyFlags)) @@ -145,7 +154,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) the same basename and different directories. */ - if (strcmp(link_name, tmp_name) && my_rename(link_name, tmp_name, MyFlags)) + if (name_is_different && my_rename(link_name, tmp_name, MyFlags)) { int save_errno=my_errno; my_delete(to, MyFlags); /* Remove created symlink */ From f2a9ad42a83816aff0f536f8453f67d841798d27 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 15 Nov 2007 14:59:40 +0100 Subject: [PATCH 004/115] Prevent a sytax error in the top-level "Makefile". Makefile.am: Prevent a sytax error in the commercial package: Removing "debian" would have produced an empty continuation line, the autotools cannot deal with that. --- Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 66daff4bd68..3e706fee80c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,8 +33,7 @@ DIST_SUBDIRS = . include @docs_dirs@ zlib \ @thread_dirs@ pstack \ @sql_union_dirs@ scripts @man_dirs@ tests SSL\ BUILD netware os2 @libmysqld_dirs@ \ - @bench_dirs@ support-files @tools_dirs@ win \ - debian + @bench_dirs@ support-files @tools_dirs@ win debian # Run these targets before any others, also make part of clean target, # to make sure we create new links after a clean. From 18f49fdf3d0d3890e8b97923bbe257da959dcaa4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Nov 2007 14:10:18 +0400 Subject: [PATCH 005/115] Bug#32458 Test "mysqlcheck" fails, because "mysqlcheck --repair" changed output format update result file because of Bug#26976 changes mysql-test/r/mysqlcheck.result: update result file --- mysql-test/r/mysqlcheck.result | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 1c42b0060f7..207b6ec88df 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -49,7 +49,8 @@ insert into t_bug25347 values (1),(2),(3); flush tables; removing and creating d_bug25347.t_bug25347 -error : Incorrect file format 't_bug25347' +Error : Incorrect file format 't_bug25347' +error : Corrupt insert into t_bug25347 values (4),(5),(6); ERROR HY000: Incorrect file format 't_bug25347' d_bug25347.t_bug25347 From 7952ac489b22175c9fcd1448b4b6eda23792d858 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Dec 2007 10:23:58 +0100 Subject: [PATCH 006/115] configure.in: Merged missing change in the 5.0 community repository, --without-server was not working if thread safe client was enabled (Bug#32898) configure.in: Merged missing change in the 5.0 community repository, --without-server was not working if thread safe client was enabled (Bug#32898) --- configure.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 05a6620965b..000bc69a967 100644 --- a/configure.in +++ b/configure.in @@ -2675,13 +2675,17 @@ AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware") export CC CXX CFLAGS CXXFLAGS LD LDFLAGS AR ac_configure_args="$ac_configure_args CFLAGS='$CFLAGS' CXXFLAGS='$CXXFLAGS'" -if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no" +if test "$with_server" != "no" -o "$THREAD_SAFE_CLIENT" != "no" then AC_DEFINE([THREAD], [1], [Define if you want to have threaded code. This may be undef on client code]) # Avoid _PROGRAMS names THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o" AC_SUBST(THREAD_LOBJECTS) +fi + +if test "$with_server" != "no" +then server_scripts="mysqld_safe mysql_install_db" sql_server_dirs="strings mysys dbug extra regex" From 6fd4c4042f1525fd7bdafb3a404b051b3ce1c87c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Jan 2008 13:47:43 +0100 Subject: [PATCH 007/115] configure.in: adjust version number configure.in: adjust version number --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 05a6620965b..9eb20b3fa7d 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.51) +AM_INIT_AUTOMAKE(mysql, 5.0.51a) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 From 2a3ed87d545d7d126db394e40472adf7bd3d209c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Jan 2008 15:15:11 +0100 Subject: [PATCH 008/115] template_instnt.cpp, yassl_imp.cpp, handshake.cpp: apply patch for bug#33814 extra/yassl/src/handshake.cpp: apply patch for bug#33814 extra/yassl/src/template_instnt.cpp: apply patch for bug#33814 extra/yassl/src/yassl_imp.cpp: apply patch for bug#33814 --- extra/yassl/src/handshake.cpp | 5 +++++ extra/yassl/src/template_instnt.cpp | 1 + extra/yassl/src/yassl_imp.cpp | 11 ++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 1d5a95820bb..262b5cb3b8b 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -527,6 +527,11 @@ void ProcessOldClientHello(input_buffer& input, SSL& ssl) input.read(len, sizeof(len)); uint16 randomLen; ato16(len, randomLen); + if (ch.suite_len_ > MAX_SUITE_SZ || sessionLen > ID_LEN || + randomLen > RAN_LEN) { + ssl.SetError(bad_input); + return; + } int j = 0; for (uint16 i = 0; i < ch.suite_len_; i += 3) { diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index f82f7924359..fe3a251b865 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -101,6 +101,7 @@ template void ysArrayDelete(unsigned char*); template void ysArrayDelete(char*); template int min(int, int); +template uint16 min(uint16, uint16); template unsigned int min(unsigned int, unsigned int); template unsigned long min(unsigned long, unsigned long); } diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 0bc95f64abc..b43d9c27355 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -621,6 +621,10 @@ void HandShakeHeader::Process(input_buffer& input, SSL& ssl) } uint len = c24to32(length_); + if (len > input.get_remaining()) { + ssl.SetError(bad_input); + return; + } hashHandShake(ssl, input, len); hs->set_length(len); @@ -1391,10 +1395,15 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello) // Suites byte tmp[2]; + uint16 len; tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; - ato16(tmp, hello.suite_len_); + ato16(tmp, len); + + hello.suite_len_ = min(len, static_cast(MAX_SUITE_SZ)); input.read(hello.cipher_suites_, hello.suite_len_); + if (len > hello.suite_len_) // ignore extra suites + input.set_current(input.get_current() + len - hello.suite_len_); // Compression hello.comp_len_ = input[AUTO]; From fd8471363a704fbd4c76c836ede58c649de83818 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Jan 2008 15:19:32 +0100 Subject: [PATCH 009/115] mysqlcheck.result: fix test case - bug#32458 mysql-test/r/mysqlcheck.result: fix test case - bug#32458 --- mysql-test/r/mysqlcheck.result | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 1c42b0060f7..207b6ec88df 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -49,7 +49,8 @@ insert into t_bug25347 values (1),(2),(3); flush tables; removing and creating d_bug25347.t_bug25347 -error : Incorrect file format 't_bug25347' +Error : Incorrect file format 't_bug25347' +error : Corrupt insert into t_bug25347 values (4),(5),(6); ERROR HY000: Incorrect file format 't_bug25347' d_bug25347.t_bug25347 From 333447eb999c539a1d179ad3ddf02dbd91b03bbc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Jan 2008 15:27:18 +0100 Subject: [PATCH 010/115] ha_federated.cc: patch for bug#29801 sql/ha_federated.cc: patch for bug#29801 --- sql/ha_federated.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index d8ffd6c55f8..4c15b13a5c9 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -2528,7 +2528,12 @@ int ha_federated::info(uint flag) status_query_string.length(0); result= mysql_store_result(mysql); - if (!result) + + /* + We're going to use fields num. 4, 12 and 13 of the resultset, + so make sure we have these fields. + */ + if (!result || (mysql_num_fields(result) < 14)) goto error; if (!mysql_num_rows(result)) From f1c8a588436d627911dc22363ad2523108795946 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Jan 2008 15:37:18 +0100 Subject: [PATCH 011/115] view_grant.result, view_grant.test, sql_view.cc: apply patch for bug#29908 mysql-test/r/view_grant.result: apply patch for bug#29908 mysql-test/t/view_grant.test: apply patch for bug#29908 sql/sql_view.cc: apply patch for bug#29908 --- mysql-test/r/view_grant.result | 51 ++++++++++++++++++++++++++++++++-- mysql-test/t/view_grant.test | 50 +++++++++++++++++++++++++++++++-- sql/sql_view.cc | 5 +--- 3 files changed, 97 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 0f9ce47dec6..eef61c65fb8 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -776,15 +776,60 @@ GRANT CREATE VIEW ON db26813.v2 TO u26813@localhost; GRANT DROP, CREATE VIEW ON db26813.v3 TO u26813@localhost; GRANT SELECT ON db26813.t1 TO u26813@localhost; ALTER VIEW v1 AS SELECT f2 FROM t1; -ERROR 42000: CREATE VIEW command denied to user 'u26813'@'localhost' for table 'v1' +ERROR 42000: Access denied; you need the SUPER privilege for this operation ALTER VIEW v2 AS SELECT f2 FROM t1; -ERROR 42000: DROP command denied to user 'u26813'@'localhost' for table 'v2' +ERROR 42000: Access denied; you need the SUPER privilege for this operation ALTER VIEW v3 AS SELECT f2 FROM t1; +ERROR 42000: Access denied; you need the SUPER privilege for this operation SHOW CREATE VIEW v3; View Create View -v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`f2` AS `f2` from `t1` +v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`f1` AS `f1` from `t1` DROP USER u26813@localhost; DROP DATABASE db26813; +# +# Bug#29908: A user can gain additional access through the ALTER VIEW. +# +CREATE DATABASE mysqltest_29908; +USE mysqltest_29908; +CREATE TABLE t1(f1 INT, f2 INT); +CREATE USER u29908_1@localhost; +CREATE DEFINER = u29908_1@localhost VIEW v1 AS SELECT f1 FROM t1; +CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS +SELECT f1 FROM t1; +GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost; +GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost; +GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost; +CREATE USER u29908_2@localhost; +GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost; +GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost; +GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost; +ALTER VIEW v1 AS SELECT f2 FROM t1; +ERROR 42000: Access denied; you need the SUPER privilege for this operation +ALTER VIEW v2 AS SELECT f2 FROM t1; +ERROR 42000: Access denied; you need the SUPER privilege for this operation +SHOW CREATE VIEW v2; +View Create View +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select `t1`.`f1` AS `f1` from `t1` +ALTER VIEW v1 AS SELECT f2 FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f2` AS `f2` from `t1` +ALTER VIEW v2 AS SELECT f2 FROM t1; +SHOW CREATE VIEW v2; +View Create View +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select `t1`.`f2` AS `f2` from `t1` +ALTER VIEW v1 AS SELECT f1 FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` +ALTER VIEW v2 AS SELECT f1 FROM t1; +SHOW CREATE VIEW v2; +View Create View +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select `t1`.`f1` AS `f1` from `t1` +DROP USER u29908_1@localhost; +DROP USER u29908_2@localhost; +DROP DATABASE mysqltest_29908; +####################################################################### DROP DATABASE IF EXISTS mysqltest1; DROP DATABASE IF EXISTS mysqltest2; CREATE DATABASE mysqltest1; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index a102f87c4e8..7f9eb4e1cff 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1034,10 +1034,11 @@ GRANT SELECT ON db26813.t1 TO u26813@localhost; connect (u1,localhost,u26813,,db26813); connection u1; ---error 1142 +--error ER_SPECIFIC_ACCESS_DENIED_ERROR ALTER VIEW v1 AS SELECT f2 FROM t1; ---error 1142 +--error ER_SPECIFIC_ACCESS_DENIED_ERROR ALTER VIEW v2 AS SELECT f2 FROM t1; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR ALTER VIEW v3 AS SELECT f2 FROM t1; connection root; @@ -1047,6 +1048,51 @@ DROP USER u26813@localhost; DROP DATABASE db26813; disconnect u1; +--echo # +--echo # Bug#29908: A user can gain additional access through the ALTER VIEW. +--echo # +connection root; +CREATE DATABASE mysqltest_29908; +USE mysqltest_29908; +CREATE TABLE t1(f1 INT, f2 INT); +CREATE USER u29908_1@localhost; +CREATE DEFINER = u29908_1@localhost VIEW v1 AS SELECT f1 FROM t1; +CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS + SELECT f1 FROM t1; +GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost; +GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost; +GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost; +CREATE USER u29908_2@localhost; +GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost; +GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost; +GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost; + +connect (u2,localhost,u29908_2,,mysqltest_29908); +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +ALTER VIEW v1 AS SELECT f2 FROM t1; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +ALTER VIEW v2 AS SELECT f2 FROM t1; +SHOW CREATE VIEW v2; + +connect (u1,localhost,u29908_1,,mysqltest_29908); +ALTER VIEW v1 AS SELECT f2 FROM t1; +SHOW CREATE VIEW v1; +ALTER VIEW v2 AS SELECT f2 FROM t1; +SHOW CREATE VIEW v2; + +connection root; +ALTER VIEW v1 AS SELECT f1 FROM t1; +SHOW CREATE VIEW v1; +ALTER VIEW v2 AS SELECT f1 FROM t1; +SHOW CREATE VIEW v2; + +DROP USER u29908_1@localhost; +DROP USER u29908_2@localhost; +DROP DATABASE mysqltest_29908; +disconnect u1; +disconnect u2; +--echo ####################################################################### + # # BUG#24040: Create View don't succed with "all privileges" on a database. # diff --git a/sql/sql_view.cc b/sql/sql_view.cc index fd05d97a94a..ea956031395 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -223,9 +223,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, { LEX *lex= thd->lex; bool link_to_local; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - bool definer_check_is_needed= mode != VIEW_ALTER || lex->definer; -#endif /* first table in list is target VIEW name => cut off it */ TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; @@ -280,7 +277,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, - same as current user - current user has SUPER_ACL */ - if (definer_check_is_needed && + if (lex->definer && (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || my_strcasecmp(system_charset_info, lex->definer->host.str, From a8cbbef15c089027cecd7f80b54b8992b49d7a36 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 15 Jul 2008 12:51:05 -0400 Subject: [PATCH 012/115] Fixed packet-test bug caused by if block that didn't have curly braces. --- sql/sql_parse.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ccd131e5f90..ab2099d932c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1559,8 +1559,10 @@ static bool do_command(THD *thd) /* Check if we can continue without closing the connection */ if (net->error != 3) + { return_value= TRUE; // We have to close it. goto out; + } net_send_error(thd, net->last_errno, NullS); net->error= 0; From f81792945a215a842894a0bc131c7ee7661f3442 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Wed, 16 Jul 2008 17:47:30 +0200 Subject: [PATCH 013/115] Put version number back to 5.0.67 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 8ac0ee407d8..7c90f0fc310 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.68) +AM_INIT_AUTOMAKE(mysql, 5.0.67) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=68 +NDB_VERSION_BUILD=67 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 9ee2262c9d815c266fc9d9bb69ab144dcc593a82 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Wed, 16 Jul 2008 18:07:16 +0200 Subject: [PATCH 014/115] Raise version number after cloning 5.0.67 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 7c90f0fc310..48d6515903f 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.67) +AM_INIT_AUTOMAKE(mysql, 5.0.69) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=67 +NDB_VERSION_BUILD=69 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 6256bf17b88da0b0e04f5223d67714e687e3738d Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 17 Jul 2008 20:19:13 -0300 Subject: [PATCH 015/115] Bug#33812: mysql client incorrectly parsing DELIMITER Revert fix for this bug as it introduced a regression reported in Bug#38158. client/mysql.cc: Revert fix for Bug#33812 mysql-test/r/mysql.result: Revert fix for Bug#33812 mysql-test/t/mysql_delimiter.sql: Revert fix for Bug#33812 --- client/mysql.cc | 31 +++++++++++++++++++++++++++++++ mysql-test/r/mysql.result | 2 -- mysql-test/t/mysql_delimiter.sql | 6 ------ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index c8d5522628d..9b14f9fb3ef 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2081,6 +2081,37 @@ static bool add_line(String &buffer,char *line,char *in_string, continue; } } + else if (!*ml_comment && !*in_string && + (end_of_line - pos) >= 10 && + !my_strnncoll(charset_info, (uchar*) pos, 10, + (const uchar*) "delimiter ", 10)) + { + // Flush previously accepted characters + if (out != line) + { + buffer.append(line, (uint32) (out - line)); + out= line; + } + + // Flush possible comments in the buffer + if (!buffer.is_empty()) + { + if (com_go(&buffer, 0) > 0) // < 0 is not fatal + DBUG_RETURN(1); + buffer.length(0); + } + + /* + Delimiter wants the get rest of the given line as argument to + allow one to change ';' to ';;' and back + */ + buffer.append(pos); + if (com_delimiter(&buffer, pos) > 0) + DBUG_RETURN(1); + + buffer.length(0); + break; + } else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter)) { // Found a statement. Continue parsing after the delimiter diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index bc50c686ac6..eded1a3fc3b 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -38,8 +38,6 @@ t2 t3 Tables_in_test t1 -delimiter -1 _ Test delimiter : from command line a diff --git a/mysql-test/t/mysql_delimiter.sql b/mysql-test/t/mysql_delimiter.sql index 917401275a2..533ac2ce093 100644 --- a/mysql-test/t/mysql_delimiter.sql +++ b/mysql-test/t/mysql_delimiter.sql @@ -60,12 +60,6 @@ use test// show tables// delimiter ; # Reset delimiter -# -# Bug #33812: mysql client incorrectly parsing DELIMITER -# -select a as delimiter from t1 -delimiter ; # Reset delimiter - # # Bug #36244: MySQL CLI doesn't recognize standalone -- as comment # before DELIMITER statement From 2d590c28257cefaa8d25a2bbdab189e362e1470c Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 28 Jul 2008 19:22:12 +0500 Subject: [PATCH 016/115] Bug#37428 Potential security issue with UDFs - linux shellcode execution. plugin_dir option backported from 5.1 per-file messages: sql/mysql_priv.h Bug#37428 Potential security issue with UDFs - linux shellcode execution. opt_plugin_dir and opt_plugin_dir_ptr declared. sql/mysqld.cc Bug#37428 Potential security issue with UDFs - linux shellcode execution. 'plugin_dir' option added sql/set_var.cc Bug#37428 Potential security issue with UDFs - linux shellcode execution. 'plugin_dir' option added. sql/sql_udf.cc Bug#37428 Potential security issue with UDFs - linux shellcode execution. opt_plugin_dir added to the udf->dl path. Warn if it's not specified. sql/unireg.h Bug#37428 Potential security issue with UDFs - linux shellcode execution. PLUGINDIR defined. --- sql/mysql_priv.h | 3 +++ sql/mysqld.cc | 11 +++++++++++ sql/set_var.cc | 1 + sql/sql_udf.cc | 26 +++++++++++++++++++++++--- sql/unireg.h | 3 +++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f3bda4e5819..c1694cbbbe4 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1362,6 +1362,9 @@ extern char *default_tz_name; extern my_bool opt_large_pages; extern uint opt_large_page_size; +extern char *opt_plugin_dir_ptr; +extern char opt_plugin_dir[FN_REFLEN]; + extern MYSQL_LOG mysql_log,mysql_slow_log,mysql_bin_log; extern FILE *bootstrap_file; extern int bootstrap_error; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7edc3b91752..d591ce46af7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -324,6 +324,9 @@ arg_cmp_func Arg_comparator::comparator_matrix[5][2] = /* static variables */ +char opt_plugin_dir[FN_REFLEN]; +char *opt_plugin_dir_ptr; + static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static bool volatile ready_to_exit; @@ -4984,6 +4987,7 @@ enum options_mysqld OPT_OLD_STYLE_USER_LIMITS, OPT_LOG_SLOW_ADMIN_STATEMENTS, OPT_TABLE_LOCK_WAIT_TIMEOUT, + OPT_PLUGIN_DIR, OPT_PORT_OPEN_TIMEOUT, OPT_MERGE, OPT_PROFILING, @@ -6223,6 +6227,10 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.optimizer_search_depth, (gptr*) &max_system_variables.optimizer_search_depth, 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, + {"plugin_dir", OPT_PLUGIN_DIR, + "Directory for plugins.", + (gptr*) &opt_plugin_dir_ptr, (gptr*) &opt_plugin_dir_ptr, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, "The size of the buffer that is allocated when preloading indexes", (gptr*) &global_system_variables.preload_buff_size, @@ -7761,6 +7769,9 @@ static void fix_paths(void) (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home); + (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr : + "", ""); + opt_plugin_dir_ptr= opt_plugin_dir; char *sharedir=get_relative_path(SHAREDIR); if (test_if_hard_path(sharedir)) diff --git a/sql/set_var.cc b/sql/set_var.cc index eb381bfecf4..a0ddef0b386 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1036,6 +1036,7 @@ struct show_var_st init_vars[]= { {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth, SHOW_SYS}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, + {"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, #ifdef ENABLED_PROFILING diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 34ca18d5c39..e3a0230d2fb 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -214,7 +214,17 @@ void udf_init() void *dl = find_udf_dl(tmp->dl); if (dl == NULL) { - if (!(dl = dlopen(tmp->dl, RTLD_NOW))) + char dlpath[FN_REFLEN]; + if (*opt_plugin_dir) + strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", tmp->dl, + NullS); + else + { + strxnmov(dlpath, sizeof(dlpath)-1, tmp->dl, NullS); + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "plugin_dir was not specified"); + } + if (!(dl = dlopen(dlpath, RTLD_NOW))) { /* Print warning to log */ sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl,errno,dlerror()); @@ -443,8 +453,18 @@ int mysql_create_function(THD *thd,udf_func *udf) } if (!(dl = find_udf_dl(udf->dl))) { - DBUG_PRINT("info", ("Calling dlopen, udf->dl: %s", udf->dl)); - if (!(dl = dlopen(udf->dl, RTLD_NOW))) + char dlpath[FN_REFLEN]; + if (*opt_plugin_dir) + strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", udf->dl, + NullS); + else + { + strxnmov(dlpath, sizeof(dlpath)-1, udf->dl, NullS); + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "plugin_dir was not specified"); + } + DBUG_PRINT("info", ("Calling dlopen, udf->dl: %s", dlpath)); + if (!(dl = dlopen(dlpath, RTLD_NOW))) { DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)", udf->dl,errno,dlerror())); diff --git a/sql/unireg.h b/sql/unireg.h index 1326b22c8c9..8e01e6222e6 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -35,6 +35,9 @@ #ifndef SHAREDIR #define SHAREDIR "share/" #endif +#ifndef PLUGINDIR +#define PLUGINDIR "lib/plugin" +#endif #define ER(X) errmesg[(X) - ER_ERROR_FIRST] #define ER_SAFE(X) (((X) >= ER_ERROR_FIRST && (X) <= ER_ERROR_LAST) ? ER(X) : "Invalid error code") From 94de2319e7d9eacc8a092ebb42c7300d568ea7cf Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 31 Jul 2008 12:41:30 +0300 Subject: [PATCH 017/115] Bug#34159: mysql_install_db fails with sql_mode=TRADITIONAL Reset session sql_mode before creating system tables as it is done in the mysql_fix_privilege_tables.sql script. scripts/mysql_system_tables.sql: reset sql_mode --- scripts/mysql_system_tables.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index d9c870f1d73..31eb205eed0 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -2,6 +2,7 @@ -- The system tables of MySQL Server -- +set sql_mode=''; set storage_engine=myisam; CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; From 1cbc2f7e3a1df747dd2aab1140e904e81a44cc8c Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 31 Jul 2008 14:42:44 +0500 Subject: [PATCH 018/115] Buq#32167 another privilege bypass with DATA/INDEX DIRECTORY. test_if_data_home_dir fixed to look into real path. Checks added to mi_open for symlinks into data home directory. per-file messages: include/my_sys.h Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. my_is_symlink interface added mysql-test/r/udf.result test result fixed (not related to #32167) mysys/my_symlink.c my_is_symlink() implementsd my_realpath() now returns the 'realpath' even if a file isn't a symlink --- include/my_sys.h | 1 + mysql-test/r/udf.result | 6 +++++ mysys/my_symlink.c | 50 +++++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index a2b705a0c59..359d3453cf5 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -575,6 +575,7 @@ extern int my_close(File Filedes,myf MyFlags); extern File my_dup(File file, myf MyFlags); extern int my_mkdir(const char *dir, int Flags, myf MyFlags); extern int my_readlink(char *to, const char *filename, myf MyFlags); +extern int my_is_symlink(const char *filename); extern int my_realpath(char *to, const char *filename, myf MyFlags); extern File my_create_with_symlink(const char *linkname, const char *filename, int createflags, int access_flags, diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index a79be1c3189..92185962d1f 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -1,5 +1,7 @@ drop table if exists t1; CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +Warnings: +Warning 1105 plugin_dir was not specified CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB"; ERROR HY000: Can't find function 'myfunc_nonexist' in library @@ -197,6 +199,8 @@ DROP FUNCTION avgcost; select * from mysql.func; name ret dl type CREATE FUNCTION is_const RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +Warnings: +Warning 1105 plugin_dir was not specified select IS_const(3); IS_const(3) const @@ -206,6 +210,8 @@ name ret dl type select is_const(3); ERROR 42000: FUNCTION test.is_const does not exist CREATE FUNCTION is_const RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +Warnings: +Warning 1105 plugin_dir was not specified select is_const(3) as const, is_const(3.14) as const, diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index 810c0c72632..4391d1fd009 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -2,7 +2,8 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -106,38 +107,38 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) #define BUFF_LEN FN_LEN #endif +int my_is_symlink(const char *filename __attribute__((unused))) +{ + struct stat stat_buff; + return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode); +} + + int my_realpath(char *to, const char *filename, myf MyFlags __attribute__((unused))) { #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) int result=0; char buff[BUFF_LEN]; - struct stat stat_buff; + char *ptr; DBUG_ENTER("my_realpath"); - if (!(MyFlags & MY_RESOLVE_LINK) || - (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode))) + DBUG_PRINT("info",("executing realpath")); + if ((ptr=realpath(filename,buff))) + strmake(to,ptr,FN_REFLEN-1); + else { - char *ptr; - DBUG_PRINT("info",("executing realpath")); - if ((ptr=realpath(filename,buff))) - { - strmake(to,ptr,FN_REFLEN-1); - } - else - { - /* - Realpath didn't work; Use my_load_path() which is a poor substitute - original name but will at least be able to resolve paths that starts - with '.'. - */ - DBUG_PRINT("error",("realpath failed with errno: %d", errno)); - my_errno=errno; - if (MyFlags & MY_WME) - my_error(EE_REALPATH, MYF(0), filename, my_errno); - my_load_path(to, filename, NullS); - result= -1; - } + /* + Realpath didn't work; Use my_load_path() which is a poor substitute + original name but will at least be able to resolve paths that starts + with '.'. + */ + DBUG_PRINT("error",("realpath failed with errno: %d", errno)); + my_errno=errno; + if (MyFlags & MY_WME) + my_error(EE_REALPATH, MYF(0), filename, my_errno); + my_load_path(to, filename, NullS); + result= -1; } DBUG_RETURN(result); #else @@ -145,3 +146,4 @@ int my_realpath(char *to, const char *filename, return 0; #endif } + From befef397b42d62c22bad858cb16fafcbfc675fff Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Mon, 4 Aug 2008 11:39:05 +0200 Subject: [PATCH 019/115] Use autoconf glue around new my_is_symlink to avoid stat(2) and friends being used on systems which don't support that interface. --- mysys/my_symlink.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index 4391d1fd009..f7a31b92f05 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -109,8 +109,12 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) int my_is_symlink(const char *filename __attribute__((unused))) { +#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) struct stat stat_buff; return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode); +#else + return 0; +#endif } From 8348a92853471d14028defb441979743bcdde79f Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Mon, 4 Aug 2008 12:05:21 +0200 Subject: [PATCH 020/115] Change preprocessor tests to match what we will be using. --- mysys/my_symlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index f7a31b92f05..f797d75c27b 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -109,7 +109,7 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) int my_is_symlink(const char *filename __attribute__((unused))) { -#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) +#if defined(HAVE_LSTAT) && defined(S_ISLNK) struct stat stat_buff; return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode); #else From cc97ca3513a0bd70b11299e292f3646d52b3a980 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Mon, 4 Aug 2008 13:45:50 +0200 Subject: [PATCH 021/115] Revert previous unintentional license change. --- mysys/my_symlink.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index f797d75c27b..49c63fc3948 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -2,8 +2,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of From c5738c0051cfd903804afd06353f3dc431ec2726 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Dec 2008 17:53:47 +0100 Subject: [PATCH 022/115] Raise version number after cloning 5.0.75 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 0dd71851315..48ac64d86c2 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.75) +AM_INIT_AUTOMAKE(mysql, 5.0.77) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=75 +NDB_VERSION_BUILD=77 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From bd414485de627818a8fd28fc00887d919d4e0ae1 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 24 Feb 2009 18:47:12 +0400 Subject: [PATCH 023/115] Fix for bug#42009: SELECT into variable gives different results to direct SELECT Problem: storing "SELECT ... INTO @var ..." results in variables we used val_xxx() methods which returned results of the current row. So, in some cases (e.g. SELECT DISTINCT, GROUP BY or HAVING) we got data from the first row of a new group (where we evaluate a clause) instead of data from the last row of the previous group. Fix: use val_xxx_result() counterparts to get proper results. mysql-test/r/distinct.result: Fix for bug#42009: SELECT into variable gives different results to direct SELECT - results adjusted. mysql-test/r/user_var.result: Fix for bug#42009: SELECT into variable gives different results to direct SELECT - test result. mysql-test/t/user_var.test: Fix for bug#42009: SELECT into variable gives different results to direct SELECT - test case. sql/item_func.cc: Fix for bug#42009: SELECT into variable gives different results to direct SELECT - Item_func_set_user_var::save_item_result() added to evaluate and store an item's result into a user variable. sql/item_func.h: Fix for bug#42009: SELECT into variable gives different results to direct SELECT - Item_func_set_user_var::save_item_result() added to evaluate and store an item's result into a user variable. sql/sql_class.cc: Fix for bug#42009: SELECT into variable gives different results to direct SELECT - use Item_func_set_user_var::save_item_result() to store results into user variables. --- mysql-test/r/distinct.result | 8 ++++---- mysql-test/r/user_var.result | 11 +++++++++++ mysql-test/t/user_var.test | 12 ++++++++++++ sql/item_func.cc | 35 +++++++++++++++++++++++++++++++++++ sql/item_func.h | 1 + sql/sql_class.cc | 2 +- 6 files changed, 64 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index 114d3088fe8..ddbee3ec79c 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -629,21 +629,21 @@ SELECT DISTINCT @v5:= fruit_id, @v6:= fruit_name INTO @v7, @v8 FROM t1 WHERE fruit_name = 'APPLE'; SELECT @v5, @v6, @v7, @v8; @v5 @v6 @v7 @v8 -3 PEAR 3 PEAR +2 APPLE 2 APPLE SELECT DISTINCT @v5 + fruit_id, CONCAT(@v6, fruit_name) INTO @v9, @v10 FROM t1 WHERE fruit_name = 'APPLE'; SELECT @v5, @v6, @v7, @v8, @v9, @v10; @v5 @v6 @v7 @v8 @v9 @v10 -3 PEAR 3 PEAR 5 PEARAPPLE +2 APPLE 2 APPLE 4 APPLEAPPLE SELECT DISTINCT @v11:= @v5 + fruit_id, @v12:= CONCAT(@v6, fruit_name) INTO @v13, @v14 FROM t1 WHERE fruit_name = 'APPLE'; SELECT @v11, @v12, @v13, @v14; @v11 @v12 @v13 @v14 -6 PEARPEAR 6 PEARPEAR +4 APPLEAPPLE 4 APPLEAPPLE SELECT DISTINCT @v13, @v14 INTO @v15, @v16 FROM t1 WHERE fruit_name = 'APPLE'; SELECT @v15, @v16; @v15 @v16 -6 PEARPEAR +4 APPLEAPPLE SELECT DISTINCT 2 + 2, 'Bob' INTO @v17, @v18 FROM t1 WHERE fruit_name = 'APPLE'; SELECT @v17, @v18; diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 80b5dccc198..bfa95d8f92b 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -353,3 +353,14 @@ select @a:=f4, count(f4) from t1 group by 1 desc; 2.6 1 1.6 4 drop table t1; +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (0, 0), (2, 1), (2, 3), (1, 1), (30, 20); +SELECT a, b INTO @a, @b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b; +SELECT @a, @b; +@a @b +2 3 +SELECT a, b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b; +a b +2 3 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 3a3e8f88f83..d39b49a0e87 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -237,3 +237,15 @@ select @a:=f2, count(f2) from t1 group by 1 desc; select @a:=f3, count(f3) from t1 group by 1 desc; select @a:=f4, count(f4) from t1 group by 1 desc; drop table t1; + +# +# Bug#42009: SELECT into variable gives different results to direct SELECT +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (0, 0), (2, 1), (2, 3), (1, 1), (30, 20); +SELECT a, b INTO @a, @b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b; +SELECT @a, @b; +SELECT a, b FROM t1 WHERE a=2 AND b=3 GROUP BY a, b; +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 55324923fe2..519b476ccf8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4147,6 +4147,41 @@ Item_func_set_user_var::check(bool use_result_field) } +/** + @brief Evaluate and store item's result. + This function is invoked on "SELECT ... INTO @var ...". + + @param item An item to get value from. +*/ + +void Item_func_set_user_var::save_item_result(Item *item) +{ + DBUG_ENTER("Item_func_set_user_var::save_item_result"); + + switch (cached_result_type) { + case REAL_RESULT: + save_result.vreal= item->val_result(); + break; + case INT_RESULT: + save_result.vint= item->val_int_result(); + unsigned_flag= item->unsigned_flag; + break; + case STRING_RESULT: + save_result.vstr= item->str_result(&value); + break; + case DECIMAL_RESULT: + save_result.vdec= item->val_decimal_result(&decimal_buff); + break; + case ROW_RESULT: + default: + // Should never happen + DBUG_ASSERT(0); + break; + } + DBUG_VOID_RETURN; +} + + /* This functions is invoked on SET @variable or @variable:= expression. diff --git a/sql/item_func.h b/sql/item_func.h index 7e15a536cf2..33aeddfe6e6 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1308,6 +1308,7 @@ public: bool send(Protocol *protocol, String *str_arg); void make_field(Send_field *tmp_field); bool check(bool use_result_field); + void save_item_result(Item *item); bool update(); enum Item_result result_type () const { return cached_result_type; } bool fix_fields(THD *thd, Item **ref); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9ff602bb62e..a95003d440b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2041,7 +2041,7 @@ bool select_dumpvar::send_data(List &items) { Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item); suv->fix_fields(thd, 0); - suv->check(0); + suv->save_item_result(item); suv->update(); } } From 6e0a64ef569584faecaaf2ad36903d7198a2e039 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Apr 2009 13:30:52 +0200 Subject: [PATCH 024/115] adjust version number --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index afadd2e0c40..6244b78a723 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.80) +AM_INIT_AUTOMAKE(mysql, 5.0.81) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=80 +NDB_VERSION_BUILD=81 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From f6eb9426ce9ba72e5a6d74755734d22aadba32e0 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Sun, 19 Apr 2009 02:21:33 +0100 Subject: [PATCH 025/115] BUG#43949 Initialization of slave produces a warning message in Valgrind In order to define the --slave-load-tmpdir, the init_relay_log_file() was calling fn_format(MY_PACK_FILENAME) which internally was indirectly calling strmov_overlapp() (through pack_dirname) and the following warning message was being printed out while running in Valgrind: "source and destination overlap in strcpy". We fixed the issue by removing the flag MY_PACK_FILENAME as it was not necessary. In a nutshell, with this flag the function fn_format() tried to replace a directory by either "~", "." or "..". However, we wanted exactly to remove such strings. In this patch, we also refactored the functions init_relay_log_file() and check_temp_dir(). The former was refactored to call the fn_format() with the flag MY_SAFE_PATH along with the MY_RETURN_REAL_PATH, in order to avoid issues with long directories and return an absolute path, respectively. The flag MY_SAFE_UNPACK_FILENAME was removed too as it was responsible for removing "~", "." or ".." only from the file parameter and we wanted to remove such strings from the directory parameter in the fn_format(). This result is stored in an rli variable, which is then processed by the other function in order to verify if the directory exists and if we are able to create files in it. mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test: Changed the output to make it consistent among different runs. mysys/mf_format.c: Replaced a return for DBUG_RETURN. --- .../rpl/r/rpl_slave_load_tmpdir_not_exist.result | 2 +- .../rpl/t/rpl_slave_load_tmpdir_not_exist.test | 4 ++-- mysys/mf_format.c | 2 +- sql/rpl_rli.cc | 13 ++++++++++--- sql/slave.cc | 11 +++++++++-- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result b/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result index a158fb5dfc4..3ed14a9cb6b 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result +++ b/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result @@ -3,4 +3,4 @@ MASTER_CONNECT_RETRY=1, MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_MYPORT; START SLAVE; -Unable to use slave's temporary directory ../../../error - Can't read dir of '../../../error' (Errcode: 2) +12 diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test index 3a80fa43f20..68c41abf537 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test +++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test @@ -20,5 +20,5 @@ eval CHANGE MASTER TO MASTER_USER='root', START SLAVE; source include/wait_for_slave_sql_to_stop.inc; -let $error=query_get_value("show slave status", Last_SQL_Error, 1); -echo $error; +let $errno=query_get_value("show slave status", Last_SQL_Errno, 1); +echo $errno; diff --git a/mysys/mf_format.c b/mysys/mf_format.c index f199132626b..6afa2938fa3 100644 --- a/mysys/mf_format.c +++ b/mysys/mf_format.c @@ -79,7 +79,7 @@ char * fn_format(char * to, const char *name, const char *dir, /* To long path, return original or NULL */ size_t tmp_length; if (flag & MY_SAFE_PATH) - return NullS; + DBUG_RETURN(NullS); tmp_length= strlength(startpos); DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %u",dev,ext, (uint) length)); diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index e93417374fe..45c0efb10c2 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -104,9 +104,16 @@ int init_relay_log_info(Relay_log_info* rli, rli->tables_to_lock= 0; rli->tables_to_lock_count= 0; - fn_format(rli->slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "", - MY_PACK_FILENAME | MY_UNPACK_FILENAME | - MY_RETURN_REAL_PATH); + char pattern[FN_REFLEN]; + if (fn_format(pattern, PREFIX_SQL_LOAD, slave_load_tmpdir, "", + MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS) + { + pthread_mutex_unlock(&rli->data_lock); + sql_print_error("Unable to use slave's temporary directory %s", + slave_load_tmpdir); + DBUG_RETURN(1); + } + unpack_filename(rli->slave_patternload_file, pattern); rli->slave_patternload_file_size= strlen(rli->slave_patternload_file); /* diff --git a/sql/slave.cc b/sql/slave.cc index a0db9837648..84f876e4a7a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2648,13 +2648,20 @@ err: LOAD DATA INFILE. */ static -int check_temp_dir(char* tmp_dir, char *tmp_file) +int check_temp_dir(char* tmp_file) { int fd; MY_DIR *dirp; + char tmp_dir[FN_REFLEN]; + size_t tmp_dir_size; DBUG_ENTER("check_temp_dir"); + /* + Get the directory from the temporary file. + */ + dirname_part(tmp_dir, tmp_file, &tmp_dir_size); + /* Check if the directory exists. */ @@ -2810,7 +2817,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff),rli->group_relay_log_name, llstr(rli->group_relay_log_pos,llbuff1)); - if (check_temp_dir(slave_load_tmpdir, rli->slave_patternload_file)) + if (check_temp_dir(rli->slave_patternload_file)) { rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), "Unable to use slave's temporary directory %s - %s", From fb2d75cb75e438fe0912cb81347638167e9ff8ca Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 10:54:26 -0700 Subject: [PATCH 026/115] Bug #27884: mysql --html does not quote HTML special characters in output Fix encoding of field values and names in HTML output from mysql client. --- client/mysql.cc | 11 +++++++---- mysql-test/r/mysql.result | 1 + mysql-test/t/mysql.test | 6 ++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 46141cd975f..eb8b522d972 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3381,9 +3381,12 @@ print_table_data_html(MYSQL_RES *result) { while((field = mysql_fetch_field(result))) { - tee_fprintf(PAGER, "%s", (field->name ? - (field->name[0] ? field->name : - "   ") : "NULL")); + tee_fputs("", PAGER); + if (field->name && field->name[0]) + xmlencode_print(field->name, field->name_length); + else + tee_fputs(field->name ? "   " : "NULL", PAGER); + tee_fputs("", PAGER); } (void) tee_fputs("", PAGER); } @@ -3396,7 +3399,7 @@ print_table_data_html(MYSQL_RES *result) for (uint i=0; i < mysql_num_fields(result); i++) { (void) tee_fputs("", PAGER); - safe_put_field(cur[i],lengths[i]); + xmlencode_print(cur[i], lengths[i]); (void) tee_fputs("", PAGER); } (void) tee_fputs("", PAGER); diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 5054c3aa76f..c53a2243811 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -200,4 +200,5 @@ Warning (Code 1286): Unknown table engine 'nonexistent2' Warning (Code 1266): Using storage engine MyISAM for table 't2' Error (Code 1050): Table 't2' already exists drop tables t1, t2; +
<
< & >
End of tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 7e970d5b104..91679c8c2ff 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -367,4 +367,10 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql; drop tables t1, t2; +# +# Bug #27884: mysql --html does not quote HTML special characters in output +# +--exec $MYSQL --html test -e "select '< & >' as \`<\`" + +--echo --echo End of tests From 5faee8ed81220fb87ad95975e008af3ca92681c5 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:12:50 -0700 Subject: [PATCH 027/115] Check for MEMORY, HEAP, and BLACKHOLE in mysql_convert_table_format when preventing a change that would result in table data loss. (Bug #27149) Also updated mysql_convert_table_format to use --engine as the documentation claimed, and use the engine terminology throughout instead of the obsolete 'table type'. --- scripts/mysql_convert_table_format.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/scripts/mysql_convert_table_format.sh b/scripts/mysql_convert_table_format.sh index d15c7b28410..e49c702d1df 100644 --- a/scripts/mysql_convert_table_format.sh +++ b/scripts/mysql_convert_table_format.sh @@ -23,18 +23,18 @@ $opt_help=$opt_version=$opt_verbose=$opt_force=0; $opt_user=$opt_database=$opt_password=undef; $opt_host="localhost"; $opt_socket=""; -$opt_type="MYISAM"; +$opt_engine="MYISAM"; $opt_port=0; $exit_status=0; -GetOptions("force","help","host=s","password=s","user=s","type=s","verbose","version","socket=s", "port=i") || +GetOptions("force","help","host=s","password=s","user=s","engine|type=s","verbose","version","socket=s", "port=i") || usage(0); usage($opt_version) if ($#ARGV < 0 || $opt_help || $opt_version); $opt_database=shift(@ARGV); -if (uc($opt_type) eq "HEAP") +if (grep { /^$opt_engine$/i } qw(HEAP MEMORY BLACKHOLE)) { - print "Converting to type HEAP would delete your tables; aborting\n"; + print "Converting to '$opt_engine' would delete your data; aborting\n"; exit(1); } @@ -76,14 +76,15 @@ foreach $table (@ARGV) $sth=$dbh->prepare("show table status like '$table'"); if ($sth->execute && ($row = $sth->fetchrow_arrayref)) { - if (uc($row->[1]) eq uc($opt_type)) + if (uc($row->[1]) eq uc($opt_engine)) { - print "$table is already of type $opt_type; Ignored\n"; + print "$table already uses the '$opt_engine' engine; Ignored\n"; next; } } print "converting $table\n" if ($opt_verbose); - if (!$dbh->do("ALTER TABLE $table ENGINE=$opt_type")) + $table=~ s/`/``/g; + if (!$dbh->do("ALTER TABLE `$table` ENGINE=$opt_engine")) { print STDERR "Can't convert $table: Error $DBI::errstr\n"; exit(1) if (!$opt_force); @@ -103,7 +104,7 @@ sub usage print < Date: Tue, 28 Apr 2009 11:16:44 -0700 Subject: [PATCH 028/115] Make help text for perror more accurate. (Bug #34574) --- extra/perror.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/perror.c b/extra/perror.c index 80eb2af2dae..a98a4fc3d1b 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -115,7 +115,7 @@ static void usage(void) { print_version(); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); - printf("Print a description for a system error code or an error code from\na MyISAM/ISAM/BDB table handler.\n"); + printf("Print a description for a system error code or a MySQL error code.\n"); printf("If you want to get the error for a negative error code, you should use\n-- before the first error code to tell perror that there was no more options.\n\n"); printf("Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]]\n",my_progname); my_print_help(my_long_options); From 137ec698ffb87ed619951e926e817475d20981e4 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:19:58 -0700 Subject: [PATCH 029/115] Update list of sorting options in mysqldumpslow (Bug #20454) --- scripts/mysqldumpslow.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mysqldumpslow.sh b/scripts/mysqldumpslow.sh index ce2670b2abd..1e942b035cb 100644 --- a/scripts/mysqldumpslow.sh +++ b/scripts/mysqldumpslow.sh @@ -20,7 +20,7 @@ GetOptions(\%opt, 'v|verbose+',# verbose 'help+', # write usage info 'd|debug+', # debug - 's=s', # what to sort by (t, at, l, al, r, ar etc) + 's=s', # what to sort by (al, at, ar, c, t, l, r) 'r!', # reverse the sort order (largest last instead of first) 't=i', # just show the top n queries 'a!', # don't abstract all numbers to N and strings to 'S' @@ -163,7 +163,7 @@ Parse and summarize the MySQL slow query log. Options are -v verbose -d debug - -s ORDER what to sort by (t, at, l, al, r, ar etc), 'at' is default + -s ORDER what to sort by (al, at, ar, c, t, l, r), 'at' is default -r reverse the sort order (largest last instead of first) -t NUM just show the top n queries -a don't abstract all numbers to N and strings to 'S' From 3e0214b8c6bd9f9b499da9eab36b5c41532bb990 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:21:47 -0700 Subject: [PATCH 030/115] Add missing newline to usage message of ndb_print_backup_file (Bug #34989) --- storage/ndb/src/kernel/blocks/backup/read.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/src/kernel/blocks/backup/read.cpp b/storage/ndb/src/kernel/blocks/backup/read.cpp index 8f4d0485f0e..78f6f2f1b50 100644 --- a/storage/ndb/src/kernel/blocks/backup/read.cpp +++ b/storage/ndb/src/kernel/blocks/backup/read.cpp @@ -50,7 +50,7 @@ main(int argc, const char * argv[]){ ndb_init(); if(argc <= 1){ - printf("Usage: %s ", argv[0]); + printf("Usage: %s \n", argv[0]); exit(1); } FILE * f = fopen(argv[1], "rb"); From 00916a44c7e79b198188817df30b0892b1e5527b Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:23:21 -0700 Subject: [PATCH 031/115] Fix list of options enabled by mysqldump --compact (Bug #32408) --- client/mysqldump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 5a1fa3cc090..44106388d69 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -221,7 +221,7 @@ static struct my_option my_long_options[] = (uchar**) &opt_compatible_mode_str, (uchar**) &opt_compatible_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compact", OPT_COMPACT, - "Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs. Enables options --skip-add-drop-table --no-set-names --skip-disable-keys --skip-add-locks", + "Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs. Enables options --skip-add-drop-table --skip-add-locks --skip-comments --skip-disable-keys --skip-set-charset", (uchar**) &opt_compact, (uchar**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"complete-insert", 'c', "Use complete insert statements.", From 23116951ae201ed4b492c186ec09817a4df6e1fa Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:26:31 -0700 Subject: [PATCH 032/115] Make SSL options appear in correct place in mysql_upgrade and mysqltest usage information. (Bug #31883) --- client/mysql_upgrade.c | 2 +- client/mysqltest.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 190bb2383e9..c50f7e03c27 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -115,11 +115,11 @@ static struct my_option my_long_options[]= #endif {"socket", 'S', "Socket file to use for connection.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#include {"tmpdir", 't', "Directory for temporary files", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"user", 'u', "User for login if not current user.", (uchar**) &opt_user, (uchar**) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#include {"verbose", 'v', "Display more output about the process", (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, diff --git a/client/mysqltest.cc b/client/mysqltest.cc index fdd4ff141bc..fb6baa744b2 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5665,11 +5665,11 @@ static struct my_option my_long_options[] = {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select", (uchar**) &sp_protocol, (uchar**) &sp_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#include "sslopt-longopts.h" {"tail-lines", OPT_TAIL_LINES, "Number of lines of the resul to include in a failure report", (uchar**) &opt_tail_lines, (uchar**) &opt_tail_lines, 0, GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0}, -#include "sslopt-longopts.h" {"test-file", 'x', "Read test from/in this file (default stdin).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"timer-file", 'm', "File where the timing in micro seconds is stored.", From a9a322e11ff601e72585d426fe7c9d0fdab5aa69 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:28:03 -0700 Subject: [PATCH 033/115] mysqld_multi still had mentions of safe_mysqld instead of mysqld_safe, as well as some unclear example paths. (Bug #28094) --- scripts/mysqld_multi.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 3cb4665eb1c..f35be69c151 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -316,11 +316,11 @@ sub start_mysqlds() $tmp.= " $options[$j]"; } } - if ($opt_verbose && $com =~ m/\/safe_mysqld$/ && !$info_sent) + if ($opt_verbose && $com =~ m/\/(safe_mysqld|mysqld_safe)$/ && !$info_sent) { - print "WARNING: safe_mysqld is being used to start mysqld. In this case you "; + print "WARNING: $1 is being used to start mysqld. In this case you "; print "may need to pass\n\"ledir=...\" under groups [mysqldN] to "; - print "safe_mysqld in order to find the actual mysqld binary.\n"; + print "$1 in order to find the actual mysqld binary.\n"; print "ledir (library executable directory) should be the path to the "; print "wanted mysqld binary.\n\n"; $info_sent= 1; @@ -670,9 +670,9 @@ language = @datadir@/mysql/english user = unix_user1 [mysqld3] -mysqld = /path/to/safe_mysqld/safe_mysqld +mysqld = /path/to/mysqld_safe ledir = /path/to/mysqld-binary/ -mysqladmin = /path/to/mysqladmin/mysqladmin +mysqladmin = /path/to/mysqladmin socket = /tmp/mysql.sock3 port = 3308 pid-file = @localstatedir@3/hostname.pid3 From 39e4b5ebd23742bfcf65e61d586aaa6f9191cc17 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:30:21 -0700 Subject: [PATCH 034/115] Remove extraneous space in --debug-check usage info. --- client/mysql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index eb8b522d972..d29bd8571c9 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1345,7 +1345,7 @@ static struct my_option my_long_options[] = {"debug", '#', "Output debug log", (uchar**) &default_dbug_option, (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .", + {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", 'T', "Print some debug info at exit.", (uchar**) &debug_info_flag, From f72fd8fe219ef362a241206117b038df92c97b57 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 28 Apr 2009 11:47:34 -0700 Subject: [PATCH 035/115] Add support for wildcards in mysql_convert_table_format, and add short options for all of the long options. (Bug #30373, original contribution by Tobias Asplund) --- scripts/mysql_convert_table_format.sh | 61 ++++++++++++++++++--------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/scripts/mysql_convert_table_format.sh b/scripts/mysql_convert_table_format.sh index e49c702d1df..6f586d0e8e0 100644 --- a/scripts/mysql_convert_table_format.sh +++ b/scripts/mysql_convert_table_format.sh @@ -27,9 +27,21 @@ $opt_engine="MYISAM"; $opt_port=0; $exit_status=0; -GetOptions("force","help","host=s","password=s","user=s","engine|type=s","verbose","version","socket=s", "port=i") || - usage(0); +GetOptions( + "e|engine|type=s" => \$opt_type, + "f|force" => \$opt_force, + "help|?" => \$opt_help, + "h|host=s" => \$opt_host, + "p|password=s" => \$opt_password, + "u|user=s" => \$opt_user, + "v|verbose" => \$opt_verbose, + "V|version" => \$opt_version, + "S|socket=s" => \$opt_socket, + "P|port=i" => \$opt_port +) || usage(0); + usage($opt_version) if ($#ARGV < 0 || $opt_help || $opt_version); + $opt_database=shift(@ARGV); if (grep { /^$opt_engine$/i } qw(HEAP MEMORY BLACKHOLE)) @@ -54,21 +66,29 @@ $dbh = DBI->connect("DBI:mysql:$opt_database:${opt_host}$connect_opt", { PrintError => 0}) || die "Can't connect to database $opt_database: $DBI::errstr\n"; -if ($#ARGV < 0) +my @tables; + +push(@ARGV, "%") if(!@ARGV); + +foreach $pattern (@ARGV) { - # Fetch all table names from the database my ($sth,$row); - $sth=$dbh->prepare("show tables"); - $sth->execute || die "Can't get tables from $opt_database; $DBI::errstr\n"; + $sth=$dbh->prepare("SHOW TABLES LIKE ?"); + $rv= $sth->execute($pattern); + if(!int($rv)) + { + warn "Can't get tables matching '$pattern' from $opt_database; $DBI::errstr\n"; + exit(1) unless $opt_force; + } while (($row = $sth->fetchrow_arrayref)) { - push(@ARGV,$row->[0]); + push(@tables, $row->[0]); } $sth->finish; } print "Converting tables:\n" if ($opt_verbose); -foreach $table (@ARGV) +foreach $table (@tables) { my ($sth,$row); @@ -106,40 +126,41 @@ sub usage Conversion of a MySQL tables to other storage engines - Usage: $0 database [tables] + Usage: $0 database [table[ table ...]] If no tables has been specifed, all tables in the database will be converted. + You can also use wildcards, ie "my%" The following options are available: ---force +-f, --force Continue even if there is some error. ---help +-?, --help Shows this help ---engine='engine' +-e, --engine=ENGINE Converts tables to the given storage engine (Default: $opt_engine) ---host='host name' (Default $opt_host) - Host name where the database server is located. +-h, --host=HOST + Host name where the database server is located. (Default: $opt_host) ---password='password' +-p, --password=PASSWORD Password for the current user. ---port=port +-P, --port=PORT TCP/IP port to connect to if host is not "localhost". ---socket='/path/to/socket' +-S, --socket=SOCKET Socket to connect with. ---user='user_name' +-u, --user=USER User name to log into the SQL server. ---verbose +-v, --verbose This is a test specific option that is only used when debugging a test. Print more information about what is going on. ---version +-V, --version Shows the version of this program. EOF exit(1); From f0791b8b6b02286a7a01b7659050f3bd900a3529 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 1 May 2009 00:20:37 +0500 Subject: [PATCH 036/115] Bug #37362: Crash in do_field_eq EXPLAIN EXTENDED of nested query containing a error: 1054 Unknown column '...' in 'field list' may cause a server crash. Parse error like described above forces a call to JOIN::destroy() on malformed subquery. That JOIN::destroy function closes and frees temporary tables. However, temporary fields of these tables may be listed in st_select_lex::group_list of outer query, and that st_select_lex may not cleanup them properly. So, after the JOIN::destroy call that st_select_lex::group_list may have Item_field objects with dangling pointers to freed temporary table Field objects. That caused a crash. mysql-test/r/subselect3.result: Added test case for bug #37362. mysql-test/t/subselect3.test: Added test case for bug #37362. sql/sql_select.cc: Bug #37362: Crash in do_field_eq The JOIN::destroy function has been modified to cleanup temporary table column items. --- mysql-test/r/subselect3.result | 19 +++++++++++++++++++ mysql-test/t/subselect3.test | 19 +++++++++++++++++++ sql/sql_select.cc | 8 ++++++++ 3 files changed, 46 insertions(+) diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 9a6f4436ff0..759c6689be8 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -849,4 +849,23 @@ ROW(1,2) = (SELECT 1, 1) ROW(1,2) IN (SELECT 1, 1) SELECT ROW(1,2) = (SELECT 1, 2), ROW(1,2) IN (SELECT 1, 2); ROW(1,2) = (SELECT 1, 2) ROW(1,2) IN (SELECT 1, 2) 1 1 +CREATE TABLE t1 (a INT, b INT, c INT); +INSERT INTO t1 VALUES (1,1,1), (1,1,1); +EXPLAIN EXTENDED +SELECT c FROM +( SELECT +(SELECT COUNT(a) FROM +(SELECT COUNT(b) FROM t1) AS x GROUP BY c +) FROM t1 GROUP BY b +) AS y; +ERROR 42S22: Unknown column 'c' in 'field list' +SHOW WARNINGS; +Level Code Message +Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2 +Note 1276 Field or reference 'test.t1.c' of SELECT #3 was resolved in SELECT #2 +Error 1054 Unknown column 'c' in 'field list' +Note 1003 select `c` AS `c` from (select (select count(`test`.`t1`.`a`) AS `COUNT(a)` from (select count(`test`.`t1`.`b`) AS `COUNT(b)` from `test`.`t1`) `x` group by `c`) AS `(SELECT COUNT(a) FROM +(SELECT COUNT(b) FROM t1) AS x GROUP BY c +)` from `test`.`t1` group by `test`.`t1`.`b`) `y` +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index 2d88d1660b0..6f08ebef86d 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -669,4 +669,23 @@ SELECT ROW(1,2) = (SELECT NULL, 1), ROW(1,2) IN (SELECT NULL, 1); SELECT ROW(1,2) = (SELECT 1, 1), ROW(1,2) IN (SELECT 1, 1); SELECT ROW(1,2) = (SELECT 1, 2), ROW(1,2) IN (SELECT 1, 2); +# +# Bug #37362 Crash in do_field_eq +# +CREATE TABLE t1 (a INT, b INT, c INT); +INSERT INTO t1 VALUES (1,1,1), (1,1,1); + +--error 1054 +EXPLAIN EXTENDED + SELECT c FROM + ( SELECT + (SELECT COUNT(a) FROM + (SELECT COUNT(b) FROM t1) AS x GROUP BY c + ) FROM t1 GROUP BY b + ) AS y; +SHOW WARNINGS; + +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index da3731865ba..9a457f2690d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2161,6 +2161,14 @@ JOIN::destroy() cond_equal= 0; cleanup(1); + /* Cleanup items referencing temporary table columns */ + if (!tmp_all_fields3.is_empty()) + { + List_iterator_fast it(tmp_all_fields3); + Item *item; + while ((item= it++)) + item->cleanup(); + } if (exec_tmp_table1) free_tmp_table(thd, exec_tmp_table1); if (exec_tmp_table2) From d64c0e16759e25285487c709dda72663d8b8cec9 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Fri, 1 May 2009 19:35:04 +0200 Subject: [PATCH 037/115] A few portability tweaks for Netware, SCO and QNX --- cmd-line-utils/libedit/readline/readline.h | 2 +- include/config-netware.h | 2 +- include/my_global.h | 69 +++++++++++----------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/cmd-line-utils/libedit/readline/readline.h b/cmd-line-utils/libedit/readline/readline.h index c77b080c439..0e300faed89 100644 --- a/cmd-line-utils/libedit/readline/readline.h +++ b/cmd-line-utils/libedit/readline/readline.h @@ -66,7 +66,7 @@ typedef KEYMAP_ENTRY *Keymap; #ifndef CTRL #include -#if !defined(__sun) && !defined(__hpux) && !defined(_AIX) +#if !defined(__sun) && !defined(__hpux) && !defined(_AIX) && !defined(__QNXNTO__) && !defined(__USLC__) #include #endif #ifndef CTRL diff --git a/include/config-netware.h b/include/config-netware.h index 9c99305789a..85a5ef86829 100644 --- a/include/config-netware.h +++ b/include/config-netware.h @@ -45,7 +45,7 @@ extern "C" { #undef HAVE_SYS_MMAN_H #undef HAVE_SYNCH_H #undef HAVE_MMAP -#undef HAVE_RINT +#undef HAVE_FESETROUND #define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1 #define HAVE_PTHREAD_SIGMASK 1 diff --git a/include/my_global.h b/include/my_global.h index f5a3016bb1e..06d5b0f94b4 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -486,40 +486,6 @@ typedef unsigned short ushort; #define test_all_bits(a,b) (((a) & (b)) == (b)) #define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1)) #define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) -#ifndef HAVE_RINT -/** - All integers up to this number can be represented exactly as double precision - values (DBL_MANT_DIG == 53 for IEEE 754 hardware). -*/ -#define MAX_EXACT_INTEGER ((1LL << DBL_MANT_DIG) - 1) - -/** - rint(3) implementation for platforms that do not have it. - Always rounds to the nearest integer with ties being rounded to the nearest - even integer to mimic glibc's rint() behavior in the "round-to-nearest" - FPU mode. Hardware-specific optimizations are possible (frndint on x86). - Unlike this implementation, hardware will also honor the FPU rounding mode. -*/ - -static inline double rint(double x) -{ - double f, i; - f = modf(x, &i); - /* - All doubles with absolute values > MAX_EXACT_INTEGER are even anyway, - no need to check it. - */ - if (x > 0.0) - i += (double) ((f > 0.5) || (f == 0.5 && - i <= (double) MAX_EXACT_INTEGER && - (longlong) i % 2)); - else - i -= (double) ((f < -0.5) || (f == -0.5 && - i >= (double) -MAX_EXACT_INTEGER && - (longlong) i % 2)); - return i; -} -#endif /* HAVE_RINT */ /* Define some general constants */ #ifndef TRUE @@ -1391,4 +1357,39 @@ do { doubleget_union _tmp; \ #define MY_INT64_NUM_DECIMAL_DIGITS 21 +#ifndef HAVE_RINT +/** + All integers up to this number can be represented exactly as double precision + values (DBL_MANT_DIG == 53 for IEEE 754 hardware). +*/ +#define MAX_EXACT_INTEGER ((1LL << DBL_MANT_DIG) - 1) + +/** + rint(3) implementation for platforms that do not have it. + Always rounds to the nearest integer with ties being rounded to the nearest + even integer to mimic glibc's rint() behavior in the "round-to-nearest" + FPU mode. Hardware-specific optimizations are possible (frndint on x86). + Unlike this implementation, hardware will also honor the FPU rounding mode. +*/ + +static inline double rint(double x) +{ + double f, i; + f = modf(x, &i); + /* + All doubles with absolute values > MAX_EXACT_INTEGER are even anyway, + no need to check it. + */ + if (x > 0.0) + i += (double) ((f > 0.5) || (f == 0.5 && + i <= (double) MAX_EXACT_INTEGER && + (longlong) i % 2)); + else + i -= (double) ((f < -0.5) || (f == -0.5 && + i >= (double) -MAX_EXACT_INTEGER && + (longlong) i % 2)); + return i; +} +#endif /* HAVE_RINT */ + #endif /* my_global_h */ From c5548ad7bdb8faa673c8455ebd4d98aad93b43eb Mon Sep 17 00:00:00 2001 From: Serge Kozlov Date: Sat, 2 May 2009 23:28:54 +0400 Subject: [PATCH 038/115] Bug#38077. 1. Replace waiting of SQL thread stop by waiting of SQL error on slave and stopped SQL thread. 2. Remove debug code because it already implemented in MTR2. --- mysql-test/suite/rpl/t/rpl_incident.test | 35 ++---------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_incident.test b/mysql-test/suite/rpl/t/rpl_incident.test index 38fcc116736..66893ebb93f 100644 --- a/mysql-test/suite/rpl/t/rpl_incident.test +++ b/mysql-test/suite/rpl/t/rpl_incident.test @@ -14,42 +14,13 @@ REPLACE INTO t1 VALUES (4); SELECT * FROM t1; connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# Wait until SQL thread stops with error LOST_EVENT on master +let $slave_sql_errno= 1590; +source include/wait_for_slave_sql_error.inc; # The 4 should not be inserted into the table, since the incident log # event should have stop the slave. --echo **** On Slave **** -#### BEGIN DEBUG INFO ADDED BY SVEN 2008-07-18 -- SEE BUG#38077 #### -let $tables= query_get_value(SHOW TABLES, Tables_in_test, 1); -if (`SELECT '$tables' != 't1'`) -{ - --echo **** TEST CASE BUG! PRINTING DEBUG INFO! **** - --echo **** Dear developer, if you see this in the output of a test - --echo **** case run, please add all the information below as a - --echo **** comment to BUG#38077. If it's a pushbuild failure, please - --echo **** include a link to the push page. - --echo **** Thank you! /Sven - SHOW BINLOG EVENTS; - --echo **** master binlog **** - --error 0,1 - --exec $MYSQL_BINLOG --hexdump $MYSQLTEST_VARDIR/log/master-bin.000001 - --echo **** slave binlog **** - --error 0,1 - --exec $MYSQL_BINLOG --hexdump $MYSQLTEST_VARDIR/log/slave-bin.000001 - --echo **** slave status **** - query_vertical SHOW SLAVE STATUS; - --echo **** slave's master status **** - SHOW MASTER STATUS; - --echo **** slave binlog events **** - --echo [on master] - connection master; - --echo **** master status **** - SHOW MASTER STATUS; - --echo **** master binlog events **** - SHOW BINLOG EVENTS; - exit; -} -#### END DEBUG INFO #### SELECT * FROM t1; --replace_result $MASTER_MYPORT MASTER_PORT From a83b1bdb951111df3c98c545443e8408974d7a3a Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 4 May 2009 12:59:10 +0300 Subject: [PATCH 039/115] removing the source of a warning in slave.cc:468 --- sql/slave.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index 9ba0788a5e4..a6264dfb0ac 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -465,8 +465,6 @@ terminate_slave_thread(THD *thd, volatile uint *slave_running, bool skip_lock) { - int error; - DBUG_ENTER("terminate_slave_thread"); if (!skip_lock) { From 3023bca11046e31cd431181c13c2b022bca66637 Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Mon, 4 May 2009 15:30:15 +0530 Subject: [PATCH 040/115] BUG#39802 On Windows, 32-bit time_t should be enforced A backport of fix for "BUG40092 - Storage engine API uses time_t datatype". Starting from MSVC C++ 2005 (v8), the default size of time_t is changed from 32-bit to 64-bit. As the result, the binaries built with pre-v8 MSVC C++ do not work with the binaries (storage engine plugins) built with v8 or after (server crashes). Fixed storage engine API to use datatype with known size (ulong) instead of time_t. sql/handler.h: Bug#39802 On Windows, 32-bit time_t should be enforced Change create_time, check_time, update_time in the ha_statistics and PARTITION_INFO structures to ulong. --- sql/handler.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index d43fc4725dd..5c7cfa4d58b 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -876,9 +876,9 @@ typedef struct { ulonglong delete_length; ha_rows records; ulong mean_rec_length; - time_t create_time; - time_t check_time; - time_t update_time; + ulong create_time; + ulong check_time; + ulong update_time; ulonglong check_sum; } PARTITION_INFO; @@ -1037,9 +1037,9 @@ public: ha_rows records; ha_rows deleted; /* Deleted records */ ulong mean_rec_length; /* physical reclength */ - time_t create_time; /* When table was created */ - time_t check_time; - time_t update_time; + ulong create_time; /* When table was created */ + ulong check_time; + ulong update_time; uint block_size; /* index block size */ ha_statistics(): From fdd5a63fe6d1e81fe80c9d2e610041a3b0bc171c Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Mon, 4 May 2009 14:45:36 +0200 Subject: [PATCH 041/115] Bug#44306: Assertion fail on duplicate key error in 'INSERT ... SELECT' statements The code that produces result rows expected that a duplicate row error could not occur in INSERT ... SELECT statements with unfulfilled WHERE conditions. This may happen, however, if the SELECT list contains only aggregate functions. Fixed by checking if an error occured before trying to send EOF to the client. mysql-test/r/insert_select.result: Bug#44306: Test result mysql-test/t/insert_select.test: Bug#44306: Test case sql/sql_select.cc: Bug#44306: Fix --- mysql-test/r/insert_select.result | 5 +++++ mysql-test/t/insert_select.test | 10 ++++++++++ sql/sql_select.cc | 6 ++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 780e91ea73f..2f2cc6334a9 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -765,6 +765,11 @@ f1 f2 2 2 10 10 DROP TABLE t1, t2; +CREATE TABLE t1 ( a INT KEY, b INT ); +INSERT INTO t1 VALUES ( 0, 1 ); +INSERT INTO t1 ( b ) SELECT MAX( b ) FROM t1 WHERE b = 2; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +DROP TABLE t1; SET SQL_MODE='STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; CREATE TABLE t1 (c VARCHAR(30), INDEX ix_c (c(10))); CREATE TABLE t2 (d VARCHAR(10)); diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 499db086877..f8023fcfc60 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -323,6 +323,16 @@ INSERT INTO t2 (f1, f2) SELECT * FROM t2; DROP TABLE t1, t2; +# +# Bug#44306: Assertion fail on duplicate key error in 'INSERT ... SELECT' +# statements +# +CREATE TABLE t1 ( a INT KEY, b INT ); +INSERT INTO t1 VALUES ( 0, 1 ); +--error ER_DUP_ENTRY +INSERT INTO t1 ( b ) SELECT MAX( b ) FROM t1 WHERE b = 2; +DROP TABLE t1; + # # Bug #26207: inserts don't work with shortened index # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 901e058d934..625608362a6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7084,15 +7084,17 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, if (!(result->send_fields(fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))) { + bool send_error= FALSE; if (send_row) { List_iterator_fast it(fields); Item *item; while ((item= it++)) item->no_rows_in_result(); - result->send_data(fields); + send_error= result->send_data(fields); } - result->send_eof(); // Should be safe + if (!send_error) + result->send_eof(); // Should be safe } /* Update results for FOUND_ROWS */ join->thd->limit_found_rows= join->thd->examined_row_count= 0; From ad7518418ca73f9ed25f5c4e45826d055d3ceac7 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 May 2009 22:33:23 +0200 Subject: [PATCH 042/115] bug#44166 removed few sprintf's --- sql/item.cc | 14 ++++++-------- sql/sql_table.cc | 2 +- sql/sql_update.cc | 6 +++--- sql/unireg.cc | 3 +-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index d1418b9a137..4d9dc50226f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3390,14 +3390,12 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, current->mark_as_dependent(last); if (thd->lex->describe & DESCRIBE_EXTENDED) { - char warn_buff[MYSQL_ERRMSG_SIZE]; - sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED), - db_name, (db_name[0] ? "." : ""), - table_name, (table_name [0] ? "." : ""), - resolved_item->field_name, - current->select_number, last->select_number); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_WARN_FIELD_RESOLVED, warn_buff); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_WARN_FIELD_RESOLVED, ER(ER_WARN_FIELD_RESOLVED), + db_name, (db_name[0] ? "." : ""), + table_name, (table_name [0] ? "." : ""), + resolved_item->field_name, + current->select_number, last->select_number); } } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 29d43155778..2744619e138 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3126,7 +3126,7 @@ static bool prepare_blob_field(THD *thd, Create_field *sql_field) } sql_field->sql_type= MYSQL_TYPE_BLOB; sql_field->flags|= BLOB_FLAG; - sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name, + my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_AUTO_CONVERT), sql_field->field_name, (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR", (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT"); push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b3bd5d0bc57..1a8c43f46aa 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -818,7 +818,7 @@ int mysql_update(THD *thd, if (error < 0) { char buff[STRING_BUFFER_USUAL_SIZE]; - sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, + my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, (ulong) thd->cuted_fields); thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; @@ -2066,8 +2066,8 @@ bool multi_update::send_eof() id= thd->arg_of_last_insert_id_function ? thd->first_successful_insert_id_in_prev_stmt : 0; - sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, - (ulong) thd->cuted_fields); + my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), + (ulong) found, (ulong) updated, (ulong) thd->cuted_fields); thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; ::my_ok(thd, (ulong) thd->row_count_func, id, buff); diff --git a/sql/unireg.cc b/sql/unireg.cc index 51293184ad8..68a352e4a44 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -37,8 +37,7 @@ static bool pack_header(uchar *forminfo,enum legacy_db_type table_type, List &create_fields, uint info_length, uint screens, uint table_options, ulong data_offset, handler *file); -static uint get_interval_id(uint *int_count,List &create_fields, - Create_field *last_field); +static uint get_interval_id(uint *,List &, Create_field *); static bool pack_fields(File file, List &create_fields, ulong data_offset); static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type, From 0df00705495937111ef20fa5050e90ca1e223ca3 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 5 May 2009 11:55:22 +0500 Subject: [PATCH 043/115] Bug#44352 UPPER/LOWER function doesn't work correctly on cp932 and sjis environment. Problem: case conversion erroneously changes the second bytes of multi-byte sequences because single-byte functions were called in a mistake. Fix: call multi-byte aware functions instead. --- mysql-test/r/ctype_cp932_binlog_stm.result | 8 ++++++++ mysql-test/r/ctype_sjis.result | 10 ++++++++++ mysql-test/t/ctype_cp932_binlog_stm.test | 6 ++++++ mysql-test/t/ctype_sjis.test | 10 ++++++++++ strings/ctype-cp932.c | 8 ++++---- strings/ctype-sjis.c | 8 ++++---- 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/ctype_cp932_binlog_stm.result b/mysql-test/r/ctype_cp932_binlog_stm.result index 0cd2d395ebc..2f67eb16b2e 100644 --- a/mysql-test/r/ctype_cp932_binlog_stm.result +++ b/mysql-test/r/ctype_cp932_binlog_stm.result @@ -46,4 +46,12 @@ master-bin.000001 1137 Query 1 1216 use `test`; DROP TABLE t4 End of 5.0 tests SHOW BINLOG EVENTS FROM 364; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error +Bug#44352 UPPER/LOWER function doesn't work correctly on cp932 and sjis environment. +CREATE TABLE t1 (a varchar(16)) character set cp932; +INSERT INTO t1 VALUES (0x8372835E),(0x8352835E); +SELECT hex(a), hex(lower(a)), hex(upper(a)) FROM t1 ORDER BY binary(a); +hex(a) hex(lower(a)) hex(upper(a)) +8352835E 8352835E 8352835E +8372835E 8372835E 8372835E +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/ctype_sjis.result b/mysql-test/r/ctype_sjis.result index 91d6ebd9795..1469e335f23 100644 --- a/mysql-test/r/ctype_sjis.result +++ b/mysql-test/r/ctype_sjis.result @@ -209,3 +209,13 @@ SET NAMES sjis; SELECT HEX('²“‘@Œ\') FROM DUAL; HEX('²“‘@Œ\') 8DB2939181408C5C +# Start of 5.1 tests +Bug#44352 UPPER/LOWER function doesn't work correctly on cp932 and sjis environment. +CREATE TABLE t1 (a varchar(16)) character set sjis; +INSERT INTO t1 VALUES (0x8372835E),(0x8352835E); +SELECT hex(a), hex(lower(a)), hex(upper(a)) FROM t1 ORDER BY binary(a); +hex(a) hex(lower(a)) hex(upper(a)) +8352835E 8352835E 8352835E +8372835E 8372835E 8372835E +DROP TABLE t1; +# End of 5.1 tests diff --git a/mysql-test/t/ctype_cp932_binlog_stm.test b/mysql-test/t/ctype_cp932_binlog_stm.test index 383009ae7c3..9e9716e5ddb 100644 --- a/mysql-test/t/ctype_cp932_binlog_stm.test +++ b/mysql-test/t/ctype_cp932_binlog_stm.test @@ -34,4 +34,10 @@ delimiter ;| --error 1220 SHOW BINLOG EVENTS FROM 364; +--echo Bug#44352 UPPER/LOWER function doesn't work correctly on cp932 and sjis environment. +CREATE TABLE t1 (a varchar(16)) character set cp932; +INSERT INTO t1 VALUES (0x8372835E),(0x8352835E); +SELECT hex(a), hex(lower(a)), hex(upper(a)) FROM t1 ORDER BY binary(a); +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/mysql-test/t/ctype_sjis.test b/mysql-test/t/ctype_sjis.test index 27cbdff451b..7de94e34dea 100644 --- a/mysql-test/t/ctype_sjis.test +++ b/mysql-test/t/ctype_sjis.test @@ -83,3 +83,13 @@ SET NAMES sjis; SELECT HEX('²“‘@Œ\') FROM DUAL; # End of 4.1 tests + +--echo # Start of 5.1 tests + +--echo Bug#44352 UPPER/LOWER function doesn't work correctly on cp932 and sjis environment. +CREATE TABLE t1 (a varchar(16)) character set sjis; +INSERT INTO t1 VALUES (0x8372835E),(0x8352835E); +SELECT hex(a), hex(lower(a)), hex(upper(a)) FROM t1 ORDER BY binary(a); +DROP TABLE t1; + +--echo # End of 5.1 tests diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index c1aba0b35c6..07191c436b7 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -5489,10 +5489,10 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_cp932, /* mb_wc */ my_wc_mb_cp932, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, + my_caseup_str_mb, + my_casedn_str_mb, + my_caseup_mb, + my_casedn_mb, my_snprintf_8bit, my_long10_to_str_8bit, my_longlong10_to_str_8bit, diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 3925b76869c..ac426e0d7b5 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4650,10 +4650,10 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_sjis, /* mb_wc */ my_wc_mb_sjis, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, + my_caseup_str_mb, + my_casedn_str_mb, + my_caseup_mb, + my_casedn_mb, my_snprintf_8bit, my_long10_to_str_8bit, my_longlong10_to_str_8bit, From ef65e32d70913dd57c206b29a1a6935aa23de210 Mon Sep 17 00:00:00 2001 From: "Bernt M. Johnsen" Date: Tue, 5 May 2009 11:07:11 +0200 Subject: [PATCH 044/115] Bug#23471 prepared for commit in 5.0 gca branch --- tests/mysql_client_test.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9e026a27b6d..9dfacb7436d 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -3971,6 +3971,10 @@ static void test_fetch_date() myheader("test_fetch_date"); + /* Will not work if sql_mode is NO_ZERO_DATE (implicit if TRADITIONAL) /*/ + rc= mysql_query(mysql, "SET SQL_MODE=''"); + myquery(rc); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result"); myquery(rc); @@ -4685,6 +4689,9 @@ static void test_stmt_close() /* set AUTOCOMMIT to ON*/ mysql_autocommit(lmysql, TRUE); + rc= mysql_query(lmysql, "SET SQL_MODE = ''"); + myquery(rc); + rc= mysql_query(lmysql, "DROP TABLE IF EXISTS test_stmt_close"); myquery(rc); @@ -11855,6 +11862,9 @@ static void test_bug6058() myheader("test_bug6058"); + rc= mysql_query(mysql, "SET SQL_MODE=''"); + myquery(rc); + stmt_text= "SELECT CAST('0000-00-00' AS DATE)"; rc= mysql_real_query(mysql, stmt_text, (uint) strlen(stmt_text)); @@ -13026,6 +13036,9 @@ static void test_bug8378() if (!opt_silent) fprintf(stdout, " OK"); + rc= mysql_query(lmysql, "SET SQL_MODE=''"); + myquery(rc); + len= mysql_real_escape_string(lmysql, out, TEST_BUG8378_IN, 4); /* No escaping should have actually happened. */ @@ -16056,6 +16069,11 @@ static void test_bug31669() rc= mysql_query(mysql, query); myquery(rc); + strxmov(query, "GRANT ALL PRIVILEGES ON *.* TO '", user, "'@'localhost' IDENTIFIED BY " + "'", buff, "' WITH GRANT OPTION", NullS); + rc= mysql_query(mysql, query); + myquery(rc); + rc= mysql_query(mysql, "FLUSH PRIVILEGES"); myquery(rc); @@ -16093,7 +16111,7 @@ static void test_bug31669() strxmov(query, "DELETE FROM mysql.user WHERE User='", user, "'", NullS); rc= mysql_query(mysql, query); myquery(rc); - DIE_UNLESS(mysql_affected_rows(mysql) == 1); + DIE_UNLESS(mysql_affected_rows(mysql) == 2); #endif DBUG_VOID_RETURN; From fdce101978cbf17481ad6b0b074776c62aee1d0b Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Tue, 5 May 2009 15:03:52 +0530 Subject: [PATCH 045/115] Bug#44232 Error msg should be improved when collation not supported. When a user selected an unsupported character set for an IBMDB2I table, error 2501 or 2511 may have been returned, giving the appearance of an internal programming error. This patch consolidates these errors into a single descriptive error message for the common case of an unsupported character set. The new error number is 2504 and indicates a user error. The errors 2501 and 2511 remain to indicate cases of internal programming errors. storage/ibmdb2i/db2i_charsetSupport.cc: Bug#44232 Error msg should be improved when collation not supported. consolidate errors 2501 and 2511 into a single descriptive error message for the common case of an unsupported character set. storage/ibmdb2i/db2i_conversion.cc: Bug#44232 Error msg should be improved when collation not supported. consolidate errors 2501 and 2511 into a single descriptive error message for the common case of an unsupported character set. storage/ibmdb2i/db2i_errors.cc: Bug#44232 Error msg should be improved when collation not supported. consolidate errors 2501 and 2511 into a single descriptive error message for the common case of an unsupported character set. storage/ibmdb2i/db2i_errors.h: Bug#44232 Error msg should be improved when collation not supported. consolidate errors 2501 and 2511 into a single descriptive error message for the common case of an unsupported character set. --- storage/ibmdb2i/db2i_charsetSupport.cc | 50 +++++++++++++++++--------- storage/ibmdb2i/db2i_conversion.cc | 9 ++++- storage/ibmdb2i/db2i_errors.cc | 2 +- storage/ibmdb2i/db2i_errors.h | 2 +- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/storage/ibmdb2i/db2i_charsetSupport.cc b/storage/ibmdb2i/db2i_charsetSupport.cc index 2609d42887e..559b526b7fd 100644 --- a/storage/ibmdb2i/db2i_charsetSupport.cc +++ b/storage/ibmdb2i/db2i_charsetSupport.cc @@ -268,8 +268,15 @@ static int32 getNewTextDesc(const int32 inType, RESULT_INT32); if (unlikely(arguments->base.result.s_int32.r_int32 < 0)) { - getErrTxt(DB2I_ERR_ILECALL,"QlgCvtTextDescToDesc",arguments->base.result.s_int32.r_int32); - DBUG_RETURN(DB2I_ERR_ILECALL); + if (arguments->base.result.s_int32.r_int32 == Qlg_InDescriptorNotFound) + { + DBUG_RETURN(DB2I_ERR_UNSUPP_CHARSET); + } + else + { + getErrTxt(DB2I_ERR_ILECALL,"QlgCvtTextDescToDesc",arguments->base.result.s_int32.r_int32); + DBUG_RETURN(DB2I_ERR_ILECALL); + } } // Store the conversion information into a cache entry @@ -428,8 +435,13 @@ int32 convertIANAToDb2Ccsid(const char* parmIANADesc, uint16* db2Ccsid) int aixEncodingScheme; int db2EncodingScheme; rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAS400CCSID, parmIANADesc, aixCcsidString); - if (rc != 0) + if (unlikely(rc)) + { + if (rc == DB2I_ERR_UNSUPP_CHARSET) + getErrTxt(DB2I_ERR_UNSUPP_CHARSET, parmIANADesc); + return rc; + } aixCcsid = atoi(aixCcsidString); rc = getEncodingScheme(aixCcsid, aixEncodingScheme); if (rc != 0) @@ -646,32 +658,38 @@ static int32 openNewConversion(enum_conversionDirection direction, there equivalent iconv descriptions. */ rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAix41, mysqlCSName, mysqlAix41Desc); - if (rc) + if (unlikely(rc)) + { + if (rc == DB2I_ERR_UNSUPP_CHARSET) + getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName); + DBUG_RETURN(rc); + } CHARSET_INFO *cs= &my_charset_bin; (uint)(cs->cset->long10_to_str)(cs,db2CcsidString,sizeof(db2CcsidString), 10, db2CCSID); rc = convertTextDesc(Qlg_TypeAS400CCSID, Qlg_TypeAix41, db2CcsidString, db2Aix41Desc); - if (rc) - DBUG_RETURN(rc); + if (unlikely(rc)) + { + if (rc == DB2I_ERR_UNSUPP_CHARSET) + getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName); + + DBUG_RETURN(rc); + } /* Call iconv to open the conversion. */ if (direction == toDB2) { newConversion = iconv_open(db2Aix41Desc, mysqlAix41Desc); - if (newConversion == (iconv_t) -1) - { - getErrTxt(DB2I_ERR_ICONV_OPEN, mysqlAix41Desc, db2Aix41Desc, errno); - DBUG_RETURN(DB2I_ERR_ICONV_OPEN); - } } else { newConversion = iconv_open(mysqlAix41Desc, db2Aix41Desc); - if (newConversion == (iconv_t) -1) - { - getErrTxt(DB2I_ERR_ICONV_OPEN, db2Aix41Desc, mysqlAix41Desc, errno); - DBUG_RETURN(DB2I_ERR_ICONV_OPEN); - } + } + + if (unlikely(newConversion == (iconv_t) -1)) + { + getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName); + DBUG_RETURN(DB2I_ERR_UNSUPP_CHARSET); } /* Insert the new conversion into the cache. */ diff --git a/storage/ibmdb2i/db2i_conversion.cc b/storage/ibmdb2i/db2i_conversion.cc index f746be6ab50..bdb8085d937 100644 --- a/storage/ibmdb2i/db2i_conversion.cc +++ b/storage/ibmdb2i/db2i_conversion.cc @@ -151,7 +151,7 @@ int ha_ibmdb2i::convertFieldChars(enum_conversionDirection direction, if (unlikely(conversion == (iconv_t)(-1))) { - return (DB2I_ERR_ICONV_OPEN); + return (DB2I_ERR_UNSUPP_CHARSET); } size_t initOLen= olen; @@ -670,6 +670,13 @@ int ha_ibmdb2i::getFieldTypeMapping(Field* field, if (rtnCode) return rtnCode; } + + // Check whether there is a character conversion available. + iconv_t temp; + int32 rc = getConversion(toDB2, fieldCharSet, db2Ccsid, temp); + if (unlikely(rc)) + return rc; + sprintf(stringBuildBuffer, " CCSID %d ", db2Ccsid); mapping.append(stringBuildBuffer); } diff --git a/storage/ibmdb2i/db2i_errors.cc b/storage/ibmdb2i/db2i_errors.cc index 43dd539447f..dd50e40e61b 100644 --- a/storage/ibmdb2i/db2i_errors.cc +++ b/storage/ibmdb2i/db2i_errors.cc @@ -52,7 +52,7 @@ static const char* engineErrors[MAX_MSGSTRING] = {"Error opening codeset conversion from %.64s to %.64s (errno = %d)"}, {"Invalid %-.10s name '%-.128s'"}, {"Unsupported move from '%-.128s' to '%-.128s' on RENAME TABLE statement"}, - {"Unsupported schema '%-.128s' specified on RENAME TABLE statement"}, + {"The %-.64s character set is not supported."}, {"Auto_increment is not allowed for a partitioned table"}, {"Character set conversion error due to unknown encoding scheme %d"}, {""}, diff --git a/storage/ibmdb2i/db2i_errors.h b/storage/ibmdb2i/db2i_errors.h index 0f6fbef33f6..b6dd314ef50 100644 --- a/storage/ibmdb2i/db2i_errors.h +++ b/storage/ibmdb2i/db2i_errors.h @@ -54,7 +54,7 @@ enum DB2I_errors DB2I_ERR_ICONV_OPEN, DB2I_ERR_INVALID_NAME, DB2I_ERR_RENAME_MOVE, - DB2I_ERR_RENAME_QTEMP, + DB2I_ERR_UNSUPP_CHARSET, DB2I_ERR_PART_AUTOINC, DB2I_ERR_UNKNOWN_ENCODING, DB2I_ERR_RESERVED, From 391364fac778621e626c9ffdf7653d2b61690ad3 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Tue, 5 May 2009 11:38:19 +0200 Subject: [PATCH 046/115] Bug#43580: Issue with Innodb on multi-table update Certain multi-updates gave different results on InnoDB from to MyISAM, due to on-the-fly updates being used on the former and the update order matters. Fixed by turning off on-the-fly updates when update order dependencies are present. mysql-test/r/innodb_mysql.result: Bug#43580: Test result. mysql-test/suite/rpl/r/rpl_slave_skip.result: Bug#43580: Changed test result. The InnoDB result is now what it would have been on MyISAM. mysql-test/t/innodb_mysql.test: Bug#43580: Test case. sql/sql_base.cc: Bug#43580: Added a word of caution about using tmp_set here. sql/sql_update.cc: Bug#43580: Fix. Calls to TABLE::mark_columns_needed_for_update() are moved from mysql_multi_update_prepare() and right before the decison to do on-the-fly updates to the place where we do (or don't do) on-the-fly updates. --- mysql-test/r/innodb_mysql.result | 27 ++++++++++++ mysql-test/suite/rpl/r/rpl_slave_skip.result | 6 +-- mysql-test/t/innodb_mysql.test | 27 ++++++++++++ sql/sql_base.cc | 7 +++ sql/sql_update.cc | 45 +++++++++++++++++--- 5 files changed, 104 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 3f830378afa..b9e236c0def 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2021,4 +2021,31 @@ DROP TABLE t4; DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; +CREATE TABLE t1 (a INT, b INT, KEY (a)) ENGINE = INNODB; +CREATE TABLE t2 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; +CREATE TABLE t3 (a INT, b INT KEY, KEY (a)) ENGINE = INNODB; +CREATE TABLE t4 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); +INSERT INTO t3 VALUES (1, 101), (2, 102), (3, 103), (4, 104), (5, 105), (6, 106); +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); +UPDATE t1, t2 SET t1.a = t1.a + 100, t2.b = t1.a + 10 +WHERE t1.a BETWEEN 2 AND 4 AND t2.a = t1.b; +SELECT * FROM t2; +a b +1 1 +2 12 +3 13 +4 14 +5 5 +UPDATE t3, t4 SET t3.a = t3.a + 100, t4.b = t3.a + 10 +WHERE t3.a BETWEEN 2 AND 4 AND t4.a = t3.b - 100; +SELECT * FROM t4; +a b +1 1 +2 12 +3 13 +4 14 +5 5 +DROP TABLE t1, t2, t3, t4; End of 5.1 tests diff --git a/mysql-test/suite/rpl/r/rpl_slave_skip.result b/mysql-test/suite/rpl/r/rpl_slave_skip.result index 747e8f235a8..93b3e124a01 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_skip.result +++ b/mysql-test/suite/rpl/r/rpl_slave_skip.result @@ -39,8 +39,8 @@ a b SELECT * FROM t2; c d 1 2 -2 16 -3 54 +2 8 +3 18 **** On Slave **** START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=762; SHOW SLAVE STATUS; @@ -50,7 +50,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1133 +Read_Master_Log_Pos 1115 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index ad9e726f5b4..1b2b861dffb 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -332,4 +332,31 @@ DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; +# +# Bug#43580: Issue with Innodb on multi-table update +# +CREATE TABLE t1 (a INT, b INT, KEY (a)) ENGINE = INNODB; +CREATE TABLE t2 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; + +CREATE TABLE t3 (a INT, b INT KEY, KEY (a)) ENGINE = INNODB; +CREATE TABLE t4 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; + +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); + +INSERT INTO t3 VALUES (1, 101), (2, 102), (3, 103), (4, 104), (5, 105), (6, 106); +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); + +UPDATE t1, t2 SET t1.a = t1.a + 100, t2.b = t1.a + 10 +WHERE t1.a BETWEEN 2 AND 4 AND t2.a = t1.b; +--sorted_result +SELECT * FROM t2; + +UPDATE t3, t4 SET t3.a = t3.a + 100, t4.b = t3.a + 10 +WHERE t3.a BETWEEN 2 AND 4 AND t4.a = t3.b - 100; +--sorted_result +SELECT * FROM t4; + +DROP TABLE t1, t2, t3, t4; + --echo End of 5.1 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0dc29f7e3c2..d4d813d0fbd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5585,6 +5585,13 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table) other_bitmap= table->read_set; } + /* + The test-and-set mechanism in the bitmap is not reliable during + multi-UPDATE statements under MARK_COLUMNS_READ mode + (thd->mark_used_columns == MARK_COLUMNS_READ), as this bitmap contains + only those columns that are used in the SET clause. I.e they are being + set here. See multi_update::prepare() + */ if (bitmap_fast_test_and_set(current_bitmap, field->field_index)) { if (thd->mark_used_columns == MARK_COLUMNS_WRITE) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b3bd5d0bc57..4b313badb6b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1031,7 +1031,6 @@ reopen_tables: DBUG_RETURN(TRUE); } - table->mark_columns_needed_for_update(); DBUG_PRINT("info",("setting table `%s` for update", tl->alias)); /* If table will be updated we should not downgrade lock for it and @@ -1274,13 +1273,41 @@ int multi_update::prepare(List ¬_used_values, DBUG_RETURN(1); } + /* + We gather the set of columns read during evaluation of SET expression in + TABLE::tmp_set by pointing TABLE::read_set to it and then restore it after + setup_fields(). + */ + for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf) + { + TABLE *table= table_ref->table; + if (tables_to_update & table->map) + { + DBUG_ASSERT(table->read_set == &table->def_read_set); + table->read_set= &table->tmp_set; + bitmap_clear_all(table->read_set); + } + } + /* We have to check values after setup_tables to get covering_keys right in reference tables */ - if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0)) - DBUG_RETURN(1); + int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0); + + for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf) + { + TABLE *table= table_ref->table; + if (tables_to_update & table->map) + { + table->read_set= &table->def_read_set; + bitmap_union(table->read_set, &table->tmp_set); + } + } + + if (error) + DBUG_RETURN(1); /* Save tables beeing updated in update_tables @@ -1375,6 +1402,8 @@ int multi_update::prepare(List ¬_used_values, a row in this table will never be read twice. This is true under the following conditions: + - No column is both written to and read in SET expressions. + - We are doing a table scan and the data is in a separate file (MyISAM) or if we don't update a clustered key. @@ -1389,6 +1418,9 @@ int multi_update::prepare(List ¬_used_values, WARNING This code is a bit dependent of how make_join_readinfo() works. + The field table->tmp_set is used for keeping track of which fields are + read during evaluation of the SET expression. See multi_update::prepare. + RETURN 0 Not safe to update 1 Safe to update @@ -1409,6 +1441,8 @@ static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab, case JT_REF_OR_NULL: return !is_key_used(table, join_tab->ref.key, table->write_set); case JT_ALL: + if (bitmap_is_overlapping(&table->tmp_set, table->write_set)) + return FALSE; /* If range search on index */ if (join_tab->quick) return !join_tab->quick->is_keys_used(table->write_set); @@ -1464,17 +1498,18 @@ multi_update::initialize_tables(JOIN *join) ORDER group; TMP_TABLE_PARAM *tmp_param; - table->mark_columns_needed_for_update(); if (ignore) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); if (table == main_table) // First table in join { if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables)) { - table_to_update= main_table; // Update table on the fly + table->mark_columns_needed_for_update(); + table_to_update= table; // Update table on the fly continue; } } + table->mark_columns_needed_for_update(); table->prepare_for_position(); /* From 84c5ba6ece069ec8874c0efec44cd2bd425bc534 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Tue, 5 May 2009 11:07:26 -0700 Subject: [PATCH 047/115] Fix incorrect filename in verbose output of innochecksum. (Bug #44484, patch contributed by Andrew Hutchings) --- extra/innochecksum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/innochecksum.c b/extra/innochecksum.c index 524637a1729..9bd4bfcc0cd 100644 --- a/extra/innochecksum.c +++ b/extra/innochecksum.c @@ -224,7 +224,7 @@ int main(int argc, char **argv) } else if (verbose) { - printf("file %s= %llu bytes (%lu pages)...\n", argv[1], size, pages); + printf("file %s = %llu bytes (%lu pages)...\n", argv[optind], size, pages); printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1)); } From 4822696ecb7302efc543e0be109f1c2a8f1bdf4e Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 5 May 2009 17:03:23 -0400 Subject: [PATCH 048/115] Pull 5.1 treatment of community features into 5.0. --- configure.in | 36 +++++++++++++++---- .../include/have_community_features.inc | 4 +++ mysql-test/include/have_profiling.inc | 4 +++ mysql-test/r/have_community_features.require | 2 ++ mysql-test/r/have_profiling.require | 2 ++ mysql-test/t/profiling.test | 2 ++ sql/mysql_priv.h | 2 ++ sql/mysqld.cc | 18 +++++++++- sql/set_var.cc | 4 ++- sql/sp_head.cc | 10 +++--- sql/sql_class.cc | 4 +-- sql/sql_class.h | 2 +- sql/sql_parse.cc | 14 ++++---- sql/sql_prepare.cc | 2 +- sql/sql_profile.cc | 4 +-- sql/sql_profile.h | 2 +- sql/sql_show.cc | 3 ++ 17 files changed, 88 insertions(+), 27 deletions(-) create mode 100644 mysql-test/include/have_community_features.inc create mode 100644 mysql-test/include/have_profiling.inc create mode 100644 mysql-test/r/have_community_features.require create mode 100644 mysql-test/r/have_profiling.require diff --git a/configure.in b/configure.in index afadd2e0c40..866f12c47a2 100644 --- a/configure.in +++ b/configure.in @@ -661,7 +661,6 @@ then fi fi - AC_ARG_WITH(server-suffix, [ --with-server-suffix Append value to the version string.], [ MYSQL_SERVER_SUFFIX=`echo "$withval" | sed -e 's/^\(...................................\)..*$/\1/'` ], @@ -724,17 +723,42 @@ else AC_MSG_RESULT([no]) fi +AC_MSG_CHECKING(whether features provided by the user community should be included.) +AC_ARG_ENABLE(community-features, + AC_HELP_STRING( + [--enable-community-features], + [Enable additional features provided by the user community.]), + [ ENABLE_COMMUNITY_FEATURES=$enableval ], + [ ENABLE_COMMUNITY_FEATURES=no ] + ) + +if test "$ENABLE_COMMUNITY_FEATURES" = "yes" +then + AC_DEFINE([COMMUNITY_SERVER], [1], + [Whether features provided by the user community should be included]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + # Add query profiler +AC_MSG_CHECKING(whether query profiling should be included) AC_ARG_ENABLE(profiling, - AS_HELP_STRING([--disable-profiling], [Build a version without query profiling code]), + AS_HELP_STRING([--enable-profiling], [Add query-profiling code.]), [ ENABLED_PROFILING=$enableval ], - [ ENABLED_PROFILING=yes ]) + [ ENABLED_PROFILING=no ]) if test "$ENABLED_PROFILING" = "yes" then - AC_DEFINE([ENABLED_PROFILING], [1], - [If SHOW PROFILE should be enabled]) - AC_MSG_RESULT([yes]) + if test "$ENABLE_COMMUNITY_FEATURES" = "yes"; + then + AC_DEFINE([ENABLED_PROFILING], [1], [If SHOW PROFILE should be enabled]) + AC_MSG_RESULT([yes]) + else + ENABLED_PROFILING="no" + AC_MSG_RESULT([no, overridden because community-features disabled]) + AC_MSG_ERROR([This is almost certainly wrong. Add --enable-community-features or remove --enable-profiling .]) + fi else AC_MSG_RESULT([no]) fi diff --git a/mysql-test/include/have_community_features.inc b/mysql-test/include/have_community_features.inc new file mode 100644 index 00000000000..66697d8dd00 --- /dev/null +++ b/mysql-test/include/have_community_features.inc @@ -0,0 +1,4 @@ +--require r/have_community_features.require +--disable_query_log +show variables like 'have_community_features'; +--enable_query_log diff --git a/mysql-test/include/have_profiling.inc b/mysql-test/include/have_profiling.inc new file mode 100644 index 00000000000..48f6668ff92 --- /dev/null +++ b/mysql-test/include/have_profiling.inc @@ -0,0 +1,4 @@ +--require r/have_profiling.require +--disable_query_log +show variables like 'have_profiling'; +--enable_query_log diff --git a/mysql-test/r/have_community_features.require b/mysql-test/r/have_community_features.require new file mode 100644 index 00000000000..9233bba91e1 --- /dev/null +++ b/mysql-test/r/have_community_features.require @@ -0,0 +1,2 @@ +Variable_name Value +have_community_features YES diff --git a/mysql-test/r/have_profiling.require b/mysql-test/r/have_profiling.require new file mode 100644 index 00000000000..54caeba1dae --- /dev/null +++ b/mysql-test/r/have_profiling.require @@ -0,0 +1,2 @@ +Variable_name Value +have_profiling YES diff --git a/mysql-test/t/profiling.test b/mysql-test/t/profiling.test index ffd38caf781..29b694fa0bd 100644 --- a/mysql-test/t/profiling.test +++ b/mysql-test/t/profiling.test @@ -1,3 +1,5 @@ +--source include/have_profiling.inc + # Verify that the protocol isn't violated if we ask for profiling info # before profiling has recorded anything. show profiles; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2e15883aeb4..261393353f8 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1479,6 +1479,8 @@ extern SHOW_COMP_OPTION have_query_cache; extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; extern SHOW_COMP_OPTION have_crypt; extern SHOW_COMP_OPTION have_compress; +extern SHOW_COMP_OPTION have_community_features; +extern SHOW_COMP_OPTION have_profiling; #ifndef __WIN__ extern pthread_t signal_thread; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 877312a9129..16353e6f0f3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -538,6 +538,8 @@ SHOW_COMP_OPTION have_isam; SHOW_COMP_OPTION have_raid, have_ssl, have_symlink, have_query_cache; SHOW_COMP_OPTION have_geometry, have_rtree_keys, have_dlopen; SHOW_COMP_OPTION have_crypt, have_compress; +SHOW_COMP_OPTION have_community_features; +SHOW_COMP_OPTION have_profiling; /* Thread specific variables */ @@ -5638,7 +5640,7 @@ Disable with --skip-ndbcluster (will save memory).", "Maximum time in seconds to wait for the port to become free. " "(Default: no wait)", (gptr*) &mysqld_port_timeout, (gptr*) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory", (gptr*) &global_system_variables.profiling_history_size, (gptr*) &max_system_variables.profiling_history_size, @@ -6685,7 +6687,9 @@ struct show_var_st status_vars[]= { {"Threads_created", (char*) &thread_created, SHOW_LONG_CONST}, {"Threads_running", (char*) &thread_running, SHOW_INT_CONST}, {"Uptime", (char*) 0, SHOW_STARTTIME}, +#ifdef COMMUNITY_SERVER {"Uptime_since_flush_status",(char*) 0, SHOW_FLUSHTIME}, +#endif {NullS, NullS, SHOW_LONG} }; @@ -6992,6 +6996,16 @@ static void mysql_init_variables(void) #if !defined(my_pthread_setprio) && !defined(HAVE_PTHREAD_SETSCHEDPARAM) opt_specialflag |= SPECIAL_NO_PRIOR; #endif +#ifdef ENABLED_PROFILING + have_profiling = SHOW_OPTION_YES; +#else + have_profiling = SHOW_OPTION_NO; +#endif +#ifdef COMMUNITY_SERVER + have_community_features = SHOW_OPTION_YES; +#else + have_community_features = SHOW_OPTION_NO; +#endif #if defined(__WIN__) || defined(__NETWARE__) /* Allow Win32 and NetWare users to move MySQL anywhere */ @@ -8016,7 +8030,9 @@ void refresh_status(THD *thd) /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters); +#ifdef COMMUNITY_SERVER flush_status_time= time((time_t*) 0); +#endif pthread_mutex_unlock(&LOCK_status); /* diff --git a/sql/set_var.cc b/sql/set_var.cc index 909496df045..dcc7a5a15d1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -564,7 +564,7 @@ static sys_var_thd_bit sys_unique_checks("unique_checks", 0, set_option_bit, OPTION_RELAXED_UNIQUE_CHECKS, 1); -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) static sys_var_thd_bit sys_profiling("profiling", NULL, set_option_bit, ulonglong(OPTION_PROFILING)); static sys_var_thd_ulong sys_profiling_history_size("profiling_history_size", @@ -899,6 +899,8 @@ struct show_var_st init_vars[]= { {"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE}, {"have_blackhole_engine", (char*) &have_blackhole_db, SHOW_HAVE}, {"have_compress", (char*) &have_compress, SHOW_HAVE}, + {"have_community_features", (char*) &have_community_features, SHOW_HAVE}, + {"have_profiling", (char*) &have_profiling, SHOW_HAVE}, {"have_crypt", (char*) &have_crypt, SHOW_HAVE}, {"have_csv", (char*) &have_csv_db, SHOW_HAVE}, {"have_dynamic_loading", (char*) &have_dlopen, SHOW_HAVE}, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f2b69ac09fd..dcb865744fd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1103,7 +1103,7 @@ sp_head::execute(THD *thd) */ thd->spcont->callers_arena= &backup_arena; -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) /* Discard the initial part of executing routines. */ thd->profiling.discard_current_query(); #endif @@ -1112,7 +1112,7 @@ sp_head::execute(THD *thd) sp_instr *i; uint hip; // Handler ip -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) /* Treat each "instr" of a routine as discrete unit that could be profiled. Profiling only records information for segments of code that set the @@ -1125,7 +1125,7 @@ sp_head::execute(THD *thd) i = get_instr(ip); // Returns NULL when we're done. if (i == NULL) { -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.discard_current_query(); #endif break; @@ -1209,7 +1209,7 @@ sp_head::execute(THD *thd) } } while (!err_status && !thd->killed); -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.finish_current_query(); thd->profiling.start_new_query("tail end of routine"); #endif @@ -2633,7 +2633,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) query= thd->query; query_length= thd->query_length; -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) /* This s-p instr is profilable and will be captured. */ thd->profiling.set_query_source(m_query.str, m_query.length); #endif diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8a0d84c6735..f2e04647452 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -173,7 +173,7 @@ const char *set_thd_proc_info(THD *thd, const char *info, { const char *old_info= thd->proc_info; DBUG_PRINT("proc_info", ("%s:%d %s", calling_file, calling_line, info)); -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.status_change(info, calling_function, calling_file, calling_line); #endif thd->proc_info= info; @@ -272,7 +272,7 @@ THD::THD() init(); /* Initialize sub structures */ init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) profiling.set_thd(this); #endif user_connect=(USER_CONN *)0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 58f7d050d64..82c464cb475 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1434,7 +1434,7 @@ public: List warn_list; uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; uint total_warn_count; -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) PROFILING profiling; #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a872585e704..fcb7047e998 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1355,7 +1355,7 @@ pthread_handler_t handle_bootstrap(void *arg) thd->db_length+1+QUERY_CACHE_FLAGS_SIZE); thd->query[length] = '\0'; DBUG_PRINT("query",("%-.4096s",thd->query)); -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.set_query_source(thd->query, length); #endif @@ -1594,7 +1594,7 @@ static bool do_command(THD *thd) net_new_transaction(net); packet_length= my_net_read(net); -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.start_new_query(); #endif if (packet_length == packet_error) @@ -1642,7 +1642,7 @@ static bool do_command(THD *thd) return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length)); out: -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.finish_current_query(); #endif DBUG_RETURN(return_value); @@ -1951,7 +1951,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_log.write(thd,command, format, thd->query_length, thd->query); DBUG_PRINT("query",("%-.4096s",thd->query)); -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.set_query_source(thd->query, thd->query_length); #endif @@ -1981,7 +1981,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, length--; } -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.finish_current_query(); thd->profiling.start_new_query("continuing"); thd->profiling.set_query_source(next_packet, length); @@ -2485,7 +2485,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, Mark this current profiling record to be discarded. We don't wish to have SHOW commands show up in profiling. */ -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.discard_current_query(); #endif break; @@ -2961,7 +2961,7 @@ mysql_execute_command(THD *thd) } case SQLCOM_SHOW_PROFILES: { -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.discard_current_query(); res= thd->profiling.show_profiles(); if (res) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c152bde1b92..a20f61436a7 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2283,7 +2283,7 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute"))) DBUG_VOID_RETURN; -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.set_query_source(stmt->query, stmt->query_length); #endif DBUG_PRINT("exec_query", ("%s", stmt->query)); diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 6ae70ab1d13..551a103da10 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -47,7 +47,7 @@ const char * const _unknown_func_ = ""; int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) { -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) return(thd->profiling.fill_statistics_info(thd, tables, cond)); #else my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILE", "enable-profiling"); @@ -129,7 +129,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) } -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) #define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec) #define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2))) diff --git a/sql/sql_profile.h b/sql/sql_profile.h index 022422fbb81..2483cb3cb6a 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -54,7 +54,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); #define PROFILE_ALL (~0) -#if defined(ENABLED_PROFILING) +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) #include "mysql_priv.h" #ifdef HAVE_SYS_RESOURCE_H diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 297061207cf..59679c96120 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1549,9 +1549,12 @@ static bool show_status_array(THD *thd, const char *wild, nr= (long) (thd->query_start() - server_start_time); end= int10_to_str(nr, buff, 10); break; +#ifdef COMMUNITY_SERVER case SHOW_FLUSHTIME: nr= (long) (thd->query_start() - flush_status_time); end= int10_to_str(nr, buff, 10); + break; +#endif case SHOW_QUERIES: end= int10_to_str((long) thd->query_id, buff, 10); break; From 609a794b15fe44408fa47582e798147d1ffe3463 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Wed, 6 May 2009 13:37:10 +0530 Subject: [PATCH 049/115] Bug #39918 memory (heap) engine crashing with b-tree index and DELETE with seg fault Multiple-table DELETE from a table joined to itself may cause server crash. This was originally discovered with MEMORY engine, but may affect other engines with different symptoms. The problem was that the server violated SE API by performing parallel table scan in one handler and removing records in another (delete on the fly optimization). mysql-test/r/heap_btree.result: Updated test result after adding new test for this bug. mysql-test/t/heap_btree.test: Updated test result after adding new test for the bug report. sql/sql_delete.cc: Updated to check if the files in delete list appears in join list and disable delete while scanning, if it appears. --- mysql-test/r/heap_btree.result | 7 +++++++ mysql-test/t/heap_btree.test | 8 ++++++++ sql/sql_delete.cc | 20 +++++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result index c20dfbe80d2..65ced2bd24e 100644 --- a/mysql-test/r/heap_btree.result +++ b/mysql-test/r/heap_btree.result @@ -336,4 +336,11 @@ a b NULL NULL NULL 1 drop table t1; +# +# bug#39918 - memory (heap) engine crashing while executing self join with delete +# +CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY; +INSERT INTO t1 VALUES(1),(1); +DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test index 76c319c0bc1..710c8411751 100644 --- a/mysql-test/t/heap_btree.test +++ b/mysql-test/t/heap_btree.test @@ -253,5 +253,13 @@ insert into t1 values (1, 1), (3, 3), (2, 2), (NULL, 1), (NULL, NULL), (0, 0); select * from t1 where a is null; drop table t1; +-- echo # +-- echo # bug#39918 - memory (heap) engine crashing while executing self join with delete +-- echo # + +CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY; +INSERT INTO t1 VALUES(1),(1); +DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a; +DROP TABLE t1; --echo End of 5.0 tests diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a757b7c28a5..5307a4426c5 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -503,6 +503,11 @@ int mysql_multi_delete_prepare(THD *thd) } } } + /* + Reset the exclude flag to false so it doesn't interfare + with further calls to unique_table + */ + lex->select_lex.exclude_from_table_unique_test= FALSE; DBUG_RETURN(FALSE); } @@ -538,11 +543,24 @@ multi_delete::initialize_tables(JOIN *join) DBUG_RETURN(1); table_map tables_to_delete_from=0; + delete_while_scanning= 1; for (walk= delete_tables; walk; walk= walk->next_local) + { tables_to_delete_from|= walk->table->map; + if (delete_while_scanning && + unique_table(thd, walk, join->tables_list, false)) + { + /* + If the table we are going to delete from appears + in join, we need to defer delete. So the delete + doesn't interfers with the scaning of results. + */ + delete_while_scanning= 0; + } + } + walk= delete_tables; - delete_while_scanning= 1; for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables; tab < end; tab++) From c0cd2742af13c90f117b563e368566ed489b1fca Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Thu, 7 May 2009 18:31:02 +0400 Subject: [PATCH 050/115] Bug #41943: mysqlbinlog.exe crashes if --hexdump option is used The --hexdump option crashed mysqlbinlog when used together with the --read-from-remote-server option due to use of uninitialized memory. Since Log_event::print_header() relies on temp_buf to be initialized when the --hexdump option is present, dump_remote_log_entries() was fixed to setup temp_buf to point to the start of a binlog event as done in dump_local_log_entries(). The root cause of this bug is identical to the one for bug #17654. The latter was fixed in 5.1 and up, so this patch is backport of the patches for bug #17654 to 5.0. Only 5.0 needs a changelog entry. client/mysqlbinlog.cc: Fixed dump_remote_log_entries() so that temp_buf is initialized as it may be used later by Log_event::print_header() if the --hexdump option is present. mysql-test/r/mysqlbinlog.result: Added a test case for bug #41943. mysql-test/t/mysqlbinlog.test: Added a test case for bug #41943. --- client/mysqlbinlog.cc | 14 ++++++++++++++ mysql-test/r/mysqlbinlog.result | 2 ++ mysql-test/t/mysqlbinlog.test | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index ed072902730..36b86ae7a96 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -626,6 +626,7 @@ Create_file event for file_id: %u\n",exv->file_id); glob_description_event= (Format_description_log_event*) ev; print_event_info->common_header_len= glob_description_event->common_header_len; ev->print(result_file, print_event_info); + ev->temp_buf= 0; /* We don't want this event to be deleted now, so let's hide it (I (Guilhem) should later see if this triggers a non-serious Valgrind @@ -668,8 +669,16 @@ Begin_load_query event for file_id: %u\n", exlq->file_id); end: rec_count++; + /* + Destroy the log_event object. If reading from a remote host, + set the temp_buf to NULL so that memory isn't freed twice. + */ if (ev) + { + if (remote_opt) + ev->temp_buf= 0; delete ev; + } DBUG_RETURN(0); } @@ -1151,6 +1160,11 @@ could be out of memory"); error= 1; goto err; } + /* + If reading from a remote host, ensure the temp_buf for the + Log_event class is pointing to the incoming stream. + */ + ev->register_temp_buf((char *) net->read_pos + 1); Log_event_type type= ev->get_type_code(); if (glob_description_event->binlog_version >= 3 || diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 23244d2b3c4..4cb8eb29f19 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -380,4 +380,6 @@ IS NOT NULL 1 *** Unsigned server_id 4294967295 is found: 1 *** SET @@global.server_id= 1; +RESET MASTER; +FLUSH LOGS; End of 5.0 tests diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 1ca07a40df1..dd45f499866 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -294,4 +294,14 @@ echo *** Unsigned server_id $s_id_max is found: $s_id_unsigned ***; eval SET @@global.server_id= $save_server_id; --remove_file $binlog_file +# +# Bug #41943: mysqlbinlog.exe crashes if --hexdump option is used +# + +RESET MASTER; +FLUSH LOGS; + +# We do not need the results, just make sure that mysqlbinlog does not crash +--exec $MYSQL_BINLOG --hexdump --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 >/dev/null + --echo End of 5.0 tests From 3fe1d299ec01e58ae5afc03dc269a70054ec8865 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 10:28:29 -0700 Subject: [PATCH 051/115] Fix support for -i (--ignore-spaces) in the mysql command line application, which didn't actually do anything. (Bug #39101) --- client/mysql.cc | 11 ++++++++--- mysql-test/r/mysql.result | 6 ++++++ mysql-test/t/mysql.test | 7 +++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 93aab390e5a..89f1f28bb1b 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -140,7 +140,7 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, tty_password= 0, opt_nobeep=0, opt_reconnect=1, default_charset_used= 0, opt_secure_auth= 0, default_pager_set= 0, opt_sigint_ignore= 0, - show_warnings= 0; + show_warnings= 0, ignore_spaces= 0; static volatile int executing_query= 0, interrupted_query= 0; static my_bool preserve_comments= 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; @@ -1350,8 +1350,9 @@ static struct my_option my_long_options[] = {"no-named-commands", 'g', "Named commands are disabled. Use \\* form only, or use named commands only in the beginning of a line ending with a semicolon (;) Since version 10.9 the client now starts with this option ENABLED by default! Disable with '-G'. Long format commands still work from the first line. WARNING: option deprecated; use --disable-named-commands instead.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"ignore-spaces", 'i', "Ignore space after function names.", 0, 0, 0, - GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"ignore-spaces", 'i', "Ignore space after function names.", + (gptr*) &ignore_spaces, (gptr*) &ignore_spaces, 0, GET_BOOL, NO_ARG, 0, 0, + 0, 0, 0, 0}, {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE.", (gptr*) &opt_local_infile, (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -1749,6 +1750,10 @@ static int get_options(int argc, char **argv) } if (tty_password) opt_password= get_tty_password(NullS); + + if (ignore_spaces) + connect_flag|= CLIENT_IGNORE_SPACE; + return(0); } diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 10537f6da16..5f315bca9c2 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -192,4 +192,10 @@ delimiter 1 1 1 +COUNT (*) +1 +COUNT (*) +1 +COUNT (*) +1 End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 12431e26596..0425b4b9022 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -341,4 +341,11 @@ EOF remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql; +# +# Bug #39101: client -i (--ignore-spaces) option does not seem to work +# +--exec $MYSQL -i -e "SELECT COUNT (*)" +--exec $MYSQL --ignore-spaces -e "SELECT COUNT (*)" +--exec $MYSQL -b -i -e "SELECT COUNT (*)" + --echo End of 5.0 tests From b78f9a8659adf3be4ecbad3db59a97deff4f2193 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 10:40:00 -0700 Subject: [PATCH 052/115] =?UTF-8?q?Add=20explanation=20of=20the=20possible?= =?UTF-8?q?=20-s=20values=20for=20mysqldumpslow.=20(Bug=20#35663,=20based?= =?UTF-8?q?=20on=20a=20contribution=20by=20Ask=20Bj=C3=B8rn=20Hansen)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/mysqldumpslow.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/mysqldumpslow.sh b/scripts/mysqldumpslow.sh index 1e942b035cb..8580b8e6203 100644 --- a/scripts/mysqldumpslow.sh +++ b/scripts/mysqldumpslow.sh @@ -163,7 +163,14 @@ Parse and summarize the MySQL slow query log. Options are -v verbose -d debug - -s ORDER what to sort by (al, at, ar, c, t, l, r), 'at' is default + -s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default + al: average lock time + ar: average rows sent + at: average query time + c: count + l: lock time + r: rows sent + t: query time -r reverse the sort order (largest last instead of first) -t NUM just show the top n queries -a don't abstract all numbers to N and strings to 'S' From 038be08a1b8f29479e6ff993328692d0875650c2 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 10:51:55 -0700 Subject: [PATCH 053/115] Various command-line utilities, including mysqlbinlog and mysqldump, don't handle the --skip-password option correctly. (Bug #28479) --- client/mysql_upgrade.c | 2 ++ client/mysqladmin.cc | 2 ++ client/mysqlbinlog.cc | 2 ++ client/mysqlcheck.c | 2 ++ client/mysqldump.c | 2 ++ client/mysqlimport.c | 2 ++ client/mysqlshow.c | 2 ++ client/mysqlslap.c | 2 ++ client/mysqltest.cc | 2 ++ 9 files changed, 18 insertions(+) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index c50f7e03c27..cbc60d8acad 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -231,6 +231,8 @@ get_one_option(int optid, const struct my_option *opt, break; case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password tty_password= 1; add_option= FALSE; if (argument) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index df0dc1e7049..94d3d92e03a 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -232,6 +232,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_count_iterations= 1; break; case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { char *start=argument; diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 1621db5ded8..2c2023ae129 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1226,6 +1226,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), one_database = 1; break; case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index d2edd084c57..1bdb28f5a11 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -286,6 +286,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), what_to_do= DO_UPGRADE; break; case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { char *start = argument; diff --git a/client/mysqldump.c b/client/mysqldump.c index 44106388d69..323376dd8bf 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -702,6 +702,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; #endif case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { char *start=argument; diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 09ba27b287a..ec418244f3d 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -221,6 +221,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; #endif case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { char *start=argument; diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 0e696aed211..e401d6cad8f 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -281,6 +281,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_verbose++; break; case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { char *start=argument; diff --git a/client/mysqlslap.c b/client/mysqlslap.c index b8515289df5..4cf8c7204ed 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -712,6 +712,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), verbose++; break; case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { char *start= argument; diff --git a/client/mysqltest.cc b/client/mysqltest.cc index fb6baa744b2..f29fd36aa27 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5803,6 +5803,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; } case 'p': + if (argument == disabled_my_option) + argument= (char*) ""; // Don't require password if (argument) { my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR)); From df3887f913fa22290e3c05074b7eab1473da1d61 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 11:17:07 -0700 Subject: [PATCH 054/115] The get_date() function in mysys interpreted the GETDATE_GMT option backwards, which resulted in the incorrect time being reported at the end of mysqldump. (Bug #44424, patch by Andrew Hutchings) --- mysys/mf_getdate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c index 1ced312848e..247172014d8 100644 --- a/mysys/mf_getdate.c +++ b/mysys/mf_getdate.c @@ -45,15 +45,15 @@ void get_date(register my_string to, int flag, time_t date) skr=date ? (time_t) date : time((time_t*) 0); #if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) if (flag & GETDATE_GMT) - localtime_r(&skr,&tm_tmp); - else gmtime_r(&skr,&tm_tmp); + else + localtime_r(&skr,&tm_tmp); start_time= &tm_tmp; #else if (flag & GETDATE_GMT) - start_time= localtime(&skr); - else start_time= gmtime(&skr); + else + start_time= localtime(&skr); #endif if (flag & GETDATE_SHORT_DATE) sprintf(to,"%02d%02d%02d", From fca0a61a1ac3de2f00f19fe40b365fff031fba6e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 May 2009 21:42:19 +0200 Subject: [PATCH 055/115] Raise version number after cloning 5.0.82 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index e4d7e0975d9..4d2b683b1e3 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.82) +AM_INIT_AUTOMAKE(mysql, 5.0.83) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=82 +NDB_VERSION_BUILD=83 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 9345dbba6fdb3ef21b72db03ce38ca832154c235 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 13:09:53 -0700 Subject: [PATCH 056/115] mysqladmin kill can't handle 64-bit thread IDs. (Bug #32457) --- client/mysqladmin.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 94d3d92e03a..9865b67bb3b 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -679,10 +679,16 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) pos=argv[1]; for (;;) { - if (mysql_kill(mysql,(ulong) atol(pos))) + /* We don't use mysql_kill(), since it only handles 32-bit IDs. */ + char buff[26], *out; /* "KILL " + max 20 digs + NUL */ + out= strxmov(buff, "KILL ", NullS); + ullstr(strtoull(pos, NULL, 0), out); + + if (mysql_query(mysql, buff)) { - my_printf_error(0, "kill failed on %ld; error: '%s'", error_flags, - atol(pos), mysql_error(mysql)); + /* out still points to just the number */ + my_printf_error(0, "kill failed on %s; error: '%s'", error_flags, + out, mysql_error(mysql)); error=1; } if (!(pos=strchr(pos,','))) From cc3f48b2e19fae758dfef659ea277cd564bec4ca Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 17:25:23 -0700 Subject: [PATCH 057/115] mysqld_safe could generate filenames with spaces and then didn't properly quote them in later use. (Bug #33685, based on a patch by Hartmut Holzgraefe) --- scripts/mysqld_safe.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 960c3e39bab..34dc019a82a 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -391,8 +391,8 @@ then fi # Change the err log to the right user, if it is in use if [ $want_syslog -eq 0 ]; then - touch $err_log - chown $user $err_log + touch "$err_log" + chown $user "$err_log" fi if test -n "$open_files" then @@ -509,9 +509,9 @@ fi # # If there exists an old pid file, check if the daemon is already running # Note: The switches to 'ps' may depend on your operating system -if test -f $pid_file +if test -f "$pid_file" then - PID=`cat $pid_file` + PID=`cat "$pid_file"` if @CHECK_PID@ then if @FIND_PROC@ @@ -520,8 +520,8 @@ then exit 1 fi fi - rm -f $pid_file - if test -f $pid_file + rm -f "$pid_file" + if test -f "$pid_file" then log_error "Fatal error: Can't remove the pid file: $pid_file @@ -563,11 +563,11 @@ test -n "$NOHUP_NICENESS" && cmd="$cmd < /dev/null" log_notice "Starting $MYSQLD daemon with databases from $DATADIR" while true do - rm -f $safe_mysql_unix_port $pid_file # Some extra safety + rm -f $safe_mysql_unix_port "$pid_file" # Some extra safety eval_log_error "$cmd" - if test ! -f $pid_file # This is removed if normal shutdown + if test ! -f "$pid_file" # This is removed if normal shutdown then break fi From 464252a25b87706a1c36306e1e4d13f738a5f71a Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 17:48:20 -0700 Subject: [PATCH 058/115] The mysql command-line client did not properly handle MYSQL_HISTFILE being set to an empty string, or to /dev/null, as we suggest and have suggested in the documentation. (Bug #34224) --- client/mysql.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index d29bd8571c9..8de3cfee041 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1183,7 +1183,12 @@ int main(int argc,char *argv[]) histfile= 0; } } - if (histfile) + + /* We used to suggest setting MYSQL_HISTFILE=/dev/null. */ + if (histfile && strncmp(histfile, "/dev/null", 10) == 0) + histfile= NULL; + + if (histfile && histfile[0]) { if (verbose) tee_fprintf(stdout, "Reading history-file %s\n",histfile); @@ -1218,7 +1223,8 @@ sig_handler mysql_end(int sig) { mysql_close(&mysql); #ifdef HAVE_READLINE - if (!status.batch && !quick && !opt_html && !opt_xml && histfile) + if (!status.batch && !quick && !opt_html && !opt_xml && + histfile && histfile[0]) { /* write-history */ if (verbose) From d0a1de80b41efa3cc5b58420905c721356eb6a52 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Thu, 7 May 2009 17:53:03 -0700 Subject: [PATCH 059/115] The arguments to use for ps on Mac OS X were mis-detected by the mysql_zap utility. (Bug #41883, patch by Nicklas Westerlund) --- scripts/mysql_zap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mysql_zap.sh b/scripts/mysql_zap.sh index 6c05afb772c..3bb92aaec2e 100644 --- a/scripts/mysql_zap.sh +++ b/scripts/mysql_zap.sh @@ -27,8 +27,8 @@ $opt_f= 0; $opt_t= 0; $opt_a = ""; -$BSD = -f '/vmunix' || $ENV{"OS"} eq "SunOS4" || $^O eq 'darwin'; -$LINUX = $^O eq 'linux'; +$BSD = -f '/vmunix' || $ENV{"OS"} eq "SunOS4"; +$LINUX = $^O eq 'linux' || $^O eq 'darwin'; $pscmd = $BSD ? "/bin/ps -auxww" : $LINUX ? "/bin/ps axuw" : "/bin/ps -ef"; open(TTYIN, " Date: Mon, 11 May 2009 13:32:38 +0200 Subject: [PATCH 060/115] Bug #44442: Incident events are silent in mysqlbinlog output In the output from mysqlbinlog, incident log events were represented as just a comment. Since the incident log event represents an incident that could cause the contents of the database to change without being logged to the binary log, it means that if the SQL is applied to a server, it could potentially lead to that the databases are out of sync. In order to handle that, this patch adds the statement "RELOAD DATABASE" to the SQL output for the incident log event. This will require a DBA to edit the file and handle the case as apropriate before applying the output to a server. mysql-test/suite/binlog/t/binlog_incident-master.opt: Options file to cause server to generate an incident log event when executing a REPLACE. mysql-test/suite/binlog/t/binlog_incident.test: Test to check that the incident log event is represented correctly in the output from mysqlbinlog. sql/log_event.cc: The incident log event now ouput a "RELOAD DATABASE" instead of just a comment. RELOAD DATABASE is not an existing command and will generate a syntax error. --- .../suite/binlog/r/binlog_incident.result | 12 +++++++++ .../suite/binlog/t/binlog_incident-master.opt | 1 + .../suite/binlog/t/binlog_incident.test | 27 +++++++++++++++++++ sql/log_event.cc | 2 +- 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/binlog/r/binlog_incident.result create mode 100644 mysql-test/suite/binlog/t/binlog_incident-master.opt create mode 100644 mysql-test/suite/binlog/t/binlog_incident.test diff --git a/mysql-test/suite/binlog/r/binlog_incident.result b/mysql-test/suite/binlog/r/binlog_incident.result new file mode 100644 index 00000000000..d8b0357b8c4 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_incident.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1; +a +1 +2 +3 +REPLACE INTO t1 VALUES (4); +DROP TABLE t1; +FLUSH LOGS; +Contain RELOAD DATABASE +1 diff --git a/mysql-test/suite/binlog/t/binlog_incident-master.opt b/mysql-test/suite/binlog/t/binlog_incident-master.opt new file mode 100644 index 00000000000..57ce0081ae5 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_incident-master.opt @@ -0,0 +1 @@ +--loose-debug=+d,incident_database_resync_on_replace \ No newline at end of file diff --git a/mysql-test/suite/binlog/t/binlog_incident.test b/mysql-test/suite/binlog/t/binlog_incident.test new file mode 100644 index 00000000000..208c7f24df2 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_incident.test @@ -0,0 +1,27 @@ +# The purpose of this test is to provide a reference for how the +# incident log event is represented in the output from the mysqlbinlog +# program. + +source include/have_log_bin.inc; +source include/have_debug.inc; + +let $MYSQLD_DATADIR= `select @@datadir`; + +CREATE TABLE t1 (a INT); + +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1; + +# This will generate an incident log event and store it in the binary +# log before the replace statement. +REPLACE INTO t1 VALUES (4); + +DROP TABLE t1; +FLUSH LOGS; + +exec $MYSQL_BINLOG --start-position=106 $MYSQLD_DATADIR/master-bin.000001 >$MYSQLTEST_VARDIR/tmp/binlog_incident-bug44442.sql; +--disable_query_log +eval SELECT cont LIKE '%RELOAD DATABASE; # Shall generate syntax error%' AS `Contain RELOAD DATABASE` FROM (SELECT load_file('$MYSQLTEST_VARDIR/tmp/binlog_incident-bug44442.sql') AS cont) AS tbl; +--enable_query_log + +remove_file $MYSQLTEST_VARDIR/tmp/binlog_incident-bug44442.sql; \ No newline at end of file diff --git a/sql/log_event.cc b/sql/log_event.cc index a10a36f3b43..cc144691fe1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -9311,7 +9311,7 @@ Incident_log_event::print(FILE *file, Write_on_release_cache cache(&print_event_info->head_cache, file); print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\n# Incident: %s", description()); + my_b_printf(&cache, "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n", description()); } #endif From 3593b73eb1f2f4d4e182b8469310faa0152cf06b Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 11 May 2009 10:00:03 -0400 Subject: [PATCH 061/115] Fix improperly-protected variable definition and use. Also, add CPP so Windows works properly for profiling. Community-server functionality is required. --- include/config-win.h | 1 + sql/set_var.cc | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/config-win.h b/include/config-win.h index 39affd3b8e9..b9519e0f2a9 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -208,6 +208,7 @@ typedef uint rf_SetTimer; /* If query profiling should be enabled by default */ #define ENABLED_PROFILING 1 +#define COMMUNITY_SERVER 1 /* Convert some simple functions to Posix */ diff --git a/sql/set_var.cc b/sql/set_var.cc index 2cdd306d542..7a85c1c0fa3 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -736,7 +736,7 @@ sys_var *sys_variables[]= &sys_optimizer_prune_level, &sys_optimizer_search_depth, &sys_preload_buff_size, -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) &sys_profiling, &sys_profiling_history_size, #endif @@ -1060,7 +1060,7 @@ struct show_var_st init_vars[]= { {sys_plugin_dir.name, (char*) &sys_plugin_dir, SHOW_SYS}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, -#ifdef ENABLED_PROFILING +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) {sys_profiling.name, (char*) &sys_profiling, SHOW_SYS}, {sys_profiling_history_size.name, (char*) &sys_profiling_history_size, SHOW_SYS}, #endif From d37aa505578cd66a79d89537fbc1bb39554f2ff2 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 11 May 2009 20:54:00 -0300 Subject: [PATCH 062/115] Bug#44664: valgrind warning for COMMIT_AND_CHAIN and ROLLBACK_AND_CHAIN The problem is that the internal variable used to specify a transaction with consistent read was being used outside the processing context of a START TRANSACTION WITH CONSISTENT SNAPSHOT statement. The practical consequence was that a consistent snapshot specification could leak to unrelated transactions on the same session. The solution is to ensure a consistent snapshot clause is only relied upon for the START TRANSACTION statement. This is already fixed in a similar way on 6.0. mysql-test/r/consistent_snapshot.result: Add test case result for Bug#44664 mysql-test/t/consistent_snapshot.test: Add test case for Bug#44664 sql/sql_parse.cc: The WITH CONSISTENT SNAPSHOT clause is only valid for the START TRANSACTION statement. --- mysql-test/r/consistent_snapshot.result | 19 ++++++++++++++++ mysql-test/t/consistent_snapshot.test | 30 ++++++++++++++++++++----- sql/sql_parse.cc | 7 ++++-- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/consistent_snapshot.result b/mysql-test/r/consistent_snapshot.result index 694c996a58e..3a0227b1a1a 100644 --- a/mysql-test/r/consistent_snapshot.result +++ b/mysql-test/r/consistent_snapshot.result @@ -1,6 +1,9 @@ DROP TABLE IF EXISTS t1; # Establish connection con1 (user=root) # Establish connection con2 (user=root) +### Test 1: +### - While a consistent snapshot transaction is executed, +### no external inserts should be visible to the transaction. # Switch to connection con1 CREATE TABLE t1 (a INT) ENGINE=innodb; START TRANSACTION WITH CONSISTENT SNAPSHOT; @@ -10,6 +13,9 @@ INSERT INTO t1 VALUES(1); SELECT * FROM t1; a COMMIT; +### Test 2: +### - For any non-consistent snapshot transaction, external +### committed inserts should be visible to the transaction. DELETE FROM t1; START TRANSACTION; # Switch to connection con2 @@ -19,5 +25,18 @@ SELECT * FROM t1; a 1 COMMIT; +### Test 3: +### - Bug#44664: valgrind warning for COMMIT_AND_CHAIN and ROLLBACK_AND_CHAIN +### Chaining a transaction does not retain consistency level. +START TRANSACTION WITH CONSISTENT SNAPSHOT; +DELETE FROM t1; +COMMIT WORK AND CHAIN; +# Switch to connection con2 +INSERT INTO t1 VALUES(1); +# Switch to connection con1 +SELECT * FROM t1; +a +1 +COMMIT; # Switch to connection default + close connections con1 and con2 DROP TABLE t1; diff --git a/mysql-test/t/consistent_snapshot.test b/mysql-test/t/consistent_snapshot.test index 82edf2e22b2..fb1f3bc007c 100644 --- a/mysql-test/t/consistent_snapshot.test +++ b/mysql-test/t/consistent_snapshot.test @@ -12,9 +12,9 @@ connect (con1,localhost,root,,); --echo # Establish connection con2 (user=root) connect (con2,localhost,root,,); -### Test 1: -### - While a consistent snapshot transaction is executed, -### no external inserts should be visible to the transaction. +--echo ### Test 1: +--echo ### - While a consistent snapshot transaction is executed, +--echo ### no external inserts should be visible to the transaction. --echo # Switch to connection con1 connection con1; @@ -31,9 +31,9 @@ SELECT * FROM t1; # if consistent snapshot was set as expected, we # should see nothing. COMMIT; -### Test 2: -### - For any non-consistent snapshot transaction, external -### committed inserts should be visible to the transaction. +--echo ### Test 2: +--echo ### - For any non-consistent snapshot transaction, external +--echo ### committed inserts should be visible to the transaction. DELETE FROM t1; START TRANSACTION; # Now we omit WITH CONSISTENT SNAPSHOT @@ -48,6 +48,24 @@ SELECT * FROM t1; # if consistent snapshot was not set, as expected, we # should see 1. COMMIT; +--echo ### Test 3: +--echo ### - Bug#44664: valgrind warning for COMMIT_AND_CHAIN and ROLLBACK_AND_CHAIN +--echo ### Chaining a transaction does not retain consistency level. + +START TRANSACTION WITH CONSISTENT SNAPSHOT; +DELETE FROM t1; +COMMIT WORK AND CHAIN; + +--echo # Switch to connection con2 +connection con2; +INSERT INTO t1 VALUES(1); + +--echo # Switch to connection con1 +connection con1; +SELECT * FROM t1; # if consistent snapshot was not set, as expected, we +# should see 1. +COMMIT; + --echo # Switch to connection default + close connections con1 and con2 connection default; disconnect con1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6dbe4a4fd8d..7bfac84c0e6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -198,8 +198,6 @@ bool begin_trans(THD *thd) LEX *lex= thd->lex; thd->options|= OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; - if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) - error= ha_start_consistent_snapshot(thd); } return error; } @@ -4027,6 +4025,11 @@ end_with_restore_list: } if (begin_trans(thd)) goto error; + if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) + { + if (ha_start_consistent_snapshot(thd)) + goto error; + } my_ok(thd); break; case SQLCOM_COMMIT: From 8b9084eff4a7142192bb1ff82c2e982ed546a78c Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 12 May 2009 13:18:27 +0500 Subject: [PATCH 063/115] Fix for bug#44774: load_file function produces valgrind warnings Problem: using LOAD_FILE() in some cases we pass a file name string without a trailing '\0' to fn_format() which relies on that however. That may lead to valgrind warnings. Fix: add a trailing '\0' to the file name passed to fn_format(). mysql-test/r/func_str.result: Fix for bug#44774: load_file function produces valgrind warnings - test result. mysql-test/t/func_str.test: Fix for bug#44774: load_file function produces valgrind warnings - test case. sql/item_strfunc.cc: Fix for bug#44774: load_file function produces valgrind warnings - passing a file name to fn_format(), file_name->c_ptr() replaced with file_name->c_ptr_safe() to ensure we have a trailing '\0'. --- mysql-test/r/func_str.result | 9 +++++++++ mysql-test/t/func_str.test | 10 ++++++++++ sql/item_strfunc.cc | 4 ++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 1d7395ae14d..75f8983e838 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2187,4 +2187,13 @@ SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i F h i 31.12.2008 AAAAAA, aaaaaa DROP TABLE t1; +# +# BUG#44774: load_file function produces valgrind warnings +# +CREATE TABLE t1 (a TINYBLOB); +INSERT INTO t1 VALUES ('aaaaaaaa'); +SELECT LOAD_FILE(a) FROM t1; +LOAD_FILE(a) +NULL +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 389538c4cc0..4b0f91e4408 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1168,4 +1168,14 @@ INSERT INTO t1 VALUES ('2008-12-31','aaaaaa'); SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i FROM t1; DROP TABLE t1; + +--echo # +--echo # BUG#44774: load_file function produces valgrind warnings +--echo # +CREATE TABLE t1 (a TINYBLOB); +INSERT INTO t1 VALUES ('aaaaaaaa'); +SELECT LOAD_FILE(a) FROM t1; +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 4640929b2bf..bc2dcb9c61b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2832,7 +2832,7 @@ String *Item_load_file::val_str(String *str) ) goto err; - (void) fn_format(path, file_name->c_ptr(), mysql_real_data_home, "", + (void) fn_format(path, file_name->c_ptr_safe(), mysql_real_data_home, "", MY_RELATIVE_PATH | MY_UNPACK_FILENAME); /* Read only allowed from within dir specified by secure_file_priv */ @@ -2858,7 +2858,7 @@ String *Item_load_file::val_str(String *str) } if (tmp_value.alloc(stat_info.st_size)) goto err; - if ((file = my_open(file_name->c_ptr(), O_RDONLY, MYF(0))) < 0) + if ((file = my_open(file_name->ptr(), O_RDONLY, MYF(0))) < 0) goto err; if (my_read(file, (byte*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP))) { From 60a2bbb8ddc1c3fe8ef3814794838c2ca17f2193 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Tue, 12 May 2009 12:53:46 +0100 Subject: [PATCH 064/115] BUG#42749: infinite loop writing to row based binlog - processlist shows "freeing items" The calculation of the table map log event in the event constructor was one byte shorter than what would be actually written. This would lead to a mismatch between the number of bytes written and the event end_log_pos, causing bad event alignment in the binlog (corrupted binlog) or in the transaction cache while fixing positions (MYSQL_BIN_LOG::write_cache). This could lead to impossible to read binlog or even infinite loops in MYSQL_BIN_LOG::write_cache. This patch addresses this issue by correcting the expected event length in the Table_map_log_event constructor, when the field metadata size exceeds 255. sql/log_event.cc: Added the extra byte as net_store_length imposes. --- .../suite/binlog/r/binlog_tbl_metadata.result | 156 ++++++++++++++ .../suite/binlog/t/binlog_tbl_metadata.test | 199 ++++++++++++++++++ sql/log_event.cc | 5 +- 3 files changed, 358 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/binlog/r/binlog_tbl_metadata.result create mode 100644 mysql-test/suite/binlog/t/binlog_tbl_metadata.test diff --git a/mysql-test/suite/binlog/r/binlog_tbl_metadata.result b/mysql-test/suite/binlog/r/binlog_tbl_metadata.result new file mode 100644 index 00000000000..a2f185edc85 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_tbl_metadata.result @@ -0,0 +1,156 @@ +RESET MASTER; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( +`c1` int(11) NOT NULL AUTO_INCREMENT, +`c2` varchar(30) NOT NULL, +`c3` varchar(30) DEFAULT NULL, +`c4` varchar(30) DEFAULT NULL, +`c5` varchar(30) DEFAULT NULL, +`c6` varchar(30) DEFAULT NULL, +`c7` varchar(30) DEFAULT NULL, +`c8` varchar(30) DEFAULT NULL, +`c9` varchar(30) DEFAULT NULL, +`c10` varchar(30) DEFAULT NULL, +`c11` varchar(30) DEFAULT NULL, +`c12` varchar(30) DEFAULT NULL, +`c13` varchar(30) DEFAULT NULL, +`c14` varchar(30) DEFAULT NULL, +`c15` varchar(30) DEFAULT NULL, +`c16` varchar(30) DEFAULT NULL, +`c17` varchar(30) DEFAULT NULL, +`c18` varchar(30) DEFAULT NULL, +`c19` varchar(30) DEFAULT NULL, +`c20` varchar(30) DEFAULT NULL, +`c21` varchar(30) DEFAULT NULL, +`c22` varchar(30) DEFAULT NULL, +`c23` varchar(30) DEFAULT NULL, +`c24` varchar(30) DEFAULT NULL, +`c25` varchar(30) DEFAULT NULL, +`c26` varchar(30) DEFAULT NULL, +`c27` varchar(30) DEFAULT NULL, +`c28` varchar(30) DEFAULT NULL, +`c29` varchar(30) DEFAULT NULL, +`c30` varchar(30) DEFAULT NULL, +`c31` varchar(30) DEFAULT NULL, +`c32` varchar(30) DEFAULT NULL, +`c33` varchar(30) DEFAULT NULL, +`c34` varchar(30) DEFAULT NULL, +`c35` varchar(30) DEFAULT NULL, +`c36` varchar(30) DEFAULT NULL, +`c37` varchar(30) DEFAULT NULL, +`c38` varchar(30) DEFAULT NULL, +`c39` varchar(30) DEFAULT NULL, +`c40` varchar(30) DEFAULT NULL, +`c41` varchar(30) DEFAULT NULL, +`c42` varchar(30) DEFAULT NULL, +`c43` varchar(30) DEFAULT NULL, +`c44` varchar(30) DEFAULT NULL, +`c45` varchar(30) DEFAULT NULL, +`c46` varchar(30) DEFAULT NULL, +`c47` varchar(30) DEFAULT NULL, +`c48` varchar(30) DEFAULT NULL, +`c49` varchar(30) DEFAULT NULL, +`c50` varchar(30) DEFAULT NULL, +`c51` varchar(30) DEFAULT NULL, +`c52` varchar(30) DEFAULT NULL, +`c53` varchar(30) DEFAULT NULL, +`c54` varchar(30) DEFAULT NULL, +`c55` varchar(30) DEFAULT NULL, +`c56` varchar(30) DEFAULT NULL, +`c57` varchar(30) DEFAULT NULL, +`c58` varchar(30) DEFAULT NULL, +`c59` varchar(30) DEFAULT NULL, +`c60` varchar(30) DEFAULT NULL, +`c61` varchar(30) DEFAULT NULL, +`c62` varchar(30) DEFAULT NULL, +`c63` varchar(30) DEFAULT NULL, +`c64` varchar(30) DEFAULT NULL, +`c65` varchar(30) DEFAULT NULL, +`c66` varchar(30) DEFAULT NULL, +`c67` varchar(30) DEFAULT NULL, +`c68` varchar(30) DEFAULT NULL, +`c69` varchar(30) DEFAULT NULL, +`c70` varchar(30) DEFAULT NULL, +`c71` varchar(30) DEFAULT NULL, +`c72` varchar(30) DEFAULT NULL, +`c73` varchar(30) DEFAULT NULL, +`c74` varchar(30) DEFAULT NULL, +`c75` varchar(30) DEFAULT NULL, +`c76` varchar(30) DEFAULT NULL, +`c77` varchar(30) DEFAULT NULL, +`c78` varchar(30) DEFAULT NULL, +`c79` varchar(30) DEFAULT NULL, +`c80` varchar(30) DEFAULT NULL, +`c81` varchar(30) DEFAULT NULL, +`c82` varchar(30) DEFAULT NULL, +`c83` varchar(30) DEFAULT NULL, +`c84` varchar(30) DEFAULT NULL, +`c85` varchar(30) DEFAULT NULL, +`c86` varchar(30) DEFAULT NULL, +`c87` varchar(30) DEFAULT NULL, +`c88` varchar(30) DEFAULT NULL, +`c89` varchar(30) DEFAULT NULL, +`c90` varchar(30) DEFAULT NULL, +`c91` varchar(30) DEFAULT NULL, +`c92` varchar(30) DEFAULT NULL, +`c93` varchar(30) DEFAULT NULL, +`c94` varchar(30) DEFAULT NULL, +`c95` varchar(30) DEFAULT NULL, +`c96` varchar(30) DEFAULT NULL, +`c97` varchar(30) DEFAULT NULL, +`c98` varchar(30) DEFAULT NULL, +`c99` varchar(30) DEFAULT NULL, +`c100` varchar(30) DEFAULT NULL, +`c101` varchar(30) DEFAULT NULL, +`c102` varchar(30) DEFAULT NULL, +`c103` varchar(30) DEFAULT NULL, +`c104` varchar(30) DEFAULT NULL, +`c105` varchar(30) DEFAULT NULL, +`c106` varchar(30) DEFAULT NULL, +`c107` varchar(30) DEFAULT NULL, +`c108` varchar(30) DEFAULT NULL, +`c109` varchar(30) DEFAULT NULL, +`c110` varchar(30) DEFAULT NULL, +`c111` varchar(30) DEFAULT NULL, +`c112` varchar(30) DEFAULT NULL, +`c113` varchar(30) DEFAULT NULL, +`c114` varchar(30) DEFAULT NULL, +`c115` varchar(30) DEFAULT NULL, +`c116` varchar(30) DEFAULT NULL, +`c117` varchar(30) DEFAULT NULL, +`c118` varchar(30) DEFAULT NULL, +`c119` varchar(30) DEFAULT NULL, +`c120` varchar(30) DEFAULT NULL, +`c121` varchar(30) DEFAULT NULL, +`c122` varchar(30) DEFAULT NULL, +`c123` varchar(30) DEFAULT NULL, +`c124` varchar(30) DEFAULT NULL, +`c125` varchar(30) DEFAULT NULL, +`c126` varchar(30) DEFAULT NULL, +`c127` varchar(30) DEFAULT NULL, +`c128` varchar(30) DEFAULT NULL, +`c129` varchar(30) DEFAULT NULL, +`c130` varchar(30) DEFAULT NULL, +`c131` varchar(30) DEFAULT NULL, +`c132` varchar(30) DEFAULT NULL, +`c133` varchar(30) DEFAULT NULL, +`c134` varchar(30) DEFAULT NULL, +`c135` varchar(30) DEFAULT NULL, +`c136` varchar(30) DEFAULT NULL, +`c137` varchar(30) DEFAULT NULL, +`c138` varchar(30) DEFAULT NULL, +`c139` varchar(30) DEFAULT NULL, +`c140` varchar(30) DEFAULT NULL, +`c141` varchar(30) DEFAULT NULL, +`c142` varchar(30) DEFAULT NULL, +`c143` varchar(30) DEFAULT NULL, +`c144` varchar(30) DEFAULT NULL, +`c145` varchar(30) DEFAULT NULL, +`c146` varchar(30) DEFAULT NULL, +PRIMARY KEY (`c1`) +) ENGINE=InnoDB; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); +DROP TABLE `t1`; +FLUSH LOGS; +=== Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. diff --git a/mysql-test/suite/binlog/t/binlog_tbl_metadata.test b/mysql-test/suite/binlog/t/binlog_tbl_metadata.test new file mode 100644 index 00000000000..5e847ab5fbd --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_tbl_metadata.test @@ -0,0 +1,199 @@ +# +# BUG#42749: infinite loop writing to row based binlog - processlist shows +# "freeing items" +# +# WHY +# === +# +# This bug would make table map event to report data_written one byte less +# than what would actually be written in its body. This would cause one byte shorter +# event end_log_pos. The ultimate impact was that it would make fixing the +# position in MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop. +# +# HOW +# === +# +# Checking that the patch fixes the problem is done as follows: +# i) a table with several fields is created; +# ii) an insert is performed; +# iii) the logs are flushed; +# iv) mysqlbinlog is used to check if it succeeds. +# +# In step iv), before the bug was fixed, the test case would fail with +# mysqlbinlog reporting that it was unable to succeed in reading the event. +# + +-- source include/have_log_bin.inc +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +-- connection default + +RESET MASTER; + +-- disable_warnings +DROP TABLE IF EXISTS `t1`; +-- enable_warnings + +CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` varchar(30) NOT NULL, + `c3` varchar(30) DEFAULT NULL, + `c4` varchar(30) DEFAULT NULL, + `c5` varchar(30) DEFAULT NULL, + `c6` varchar(30) DEFAULT NULL, + `c7` varchar(30) DEFAULT NULL, + `c8` varchar(30) DEFAULT NULL, + `c9` varchar(30) DEFAULT NULL, + `c10` varchar(30) DEFAULT NULL, + `c11` varchar(30) DEFAULT NULL, + `c12` varchar(30) DEFAULT NULL, + `c13` varchar(30) DEFAULT NULL, + `c14` varchar(30) DEFAULT NULL, + `c15` varchar(30) DEFAULT NULL, + `c16` varchar(30) DEFAULT NULL, + `c17` varchar(30) DEFAULT NULL, + `c18` varchar(30) DEFAULT NULL, + `c19` varchar(30) DEFAULT NULL, + `c20` varchar(30) DEFAULT NULL, + `c21` varchar(30) DEFAULT NULL, + `c22` varchar(30) DEFAULT NULL, + `c23` varchar(30) DEFAULT NULL, + `c24` varchar(30) DEFAULT NULL, + `c25` varchar(30) DEFAULT NULL, + `c26` varchar(30) DEFAULT NULL, + `c27` varchar(30) DEFAULT NULL, + `c28` varchar(30) DEFAULT NULL, + `c29` varchar(30) DEFAULT NULL, + `c30` varchar(30) DEFAULT NULL, + `c31` varchar(30) DEFAULT NULL, + `c32` varchar(30) DEFAULT NULL, + `c33` varchar(30) DEFAULT NULL, + `c34` varchar(30) DEFAULT NULL, + `c35` varchar(30) DEFAULT NULL, + `c36` varchar(30) DEFAULT NULL, + `c37` varchar(30) DEFAULT NULL, + `c38` varchar(30) DEFAULT NULL, + `c39` varchar(30) DEFAULT NULL, + `c40` varchar(30) DEFAULT NULL, + `c41` varchar(30) DEFAULT NULL, + `c42` varchar(30) DEFAULT NULL, + `c43` varchar(30) DEFAULT NULL, + `c44` varchar(30) DEFAULT NULL, + `c45` varchar(30) DEFAULT NULL, + `c46` varchar(30) DEFAULT NULL, + `c47` varchar(30) DEFAULT NULL, + `c48` varchar(30) DEFAULT NULL, + `c49` varchar(30) DEFAULT NULL, + `c50` varchar(30) DEFAULT NULL, + `c51` varchar(30) DEFAULT NULL, + `c52` varchar(30) DEFAULT NULL, + `c53` varchar(30) DEFAULT NULL, + `c54` varchar(30) DEFAULT NULL, + `c55` varchar(30) DEFAULT NULL, + `c56` varchar(30) DEFAULT NULL, + `c57` varchar(30) DEFAULT NULL, + `c58` varchar(30) DEFAULT NULL, + `c59` varchar(30) DEFAULT NULL, + `c60` varchar(30) DEFAULT NULL, + `c61` varchar(30) DEFAULT NULL, + `c62` varchar(30) DEFAULT NULL, + `c63` varchar(30) DEFAULT NULL, + `c64` varchar(30) DEFAULT NULL, + `c65` varchar(30) DEFAULT NULL, + `c66` varchar(30) DEFAULT NULL, + `c67` varchar(30) DEFAULT NULL, + `c68` varchar(30) DEFAULT NULL, + `c69` varchar(30) DEFAULT NULL, + `c70` varchar(30) DEFAULT NULL, + `c71` varchar(30) DEFAULT NULL, + `c72` varchar(30) DEFAULT NULL, + `c73` varchar(30) DEFAULT NULL, + `c74` varchar(30) DEFAULT NULL, + `c75` varchar(30) DEFAULT NULL, + `c76` varchar(30) DEFAULT NULL, + `c77` varchar(30) DEFAULT NULL, + `c78` varchar(30) DEFAULT NULL, + `c79` varchar(30) DEFAULT NULL, + `c80` varchar(30) DEFAULT NULL, + `c81` varchar(30) DEFAULT NULL, + `c82` varchar(30) DEFAULT NULL, + `c83` varchar(30) DEFAULT NULL, + `c84` varchar(30) DEFAULT NULL, + `c85` varchar(30) DEFAULT NULL, + `c86` varchar(30) DEFAULT NULL, + `c87` varchar(30) DEFAULT NULL, + `c88` varchar(30) DEFAULT NULL, + `c89` varchar(30) DEFAULT NULL, + `c90` varchar(30) DEFAULT NULL, + `c91` varchar(30) DEFAULT NULL, + `c92` varchar(30) DEFAULT NULL, + `c93` varchar(30) DEFAULT NULL, + `c94` varchar(30) DEFAULT NULL, + `c95` varchar(30) DEFAULT NULL, + `c96` varchar(30) DEFAULT NULL, + `c97` varchar(30) DEFAULT NULL, + `c98` varchar(30) DEFAULT NULL, + `c99` varchar(30) DEFAULT NULL, + `c100` varchar(30) DEFAULT NULL, + `c101` varchar(30) DEFAULT NULL, + `c102` varchar(30) DEFAULT NULL, + `c103` varchar(30) DEFAULT NULL, + `c104` varchar(30) DEFAULT NULL, + `c105` varchar(30) DEFAULT NULL, + `c106` varchar(30) DEFAULT NULL, + `c107` varchar(30) DEFAULT NULL, + `c108` varchar(30) DEFAULT NULL, + `c109` varchar(30) DEFAULT NULL, + `c110` varchar(30) DEFAULT NULL, + `c111` varchar(30) DEFAULT NULL, + `c112` varchar(30) DEFAULT NULL, + `c113` varchar(30) DEFAULT NULL, + `c114` varchar(30) DEFAULT NULL, + `c115` varchar(30) DEFAULT NULL, + `c116` varchar(30) DEFAULT NULL, + `c117` varchar(30) DEFAULT NULL, + `c118` varchar(30) DEFAULT NULL, + `c119` varchar(30) DEFAULT NULL, + `c120` varchar(30) DEFAULT NULL, + `c121` varchar(30) DEFAULT NULL, + `c122` varchar(30) DEFAULT NULL, + `c123` varchar(30) DEFAULT NULL, + `c124` varchar(30) DEFAULT NULL, + `c125` varchar(30) DEFAULT NULL, + `c126` varchar(30) DEFAULT NULL, + `c127` varchar(30) DEFAULT NULL, + `c128` varchar(30) DEFAULT NULL, + `c129` varchar(30) DEFAULT NULL, + `c130` varchar(30) DEFAULT NULL, + `c131` varchar(30) DEFAULT NULL, + `c132` varchar(30) DEFAULT NULL, + `c133` varchar(30) DEFAULT NULL, + `c134` varchar(30) DEFAULT NULL, + `c135` varchar(30) DEFAULT NULL, + `c136` varchar(30) DEFAULT NULL, + `c137` varchar(30) DEFAULT NULL, + `c138` varchar(30) DEFAULT NULL, + `c139` varchar(30) DEFAULT NULL, + `c140` varchar(30) DEFAULT NULL, + `c141` varchar(30) DEFAULT NULL, + `c142` varchar(30) DEFAULT NULL, + `c143` varchar(30) DEFAULT NULL, + `c144` varchar(30) DEFAULT NULL, + `c145` varchar(30) DEFAULT NULL, + `c146` varchar(30) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB; + +LOCK TABLES `t1` WRITE; + +INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); + +DROP TABLE `t1`; + +FLUSH LOGS; + +-- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. + +-- let $MYSQLD_DATADIR= `SELECT @@datadir`; +-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog +-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog diff --git a/sql/log_event.cc b/sql/log_event.cc index a10a36f3b43..a878e9a2f9d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7861,10 +7861,11 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, /* Now set the size of the data to the size of the field metadata array - plus one or two bytes for number of elements in the field metadata array. + plus one or three bytes (see pack.c:net_store_length) for number of + elements in the field metadata array. */ if (m_field_metadata_size > 255) - m_data_size+= m_field_metadata_size + 2; + m_data_size+= m_field_metadata_size + 3; else m_data_size+= m_field_metadata_size + 1; From dbf8997b40a34ab01a57c0fe37c5ae9e345659fc Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 12 May 2009 09:14:23 -0400 Subject: [PATCH 065/115] Remove community-server only feature and place in its own test with appropriate condition. --- mysql-test/r/information_schema.result | 5 ----- mysql-test/r/information_schema_community.result | 8 ++++++++ mysql-test/t/information_schema.test | 7 ------- mysql-test/t/information_schema_community.test | 13 +++++++++++++ 4 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 mysql-test/r/information_schema_community.result create mode 100644 mysql-test/t/information_schema_community.test diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 6d88527e104..54fa4be027e 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1318,11 +1318,6 @@ TABLE_PRIVILEGES information_schema.TABLE_PRIVILEGES 1 TRIGGERS information_schema.TRIGGERS 1 USER_PRIVILEGES information_schema.USER_PRIVILEGES 1 VIEWS information_schema.VIEWS 1 -show global status like "Uptime_%"; -Variable_name Value -flush status; -show global status like "Uptime_%"; -Variable_name Value create table t1(f1 int); create view v1 as select f1+1 as a from t1; create table t2 (f1 int, f2 int); diff --git a/mysql-test/r/information_schema_community.result b/mysql-test/r/information_schema_community.result new file mode 100644 index 00000000000..e21039d1bb9 --- /dev/null +++ b/mysql-test/r/information_schema_community.result @@ -0,0 +1,8 @@ +show global status like "Uptime_%"; +Variable_name Value +Uptime_since_flush_status # +flush status; +show global status like "Uptime_%"; +Variable_name Value +Uptime_since_flush_status # +End of 5.0 tests. diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 95c816afae6..63b69ce8384 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1028,13 +1028,6 @@ where t.table_schema = 'information_schema' and (c2.column_type = 'varchar(7)' or c2.column_type = 'varchar(20)') group by c2.column_type order by num limit 1) group by t.table_name order by num1, t.table_name; -# Bug#24822: Patch: uptime_since_flush_status -# ---replace_column 2 # -show global status like "Uptime_%"; -flush status; ---replace_column 2 # -show global status like "Uptime_%"; # Almost certainly zero # diff --git a/mysql-test/t/information_schema_community.test b/mysql-test/t/information_schema_community.test new file mode 100644 index 00000000000..d150e0bbb8b --- /dev/null +++ b/mysql-test/t/information_schema_community.test @@ -0,0 +1,13 @@ +-- source include/have_community_features.inc + +# +# Bug#24822: Patch: uptime_since_flush_status +# +--replace_column 2 # +show global status like "Uptime_%"; +flush status; +--replace_column 2 # +show global status like "Uptime_%"; # Almost certainly zero + +--echo End of 5.0 tests. + From d7004f0b23ae2b4c3095fdae83bc5a1bdb06b548 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Mon, 18 May 2009 10:10:30 +0200 Subject: [PATCH 066/115] Bug#19027 MySQL 5.0 starts even with Fatal InnoDB errors convert_dash_to_underscore was supplied with a character length containing my byte too many which caused valgrind errors of invalid read. --- sql/sql_plugin.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index b5c7ceda6ab..da168d36429 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3314,7 +3314,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, varname= (char*) alloc_root(mem_root, len); strxmov(varname, tmp->name.str, "-", o->name, NullS); my_casedn_str(&my_charset_latin1, varname); - convert_dash_to_underscore(varname, len); + convert_dash_to_underscore(varname, len-1); v= new (mem_root) sys_var_pluginvar(varname, o); } DBUG_ASSERT(v); /* check that an object was actually constructed */ From cc5d329ae540da2f63f7824cba01e85d2f743d55 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Mon, 18 May 2009 13:39:13 +0200 Subject: [PATCH 067/115] Bug#19027 MySQL 5.0 starts even with Fatal InnoDB errors Fixed start up options for test case "rpl_ndb_2other-slave" to match the changed behavior for plugin options. --- mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt index 188b31efa8a..dff423702b4 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt @@ -1 +1 @@ ---innodb --ndbcluster=0 --log-slave-updates=0 +--innodb --loose-ndbcluster=OFF --log-slave-updates=0 From bb3f97f4bfa7946e83bf69bc962efff8131bd11a Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Mon, 18 May 2009 12:53:06 -0400 Subject: [PATCH 068/115] Bug#44920 - MTR2 is not processing master.opt input properly on Windows Disabling these two tests as they are affected by this bug / causing PB2 failures on Windows platforms. Can always disable via include/not_windows.inc if the bug fix looks like it will take some time. --- mysql-test/suite/rpl/t/disabled.def | 3 ++- mysql-test/t/disabled.def | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index b7cb6da8127..fcc3d56a9f5 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -10,4 +10,5 @@ # ############################################################################## -rpl_cross_version : BUG#42311 2009-03-27 joro rpl_cross_version fails on macosx +rpl_cross_version : Bug#42311 2009-03-27 joro rpl_cross_version fails on macosx +rpl_init_slave : Bug#44920 2009-05-18 pcrews MTR2 is not processing master.opt input properly on Windows diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 760c29bbae6..af4eb44b464 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,8 +10,6 @@ # ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. -innodb_bug39438 : BUG#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" +innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically - -#concurrent_innodb_safelog: disabled for embedded server due to bug#43733 Select on processlist let the embedded server crash (concurrent_innodb_safelog). -#concurrent_innodb_unsafelog: disabled for embedded server due to bug#43733. +init_connect : Bug#44920 2009-05-18 pcrews MTR2 is not processing master.opt input properly on Windows From fb3e433d4e89b8b111444a1460ea2f4cacadbb9b Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 19 May 2009 09:25:36 +0500 Subject: [PATCH 069/115] Fix for bug#44860: ALTER TABLE on view crashes server Problem: executing queries like "ALTER TABLE view1;" we don't check new view's name (which is not specified), that leads to server crash. Fix: do nothing (to be consistent with the behaviour for tables) in such cases. mysql-test/r/view.result: Fix for bug#44860: ALTER TABLE on view crashes server - test result. mysql-test/t/view.test: Fix for bug#44860: ALTER TABLE on view crashes server - test case. sql/sql_rename.cc: Fix for bug#44860: ALTER TABLE on view crashes server - do_rename(): new view/table name must be specified, ASSERT() added. sql/sql_table.cc: Fix for bug#44860: ALTER TABLE on view crashes server - mysql_alter_table(): renaming a view, check if new view name is specified. --- mysql-test/r/view.result | 8 ++++++++ mysql-test/t/view.test | 11 +++++++++++ sql/sql_rename.cc | 2 ++ sql/sql_table.cc | 14 ++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index a7af6a30f5c..613939bfdf6 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3836,6 +3836,14 @@ call p(); call p(); drop view a; drop procedure p; +# +# Bug #44860: ALTER TABLE on view crashes server +# +CREATE TABLE t1 (a INT); +CREATE VIEW v1 AS SELECT a FROM t1; +ALTER TABLE v1; +DROP VIEW v1; +DROP TABLE t1; # ----------------------------------------------------------------- # -- End of 5.1 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 39db92ee1bc..a788b5ab41e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3859,6 +3859,17 @@ drop procedure p; ########################################################################### + +--echo # +--echo # Bug #44860: ALTER TABLE on view crashes server +--echo # +CREATE TABLE t1 (a INT); +CREATE VIEW v1 AS SELECT a FROM t1; +ALTER TABLE v1; +DROP VIEW v1; +DROP TABLE t1; + + --echo # ----------------------------------------------------------------- --echo # -- End of 5.1 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index d4331b12cd4..7cc9130cc4a 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -261,6 +261,8 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, old_alias= ren_table->table_name; new_alias= new_table_name; } + DBUG_ASSERT(new_alias); + build_table_filename(name, sizeof(name), new_db, new_alias, reg_ext, 0); if (!access(name,F_OK)) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2744619e138..5397128855a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6139,6 +6139,20 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* Sic: there is a race here */ if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME)) { + /* + The following branch handles "ALTER VIEW v1 /no arguments/;" + This feature is not documented one. + However, before "OPTIMIZE TABLE t1;" was implemented, + ALTER TABLE with no alter_specifications was used to force-rebuild + the table. That's why this grammar is allowed. That's why we ignore + it for views. So just do nothing in such a case. + */ + if (!new_name) + { + my_ok(thd); + DBUG_RETURN(FALSE); + } + /* Avoid problems with a rename on a table that we have locked or if the user is trying to to do this in a transcation context From 9854967b92168c4d66661493d6a829c3ebdab1a0 Mon Sep 17 00:00:00 2001 From: Satya B Date: Tue, 19 May 2009 13:22:19 +0530 Subject: [PATCH 070/115] Applying InnoDB snashot 5.1-ss5024 part 1, Follow up Fix for BUG#43660 Detailed revision comments: r4705 | vasil | 2009-04-14 14:30:13 +0300 (Tue, 14 Apr 2009) | 7 lines branches/5.1: When using the random function, first take the modulus by the number of pages and then typecast to ulint. This is a followup to r4699 - the fix of Bug#43660. --- storage/innobase/page/page0cur.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c index 70b7de194fd..ea011843890 100644 --- a/storage/innobase/page/page0cur.c +++ b/storage/innobase/page/page0cur.c @@ -538,7 +538,7 @@ page_cur_open_on_rnd_user_rec( rnd = page_rnd % page_get_n_recs(page); } else { - rnd = (ulint) page_cur_lcg_prng() % page_get_n_recs(page); + rnd = (ulint) (page_cur_lcg_prng() % page_get_n_recs(page)); } rec = page_get_infimum_rec(page); From 65eac15004f2f455182dc09e100bacca21afaa36 Mon Sep 17 00:00:00 2001 From: Satya B Date: Tue, 19 May 2009 13:26:49 +0530 Subject: [PATCH 071/115] Applying InnoDB snashot 5.1-ss5024, part 2. Fix for BUG#44320 BUG#44320 - InnoDB: missing DB_ROLL_PTR in Table Monitor COLUMNS output Detailed revision comments: r4976 | marko | 2009-05-13 15:44:54 +0300 (Wed, 13 May 2009) | 6 lines branches/5.1: Display DB_ROLL_PTR in the COLUMNS section of the innodb_table_monitor output. It was accidentally omitted due to an off-by-one loop condition. (Bug #44320) rb://116 approved by Heikki Tuuri --- storage/innobase/dict/dict0dict.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index c7a57d6a2b8..0fec2443836 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -3932,7 +3932,7 @@ dict_table_print_low( (ulong) UT_LIST_GET_LEN(table->indexes), (ulong) table->stat_n_rows); - for (i = 0; i + 1 < (ulint) table->n_cols; i++) { + for (i = 0; i < (ulint) table->n_cols; i++) { dict_col_print_low(table, dict_table_get_nth_col(table, i)); fputs("; ", stderr); } From 07b93588609d8b5c2db72b61e61a8a2a70281175 Mon Sep 17 00:00:00 2001 From: Satya B Date: Tue, 19 May 2009 13:50:28 +0530 Subject: [PATCH 072/115] Applying InnoDB snashot 5.1-ss5024,part 3. Fixes BUG#42101 BUG#42101 - Race condition in innodb_commit_concurrency Detailed revision comments: r4994 | marko | 2009-05-14 15:04:55 +0300 (Thu, 14 May 2009) | 18 lines branches/5.1: Prevent a race condition in innobase_commit() by ensuring that innodb_commit_concurrency>0 remains constant at run time. (Bug #42101) srv_commit_concurrency: Make this a static variable in ha_innodb.cc. innobase_commit_concurrency_validate(): Check that innodb_commit_concurrency is not changed from or to 0 at run time. This is needed, because innobase_commit() assumes that innodb_commit_concurrency>0 remains constant. Without this limitation, the checks for innodb_commit_concurrency>0 in innobase_commit() should be removed and that function would have to acquire and release commit_cond_m at least twice per invocation. Normally, innodb_commit_concurrency=0, and introducing the mutex operations would mean significant overhead. innodb_bug42101.test, innodb_bug42101-nonzero.test: Test cases. rb://123 approved by Heikki Tuuri --- mysql-test/r/innodb_bug42101-nonzero.result | 22 ++++++++++ mysql-test/r/innodb_bug42101.result | 18 ++++++++ .../t/innodb_bug42101-nonzero-master.opt | 1 + mysql-test/t/innodb_bug42101-nonzero.test | 19 ++++++++ mysql-test/t/innodb_bug42101.test | 17 ++++++++ storage/innobase/handler/ha_innodb.cc | 43 ++++++++++++++++--- storage/innobase/include/srv0srv.h | 1 - storage/innobase/srv/srv0srv.c | 1 - 8 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 mysql-test/r/innodb_bug42101-nonzero.result create mode 100644 mysql-test/r/innodb_bug42101.result create mode 100644 mysql-test/t/innodb_bug42101-nonzero-master.opt create mode 100644 mysql-test/t/innodb_bug42101-nonzero.test create mode 100644 mysql-test/t/innodb_bug42101.test diff --git a/mysql-test/r/innodb_bug42101-nonzero.result b/mysql-test/r/innodb_bug42101-nonzero.result new file mode 100644 index 00000000000..8a14296381c --- /dev/null +++ b/mysql-test/r/innodb_bug42101-nonzero.result @@ -0,0 +1,22 @@ +set global innodb_commit_concurrency=0; +ERROR HY000: Incorrect arguments to SET +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +1 +set global innodb_commit_concurrency=1; +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +1 +set global innodb_commit_concurrency=42; +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +42 +set global innodb_commit_concurrency=0; +ERROR HY000: Incorrect arguments to SET +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +42 +set global innodb_commit_concurrency=1; +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +1 diff --git a/mysql-test/r/innodb_bug42101.result b/mysql-test/r/innodb_bug42101.result new file mode 100644 index 00000000000..9a9c8e0ce9b --- /dev/null +++ b/mysql-test/r/innodb_bug42101.result @@ -0,0 +1,18 @@ +set global innodb_commit_concurrency=0; +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +0 +set global innodb_commit_concurrency=1; +ERROR HY000: Incorrect arguments to SET +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +0 +set global innodb_commit_concurrency=42; +ERROR HY000: Incorrect arguments to SET +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +0 +set global innodb_commit_concurrency=0; +select @@innodb_commit_concurrency; +@@innodb_commit_concurrency +0 diff --git a/mysql-test/t/innodb_bug42101-nonzero-master.opt b/mysql-test/t/innodb_bug42101-nonzero-master.opt new file mode 100644 index 00000000000..d71dbe17d5b --- /dev/null +++ b/mysql-test/t/innodb_bug42101-nonzero-master.opt @@ -0,0 +1 @@ +--innodb_commit_concurrency=1 diff --git a/mysql-test/t/innodb_bug42101-nonzero.test b/mysql-test/t/innodb_bug42101-nonzero.test new file mode 100644 index 00000000000..c691a234c51 --- /dev/null +++ b/mysql-test/t/innodb_bug42101-nonzero.test @@ -0,0 +1,19 @@ +# +# Bug#42101 Race condition in innodb_commit_concurrency +# http://bugs.mysql.com/42101 +# + +-- source include/have_innodb.inc + +--error ER_WRONG_ARGUMENTS +set global innodb_commit_concurrency=0; +select @@innodb_commit_concurrency; +set global innodb_commit_concurrency=1; +select @@innodb_commit_concurrency; +set global innodb_commit_concurrency=42; +select @@innodb_commit_concurrency; +--error ER_WRONG_ARGUMENTS +set global innodb_commit_concurrency=0; +select @@innodb_commit_concurrency; +set global innodb_commit_concurrency=1; +select @@innodb_commit_concurrency; diff --git a/mysql-test/t/innodb_bug42101.test b/mysql-test/t/innodb_bug42101.test new file mode 100644 index 00000000000..13d531ecde7 --- /dev/null +++ b/mysql-test/t/innodb_bug42101.test @@ -0,0 +1,17 @@ +# +# Bug#42101 Race condition in innodb_commit_concurrency +# http://bugs.mysql.com/42101 +# + +-- source include/have_innodb.inc + +set global innodb_commit_concurrency=0; +select @@innodb_commit_concurrency; +--error ER_WRONG_ARGUMENTS +set global innodb_commit_concurrency=1; +select @@innodb_commit_concurrency; +--error ER_WRONG_ARGUMENTS +set global innodb_commit_concurrency=42; +select @@innodb_commit_concurrency; +set global innodb_commit_concurrency=0; +select @@innodb_commit_concurrency; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b1c7221f4ec..56e28cf5f14 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -101,6 +101,7 @@ static long innobase_mirrored_log_groups, innobase_log_files_in_group, innobase_additional_mem_pool_size, innobase_file_io_threads, innobase_lock_wait_timeout, innobase_force_recovery, innobase_open_files, innobase_autoinc_lock_mode; +static ulong innobase_commit_concurrency = 0; static long long innobase_buffer_pool_size, innobase_log_file_size; @@ -165,6 +166,38 @@ static handler *innobase_create_handler(handlerton *hton, static const char innobase_hton_name[]= "InnoDB"; +/***************************************************************** +Check for a valid value of innobase_commit_concurrency. */ +static +int +innobase_commit_concurrency_validate( +/*=================================*/ + /* out: 0 for valid + innodb_commit_concurrency */ + THD* thd, /* in: thread handle */ + struct st_mysql_sys_var* var, /* in: pointer to system + variable */ + void* save, /* out: immediate result + for update function */ + struct st_mysql_value* value) /* in: incoming string */ +{ + long long intbuf; + ulong commit_concurrency; + + DBUG_ENTER("innobase_commit_concurrency_validate"); + + if (value->val_int(value, &intbuf)) { + /* The value is NULL. That is invalid. */ + DBUG_RETURN(1); + } + + *reinterpret_cast(save) = commit_concurrency + = static_cast(intbuf); + + /* Allow the value to be updated, as long as it remains zero + or nonzero. */ + DBUG_RETURN(!(!commit_concurrency == !innobase_commit_concurrency)); +} static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG, "Enable InnoDB support for the XA two-phase commit", @@ -1951,11 +1984,11 @@ innobase_commit( Note, the position is current because of prepare_commit_mutex */ retry: - if (srv_commit_concurrency > 0) { + if (innobase_commit_concurrency > 0) { pthread_mutex_lock(&commit_cond_m); commit_threads++; - if (commit_threads > srv_commit_concurrency) { + if (commit_threads > innobase_commit_concurrency) { commit_threads--; pthread_cond_wait(&commit_cond, &commit_cond_m); @@ -1972,7 +2005,7 @@ retry: innobase_commit_low(trx); - if (srv_commit_concurrency > 0) { + if (innobase_commit_concurrency > 0) { pthread_mutex_lock(&commit_cond_m); commit_threads--; pthread_cond_signal(&commit_cond); @@ -8289,10 +8322,10 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", NULL, NULL, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 1024*1024L); -static MYSQL_SYSVAR_ULONG(commit_concurrency, srv_commit_concurrency, +static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency, PLUGIN_VAR_RQCMDARG, "Helps in performance tuning in heavily concurrent environments.", - NULL, NULL, 0, 0, 1000, 0); + innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0); static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter, PLUGIN_VAR_RQCMDARG, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 9ff3c225eb0..67144a41d3d 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -109,7 +109,6 @@ extern ulint srv_max_dirty_pages_pct; extern ulint srv_force_recovery; extern ulong srv_thread_concurrency; -extern ulong srv_commit_concurrency; extern ulint srv_max_n_threads; diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index b8b63052394..71e74ab848b 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -285,7 +285,6 @@ computer. Bigger computers need bigger values. Value 0 will disable the concurrency check. */ ulong srv_thread_concurrency = 0; -ulong srv_commit_concurrency = 0; os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data structures */ From d7a22ed9a91313c709bc9362321568cdd9842d5e Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 12 May 2009 16:59:17 +0300 Subject: [PATCH 073/115] Bug #44399: crash with statement using TEXT columns, aggregates, GROUP BY, and HAVING When calculating GROUP BY the server caches some expressions. It does that by allocating a string slot (Item_copy_string) and assigning the value of the expression to it. This effectively means that the result type of the expression can be changed from whatever it was to a string. As this substitution takes place after the compile-time result type calculation for IN but before the run-time type calculations, it causes the type calculations in the IN function done at run time to get unexpected results different from what was prepared at compile time. In the CASE ... WHEN ... THEN ... statement there was a similar problem and it was solved by artificially adding a STRING argument to the matrix at compile time, so if any of the arguments of the CASE function changes its type to a string it will still be covered by the information prepared at compile time. Extended the CASE fix for cover the IN case. An alternative way of fixing this problem is by caching the result type of the arguments at compile time and using the cached information at run time instead of re-calculating the result types. Preferred the CASE approach for uniformity and fix localization. mysql-test/r/func_in.result: Bug #44399: test case mysql-test/t/func_in.test: Bug #44399: test case sql/item_cmpfunc.cc: Bug #44399: assume at compile time there's an extra string argument in the IN function (similar to CASE) to cater for possible string conversions in the process of calculating the GROUP BY/aggregates. --- mysql-test/r/func_in.result | 5 +++++ mysql-test/t/func_in.test | 10 ++++++++++ sql/item_cmpfunc.cc | 28 ++++++++++++++-------------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 1e967b668c5..b19edbd1a00 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -587,4 +587,9 @@ SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1; CASE c1 WHEN c1 + 1 THEN 1 END ABS(AVG(c0)) NULL 1.0000 DROP TABLE t1; +CREATE TABLE t1(a TEXT); +INSERT INTO t1 VALUES('iynfj'); +SELECT SUM( DISTINCT a ) FROM t1 GROUP BY a HAVING a IN ( AVG( 1 ), 1 + a ); +SUM( DISTINCT a ) +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 3fc1697f146..795a92180db 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -439,4 +439,14 @@ SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1; DROP TABLE t1; +# +# Bug #44399: crash with statement using TEXT columns, aggregates, GROUP BY, +# and HAVING +# + +CREATE TABLE t1(a TEXT); +INSERT INTO t1 VALUES('iynfj'); +SELECT SUM( DISTINCT a ) FROM t1 GROUP BY a HAVING a IN ( AVG( 1 ), 1 + a ); +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a9bfea1b806..5017464f968 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -189,6 +189,7 @@ enum_field_types agg_field_type(Item **items, uint nitems) collect_cmp_types() items Array of items to collect types from nitems Number of items in the array + with_sum_func a sum function is referenced DESCRIPTION This function collects different result types for comparison of the first @@ -199,7 +200,7 @@ enum_field_types agg_field_type(Item **items, uint nitems) Bitmap of collected types - otherwise */ -static uint collect_cmp_types(Item **items, uint nitems) +static uint collect_cmp_types(Item **items, uint nitems, my_bool with_sum_func) { uint i; uint found_types; @@ -215,6 +216,16 @@ static uint collect_cmp_types(Item **items, uint nitems) found_types|= 1<< (uint)item_cmp_type(left_result, items[i]->result_type()); } + if (with_sum_func || current_thd->lex->current_select->group_list.elements) + { + /* + See TODO commentary in the setup_copy_fields function: + item in a group may be wrapped with an Item_copy_string item. + That item has a STRING_RESULT result type, so we need + to take this type into account. + */ + found_types |= (1 << item_cmp_type(left_result, STRING_RESULT)); + } return found_types; } @@ -2722,19 +2733,8 @@ void Item_func_case::fix_length_and_dec() for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; - if (!(found_types= collect_cmp_types(agg, nagg))) + if (!(found_types= collect_cmp_types(agg, nagg, with_sum_func))) return; - if (with_sum_func || current_thd->lex->current_select->group_list.elements) - { - /* - See TODO commentary in the setup_copy_fields function: - item in a group may be wrapped with an Item_copy_string item. - That item has a STRING_RESULT result type, so we need - to take this type into account. - */ - found_types |= (1 << item_cmp_type(left_result_type, STRING_RESULT)); - } - for (i= 0; i <= (uint)DECIMAL_RESULT; i++) { if (found_types & (1 << i) && !cmp_items[i]) @@ -3525,7 +3525,7 @@ void Item_func_in::fix_length_and_dec() uint type_cnt= 0, i; Item_result cmp_type= STRING_RESULT; left_result_type= args[0]->result_type(); - if (!(found_types= collect_cmp_types(args, arg_count))) + if (!(found_types= collect_cmp_types(args, arg_count, with_sum_func))) return; for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++) From bd59628754d7f6ced2c19286c041b1ee5ce354e0 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Tue, 12 May 2009 22:42:31 +0500 Subject: [PATCH 074/115] Bug #44290: explain crashes for subquery with distinct in SQL_SELECT::test_quick_select The crash was caused by an incomplete cleanup of JOIN_TAB::select during the filesort of rows for GROUP BY clause inside a subquery. Queries where a quick index access is replaced with filesort was was affected. For example: SELECT 1 FROM (SELECT COUNT(DISTINCT c1) FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x Quick index access related data in the SQL_SELECT::test_quick_select function was inconsistent after an incomplete cleanup. This function has been completed to prevent crashes in the SQL_SELECT::test_quick_select function. mysql-test/include/mix1.inc: Add test case for bug #44290. mysql-test/r/innodb_mysql.result: Add test case for bug #44290. sql/sql_select.cc: Bug #44290: explain crashes for subquery with distinct in SQL_SELECT::test_quick_select Quick index access related data in the SQL_SELECT::test_quick_select function was inconsistent after an incomplete cleanup. This function has been completed to prevent crashes in the SQL_SELECT::test_quick_select function. --- mysql-test/include/mix1.inc | 19 +++++++++++++++++++ mysql-test/r/innodb_mysql.result | 19 +++++++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 39 insertions(+) diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index c9cbf2d2839..7c87949830f 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1516,4 +1516,23 @@ DROP TABLE t1; # DROP TABLE t1; # +--echo # +--echo # Bug #44290: explain crashes for subquery with distinct in +--echo # SQL_SELECT::test_quick_select +--echo # (reproduced only with InnoDB tables) +--echo # + +eval +CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, KEY (c3), KEY (c2, c3)) + ENGINE=$engine_type; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); + +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) + FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) + FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 3f830378afa..191a8578d4c 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1687,6 +1687,25 @@ vid tid idx name type 3 1 2 c1 NULL 3 1 1 pk NULL DROP TABLE t1; +# +# Bug #44290: explain crashes for subquery with distinct in +# SQL_SELECT::test_quick_select +# (reproduced only with InnoDB tables) +# +CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, KEY (c3), KEY (c2, c3)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +1 +1 +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 +2 DERIVED t1 index c3,c2 c2 10 NULL 5 +DROP TABLE t1; End of 5.1 tests drop table if exists t1, t2, t3; create table t1(a int); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cdae1581a0c..ab9c060c69c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13481,6 +13481,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, { select->cleanup(); // filesort did select tab->select= 0; + table->quick_keys.clear_all(); // as far as we cleanup select->quick } tab->select_cond=0; tab->last_inner= 0; From da0fe3cb31c80b2b218285cf02c72a70be3b402f Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Wed, 13 May 2009 15:41:24 +0530 Subject: [PATCH 075/115] Bug #39802 On Windows, 32-bit time_t should be enforced This patch fixes compilation warning, "conversion from 'time_t' to 'ulong', possible loss of data". The fix is to typecast time_t to ulong before assigning it to ulong. Backported this from 6.0-bugteam tree. storage/archive/ha_archive.cc: type casting time_t to ulong before assigning. storage/federated/ha_federated.cc: type casting time_t to ulong before assigning. storage/innobase/handler/ha_innodb.cc: type casting time_t to ulong before assigning. storage/myisam/ha_myisam.cc: type casting time_t to ulong before assigning. --- storage/archive/ha_archive.cc | 4 ++-- storage/federated/ha_federated.cc | 4 ++-- storage/innobase/handler/ha_innodb.cc | 2 +- storage/myisam/ha_myisam.cc | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 5e2a4ad5da3..1146b2eb73a 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -1474,8 +1474,8 @@ int ha_archive::info(uint flag) stats.mean_rec_length= table->s->reclength + buffer.alloced_length(); stats.data_file_length= file_stat.st_size; - stats.create_time= file_stat.st_ctime; - stats.update_time= file_stat.st_mtime; + stats.create_time= (ulong) file_stat.st_ctime; + stats.update_time= (ulong) file_stat.st_mtime; stats.max_data_file_length= share->rows_recorded * stats.mean_rec_length; } stats.delete_length= 0; diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 1f4e1ae48b9..2fdf1bc7900 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -2850,10 +2850,10 @@ int ha_federated::info(uint flag) stats.data_file_length= stats.records * stats.mean_rec_length; if (row[12] != NULL) - stats.update_time= (time_t) my_strtoll10(row[12], (char**) 0, + stats.update_time= (ulong) my_strtoll10(row[12], (char**) 0, &error); if (row[13] != NULL) - stats.check_time= (time_t) my_strtoll10(row[13], (char**) 0, + stats.check_time= (ulong) my_strtoll10(row[13], (char**) 0, &error); } /* diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e9c3f62c9dc..b1c7221f4ec 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6012,7 +6012,7 @@ ha_innobase::info( nor the CHECK TABLE time, nor the UPDATE or INSERT time. */ if (os_file_get_status(path,&stat_info)) { - stats.create_time = stat_info.ctime; + stats.create_time = (ulong) stat_info.ctime; } } diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index e82246638ff..1845859ec81 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1784,7 +1784,7 @@ int ha_myisam::info(uint flag) stats.data_file_length= misam_info.data_file_length; stats.index_file_length= misam_info.index_file_length; stats.delete_length= misam_info.delete_length; - stats.check_time= misam_info.check_time; + stats.check_time= (ulong) misam_info.check_time; stats.mean_rec_length= misam_info.mean_reclength; } if (flag & HA_STATUS_CONST) @@ -1792,7 +1792,7 @@ int ha_myisam::info(uint flag) TABLE_SHARE *share= table->s; stats.max_data_file_length= misam_info.max_data_file_length; stats.max_index_file_length= misam_info.max_index_file_length; - stats.create_time= misam_info.create_time; + stats.create_time= (ulong) misam_info.create_time; ref_length= misam_info.reflength; share->db_options_in_use= misam_info.options; stats.block_size= myisam_block_size; /* record block size */ @@ -1831,7 +1831,7 @@ int ha_myisam::info(uint flag) my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos); } if (flag & HA_STATUS_TIME) - stats.update_time = misam_info.update_time; + stats.update_time = (ulong) misam_info.update_time; if (flag & HA_STATUS_AUTO) stats.auto_increment_value= misam_info.auto_increment; From 78283436d73a0d181ddc2477cc9b8c08b5bbc9fc Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Thu, 14 May 2009 16:05:09 +0530 Subject: [PATCH 076/115] Bug#44232 Error msg should be improved when collation not supported. checking in a test case that will reproduce the error on v5r4. mysql-test/suite/ibmdb2i/include/have_i54.inc: Bug#44232 Error msg should be improved when collation not supported. mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result: Bug#44232 Error msg should be improved when collation not supported. mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test: Bug#44232 Error msg should be improved when collation not supported. --- mysql-test/suite/ibmdb2i/include/have_i54.inc | 20 +++++++++++++++++++ .../suite/ibmdb2i/r/ibmdb2i_bug_44232.result | 4 ++++ .../suite/ibmdb2i/t/ibmdb2i_bug_44232.test | 8 ++++++++ 3 files changed, 32 insertions(+) create mode 100755 mysql-test/suite/ibmdb2i/include/have_i54.inc create mode 100755 mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result create mode 100755 mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test diff --git a/mysql-test/suite/ibmdb2i/include/have_i54.inc b/mysql-test/suite/ibmdb2i/include/have_i54.inc new file mode 100755 index 00000000000..7054e196153 --- /dev/null +++ b/mysql-test/suite/ibmdb2i/include/have_i54.inc @@ -0,0 +1,20 @@ +# Check for IBM i 6.1 or later +--disable_query_log +system uname -rv > $MYSQLTEST_VARDIR/tmp/version; +--disable_warnings +drop table if exists uname_vr; +--enable_warnings +create temporary table uname_vr (r int, v int); +--disable_warnings +eval LOAD DATA INFILE "$MYSQLTEST_VARDIR/tmp/version" into table uname_vr fields terminated by ' '; +--enable_warnings +let $ok = `select count(*) from uname_vr where v = 5 and r = 4`; +drop table uname_vr; +remove_file $MYSQLTEST_VARDIR/tmp/version; +--enable_query_log +if (!$ok) +{ + skip "Need IBM i 5.4 or later"; +} + + diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result new file mode 100755 index 00000000000..8276b401073 --- /dev/null +++ b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result @@ -0,0 +1,4 @@ +create table t1 (c char(1) character set armscii8) engine=ibmdb2i; +ERROR HY000: Can't create table 'test.t1' (errno: 2504) +create table t1 (c char(1) character set eucjpms ) engine=ibmdb2i; +ERROR HY000: Can't create table 'test.t1' (errno: 2504) diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test new file mode 100755 index 00000000000..ea29b5abcd4 --- /dev/null +++ b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test @@ -0,0 +1,8 @@ +--source suite/ibmdb2i/include/have_ibmdb2i.inc +--source suite/ibmdb2i/include/have_i54.inc + +--error 1005 +create table t1 (c char(1) character set armscii8) engine=ibmdb2i; + +--error 1005 +create table t1 (c char(1) character set eucjpms ) engine=ibmdb2i; From e67233ff3f97231fbc9829793319a4e9b7faf140 Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Thu, 14 May 2009 14:44:47 +0300 Subject: [PATCH 077/115] Bugs #44871 and #43894: UNIX sockets need to be on a path shorter than 70 characters on some older platofrms. MTRv1 tries to fix this by moving the socket to the $TMPDIR, however this causes issues with certain tests on Windows. Fixed by not applying any hacks on Windows - Windows does not need them. --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index ffa9b4cb1d3..f60701b7b49 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1106,7 +1106,7 @@ sub command_line_setup () { # On some operating systems, there is a limit to the length of a # UNIX domain socket's path far below PATH_MAX, so try to avoid long # socket path names. - $sockdir = tempdir(CLEANUP => 0) if ( length($sockdir) >= 70 ); + $sockdir = tempdir(CLEANUP => 0) if ( length($sockdir) >= 70 ) && (! $glob_win32 ); $master->[0]= { From afee63222a3cb944654b2f5d997acd2d88e5b89b Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Thu, 14 May 2009 14:03:33 +0200 Subject: [PATCH 078/115] Bug#19027 MySQL 5.0 starts even with Fatal InnoDB errors It is not possible to prevent the server from starting if a mandatory built-in plugin fails to start. This can in some cases lead to data corruption when the old table name space suddenly is used by a different storage engine. A boolean command line option in the form of --foobar is automatically created for every existing plugin "foobar". By changing this command line option from a boolean to a tristate { OFF, ON, FORCE } it is possible to specify the plugin loading policy for each plugin. The behavior is specified as follows: OFF = Disable the plugin and start the server ON = Enable the plugin and start the server even if an error occurrs during plugin initialization. FORCE = Enable the plugin but don't start the server if an error occurrs during plugin initialization. mysql-test/lib/mtr_cases.pm: * Changed -- from a boolean to a tristate. mysys/my_getopt.c: * Changed -- from boolean to tristate. Optional arguments must still work for tristates. It is praxis that disable means value 0 and enable is value 1. Since plugin name is the only tristate with optional arguments this principle will still hold. sql/sql_plugin.cc: * Changed -- option from a boolean type to a tristate. - FORCE will now terminate the server if the plugin fails to initialize properly. * Refactored prototypes for test_plugin_options() and construct_options() to get rid of the 'enable' value pointer. * Cleaned up code related to option name constructing. * Added documentation sql/sql_plugin.h: * Introduced new member to st_plugin_int structure. --- mysql-test/lib/mtr_cases.pm | 2 +- mysys/my_getopt.c | 3 +- sql/sql_plugin.cc | 346 ++++++++++++++++++++++-------------- sql/sql_plugin.h | 1 + 4 files changed, 213 insertions(+), 139 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 23a85ef7ecc..d7a633cb80c 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -887,7 +887,7 @@ sub collect_one_test_case { if ( $tinfo->{'innodb_test'} ) { # This is a test that need innodb - if ( $::mysqld_variables{'innodb'} ne "TRUE" ) + if ( $::mysqld_variables{'innodb'} eq "OFF" ) { # innodb is not supported, skip it $tinfo->{'skip'}= 1; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 4b74cdbf266..33942d87e4f 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -410,7 +410,8 @@ invalid value '%s'", argument= optend; } else if (optp->arg_type == OPT_ARG && - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) + (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) || + (optp->var_type & GET_TYPE_MASK) == GET_ENUM)) { if (optend == disabled_my_option) *((my_bool*) value)= (my_bool) 0; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 1465b6d2d30..b5c7ceda6ab 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -29,6 +29,18 @@ extern struct st_mysql_plugin *mysqld_builtins[]; +/** + @note The order of the enumeration is critical. + @see construct_options +*/ +static const char *global_plugin_typelib_names[]= + { "OFF", "ON", "FORCE", NULL }; +enum enum_plugin_load_policy {PLUGIN_OFF, PLUGIN_ON, PLUGIN_FORCE}; +static TYPELIB global_plugin_typelib= + { array_elements(global_plugin_typelib_names)-1, + "", global_plugin_typelib_names, NULL }; + + char *opt_plugin_load= NULL; char *opt_plugin_dir_ptr; char opt_plugin_dir[FN_REFLEN]; @@ -192,7 +204,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv); static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, const char *list); static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *, - int *, char **, my_bool); + int *, char **); static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *, struct st_plugin_int **); static void unlock_variables(THD *thd, struct system_variables *vars); @@ -751,7 +763,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, tmp.name.length= name_len; tmp.ref_count= 0; tmp.state= PLUGIN_IS_UNINITIALIZED; - if (test_plugin_options(tmp_root, &tmp, argc, argv, true)) + if (test_plugin_options(tmp_root, &tmp, argc, argv)) tmp.state= PLUGIN_IS_DISABLED; if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) @@ -997,7 +1009,6 @@ static int plugin_initialize(struct st_plugin_int *plugin) DBUG_ENTER("plugin_initialize"); safe_mutex_assert_owner(&LOCK_plugin); - if (plugin_type_initialize[plugin->plugin->type]) { if ((*plugin_type_initialize[plugin->plugin->type])(plugin)) @@ -1083,6 +1094,20 @@ uchar *get_bookmark_hash_key(const uchar *buff, size_t *length, return (uchar*) var->key; } +static inline void convert_dash_to_underscore(char *str, int len) +{ + for (char *p= str; p <= str+len; p++) + if (*p == '-') + *p= '_'; +} + +static inline void convert_underscore_to_dash(char *str, int len) +{ + for (char *p= str; p <= str+len; p++) + if (*p == '_') + *p= '-'; +} + /* The logic is that we first load and initialize all compiled in plugins. @@ -1094,11 +1119,12 @@ uchar *get_bookmark_hash_key(const uchar *buff, size_t *length, int plugin_init(int *argc, char **argv, int flags) { uint i; - bool def_enabled, is_myisam; + bool is_myisam; struct st_mysql_plugin **builtins; struct st_mysql_plugin *plugin; struct st_plugin_int tmp, *plugin_ptr, **reap; MEM_ROOT tmp_root; + bool reaped_mandatory_plugin= FALSE; DBUG_ENTER("plugin_init"); if (initialized) @@ -1142,17 +1168,13 @@ int plugin_init(int *argc, char **argv, int flags) !my_strnncoll(&my_charset_latin1, (const uchar*) plugin->name, 6, (const uchar*) "InnoDB", 6)) continue; - /* by default, ndbcluster and federated are disabled */ - def_enabled= - my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0 && - my_strcasecmp(&my_charset_latin1, plugin->name, "FEDERATED") != 0; bzero(&tmp, sizeof(tmp)); tmp.plugin= plugin; tmp.name.str= (char *)plugin->name; tmp.name.length= strlen(plugin->name); tmp.state= 0; free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE)); - if (test_plugin_options(&tmp_root, &tmp, argc, argv, def_enabled)) + if (test_plugin_options(&tmp_root, &tmp, argc, argv)) tmp.state= PLUGIN_IS_DISABLED; else tmp.state= PLUGIN_IS_UNINITIALIZED; @@ -1227,6 +1249,8 @@ int plugin_init(int *argc, char **argv, int flags) while ((plugin_ptr= *(--reap))) { pthread_mutex_unlock(&LOCK_plugin); + if (plugin_ptr->is_mandatory) + reaped_mandatory_plugin= TRUE; plugin_deinitialize(plugin_ptr, true); pthread_mutex_lock(&LOCK_plugin); plugin_del(plugin_ptr); @@ -1234,6 +1258,8 @@ int plugin_init(int *argc, char **argv, int flags) pthread_mutex_unlock(&LOCK_plugin); my_afree(reap); + if (reaped_mandatory_plugin) + goto err; end: free_root(&tmp_root, MYF(0)); @@ -1299,7 +1325,7 @@ bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin) pthread_mutex_lock(&LOCK_plugin); rw_wrlock(&LOCK_system_variables_hash); - if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL, true)) + if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL)) goto end; tmp.state= PLUGIN_IS_UNINITIALIZED; if ((result= register_builtin(plugin, &tmp, &ptr))) @@ -2889,59 +2915,78 @@ my_bool get_one_plugin_option(int optid __attribute__((unused)), } +/** + Creates a set of my_option objects associated with a specified plugin- + handle. + + @param mem_root Memory allocator to be used. + @param tmp A pointer to a plugin handle + @param[out] options A pointer to a pre-allocated static array + + The set is stored in the pre-allocated static array supplied to the function. + The size of the array is calculated as (number_of_plugin_varaibles*2+3). The + reason is that each option can have a prefix '--plugin-' in addtion to the + shorter form '--<plugin-name>'. There is also space allocated for + terminating NULL pointers. + + @return + @retval -1 An error occurred + @retval 0 Success +*/ + static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, - my_option *options, my_bool **enabled, - bool can_disable) + my_option *options) { const char *plugin_name= tmp->plugin->name; - uint namelen= strlen(plugin_name), optnamelen; - uint buffer_length= namelen * 4 + (can_disable ? 75 : 10); - char *name= (char*) alloc_root(mem_root, buffer_length) + 1; - char *optname, *p; + const LEX_STRING plugin_dash = { C_STRING_WITH_LEN("plugin-") }; + uint plugin_name_len= strlen(plugin_name); + uint optnamelen; + const int max_comment_len= 180; + char *comment= (char *) alloc_root(mem_root, max_comment_len + 1); + char *optname; + int index= 0, offset= 0; st_mysql_sys_var *opt, **plugin_option; st_bookmark *v; + + /** Used to circumvent the const attribute on my_option::name */ + char *plugin_name_ptr, *plugin_name_with_prefix_ptr; + DBUG_ENTER("construct_options"); - DBUG_PRINT("plugin", ("plugin: '%s' enabled: %d can_disable: %d", - plugin_name, **enabled, can_disable)); + options[0].name= plugin_name_ptr= (char*) alloc_root(mem_root, + plugin_name_len + 1); + strcpy(plugin_name_ptr, plugin_name); + my_casedn_str(&my_charset_latin1, plugin_name_ptr); + convert_underscore_to_dash(plugin_name_ptr, plugin_name_len); /* support --skip-plugin-foo syntax */ - memcpy(name, plugin_name, namelen + 1); - my_casedn_str(&my_charset_latin1, name); - strxmov(name + namelen + 1, "plugin-", name, NullS); - /* Now we have namelen + 1 + 7 + namelen + 1 == namelen * 2 + 9. */ + options[1].name= plugin_name_with_prefix_ptr= (char*) alloc_root(mem_root, + plugin_name_len + + plugin_dash.length + 1); + strxmov(plugin_name_with_prefix_ptr, plugin_dash.str, options[0].name, NullS); - for (p= name + namelen*2 + 8; p > name; p--) - if (*p == '_') - *p= '-'; + options[0].id= options[1].id= 256; /* must be >255. dup id ok */ + options[0].var_type= options[1].var_type= GET_ENUM; + options[0].arg_type= options[1].arg_type= OPT_ARG; + options[0].def_value= options[1].def_value= 1; /* ON */ + options[0].typelib= options[1].typelib= &global_plugin_typelib; - if (can_disable) - { - strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. " - "Disable with --skip-", name," (will save memory).", NullS); - /* - Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 + - 20 + namelen + 20 + 1 == namelen * 4 + 67. - */ - - options[0].comment= name + namelen*2 + 10; - } + strxnmov(comment, max_comment_len, "Enable or disable ", plugin_name, + " plugin. Possible values are ON, OFF, FORCE (don't start " + "if the plugin fails to load).", NullS); + options[0].comment= comment; /* - NOTE: 'name' is one char above the allocated buffer! - NOTE: This code assumes that 'my_bool' and 'char' are of same size. + Allocate temporary space for the value of the tristate. + This option will have a limited lifetime and is not used beyond + server initialization. + GET_ENUM value is an integer. */ - *((my_bool *)(name -1))= **enabled; - *enabled= (my_bool *)(name - 1); + options[0].value= options[1].value= (uchar **)alloc_root(mem_root, + sizeof(int)); + *((uint*) options[0].value)= *((uint*) options[1].value)= + (uint) options[0].def_value; - - options[1].name= (options[0].name= name) + namelen + 1; - options[0].id= options[1].id= 256; /* must be >255. dup id ok */ - options[0].var_type= options[1].var_type= GET_BOOL; - options[0].arg_type= options[1].arg_type= NO_ARG; - options[0].def_value= options[1].def_value= **enabled; - options[0].value= options[0].u_max_value= - options[1].value= options[1].u_max_value= (uchar**) (name - 1); options+= 2; /* @@ -2955,7 +3000,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, opt= *plugin_option; if (!(opt->flags & PLUGIN_VAR_THDLOCAL)) continue; - if (!(register_var(name, opt->name, opt->flags))) + if (!(register_var(plugin_name_ptr, opt->name, opt->flags))) continue; switch (opt->flags & PLUGIN_VAR_TYPEMASK) { case PLUGIN_VAR_BOOL: @@ -3020,7 +3065,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, if (!opt->update) { opt->update= update_func_str; - if (!(opt->flags & PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)) + if (!(opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY))) { opt->flags|= PLUGIN_VAR_READONLY; sql_print_warning("Server variable %s of plugin %s was forced " @@ -3062,14 +3107,14 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, if (!(opt->flags & PLUGIN_VAR_THDLOCAL)) { optnamelen= strlen(opt->name); - optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2); - strxmov(optname, name, "-", opt->name, NullS); - optnamelen= namelen + optnamelen + 1; + optname= (char*) alloc_root(mem_root, plugin_name_len + optnamelen + 2); + strxmov(optname, plugin_name_ptr, "-", opt->name, NullS); + optnamelen= plugin_name_len + optnamelen + 1; } else { /* this should not fail because register_var should create entry */ - if (!(v= find_bookmark(name, opt->name, opt->flags))) + if (!(v= find_bookmark(plugin_name_ptr, opt->name, opt->flags))) { sql_print_error("Thread local variable '%s' not allocated " "in plugin '%s'.", opt->name, plugin_name); @@ -3085,10 +3130,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, (optnamelen= v->name_len) + 1); } - /* convert '_' to '-' */ - for (p= optname; *p; p++) - if (*p == '_') - *p= '-'; + convert_underscore_to_dash(optname, optnamelen); options->name= optname; options->comment= opt->comment; @@ -3103,10 +3145,13 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, else options->value= options->u_max_value= *(uchar***) (opt + 1); + char *option_name_ptr; options[1]= options[0]; - options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8); - options[1].comment= 0; // hidden - strxmov(p, "plugin-", optname, NullS); + options[1].name= option_name_ptr= (char*) alloc_root(mem_root, + plugin_dash.length + + optnamelen + 1); + options[1].comment= 0; /* Hidden from the help text */ + strxmov(option_name_ptr, plugin_dash.str, optname, NullS); options+= 2; } @@ -3120,55 +3165,57 @@ static my_option *construct_help_options(MEM_ROOT *mem_root, { st_mysql_sys_var **opt; my_option *opts; - my_bool dummy, can_disable; - my_bool *dummy2= &dummy; uint count= EXTRA_OPTIONS; DBUG_ENTER("construct_help_options"); - for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2); + for (opt= p->plugin->system_vars; opt && *opt; opt++, count+= 2) + ; if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count))) DBUG_RETURN(NULL); bzero(opts, sizeof(my_option) * count); - dummy= TRUE; /* plugin is enabled. */ - - can_disable= - my_strcasecmp(&my_charset_latin1, p->name.str, "MyISAM") && - my_strcasecmp(&my_charset_latin1, p->name.str, "MEMORY"); - - if (construct_options(mem_root, p, opts, &dummy2, can_disable)) + if (construct_options(mem_root, p, opts)) DBUG_RETURN(NULL); DBUG_RETURN(opts); } -/* - SYNOPSIS - test_plugin_options() - tmp_root temporary scratch space - plugin internal plugin structure - argc user supplied arguments - argv user supplied arguments - default_enabled default plugin enable status - RETURNS: - 0 SUCCESS - plugin should be enabled/loaded - NOTE: - Requires that a write-lock is held on LOCK_system_variables_hash +/** + Create and register system variables supplied from the plugin and + assigns initial values from corresponding command line arguments. + + @param tmp_root Temporary scratch space + @param[out] plugin Internal plugin structure + @param argc Number of command line arguments + @param argv Command line argument vector + + The plugin will be updated with a policy on how to handle errors during + initialization. + + @note Requires that a write-lock is held on LOCK_system_variables_hash + + @return How initialization of the plugin should be handled. + @retval 0 Initialization should proceed. + @retval 1 Plugin is disabled. + @retval -1 An error has occurred. */ + static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, - int *argc, char **argv, my_bool default_enabled) + int *argc, char **argv) { struct sys_var_chain chain= { NULL, NULL }; - my_bool enabled_saved= default_enabled, can_disable; - my_bool *enabled= &default_enabled; + my_bool can_disable; + bool disable_plugin; + enum_plugin_load_policy plugin_load_policy= PLUGIN_ON; + MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ? &tmp->mem_root : &plugin_mem_root; st_mysql_sys_var **opt; my_option *opts= NULL; - char *p, *varname; + char *varname; int error; st_mysql_sys_var *o; sys_var *v; @@ -3177,13 +3224,17 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, DBUG_ENTER("test_plugin_options"); DBUG_ASSERT(tmp->plugin && tmp->name.str); + /* + The 'federated' and 'ndbcluster' storage engines are always disabled by + default. + */ + if (!(my_strcasecmp(&my_charset_latin1, tmp->name.str, "federated") && + my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster"))) + plugin_load_policy= PLUGIN_OFF; + for (opt= tmp->plugin->system_vars; opt && *opt; opt++) count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */ - can_disable= - my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") && - my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY"); - if (count > EXTRA_OPTIONS || (*argc > 1)) { if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count))) @@ -3193,12 +3244,18 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, } bzero(opts, sizeof(my_option) * count); - if (construct_options(tmp_root, tmp, opts, &enabled, can_disable)) + if (construct_options(tmp_root, tmp, opts)) { sql_print_error("Bad options for plugin '%s'.", tmp->name.str); DBUG_RETURN(-1); } + /* + We adjust the default value to account for the hardcoded exceptions + we have set for the federated and ndbcluster storage engines. + */ + opts[0].def_value= opts[1].def_value= (int)plugin_load_policy; + error= handle_options(argc, &argv, opts, get_one_plugin_option); (*argc)++; /* add back one for the program name */ @@ -3208,64 +3265,79 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, tmp->name.str); goto err; } + /* + Set plugin loading policy from option value. First element in the option + list is always the option value. + */ + plugin_load_policy= (enum_plugin_load_policy)*(uint*)opts[0].value; } - if (!*enabled && !can_disable) + disable_plugin= (plugin_load_policy == PLUGIN_OFF); + /* + The 'MyISAM' and 'Memory' storage engines currently can't be disabled. + */ + can_disable= + my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") && + my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY"); + + tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE) || !can_disable; + + if (disable_plugin && !can_disable) { sql_print_warning("Plugin '%s' cannot be disabled", tmp->name.str); - *enabled= TRUE; + disable_plugin= FALSE; + } + + /* + If the plugin is disabled it should not be initialized. + */ + if (disable_plugin) + { + if (global_system_variables.log_warnings) + sql_print_information("Plugin '%s' is disabled.", + tmp->name.str); + if (opts) + my_cleanup_options(opts); + DBUG_RETURN(1); } error= 1; - - if (*enabled) + for (opt= tmp->plugin->system_vars; opt && *opt; opt++) { - for (opt= tmp->plugin->system_vars; opt && *opt; opt++) + if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR)) + continue; + if ((var= find_bookmark(tmp->name.str, o->name, o->flags))) + v= new (mem_root) sys_var_pluginvar(var->key + 1, o); + else { - if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR)) - continue; - - if ((var= find_bookmark(tmp->name.str, o->name, o->flags))) - v= new (mem_root) sys_var_pluginvar(var->key + 1, o); - else - { - len= tmp->name.length + strlen(o->name) + 2; - varname= (char*) alloc_root(mem_root, len); - strxmov(varname, tmp->name.str, "-", o->name, NullS); - my_casedn_str(&my_charset_latin1, varname); - - for (p= varname; *p; p++) - if (*p == '-') - *p= '_'; - - v= new (mem_root) sys_var_pluginvar(varname, o); - } - DBUG_ASSERT(v); /* check that an object was actually constructed */ - - /* - Add to the chain of variables. - Done like this for easier debugging so that the - pointer to v is not lost on optimized builds. - */ - v->chain_sys_var(&chain); + len= tmp->name.length + strlen(o->name) + 2; + varname= (char*) alloc_root(mem_root, len); + strxmov(varname, tmp->name.str, "-", o->name, NullS); + my_casedn_str(&my_charset_latin1, varname); + convert_dash_to_underscore(varname, len); + v= new (mem_root) sys_var_pluginvar(varname, o); } - if (chain.first) + DBUG_ASSERT(v); /* check that an object was actually constructed */ + /* + Add to the chain of variables. + Done like this for easier debugging so that the + pointer to v is not lost on optimized builds. + */ + v->chain_sys_var(&chain); + } /* end for */ + if (chain.first) + { + chain.last->next = NULL; + if (mysql_add_sys_var_chain(chain.first, NULL)) { - chain.last->next = NULL; - if (mysql_add_sys_var_chain(chain.first, NULL)) - { - sql_print_error("Plugin '%s' has conflicting system variables", - tmp->name.str); - goto err; - } - tmp->system_vars= chain.first; + sql_print_error("Plugin '%s' has conflicting system variables", + tmp->name.str); + goto err; } - DBUG_RETURN(0); + tmp->system_vars= chain.first; } - - if (enabled_saved && global_system_variables.log_warnings) - sql_print_information("Plugin '%s' disabled by command line option", - tmp->name.str); + DBUG_RETURN(0); + err: if (opts) my_cleanup_options(opts); diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 8ae38d58845..004d0d5abb7 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -79,6 +79,7 @@ struct st_plugin_int void *data; /* plugin type specific, e.g. handlerton */ MEM_ROOT mem_root; /* memory for dynamic plugin structures */ sys_var *system_vars; /* server variables for this plugin */ + bool is_mandatory; /* If true then plugin must not fail to load */ }; From fc57b4cfb569635edc1613154d9b7ed14efaf840 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 15 May 2009 12:03:34 +0500 Subject: [PATCH 079/115] Bug#43612 crash with explain extended, union, order by In UNION if we use last SELECT without braces and this SELECT have ORDER BY clause, such clause belongs to global UNION. It is parsed like last SELECT part and used further as 'unit->global_parameters->order_list' value. During DESCRIBE EXTENDED we call select_lex->print_order() for last SELECT where order fields refer to tmp table which already freed. It leads to crash. The fix is clean up global_parameters->order_list instead of fake_select_lex->order_list. mysql-test/r/union.result: test result mysql-test/t/union.test: test case sql/sql_union.cc: In UNION if we use last SELECT without braces and this SELECT have ORDER BY clause, such clause belongs to global UNION. It is parsed like last SELECT part and used further as 'unit->global_parameters->order_list' value. During DESCRIBE EXTENDED we call select_lex->print_order() for last SELECT where order fields refer to tmp table which already freed. It leads to crash. The fix is clean up global_parameters->order_list instead of fake_select_lex->order_list. --- mysql-test/r/union.result | 13 +++++++++++++ mysql-test/t/union.test | 12 ++++++++++++ sql/sql_union.cc | 16 ++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index a5f49eef8d1..e806ed49c34 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1518,4 +1518,17 @@ SHOW FIELDS FROM t2; Field Type Null Key Default Extra d double(9,6) YES NULL DROP TABLE t1, t2; +CREATE TABLE t1(a INT); +EXPLAIN EXTENDED +SELECT a FROM t1 +UNION +SELECT a FROM t1 +ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 UNION t1 system NULL NULL NULL NULL 0 const row not found +NULL UNION RESULT ALL NULL NULL NULL NULL NULL Using filesort +Warnings: +Note 1003 select '0' AS `a` from `test`.`t1` union select '0' AS `a` from `test`.`t1` order by `a` +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 1dbbdae24b7..0c8e025e54e 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -1038,4 +1038,16 @@ CREATE TABLE t2 AS SELECT d FROM t1 UNION SELECT d FROM t1; SHOW FIELDS FROM t2; DROP TABLE t1, t2; +# +# Bug#43612 crash with explain extended, union, order by +# +CREATE TABLE t1(a INT); +EXPLAIN EXTENDED +SELECT a FROM t1 +UNION +SELECT a FROM t1 +ORDER BY a; +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 2875aefbd97..fca5c205610 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -653,10 +653,22 @@ bool st_select_lex_unit::cleanup() join->tables= 0; } error|= fake_select_lex->cleanup(); - if (fake_select_lex->order_list.elements) + /* + There are two cases when we should clean order items: + 1. UNION with SELECTs which all enclosed into braces + in this case global_parameters == fake_select_lex + 2. UNION where last SELECT is not enclosed into braces + in this case global_parameters == 'last select' + So we should use global_parameters->order_list for + proper order list clean up. + Note: global_parameters and fake_select_lex are always + initialized for UNION + */ + DBUG_ASSERT(global_parameters); + if (global_parameters->order_list.elements) { ORDER *ord; - for (ord= (ORDER*)fake_select_lex->order_list.first; ord; ord= ord->next) + for (ord= (ORDER*)global_parameters->order_list.first; ord; ord= ord->next) (*ord->item)->cleanup(); } } From 22e840d70700cd1aceec27d6aee3883203a5a566 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Fri, 15 May 2009 12:16:00 +0400 Subject: [PATCH 080/115] Bug #44792: valgrind warning when casting from time to time Field_time::get_time() did not initialize some members of MYSQL_TIME which led to valgrind warnings when those members were accessed in Protocol_simple::store_time(). It is unlikely that this bug could result in wrong data being returned, since Field_time::get_time() initializes the 'day' member of MYSQL_TIME to 0, so the value of 'day' in Protocol_simple::store_time() would be 0 regardless of the values for 'year' and 'month'. mysql-test/r/type_time.result: Added a test case for bug #44792. mysql-test/t/type_time.test: Added a test case for bug #44792. sql/field.cc: Field_time::get_time() did not initialize some members of MYSQL_TIME which led to valgrind warnings when those members were accessed in Protocol_simple::store_time(). --- mysql-test/r/type_time.result | 10 ++++++++++ mysql-test/t/type_time.test | 13 +++++++++++++ sql/field.cc | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index 96bf23109df..69dca57398f 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -128,3 +128,13 @@ SELECT sum(f3) FROM t1 where f2='2007-07-01 00:00:00' group by f2; sum(f3) 3 drop table t1; +# +# Bug #44792: valgrind warning when casting from time to time +# +CREATE TABLE t1 (c TIME); +INSERT INTO t1 VALUES ('0:00:00'); +SELECT CAST(c AS TIME) FROM t1; +CAST(c AS TIME) +00:00:00 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test index 5fc763be7fe..5bb521601e5 100644 --- a/mysql-test/t/type_time.test +++ b/mysql-test/t/type_time.test @@ -77,3 +77,16 @@ insert into t1 values('2007-07-02', 1); insert into t1 values('2007-07-02', 2); SELECT sum(f3) FROM t1 where f2='2007-07-01 00:00:00' group by f2; drop table t1; + + +--echo # +--echo # Bug #44792: valgrind warning when casting from time to time +--echo # + +CREATE TABLE t1 (c TIME); +INSERT INTO t1 VALUES ('0:00:00'); +SELECT CAST(c AS TIME) FROM t1; +DROP TABLE t1; + + +--echo End of 5.0 tests diff --git a/sql/field.cc b/sql/field.cc index 99e9d7803e1..c7dd2afd934 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4877,7 +4877,7 @@ bool Field_time::get_time(MYSQL_TIME *ltime) ltime->neg= 1; tmp=-tmp; } - ltime->day= 0; + ltime->year= ltime->month= ltime->day= 0; ltime->hour= (int) (tmp/10000); tmp-=ltime->hour*10000; ltime->minute= (int) tmp/100; From f4eb0953b1367471e808263a699d6a20ea842b3e Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Fri, 15 May 2009 11:59:31 +0200 Subject: [PATCH 081/115] Fix for Bug#44826 main.information_schema_db could harm succeeding tests Details: 1. Add missing "disconnect " 2. Take care that the disconnects are finished when the test terminates 3. Replace error names by error numbers 4. Minor beautifying of script code --- mysql-test/r/information_schema_db.result | 8 ++--- mysql-test/t/information_schema_db.test | 44 ++++++++++++++--------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index 67c9921e1ca..e7f16138aa4 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -49,7 +49,7 @@ begin select table_name from information_schema.key_column_usage order by table_name; end| -create table t1 +create table t1 (f1 int(10) unsigned not null, f2 varchar(100) not null, primary key (f1), unique key (f2)); @@ -191,15 +191,15 @@ View Create View v2 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_2`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `v1`.`f1` AS `f1` from `testdb_1`.`v1` show create view testdb_1.v1; ERROR 42000: SHOW VIEW command denied to user 'testdb_2'@'localhost' for table 'v1' -select table_name from information_schema.columns a +select table_name from information_schema.columns a where a.table_name = 'v2'; table_name v2 -select view_definition from information_schema.views a +select view_definition from information_schema.views a where a.table_name = 'v2'; view_definition /* ALGORITHM=UNDEFINED */ select `v1`.`f1` AS `f1` from `testdb_1`.`v1` -select view_definition from information_schema.views a +select view_definition from information_schema.views a where a.table_name = 'testdb_1.v1'; view_definition select * from v2; diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test index 6353e94fd51..0ff1d05f364 100644 --- a/mysql-test/t/information_schema_db.test +++ b/mysql-test/t/information_schema_db.test @@ -53,7 +53,7 @@ order by table_name; end| delimiter ;| -create table t1 +create table t1 (f1 int(10) unsigned not null, f2 varchar(100) not null, primary key (f1), unique key (f2)); @@ -105,8 +105,8 @@ drop function f2; drop view v1, v2; # -# Bug#20543: select on information_schema strange warnings, view, different -# schemas/users +# Bug#20543 select on information_schema strange warnings, view, different +# schemas/users # # create database testdb_1; @@ -125,7 +125,7 @@ grant insert on v1 to testdb_2@localhost; create view v5 as select f1 from t1; grant show view on v5 to testdb_2@localhost; ---error 1227 +--error ER_SPECIFIC_ACCESS_DENIED_ERROR create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1; connection default; @@ -169,46 +169,53 @@ use testdb_1; revoke show view on v6 from testdb_2@localhost; connection testdb_2; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show fields from testdb_1.v5; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show create view testdb_1.v5; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show fields from testdb_1.v6; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show create view testdb_1.v6; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show fields from testdb_1.v7; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show create view testdb_1.v7; ---error 1345 +--error ER_VIEW_NO_EXPLAIN show create view v4; -#--error 1345 +#--error ER_VIEW_NO_EXPLAIN show fields from v4; show fields from v2; show fields from testdb_1.v1; show create view v2; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show create view testdb_1.v1; -select table_name from information_schema.columns a +select table_name from information_schema.columns a where a.table_name = 'v2'; -select view_definition from information_schema.views a +select view_definition from information_schema.views a where a.table_name = 'v2'; -select view_definition from information_schema.views a +select view_definition from information_schema.views a where a.table_name = 'testdb_1.v1'; ---error 1356 +--error ER_VIEW_INVALID select * from v2; connection default; use test; drop view testdb_1.v1, v2, testdb_1.v3, v4; drop database testdb_1; +connection testdb_1; +disconnect testdb_1; +--source include/wait_until_disconnected.inc +connection testdb_2; +disconnect testdb_2; +--source include/wait_until_disconnected.inc +connection default; drop user testdb_1@localhost; drop user testdb_2@localhost; @@ -239,4 +246,7 @@ show create view testdb_1.v1; connection default; drop user mysqltest_1@localhost; drop database testdb_1; +connection user1; disconnect user1; +--source include/wait_until_disconnected.inc +connection default; From 8e72b44969fdd42e4e8dd5c61bbfdaab68075c57 Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Fri, 15 May 2009 13:06:11 +0300 Subject: [PATCH 082/115] Bug #32651 grant_cache.test fails It turns out that this test case no longer fails with the discrepancy in numbers that was the original cause for disabling this test (and showed potential genuine issues with the query cache). Therefore this test is being enabled after some minor adjustment of error codes and messages. --- mysql-test/r/grant_cache.result | 2 +- mysql-test/t/disabled.def | 1 - mysql-test/t/grant_cache.test | 12 ++++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result index 925a5918c1b..b56ad6dea2a 100644 --- a/mysql-test/r/grant_cache.result +++ b/mysql-test/r/grant_cache.result @@ -149,7 +149,7 @@ select "user3"; user3 user3 select * from t1; -ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'b' in table 't1' +ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't1' select a from t1; a 1 diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 49f422af298..e9de29e2c27 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -16,7 +16,6 @@ im_daemon_life_cycle : Bug#20294: Instance manager tests fail randomly im_options_set : Bug#20294: Instance manager tests fail randomly im_options_unset : Bug#20294: Instance manager tests fail randomly im_utils : Bug#20294: Instance manager tests fail randomly -grant_cache : Bug#32651: grant_cache.test fails ndb_backup_print : Bug#32357: ndb_backup_print test fails sometimes in pushbuild rpl_log_pos : Bug#8693 Test 'rpl_log_pos' fails sometimes kill : Bug#29149 Test "kill" fails on Windows diff --git a/mysql-test/t/grant_cache.test b/mysql-test/t/grant_cache.test index c2e31621744..616a2746148 100644 --- a/mysql-test/t/grant_cache.test +++ b/mysql-test/t/grant_cache.test @@ -88,7 +88,7 @@ select a from t1; select c from t1; select * from mysqltest.t1,test.t1; --replace_result 127.0.0.1 localhost ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR select * from t2; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; @@ -99,17 +99,17 @@ connect (user3,localhost,mysqltest_3,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK); connection user3; select "user3"; --replace_result 127.0.0.1 localhost ---error 1143 +--error ER_TABLEACCESS_DENIED_ERROR select * from t1; select a from t1; --replace_result 127.0.0.1 localhost ---error 1143 +--error ER_COLUMNACCESS_DENIED_ERROR select c from t1; --replace_result 127.0.0.1 localhost ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR select * from t2; --replace_result 127.0.0.1 localhost ---error 1143 +--error ER_COLUMNACCESS_DENIED_ERROR select mysqltest.t1.c from test.t1,mysqltest.t1; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; @@ -120,7 +120,7 @@ connect (user4,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,$MASTER_MYSOCK); connection user4; select "user4"; show grants; ---error 1046 +--error ER_NO_DB_ERROR select a from t1; # The following query is not cached before (different database) select * from mysqltest.t1,test.t1; From 21f878e7243346efa9e8ae41400528a8d5cb76cb Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Fri, 15 May 2009 12:15:56 +0200 Subject: [PATCH 083/115] Fix for Bug#42308 Several server tests do not pass MTR's --check option Details: Most tests mentioned within the bug report were already fixed. The test modified here failed in stability (high parallel load) tests. Details: 1. Take care that disconnects are finished before the test terminates. 2. Correct wrong handling of send/reap in events_stress which caused random garbled output 3. Minor beautifying of script code --- mysql-test/include/concurrent.inc | 11 +++++++--- mysql-test/include/grant_cache.inc | 19 +++++++++++++++-- mysql-test/include/handler.inc | 1 + mysql-test/include/query_cache.inc | 3 ++- mysql-test/r/concurrent_innodb_safelog.result | 2 ++ .../r/concurrent_innodb_unsafelog.result | 2 ++ mysql-test/r/ddl_i18n_koi8r.result | 10 ++++++--- mysql-test/r/ddl_i18n_utf8.result | 10 ++++++--- mysql-test/r/events_stress.result | 1 + mysql-test/r/grant_cache_no_prot.result | 3 ++- mysql-test/r/grant_cache_ps_prot.result | 3 ++- mysql-test/t/archive_bitfield.test | 6 ++++++ mysql-test/t/client_xml.test | 9 ++++++++ mysql-test/t/csv.test | 3 ++- mysql-test/t/ddl_i18n_koi8r.test | 21 ++++++++++++------- mysql-test/t/ddl_i18n_utf8.test | 21 ++++++++++++------- mysql-test/t/derived.test | 2 ++ mysql-test/t/drop.test | 5 ++++- mysql-test/t/events_grant.test | 7 +++---- mysql-test/t/events_stress.test | 6 +++++- mysql-test/t/events_trans_notembedded.test | 1 + mysql-test/t/fix_priv_tables.test | 5 +++++ mysql-test/t/flush.test | 1 + mysql-test/t/func_compress.test | 1 + mysql-test/t/lowercase_fs_off.test | 6 ++++-- 25 files changed, 122 insertions(+), 37 deletions(-) diff --git a/mysql-test/include/concurrent.inc b/mysql-test/include/concurrent.inc index 2180ec4cc9c..66f8a65a102 100644 --- a/mysql-test/include/concurrent.inc +++ b/mysql-test/include/concurrent.inc @@ -659,11 +659,16 @@ drop table t1; connection thread1; select * from t1; +--echo ** Cleanup +connection thread1; +disconnect thread1; +--source include/wait_until_disconnected.inc +--echo ** connection thread2 +connection thread2; +disconnect thread2; +--source include/wait_until_disconnected.inc --echo ** connection default connection default; drop table t1; drop user mysqltest@localhost; -disconnect thread1; -disconnect thread2; - diff --git a/mysql-test/include/grant_cache.inc b/mysql-test/include/grant_cache.inc index 501e115f0ee..47eef1cdb67 100644 --- a/mysql-test/include/grant_cache.inc +++ b/mysql-test/include/grant_cache.inc @@ -171,15 +171,30 @@ show status like "Qcache_not_cached"; # Cleanup ---echo ----- switch to connection default and close connections ----- -connection default; +--echo ----- close connections ----- +connection root; disconnect root; +--source include/wait_until_disconnected.inc +connection root2; disconnect root2; +--source include/wait_until_disconnected.inc +connection user1; disconnect user1; +--source include/wait_until_disconnected.inc +connection user2; disconnect user2; +--source include/wait_until_disconnected.inc +connection user3; disconnect user3; +--source include/wait_until_disconnected.inc +connection user4; disconnect user4; +--source include/wait_until_disconnected.inc +connection unkuser; disconnect unkuser; +--source include/wait_until_disconnected.inc +--echo ----- switch to connection default ----- +connection default; # # A temporary 4.1 workaround to make this test pass if diff --git a/mysql-test/include/handler.inc b/mysql-test/include/handler.inc index 96f90aba8e0..6e7f53ba9b2 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/include/handler.inc @@ -719,6 +719,7 @@ connection con1; --reap drop table t1; disconnect con1; +--source include/wait_until_disconnected.inc connection default; # diff --git a/mysql-test/include/query_cache.inc b/mysql-test/include/query_cache.inc index 77ea0021a5d..7ce97b42158 100644 --- a/mysql-test/include/query_cache.inc +++ b/mysql-test/include/query_cache.inc @@ -177,6 +177,7 @@ show status like "Qcache_hits"; # Final cleanup eval set GLOBAL query_cache_size=$save_query_cache_size; +disconnect connection1; +--source include/wait_until_disconnected.inc connection default; drop table t2; -disconnect connection1; diff --git a/mysql-test/r/concurrent_innodb_safelog.result b/mysql-test/r/concurrent_innodb_safelog.result index e6adaac1068..24a84afb9ce 100644 --- a/mysql-test/r/concurrent_innodb_safelog.result +++ b/mysql-test/r/concurrent_innodb_safelog.result @@ -785,6 +785,8 @@ eta tipo c 70 1 iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii 80 22 jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj 90 11 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk +** Cleanup +** connection thread2 ** connection default drop table t1; drop user mysqltest@localhost; diff --git a/mysql-test/r/concurrent_innodb_unsafelog.result b/mysql-test/r/concurrent_innodb_unsafelog.result index e9c53d4cfa0..35fc2d89cfe 100644 --- a/mysql-test/r/concurrent_innodb_unsafelog.result +++ b/mysql-test/r/concurrent_innodb_unsafelog.result @@ -781,6 +781,8 @@ eta tipo c 70 1 iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii 80 1 jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj 90 11 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk +** Cleanup +** connection thread2 ** connection default drop table t1; drop user mysqltest@localhost; diff --git a/mysql-test/r/ddl_i18n_koi8r.result b/mysql-test/r/ddl_i18n_koi8r.result index af3a0899181..fe24c17a1c5 100644 --- a/mysql-test/r/ddl_i18n_koi8r.result +++ b/mysql-test/r/ddl_i18n_koi8r.result @@ -2829,7 +2829,11 @@ t2 CREATE TABLE `t2` ( `col1` varchar(10) COLLATE cp1251_general_cs DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_general_cs +---> connection: con2 + +---> connection: con3 + ---> connection: default -use test| -DROP DATABASE mysqltest1| -DROP DATABASE mysqltest2| +USE test; +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; diff --git a/mysql-test/r/ddl_i18n_utf8.result b/mysql-test/r/ddl_i18n_utf8.result index 10c2afcadc1..cf4272bf90c 100644 --- a/mysql-test/r/ddl_i18n_utf8.result +++ b/mysql-test/r/ddl_i18n_utf8.result @@ -2829,7 +2829,11 @@ t2 CREATE TABLE `t2` ( `col1` varchar(10) COLLATE cp1251_general_cs DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_general_cs +---> connection: con2 + +---> connection: con3 + ---> connection: default -use test| -DROP DATABASE mysqltest1| -DROP DATABASE mysqltest2| +USE test; +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; diff --git a/mysql-test/r/events_stress.result b/mysql-test/r/events_stress.result index 17eb32b36b7..9b9f3caaff6 100644 --- a/mysql-test/r/events_stress.result +++ b/mysql-test/r/events_stress.result @@ -63,3 +63,4 @@ DROP TABLE fill_it1; DROP TABLE fill_it2; DROP TABLE fill_it3; DROP DATABASE events_test; +SET GLOBAL event_scheduler=off; diff --git a/mysql-test/r/grant_cache_no_prot.result b/mysql-test/r/grant_cache_no_prot.result index cb9acaf540d..32bb9cce90e 100644 --- a/mysql-test/r/grant_cache_no_prot.result +++ b/mysql-test/r/grant_cache_no_prot.result @@ -206,7 +206,8 @@ Qcache_hits 8 show status like "Qcache_not_cached"; Variable_name Value Qcache_not_cached 8 ------ switch to connection default and close connections ----- +----- close connections ----- +----- switch to connection default ----- set names binary; delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); diff --git a/mysql-test/r/grant_cache_ps_prot.result b/mysql-test/r/grant_cache_ps_prot.result index cf1450f3b75..281468ee2e1 100644 --- a/mysql-test/r/grant_cache_ps_prot.result +++ b/mysql-test/r/grant_cache_ps_prot.result @@ -206,7 +206,8 @@ Qcache_hits 8 show status like "Qcache_not_cached"; Variable_name Value Qcache_not_cached 5 ------ switch to connection default and close connections ----- +----- close connections ----- +----- switch to connection default ----- set names binary; delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); diff --git a/mysql-test/t/archive_bitfield.test b/mysql-test/t/archive_bitfield.test index 1e4692270b5..2e90ce39708 100644 --- a/mysql-test/t/archive_bitfield.test +++ b/mysql-test/t/archive_bitfield.test @@ -94,5 +94,11 @@ INSERT INTO `t1` VALUES (NULL,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'100000',b'010010',b'011111',4,5,5,5,5,5,5,5,5,5,3,2,1), (NULL,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'001100',b'111111',4,5,5,5,5,5,5,5,5,5,3,2,1), (NULL,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1); +# Determine the number of open sessions +--source include/count_sessions.inc --exec $MYSQL_DUMP --hex-blob --compact --order-by-primary --skip-extended-insert --no-create-info test t1 drop table t1; +# Wait till the number of open sessions is <= the number before the run with $MYSQL_DUMP +# = The session caused by mysqldump has finished its disconnect +--source include/wait_until_count_sessions.inc + diff --git a/mysql-test/t/client_xml.test b/mysql-test/t/client_xml.test index 739b56f5ab1..0847e2b366b 100644 --- a/mysql-test/t/client_xml.test +++ b/mysql-test/t/client_xml.test @@ -18,6 +18,10 @@ create table t1 ( `a>b` text ); insert into t1 values (1, 2, 'a&b ab'); + +# Determine the number of open sessions +--source include/count_sessions.inc + --exec $MYSQL --xml test -e "select * from t1" --exec $MYSQL_DUMP --xml --skip-create test @@ -33,3 +37,8 @@ drop table t1; # Restore global concurrent_insert value set @@global.concurrent_insert= @old_concurrent_insert; + +# Wait till the number of open sessions is <= the number before the runs with +# $MYSQL and $MYSQL_DUMP +# = The session caused by mysql and mysqldump have finished their disconnect +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index abc161d014c..cdf274190dd 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1800,10 +1800,11 @@ connect (con1,localhost,root,,); # EE_FILENOTFOUND 29 --error 29 select * from t1; +--disconnect con1 +--source include/wait_until_disconnected.inc connection default; unlock tables; drop table t1; ---disconnect con1 # # Bug#41441 repair csv table crashes debug server diff --git a/mysql-test/t/ddl_i18n_koi8r.test b/mysql-test/t/ddl_i18n_koi8r.test index 2d94a899aad..fecef2f95d5 100644 --- a/mysql-test/t/ddl_i18n_koi8r.test +++ b/mysql-test/t/ddl_i18n_koi8r.test @@ -1128,15 +1128,22 @@ SHOW CREATE TABLE mysqltest2.t2| # # Cleanup. # +delimiter ;| +--connection con2 +--echo +--echo ---> connection: con2 +--disconnect con2 +--source include/wait_until_disconnected.inc +--connection con3 +--echo +--echo ---> connection: con3 +--disconnect con3 +--source include/wait_until_disconnected.inc --connection default --echo --echo ---> connection: default +USE test; +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; ---disconnect con2 ---disconnect con3 - -use test| - -DROP DATABASE mysqltest1| -DROP DATABASE mysqltest2| diff --git a/mysql-test/t/ddl_i18n_utf8.test b/mysql-test/t/ddl_i18n_utf8.test index 1d5415d9373..8788d0604f2 100644 --- a/mysql-test/t/ddl_i18n_utf8.test +++ b/mysql-test/t/ddl_i18n_utf8.test @@ -1128,15 +1128,22 @@ SHOW CREATE TABLE mysqltest2.t2| # # Cleanup. # +delimiter ;| +--connection con2 +--echo +--echo ---> connection: con2 +--disconnect con2 +--source include/wait_until_disconnected.inc +--connection con3 +--echo +--echo ---> connection: con3 +--disconnect con3 +--source include/wait_until_disconnected.inc --connection default --echo --echo ---> connection: default +USE test; +DROP DATABASE mysqltest1; +DROP DATABASE mysqltest2; ---disconnect con2 ---disconnect con3 - -use test| - -DROP DATABASE mysqltest1| -DROP DATABASE mysqltest2| diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 4e79fac584f..bf5cd4aa8d8 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -273,7 +273,9 @@ select t2.* from ((select * from t1) as A inner join t2 on A.ID = t2.FID); select t2.* from (select * from t1) as A inner join t2 on A.ID = t2.FID; drop table t1, t2; +connection con1; disconnect con1; +--source include/wait_until_disconnected.inc connection default; drop user mysqltest_1; diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test index 91345886e93..bb4dd3e11f9 100644 --- a/mysql-test/t/drop.test +++ b/mysql-test/t/drop.test @@ -117,8 +117,11 @@ connection addconroot1; --reap connection addconroot2; --reap -disconnect addconroot1; disconnect addconroot2; +--source include/wait_until_disconnected.inc +connection addconroot1; +disconnect addconroot1; +--source include/wait_until_disconnected.inc connection default; --echo End of 5.0 tests diff --git a/mysql-test/t/events_grant.test b/mysql-test/t/events_grant.test index cff2475c5aa..8db4333cc03 100644 --- a/mysql-test/t/events_grant.test +++ b/mysql-test/t/events_grant.test @@ -97,7 +97,9 @@ DROP EVENT one_event; connection default; --echo "One event should not be there" SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; +connection ev_con1; disconnect ev_con1; +--source include/wait_until_disconnected.inc connection default; DROP USER ev_test@localhost; DROP DATABASE events_test2; @@ -106,9 +108,6 @@ DROP DATABASE events_test2; # End of tests # -let $wait_condition= - select count(*) = 0 from information_schema.processlist - where db='events_test' and command = 'Connect' and user=current_user(); ---source include/wait_condition.inc +--source include/check_events_off.inc DROP DATABASE events_test; diff --git a/mysql-test/t/events_stress.test b/mysql-test/t/events_stress.test index 22959898b43..e51fa734256 100644 --- a/mysql-test/t/events_stress.test +++ b/mysql-test/t/events_stress.test @@ -109,7 +109,7 @@ connection conn3; --send DROP DATABASE events_conn3_db; connection default; ---send +# --send DROP DATABASE events_conn1_test2; DROP DATABASE events_conn1_test3; SET GLOBAL event_scheduler=off; @@ -135,3 +135,7 @@ DROP USER event_user3@localhost; # DROP DATABASE events_test; + +# Cleanup +SET GLOBAL event_scheduler=off; +--source include/check_events_off.inc diff --git a/mysql-test/t/events_trans_notembedded.test b/mysql-test/t/events_trans_notembedded.test index 3c151dd18b1..0353d183386 100644 --- a/mysql-test/t/events_trans_notembedded.test +++ b/mysql-test/t/events_trans_notembedded.test @@ -50,6 +50,7 @@ delete from t1; commit work; # Cleanup disconnect conn1; +--source include/wait_until_disconnected.inc connection default; drop user mysqltest_user1@localhost; drop database mysqltest_db2; diff --git a/mysql-test/t/fix_priv_tables.test b/mysql-test/t/fix_priv_tables.test index c7cd500f8d2..eeda9bc8d15 100644 --- a/mysql-test/t/fix_priv_tables.test +++ b/mysql-test/t/fix_priv_tables.test @@ -51,8 +51,13 @@ echo; -- disable_query_log # Run the mysql_fix_privilege_tables.sql using "mysql --force" +# Determine the number of open sessions +--source include/count_sessions.inc --exec $MYSQL --force mysql < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/tmp/fix_priv_tables.log 2>&1 --remove_file $MYSQLTEST_VARDIR/tmp/fix_priv_tables.log +# Wait till the number of open sessions is <= the number before the run with $MYSQL +# = The session caused by mysql has finished its disconnect +--source include/wait_until_count_sessions.inc -- enable_query_log -- enable_result_log diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test index c832cb79158..f27d4cf2fad 100644 --- a/mysql-test/t/flush.test +++ b/mysql-test/t/flush.test @@ -171,6 +171,7 @@ set session low_priority_updates=default; connect (con1,localhost,root,,); send select benchmark(200, (select sin(1))) > 1000; disconnect con1; +--source include/wait_until_disconnected.inc connection default; --echo End of 5.0 tests diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test index 0a3a3823fee..4c5121da345 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -50,6 +50,7 @@ set @@global.max_allowed_packet=1048576*100; --connect (newconn, localhost, root,,) eval select compress(repeat('aaaaaaaaaa', IF('$LOW_MEMORY', 10, 10000000))) is null; disconnect newconn; +--source include/wait_until_disconnected.inc connection default; set @@global.max_allowed_packet=default; diff --git a/mysql-test/t/lowercase_fs_off.test b/mysql-test/t/lowercase_fs_off.test index 414027cb485..878564c32ab 100644 --- a/mysql-test/t/lowercase_fs_off.test +++ b/mysql-test/t/lowercase_fs_off.test @@ -14,16 +14,18 @@ flush privileges; connect (sample,localhost,sample,password,d1); connection sample; select database(); ---error 1044 +--error ER_DBACCESS_DENIED_ERROR create database d2; ---error 1044 +--error ER_DBACCESS_DENIED_ERROR create database D1; disconnect sample; +--source include/wait_until_disconnected.inc connection master; drop user 'sample'@'localhost'; drop database if exists d1; disconnect master; +--source include/wait_until_disconnected.inc connection default; # End of 4.1 tests From 793bf595367ce43eef9d054f3107f848326e6e95 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 15 May 2009 16:11:27 +0300 Subject: [PATCH 084/115] fixed a win32 compile error --- sql/sql_profile.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 551a103da10..8dde9fbf871 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -552,8 +552,9 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) The order of these fields is set by the query_profile_statistics_info array. */ - table->field[0]->store((ulonglong) query->profiling_query_id); - table->field[1]->store((ulonglong) seq); /* the step in the sequence */ + table->field[0]->store((longlong) query->profiling_query_id, TRUE); + /* the step in the sequence */ + table->field[1]->store((longlong) seq, TRUE); /* This entry, n, has a point in time, T(n), and a status phrase, S(n). The status phrase S(n) describes the period of time that begins at From df41cc207e7633d0184d481eeeeba0b52623049c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 15 May 2009 16:13:54 +0300 Subject: [PATCH 085/115] backported a change from 5.1 --- sql/sql_profile.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 8dde9fbf871..f87f92471a3 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -552,9 +552,9 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) The order of these fields is set by the query_profile_statistics_info array. */ - table->field[0]->store((longlong) query->profiling_query_id, TRUE); + table->field[0]->store((ulonglong) query->profiling_query_id, TRUE); /* the step in the sequence */ - table->field[1]->store((longlong) seq, TRUE); + table->field[1]->store((ulonglong) seq, TRUE); /* This entry, n, has a point in time, T(n), and a status phrase, S(n). The status phrase S(n) describes the period of time that begins at From e640fa18c4d75becffc00e7989ecb1df63d90df7 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 15 May 2009 16:40:09 +0300 Subject: [PATCH 086/115] fixed a compile warning in 5.1-bugteam --- sql/sql_parse.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7bfac84c0e6..8f1d3842245 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -195,7 +195,6 @@ bool begin_trans(THD *thd) error= -1; else { - LEX *lex= thd->lex; thd->options|= OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; } From 793d8e1820acc264088ff55884c75510c7ec21f7 Mon Sep 17 00:00:00 2001 From: Jim Winstead Date: Fri, 15 May 2009 10:36:59 -0700 Subject: [PATCH 087/115] Fix syntax in test to eliminate failure on Windows. --- mysql-test/t/mysql.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 1054d1cbe0a..ba5cc243c01 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -377,7 +377,7 @@ drop tables t1, t2; # # Bug #27884: mysql --html does not quote HTML special characters in output # ---exec $MYSQL --html test -e "select '< & >' as \`<\`" +--exec $MYSQL --html test -e "select '< & >' as '<'" --echo --echo End of tests From a8df3d3c90606b05b7655705517712c2cd418632 Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Sun, 17 May 2009 21:55:23 +0530 Subject: [PATCH 088/115] Bug#44610 RCDFMT clause requested when creating DB2 table In order to better support the usage of IBMDB2I tables from within RPG programs, the storage engine should ensure that the RCDFMT name is consistent and predictable for DB2 tables. This patch appends a "RCDFMT " clause to the CREATE TABLE statement that is passed to DB2. is generated from the original name of the table itself. This ensures a consistent and deterministic mapping from the original table. For the sake of simplicity only the alpha-numeric characters are preserved when generating the new name, and these are upper-cased; other characters are replaced with an underscore (_). Following DB2 system identifier rules, the name always begins with an alpha-character and has a maximum of ten characters. If no usable characters are found in the table name, the name X is used. mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result: Bug#44610 RCDFMT clause requested when creating DB2 table Result file for the test case. mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test: Bug#44610 RCDFMT clause requested when creating DB2 table Test case that confirms that the names that are being generated are valid. storage/ibmdb2i/ha_ibmdb2i.cc: Bug#44610 RCDFMT clause requested when creating DB2 table This patch appends a "RCDFMT " clause to the CREATE TABLE statement that is passed to DB2. is generated from the original name of the table itself. This ensures a consistent and deterministic mapping from the original table. storage/ibmdb2i/ha_ibmdb2i.h: Bug#44610 RCDFMT clause requested when creating DB2 table This patch appends a "RCDFMT " clause to the CREATE TABLE statement that is passed to DB2. is generated from the original name of the table itself. This ensures a consistent and deterministic mapping from the original table. --- .../suite/ibmdb2i/r/ibmdb2i_bug_44610.result | 18 +++++++ .../suite/ibmdb2i/t/ibmdb2i_bug_44610.test | 28 ++++++++++ storage/ibmdb2i/ha_ibmdb2i.cc | 7 ++- storage/ibmdb2i/ha_ibmdb2i.h | 53 ++++++++++++++++++- 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100755 mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result create mode 100755 mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result new file mode 100755 index 00000000000..311e800e1b0 --- /dev/null +++ b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result @@ -0,0 +1,18 @@ +create table ABC (i int) engine=ibmdb2i; +drop table ABC; +create table `1234567890ABC` (i int) engine=ibmdb2i; +drop table `1234567890ABC`; +create table `!@#$%` (i int) engine=ibmdb2i; +drop table `!@#$%`; +create table `ABCD#########` (i int) engine=ibmdb2i; +drop table `ABCD#########`; +create table `_` (i int) engine=ibmdb2i; +drop table `_`; +create table `abc##def` (i int) engine=ibmdb2i; +drop table `abc##def`; +set names utf8; +create table İ (s1 int) engine=ibmdb2i; +drop table İ; +create table İİ (s1 int) engine=ibmdb2i; +drop table İİ; +set names latin1; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test new file mode 100755 index 00000000000..da69b5d9148 --- /dev/null +++ b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test @@ -0,0 +1,28 @@ +source suite/ibmdb2i/include/have_ibmdb2i.inc; + +# Test RCDFMT generation for a variety of kinds of table names +create table ABC (i int) engine=ibmdb2i; +drop table ABC; + +create table `1234567890ABC` (i int) engine=ibmdb2i; +drop table `1234567890ABC`; + +create table `!@#$%` (i int) engine=ibmdb2i; +drop table `!@#$%`; + +create table `ABCD#########` (i int) engine=ibmdb2i; +drop table `ABCD#########`; + +create table `_` (i int) engine=ibmdb2i; +drop table `_`; + +create table `abc##def` (i int) engine=ibmdb2i; +drop table `abc##def`; + +set names utf8; +create table İ (s1 int) engine=ibmdb2i; +drop table İ; + +create table İİ (s1 int) engine=ibmdb2i; +drop table İİ; +set names latin1; diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc index 46c84de4aee..5cf9568be67 100644 --- a/storage/ibmdb2i/ha_ibmdb2i.cc +++ b/storage/ibmdb2i/ha_ibmdb2i.cc @@ -2273,7 +2273,12 @@ int ha_ibmdb2i::create(const char *name, TABLE *table_arg, if (isTemporary) query.append(STRING_WITH_LEN(" ON COMMIT PRESERVE ROWS ")); - + + if (create_info->alias) + generateAndAppendRCDFMT(create_info->alias, query); + else if (((TABLE_LIST*)(thd->lex->select_lex.table_list.first))->table_name) + generateAndAppendRCDFMT((char*)((TABLE_LIST*)(thd->lex->select_lex.table_list.first))->table_name, query); + DBUG_PRINT("ha_ibmdb2i::create", ("Sent to DB2: %s",query.c_ptr())); SqlStatementStream sqlStream(query.length()); sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary); diff --git a/storage/ibmdb2i/ha_ibmdb2i.h b/storage/ibmdb2i/ha_ibmdb2i.h index e90f152919c..2a8d65825bf 100644 --- a/storage/ibmdb2i/ha_ibmdb2i.h +++ b/storage/ibmdb2i/ha_ibmdb2i.h @@ -746,5 +746,56 @@ private: free_root(&conversionBufferMemroot, MYF(0)); } } - + + +/** + Generate a valid RCDFMT name based on the name of the table. + + The RCDFMT name is devised by munging the name of the table, + uppercasing all ascii alpha-numeric characters and replacing all other + characters with underscores until up to ten characters have been generated. + + @param tableName The name of the table, as given on the MySQL + CREATE TABLE statement + @param[out] query The string to receive the generated RCDFMT name +*/ + static void generateAndAppendRCDFMT(const char* tableName, String& query) + { + char rcdfmt[11]; + + // The RCDFMT name must begin with an alpha character. + // We enforce this by skipping to the first alpha character in the table + // name. If no alpha character exists, we use 'X' for the RCDFMT name; + + while (*tableName && + (!my_isascii(*tableName) || + !my_isalpha(system_charset_info, *tableName))) + { + tableName += my_mbcharlen(system_charset_info, *tableName); + } + + if (unlikely(!(*tableName))) + { + rcdfmt[0]= 'X'; + rcdfmt[1]= 0; + } + else + { + int r= 0; + while ((r < sizeof(rcdfmt)-1) && *tableName) + { + if (my_isascii(*tableName) && + my_isalnum(system_charset_info, *tableName)) + rcdfmt[r] = my_toupper(system_charset_info, *tableName); + else + rcdfmt[r] = '_'; + + ++r; + tableName += my_mbcharlen(system_charset_info, *tableName); + } + rcdfmt[r]= 0; + } + query.append(STRING_WITH_LEN(" RCDFMT ")); + query.append(rcdfmt); + } }; From 02b90ed9c36d0f76f38dee8d5a5d4ba3a2832d66 Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Sun, 17 May 2009 22:50:20 +0530 Subject: [PATCH 089/115] Bug#44856 IBMDB2I gives misleading 2504 error Occasionally, if both the partition_pruning and partition_range tests are run sequentially against the IBMDB2I engine, the partition_range test will fail. Compiler padding on a 64-bit build allowed garbage data in the hash key used for caching open iconv descriptors. As a result, cached descriptors were not found, and multiple duplicate iconv descriptors were opened for a single character set. Eventually, the maximum number of open iconv descriptors was reached, and further iconv_open() calls would fail, leading the storage engine to report incorrectly that the character set was not supported. This patch widens the 16-bit members of the hash key to 32 bits to eliminate compiler padding. The entire length of the hash key is now initialized correctly on both 32-bit and 64-bit builds. storage/ibmdb2i/db2i_charsetSupport.cc: Bug#44856 IBMDB2I gives misleading 2504 error widen the 16-bit members of the hash key to 32 bits to eliminate compiler padding. --- storage/ibmdb2i/db2i_charsetSupport.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/ibmdb2i/db2i_charsetSupport.cc b/storage/ibmdb2i/db2i_charsetSupport.cc index 559b526b7fd..1479776d71a 100644 --- a/storage/ibmdb2i/db2i_charsetSupport.cc +++ b/storage/ibmdb2i/db2i_charsetSupport.cc @@ -129,8 +129,8 @@ struct IconvMap { struct HashKey { - uint16 direction; // This is a uint16 instead of a uchar to avoid garbage data in the key from compiler padding - uint16 db2CCSID; + uint32 direction; // These are uint32s to avoid garbage data in the key from compiler padding + uint32 db2CCSID; const CHARSET_INFO* myCharset; } hashKey; iconv_t iconvDesc; From baeac8762396a181440368c9413d617f0f49aacc Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Sun, 17 May 2009 22:16:21 +0200 Subject: [PATCH 090/115] Bug#19027 MySQL 5.0 starts even with Fatal InnoDB errors Fix bug in mtr_cases.pm script visible only when InnoDB isn't configured. mysql-test/lib/mtr_cases.pm: If InnoDB isn't configured the help texts won't show the "innodb" option and mysqld_variables will not contain any "innodb" entry. --- mysql-test/lib/mtr_cases.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index d7a633cb80c..ae4fddae0a9 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -887,7 +887,8 @@ sub collect_one_test_case { if ( $tinfo->{'innodb_test'} ) { # This is a test that need innodb - if ( $::mysqld_variables{'innodb'} eq "OFF" ) + if ( $::mysqld_variables{'innodb'} eq "OFF" || + ! exists $::mysqld_variables{'innodb'} ) { # innodb is not supported, skip it $tinfo->{'skip'}= 1; From 405bd2af117384e009c3feffe1fd7d9019bf9d2b Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Mon, 18 May 2009 09:21:25 +0500 Subject: [PATCH 091/115] Bug #44768: SIGFPE crash when selecting rand from a view containing null The RAND(N) function where the N is a field of "constant" table (table of single row) failed with a SIGFPE. Evaluation of RAND(N) rely on constant status of its argument. Current server "seeded" random value for each constant argument only once, in the Item_func_rand::fix_fields method. Then the server skipped a call to seed_random() in the Item_func_rand::val_real method for such constant arguments. However, non-constant state of an argument may be changed after the call to fix_fields, if an argument is a field of "constant" table. Thus, pre-initialization of random value in the fix_fields method is too early. Initialization of random value by seed_random() has been removed from Item_func_rand::fix_fields method. The Item_func_rand::val_real method has been modified to call seed_random() on the first evaluation of this method if an argument is a function. mysql-test/r/func_math.result: Added test case for bug #44768. mysql-test/t/func_math.test: Added test case for bug #44768. sql/item_func.cc: Bug #44768: SIGFPE crash when selecting rand from a view containing null 1. Initialization of random value by seed_random() has been removed from Item_func_rand::fix_fields method. 2. The Item_func_rand::val_real method has been modified to call seed_random() on the first evaluation of this method if an argument is a function. sql/item_func.h: Bug #44768: SIGFPE crash when selecting rand from a view containing null 1. The Item_func_rand::first_eval has been added to trace the first evaluation of the val_real method. 2. The Item_func_rand::cleanup method has been added to cleanup the first_eval flag. --- mysql-test/r/func_math.result | 19 +++++++++++++++++++ mysql-test/t/func_math.test | 18 ++++++++++++++++++ sql/item_func.cc | 20 +++++++++++++++----- sql/item_func.h | 4 +++- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index c3d2db2d553..9bc83087232 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -456,4 +456,23 @@ NULL SELECT POW(10, 309); POW(10, 309) NULL +# +# Bug #44768: SIGFPE crash when selecting rand from a view +# containing null +# +CREATE OR REPLACE VIEW v1 AS SELECT NULL AS a; +SELECT RAND(a) FROM v1; +RAND(a) +0.155220427694936 +DROP VIEW v1; +SELECT RAND(a) FROM (SELECT NULL AS a) b; +RAND(a) +0.155220427694936 +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (NULL); +SELECT RAND(i) FROM t1; +RAND(i) +0.155220427694936 +DROP TABLE t1; +# End of 5.1 tests diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index e67f5f29e3a..f9369943d6c 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -282,4 +282,22 @@ SELECT 1e300 / 1e-300; SELECT EXP(750); SELECT POW(10, 309); +--echo # +--echo # Bug #44768: SIGFPE crash when selecting rand from a view +--echo # containing null +--echo # + +CREATE OR REPLACE VIEW v1 AS SELECT NULL AS a; +SELECT RAND(a) FROM v1; +DROP VIEW v1; + +SELECT RAND(a) FROM (SELECT NULL AS a) b; + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (NULL); +SELECT RAND(i) FROM t1; +DROP TABLE t1; + +--echo # + --echo End of 5.1 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 6f40298f8cf..4bb61f4ef52 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2143,9 +2143,6 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref) if (!rand && !(rand= (struct rand_struct*) thd->stmt_arena->alloc(sizeof(*rand)))) return TRUE; - - if (args[0]->const_item()) - seed_random (args[0]); } else { @@ -2175,8 +2172,21 @@ void Item_func_rand::update_used_tables() double Item_func_rand::val_real() { DBUG_ASSERT(fixed == 1); - if (arg_count && !args[0]->const_item()) - seed_random (args[0]); + if (arg_count) + { + if (!args[0]->const_item()) + seed_random(args[0]); + else if (first_eval) + { + /* + Constantness of args[0] may be set during JOIN::optimize(), if arg[0] + is a field item of "constant" table. Thus, we have to evaluate + seed_random() for constant arg there but not at the fix_fields method. + */ + first_eval= FALSE; + seed_random(args[0]); + } + } return my_rnd(rand); } diff --git a/sql/item_func.h b/sql/item_func.h index 147dfcc9d36..e512c94efc1 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -696,14 +696,16 @@ public: class Item_func_rand :public Item_real_func { struct rand_struct *rand; + bool first_eval; // TRUE if val_real() is called 1st time public: - Item_func_rand(Item *a) :Item_real_func(a), rand(0) {} + Item_func_rand(Item *a) :Item_real_func(a), rand(0), first_eval(TRUE) {} Item_func_rand() :Item_real_func() {} double val_real(); const char *func_name() const { return "rand"; } bool const_item() const { return 0; } void update_used_tables(); bool fix_fields(THD *thd, Item **ref); + void cleanup() { first_eval= TRUE; Item_real_func::cleanup(); } private: void seed_random (Item * val); }; From a7294532b2f45342075d2a1bdac6cb8720a90ea3 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Mon, 18 May 2009 23:43:06 +0500 Subject: [PATCH 092/115] Bug#40825: Error 1356 while selecting from a view with a "HAVING" clause though query works SELECT from views defined like: CREATE VIEW v1 (view_column) AS SELECT c AS alias FROM t1 HAVING alias fails with an error 1356: View '...' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them CREATE VIEW form with a (column list) substitutes SELECT column names/aliases with names from a view column list. However, alias references in HAVING clause was not substituted. The Item_ref::print function has been modified to write correct aliased names of underlying items into VIEW definition generation/.frm file. mysql-test/r/view.result: Added test file for bug #40825. mysql-test/t/view.test: Added test file for bug #40825. sql/item.cc: Bug#40825: Error 1356 while selecting from a view with a "HAVING" clause though query works The Item_ref::print function has been modified to write correct aliased names of underlying items into VIEW definition generation/.frm file. --- mysql-test/r/view.result | 19 +++++++++++++++++++ mysql-test/t/view.test | 23 +++++++++++++++++++++++ sql/item.cc | 3 ++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 58aa614c508..a7ac971ef45 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3704,6 +3704,25 @@ SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; ERROR HY000: Key 'c2' doesn't exist in table 'v1' DROP VIEW v1; DROP TABLE t1; +# ----------------------------------------------------------------- +# -- Bug#40825: Error 1356 while selecting from a view +# -- with a "HAVING" clause though query works +# ----------------------------------------------------------------- + +CREATE TABLE t1 (c INT); + +CREATE VIEW v1 (view_column) AS SELECT c AS alias FROM t1 HAVING alias; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`c` AS `view_column` from `t1` having `view_column` +SELECT * FROM v1; +view_column + +DROP VIEW v1; +DROP TABLE t1; + +# -- End of test case for Bug#40825 + # ----------------------------------------------------------------- # -- End of 5.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 6437e546697..89e68e4bd99 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3680,6 +3680,29 @@ SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; DROP VIEW v1; DROP TABLE t1; +--echo # ----------------------------------------------------------------- +--echo # -- Bug#40825: Error 1356 while selecting from a view +--echo # -- with a "HAVING" clause though query works +--echo # ----------------------------------------------------------------- +--echo + +CREATE TABLE t1 (c INT); + +--echo + +CREATE VIEW v1 (view_column) AS SELECT c AS alias FROM t1 HAVING alias; +SHOW CREATE VIEW v1; +SELECT * FROM v1; + +--echo + +DROP VIEW v1; +DROP TABLE t1; + +--echo +--echo # -- End of test case for Bug#40825 +--echo + --echo # ----------------------------------------------------------------- --echo # -- End of 5.0 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/item.cc b/sql/item.cc index 13f09914ec6..7c4e86d756f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5648,7 +5648,8 @@ void Item_ref::print(String *str) !table_name && name && alias_name_used) { THD *thd= current_thd; - append_identifier(thd, str, name, (uint) strlen(name)); + append_identifier(thd, str, (*ref)->real_item()->name, + (*ref)->real_item()->name_length); } else (*ref)->print(str); From 0a892c46e0f53cb1404bea696da6adecb95d39cb Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Tue, 19 May 2009 11:32:21 +0500 Subject: [PATCH 093/115] Bug#39793 Foreign keys not constructed when column has a '#' in a comment or default value Internal InnoDN FK parser does not recognize '\'' as quotation symbol. Suggested fix is to add '\'' symbol check for quotation condition (dict_strip_comments() function). innobase/dict/dict0dict.c: Internal InnoDN FK parser does not recognize '\'' as quotation symbol. Suggested fix is to add '\'' symbol check for quotation condition (dict_strip_comments() function). mysql-test/r/innodb_mysql.result: test result mysql-test/t/innodb_mysql.test: test case --- innobase/dict/dict0dict.c | 2 +- mysql-test/r/innodb_mysql.result | 12 ++++++++++++ mysql-test/t/innodb_mysql.test | 9 +++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index b0d95597153..c1ca6f369c3 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2829,7 +2829,7 @@ scan_more: } else if (quote) { /* Within quotes: do not look for starting quotes or comments. */ - } else if (*sptr == '"' || *sptr == '`') { + } else if (*sptr == '"' || *sptr == '`' || *sptr == '\'') { /* Starting quote: remember the quote character. */ quote = *sptr; } else if (*sptr == '#' diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index d95499fe3ba..b6fc58be4c2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1291,4 +1291,16 @@ SAVEPOINT s4; ROLLBACK; ROLLBACK TO SAVEPOINT s4; ERROR 42000: SAVEPOINT s4 does not exist +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY COMMENT 'My ID#', f2 INTEGER DEFAULT NULL, f3 CHAR(10) DEFAULT 'My ID#', CONSTRAINT f2_ref FOREIGN KEY (f2) REFERENCES t1 (f1)) ENGINE=INNODB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL COMMENT 'My ID#', + `f2` int(11) default NULL, + `f3` char(10) default 'My ID#', + PRIMARY KEY (`f1`), + KEY `f2_ref` (`f2`), + CONSTRAINT `f2_ref` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 512f7fc7fe2..05be75fc368 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -1054,4 +1054,13 @@ ROLLBACK; --error 1305 ROLLBACK TO SAVEPOINT s4; +# +# Bug#39793 Foreign keys not constructed when column has a '#' in a comment or default value +# + +#This statement should be written on a single line for proper testing +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY COMMENT 'My ID#', f2 INTEGER DEFAULT NULL, f3 CHAR(10) DEFAULT 'My ID#', CONSTRAINT f2_ref FOREIGN KEY (f2) REFERENCES t1 (f1)) ENGINE=INNODB; +SHOW CREATE TABLE t1; +DROP TABLE t1; + --echo End of 5.0 tests From e5a9d41c583946d13e5464e516f007a6eefc4b57 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Wed, 20 May 2009 16:24:22 +0800 Subject: [PATCH 094/115] BUG#42415 UPDATE with LIMIT clause unsafe for statement format even when ORDER BY PK Change the warning message to 'Statement may not be safe to log in statement format' to indicate that the decision on whether a statement is safe or not is heuristic, and we are conservative. --- sql/share/errmsg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index f9b66990e93..2dfc5310643 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6076,7 +6076,7 @@ ER_SLAVE_INCIDENT ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT eng "Table has no partition for some existing values" ER_BINLOG_UNSAFE_STATEMENT - eng "Statement is not safe to log in statement format." + eng "Statement may not be safe to log in statement format." swe "Detta är inte säkert att logga i statement-format." ER_SLAVE_FATAL_ERROR eng "Fatal error: %s" From 0b62b7f26d2bef58983f7c7e8b288dd9bce0cdcc Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Wed, 20 May 2009 12:30:06 +0400 Subject: [PATCH 095/115] Bug #44796: valgrind: too many my_longlong10_to_str_8bit warnings after uncompressed_length UNCOMPRESSED_LENGTH() did not validate its argument. In particular, if the argument length was less than 4 bytes, an uninitialized memory value was returned as a result. Since the result of COMPRESS() is either an empty string or a 4-byte length prefix followed by compressed data, the bug was fixed by ensuring that the argument of UNCOMPRESSED_LENGTH() is either an empty string or contains at least 5 bytes (as done in UNCOMPRESS()). This is the best we can do to validate input without decompressing. mysql-test/r/func_compress.result: Added a test case for bug #44796. mysql-test/t/func_compress.test: Added a test case for bug #44796. sql/item_strfunc.cc: Make sure that the argument of UNCOMPRESSED_LENGTH() contains at least 5 bytes (as done in UNCOMPRESS()). --- mysql-test/r/func_compress.result | 15 +++++++++++++++ mysql-test/t/func_compress.test | 17 +++++++++++++++++ sql/item_strfunc.cc | 16 +++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result index 4a3454cf658..a30ca7859f1 100644 --- a/mysql-test/r/func_compress.result +++ b/mysql-test/r/func_compress.result @@ -116,4 +116,19 @@ Warnings: Error 1259 ZLIB: Input data corrupted Error 1259 ZLIB: Input data corrupted drop table t1; +CREATE TABLE t1 (c1 INT); +INSERT INTO t1 VALUES (1), (1111), (11111); +SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; +UNCOMPRESS(c1) UNCOMPRESSED_LENGTH(c1) +NULL NULL +NULL NULL +NULL 825307441 +Warnings: +Error 1259 ZLIB: Input data corrupted +Error 1259 ZLIB: Input data corrupted +Error 1259 ZLIB: Input data corrupted +Error 1259 ZLIB: Input data corrupted +Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test index 68f07f258bf..b1a37c16c6d 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -82,4 +82,21 @@ select *, uncompress(a) from t1; select *, uncompress(a), uncompress(a) is null from t1; drop table t1; +# +# Bug #44796: valgrind: too many my_longlong10_to_str_8bit warnings after +# uncompressed_length +# + +CREATE TABLE t1 (c1 INT); +INSERT INTO t1 VALUES (1), (1111), (11111); + +SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; + +# We do not need the results, just make sure there are no valgrind errors +--disable_result_log +EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; +--enable_result_log + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index bc2dcb9c61b..4941f427731 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3108,7 +3108,21 @@ longlong Item_func_uncompressed_length::val_int() if (res->is_empty()) return 0; /* - res->ptr() using is safe because we have tested that string is not empty, + If length is <= 4 bytes, data is corrupt. This is the best we can do + to detect garbage input without decompressing it. + */ + if (res->length() <= 4) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_ZLIB_Z_DATA_ERROR, + ER(ER_ZLIB_Z_DATA_ERROR)); + null_value= 1; + return 0; + } + + /* + res->ptr() using is safe because we have tested that string is at least + 5 bytes long. res->c_ptr() is not used because: - we do not need \0 terminated string to get first 4 bytes - c_ptr() tests simbol after string end (uninitialiozed memory) which From 65d15fcd2a7cf1a0a9d508fc929ab1e8f6467da5 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Wed, 20 May 2009 18:28:43 +0800 Subject: [PATCH 096/115] Post fix of result file after push of BUG#42415 --- .../suite/binlog/r/binlog_stm_ps.result | 2 +- .../suite/binlog/r/binlog_unsafe.result | 122 +++++++++--------- mysql-test/suite/binlog/t/binlog_unsafe.test | 4 +- .../suite/rpl/r/rpl_stm_loadfile.result | 4 +- mysql-test/suite/rpl/r/rpl_udf.result | 8 +- 5 files changed, 70 insertions(+), 70 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_stm_ps.result b/mysql-test/suite/binlog/r/binlog_stm_ps.result index ea7cc6f16df..3af525e297c 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_ps.result +++ b/mysql-test/suite/binlog/r/binlog_stm_ps.result @@ -11,7 +11,7 @@ prepare s from "insert into t1 select 100 limit ?"; set @a=100; execute s using @a; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; create table t1 (a int) diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index 675c327e9e7..4c2c32ad8f1 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -10,25 +10,25 @@ INSERT DELAYED INTO t1 VALUES (5); ---- Insert directly ---- INSERT INTO t1 VALUES (@@global.sync_binlog); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. INSERT INTO t1 VALUES (@@session.insert_id); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. INSERT INTO t1 VALUES (@@global.auto_increment_increment); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. INSERT INTO t2 SELECT UUID(); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. INSERT INTO t2 VALUES (@@session.sql_mode); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. INSERT INTO t2 VALUES (@@global.init_slave); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. INSERT INTO t2 VALUES (@@hostname); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. ---- Insert from stored procedure ---- CREATE PROCEDURE proc() BEGIN @@ -42,13 +42,13 @@ INSERT INTO t2 VALUES (@@hostname); END| CALL proc(); Warnings: -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. ---- Insert from stored function ---- CREATE FUNCTION func() RETURNS INT @@ -66,13 +66,13 @@ SELECT func(); func() 0 Warnings: -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. ---- Insert from trigger ---- CREATE TRIGGER trig BEFORE INSERT ON trigger_table @@ -88,14 +88,14 @@ INSERT INTO t2 VALUES (@@hostname); END| INSERT INTO trigger_table VALUES ('bye.'); Warnings: -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. ---- Insert from prepared statement ---- PREPARE p1 FROM 'INSERT INTO t1 VALUES (@@global.sync_binlog)'; PREPARE p2 FROM 'INSERT INTO t1 VALUES (@@session.insert_id)'; @@ -106,25 +106,25 @@ PREPARE p6 FROM 'INSERT INTO t2 VALUES (@@global.init_slave)'; PREPARE p7 FROM 'INSERT INTO t2 VALUES (@@hostname)'; EXECUTE p1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. EXECUTE p2; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. EXECUTE p3; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. EXECUTE p4; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. EXECUTE p5; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. EXECUTE p6; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. EXECUTE p7; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. ---- Insert from nested call of triggers / functions / procedures ---- CREATE PROCEDURE proc1() INSERT INTO trigger_table VALUES ('ha!')| @@ -154,13 +154,13 @@ EXECUTE prep6; func5() 0 Warnings: -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. ==== Variables that should *not* be unsafe ==== INSERT INTO t1 VALUES (@@session.pseudo_thread_id); INSERT INTO t1 VALUES (@@session.pseudo_thread_id); @@ -195,16 +195,16 @@ DROP TABLE t1, t2, t3, trigger_table, trigger_table2; CREATE TABLE t1(a INT, b INT, KEY(a), PRIMARY KEY(b)); INSERT INTO t1 SELECT * FROM t1 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. REPLACE INTO t1 SELECT * FROM t1 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. UPDATE t1 SET a=1 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. DELETE FROM t1 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. CREATE PROCEDURE p1() BEGIN INSERT INTO t1 SELECT * FROM t1 LIMIT 1; @@ -214,10 +214,10 @@ DELETE FROM t1 LIMIT 1; END| CALL p1(); Warnings: -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. DROP PROCEDURE p1; DROP TABLE t1; DROP TABLE IF EXISTS t1; @@ -225,16 +225,16 @@ CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100)); INSERT INTO t1 VALUES ('a','b'); UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. DROP TABLE t1; DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1(i INT PRIMARY KEY); CREATE TABLE t2(i INT PRIMARY KEY); CREATE TABLE t3(i INT, ch CHAR(50)); -"Should issue message Statement is not safe to log in statement format." +"Should issue message Statement may not be safe to log in statement format." INSERT INTO t1 SELECT * FROM t2 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. CREATE FUNCTION func6() RETURNS INT BEGIN @@ -243,10 +243,10 @@ INSERT INTO t1 VALUES (11); INSERT INTO t1 VALUES (12); RETURN 0; END| -"Should issue message Statement is not safe to log in statement format only once" +"Should issue message Statement may not be safe to log in statement format only once" INSERT INTO t3 VALUES(func6(), UUID()); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. "Check whether SET @@SQL_LOG_BIN = 0/1 doesn't work in substatements" CREATE FUNCTION fun_check_log_bin() RETURNS INT BEGIN @@ -259,7 +259,7 @@ SELECT fun_check_log_bin(); fun_check_log_bin() 100 Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. "SQL_LOG_BIN should be ON still" SHOW VARIABLES LIKE "SQL_LOG_BIN"; Variable_name Value @@ -315,16 +315,16 @@ CREATE TABLE t1(i INT PRIMARY KEY); CREATE TABLE t2(i INT PRIMARY KEY); INSERT INTO t1 SELECT * FROM t2 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. INSERT INTO t1 VALUES(@@global.sync_binlog); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. UPDATE t1 SET i = 999 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. DELETE FROM t1 LIMIT 1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. DROP TABLE t1, t2; SET @@SESSION.SQL_MODE = @save_sql_mode; "End of tests" diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index 1b0f0a6c30a..c4e1f31cbce 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -289,7 +289,7 @@ CREATE TABLE t1(i INT PRIMARY KEY); CREATE TABLE t2(i INT PRIMARY KEY); CREATE TABLE t3(i INT, ch CHAR(50)); ---echo "Should issue message Statement is not safe to log in statement format." +--echo "Should issue message Statement may not be safe to log in statement format." INSERT INTO t1 SELECT * FROM t2 LIMIT 1; DELIMITER |; @@ -302,7 +302,7 @@ BEGIN RETURN 0; END| DELIMITER ;| ---echo "Should issue message Statement is not safe to log in statement format only once" +--echo "Should issue message Statement may not be safe to log in statement format only once" INSERT INTO t3 VALUES(func6(), UUID()); --echo "Check whether SET @@SQL_LOG_BIN = 0/1 doesn't work in substatements" diff --git a/mysql-test/suite/rpl/r/rpl_stm_loadfile.result b/mysql-test/suite/rpl/r/rpl_stm_loadfile.result index 72f58268d5f..ca76695f4d4 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_loadfile.result +++ b/mysql-test/suite/rpl/r/rpl_stm_loadfile.result @@ -10,7 +10,7 @@ CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, PRIMARY KEY(a)); INSERT INTO test.t1 VALUES(1,'test'); UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=1; Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. create procedure test.p1() begin INSERT INTO test.t1 VALUES(2,'test'); @@ -18,7 +18,7 @@ UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=2; end| CALL test.p1(); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. SELECT * FROM test.t1 ORDER BY blob_column; a blob_column 1 abase diff --git a/mysql-test/suite/rpl/r/rpl_udf.result b/mysql-test/suite/rpl/r/rpl_udf.result index 56df5b30d93..ccf16271d01 100644 --- a/mysql-test/suite/rpl/r/rpl_udf.result +++ b/mysql-test/suite/rpl/r/rpl_udf.result @@ -182,19 +182,19 @@ CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM; affected rows: 0 INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00)); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00)); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00)); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00)); Warnings: -Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. affected rows: 1 SELECT * FROM t1 ORDER BY sum; sum price From 54d36955b2109d638d630366d91d88f37961ca6c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 20 May 2009 14:14:33 +0300 Subject: [PATCH 097/115] Revert of the fix for bug #44399 (joro@sun.com-20090512135917-kal1dvtqpqgnj3yc). --- mysql-test/r/func_in.result | 5 ----- mysql-test/t/func_in.test | 10 ---------- sql/item_cmpfunc.cc | 28 ++++++++++++++-------------- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index b19edbd1a00..1e967b668c5 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -587,9 +587,4 @@ SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1; CASE c1 WHEN c1 + 1 THEN 1 END ABS(AVG(c0)) NULL 1.0000 DROP TABLE t1; -CREATE TABLE t1(a TEXT); -INSERT INTO t1 VALUES('iynfj'); -SELECT SUM( DISTINCT a ) FROM t1 GROUP BY a HAVING a IN ( AVG( 1 ), 1 + a ); -SUM( DISTINCT a ) -DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 795a92180db..3fc1697f146 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -439,14 +439,4 @@ SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1; DROP TABLE t1; -# -# Bug #44399: crash with statement using TEXT columns, aggregates, GROUP BY, -# and HAVING -# - -CREATE TABLE t1(a TEXT); -INSERT INTO t1 VALUES('iynfj'); -SELECT SUM( DISTINCT a ) FROM t1 GROUP BY a HAVING a IN ( AVG( 1 ), 1 + a ); -DROP TABLE t1; - --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5017464f968..a9bfea1b806 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -189,7 +189,6 @@ enum_field_types agg_field_type(Item **items, uint nitems) collect_cmp_types() items Array of items to collect types from nitems Number of items in the array - with_sum_func a sum function is referenced DESCRIPTION This function collects different result types for comparison of the first @@ -200,7 +199,7 @@ enum_field_types agg_field_type(Item **items, uint nitems) Bitmap of collected types - otherwise */ -static uint collect_cmp_types(Item **items, uint nitems, my_bool with_sum_func) +static uint collect_cmp_types(Item **items, uint nitems) { uint i; uint found_types; @@ -216,16 +215,6 @@ static uint collect_cmp_types(Item **items, uint nitems, my_bool with_sum_func) found_types|= 1<< (uint)item_cmp_type(left_result, items[i]->result_type()); } - if (with_sum_func || current_thd->lex->current_select->group_list.elements) - { - /* - See TODO commentary in the setup_copy_fields function: - item in a group may be wrapped with an Item_copy_string item. - That item has a STRING_RESULT result type, so we need - to take this type into account. - */ - found_types |= (1 << item_cmp_type(left_result, STRING_RESULT)); - } return found_types; } @@ -2733,8 +2722,19 @@ void Item_func_case::fix_length_and_dec() for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; - if (!(found_types= collect_cmp_types(agg, nagg, with_sum_func))) + if (!(found_types= collect_cmp_types(agg, nagg))) return; + if (with_sum_func || current_thd->lex->current_select->group_list.elements) + { + /* + See TODO commentary in the setup_copy_fields function: + item in a group may be wrapped with an Item_copy_string item. + That item has a STRING_RESULT result type, so we need + to take this type into account. + */ + found_types |= (1 << item_cmp_type(left_result_type, STRING_RESULT)); + } + for (i= 0; i <= (uint)DECIMAL_RESULT; i++) { if (found_types & (1 << i) && !cmp_items[i]) @@ -3525,7 +3525,7 @@ void Item_func_in::fix_length_and_dec() uint type_cnt= 0, i; Item_result cmp_type= STRING_RESULT; left_result_type= args[0]->result_type(); - if (!(found_types= collect_cmp_types(args, arg_count, with_sum_func))) + if (!(found_types= collect_cmp_types(args, arg_count))) return; for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++) From 059dba14b774083ae63cde9ad41b00308f001ce7 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 20 May 2009 16:17:47 +0200 Subject: [PATCH 098/115] Recommit of bug 43560 after merge with mysql-5.1-bugteam --- sql-common/client.c | 68 +++++++++++------- sql/sql_prepare.cc | 3 + tests/mysql_client_test.c | 140 ++++++++++++++++++++++++++++++++++---- 3 files changed, 173 insertions(+), 38 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index d2c7e02551d..9ba7f13e6b6 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -924,6 +924,7 @@ void end_server(MYSQL *mysql) vio_delete(mysql->net.vio); reset_sigpipe(mysql); mysql->net.vio= 0; /* Marker */ + mysql_prune_stmt_list(mysql); } net_end(&mysql->net); free_old_query(mysql); @@ -2526,30 +2527,9 @@ my_bool mysql_reconnect(MYSQL *mysql) tmp_mysql.reconnect= 1; tmp_mysql.free_me= mysql->free_me; - /* - For each stmt in mysql->stmts, move it to tmp_mysql if it is - in state MYSQL_STMT_INIT_DONE, otherwise close it. - */ - { - LIST *element= mysql->stmts; - for (; element; element= element->next) - { - MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; - if (stmt->state != MYSQL_STMT_INIT_DONE) - { - stmt->mysql= 0; - stmt->last_errno= CR_SERVER_LOST; - strmov(stmt->last_error, ER(CR_SERVER_LOST)); - strmov(stmt->sqlstate, unknown_sqlstate); - } - else - { - tmp_mysql.stmts= list_add(tmp_mysql.stmts, &stmt->list); - } - /* No need to call list_delete for statement here */ - } - mysql->stmts= NULL; - } + /* Move prepared statements (if any) over to the new mysql object */ + tmp_mysql.stmts= mysql->stmts; + mysql->stmts= 0; /* Don't free options as these are now used in tmp_mysql */ bzero((char*) &mysql->options,sizeof(mysql->options)); @@ -2639,6 +2619,46 @@ static void mysql_close_free(MYSQL *mysql) } +/** + For use when the connection to the server has been lost (in which case + the server has discarded all information about prepared statements + associated with the connection). + + Mark all statements in mysql->stmts by setting stmt->mysql= 0 if the + statement has transitioned beyond the MYSQL_STMT_INIT_DONE state, and + unlink the statement from the mysql->stmts list. + + The remaining pruned list of statements (if any) is kept in mysql->stmts. + + @param mysql pointer to the MYSQL object + + @return none +*/ +void mysql_prune_stmt_list(MYSQL *mysql) +{ + LIST *element= mysql->stmts; + LIST *pruned_list= 0; + + for (; element; element= element->next) + { + MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; + if (stmt->state != MYSQL_STMT_INIT_DONE) + { + stmt->mysql= 0; + stmt->last_errno= CR_SERVER_LOST; + strmov(stmt->last_error, ER(CR_SERVER_LOST)); + strmov(stmt->sqlstate, unknown_sqlstate); + } + else + { + pruned_list= list_add(pruned_list, element); + } + } + + mysql->stmts= pruned_list; +} + + /* Clear connection pointer of every statement: this is necessary to give error on attempt to use a prepared statement of closed diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index cd11b6d4c24..cc7ea75dbbf 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2461,6 +2461,9 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end); + /* Close connection socket; for use with client testing (Bug#43560). */ + DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_close(thd->net.vio);); + DBUG_VOID_RETURN; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 1183256eb1a..e56d1e9f506 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -103,7 +103,7 @@ if (!opt_silent) \ static void print_error(const char *msg); static void print_st_error(MYSQL_STMT *stmt, const char *msg); -static void client_disconnect(void); +static void client_disconnect(MYSQL* mysql, my_bool drop_db); /* @@ -271,10 +271,20 @@ mysql_simple_prepare(MYSQL *mysql_arg, const char *query) } -/* Connect to the server */ +/** + Connect to the server with options given by arguments to this application, + stored in global variables opt_host, opt_user, opt_password, opt_db, + opt_port and opt_unix_socket. -static void client_connect(ulong flag) + @param flag[in] client_flag passed on to mysql_real_connect + @param protocol[in] MYSQL_PROTOCOL_* to use for this connection + @param auto_reconnect[in] set to 1 for auto reconnect + + @return pointer to initialized and connected MYSQL object +*/ +static MYSQL* client_connect(ulong flag, uint protocol, my_bool auto_reconnect) { + MYSQL* mysql; int rc; static char query[MAX_TEST_QUERY_LENGTH]; myheader_r("client_connect"); @@ -291,6 +301,7 @@ static void client_connect(ulong flag) } /* enable local infile, in non-binary builds often disabled by default */ mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0); + mysql_options(mysql, MYSQL_OPT_PROTOCOL, &protocol); if (!(mysql_real_connect(mysql, opt_host, opt_user, opt_password, opt_db ? opt_db:"test", opt_port, @@ -302,7 +313,7 @@ static void client_connect(ulong flag) fprintf(stdout, "\n Check the connection options using --help or -?\n"); exit(1); } - mysql->reconnect= 1; + mysql->reconnect= auto_reconnect; if (!opt_silent) fprintf(stdout, "OK"); @@ -329,12 +340,14 @@ static void client_connect(ulong flag) if (!opt_silent) fprintf(stdout, "OK"); + + return mysql; } /* Close the connection */ -static void client_disconnect() +static void client_disconnect(MYSQL* mysql, my_bool drop_db) { static char query[MAX_TEST_QUERY_LENGTH]; @@ -342,13 +355,16 @@ static void client_disconnect() if (mysql) { - if (!opt_silent) - fprintf(stdout, "\n dropping the test database '%s' ...", current_db); - strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS); + if (drop_db) + { + if (!opt_silent) + fprintf(stdout, "\n dropping the test database '%s' ...", current_db); + strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS); - mysql_query(mysql, query); - if (!opt_silent) - fprintf(stdout, "OK"); + mysql_query(mysql, query); + if (!opt_silent) + fprintf(stdout, "OK"); + } if (!opt_silent) fprintf(stdout, "\n closing the connection ..."); @@ -17712,6 +17728,100 @@ static void test_bug40365(void) } +/** + Subtest for Bug#43560. Verifies that a loss of connection on the server side + is handled well by the mysql_stmt_execute() call, i.e., no SIGSEGV due to + a vio socket that is cleared upon closed connection. + + Assumes the presence of the close_conn_after_stmt_execute debug feature in + the server. Verifies that it is connected to a debug server before proceeding + with the test. + */ +static void test_bug43560(void) +{ + MYSQL* conn; + uint rc; + MYSQL_STMT *stmt= 0; + MYSQL_BIND bind; + my_bool is_null= 0; + const uint BUFSIZE= 256; + char buffer[BUFSIZE]; + const char* values[] = {"eins", "zwei", "drei", "viele", NULL}; + const char insert_str[] = "INSERT INTO t1 (c2) VALUES (?)"; + unsigned long length; + + DBUG_ENTER("test_bug43560"); + myheader("test_bug43560"); + + /* Make sure we only run against a debug server. */ + if (!strstr(mysql->server_version, "debug")) + { + fprintf(stdout, "Skipping test_bug43560: server not DEBUG version\n"); + DBUG_VOID_RETURN; + } + + /* + Set up a separate connection for this test to avoid messing up the + general MYSQL object used in other subtests. Use TCP protocol to avoid + problems with the buffer semantics of AF_UNIX, and turn off auto reconnect. + */ + conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0); + + rc= mysql_query(conn, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(conn, + "CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 CHAR(10))"); + myquery(rc); + + stmt= mysql_stmt_init(conn); + check_stmt(stmt); + rc= mysql_stmt_prepare(stmt, insert_str, strlen(insert_str)); + check_execute(stmt, rc); + + bind.buffer_type= MYSQL_TYPE_STRING; + bind.buffer_length= BUFSIZE; + bind.buffer= buffer; + bind.is_null= &is_null; + bind.length= &length; + rc= mysql_stmt_bind_param(stmt, &bind); + check_execute(stmt, rc); + + /* First execute; should succeed. */ + strncpy(buffer, values[0], BUFSIZE); + length= strlen(buffer); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + /* + Set up the server to close this session's server-side socket after + next execution of prep statement. + */ + rc= mysql_query(conn,"SET SESSION debug='+d,close_conn_after_stmt_execute'"); + myquery(rc); + + /* Second execute; should fail due to socket closed during execution. */ + strncpy(buffer, values[1], BUFSIZE); + length= strlen(buffer); + rc= mysql_stmt_execute(stmt); + DIE_UNLESS(rc && mysql_stmt_errno(stmt) == CR_SERVER_LOST); + + /* + Third execute; should fail (connection already closed), or SIGSEGV in + case of a Bug#43560 type regression in which case the whole test fails. + */ + strncpy(buffer, values[2], BUFSIZE); + length= strlen(buffer); + rc= mysql_stmt_execute(stmt); + DIE_UNLESS(rc && mysql_stmt_errno(stmt) == CR_SERVER_LOST); + + client_disconnect(conn, 0); + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); + + DBUG_VOID_RETURN; +} + + /** Bug#36326: nested transaction and select */ @@ -18140,6 +18250,7 @@ static struct my_tests_st my_tests[]= { { "test_wl4166_2", test_wl4166_2 }, { "test_bug38486", test_bug38486 }, { "test_bug40365", test_bug40365 }, + { "test_bug43560", test_bug43560 }, #ifdef HAVE_QUERY_CACHE { "test_bug36326", test_bug36326 }, #endif @@ -18268,7 +18379,8 @@ int main(int argc, char **argv) (char**) embedded_server_groups)) DIE("Can't initialize MySQL server"); - client_connect(0); /* connect to server */ + /* connect to server with no flags, default protocol, auto reconnect true */ + mysql= client_connect(0, MYSQL_PROTOCOL_DEFAULT, 1); total_time= 0; for (iter_count= 1; iter_count <= opt_count; iter_count++) @@ -18298,7 +18410,7 @@ int main(int argc, char **argv) fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv); fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n", my_progname); - client_disconnect(); + client_disconnect(mysql, 1); free_defaults(defaults_argv); exit(1); } @@ -18311,7 +18423,7 @@ int main(int argc, char **argv) /* End of tests */ } - client_disconnect(); /* disconnect from server */ + client_disconnect(mysql, 1); /* disconnect from server */ free_defaults(defaults_argv); print_test_output(); From aede9b7d1328657ba454d5d0f88825f9e0c616c0 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 20 May 2009 19:34:37 +0200 Subject: [PATCH 099/115] Adding missing forward declaration for bug 43560 --- sql-common/client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql-common/client.c b/sql-common/client.c index 9ba7f13e6b6..a6a2be1086f 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -120,6 +120,7 @@ const char *def_shared_memory_base_name= default_shared_memory_base_name; static void mysql_close_free_options(MYSQL *mysql); static void mysql_close_free(MYSQL *mysql); +static void mysql_prune_stmt_list(MYSQL *mysql); #if !(defined(__WIN__) || defined(__NETWARE__)) static int wait_for_data(my_socket fd, uint timeout); @@ -2634,7 +2635,7 @@ static void mysql_close_free(MYSQL *mysql) @return none */ -void mysql_prune_stmt_list(MYSQL *mysql) +static void mysql_prune_stmt_list(MYSQL *mysql) { LIST *element= mysql->stmts; LIST *pruned_list= 0; From b243283e693452549457bd9ccf73918965809571 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Wed, 20 May 2009 23:04:34 +0200 Subject: [PATCH 100/115] Updates to build with community features enabled for community builds. --- CMakeLists.txt | 4 ++++ include/config-win.h | 3 --- support-files/mysql.spec.sh | 2 ++ win/configure.js | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f66453ef492..91c3a804eea 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,10 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFORCE_INIT_OF_VARS") # Note that some engines are always compiled in, MyISAM, MyISAMMRG, HEAP +IF(WITH_COMMUNITY_FEATURES) + ADD_DEFINITIONS(-DENABLED_PROFILING -DCOMMUNITY_SERVER) +ENDIF(WITH_COMMUNITY_FEATURES) + IF(WITH_ARCHIVE_STORAGE_ENGINE) ADD_DEFINITIONS(-DHAVE_ARCHIVE_DB) ENDIF(WITH_ARCHIVE_STORAGE_ENGINE) diff --git a/include/config-win.h b/include/config-win.h index 39affd3b8e9..ab463a7c142 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -206,9 +206,6 @@ typedef uint rf_SetTimer; /* If LOAD DATA LOCAL INFILE should be enabled by default */ #define ENABLED_LOCAL_INFILE 1 -/* If query profiling should be enabled by default */ -#define ENABLED_PROFILING 1 - /* Convert some simple functions to Posix */ #define my_sigset(A,B) signal((A),(B)) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index fa3c3a8b4ce..584c0abc777 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -264,6 +264,8 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --includedir=%{_includedir} \ --mandir=%{_mandir} \ --enable-thread-safe-client \ + --enable-community-features \ + --enable-profiling \ --with-readline ; \ # Add this for more debugging support # --with-debug diff --git a/win/configure.js b/win/configure.js index 0de09fb318c..8370497ea4b 100755 --- a/win/configure.js +++ b/win/configure.js @@ -39,6 +39,7 @@ try var parts = args.Item(i).split('='); switch (parts[0]) { + case "WITH_COMMUNITY_FEATURES": case "WITH_ARCHIVE_STORAGE_ENGINE": case "WITH_BERKELEY_STORAGE_ENGINE": case "WITH_BLACKHOLE_STORAGE_ENGINE": From 985df4dcdc734ac3b63d6829b417302649c20104 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 21 May 2009 13:06:43 +0500 Subject: [PATCH 101/115] Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery Problem: input and output buffers may be the same converting a string to some charset. That may lead to wrong results/valgrind warnings. Fix: use different buffers. mysql-test/r/cast.result: Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery - test result. mysql-test/r/func_concat.result: Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery - test result. mysql-test/t/cast.test: Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery - test case. mysql-test/t/func_concat.test: Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery - test case. sql/item.cc: Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery - comment added. sql/item_strfunc.cc: Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery - '&args[0]->str_value' used as a parameter of args[0]->val_str(), as 'str' may be equal to 'str_value' which we use as the output buffer converting strings. sql/sql_string.cc: Fix for bug#44743: Join in combination with concat does not always work bug#44766: valgrind error when using convert() in a subquery - input and output buffers must NOT be the same. --- mysql-test/r/cast.result | 13 +++++++++++++ mysql-test/r/func_concat.result | 31 ++++++++++++++++++++++++++++++ mysql-test/t/cast.test | 15 +++++++++++++++ mysql-test/t/func_concat.test | 34 +++++++++++++++++++++++++++++++++ sql/item.cc | 5 ++++- sql/item_strfunc.cc | 9 ++++++++- sql/sql_string.cc | 3 +++ 7 files changed, 108 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index c1af92c5f8d..dd61396e485 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -439,3 +439,16 @@ HOUR(NULL) MINUTE(NULL) SECOND(NULL) NULL NULL NULL DROP TABLE t1; End of 5.0 tests +# +# Bug #44766: valgrind error when using convert() in a subquery +# +CREATE TABLE t1(a tinyint); +INSERT INTO t1 VALUES (127); +SELECT 1 FROM +( +SELECT CONVERT(t2.a USING UTF8) FROM t1, t1 t2 LIMIT 1 +) AS s LIMIT 1; +1 +1 +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result index 7e7c163716e..75b4888fbb2 100644 --- a/mysql-test/r/func_concat.result +++ b/mysql-test/r/func_concat.result @@ -89,3 +89,34 @@ c1 c2 First DROP TABLE t1; # End of 5.0 tests +# +# Bug #44743: Join in combination with concat does not always work +# +CREATE TABLE t1 ( +a VARCHAR(100) NOT NULL DEFAULT '0', +b VARCHAR(2) NOT NULL DEFAULT '', +c VARCHAR(2) NOT NULL DEFAULT '', +d TEXT NOT NULL, +PRIMARY KEY (a, b, c), +KEY (a) +) DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES ('gui_A', 'a', 'b', 'str1'), +('gui_AB', 'a', 'b', 'str2'), ('gui_ABC', 'a', 'b', 'str3'); +CREATE TABLE t2 ( +a VARCHAR(100) NOT NULL DEFAULT '', +PRIMARY KEY (a) +) DEFAULT CHARSET=latin1; +INSERT INTO t2 VALUES ('A'), ('AB'), ('ABC'); +SELECT CONCAT('gui_', t2.a), t1.d FROM t2 +LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; +CONCAT('gui_', t2.a) d +gui_A str1 +gui_AB str2 +gui_ABC str3 +EXPLAIN SELECT CONCAT('gui_', t2.a), t1.d FROM t2 +LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL PRIMARY 102 NULL 3 Using index +1 SIMPLE t1 eq_ref PRIMARY,a PRIMARY 318 func,const,const 1 +DROP TABLE t1, t2; +# End of 5.1 tests diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 50865215944..8e60d548c2f 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -269,3 +269,18 @@ SELECT HOUR(NULL), DROP TABLE t1; --echo End of 5.0 tests + +--echo # +--echo # Bug #44766: valgrind error when using convert() in a subquery +--echo # + +CREATE TABLE t1(a tinyint); +INSERT INTO t1 VALUES (127); +SELECT 1 FROM +( + SELECT CONVERT(t2.a USING UTF8) FROM t1, t1 t2 LIMIT 1 +) AS s LIMIT 1; +DROP TABLE t1; + + +--echo End of 5.1 tests diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test index f2aa0d004e5..1c7e5823fb2 100644 --- a/mysql-test/t/func_concat.test +++ b/mysql-test/t/func_concat.test @@ -78,3 +78,37 @@ SELECT * FROM t1 WHERE CONCAT(c1,' ',c2) REGEXP 'First.*'; DROP TABLE t1; --echo # End of 5.0 tests + + +--echo # +--echo # Bug #44743: Join in combination with concat does not always work +--echo # +CREATE TABLE t1 ( + a VARCHAR(100) NOT NULL DEFAULT '0', + b VARCHAR(2) NOT NULL DEFAULT '', + c VARCHAR(2) NOT NULL DEFAULT '', + d TEXT NOT NULL, + PRIMARY KEY (a, b, c), + KEY (a) +) DEFAULT CHARSET=utf8; + +INSERT INTO t1 VALUES ('gui_A', 'a', 'b', 'str1'), + ('gui_AB', 'a', 'b', 'str2'), ('gui_ABC', 'a', 'b', 'str3'); + +CREATE TABLE t2 ( + a VARCHAR(100) NOT NULL DEFAULT '', + PRIMARY KEY (a) +) DEFAULT CHARSET=latin1; + +INSERT INTO t2 VALUES ('A'), ('AB'), ('ABC'); + +SELECT CONCAT('gui_', t2.a), t1.d FROM t2 + LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; + +EXPLAIN SELECT CONCAT('gui_', t2.a), t1.d FROM t2 + LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; + +DROP TABLE t1, t2; + + +--echo # End of 5.1 tests diff --git a/sql/item.cc b/sql/item.cc index 8a8c3610198..62c8bfa3043 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4873,7 +4873,10 @@ int Item_null::save_safe_in_field(Field *field) /* This implementation can lose str_value content, so if the Item uses str_value to store something, it should - reimplement it's ::save_in_field() as Item_string, for example, does + reimplement it's ::save_in_field() as Item_string, for example, does. + + Note: all Item_XXX::val_str(str) methods must NOT rely on the fact that + str != str_value. For example, see fix for bug #44743. */ int Item::save_in_field(Field *field, bool no_conversions) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 501b7e85080..a3140b4db64 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2706,8 +2706,15 @@ String *Item_func_conv_charset::val_str(String *str) DBUG_ASSERT(fixed == 1); if (use_cached_value) return null_value ? 0 : &str_value; - String *arg= args[0]->val_str(str); + /* + Here we don't pass 'str' as a parameter to args[0]->val_str() + as 'str' may points to 'str_value' (e.g. see Item::save_in_field()), + which we use below to convert string. + Use argument's 'str_value' instead. + */ + String *arg= args[0]->val_str(&args[0]->str_value);; uint dummy_errors; + arg= args[0]->val_str(&args[0]->str_value); if (!arg) { null_value=1; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 1dd7b55d136..61731f3b984 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -328,6 +328,9 @@ bool String::copy(const char *str, uint32 arg_length, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors) { uint32 offset; + + DBUG_ASSERT(str != Ptr); + if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) { *errors= 0; From 2cd3eaf27d461d4563d7f1719a022b8d55d67849 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Thu, 21 May 2009 19:14:56 +0400 Subject: [PATCH 102/115] Fixed a PB failure introduced by the patch for bug #44796. Set max_allowed_packet to get a consistent error message. --- mysql-test/r/func_compress.result | 5 ++++- mysql-test/t/func_compress.test | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result index a30ca7859f1..af3c5905678 100644 --- a/mysql-test/r/func_compress.result +++ b/mysql-test/r/func_compress.result @@ -116,6 +116,8 @@ Warnings: Error 1259 ZLIB: Input data corrupted Error 1259 ZLIB: Input data corrupted drop table t1; +SET @old_max_allowed_packet = @@max_allowed_packet; +SET @@max_allowed_packet = 1024 * 1024; CREATE TABLE t1 (c1 INT); INSERT INTO t1 VALUES (1), (1111), (11111); SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; @@ -128,7 +130,8 @@ Error 1259 ZLIB: Input data corrupted Error 1259 ZLIB: Input data corrupted Error 1259 ZLIB: Input data corrupted Error 1259 ZLIB: Input data corrupted -Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +Error 1256 Uncompressed data size too large; the maximum size is 1048576 (probably, length of uncompressed data was corrupted) EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; +SET @@max_allowed_packet = @old_max_allowed_packet; DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test index b1a37c16c6d..8df26dce2ee 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -87,6 +87,9 @@ drop table t1; # uncompressed_length # +SET @old_max_allowed_packet = @@max_allowed_packet; +SET @@max_allowed_packet = 1024 * 1024; + CREATE TABLE t1 (c1 INT); INSERT INTO t1 VALUES (1), (1111), (11111); @@ -97,6 +100,8 @@ SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; --enable_result_log +SET @@max_allowed_packet = @old_max_allowed_packet; + DROP TABLE t1; --echo End of 5.0 tests From 82c878f913daacb7d047efea172e0b3fa491e122 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Thu, 21 May 2009 21:50:17 +0400 Subject: [PATCH 103/115] Attempt #2 to fix PB failures introduced by the patch for bug #44796. Since max_allowed_packet is a read-only variable in 5.1 and up, disable warnings to avoid unnecessary test case complication. --- mysql-test/r/func_compress.result | 9 --------- mysql-test/t/func_compress.test | 8 +++----- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result index af3c5905678..d8745c38f57 100644 --- a/mysql-test/r/func_compress.result +++ b/mysql-test/r/func_compress.result @@ -116,8 +116,6 @@ Warnings: Error 1259 ZLIB: Input data corrupted Error 1259 ZLIB: Input data corrupted drop table t1; -SET @old_max_allowed_packet = @@max_allowed_packet; -SET @@max_allowed_packet = 1024 * 1024; CREATE TABLE t1 (c1 INT); INSERT INTO t1 VALUES (1), (1111), (11111); SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; @@ -125,13 +123,6 @@ UNCOMPRESS(c1) UNCOMPRESSED_LENGTH(c1) NULL NULL NULL NULL NULL 825307441 -Warnings: -Error 1259 ZLIB: Input data corrupted -Error 1259 ZLIB: Input data corrupted -Error 1259 ZLIB: Input data corrupted -Error 1259 ZLIB: Input data corrupted -Error 1256 Uncompressed data size too large; the maximum size is 1048576 (probably, length of uncompressed data was corrupted) EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; -SET @@max_allowed_packet = @old_max_allowed_packet; DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test index 8df26dce2ee..c84f22c5595 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -87,21 +87,19 @@ drop table t1; # uncompressed_length # -SET @old_max_allowed_packet = @@max_allowed_packet; -SET @@max_allowed_packet = 1024 * 1024; - CREATE TABLE t1 (c1 INT); INSERT INTO t1 VALUES (1), (1111), (11111); +# Disable warnings to avoid dependency on max_allowed_packet value +--disable_warnings SELECT UNCOMPRESS(c1), UNCOMPRESSED_LENGTH(c1) FROM t1; +--enable_warnings # We do not need the results, just make sure there are no valgrind errors --disable_result_log EXPLAIN EXTENDED SELECT * FROM (SELECT UNCOMPRESSED_LENGTH(c1) FROM t1) AS s; --enable_result_log -SET @@max_allowed_packet = @old_max_allowed_packet; - DROP TABLE t1; --echo End of 5.0 tests From 2a47699cad56952ff5d22e18b080a2aacf4c91b4 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Thu, 21 May 2009 16:03:53 -0400 Subject: [PATCH 104/115] Bug#40465: mysqldump.test does no checking of dump or restore. Created new .test file - mysqldump_restore that does this for a limited number of basic cases. Created new .inc file - mysqldump.inc - renames original table and uses mysqldump output to recreate the table, then uses diff_tables.inc to compare the two tables. Backported include/diff_tables.inc to facilitate this testing. --- mysql-test/include/diff_tables.inc | 122 ++++++++++++++++++++++++++ mysql-test/include/mysqldump.inc | 41 +++++++++ mysql-test/r/mysqldump_restore.result | 110 +++++++++++++++++++++++ mysql-test/t/mysqldump_restore.test | 120 +++++++++++++++++++++++++ 4 files changed, 393 insertions(+) create mode 100644 mysql-test/include/diff_tables.inc create mode 100644 mysql-test/include/mysqldump.inc create mode 100644 mysql-test/r/mysqldump_restore.result create mode 100644 mysql-test/t/mysqldump_restore.test diff --git a/mysql-test/include/diff_tables.inc b/mysql-test/include/diff_tables.inc new file mode 100644 index 00000000000..d15dd56b35d --- /dev/null +++ b/mysql-test/include/diff_tables.inc @@ -0,0 +1,122 @@ +# ==== Purpose ==== +# +# Check if the two given tables (possibly residing on different +# master/slave servers) are equal. +# +# ==== Usage ==== +# +# The tables to check are given by the test language variables +# $diff_table_1 and $diff_table_2. They must be of the +# following form: +# +# [master:|slave:]database.table +# +# I.e., both database and table must be speicified. Optionally, you +# can prefix the name with 'master:' (to read the table on master) or +# with 'slave:' (to read the table on slave). If no prefix is given, +# reads the table from the current connection. If one of these +# variables has a prefix, both should have a prefix. +# +# ==== Side effects ==== +# +# - Prints "Comparing tables $diff_table_1 and $diff_tables_2". +# +# - If the tables are different, prints the difference in a +# system-specific format (unified diff if supported) and generates +# an error. +# +# - If $diff_table_1 or $diff_table_2 begins with 'master:' or +# 'slave:', it will stay connected to one of those hosts after +# execution. The host is only guaranteed to remain unchanged if +# none of $diff_table_1 or $diff_table_2 begins with 'master:' or +# 'slave:'. +# +# ==== Bugs ==== +# +# - It is currently not possible to use this for tables that are +# supposed to be different, because if the files are different: +# - 'diff' produces system-dependent output, +# - the output includes the absolute path of the compared files, +# - the output includes a timestamp. +# To fix that, we'd probably have to use SQL to compute the +# symmetric difference between the tables. I'm not sure how to do +# that efficiently. If we implement this, it would be nice to +# compare the table definitions too. +# +# - It actually compares the result of "SELECT * FROM table ORDER BY +# col1, col2, ..., colN INTO OUTFILE 'file'". Hence, it is assumed +# that the comparison orders for both tables are equal and that two +# rows that are equal in the comparison order cannot differ, e.g., +# by character case. + + +# ==== Save both tables to file ==== + +--echo Comparing tables $diff_table_1 and $diff_table_2 +disable_query_log; + +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_1 +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_2 + +let $_diff_table=$diff_table_2; +let $_diff_i=2; +while ($_diff_i) { + + # Parse out any leading "master:" or "slave:" from the table + # specification and connect the appropriate server. + let $_diff_conn_master=`SELECT SUBSTR('$_diff_table', 1, 7) = 'master:'`; + if ($_diff_conn_master) { + let $_diff_table=`SELECT SUBSTR('$_diff_table', 8)`; + connection master; + } + let $_diff_conn_slave=`SELECT SUBSTR('$_diff_table', 1, 6) = 'slave:'`; + if ($_diff_conn_slave) { + let $_diff_table=`SELECT SUBSTR('$_diff_table', 7)`; + connection slave; + } + + # Sanity-check the input. + let $_diff_error= `SELECT '$_diff_table' NOT LIKE '_%._%'`; + if ($_diff_error) { + --echo !!!ERROR IN TEST: \$diff_table_$_diff_i='$_diff_table' is not in the form database.table + exit; + } + + # We need the output files to be sorted (so that diff_files does not + # think the files are different just because they are differently + # ordered). To this end, we first generate a query that sorts the + # table by all columns. Since ORDER BY accept column indices, we + # just generate a comma-separated list of all numbers from 1 to the + # number of columns in the table. + let $_diff_column_index=`SELECT MAX(ordinal_position) + FROM information_schema.columns + WHERE CONCAT(table_schema, '.', table_name) = + '$_diff_table'`; + let $_diff_column_list=$_diff_column_index; + dec $_diff_column_index; + while ($_diff_column_index) { + let $_diff_column_list=$_diff_column_index, $_diff_column_list; + dec $_diff_column_index; + } + + # Now that we have the comma-separated list of columns, we can write + # the table to a file. + eval SELECT * FROM $_diff_table ORDER BY $_diff_column_list + INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/diff_table_$_diff_i'; + + # Do the same for $diff_table_1. + dec $_diff_i; + let $_diff_table=$diff_table_1; +} + + +# ==== Compare the generated files ==== + +diff_files $MYSQLTEST_VARDIR/tmp/diff_table_1 $MYSQLTEST_VARDIR/tmp/diff_table_2; + +--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_1 +--remove_file $MYSQLTEST_VARDIR/tmp/diff_table_2 + +enable_query_log; diff --git a/mysql-test/include/mysqldump.inc b/mysql-test/include/mysqldump.inc new file mode 100644 index 00000000000..fb22ab0bc74 --- /dev/null +++ b/mysql-test/include/mysqldump.inc @@ -0,0 +1,41 @@ +################################################################################ +# mysqldump.inc +# SUMMARY: include file to facilitate testing the quality of mysqldump output +# INPUTS: Two variables: +# $table_name - the name of the table that was dumped +# $mysqldumpfile - the name of the file that captured mysqldump output +# OUTPUTS: minor echo data: +# We 'echo' some stage information to the .result file: +# 'altering original table', 'restoring from dumpfile', 'comparing' +# OTHER FILES: We use include/diff_tables.inc to compare the original, renamed +# table with the 'restored' one. +# DESCRIPTION: This file works by being fed the name of the original table +# and a mysqldump output file. The original table is then renamed +# to _orig, the mysqldump file is used to recreate the +# table, then diff_tables.inc is called to compare them. +# LIMITATIONS: Does *NOT* work with xml output! +# AUTHOR: pcrews +# LAST CHANGE: 2009-05-21 +# PURPOSE: Bug#40465: mysqldump.test does no checking of dump or restore +################################################################################ + +--echo # Begin testing mysqldump output + restore +--echo # Create 'original table name - _orig +# NOTE: We use SET then let as query_get_value has issues with the extra commas +# used in the CONCAT statement. +eval SET @orig_table_name = CONCAT('$table_name', '_orig'); +let $orig_table_name = query_get_value(SELECT @orig_table_name,@orig_table_name,1); +--echo # Rename original table +eval ALTER TABLE $table_name RENAME to $orig_table_name; +--echo # Recreate table from mysqldump output +--exec $MYSQL test < $mysqldumpfile +--echo # Compare original and recreated tables +--echo # Recreated table: $table_name +--echo # Original table: $orig_table_name +let $diff_table_1 = $table_name; +let $diff_table_2 = $orig_table_name; +--source include/diff_tables.inc +--echo # Cleanup +--remove_file $mysqldumpfile +eval DROP TABLE $table_name, $orig_table_name; + diff --git a/mysql-test/r/mysqldump_restore.result b/mysql-test/r/mysqldump_restore.result new file mode 100644 index 00000000000..1e106c3be11 --- /dev/null +++ b/mysql-test/r/mysqldump_restore.result @@ -0,0 +1,110 @@ +# Set concurrent_insert = 0 to prevent random errors +# will reset to original value at the end of the test +SET @old_concurrent_insert = @@global.concurrent_insert; +SET @@global.concurrent_insert = 0; +# Pre-test cleanup +DROP TABLE IF EXISTS t1; +# Begin tests +# +# Bug#2005 Long decimal comparison bug. +# +CREATE TABLE t1 (a decimal(64, 20)); +INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), +("0987654321098765432109876543210987654321"); +# Begin testing mysqldump output + restore +# Create 'original table name -
_orig +SET @orig_table_name = CONCAT('test.t1', '_orig'); +# Rename original table +ALTER TABLE test.t1 RENAME to test.t1_orig; +# Recreate table from mysqldump output +# Compare original and recreated tables +# Recreated table: test.t1 +# Original table: test.t1_orig +Comparing tables test.t1 and test.t1_orig +# Cleanup +DROP TABLE test.t1, test.t1_orig; +# +# Bug#3361 mysqldump quotes DECIMAL values inconsistently +# +CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); +INSERT INTO t1 VALUES (1.2345, 2.3456); +INSERT INTO t1 VALUES ('1.2345', 2.3456); +INSERT INTO t1 VALUES ("1.2345", 2.3456); +SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI_QUOTES'; +INSERT INTO t1 VALUES (1.2345, 2.3456); +INSERT INTO t1 VALUES ('1.2345', 2.3456); +INSERT INTO t1 VALUES ("1.2345", 2.3456); +ERROR 42S22: Unknown column '1.2345' in 'field list' +SET SQL_MODE=@OLD_SQL_MODE; +# Begin testing mysqldump output + restore +# Create 'original table name -
_orig +SET @orig_table_name = CONCAT('test.t1', '_orig'); +# Rename original table +ALTER TABLE test.t1 RENAME to test.t1_orig; +# Recreate table from mysqldump output +# Compare original and recreated tables +# Recreated table: test.t1 +# Original table: test.t1_orig +Comparing tables test.t1 and test.t1_orig +# Cleanup +DROP TABLE test.t1, test.t1_orig; +# +# Bug#1994 mysqldump does not correctly dump UCS2 data +# Bug#4261 mysqldump 10.7 (mysql 4.1.2) --skip-extended-insert drops NULL from inserts +# +CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; +INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); +# Begin testing mysqldump output + restore +# Create 'original table name -
_orig +SET @orig_table_name = CONCAT('test.t1', '_orig'); +# Rename original table +ALTER TABLE test.t1 RENAME to test.t1_orig; +# Recreate table from mysqldump output +# Compare original and recreated tables +# Recreated table: test.t1 +# Original table: test.t1_orig +Comparing tables test.t1 and test.t1_orig +# Cleanup +DROP TABLE test.t1, test.t1_orig; +# +# WL#2319 Exclude Tables from dump +# +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t2 VALUES (4),(5),(6); +# Begin testing mysqldump output + restore +# Create 'original table name -
_orig +SET @orig_table_name = CONCAT('test.t2', '_orig'); +# Rename original table +ALTER TABLE test.t2 RENAME to test.t2_orig; +# Recreate table from mysqldump output +# Compare original and recreated tables +# Recreated table: test.t2 +# Original table: test.t2_orig +Comparing tables test.t2 and test.t2_orig +# Cleanup +DROP TABLE test.t2, test.t2_orig; +DROP TABLE t1; +# +# Bug#8830 mysqldump --skip-extended-insert causes --hex-blob to dump wrong values +# +CREATE TABLE t1 (`b` blob); +INSERT INTO `t1` VALUES (0x602010000280100005E71A); +# Begin testing mysqldump output + restore +# Create 'original table name -
_orig +SET @orig_table_name = CONCAT('test.t1', '_orig'); +# Rename original table +ALTER TABLE test.t1 RENAME to test.t1_orig; +# Recreate table from mysqldump output +# Compare original and recreated tables +# Recreated table: test.t1 +# Original table: test.t1_orig +Comparing tables test.t1 and test.t1_orig +# Cleanup +DROP TABLE test.t1, test.t1_orig; +# End tests +# Cleanup +# Reset concurrent_insert to its original value +SET @@global.concurrent_insert = @old_concurrent_insert; +# remove mysqldumpfile diff --git a/mysql-test/t/mysqldump_restore.test b/mysql-test/t/mysqldump_restore.test new file mode 100644 index 00000000000..c5220e5de69 --- /dev/null +++ b/mysql-test/t/mysqldump_restore.test @@ -0,0 +1,120 @@ +############################################################################### +# mysqldump_restore.test +# Purpose: Tests if mysqldump output can be used to successfully restore +# tables and data. +# We CREATE a table, mysqldump it to a file, ALTER the original +# table's name, recreate the table from the mysqldump file, then +# utilize include/diff_tables to compare the original and recreated +# tables. +# +# We use several examples from mysqldump.test here and include +# the relevant bug numbers and headers from that test. +# +# NOTE: This test is not currently complete and offers only basic +# cases of mysqldump output being restored. +# Also, does NOT work with -X (xml) output! +# +# Author: pcrews +# Created: 2009-05-21 +# Last Change: +# Change date: +############################################################################### + +# Embedded server doesn't support external clients +--source include/not_embedded.inc +--source include/have_log_bin.inc + +--echo # Set concurrent_insert = 0 to prevent random errors +--echo # will reset to original value at the end of the test +SET @old_concurrent_insert = @@global.concurrent_insert; +SET @@global.concurrent_insert = 0; + +# Define mysqldumpfile here. It is used to capture mysqldump output +# in order to test the output's ability to restore an exact copy of the table +let $mysqldumpfile = $MYSQLTEST_VARDIR/tmp/mysqldumpfile.sql; + +--echo # Pre-test cleanup +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo # Begin tests +--echo # +--echo # Bug#2005 Long decimal comparison bug. +--echo # + +CREATE TABLE t1 (a decimal(64, 20)); +INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), +("0987654321098765432109876543210987654321"); +--exec $MYSQL_DUMP --compact test t1 > $mysqldumpfile +let $table_name = test.t1; +--source include/mysqldump.inc + +--echo # +--echo # Bug#3361 mysqldump quotes DECIMAL values inconsistently +--echo # + +CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); + +# check at first how mysql work with quoted decimal + +INSERT INTO t1 VALUES (1.2345, 2.3456); +INSERT INTO t1 VALUES ('1.2345', 2.3456); +INSERT INTO t1 VALUES ("1.2345", 2.3456); + +SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI_QUOTES'; +INSERT INTO t1 VALUES (1.2345, 2.3456); +INSERT INTO t1 VALUES ('1.2345', 2.3456); +--error ER_BAD_FIELD_ERROR +INSERT INTO t1 VALUES ("1.2345", 2.3456); +SET SQL_MODE=@OLD_SQL_MODE; + +# check how mysqldump make quoting +--exec $MYSQL_DUMP --compact test t1 > $mysqldumpfile +let $table_name = test.t1; +--source include/mysqldump.inc + +--echo # +--echo # Bug#1994 mysqldump does not correctly dump UCS2 data +--echo # Bug#4261 mysqldump 10.7 (mysql 4.1.2) --skip-extended-insert drops NULL from inserts +--echo # + +CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; +INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); +--exec $MYSQL_DUMP --skip-comments --skip-extended-insert test t1 > $mysqldumpfile +let $table_name = test.t1; +--source include/mysqldump.inc + +--echo # +--echo # WL#2319 Exclude Tables from dump +--echo # + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t2 VALUES (4),(5),(6); +--exec $MYSQL_DUMP --skip-comments --ignore-table=test.t1 test > $mysqldumpfile +let $table_name = test.t2; +--source include/mysqldump.inc +DROP TABLE t1; + +--echo # +--echo # Bug#8830 mysqldump --skip-extended-insert causes --hex-blob to dump wrong values +--echo # + +CREATE TABLE t1 (`b` blob); +INSERT INTO `t1` VALUES (0x602010000280100005E71A); +--exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 > $mysqldumpfile +let $table_name = test.t1; +--source include/mysqldump.inc + + + +--echo # End tests + +--echo # Cleanup +--echo # Reset concurrent_insert to its original value +SET @@global.concurrent_insert = @old_concurrent_insert; +--echo # remove mysqldumpfile +--error 0,1 +--remove_file $mysqldumpfile From 06142cd5452efc4ea0ac48d9340dd28f4a9e520b Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 22 May 2009 01:22:46 +0500 Subject: [PATCH 105/115] Bug #42778: delete order by null global variable causes assertion .\filesort.cc, line 797 A query with the "ORDER BY @@some_system_variable" clause, where @@some_system_variable is NULL, causes assertion failure in the filesort procedures. The reason of the failure is in the value of Item_func_get_system_var::maybe_null: it was unconditionally set to false even if the value of a variable was NULL. mysql-test/r/variables.result: Added test case for bug #42778. mysql-test/suite/sys_vars/r/innodb_data_home_dir_basic.result: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/r/innodb_flush_method_basic.result: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/r/rpl_init_slave_func.result: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/r/ssl_capath_basic.result: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/r/ssl_cipher_basic.result: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/t/innodb_data_home_dir_basic.test: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/t/innodb_flush_method_basic.test: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/t/ssl_capath_basic.test: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/suite/sys_vars/t/ssl_cipher_basic.test: Updated test case for bug #42778: system variables were NOT NULL, now they are nullable. mysql-test/t/variables.test: Added test case for bug #42778. sql/item.cc: Bug #42778: delete order by null global variable causes assertion .\filesort.cc, line 797 The longlong_from_string_with_check function has been modified to skip unwanted warnings: now it uses the THD::no_errors flag to suppress warnings. The Item_func_get_system_var::update_null_value method sets the no_error flag. sql/item_func.cc: Bug #42778: delete order by null global variable causes assertion .\filesort.cc, line 797 1. The Item_func_get_system_var::fix_length_and_dec method has been modified to make system variables truly nullable. 2. The Item_func_get_system_var::update_null_value method method has been overloaded with a simple wrapper (like Item_field::update_null_value) to suppress unwanted warnings from Item_func_get_system_var::val_int() calls on non-numeric variable values: the Item_func_get_system_var::update_null_value method sets and restores THD::no_errors flag for a nested call of the longlong_from_string_with_check function. sql/item_func.h: Bug #42778: delete order by null global variable causes assertion .\filesort.cc, line 797 The Item_func_get_system_var::update_null_value method method has been overloaded. --- mysql-test/r/variables.result | 21 ++++++++++++++++++- .../r/innodb_data_home_dir_basic.result | 20 +++++++++--------- .../r/innodb_flush_method_basic.result | 20 +++++++++--------- .../sys_vars/r/rpl_init_slave_func.result | 2 +- .../suite/sys_vars/r/ssl_capath_basic.result | 20 +++++++++--------- .../suite/sys_vars/r/ssl_cipher_basic.result | 20 +++++++++--------- .../t/innodb_data_home_dir_basic.test | 10 ++++----- .../sys_vars/t/innodb_flush_method_basic.test | 10 ++++----- .../suite/sys_vars/t/ssl_capath_basic.test | 10 ++++----- .../suite/sys_vars/t/ssl_cipher_basic.test | 10 ++++----- mysql-test/t/variables.test | 19 +++++++++++++++++ sql/item.cc | 5 +++-- sql/item_func.cc | 12 ++++++++++- sql/item_func.h | 1 + 14 files changed, 115 insertions(+), 65 deletions(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index f27d0b9fdd5..244a40a0f30 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -1436,7 +1436,7 @@ Warnings: Warning 1292 Truncated incorrect auto_increment_offset value: '0' select @@storage_engine; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def @@storage_engine 253 6 6 N 1 31 8 +def @@storage_engine 253 6 6 Y 0 31 8 @@storage_engine MyISAM SET @old_server_id = @@GLOBAL.server_id; @@ -1467,4 +1467,23 @@ SELECT @@GLOBAL.server_id; @@GLOBAL.server_id 0 SET GLOBAL server_id = @old_server_id; +SELECT @@GLOBAL.INIT_FILE, @@GLOBAL.INIT_FILE IS NULL; +@@GLOBAL.INIT_FILE @@GLOBAL.INIT_FILE IS NULL +NULL 1 +SELECT @@GLOBAL.REPORT_HOST, @@GLOBAL.REPORT_HOST IS NULL; +@@GLOBAL.REPORT_HOST @@GLOBAL.REPORT_HOST IS NULL +NULL 1 +SELECT @@GLOBAL.REPORT_PASSWORD, @@GLOBAL.REPORT_PASSWORD IS NULL; +@@GLOBAL.REPORT_PASSWORD @@GLOBAL.REPORT_PASSWORD IS NULL +NULL 1 +SELECT @@GLOBAL.REPORT_USER, @@GLOBAL.REPORT_USER IS NULL; +@@GLOBAL.REPORT_USER @@GLOBAL.REPORT_USER IS NULL +NULL 1 +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (); +SET @bug42778= @@sql_safe_updates; +SET @@sql_safe_updates= 0; +DELETE FROM t1 ORDER BY (@@GLOBAL.INIT_FILE) ASC LIMIT 10; +SET @@sql_safe_updates= @bug42778; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/suite/sys_vars/r/innodb_data_home_dir_basic.result b/mysql-test/suite/sys_vars/r/innodb_data_home_dir_basic.result index e4bdd79b7c3..52a97bb6c95 100644 --- a/mysql-test/suite/sys_vars/r/innodb_data_home_dir_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_data_home_dir_basic.result @@ -1,16 +1,16 @@ '#---------------------BS_STVARS_025_01----------------------#' SELECT COUNT(@@GLOBAL.innodb_data_home_dir); COUNT(@@GLOBAL.innodb_data_home_dir) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_025_02----------------------#' SET @@GLOBAL.innodb_data_home_dir=1; ERROR HY000: Variable 'innodb_data_home_dir' is a read only variable Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.innodb_data_home_dir); COUNT(@@GLOBAL.innodb_data_home_dir) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_025_03----------------------#' SELECT @@GLOBAL.innodb_data_home_dir = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -20,8 +20,8 @@ NULL 1 Expected SELECT COUNT(@@GLOBAL.innodb_data_home_dir); COUNT(@@GLOBAL.innodb_data_home_dir) -1 -1 Expected +0 +0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_data_home_dir'; @@ -36,8 +36,8 @@ NULL '#---------------------BS_STVARS_025_05----------------------#' SELECT COUNT(@@innodb_data_home_dir); COUNT(@@innodb_data_home_dir) -1 -1 Expected +0 +0 Expected SELECT COUNT(@@local.innodb_data_home_dir); ERROR HY000: Variable 'innodb_data_home_dir' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' @@ -46,8 +46,8 @@ ERROR HY000: Variable 'innodb_data_home_dir' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.innodb_data_home_dir); COUNT(@@GLOBAL.innodb_data_home_dir) -1 -1 Expected +0 +0 Expected SELECT innodb_data_home_dir = @@SESSION.innodb_data_home_dir; ERROR 42S22: Unknown column 'innodb_data_home_dir' in 'field list' Expected error 'Readonly variable' diff --git a/mysql-test/suite/sys_vars/r/innodb_flush_method_basic.result b/mysql-test/suite/sys_vars/r/innodb_flush_method_basic.result index 8c8924cdd86..4a85748092d 100644 --- a/mysql-test/suite/sys_vars/r/innodb_flush_method_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_flush_method_basic.result @@ -1,16 +1,16 @@ '#---------------------BS_STVARS_029_01----------------------#' SELECT COUNT(@@GLOBAL.innodb_flush_method); COUNT(@@GLOBAL.innodb_flush_method) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_029_02----------------------#' SET @@GLOBAL.innodb_flush_method=1; ERROR HY000: Variable 'innodb_flush_method' is a read only variable Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.innodb_flush_method); COUNT(@@GLOBAL.innodb_flush_method) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_029_03----------------------#' SELECT @@GLOBAL.innodb_flush_method = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -20,8 +20,8 @@ NULL 1 Expected SELECT COUNT(@@GLOBAL.innodb_flush_method); COUNT(@@GLOBAL.innodb_flush_method) -1 -1 Expected +0 +0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_flush_method'; @@ -36,8 +36,8 @@ NULL '#---------------------BS_STVARS_029_05----------------------#' SELECT COUNT(@@innodb_flush_method); COUNT(@@innodb_flush_method) -1 -1 Expected +0 +0 Expected SELECT COUNT(@@local.innodb_flush_method); ERROR HY000: Variable 'innodb_flush_method' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' @@ -46,8 +46,8 @@ ERROR HY000: Variable 'innodb_flush_method' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.innodb_flush_method); COUNT(@@GLOBAL.innodb_flush_method) -1 -1 Expected +0 +0 Expected SELECT innodb_flush_method = @@SESSION.innodb_flush_method; ERROR 42S22: Unknown column 'innodb_flush_method' in 'field list' Expected error 'Readonly variable' diff --git a/mysql-test/suite/sys_vars/r/rpl_init_slave_func.result b/mysql-test/suite/sys_vars/r/rpl_init_slave_func.result index 5f730bff882..bdb586e84c2 100644 --- a/mysql-test/suite/sys_vars/r/rpl_init_slave_func.result +++ b/mysql-test/suite/sys_vars/r/rpl_init_slave_func.result @@ -12,7 +12,7 @@ DROP TABLE IF EXISTS t1; CREATE TEMPORARY TABLE t1 AS SELECT @@global.init_slave AS my_column; DESCRIBE t1; Field Type Null Key Default Extra -my_column varchar(59) NO +my_column varchar(59) YES NULL DROP TABLE t1; SELECT @@global.init_slave = 'SET @@global.max_connections = @@global.max_connections + 1'; @@global.init_slave = 'SET @@global.max_connections = @@global.max_connections + 1' diff --git a/mysql-test/suite/sys_vars/r/ssl_capath_basic.result b/mysql-test/suite/sys_vars/r/ssl_capath_basic.result index 3d161392917..f04b85b956f 100644 --- a/mysql-test/suite/sys_vars/r/ssl_capath_basic.result +++ b/mysql-test/suite/sys_vars/r/ssl_capath_basic.result @@ -1,16 +1,16 @@ '#---------------------BS_STVARS_046_01----------------------#' SELECT COUNT(@@GLOBAL.ssl_capath); COUNT(@@GLOBAL.ssl_capath) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_046_02----------------------#' SET @@GLOBAL.ssl_capath=1; ERROR HY000: Variable 'ssl_capath' is a read only variable Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.ssl_capath); COUNT(@@GLOBAL.ssl_capath) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_046_03----------------------#' SELECT @@GLOBAL.ssl_capath = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -20,8 +20,8 @@ NULL 1 Expected SELECT COUNT(@@GLOBAL.ssl_capath); COUNT(@@GLOBAL.ssl_capath) -1 -1 Expected +0 +0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='ssl_capath'; @@ -36,8 +36,8 @@ NULL '#---------------------BS_STVARS_046_05----------------------#' SELECT COUNT(@@ssl_capath); COUNT(@@ssl_capath) -1 -1 Expected +0 +0 Expected SELECT COUNT(@@local.ssl_capath); ERROR HY000: Variable 'ssl_capath' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' @@ -46,8 +46,8 @@ ERROR HY000: Variable 'ssl_capath' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.ssl_capath); COUNT(@@GLOBAL.ssl_capath) -1 -1 Expected +0 +0 Expected SELECT ssl_capath = @@SESSION.ssl_capath; ERROR 42S22: Unknown column 'ssl_capath' in 'field list' Expected error 'Readonly variable' diff --git a/mysql-test/suite/sys_vars/r/ssl_cipher_basic.result b/mysql-test/suite/sys_vars/r/ssl_cipher_basic.result index df0fc8b5aad..0eed40d0580 100644 --- a/mysql-test/suite/sys_vars/r/ssl_cipher_basic.result +++ b/mysql-test/suite/sys_vars/r/ssl_cipher_basic.result @@ -1,16 +1,16 @@ '#---------------------BS_STVARS_048_01----------------------#' SELECT COUNT(@@GLOBAL.ssl_cipher); COUNT(@@GLOBAL.ssl_cipher) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_048_02----------------------#' SET @@GLOBAL.ssl_cipher=1; ERROR HY000: Variable 'ssl_cipher' is a read only variable Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.ssl_cipher); COUNT(@@GLOBAL.ssl_cipher) -1 -1 Expected +0 +0 Expected '#---------------------BS_STVARS_048_03----------------------#' SELECT @@GLOBAL.ssl_cipher = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -20,8 +20,8 @@ NULL 1 Expected SELECT COUNT(@@GLOBAL.ssl_cipher); COUNT(@@GLOBAL.ssl_cipher) -1 -1 Expected +0 +0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='ssl_cipher'; @@ -36,8 +36,8 @@ NULL '#---------------------BS_STVARS_048_05----------------------#' SELECT COUNT(@@ssl_cipher); COUNT(@@ssl_cipher) -1 -1 Expected +0 +0 Expected SELECT COUNT(@@local.ssl_cipher); ERROR HY000: Variable 'ssl_cipher' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' @@ -46,8 +46,8 @@ ERROR HY000: Variable 'ssl_cipher' is a GLOBAL variable Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.ssl_cipher); COUNT(@@GLOBAL.ssl_cipher) -1 -1 Expected +0 +0 Expected SELECT ssl_cipher = @@SESSION.ssl_cipher; ERROR 42S22: Unknown column 'ssl_cipher' in 'field list' Expected error 'Readonly variable' diff --git a/mysql-test/suite/sys_vars/t/innodb_data_home_dir_basic.test b/mysql-test/suite/sys_vars/t/innodb_data_home_dir_basic.test index f3b02edf83b..acf3741d5fa 100644 --- a/mysql-test/suite/sys_vars/t/innodb_data_home_dir_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_data_home_dir_basic.test @@ -29,7 +29,7 @@ # Displaying default value # #################################################################### SELECT COUNT(@@GLOBAL.innodb_data_home_dir); ---echo 1 Expected +--echo 0 Expected --echo '#---------------------BS_STVARS_025_02----------------------#' @@ -42,7 +42,7 @@ SET @@GLOBAL.innodb_data_home_dir=1; --echo Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.innodb_data_home_dir); ---echo 1 Expected +--echo 0 Expected @@ -58,7 +58,7 @@ WHERE VARIABLE_NAME='innodb_data_home_dir'; --echo 1 Expected SELECT COUNT(@@GLOBAL.innodb_data_home_dir); ---echo 1 Expected +--echo 0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -82,7 +82,7 @@ SELECT @@innodb_data_home_dir = @@GLOBAL.innodb_data_home_dir; ################################################################################ SELECT COUNT(@@innodb_data_home_dir); ---echo 1 Expected +--echo 0 Expected --Error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT COUNT(@@local.innodb_data_home_dir); @@ -93,7 +93,7 @@ SELECT COUNT(@@SESSION.innodb_data_home_dir); --echo Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.innodb_data_home_dir); ---echo 1 Expected +--echo 0 Expected --Error ER_BAD_FIELD_ERROR SELECT innodb_data_home_dir = @@SESSION.innodb_data_home_dir; diff --git a/mysql-test/suite/sys_vars/t/innodb_flush_method_basic.test b/mysql-test/suite/sys_vars/t/innodb_flush_method_basic.test index 531df4a2464..75af00e33af 100644 --- a/mysql-test/suite/sys_vars/t/innodb_flush_method_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_flush_method_basic.test @@ -29,7 +29,7 @@ # Displaying default value # #################################################################### SELECT COUNT(@@GLOBAL.innodb_flush_method); ---echo 1 Expected +--echo 0 Expected --echo '#---------------------BS_STVARS_029_02----------------------#' @@ -42,7 +42,7 @@ SET @@GLOBAL.innodb_flush_method=1; --echo Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.innodb_flush_method); ---echo 1 Expected +--echo 0 Expected @@ -58,7 +58,7 @@ WHERE VARIABLE_NAME='innodb_flush_method'; --echo 1 Expected SELECT COUNT(@@GLOBAL.innodb_flush_method); ---echo 1 Expected +--echo 0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -82,7 +82,7 @@ SELECT @@innodb_flush_method = @@GLOBAL.innodb_flush_method; ################################################################################ SELECT COUNT(@@innodb_flush_method); ---echo 1 Expected +--echo 0 Expected --Error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT COUNT(@@local.innodb_flush_method); @@ -93,7 +93,7 @@ SELECT COUNT(@@SESSION.innodb_flush_method); --echo Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.innodb_flush_method); ---echo 1 Expected +--echo 0 Expected --Error ER_BAD_FIELD_ERROR SELECT innodb_flush_method = @@SESSION.innodb_flush_method; diff --git a/mysql-test/suite/sys_vars/t/ssl_capath_basic.test b/mysql-test/suite/sys_vars/t/ssl_capath_basic.test index c32b572fb1b..ece9fe992d9 100644 --- a/mysql-test/suite/sys_vars/t/ssl_capath_basic.test +++ b/mysql-test/suite/sys_vars/t/ssl_capath_basic.test @@ -27,7 +27,7 @@ # Displaying default value # #################################################################### SELECT COUNT(@@GLOBAL.ssl_capath); ---echo 1 Expected +--echo 0 Expected --echo '#---------------------BS_STVARS_046_02----------------------#' @@ -40,7 +40,7 @@ SET @@GLOBAL.ssl_capath=1; --echo Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.ssl_capath); ---echo 1 Expected +--echo 0 Expected @@ -56,7 +56,7 @@ WHERE VARIABLE_NAME='ssl_capath'; --echo 1 Expected SELECT COUNT(@@GLOBAL.ssl_capath); ---echo 1 Expected +--echo 0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -80,7 +80,7 @@ SELECT @@ssl_capath = @@GLOBAL.ssl_capath; ################################################################################ SELECT COUNT(@@ssl_capath); ---echo 1 Expected +--echo 0 Expected --Error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT COUNT(@@local.ssl_capath); @@ -91,7 +91,7 @@ SELECT COUNT(@@SESSION.ssl_capath); --echo Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.ssl_capath); ---echo 1 Expected +--echo 0 Expected --Error ER_BAD_FIELD_ERROR SELECT ssl_capath = @@SESSION.ssl_capath; diff --git a/mysql-test/suite/sys_vars/t/ssl_cipher_basic.test b/mysql-test/suite/sys_vars/t/ssl_cipher_basic.test index 425f7aae442..c58b22da2d5 100644 --- a/mysql-test/suite/sys_vars/t/ssl_cipher_basic.test +++ b/mysql-test/suite/sys_vars/t/ssl_cipher_basic.test @@ -27,7 +27,7 @@ # Displaying default value # #################################################################### SELECT COUNT(@@GLOBAL.ssl_cipher); ---echo 1 Expected +--echo 0 Expected --echo '#---------------------BS_STVARS_048_02----------------------#' @@ -40,7 +40,7 @@ SET @@GLOBAL.ssl_cipher=1; --echo Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.ssl_cipher); ---echo 1 Expected +--echo 0 Expected @@ -56,7 +56,7 @@ WHERE VARIABLE_NAME='ssl_cipher'; --echo 1 Expected SELECT COUNT(@@GLOBAL.ssl_cipher); ---echo 1 Expected +--echo 0 Expected SELECT COUNT(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -80,7 +80,7 @@ SELECT @@ssl_cipher = @@GLOBAL.ssl_cipher; ################################################################################ SELECT COUNT(@@ssl_cipher); ---echo 1 Expected +--echo 0 Expected --Error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT COUNT(@@local.ssl_cipher); @@ -91,7 +91,7 @@ SELECT COUNT(@@SESSION.ssl_cipher); --echo Expected error 'Variable is a GLOBAL variable' SELECT COUNT(@@GLOBAL.ssl_cipher); ---echo 1 Expected +--echo 0 Expected --Error ER_BAD_FIELD_ERROR SELECT ssl_cipher = @@SESSION.ssl_cipher; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 6da20409639..b404b5b07fb 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -1201,4 +1201,23 @@ SET GLOBAL server_id = -1; SELECT @@GLOBAL.server_id; SET GLOBAL server_id = @old_server_id; +# +# Bug #42778: delete order by null global variable causes +# assertion .\filesort.cc, line 797 +# + +SELECT @@GLOBAL.INIT_FILE, @@GLOBAL.INIT_FILE IS NULL; +SELECT @@GLOBAL.REPORT_HOST, @@GLOBAL.REPORT_HOST IS NULL; +SELECT @@GLOBAL.REPORT_PASSWORD, @@GLOBAL.REPORT_PASSWORD IS NULL; +SELECT @@GLOBAL.REPORT_USER, @@GLOBAL.REPORT_USER IS NULL; + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (); +SET @bug42778= @@sql_safe_updates; +SET @@sql_safe_updates= 0; +DELETE FROM t1 ORDER BY (@@GLOBAL.INIT_FILE) ASC LIMIT 10; +SET @@sql_safe_updates= @bug42778; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/item.cc b/sql/item.cc index 62c8bfa3043..420efb2a4ee 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2472,8 +2472,9 @@ longlong_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end) TODO: Give error if we wanted a signed integer and we got an unsigned one */ - if (err > 0 || - (end != org_end && !check_if_only_end_space(cs, end, org_end))) + if (!current_thd->no_errors && + (err > 0 || + (end != org_end && !check_if_only_end_space(cs, end, org_end)))) { push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, diff --git a/sql/item_func.cc b/sql/item_func.cc index 4bb61f4ef52..0c8f236a27c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4880,10 +4880,20 @@ bool Item_func_get_system_var::is_written_to_binlog() } +void Item_func_get_system_var::update_null_value() +{ + THD *thd= current_thd; + int save_no_errors= thd->no_errors; + thd->no_errors= TRUE; + Item::update_null_value(); + thd->no_errors= save_no_errors; +} + + void Item_func_get_system_var::fix_length_and_dec() { char *cptr; - maybe_null=0; + maybe_null= TRUE; max_length= 0; if (var->check_type(var_type)) diff --git a/sql/item_func.h b/sql/item_func.h index e512c94efc1..67049af81a2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1455,6 +1455,7 @@ public: LEX_STRING *component_arg, const char *name_arg, size_t name_len_arg); enum Functype functype() const { return GSYSVAR_FUNC; } + void update_null_value(); void fix_length_and_dec(); void print(String *str, enum_query_type query_type); bool const_item() const { return true; } From 8354ce0771672b264ad3aac9e056381060edf1e2 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 22 May 2009 11:44:11 +0500 Subject: [PATCH 106/115] Bug #42778: delete order by null global variable causes assertion .\filesort.cc, line 797 Minor fix to test case (embedded server failure). --- mysql-test/r/variables.result | 9 --------- mysql-test/t/variables.test | 3 --- 2 files changed, 12 deletions(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 244a40a0f30..3f79d81dd71 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -1470,15 +1470,6 @@ SET GLOBAL server_id = @old_server_id; SELECT @@GLOBAL.INIT_FILE, @@GLOBAL.INIT_FILE IS NULL; @@GLOBAL.INIT_FILE @@GLOBAL.INIT_FILE IS NULL NULL 1 -SELECT @@GLOBAL.REPORT_HOST, @@GLOBAL.REPORT_HOST IS NULL; -@@GLOBAL.REPORT_HOST @@GLOBAL.REPORT_HOST IS NULL -NULL 1 -SELECT @@GLOBAL.REPORT_PASSWORD, @@GLOBAL.REPORT_PASSWORD IS NULL; -@@GLOBAL.REPORT_PASSWORD @@GLOBAL.REPORT_PASSWORD IS NULL -NULL 1 -SELECT @@GLOBAL.REPORT_USER, @@GLOBAL.REPORT_USER IS NULL; -@@GLOBAL.REPORT_USER @@GLOBAL.REPORT_USER IS NULL -NULL 1 CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (); SET @bug42778= @@sql_safe_updates; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index b404b5b07fb..c568b79185d 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -1207,9 +1207,6 @@ SET GLOBAL server_id = @old_server_id; # SELECT @@GLOBAL.INIT_FILE, @@GLOBAL.INIT_FILE IS NULL; -SELECT @@GLOBAL.REPORT_HOST, @@GLOBAL.REPORT_HOST IS NULL; -SELECT @@GLOBAL.REPORT_PASSWORD, @@GLOBAL.REPORT_PASSWORD IS NULL; -SELECT @@GLOBAL.REPORT_USER, @@GLOBAL.REPORT_USER IS NULL; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (); From e42f28192d582ec84cd62066a6ce0fb83e32ad0b Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Fri, 22 May 2009 10:38:17 -0400 Subject: [PATCH 107/115] Bug#40465 - mysqldump.test does no checking of dump or restore Created new .test file - mysqldump_restore that does test restore from mysqldump output for a limited number of basic cases. Create new .inc file - mysqldump.inc - renames original table and uses mysqldump output to recreate the table, then uses diff_tables.inc to compare the two tables. Backported include/diff_tables.inc to facilitate this testing. New patch incorporating review feedback prior to push. mysqldump.test - removed redundant call to include/have_log_bin.inc (was used twice in the test!) --- mysql-test/include/mysqldump.inc | 15 ++++++++++++--- mysql-test/r/mysqldump_restore.result | 6 +++--- mysql-test/t/mysqldump.test | 1 - mysql-test/t/mysqldump_restore.test | 21 ++++++--------------- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/mysql-test/include/mysqldump.inc b/mysql-test/include/mysqldump.inc index fb22ab0bc74..6227138b012 100644 --- a/mysql-test/include/mysqldump.inc +++ b/mysql-test/include/mysqldump.inc @@ -1,28 +1,37 @@ ################################################################################ # mysqldump.inc +# # SUMMARY: include file to facilitate testing the quality of mysqldump output +# # INPUTS: Two variables: # $table_name - the name of the table that was dumped # $mysqldumpfile - the name of the file that captured mysqldump output +# # OUTPUTS: minor echo data: # We 'echo' some stage information to the .result file: # 'altering original table', 'restoring from dumpfile', 'comparing' +# # OTHER FILES: We use include/diff_tables.inc to compare the original, renamed # table with the 'restored' one. +# # DESCRIPTION: This file works by being fed the name of the original table # and a mysqldump output file. The original table is then renamed # to _orig, the mysqldump file is used to recreate the # table, then diff_tables.inc is called to compare them. +# # LIMITATIONS: Does *NOT* work with xml output! -# AUTHOR: pcrews +# +# AUTHOR: pcrews 2009-05-21 +# Bug#40465 mysqldump.test does no checking of dump or restore +# # LAST CHANGE: 2009-05-21 -# PURPOSE: Bug#40465: mysqldump.test does no checking of dump or restore +# ################################################################################ --echo # Begin testing mysqldump output + restore --echo # Create 'original table name -
_orig # NOTE: We use SET then let as query_get_value has issues with the extra commas -# used in the CONCAT statement. +# used in the CONCAT statement. eval SET @orig_table_name = CONCAT('$table_name', '_orig'); let $orig_table_name = query_get_value(SELECT @orig_table_name,@orig_table_name,1); --echo # Rename original table diff --git a/mysql-test/r/mysqldump_restore.result b/mysql-test/r/mysqldump_restore.result index 1e106c3be11..16698251913 100644 --- a/mysql-test/r/mysqldump_restore.result +++ b/mysql-test/r/mysqldump_restore.result @@ -8,7 +8,7 @@ DROP TABLE IF EXISTS t1; # # Bug#2005 Long decimal comparison bug. # -CREATE TABLE t1 (a decimal(64, 20)); +CREATE TABLE t1 (a DECIMAL(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); # Begin testing mysqldump output + restore @@ -69,8 +69,8 @@ DROP TABLE test.t1, test.t1_orig; # # WL#2319 Exclude Tables from dump # -CREATE TABLE t1 (a int); -CREATE TABLE t2 (a int); +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t2 VALUES (4),(5),(6); # Begin testing mysqldump output + restore diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 1e9090fdd01..1aceb113b65 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1,6 +1,5 @@ # Embedded server doesn't support external clients --source include/not_embedded.inc ---source include/have_log_bin.inc # Binlog is required --source include/have_log_bin.inc diff --git a/mysql-test/t/mysqldump_restore.test b/mysql-test/t/mysqldump_restore.test index c5220e5de69..835ee3ee9e9 100644 --- a/mysql-test/t/mysqldump_restore.test +++ b/mysql-test/t/mysqldump_restore.test @@ -1,5 +1,6 @@ ############################################################################### # mysqldump_restore.test +# # Purpose: Tests if mysqldump output can be used to successfully restore # tables and data. # We CREATE a table, mysqldump it to a file, ALTER the original @@ -35,15 +36,14 @@ let $mysqldumpfile = $MYSQLTEST_VARDIR/tmp/mysqldumpfile.sql; --echo # Pre-test cleanup --disable_warnings -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1; --enable_warnings --echo # Begin tests --echo # --echo # Bug#2005 Long decimal comparison bug. --echo # - -CREATE TABLE t1 (a decimal(64, 20)); +CREATE TABLE t1 (a DECIMAL(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); --exec $MYSQL_DUMP --compact test t1 > $mysqldumpfile @@ -53,15 +53,11 @@ let $table_name = test.t1; --echo # --echo # Bug#3361 mysqldump quotes DECIMAL values inconsistently --echo # - CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); - -# check at first how mysql work with quoted decimal - +# Check at first how mysql work with quoted decimal INSERT INTO t1 VALUES (1.2345, 2.3456); INSERT INTO t1 VALUES ('1.2345', 2.3456); INSERT INTO t1 VALUES ("1.2345", 2.3456); - SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI_QUOTES'; INSERT INTO t1 VALUES (1.2345, 2.3456); INSERT INTO t1 VALUES ('1.2345', 2.3456); @@ -78,7 +74,6 @@ let $table_name = test.t1; --echo # Bug#1994 mysqldump does not correctly dump UCS2 data --echo # Bug#4261 mysqldump 10.7 (mysql 4.1.2) --skip-extended-insert drops NULL from inserts --echo # - CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); --exec $MYSQL_DUMP --skip-comments --skip-extended-insert test t1 > $mysqldumpfile @@ -88,9 +83,8 @@ let $table_name = test.t1; --echo # --echo # WL#2319 Exclude Tables from dump --echo # - -CREATE TABLE t1 (a int); -CREATE TABLE t2 (a int); +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t2 VALUES (4),(5),(6); --exec $MYSQL_DUMP --skip-comments --ignore-table=test.t1 test > $mysqldumpfile @@ -101,15 +95,12 @@ DROP TABLE t1; --echo # --echo # Bug#8830 mysqldump --skip-extended-insert causes --hex-blob to dump wrong values --echo # - CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); --exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 > $mysqldumpfile let $table_name = test.t1; --source include/mysqldump.inc - - --echo # End tests --echo # Cleanup From 8e589d1d06d48471bcef7164e458f6d9cefec2ec Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Sat, 23 May 2009 00:15:21 +0100 Subject: [PATCH 108/115] BUG#41725: slave crashes when inserting into temporary table after stop/start slave When stopping and restarting the slave while it is replicating temporary tables, the server would crash or raise an assertion failure. This was due to the fact that although temporary tables are saved between slave threads restart, the reference to the thread in use (table->in_use) was not being properly updated when the restart happened (it would still reference the old/invalid thread instead of the new one). This patch addresses this issue by resetting the reference to the new slave thread on slave thread restart. mysql-test/r/rpl_temporary.result: Result file. mysql-test/t/rpl_temporary.test: Test case that checks that both failures go away. sql/slave.cc: Changed slave.cc to reset sql_thd reference in temporary tables. --- mysql-test/r/rpl_temporary.result | 19 +++++++++ mysql-test/t/rpl_temporary.test | 70 +++++++++++++++++++++++++++++++ sql/slave.cc | 10 +++++ 3 files changed, 99 insertions(+) diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index 15c069ab68d..1326c7491f5 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -133,3 +133,22 @@ select * from t1; a 1 drop table t1; +DROP TABLE IF EXISTS t1; +CREATE TEMPORARY TABLE t1 (a char(1)); +INSERT INTO t1 VALUES ('a'); +include/stop_slave.inc +include/start_slave.inc +INSERT INTO t1 VALUES ('b'); +DROP TABLE IF EXISTS t1; +CREATE TEMPORARY TABLE `t1`(`a` tinyint,`b` char(1))engine=myisam; +INSERT INTO `t1` set `a`=128,`b`='128'; +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1265 Data truncated for column 'b' at row 1 +include/stop_slave.inc +include/start_slave.inc +INSERT INTO `t1` set `a`=128,`b`='128'; +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1265 Data truncated for column 'b' at row 1 +DROP TABLE t1; diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 516f3a026c9..4cd538877eb 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -217,4 +217,74 @@ drop table t1; # Delete the anonymous users source include/delete_anonymous_users.inc; +# ################################################################## +# BUG#41725: slave crashes when inserting into temporary table after +# stop/start slave +# +# This test checks that both reported issues (assertion failure and +# crash) go away. It is implemented as follows: +# +# case 1: assertion failure +# i) create and insert into temporary table on master +# ii) sync slave with master +# iii) stop and restart slave +# iv) insert into master another value +# v) sync slave with master +# +# +# case 2: crash (SIGSEV) +# i) create and insert into temporary table on master (insert +# produces warnings) +# ii) sync slave with master +# iii) stop and restart slave +# iv) insert into master more values +# v) sync slave with master + +# case 1: Assertion in Field_string::store() failed because current +# thread reference differed from table->in_use after slave +# restart + +connection master; + +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; + +CREATE TEMPORARY TABLE t1 (a char(1)); +INSERT INTO t1 VALUES ('a'); +sync_slave_with_master; + +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; +INSERT INTO t1 VALUES ('b'); +sync_slave_with_master; + +# case 2: crash on sp_rcontext::find_handler because it used +# reference to invalid THD object after slave restart + +connection master; + +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; +CREATE TEMPORARY TABLE `t1`(`a` tinyint,`b` char(1))engine=myisam; +INSERT INTO `t1` set `a`=128,`b`='128'; + +sync_slave_with_master; + +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; +INSERT INTO `t1` set `a`=128,`b`='128'; +sync_slave_with_master; + +# cleanup + +connection master; +DROP TABLE t1; +sync_slave_with_master; + # End of 5.0 tests diff --git a/sql/slave.cc b/sql/slave.cc index f29936c5942..88c19a04602 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -545,6 +545,14 @@ void st_relay_log_info::close_temporary_tables() slave_open_temp_tables= 0; } +static void set_thd_in_use_temporary_tables(RELAY_LOG_INFO *rli) +{ + TABLE *table; + + for (table= rli->save_temporary_tables ; table ; table= table->next) + table->in_use= rli->sql_thd; +} + /* purge_relay_logs() @@ -3964,6 +3972,7 @@ slave_begin: } thd->init_for_queries(); thd->temporary_tables = rli->save_temporary_tables; // restore temp tables + set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables pthread_mutex_lock(&LOCK_thread_count); threads.append(thd); pthread_mutex_unlock(&LOCK_thread_count); @@ -4136,6 +4145,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ DBUG_ASSERT(rli->sql_thd == thd); THD_CHECK_SENTRY(thd); rli->sql_thd= 0; + set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables pthread_mutex_lock(&LOCK_thread_count); THD_CHECK_SENTRY(thd); delete thd; From bd1c124681b824051674bb3f7302f2fd132f19ac Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Sat, 23 May 2009 10:19:58 -0300 Subject: [PATCH 109/115] Workaround a compiler that does not support certain C99 features for C code. tests/mysql_client_test.c: Use a suitable constant for specifying the size of the array. --- tests/mysql_client_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index e56d1e9f506..b836293442a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -17744,8 +17744,8 @@ static void test_bug43560(void) MYSQL_STMT *stmt= 0; MYSQL_BIND bind; my_bool is_null= 0; - const uint BUFSIZE= 256; - char buffer[BUFSIZE]; + char buffer[256]; + const uint BUFSIZE= sizeof(buffer); const char* values[] = {"eins", "zwei", "drei", "viele", NULL}; const char insert_str[] = "INSERT INTO t1 (c2) VALUES (?)"; unsigned long length; From 73481404656a954b314398f26ee7b4e3aec14282 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 25 May 2009 11:00:40 +0300 Subject: [PATCH 110/115] Bug #44399 : crash with statement using TEXT columns, aggregates, GROUP BY, and HAVING When calculating GROUP BY the server caches some expressions. It does that by allocating a string slot (Item_copy_string) and assigning the value of the expression to it. This effectively means that the result type of the expression can be changed from whatever it was to a string. As this substitution takes place after the compile-time result type calculation for IN but before the run-time type calculations, it causes the type calculations in the IN function done at run time to get unexpected results different from what was prepared at compile time. In the CASE ... WHEN ... THEN ... statement there was a similar problem and it was solved by artificially adding a STRING argument to the set of types of the IN/CASE arguments at compile time, so if any of the arguments of the CASE function changes its type to a string it will still be covered by the information prepared at compile time. mysql-test/include/mix1.inc: Bug #44399: extended the test to cover the different types mysql-test/r/func_in.result: Bug #44399: test case mysql-test/r/innodb_mysql.result: Bug #44399: extended the test to cover the different types mysql-test/t/func_in.test: Bug #44399: test case sql/item.cc: Bug #44399: Implement typed caching for GROUP BY sql/item.h: Bug #44399: Implement typed caching for GROUP BY sql/item_cmpfunc.cc: Bug #44399: remove the special case sql/sql_select.cc: Bug #44399: Implement typed caching for GROUP BY --- mysql-test/include/mix1.inc | 27 ++++ mysql-test/r/func_in.result | 21 +++ mysql-test/r/innodb_mysql.result | 29 +++++ mysql-test/t/func_in.test | 17 +++ sql/item.cc | 212 ++++++++++++++++++++++++++++++- sql/item.h | 207 ++++++++++++++++++++++++++---- sql/item_cmpfunc.cc | 10 -- sql/sql_select.cc | 10 +- 8 files changed, 488 insertions(+), 45 deletions(-) diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index d40d78c21b8..303f896cdfe 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1544,4 +1544,31 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1) DROP TABLE t1; +eval +CREATE TABLE t1 (c1 REAL, c2 REAL, c3 REAL, KEY (c3), KEY (c2, c3)) + ENGINE=$engine_type; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); + +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) + FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) + FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; + +DROP TABLE t1; + +eval +CREATE TABLE t1 (c1 DECIMAL(12,2), c2 DECIMAL(12,2), c3 DECIMAL(12,2), + KEY (c3), KEY (c2, c3)) + ENGINE=$engine_type; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); + +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) + FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) + FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 1e967b668c5..88a822a2fa6 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -587,4 +587,25 @@ SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1; CASE c1 WHEN c1 + 1 THEN 1 END ABS(AVG(c0)) NULL 1.0000 DROP TABLE t1; +CREATE TABLE t1(a TEXT, b INT, c INT UNSIGNED, d DECIMAL(12,2), e REAL); +INSERT INTO t1 VALUES('iynfj', 1, 1, 1, 1); +INSERT INTO t1 VALUES('innfj', 2, 2, 2, 2); +SELECT SUM( DISTINCT a ) FROM t1 GROUP BY a HAVING a IN ( AVG( 1 ), 1 + a); +SUM( DISTINCT a ) +SELECT SUM( DISTINCT b ) FROM t1 GROUP BY b HAVING b IN ( AVG( 1 ), 1 + b); +SUM( DISTINCT b ) +1 +SELECT SUM( DISTINCT c ) FROM t1 GROUP BY c HAVING c IN ( AVG( 1 ), 1 + c); +SUM( DISTINCT c ) +1 +SELECT SUM( DISTINCT d ) FROM t1 GROUP BY d HAVING d IN ( AVG( 1 ), 1 + d); +SUM( DISTINCT d ) +1.00 +SELECT SUM( DISTINCT e ) FROM t1 GROUP BY e HAVING e IN ( AVG( 1 ), 1 + e); +SUM( DISTINCT e ) +1 +SELECT SUM( DISTINCT e ) FROM t1 GROUP BY b,c,d HAVING (b,c,d) IN +((AVG( 1 ), 1 + c, 1 + d), (AVG( 1 ), 2 + c, 2 + d)); +SUM( DISTINCT e ) +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 671009a8a73..83a2a2111d5 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1718,6 +1718,35 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 2 DERIVED t1 index c3,c2 c2 10 NULL 5 DROP TABLE t1; +CREATE TABLE t1 (c1 REAL, c2 REAL, c3 REAL, KEY (c3), KEY (c2, c3)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +1 +1 +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 +2 DERIVED t1 index c3,c2 c2 18 NULL 5 +DROP TABLE t1; +CREATE TABLE t1 (c1 DECIMAL(12,2), c2 DECIMAL(12,2), c3 DECIMAL(12,2), +KEY (c3), KEY (c2, c3)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +1 +1 +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 +2 DERIVED t1 index c3,c2 c2 14 NULL 5 +DROP TABLE t1; End of 5.1 tests drop table if exists t1, t2, t3; create table t1(a int); diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 3fc1697f146..adc074259ad 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -439,4 +439,21 @@ SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1; DROP TABLE t1; +# +# Bug #44399: crash with statement using TEXT columns, aggregates, GROUP BY, +# and HAVING +# + +CREATE TABLE t1(a TEXT, b INT, c INT UNSIGNED, d DECIMAL(12,2), e REAL); +INSERT INTO t1 VALUES('iynfj', 1, 1, 1, 1); +INSERT INTO t1 VALUES('innfj', 2, 2, 2, 2); +SELECT SUM( DISTINCT a ) FROM t1 GROUP BY a HAVING a IN ( AVG( 1 ), 1 + a); +SELECT SUM( DISTINCT b ) FROM t1 GROUP BY b HAVING b IN ( AVG( 1 ), 1 + b); +SELECT SUM( DISTINCT c ) FROM t1 GROUP BY c HAVING c IN ( AVG( 1 ), 1 + c); +SELECT SUM( DISTINCT d ) FROM t1 GROUP BY d HAVING d IN ( AVG( 1 ), 1 + d); +SELECT SUM( DISTINCT e ) FROM t1 GROUP BY e HAVING e IN ( AVG( 1 ), 1 + e); +SELECT SUM( DISTINCT e ) FROM t1 GROUP BY b,c,d HAVING (b,c,d) IN + ((AVG( 1 ), 1 + c, 1 + d), (AVG( 1 ), 2 + c, 2 + d)); +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/item.cc b/sql/item.cc index 420efb2a4ee..768af47d660 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3268,10 +3268,58 @@ Item_param::set_param_type_and_swap_value(Item_param *src) str_value_ptr.swap(src->str_value_ptr); } +/**************************************************************************** + Item_copy +****************************************************************************/ +Item_copy *Item_copy::create (Item *item) +{ + switch (item->result_type()) + { + case STRING_RESULT: + return new Item_copy_string (item); + case REAL_RESULT: + return new Item_copy_float (item); + case INT_RESULT: + return item->unsigned_flag ? + new Item_copy_uint (item) : new Item_copy_int (item); + case DECIMAL_RESULT: + return new Item_copy_decimal (item); + + case ROW_RESULT: + DBUG_ASSERT (0); + } + /* should not happen */ + return NULL; +} + /**************************************************************************** Item_copy_string ****************************************************************************/ +double Item_copy_string::val_real() +{ + int err_not_used; + char *end_not_used; + return (null_value ? 0.0 : + my_strntod(str_value.charset(), (char*) str_value.ptr(), + str_value.length(), &end_not_used, &err_not_used)); +} + +longlong Item_copy_string::val_int() +{ + int err; + return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(), + str_value.length(),10, (char**) 0, + &err); +} + + +int Item_copy_string::save_in_field(Field *field, bool no_conversions) +{ + return save_str_value_in_field(field, &str_value); +} + + void Item_copy_string::copy() { String *res=item->val_str(&str_value); @@ -3294,12 +3342,163 @@ my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value) { // Item_copy_string is used without fix_fields call if (null_value) - return 0; + return (my_decimal *) 0; string2my_decimal(E_DEC_FATAL_ERROR, &str_value, decimal_value); return (decimal_value); } +/**************************************************************************** + Item_copy_int +****************************************************************************/ + +void Item_copy_int::copy() +{ + cached_value= item->val_int(); + null_value=item->null_value; +} + +static int save_int_value_in_field (Field *field, longlong nr, + bool null_value, bool unsigned_flag); + +int Item_copy_int::save_in_field(Field *field, bool no_conversions) +{ + return save_int_value_in_field(field, cached_value, + null_value, unsigned_flag); +} + + +String *Item_copy_int::val_str(String *str) +{ + if (null_value) + return (String *) 0; + + str->set(cached_value, &my_charset_bin); + return str; +} + + +my_decimal *Item_copy_int::val_decimal(my_decimal *decimal_value) +{ + if (null_value) + return (my_decimal *) 0; + + int2my_decimal(E_DEC_FATAL_ERROR, cached_value, unsigned_flag, decimal_value); + return decimal_value; +} + + +/**************************************************************************** + Item_copy_uint +****************************************************************************/ + +String *Item_copy_uint::val_str(String *str) +{ + if (null_value) + return (String *) 0; + + str->set((ulonglong) cached_value, &my_charset_bin); + return str; +} + + +/**************************************************************************** + Item_copy_float +****************************************************************************/ + +String *Item_copy_float::val_str(String *str) +{ + if (null_value) + return (String *) 0; + else + { + double nr= val_real(); + str->set_real(nr,decimals, &my_charset_bin); + return str; + } +} + + +my_decimal *Item_copy_float::val_decimal(my_decimal *decimal_value) +{ + if (null_value) + return (my_decimal *) 0; + else + { + double nr= val_real(); + double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value); + return decimal_value; + } +} + + +int Item_copy_float::save_in_field(Field *field, bool no_conversions) +{ + if (null_value) + return set_field_to_null(field); + field->set_notnull(); + return field->store(cached_value); +} + + +/**************************************************************************** + Item_copy_decimal +****************************************************************************/ + +int Item_copy_decimal::save_in_field(Field *field, bool no_conversions) +{ + if (null_value) + return set_field_to_null(field); + field->set_notnull(); + return field->store_decimal(&cached_value); +} + + +String *Item_copy_decimal::val_str(String *result) +{ + if (null_value) + return (String *) 0; + result->set_charset(&my_charset_bin); + my_decimal2string(E_DEC_FATAL_ERROR, &cached_value, 0, 0, 0, result); + return result; +} + + +double Item_copy_decimal::val_real() +{ + if (null_value) + return 0.0; + else + { + double result; + my_decimal2double(E_DEC_FATAL_ERROR, &cached_value, &result); + return result; + } +} + + +longlong Item_copy_decimal::val_int() +{ + if (null_value) + return LL(0); + else + { + longlong result; + my_decimal2int(E_DEC_FATAL_ERROR, &cached_value, unsigned_flag, &result); + return result; + } +} + + +void Item_copy_decimal::copy() +{ + my_decimal *nr= item->val_decimal(&cached_value); + if (nr && nr != &cached_value) + memcpy (&cached_value, nr, sizeof (my_decimal)); + null_value= item->null_value; +} + + /* Functions to convert item to field (for send_fields) */ @@ -4947,10 +5146,9 @@ int Item_uint::save_in_field(Field *field, bool no_conversions) return Item_int::save_in_field(field, no_conversions); } - -int Item_int::save_in_field(Field *field, bool no_conversions) +static int save_int_value_in_field (Field *field, longlong nr, + bool null_value, bool unsigned_flag) { - longlong nr=val_int(); if (null_value) return set_field_to_null(field); field->set_notnull(); @@ -4958,6 +5156,12 @@ int Item_int::save_in_field(Field *field, bool no_conversions) } +int Item_int::save_in_field(Field *field, bool no_conversions) +{ + return save_int_value_in_field (field, val_int(), null_value, unsigned_flag); +} + + int Item_decimal::save_in_field(Field *field, bool no_conversions) { field->set_notnull(); diff --git a/sql/item.h b/sql/item.h index 96a4e9f7a31..3dfcd7c2612 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2443,48 +2443,203 @@ public: #include "item_xmlfunc.h" #endif -class Item_copy_string :public Item +/** + Base class to implement typed value caching Item classes + + Item_copy_ classes are very similar to the corresponding Item_ + classes (e.g. Item_copy_int is similar to Item_int) but they add + the following additional functionality to Item_ : + 1. Nullability + 2. Possibility to store the value not only on instantiation time, + but also later. + Item_copy_ classes are a functionality subset of Item_cache_ + classes, as e.g. they don't support comparisons with the original Item + as Item_cache_ classes do. + Item_copy_ classes are used in GROUP BY calculation. + TODO: Item_copy should be made an abstract interface and Item_copy_ + classes should inherit both the respective Item_ class and the interface. + Ideally we should drop Item_copy_ classes altogether and merge + their functionality to Item_cache_ (and these should be made to inherit + from Item_). +*/ + +class Item_copy :public Item { +protected: + + /** + Stores the type of the resulting field that would be used to store the data + in the cache. This is to avoid calls to the original item. + */ enum enum_field_types cached_field_type; -public: + + /** The original item that is copied */ Item *item; - Item_copy_string(Item *i) :item(i) + + /** + Stores the result type of the original item, so it can be returned + without calling the original item's method + */ + Item_result cached_result_type; + + /** + Constructor of the Item_copy class + + stores metadata information about the original class as well as a + pointer to it. + */ + Item_copy(Item *i) { + item= i; null_value=maybe_null=item->maybe_null; decimals=item->decimals; max_length=item->max_length; name=item->name; cached_field_type= item->field_type(); + cached_result_type= item->result_type(); + unsigned_flag= item->unsigned_flag; } + +public: + /** + Factory method to create the appropriate subclass dependent on the type of + the original item. + + @param item the original item. + */ + static Item_copy *create (Item *item); + + /** + Update the cache with the value of the original item + + This is the method that updates the cached value. + It must be explicitly called by the user of this class to store the value + of the orginal item in the cache. + */ + virtual void copy() = 0; + + Item *get_item() { return item; } + /** All of the subclasses should have the same type tag */ enum Type type() const { return COPY_STR_ITEM; } - enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return cached_field_type; } - double val_real() - { - int err_not_used; - char *end_not_used; - return (null_value ? 0.0 : - my_strntod(str_value.charset(), (char*) str_value.ptr(), - str_value.length(), &end_not_used, &err_not_used)); - } - longlong val_int() - { - int err; - return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(), - str_value.length(),10, (char**) 0, - &err); - } - String *val_str(String*); - my_decimal *val_decimal(my_decimal *); + enum Item_result result_type () const { return cached_result_type; } + void make_field(Send_field *field) { item->make_field(field); } - void copy(); - int save_in_field(Field *field, bool no_conversions) - { - return save_str_value_in_field(field, &str_value); - } table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } + + /* + Override the methods below as pure virtual to make sure all the + sub-classes implement them. + */ + + virtual String *val_str(String*) = 0; + virtual my_decimal *val_decimal(my_decimal *) = 0; + virtual double val_real() = 0; + virtual longlong val_int() = 0; + virtual int save_in_field(Field *field, bool no_conversions) = 0; +}; + +/** + Implementation of a string cache. + + Uses Item::str_value for storage +*/ +class Item_copy_string : public Item_copy +{ +public: + Item_copy_string (Item *item) : Item_copy(item) {} + + String *val_str(String*); + my_decimal *val_decimal(my_decimal *); + double val_real(); + longlong val_int(); + void copy(); + int save_in_field(Field *field, bool no_conversions); +}; + + +class Item_copy_int : public Item_copy +{ +protected: + longlong cached_value; +public: + Item_copy_int (Item *i) : Item_copy(i) {} + int save_in_field(Field *field, bool no_conversions); + + virtual String *val_str(String*); + virtual my_decimal *val_decimal(my_decimal *); + virtual double val_real() + { + return null_value ? 0.0 : (double) cached_value; + } + virtual longlong val_int() + { + return null_value ? LL(0) : cached_value; + } + virtual void copy(); +}; + + +class Item_copy_uint : public Item_copy_int +{ +public: + Item_copy_uint (Item *item) : Item_copy_int(item) + { + unsigned_flag= 1; + } + + String *val_str(String*); + double val_real() + { + return null_value ? 0.0 : (double) (ulonglong) cached_value; + } +}; + + +class Item_copy_float : public Item_copy +{ +protected: + double cached_value; +public: + Item_copy_float (Item *i) : Item_copy(i) {} + int save_in_field(Field *field, bool no_conversions); + + String *val_str(String*); + my_decimal *val_decimal(my_decimal *); + double val_real() + { + return null_value ? 0.0 : cached_value; + } + longlong val_int() + { + return (longlong) rint(val_real()); + } + void copy() + { + cached_value= item->val_real(); + null_value= item->null_value; + } +}; + + +class Item_copy_decimal : public Item_copy +{ +protected: + my_decimal cached_value; +public: + Item_copy_decimal (Item *i) : Item_copy(i) {} + int save_in_field(Field *field, bool no_conversions); + + String *val_str(String*); + my_decimal *val_decimal(my_decimal *) + { + return null_value ? NULL: &cached_value; + } + double val_real(); + longlong val_int(); + void copy(); }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a9bfea1b806..ee823517df8 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2724,16 +2724,6 @@ void Item_func_case::fix_length_and_dec() nagg++; if (!(found_types= collect_cmp_types(agg, nagg))) return; - if (with_sum_func || current_thd->lex->current_select->group_list.elements) - { - /* - See TODO commentary in the setup_copy_fields function: - item in a group may be wrapped with an Item_copy_string item. - That item has a STRING_RESULT result type, so we need - to take this type into account. - */ - found_types |= (1 << item_cmp_type(left_result_type, STRING_RESULT)); - } for (i= 0; i <= (uint)DECIMAL_RESULT; i++) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ab9c060c69c..fad533986d6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13855,7 +13855,7 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length, pos->field= ((Item_sum*) item)->get_tmp_table_field(); else if (item->type() == Item::COPY_STR_ITEM) { // Blob patch - pos->item= ((Item_copy_string*) item)->item; + pos->item= ((Item_copy*) item)->get_item(); } else pos->item= *order->item; @@ -14926,7 +14926,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, pos= item; if (item->field->flags & BLOB_FLAG) { - if (!(pos= new Item_copy_string(pos))) + if (!(pos= Item_copy::create(pos))) goto err; /* Item_copy_string::copy for function can call @@ -14980,7 +14980,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, on how the value is to be used: In some cases this may be an argument in a group function, like: IF(ISNULL(col),0,COUNT(*)) */ - if (!(pos=new Item_copy_string(pos))) + if (!(pos= Item_copy::create(pos))) goto err; if (i < border) // HAVING, ORDER and GROUP BY { @@ -15033,8 +15033,8 @@ copy_fields(TMP_TABLE_PARAM *param) (*ptr->do_copy)(ptr); List_iterator_fast it(param->copy_funcs); - Item_copy_string *item; - while ((item = (Item_copy_string*) it++)) + Item_copy *item; + while ((item = (Item_copy*) it++)) item->copy(); } From 7c4eb8c0d17fc68da2ab58ee3ace88ea38e48515 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 25 May 2009 10:00:18 -0300 Subject: [PATCH 111/115] Bug#42158: leak: SSL_get_peer_certificate() doesn't have matching X509_free() The problem is that the server failed to follow the rule that every X509 object retrieved using SSL_get_peer_certificate() must be explicitly freed by X509_free(). This caused a memory leak for builds linked against OpenSSL where the X509 object is reference counted -- improper counting will prevent the object from being destroyed once the session containing the peer certificate is freed. The solution is to explicitly free every X509 object used. mysql-test/r/openssl_1.result: Add test case result for Bug#42158 mysql-test/t/openssl_1.test: Add test case for Bug#42158 sql/sql_acl.cc: Deallocate X509 objects. --- mysql-test/r/openssl_1.result | 6 ++++++ mysql-test/t/openssl_1.test | 13 ++++++++++++- sql/sql_acl.cc | 11 +++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index c408c14b716..b0dd3acd662 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -202,4 +202,10 @@ Ssl_cipher RC4-SHA select 'is still running; no cipher request crashed the server' as result from dual; result is still running; no cipher request crashed the server +GRANT SELECT ON test.* TO bug42158@localhost REQUIRE X509; +FLUSH PRIVILEGES; +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +DROP USER bug42158@localhost; End of 5.1 tests diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index 240a977fdca..baa1603faab 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -238,7 +238,18 @@ DROP TABLE t1; --enable_query_log select 'is still running; no cipher request crashed the server' as result from dual; -## +# +# Bug#42158: leak: SSL_get_peer_certificate() doesn't have matching X509_free() +# + +GRANT SELECT ON test.* TO bug42158@localhost REQUIRE X509; +FLUSH PRIVILEGES; +connect(con1,localhost,bug42158,,,,,SSL); +SHOW STATUS LIKE 'Ssl_cipher'; +disconnect con1; +connection default; +DROP USER bug42158@localhost; + --echo End of 5.1 tests # Wait till we reached the initial number of concurrent sessions diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b1dbb7031ce..4d4e4d24684 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -936,6 +936,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, #ifdef HAVE_OPENSSL Vio *vio=thd->net.vio; SSL *ssl= (SSL*) vio->ssl_arg; + X509 *cert; #endif /* @@ -964,8 +965,11 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, */ if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_verify_result(ssl) == X509_V_OK && - SSL_get_peer_certificate(ssl)) + (cert= SSL_get_peer_certificate(ssl))) + { user_access= acl_user->access; + X509_free(cert); + } break; case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */ /* @@ -974,7 +978,6 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, If cipher name is specified, we compare it to actual cipher in use. */ - X509 *cert; if (vio_type(vio) != VIO_TYPE_SSL || SSL_get_verify_result(ssl) != X509_V_OK) break; @@ -1014,6 +1017,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, sql_print_information("X509 issuer mismatch: should be '%s' " "but is '%s'", acl_user->x509_issuer, ptr); free(ptr); + X509_free(cert); user_access=NO_ACCESS; break; } @@ -1033,12 +1037,15 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, sql_print_information("X509 subject mismatch: should be '%s' but is '%s'", acl_user->x509_subject, ptr); free(ptr); + X509_free(cert); user_access=NO_ACCESS; break; } user_access= acl_user->access; free(ptr); } + /* Deallocate the X509 certificate. */ + X509_free(cert); break; #else /* HAVE_OPENSSL */ default: From a1212080ade9197bfb8c6653bed5af71b83af04a Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Mon, 25 May 2009 18:21:40 +0200 Subject: [PATCH 112/115] Bug #44736 mysqld_safe's my_which() is broken and doesn't find 'logger' Due to a variable quoting mistake, the $PATH environment variable isn't parsed correctly when searching for the existence of the desired executable(s) (logger in this case). This patch removes the quotes. --- scripts/mysqld_safe.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 34dc019a82a..23b5efcaf2b 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -67,7 +67,7 @@ my_which () ret=0 for file do - for dir in "$PATH" + for dir in $PATH do if [ -f "$dir/$file" ] then From d31b6e47844bb277c69eb9a8993a1024cbdca629 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 27 May 2009 13:11:28 +0500 Subject: [PATCH 113/115] Bug#43940 64-bit windows myisamchk doesn't support key_buffer_size > 4G The fix is to allow myisamchk to use >4G key_buffer_size on win64 include/myisam.h: use ulonglong instead of ulong for use_buffers storage/myisam/myisamchk.c: use ulonglong instead of ulong for use_buffers --- include/myisam.h | 3 ++- storage/myisam/myisamchk.c | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index d7bfdf7191e..02251eeacb4 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -404,7 +404,8 @@ typedef struct st_mi_check_param my_off_t keydata,totaldata,key_blocks,start_check_pos; ha_rows total_records,total_deleted; ha_checksum record_checksum,glob_crc; - ulong use_buffers,read_buffer_length,write_buffer_length, + ulonglong use_buffers; + ulong read_buffer_length,write_buffer_length, sort_buffer_length,sort_key_blocks; uint out_flag,warning_printed,error_printed,verbose; uint opt_sort_key,total_files,max_level; diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index ac0be2f01cc..75678375ce7 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -287,8 +287,8 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { "key_buffer_size", OPT_KEY_BUFFER_SIZE, "", (uchar**) &check_param.use_buffers, (uchar**) &check_param.use_buffers, 0, - GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD, - (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0}, + GET_ULL, REQUIRED_ARG, USE_BUFFER_INIT, MALLOC_OVERHEAD, + SIZE_T_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, { "key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "", (uchar**) &opt_key_cache_block_size, (uchar**) &opt_key_cache_block_size, 0, @@ -1102,7 +1102,7 @@ static int myisamchk(MI_CHECK *param, char * filename) { if (param->testflag & (T_EXTEND | T_MEDIUM)) VOID(init_key_cache(dflt_key_cache,opt_key_cache_block_size, - param->use_buffers, 0, 0)); + (size_t) param->use_buffers, 0, 0)); VOID(init_io_cache(¶m->read_cache,datafile, (uint) param->read_buffer_length, READ_CACHE, @@ -1525,8 +1525,8 @@ static int mi_sort_records(MI_CHECK *param, if (share->state.key_root[sort_key] == HA_OFFSET_ERROR) DBUG_RETURN(0); /* Nothing to do */ - init_key_cache(dflt_key_cache, opt_key_cache_block_size, param->use_buffers, - 0, 0); + init_key_cache(dflt_key_cache, opt_key_cache_block_size, + (size_t) param->use_buffers, 0, 0); if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length, WRITE_CACHE,share->pack.header_length,1, MYF(MY_WME | MY_WAIT_IF_FULL))) From f54beb2dccb921296a4c0bec1aa45e5dd6e53a69 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 27 May 2009 15:34:21 +0500 Subject: [PATCH 114/115] Bug#41212 crash after race condition between merge table and table_cache evictions On 64-bit Windows: querying MERGE table with keys may cause server crash.The problem is generic and may affect any statement accessing MERGE table cardinality values. When MERGE engine was copying cardinality statistics, it was using incorrect size of element in cardinality statistics array (sizeof(ptr)==8 instead of sizeof(ulong)==4), causing access of memory beyond of the allocated bounds. sql/ha_myisam.cc: When copying rec_per_key array (an array of ulong) use proper size of element, that is sizeof(ulong). sql/ha_myisammrg.cc: When copying rec_per_key array (an array of ulong) use proper size of element, that is sizeof(ulong). sql/table.cc: When allocating rec_per_key array (an array of ulong) use proper size of element, that is sizeof(ulong). --- sql/ha_myisam.cc | 2 +- sql/ha_myisammrg.cc | 4 ++-- sql/table.cc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 5ed791d0f68..95b7b338131 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1684,7 +1684,7 @@ int ha_myisam::info(uint flag) if (share->key_parts) memcpy((char*) table->key_info[0].rec_per_key, (char*) misam_info.rec_per_key, - sizeof(table->key_info[0].rec_per_key)*share->key_parts); + sizeof(table->key_info[0].rec_per_key[0])*share->key_parts); raid_type= misam_info.raid_type; raid_chunks= misam_info.raid_chunks; raid_chunksize= misam_info.raid_chunksize; diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index f15a37efdc5..fef2e21d271 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -402,11 +402,11 @@ int ha_myisammrg::info(uint flag) with such a number, it'll be an error later anyway. */ bzero((char*) table->key_info[0].rec_per_key, - sizeof(table->key_info[0].rec_per_key) * table->s->key_parts); + sizeof(table->key_info[0].rec_per_key[0]) * table->s->key_parts); #endif memcpy((char*) table->key_info[0].rec_per_key, (char*) mrg_info.rec_per_key, - sizeof(table->key_info[0].rec_per_key) * + sizeof(table->key_info[0].rec_per_key[0]) * min(file->keys, table->s->key_parts)); } } diff --git a/sql/table.cc b/sql/table.cc index c559b4bb7fd..55a9b50605d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -233,7 +233,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, ulong *rec_per_key; if (!(rec_per_key= (ulong*) alloc_root(&outparam->mem_root, - sizeof(ulong*)*key_parts))) + sizeof(ulong)*key_parts))) goto err; for (i=0 ; i < keys ; i++, keyinfo++) From 4673975379e0ca797d7dddad7e853ce13e07bb4e Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 28 May 2009 10:35:29 +0300 Subject: [PATCH 115/115] changed the version --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..f79c1cd6319 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0"