From c1a36d80ef50b7cd23da893a08e7610d9e9dd02e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Nov 2007 15:11:58 -0500 Subject: [PATCH 01/28] 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 02/28] 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 03/28] 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 04/28] 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 05/28] 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 06/28] 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 07/28] 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 08/28] 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 09/28] 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 10/28] 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 11/28] 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 12/28] 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 13/28] 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 14/28] 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 15/28] 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 16/28] 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 17/28] 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 18/28] 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 19/28] 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 20/28] 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 21/28] 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 22/28] 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 6e0a64ef569584faecaaf2ad36903d7198a2e039 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Apr 2009 13:30:52 +0200 Subject: [PATCH 23/28] 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 d64c0e16759e25285487c709dda72663d8b8cec9 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Fri, 1 May 2009 19:35:04 +0200 Subject: [PATCH 24/28] 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 4822696ecb7302efc543e0be109f1c2a8f1bdf4e Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 5 May 2009 17:03:23 -0400 Subject: [PATCH 25/28] 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 fca0a61a1ac3de2f00f19fe40b365fff031fba6e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 May 2009 21:42:19 +0200 Subject: [PATCH 26/28] 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 3593b73eb1f2f4d4e182b8469310faa0152cf06b Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 11 May 2009 10:00:03 -0400 Subject: [PATCH 27/28] 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 dbf8997b40a34ab01a57c0fe37c5ae9e345659fc Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 12 May 2009 09:14:23 -0400 Subject: [PATCH 28/28] 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. +