From 0f1516b98e50d61de960456625a6f65e39047504 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 15 Oct 2005 19:47:23 +0500 Subject: [PATCH 01/37] Fix for bug #9855 (Inconsistend column type in create select) mysql-test/r/func_gconcat.result: result fixed mysql-test/r/subselect.result: result fixed mysql-test/r/type_float.result: result fixed mysql-test/t/type_float.test: testcase added sql/item_func.cc: Now we set decimals to NOT_FIXED_DEC if the max_length is longer than maximum possible double length --- mysql-test/r/func_gconcat.result | 6 +++--- mysql-test/r/subselect.result | 6 +++--- mysql-test/r/type_float.result | 22 ++++++++++++++++++++++ mysql-test/t/type_float.test | 17 +++++++++++++++++ sql/item_func.cc | 9 +++++++++ 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index d7a741827d5..200b4a4d53b 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -131,9 +131,9 @@ grp group_concat(a separator "")+0 3 456789 select grp, group_concat(a separator "")+0.0 from t1 group by grp; grp group_concat(a separator "")+0.0 -1 1.0 -2 23.0 -3 456789.0 +1 1 +2 23 +3 456789 select grp, ROUND(group_concat(a separator "")) from t1 group by grp; grp ROUND(group_concat(a separator "")) 1 1 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 4c795abe986..500aa4b1728 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -213,9 +213,9 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from a select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) -8 7.5000 -8 4.5000 -9 7.5000 +8 7.5 +8 4.5 +9 7.5 explain extended select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t4 ALL NULL NULL NULL NULL 3 diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 6e381192270..e8daeb08526 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -250,3 +250,25 @@ t3 CREATE TABLE `t3` ( `d` double(22,9) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1, t2, t3; +create table t1 select 105213674794682365.00 + 0.0 x; +show warnings; +Level Code Message +desc t1; +Field Type Null Key Default Extra +x double 0 +drop table t1; +create table t1 select 0.0 x; +desc t1; +Field Type Null Key Default Extra +x double(3,1) 0.0 +create table t2 select 105213674794682365.00 y; +desc t2; +Field Type Null Key Default Extra +y double(21,2) 0.00 +create table t3 select x+y a from t1,t2; +show warnings; +Level Code Message +desc t3; +Field Type Null Key Default Extra +a double 0 +drop table t1,t2,t3; diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index abaf72ea2ed..75723d2a0ff 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -162,4 +162,21 @@ show create table t3; drop table t1, t2, t3; +# +# Bug #9855 (inconsistent column type for create select +# +create table t1 select 105213674794682365.00 + 0.0 x; +show warnings; +desc t1; +drop table t1; + +create table t1 select 0.0 x; +desc t1; +create table t2 select 105213674794682365.00 y; +desc t2; +create table t3 select x+y a from t1,t2; +show warnings; +desc t3; +drop table t1,t2,t3; + # End of 4.1 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 288859443ff..019147e151f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -359,10 +359,19 @@ String *Item_num_func::val_str(String *str) void Item_func::fix_num_length_and_dec() { + uint fl_length= 0; decimals=0; for (uint i=0 ; i < arg_count ; i++) + { set_if_bigger(decimals,args[i]->decimals); + set_if_bigger(fl_length, args[i]->max_length); + } max_length=float_length(decimals); + if (fl_length > max_length) + { + decimals= NOT_FIXED_DEC; + max_length= float_length(NOT_FIXED_DEC); + } } Item *Item_func::get_tmp_table_item(THD *thd) From 2541d76e092ec17e884539015662e9242524f29b Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Dec 2005 18:20:00 +0400 Subject: [PATCH 02/37] Fix for bug #14320 (MBROverlaps does wrong test) sql/spatial.h: MBR::inner_point fixed --- sql/spatial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/spatial.h b/sql/spatial.h index ec5e80e00fd..206958b3eaf 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -142,7 +142,7 @@ struct MBR bool inner_point(double x, double y) const { /* The following should be safe, even if we compare doubles */ - return (xminx) && (yminx); + return (xminx) && (yminy); } int overlaps(const MBR *mbr) From 718128db908c921b3ad8b45342be33d66660bae4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 15 Dec 2005 15:23:16 +0100 Subject: [PATCH 03/37] Fixed BUG#14834: Server denies to execute Stored Procedure The problem was that databases with '_' in the name did not match a correct ACL with a literal '_' (i.e. '\_') in the db name, only identical strings matched. The fix makes this work, and also ACLs with wildcards in the db name work. mysql-test/r/sp-security.result: New test case for BUG#14834 mysql-test/t/sp-security.test: New test case for BUG#14834 sql/sql_acl.cc: Match wild db:s in ACL in acl_getroot_no_password() (used for "suid" security context switching when invoking stored routines) --- mysql-test/r/sp-security.result | 21 ++++++++++++++++ mysql-test/t/sp-security.test | 44 +++++++++++++++++++++++++++++++++ sql/sql_acl.cc | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 614e670f25d..fbc6d64f9c9 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -263,3 +263,24 @@ CREATE VIEW v1 AS SELECT test.bug12812()| ERROR 42000: execute command denied to user 'user_bug12812'@'localhost' for routine 'test.bug12812' DROP USER user_bug12812@localhost| drop function bug12812| +create database db_bug14834; +create user user1_bug14834@localhost identified by ''; +grant all on `db\_bug14834`.* to user1_bug14834@localhost; +create user user2_bug14834@localhost identified by ''; +grant all on `db\_bug14834`.* to user2_bug14834@localhost; +create user user3_bug14834@localhost identified by ''; +grant all on `db__ug14834`.* to user3_bug14834@localhost; +create procedure p_bug14834() select user(), current_user(); +call p_bug14834(); +user() current_user() +user1_bug14834@localhost user1_bug14834@localhost +call p_bug14834(); +user() current_user() +user2_bug14834@localhost user1_bug14834@localhost +call p_bug14834(); +user() current_user() +user3_bug14834@localhost user1_bug14834@localhost +drop user user1_bug14834@localhost; +drop user user2_bug14834@localhost; +drop user user3_bug14834@localhost; +drop database db_bug14834; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 8d4f99abd71..0b24881a056 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -437,4 +437,48 @@ disconnect test_user_12812| DROP USER user_bug12812@localhost| drop function bug12812| delimiter ;| + + +# +# BUG#14834: Server denies to execute Stored Procedure +# +# The problem here was with '_' in the database name. +# +create database db_bug14834; + +create user user1_bug14834@localhost identified by ''; +# The exact name of the database (no wildcard) +grant all on `db\_bug14834`.* to user1_bug14834@localhost; + +create user user2_bug14834@localhost identified by ''; +# The exact name of the database (no wildcard) +grant all on `db\_bug14834`.* to user2_bug14834@localhost; + +create user user3_bug14834@localhost identified by ''; +# Wildcards in the database name +grant all on `db__ug14834`.* to user3_bug14834@localhost; + +connect (user1_bug14834,localhost,user1_bug14834,,db_bug14834); +# Create the procedure and check that we can call it +create procedure p_bug14834() select user(), current_user(); +call p_bug14834(); + +connect (user2_bug14834,localhost,user2_bug14834,,db_bug14834); +# This didn't work before +call p_bug14834(); + +connect (user3_bug14834,localhost,user3_bug14834,,db_bug14834); +# Should also work +call p_bug14834(); + +# Cleanup +connection default; +disconnect user1_bug14834; +disconnect user2_bug14834; +disconnect user3_bug14834; +drop user user1_bug14834@localhost; +drop user user2_bug14834@localhost; +drop user user3_bug14834@localhost; +drop database db_bug14834; + # End of 5.0 bugs. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index cd83efcac2c..dadb4b75d7c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -987,7 +987,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, { if (compare_hostname(&acl_db->host, host, ip)) { - if (!acl_db->db || (db && !strcmp(acl_db->db, db))) + if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0))) { sctx->db_access= acl_db->access; break; From 2c29ced92859413585cb4cebc85b69bba408940d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Dec 2005 14:21:42 +0400 Subject: [PATCH 04/37] bug #15429 (Test 'func_math' not prepared for 'classic' build) mysql-test/t/func_math.test: warnings disabled on CREATE TABLE INNODB --- mysql-test/t/func_math.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index a8f62e38e86..c22c09ab62b 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -91,7 +91,9 @@ drop table t1; # # InnoDB is required to reproduce the fault, but it is okay if we default to # MyISAM when testing. +--disable_warnings create table t1 (a varchar(90), ts datetime not null, index (a)) engine=innodb default charset=utf8; +--enable_warnings insert into t1 values ('http://www.foo.com/', now()); select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0)); drop table t1; From 307c0b77a191a428c4bfdcba42b53872aa7c917f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jan 2006 17:54:54 +0100 Subject: [PATCH 05/37] many warnings (practically safe but annoying) corrected client/mysqladmin.cc: don't use the handler after it's closed client/mysqlbinlog.cc: memory leak client/mysqldump.c: many "ignore return value" warnings, one "NULL dereference" cmd-line-utils/libedit/history.c: memory leak include/my_base.h: cleanup libmysql/libmysql.c: "return value ignored" warning myisam/mi_delete.c: "return value ignored" warning myisam/myisampack.c: "out-of-bound access" warning myisam/sort.c: "double free" warning mysys/default_modify.c: "double free" warning mysys/mf_iocache2.c: "return value ignored" warnings mysys/my_bitmap.c: s/return/DBUG_RETURN/ mysys/my_error.c: memory leak server-tools/instance-manager/parse.cc: "NULL dereference" warning sql-common/client.c: "NULL dereference" warning sql/field.cc: deadcode, "NULL dereference", "uninitialized" warnings sql/field.h: unused parameters removed from constructor sql/ha_myisam.cc: "return value ignored" warnings sql/item.cc: "return value ignored" warnings changed constructor sql/item_func.cc: "return value ignored" warnings sql/log_event.cc: uninitialized warning sql/opt_range.cc: "double free" and uninitialized warnings sql/opt_range.h: "return value ignored" warning sql/repl_failsafe.cc: "return value ignored" warning sql/set_var.cc: "return value ignored" warning sql/slave.cc: "return value ignored" warnings sql/slave.h: new prototype sql/sql_acl.cc: deadcode and "NULL dereference" warnings sql/sql_db.cc: "return value ignored" warning sql/sql_handler.cc: "NULL dereference" warning sql/sql_help.cc: "NULL dereference" warning sql/sql_insert.cc: "return value ignored" warning sql/sql_parse.cc: "return value ignored" warning one more DBUG_ASSERT sql/sql_repl.cc: "return value ignored" and memory leak warnings sql/sql_show.cc: "return value ignored" and "NULL dereference" warnings sql/sql_test.cc: "return value ignored" warning sql/table.cc: memory leak sql/uniques.cc: "return value ignored" warning endspaces deleted --- client/mysqladmin.cc | 1 + client/mysqlbinlog.cc | 9 +- client/mysqldump.c | 27 +++--- cmd-line-utils/libedit/history.c | 4 +- include/my_base.h | 3 +- libmysql/libmysql.c | 2 +- myisam/mi_delete.c | 3 +- myisam/myisampack.c | 2 +- myisam/sort.c | 3 + mysys/default_modify.c | 2 +- mysys/mf_iocache2.c | 10 +- mysys/my_bitmap.c | 2 +- mysys/my_error.c | 3 + server-tools/instance-manager/parse.cc | 2 +- sql-common/client.c | 2 +- sql/field.cc | 22 ++--- sql/field.h | 4 +- sql/ha_myisam.cc | 17 ++-- sql/item.cc | 8 +- sql/item_func.cc | 13 ++- sql/log_event.cc | 4 + sql/opt_range.cc | 7 +- sql/opt_range.h | 2 +- sql/repl_failsafe.cc | 3 +- sql/set_var.cc | 1 - sql/slave.cc | 38 +++++--- sql/slave.h | 2 +- sql/sql_acl.cc | 6 +- sql/sql_db.cc | 114 ++++++++++++----------- sql/sql_handler.cc | 8 +- sql/sql_help.cc | 2 +- sql/sql_insert.cc | 3 +- sql/sql_parse.cc | 12 ++- sql/sql_repl.cc | 12 ++- sql/sql_show.cc | 23 ++--- sql/sql_test.cc | 2 +- sql/table.cc | 5 +- sql/uniques.cc | 122 ++++++++++++------------- 38 files changed, 274 insertions(+), 231 deletions(-) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 8d2e040b21f..5b52d524f8e 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -569,6 +569,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) return -1; } mysql_close(mysql); /* Close connection to avoid error messages */ + argc=1; /* force SHUTDOWN to be the last command */ if (got_pidfile) { if (opt_verbose) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index ae482a155d5..b1a931a9df1 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1266,12 +1266,13 @@ at offset %lu ; this could be a log format error or read error", } else if (buf[4] == ROTATE_EVENT) { + Log_event *ev; my_b_seek(file, tmp_pos); /* seek back to event's start */ - if (!Log_event::read_log_event(file, *description_event)) + if (!(ev= Log_event::read_log_event(file, *description_event))) /* EOF can't be hit here normally, so it's a real error */ - die("Could not read a Rotate_log_event event \ -at offset %lu ; this could be a log format error or read error", - tmp_pos); + die("Could not read a Rotate_log_event event at offset %lu ;" + " this could be a log format error or read error", tmp_pos); + delete ev; } else break; diff --git a/client/mysqldump.c b/client/mysqldump.c index 454fc0df84e..64daa39feee 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1306,7 +1306,7 @@ static uint dump_routines_for_db(char *db) fprintf(sql_file, "DELIMITER ;\n"); if (lock_tables) - mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); + VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES")); DBUG_RETURN(0); } @@ -2095,7 +2095,10 @@ static void dump_table(char *table, char *db) else res=mysql_store_result(sock); if (!res) + { DB_error(sock, "when retrieving data from server"); + goto err; + } if (verbose) fprintf(stderr, "-- Retrieving rows...\n"); if (mysql_num_fields(res) != num_fields) @@ -2625,7 +2628,7 @@ static int dump_all_tables_in_db(char *database) check_io(md_result_file); } if (lock_tables) - mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); + VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES")); return 0; } /* dump_all_tables_in_db */ @@ -2680,23 +2683,23 @@ static my_bool dump_all_views_in_db(char *database) check_io(md_result_file); } if (lock_tables) - mysql_query(sock,"UNLOCK TABLES"); + VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES")); return 0; } /* dump_all_tables_in_db */ /* - get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual - table name from the server for the table name given on the command line. - we do this because the table name given on the command line may be a + get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual + table name from the server for the table name given on the command line. + we do this because the table name given on the command line may be a different case (e.g. T1 vs t1) - + RETURN int - 0 if a tablename was retrieved. 1 if not */ -static int get_actual_table_name(const char *old_table_name, - char *new_table_name, +static int get_actual_table_name(const char *old_table_name, + char *new_table_name, int buf_size) { int retval; @@ -2708,7 +2711,7 @@ static int get_actual_table_name(const char *old_table_name, /* Check memory for quote_for_like() */ DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff)); - my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", + my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", quote_for_like(old_table_name, show_name_buff)); if (mysql_query_with_error_report(sock, 0, query)) @@ -2717,7 +2720,7 @@ static int get_actual_table_name(const char *old_table_name, } retval = 1; - + if ((table_res= mysql_store_result(sock))) { my_ulonglong num_rows= mysql_num_rows(table_res); @@ -2839,7 +2842,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) check_io(md_result_file); } if (lock_tables) - mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); + VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES")); DBUG_RETURN(0); } /* dump_selected_tables */ diff --git a/cmd-line-utils/libedit/history.c b/cmd-line-utils/libedit/history.c index 1da6a864181..c0fa7cc717d 100644 --- a/cmd-line-utils/libedit/history.c +++ b/cmd-line-utils/libedit/history.c @@ -676,8 +676,8 @@ history_load(History *h, const char *fname) (void) strunvis(ptr, line); line[sz] = c; if (HENTER(h, &ev, ptr) == -1) { - h_free((ptr_t)ptr); - return -1; + i = -1; + goto oomem; } } oomem: diff --git a/include/my_base.h b/include/my_base.h index 8eab79a96fd..77cd60fda92 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -404,7 +404,8 @@ enum ha_base_keytype { enum en_fieldtype { FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE, FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO, - FIELD_VARCHAR,FIELD_CHECK + FIELD_VARCHAR,FIELD_CHECK, + FIELD_enum_val_count }; enum data_file_type { diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 11ee7284cbf..0c74dc9121c 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -818,7 +818,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) if ((*options->local_infile_init)(&li_ptr, net_filename, options->local_infile_userdata)) { - my_net_write(net,"",0); /* Server needs one packet */ + VOID(my_net_write(net,"",0)); /* Server needs one packet */ net_flush(net); strmov(net->sqlstate, unknown_sqlstate); net->last_errno= (*options->local_infile_error)(li_ptr, diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index bf99830b37f..daac2c4e17e 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -276,7 +276,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, if (subkeys == -1) { /* the last entry in sub-tree */ - _mi_dispose(info, keyinfo, root,DFLT_INIT_HITS); + if (_mi_dispose(info, keyinfo, root,DFLT_INIT_HITS)) + DBUG_RETURN(-1); /* fall through to normal delete */ } else diff --git a/myisam/myisampack.c b/myisam/myisampack.c index d691c24e890..e80a3ffacd9 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -1159,7 +1159,7 @@ static int compare_huff_elements(void *not_used __attribute__((unused)), static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records) { - uint space_fields,fill_zero_fields,field_count[(int) FIELD_VARCHAR+1]; + uint space_fields,fill_zero_fields,field_count[(int) FIELD_enum_val_count]; my_off_t old_length,new_length,length; DBUG_ENTER("check_counts"); diff --git a/myisam/sort.c b/myisam/sort.c index c3eaddb3e92..c9562461f56 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -376,7 +376,10 @@ pthread_handler_t thr_find_all_keys(void *arg) { if (my_init_dynamic_array(&info->buffpek, sizeof(BUFFPEK), maxbuffer, maxbuffer/2)) + { my_free((gptr) sort_keys,MYF(0)); + sort_keys= (uchar **) NULL; /* for err: label */ + } else break; } diff --git a/mysys/default_modify.c b/mysys/default_modify.c index de03d783c68..0f58b8a930c 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -197,7 +197,7 @@ int modify_defaults_file(const char *file_location, const char *option, goto err; } if (my_fclose(cnf_file, MYF(MY_WME))) - goto err; + DBUG_RETURN(1); my_free(file_buffer, MYF(0)); DBUG_RETURN(0); diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 1f3db84304e..e181ccfb88d 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -79,7 +79,7 @@ my_off_t my_b_safe_tell(IO_CACHE *info) void my_b_seek(IO_CACHE *info,my_off_t pos) { - my_off_t offset; + my_off_t offset; DBUG_ENTER("my_b_seek"); DBUG_PRINT("enter",("pos: %lu", (ulong) pos)); @@ -91,10 +91,10 @@ void my_b_seek(IO_CACHE *info,my_off_t pos) b) see if there is a better way to make it work */ if (info->type == SEQ_READ_APPEND) - flush_io_cache(info); - + VOID(flush_io_cache(info)); + offset=(pos - info->pos_in_file); - + if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND) { /* TODO: explain why this works if pos < info->pos_in_file */ @@ -119,7 +119,7 @@ void my_b_seek(IO_CACHE *info,my_off_t pos) info->write_pos = info->write_buffer + offset; DBUG_VOID_RETURN; } - flush_io_cache(info); + VOID(flush_io_cache(info)); /* Correct buffer end so that we write in increments of IO_SIZE */ info->write_end=(info->write_buffer+info->buffer_length- (pos & (IO_SIZE-1))); diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 4a917fc8287..e2875d9e53e 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -69,7 +69,7 @@ my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, (thread_safe ? sizeof(pthread_mutex_t) : 0), MYF(MY_WME | MY_ZEROFILL)))) - return 1; + DBUG_RETURN(1); map->bitmap_size=bitmap_size; #ifdef THREAD if (thread_safe) diff --git a/mysys/my_error.c b/mysys/my_error.c index 0c18bbf6e8b..d7177e7a047 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -189,7 +189,10 @@ int my_error_register(const char **errmsgs, int first, int last) /* Error numbers must be unique. No overlapping is allowed. */ if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last)) + { + my_free((gptr)meh_p, MYF(0)); return 1; + } /* Insert header into the chain. */ meh_p->meh_next= *search_meh_pp; diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc index d83af2b9cf0..a79a6ad6742 100644 --- a/server-tools/instance-manager/parse.cc +++ b/server-tools/instance-manager/parse.cc @@ -107,7 +107,7 @@ Token shift_token(const char **text, uint *word_len) int get_text_id(const char **text, uint *word_len, const char **id) { get_word(text, word_len); - if (word_len == 0) + if (*word_len == 0) return 1; *id= *text; return 0; diff --git a/sql-common/client.c b/sql-common/client.c index 4c2debd41ff..824d3705c23 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -599,7 +599,7 @@ net_safe_read(MYSQL *mysql) DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", vio_description(net->vio),len)); #ifdef MYSQL_SERVER - if (vio_was_interrupted(net->vio)) + if (net->vio && vio_was_interrupted(net->vio)) return (packet_error); #endif /*MYSQL_SERVER*/ end_server(mysql); diff --git a/sql/field.cc b/sql/field.cc index 3903d8323ad..cc8f57fb564 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1570,7 +1570,6 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table, bool Field::quote_data(String *unquoted_string) { char escaped_string[IO_SIZE]; - char *unquoted_string_buffer= (char *)(unquoted_string->ptr()); DBUG_ENTER("Field::quote_data"); if (!needs_quotes()) @@ -4541,8 +4540,6 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs) error= 1; } } - if (error > 1) - error= 2; #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) @@ -7064,7 +7061,7 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type) } get_ptr(&blob); gobj= Geometry::construct(&buffer, blob, blob_length); - if (gobj->get_mbr(&mbr, &dummy)) + if (!gobj || gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else { @@ -7393,7 +7390,7 @@ void Field_geom::get_key_image(char *buff, uint length, imagetype type) } get_ptr(&blob); gobj= Geometry::construct(&buffer, blob, blob_length); - if (gobj->get_mbr(&mbr, &dummy)) + if (!gobj || gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else { @@ -8151,17 +8148,14 @@ const char *Field_bit::unpack(char *to, const char *from) */ Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg, - uchar *null_ptr_arg, uchar null_bit_arg, - uchar *bit_ptr_arg, uchar bit_ofs_arg, - enum utype unireg_check_arg, + uchar *null_ptr_arg, uchar null_bit_arg, + enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg) - : Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, bit_ptr_arg, - bit_ofs_arg, unireg_check_arg, field_name_arg, table_arg), + : Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, 0, + 0, unireg_check_arg, field_name_arg, table_arg), create_length(len_arg) { - bit_ptr= 0; - bit_ofs= 0; bit_len= 0; field_length= ((len_arg + 7) & ~7) / 8; } @@ -8518,8 +8512,8 @@ Field *make_field(char *ptr, uint32 field_length, return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset); case FIELD_TYPE_BIT: return f_bit_as_char(pack_flag) ? - new Field_bit_as_char(ptr, field_length, null_pos, null_bit, bit_ptr, - bit_offset, unireg_check, field_name, table) : + new Field_bit_as_char(ptr, field_length, null_pos, null_bit, + unireg_check, field_name, table) : new Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr, bit_offset, unireg_check, field_name, table); default: // Impossible (Wrong version) diff --git a/sql/field.h b/sql/field.h index ed6bf1c0a9c..5d722fccb18 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1336,12 +1336,12 @@ public: } }; - + class Field_bit_as_char: public Field_bit { public: uchar create_length; Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, - uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, + uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg); enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 08fd2d9a8e3..ff6431fa0f3 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -266,7 +266,8 @@ int ha_myisam::dump(THD* thd, int fd) if (fd < 0) { - my_net_write(net, "", 0); + if (my_net_write(net, "", 0)) + error = errno ? errno : EPIPE; net_flush(net); } @@ -365,12 +366,14 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) { uint old_testflag=param.testflag; param.testflag|=T_MEDIUM; - init_io_cache(¶m.read_cache, file->dfile, - my_default_record_cache_size, READ_CACHE, - share->pack.header_length, 1, MYF(MY_WME)); - error |= chk_data_link(¶m, file, param.testflag & T_EXTEND); - end_io_cache(&(param.read_cache)); - param.testflag=old_testflag; + if (!(error= init_io_cache(¶m.read_cache, file->dfile, + my_default_record_cache_size, READ_CACHE, + share->pack.header_length, 1, MYF(MY_WME)))) + { + error= chk_data_link(¶m, file, param.testflag & T_EXTEND); + end_io_cache(&(param.read_cache)); + } + param.testflag= old_testflag; } } if (!error) diff --git a/sql/item.cc b/sql/item.cc index c15fd948b5a..6b756ff9d60 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -931,9 +931,9 @@ void Item_splocal::cleanup() void Item_splocal::print(String *str) { - str->reserve(m_name.length+8); - str->append(m_name.str, m_name.length); - str->append('@'); + VOID(str->reserve(m_name.length+8)); + VOID(str->append(m_name.str, m_name.length)); + VOID(str->append('@')); str->qs_append(m_offset); } @@ -3784,7 +3784,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) return new Field_year((char*) 0, max_length, null_ptr, 0, Field::NONE, name, table); case MYSQL_TYPE_BIT: - return new Field_bit_as_char(NULL, max_length, null_ptr, 0, NULL, 0, + return new Field_bit_as_char(NULL, max_length, null_ptr, 0, Field::NONE, name, table); default: /* This case should never be chosen */ diff --git a/sql/item_func.cc b/sql/item_func.cc index 89561e8eb17..11f4ea0439a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -888,7 +888,7 @@ String *Item_decimal_typecast::val_str(String *str) my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); if (null_value) return NULL; - my_decimal2string(E_DEC_FATAL_ERROR, &tmp_buf, 0, 0, 0, str); + my_decimal2string(E_DEC_FATAL_ERROR, tmp, 0, 0, 0, str); return str; } @@ -4709,7 +4709,7 @@ Item_func_sp::sp_result_field(void) const { char *empty_name= (char *) ""; TABLE_SHARE *share; - dummy_table->s= share= &dummy_table->share_not_to_be_used; + dummy_table->s= share= &dummy_table->share_not_to_be_used; dummy_table->alias = empty_name; dummy_table->maybe_null = maybe_null; dummy_table->in_use= current_thd; @@ -4742,8 +4742,13 @@ Item_func_sp::execute(Field **flp) } if (!(f= *flp)) { - *flp= f= sp_result_field(); - f->move_field((f->pack_length() > sizeof(result_buf)) ? + if (!(*flp= f= sp_result_field())) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + return 0; + } + + f->move_field((f->pack_length() > sizeof(result_buf)) ? sql_alloc(f->pack_length()) : result_buf); f->null_ptr= (uchar *)&null_value; f->null_bit= 1; diff --git a/sql/log_event.cc b/sql/log_event.cc index 056bcca1a02..e977016ea21 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3253,6 +3253,10 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) case INSERT_ID_EVENT: msg="INSERT_ID"; break; + case INVALID_INT_EVENT: + default: // cannot happen + msg="INVALID_INT"; + break; } fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff)); fflush(file); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d9a608eb064..9a44b6e1cab 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -652,7 +652,6 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, table_map read_tables, COND *conds, bool allow_null_cond, int *error) - { SQL_SELECT *select; DBUG_ENTER("make_select"); @@ -5774,10 +5773,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, if (!quick) return 0; /* no ranges found */ if (quick->init()) - { - delete quick; goto err; - } quick->records= records; if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error || @@ -7111,7 +7107,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ha_rows cur_records; SEL_ARG *cur_index_tree= NULL; ha_rows cur_quick_prefix_records= 0; - uint cur_param_idx; + uint cur_param_idx=MAX_KEY; key_map cur_used_key_parts; uint pk= param->table->s->primary_key; @@ -7327,6 +7323,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) */ if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost)) { + DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY); index_info= cur_index_info; index= cur_index; best_read_cost= cur_read_cost; diff --git a/sql/opt_range.h b/sql/opt_range.h index f84058f3b64..cdb00ea7d0c 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -705,7 +705,7 @@ class SQL_SELECT :public Sql_alloc { class FT_SELECT: public QUICK_RANGE_SELECT { public: FT_SELECT(THD *thd, TABLE *table, uint key) : - QUICK_RANGE_SELECT (thd, table, key, 1) { init(); } + QUICK_RANGE_SELECT (thd, table, key, 1) { VOID(init()); } ~FT_SELECT() { file->ft_end(); } int init() { return error=file->ft_init(); } int reset() { return 0; } diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index d76be2ec2e4..5cdd24afba4 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -929,7 +929,8 @@ bool load_master_data(THD* thd) host was specified; there could have been a problem when replication started, which led to relay log's IO_CACHE to not be inited. */ - flush_master_info(active_mi, 0); + if (flush_master_info(active_mi, 0)) + sql_print_error("Failed to flush master info file"); } mysql_free_result(master_status_res); } diff --git a/sql/set_var.cc b/sql/set_var.cc index 632c37d2296..f10da4ad9ba 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2518,7 +2518,6 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) bool sys_var_sync_binlog_period::update(THD *thd, set_var *var) { - pthread_mutex_t *lock_log= mysql_bin_log.get_log_lock(); sync_binlog_period= (ulong) var->save_result.ulonglong_value; return 0; } diff --git a/sql/slave.cc b/sql/slave.cc index 5e1c838730c..3795cbaf7c0 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2017,7 +2017,8 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) " to the relay log, " "SHOW SLAVE STATUS may be inaccurate"); rli->relay_log.harvest_bytes_written(&rli->log_space_total); - flush_master_info(mi, 1); + if (flush_master_info(mi, 1)) + sql_print_error("Failed to flush master info file"); delete ev; } else @@ -2555,7 +2556,7 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) pthread_mutex_unlock(&mi->rli.data_lock); pthread_mutex_unlock(&mi->data_lock); - + if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length())) DBUG_RETURN(TRUE); } @@ -2563,8 +2564,13 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) DBUG_RETURN(FALSE); } - -bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) +/* + RETURN + 2 - flush relay log failed + 1 - flush master info failed + 0 - all ok +*/ +int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) { IO_CACHE* file = &mi->file; char lbuf[22]; @@ -2583,8 +2589,9 @@ bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) When we come to this place in code, relay log may or not be initialized; the caller is responsible for setting 'flush_relay_log_cache' accordingly. */ - if (flush_relay_log_cache) - flush_io_cache(mi->rli.relay_log.get_log_file()); + if (flush_relay_log_cache && + flush_io_cache(mi->rli.relay_log.get_log_file())) + DBUG_RETURN(2); /* We flushed the relay log BEFORE the master.info file, because if we crash @@ -2596,13 +2603,13 @@ bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) */ /* - In certain cases this code may create master.info files that seems - corrupted, because of extra lines filled with garbage in the end - file (this happens if new contents take less space than previous - contents of file). But because of number of lines in the first line + In certain cases this code may create master.info files that seems + corrupted, because of extra lines filled with garbage in the end + file (this happens if new contents take less space than previous + contents of file). But because of number of lines in the first line of file we don't care about this garbage. */ - + my_b_seek(file, 0L); my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n", LINES_IN_MASTER_INFO_WITH_SSL, @@ -2611,8 +2618,7 @@ bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) mi->password, mi->port, mi->connect_retry, (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert, mi->ssl_cipher, mi->ssl_key); - flush_io_cache(file); - DBUG_RETURN(0); + DBUG_RETURN(-flush_io_cache(file)); } @@ -3644,7 +3650,11 @@ reconnect done to recover from failed read"); sql_print_error("Slave I/O thread could not queue event from master"); goto err; } - flush_master_info(mi, 1); /* sure that we can flush the relay log */ + if (flush_master_info(mi, 1)) + { + sql_print_error("Failed to flush master info file"); + goto err; + } /* See if the relay logs take too much space. We don't lock mi->rli.log_space_lock here; this dirty read saves time diff --git a/sql/slave.h b/sql/slave.h index 4d3c338680d..040ce4eaf85 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -500,7 +500,7 @@ typedef struct st_table_rule_ent int init_slave(); void init_slave_skip_errors(const char* arg); -bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache); +int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache); bool flush_relay_log_info(RELAY_LOG_INFO* rli); int register_slave_on_master(MYSQL* mysql); int terminate_slave_threads(MASTER_INFO* mi, int thread_mask, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index cd83efcac2c..b07a034dfd7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -937,7 +937,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'", (host ? host : "(NULL)"), (ip ? ip : "(NULL)"), - (user ? user : "(NULL)"), (db ? db : "(NULL)"))); + user, (db ? db : "(NULL)"))); sctx->user= user; sctx->host= host; sctx->ip= ip; @@ -966,7 +966,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, for (i=0 ; i < acl_users.elements ; i++) { acl_user= dynamic_element(&acl_users,i,ACL_USER*); - if ((!acl_user->user && (!user || !user[0])) || + if ((!acl_user->user && !user[0]) || (acl_user->user && strcmp(user, acl_user->user) == 0)) { if (compare_hostname(&acl_user->host, host, ip)) @@ -4939,8 +4939,6 @@ static int handle_grant_struct(uint struct_no, bool drop, } if (! user) user= ""; - if (! host) - host= ""; #ifdef EXTRA_DEBUG DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'", struct_no, idx, user, host)); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index bde6522a38b..cff28864ebe 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -287,7 +287,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) } -/* +/* Load database options file load_db_opt() @@ -313,68 +313,72 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) bzero((char*) create,sizeof(*create)); create->default_table_charset= thd->variables.collation_server; - + /* Check if options for this database are already in the hash */ if (!get_dbopt(path, create)) - DBUG_RETURN(0); - - /* Otherwise, load options from the .opt file */ - if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0) - { - IO_CACHE cache; - init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0)); + DBUG_RETURN(0); - while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0) + /* Otherwise, load options from the .opt file */ + if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) + goto err1; + + IO_CACHE cache; + if (init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0))) + goto err2; + + while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0) + { + char *pos= buf+nbytes-1; + /* Remove end space and control characters */ + while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1])) + pos--; + *pos=0; + if ((pos= strchr(buf, '='))) { - char *pos= buf+nbytes-1; - /* Remove end space and control characters */ - while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1])) - pos--; - *pos=0; - if ((pos= strchr(buf, '='))) + if (!strncmp(buf,"default-character-set", (pos-buf))) { - if (!strncmp(buf,"default-character-set", (pos-buf))) - { - /* - Try character set name, and if it fails - try collation name, probably it's an old - 4.1.0 db.opt file, which didn't have - separate default-character-set and - default-collation commands. - */ - if (!(create->default_table_charset= - get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) && - !(create->default_table_charset= - get_charset_by_name(pos+1, MYF(0)))) - { - sql_print_error("Error while loading database options: '%s':",path); - sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1); - create->default_table_charset= default_charset_info; - } - } - else if (!strncmp(buf,"default-collation", (pos-buf))) - { - if (!(create->default_table_charset= get_charset_by_name(pos+1, - MYF(0)))) - { - sql_print_error("Error while loading database options: '%s':",path); - sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1); - create->default_table_charset= default_charset_info; - } - } + /* + Try character set name, and if it fails + try collation name, probably it's an old + 4.1.0 db.opt file, which didn't have + separate default-character-set and + default-collation commands. + */ + if (!(create->default_table_charset= + get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) && + !(create->default_table_charset= + get_charset_by_name(pos+1, MYF(0)))) + { + sql_print_error("Error while loading database options: '%s':",path); + sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1); + create->default_table_charset= default_charset_info; + } + } + else if (!strncmp(buf,"default-collation", (pos-buf))) + { + if (!(create->default_table_charset= get_charset_by_name(pos+1, + MYF(0)))) + { + sql_print_error("Error while loading database options: '%s':",path); + sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1); + create->default_table_charset= default_charset_info; + } } } - end_io_cache(&cache); - my_close(file,MYF(0)); - /* - Put the loaded value into the hash. - Note that another thread could've added the same - entry to the hash after we called get_dbopt(), - but it's not an error, as put_dbopt() takes this - possibility into account. - */ - error= put_dbopt(path, create); } + /* + Put the loaded value into the hash. + Note that another thread could've added the same + entry to the hash after we called get_dbopt(), + but it's not an error, as put_dbopt() takes this + possibility into account. + */ + error= put_dbopt(path, create); + + end_io_cache(&cache); +err2: + my_close(file,MYF(0)); +err1: DBUG_RETURN(error); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index da72d283259..ef0f4243d89 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -377,10 +377,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, address of the 'next' pointer referencing this table for close_thread_table(). */ - for (table_ptr= &(thd->handler_tables); - *table_ptr && (*table_ptr != table); - table_ptr= &(*table_ptr)->next) - {} + for (table_ptr= &(thd->handler_tables); *table_ptr != table; + table_ptr= &(*table_ptr)->next) /* no-op */ ; (*table_ptr)->file->ha_index_or_rnd_end(); VOID(pthread_mutex_lock(&LOCK_open)); if (close_thread_table(thd, table_ptr)) @@ -750,7 +748,7 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) /* Mark table as closed, ready for re-open. */ hash_tables->table= NULL; } - } + } safe_mutex_assert_owner(&LOCK_open); (*table_ptr)->file->ha_index_or_rnd_end(); diff --git a/sql/sql_help.cc b/sql/sql_help.cc index b47412981ea..d6d1a6ed119 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -567,7 +567,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error); if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) || - (res->quick && res->quick->reset())) + (res && res->quick && res->quick->reset())) { delete res; res=0; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8903f28be11..4f61891fb09 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -666,7 +666,8 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) DBUG_ASSERT(view->table != 0 && view->field_translation != 0); - bitmap_init(&used_fields, used_fields_buff, used_fields_buff_size * 8, 0); + VOID(bitmap_init(&used_fields, used_fields_buff, used_fields_buff_size * 8, + 0)); bitmap_clear_all(&used_fields); view->contain_auto_increment= 0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index dc5237d9b7d..7e53d435400 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1593,6 +1593,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_other, &LOCK_status); thd->enable_slow_log= opt_log_slow_admin_statements; db= thd->alloc(db_len + tbl_len + 2); + if (!db) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + break; + } tbl_name= strmake(db, packet + 1, db_len)+1; strmake(tbl_name, packet + db_len + 2, tbl_len); mysql_table_dump(thd, db, tbl_name, -1); @@ -1606,14 +1611,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_other, &LOCK_status); char *user= (char*) packet; char *passwd= strend(user)+1; - /* + /* Old clients send null-terminated string ('\0' for empty string) for password. New clients send the size (1 byte) + string (not null terminated, so also '\0' for empty string). */ - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; - uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); db+= passwd_len + 1; #ifndef EMBEDDED_LIBRARY @@ -6865,6 +6870,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, #ifdef HAVE_REPLICATION if (options & REFRESH_MASTER) { + DBUG_ASSERT(thd); tmp_write_to_binlog= 0; if (reset_master(thd)) { diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index cd293fc21c7..07678d97800 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1197,7 +1197,12 @@ bool change_master(THD* thd, MASTER_INFO* mi) Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never a slave before). */ - flush_master_info(mi, 0); + if (flush_master_info(mi, 0)) + { + my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file"); + unlock_slave_threads(mi); + DBUG_RETURN(TRUE); + } if (need_relay_log_purge) { relay_log_purge= 1; @@ -1307,14 +1312,15 @@ bool mysql_show_binlog_events(THD* thd) bool ret = TRUE; IO_CACHE log; File file = -1; - Format_description_log_event *description_event= new - Format_description_log_event(3); /* MySQL 4.0 by default */ Log_event::init_show_field_list(&field_list); if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); + Format_description_log_event *description_event= new + Format_description_log_event(3); /* MySQL 4.0 by default */ + if (mysql_bin_log.is_open()) { LEX_MASTER_INFO *lex_mi= &thd->lex->mi; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 82870d46e6c..7a1535edcac 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -663,7 +663,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) it's a keyword */ - packet->reserve(length*2 + 2); + VOID(packet->reserve(length*2 + 2)); quote_char= (char) q; packet->append("e_char, 1, system_charset_info); @@ -950,13 +950,13 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) if (key_part->field) append_identifier(thd,packet,key_part->field->field_name, strlen(key_part->field->field_name)); - if (!key_part->field || + if (key_part->field && (key_part->length != table->field[key_part->fieldnr-1]->key_length() && !(key_info->flags & HA_FULLTEXT))) { buff[0] = '('; - char* end=int10_to_str((long) key_part->length / + char* end=int10_to_str((long) key_part->length / key_part->field->charset()->mbmaxlen, buff + 1,10); *end++ = ')'; @@ -1732,7 +1732,8 @@ LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str, { MEM_ROOT *mem= thd->mem_root; if (allocate_lex_string) - lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING)); + if (!(lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING)))) + return 0; lex_str->str= strmake_root(mem, str, length); lex_str->length= length; return lex_str; @@ -2933,7 +2934,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, /* I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS rather than in SHOW KEYS - */ + */ if (!tables->view) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->net.last_errno, thd->net.last_error); @@ -2946,7 +2947,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, { TABLE *show_table= tables->table; KEY *key_info=show_table->key_info; - show_table->file->info(HA_STATUS_VARIABLE | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < show_table->s->keys ; i++,key_info++) @@ -2958,7 +2959,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, restore_record(table, s->default_values); table->field[1]->store(base_name, strlen(base_name), cs); table->field[2]->store(file_name, strlen(file_name), cs); - table->field[3]->store((longlong) ((key_info->flags & + table->field[3]->store((longlong) ((key_info->flags & HA_NOSAME) ? 0 : 1), TRUE); table->field[4]->store(base_name, strlen(base_name), cs); table->field[5]->store(key_info->name, strlen(key_info->name), cs); @@ -2981,12 +2982,12 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, table->field[9]->store((longlong) records, TRUE); table->field[9]->set_notnull(); } - if (!(key_info->flags & HA_FULLTEXT) && - (!key_part->field || - key_part->length != + if (!(key_info->flags & HA_FULLTEXT) && + (key_part->field && + key_part->length != show_table->field[key_part->fieldnr-1]->key_length())) { - table->field[10]->store((longlong) key_part->length / + table->field[10]->store((longlong) key_part->length / key_part->field->charset()->mbmaxlen); table->field[10]->set_notnull(); } diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 1bd298dda04..975cc19ea3f 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -450,7 +450,7 @@ void mysql_print_status() calc_sum_of_all_status(&tmp); printf("\nStatus information:\n\n"); - my_getwd(current_dir, sizeof(current_dir),MYF(0)); + VOID(my_getwd(current_dir, sizeof(current_dir),MYF(0))); printf("Current dir: %s\n", current_dir); printf("Running threads: %d Stack size: %ld\n", thread_count, (long) thread_stack); diff --git a/sql/table.cc b/sql/table.cc index fc75568b615..45f8edddd0b 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1040,7 +1040,10 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) ret_value=uint4korr(pos); } if (! save_names) - my_free((gptr) buf,MYF(0)); + { + if (names) + my_free((gptr) buf,MYF(0)); + } else if (!names) bzero((char*) save_names,sizeof(save_names)); else diff --git a/sql/uniques.cc b/sql/uniques.cc index 367aed2d113..ad074f8b2b0 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -38,8 +38,8 @@ int unique_write_to_file(gptr key, element_count count, Unique *unique) { /* - Use unique->size (size of element stored in the tree) and not - unique->tree.size_of_element. The latter is different from unique->size + Use unique->size (size of element stored in the tree) and not + unique->tree.size_of_element. The latter is different from unique->size when tree implementation chooses to store pointer to key in TREE_ELEMENT (instead of storing the element itself there) */ @@ -63,27 +63,27 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, comp_func_fixed_arg); /* If the following fail's the next add will also fail */ my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16); - /* + /* If you change the following, change it in get_max_elements function, too. */ max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size); - open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, - MYF(MY_WME)); + VOID(open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, + MYF(MY_WME))); } /* Calculate log2(n!) - + NOTES Stirling's approximate formula is used: - - n! ~= sqrt(2*M_PI*n) * (n/M_E)^n - + + n! ~= sqrt(2*M_PI*n) * (n/M_E)^n + Derivation of formula used for calculations is as follows: log2(n!) = log(n!)/log(2) = log(sqrt(2*M_PI*n)*(n/M_E)^n) / log(2) = - + = (log(2*M_PI*n)/2 + n*log(n/M_E)) / log(2). */ @@ -94,7 +94,7 @@ inline double log2_n_fact(double x) /* - Calculate cost of merge_buffers function call for given sequence of + Calculate cost of merge_buffers function call for given sequence of input stream lengths and store the number of rows in result stream in *last. SYNOPSIS @@ -103,21 +103,21 @@ inline double log2_n_fact(double x) elem_size Size of element stored in buffer first Pointer to first merged element size last Pointer to last merged element size - + RETURN Cost of merge_buffers operation in disk seeks. - + NOTES It is assumed that no rows are eliminated during merge. - The cost is calculated as - + The cost is calculated as + cost(read_and_write) + cost(merge_comparisons). - - All bytes in the sequences is read and written back during merge so cost + + All bytes in the sequences is read and written back during merge so cost of disk io is 2*elem_size*total_buf_elems/IO_SIZE (2 is for read + write) - + For comparisons cost calculations we assume that all merged sequences have - the same length, so each of total_buf_size elements will be added to a sort + the same length, so each of total_buf_size elements will be added to a sort heap with (n_buffers-1) elements. This gives the comparison cost: total_buf_elems* log2(n_buffers) / TIME_FOR_COMPARE_ROWID; @@ -125,16 +125,16 @@ inline double log2_n_fact(double x) static double get_merge_buffers_cost(uint *buff_elems, uint elem_size, uint *first, uint *last) -{ +{ uint total_buf_elems= 0; for (uint *pbuf= first; pbuf <= last; pbuf++) total_buf_elems+= *pbuf; *last= total_buf_elems; - + int n_buffers= last - first + 1; /* Using log2(n)=log(n)/log(2) formula */ - return 2*((double)total_buf_elems*elem_size) / IO_SIZE + + return 2*((double)total_buf_elems*elem_size) / IO_SIZE + total_buf_elems*log((double) n_buffers) / (TIME_FOR_COMPARE_ROWID * M_LN2); } @@ -142,13 +142,13 @@ static double get_merge_buffers_cost(uint *buff_elems, uint elem_size, /* Calculate cost of merging buffers into one in Unique::get, i.e. calculate how long (in terms of disk seeks) the two calls - merge_many_buffs(...); - merge_buffers(...); + merge_many_buffs(...); + merge_buffers(...); will take. SYNOPSIS get_merge_many_buffs_cost() - buffer buffer space for temporary data, at least + buffer buffer space for temporary data, at least Unique::get_cost_calc_buff_size bytes maxbuffer # of full buffers max_n_elems # of elements in first maxbuffer buffers @@ -156,12 +156,12 @@ static double get_merge_buffers_cost(uint *buff_elems, uint elem_size, elem_size size of buffer element NOTES - maxbuffer+1 buffers are merged, where first maxbuffer buffers contain + maxbuffer+1 buffers are merged, where first maxbuffer buffers contain max_n_elems elements each and last buffer contains last_n_elems elements. The current implementation does a dumb simulation of merge_many_buffs function actions. - + RETURN Cost of merge in disk seeks. */ @@ -173,17 +173,17 @@ static double get_merge_many_buffs_cost(uint *buffer, register int i; double total_cost= 0.0; uint *buff_elems= buffer; /* #s of elements in each of merged sequences */ - - /* + + /* Set initial state: first maxbuffer sequences contain max_n_elems elements each, last sequence contains last_n_elems elements. */ for (i = 0; i < (int)maxbuffer; i++) - buff_elems[i]= max_n_elems; + buff_elems[i]= max_n_elems; buff_elems[maxbuffer]= last_n_elems; - /* - Do it exactly as merge_many_buff function does, calling + /* + Do it exactly as merge_many_buff function does, calling get_merge_buffers_cost to get cost of merge_buffers. */ if (maxbuffer >= MERGEBUFF2) @@ -194,17 +194,17 @@ static double get_merge_many_buffs_cost(uint *buffer, for (i = 0; i <= (int) maxbuffer - MERGEBUFF*3/2; i += MERGEBUFF) { total_cost+=get_merge_buffers_cost(buff_elems, elem_size, - buff_elems + i, + buff_elems + i, buff_elems + i + MERGEBUFF-1); lastbuff++; } total_cost+=get_merge_buffers_cost(buff_elems, elem_size, - buff_elems + i, + buff_elems + i, buff_elems + maxbuffer); maxbuffer= lastbuff; } } - + /* Simulate final merge_buff call. */ total_cost += get_merge_buffers_cost(buff_elems, elem_size, buff_elems, buff_elems + maxbuffer); @@ -213,7 +213,7 @@ static double get_merge_many_buffs_cost(uint *buffer, /* - Calculate cost of using Unique for processing nkeys elements of size + Calculate cost of using Unique for processing nkeys elements of size key_size using max_in_memory_size memory. SYNOPSIS @@ -223,12 +223,12 @@ static double get_merge_many_buffs_cost(uint *buffer, nkeys #of elements in Unique key_size size of each elements in bytes max_in_memory_size amount of memory Unique will be allowed to use - + RETURN Cost in disk seeks. - + NOTES - cost(using_unqiue) = + cost(using_unqiue) = cost(create_trees) + (see #1) cost(merge) + (see #2) cost(read_result) (see #3) @@ -237,42 +237,42 @@ static double get_merge_many_buffs_cost(uint *buffer, For each Unique::put operation there will be 2*log2(n+1) elements comparisons, where n runs from 1 tree_size (we assume that all added elements are different). Together this gives: - + n_compares = 2*(log2(2) + log2(3) + ... + log2(N+1)) = 2*log2((N+1)!) - + then cost(tree_creation) = n_compares*ROWID_COMPARE_COST; Total cost of creating trees: (n_trees - 1)*max_size_tree_cost + non_max_size_tree_cost. Approximate value of log2(N!) is calculated by log2_n_fact function. - + 2. Cost of merging. If only one tree is created by Unique no merging will be necessary. Otherwise, we model execution of merge_many_buff function and count - #of merges. (The reason behind this is that number of buffers is small, - while size of buffers is big and we don't want to loose precision with + #of merges. (The reason behind this is that number of buffers is small, + while size of buffers is big and we don't want to loose precision with O(x)-style formula) - + 3. If only one tree is created by Unique no disk io will happen. - Otherwise, ceil(key_len*n_keys) disk seeks are necessary. We assume + Otherwise, ceil(key_len*n_keys) disk seeks are necessary. We assume these will be random seeks. */ -double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size, +double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size, ulong max_in_memory_size) { ulong max_elements_in_tree; ulong last_tree_elems; int n_full_trees; /* number of trees in unique - 1 */ double result; - - max_elements_in_tree= + + max_elements_in_tree= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); n_full_trees= nkeys / max_elements_in_tree; last_tree_elems= nkeys % max_elements_in_tree; - + /* Calculate cost of creating trees */ result= 2*log2_n_fact(last_tree_elems + 1.0); if (n_full_trees) @@ -285,13 +285,13 @@ double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size, if (!n_full_trees) return result; - - /* + + /* There is more then one tree and merging is necessary. First, add cost of writing all trees to disk, assuming that all disk writes are sequential. */ - result += DISK_SEEK_BASE_COST * n_full_trees * + result += DISK_SEEK_BASE_COST * n_full_trees * ceil(((double) key_size)*max_elements_in_tree / IO_SIZE); result += DISK_SEEK_BASE_COST * ceil(((double) key_size)*last_tree_elems / IO_SIZE); @@ -303,8 +303,8 @@ double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size, return merge_cost; result += merge_cost; - /* - Add cost of reading the resulting sequence, assuming there were no + /* + Add cost of reading the resulting sequence, assuming there were no duplicate elements. */ result += ceil((double)key_size*nkeys/IO_SIZE); @@ -320,7 +320,7 @@ Unique::~Unique() } - /* Write tree to disk; clear tree */ + /* Write tree to disk; clear tree */ bool Unique::flush() { BUFFPEK file_ptr; @@ -359,7 +359,7 @@ Unique::reset() } elements= 0; } - + /* The comparison function, passed to queue_init() in merge_walk() must use comparison function of Uniques::tree, but compare members of struct @@ -386,7 +386,7 @@ C_MODE_END /* DESCRIPTION - Function is very similar to merge_buffers, but instead of writing sorted + Function is very similar to merge_buffers, but instead of writing sorted unique keys to the output file, it invokes walk_action for each key. This saves I/O if you need to pass through all unique keys only once. SYNOPSIS @@ -601,7 +601,7 @@ bool Unique::get(TABLE *table) bool error=1; /* Open cached file if it isn't open */ - outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), + outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), MYF(MY_ZEROFILL)); if (!outfile || ! my_b_inited(outfile) && @@ -618,7 +618,7 @@ bool Unique::get(TABLE *table) sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.not_killable=1; - if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * + if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * sort_param.sort_length, MYF(0)))) return 1; @@ -633,7 +633,7 @@ bool Unique::get(TABLE *table) goto err; if (merge_buffers(&sort_param, &file, outfile, sort_buffer, file_ptr, file_ptr, file_ptr+maxbuffer,0)) - goto err; + goto err; error=0; err: x_free((gptr) sort_buffer); From 9af5f7f9414603a8db61ef310f26b68ef04a8764 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Jan 2006 17:32:25 +0100 Subject: [PATCH 06/37] BSD make compatibility --- Docs/Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 542c82d8f58..f512aa9e29e 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -45,22 +45,22 @@ CLEAN_FILES: $(TXT_FILES) GT = $(srcdir)/Support/generate-text-files.pl ../INSTALL-SOURCE: mysql.info $(GT) - perl -w $(GT) $< "installing-source" "windows-source-build" > $@ + perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@ ../INSTALL-WIN-SOURCE: mysql.info $(GT) - perl -w $(GT) $< "windows-source-build" "post-installation" > $@ + perl -w $(GT) mysql.info "windows-source-build" "post-installation" > $@ # We put the description for the binary installation here so that # people who download source wont have to see it. It is moved up to # the toplevel by the script that makes the binary tar files. INSTALL-BINARY: mysql.info $(GT) - perl -w $(GT) $< "installing-binary" "installing-source" > $@ + perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@ ../EXCEPTIONS-CLIENT: mysql.info $(GT) - perl -w $(GT) $< "mysql-floss-license-exception" "function-index" > $@ + perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@ ../support-files/MacOSX/ReadMe.txt: mysql.info $(GT) - perl -w $(GT) $< "mac-os-x-installation" "netware-installation" > $@ + perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@ # Don't update the files from bitkeeper %::SCCS/s.% From 1e968057523db1313438368812b99a38ba460542 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Jan 2006 15:11:05 +0100 Subject: [PATCH 07/37] Fixing BUG#15658: Server crashes after creating function as empty string Empty strings (and names with trailing spaces) should not be allowed. mysql-test/r/sp-error.result: New testcase for BUG#15658 mysql-test/t/sp-error.test: New testcase for BUG#15658 sql/share/errmsg.txt: New error message for bad stored routine names. sql/sp_head.cc: Added function for checking SP names. (Mustn't be empty or contain trailing spaces.) sql/sp_head.h: Added function for checking SP names. sql/sql_yacc.yy: Check db and name for stored routines. --- mysql-test/r/sp-error.result | 19 +++++++++++++++++++ mysql-test/t/sp-error.test | 27 +++++++++++++++++++++++++++ sql/share/errmsg.txt | 2 ++ sql/sp_head.cc | 17 +++++++++++++++++ sql/sp_head.h | 2 ++ sql/sql_yacc.yy | 15 +++++++++++++++ 6 files changed, 82 insertions(+) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index d7bed7e88a7..a784b59a6e5 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1128,3 +1128,22 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function drop function bug11555_1; drop table t1; drop view v1; +drop procedure if exists ` bug15658`; +create procedure ``() select 1; +ERROR 42000: Incorrect routine name '' +create procedure ` `() select 1; +ERROR 42000: Incorrect routine name ' ' +create procedure `bug15658 `() select 1; +ERROR 42000: Incorrect routine name 'bug15658 ' +create procedure ``.bug15658() select 1; +ERROR 42000: Incorrect database name '' +create procedure `x `.bug15658() select 1; +ERROR 42000: Incorrect database name 'x ' +create procedure ` bug15658`() select 1; +call ` bug15658`(); +1 +1 +show procedure status; +Db Name Type Definer Modified Created Security_type Comment +test bug15658 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +drop procedure ` bug15658`; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index cf8f8dfc79c..25944144d21 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1556,6 +1556,7 @@ drop procedure bug13012_1| drop function bug13012_2| delimiter ;| +# # BUG#11555 "Stored procedures: current SP tables locking make # impossible view security". We should not expose names of tables # which are implicitly used by view (via stored routines/triggers). @@ -1616,7 +1617,33 @@ drop function bug11555_1; drop table t1; drop view v1; +# +# BUG#15658: Server crashes after creating function as empty string +# +--disable_warnings +drop procedure if exists ` bug15658`; +--enable_warnings +--error ER_SP_WRONG_NAME +create procedure ``() select 1; +--error ER_SP_WRONG_NAME +create procedure ` `() select 1; +--error ER_SP_WRONG_NAME +create procedure `bug15658 `() select 1; +--error ER_WRONG_DB_NAME +create procedure ``.bug15658() select 1; +--error ER_WRONG_DB_NAME +create procedure `x `.bug15658() select 1; + +# This should work +create procedure ` bug15658`() select 1; +call ` bug15658`(); +--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' +show procedure status; +drop procedure ` bug15658`; + + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 185b4326c5c..63c75cdaddc 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5605,3 +5605,5 @@ ER_SP_RECURSION_LIMIT ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.64s überschritten" ER_SP_PROC_TABLE_CORRUPT eng "Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)" +ER_SP_WRONG_NAME 42000 + eng "Incorrect routine name '%-.64s'" diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 12f9260e7b1..bf1de53acd6 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -384,6 +384,23 @@ sp_name_current_db_new(THD *thd, LEX_STRING name) return qname; } +/* + * Check that the name 'ident' is ok. It's assumed to be an 'ident' + * from the parser, so we only have to check length and trailing spaces. + * The former is a standard requirement (and 'show status' assumes a + * non-empty name), the latter is a mysql:ism as trailing spaces are + * removed by get_field(). + * + * RETURN + * TRUE - bad name + * FALSE - name is ok + */ + +bool +sp_name_check(LEX_STRING ident) +{ + return (!ident.str || !ident.str[0] || ident.str[ident.length-1] == ' '); +} /* ------------------------------------------------------------------ */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 2eebd35f6dc..30859ee8f8a 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -102,6 +102,8 @@ public: sp_name * sp_name_current_db_new(THD *thd, LEX_STRING name); +bool +sp_name_check(LEX_STRING name); class sp_head :private Query_arena { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 25e10362ece..281e3e2eb5b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1288,11 +1288,26 @@ clear_privileges: sp_name: ident '.' ident { + if (!$1.str || check_db_name($1.str)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); + YYABORT; + } + if (sp_name_check($3)) + { + my_error(ER_SP_WRONG_NAME, MYF(0), $3.str); + YYABORT; + } $$= new sp_name($1, $3); $$->init_qname(YYTHD); } | ident { + if (sp_name_check($1)) + { + my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); + YYABORT; + } $$= sp_name_current_db_new(YYTHD, $1); } ; From 988584f0dde5433f286d5a1d2740c1f73314cb86 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jan 2006 17:32:39 +0300 Subject: [PATCH 08/37] Fixes bug #15787. Fix makes available _FILE_OFFSET_BITS definition for zlib library in order to enable support of files larger than 2Gb. Providing an effective test is hardly possible, since the problem starts only when archive table becomes larger than 2Gb. zlib/gzio.c: Move include of zutil.h on top of gzio.c to include chain of zutil.h->zlib.h->zconf.h->config.h before including anything else. zlib/zconf.h: Includes config.h in order to make _FILE_OFFSET_BITS definition available. --- zlib/gzio.c | 4 ++-- zlib/zconf.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/zlib/gzio.c b/zlib/gzio.c index 7e90f4928fc..afac5352323 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -7,10 +7,10 @@ /* @(#) $Id$ */ -#include - #include "zutil.h" +#include + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif diff --git a/zlib/zconf.h b/zlib/zconf.h index 03a9431c8be..f786a20a6f9 100644 --- a/zlib/zconf.h +++ b/zlib/zconf.h @@ -8,6 +8,10 @@ #ifndef ZCONF_H #define ZCONF_H +#ifdef HAVE_CONFIG_H +#include +#endif + /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. From ba3086a2d25db49eee788bdc241de799afd769c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Jan 2006 11:43:50 +1100 Subject: [PATCH 09/37] BUG#11331 "Warning: could not add log destination" message does not provide enough info Implement error reporting to Logger and associated classes. ndb/include/logger/LogHandler.hpp: Add error string to LogHandler along with error code ndb/include/logger/Logger.hpp: Add reporting back of error to addHandler(BaseString). ndb/src/common/logger/FileLogHandler.cpp: Implement error reporting ndb/src/common/logger/LogHandler.cpp: Implement error reporting. Trim spaces and tabs out of parameter names. This allows "p=v, param=value" ndb/src/common/logger/Logger.cpp: Report back errors when adding a handler via BaseString ndb/src/common/logger/SysLogHandler.cpp: Report an error on invalid syslog facility ndb/src/mgmsrv/MgmtSrvr.cpp: Report error when adding log handler --- ndb/include/logger/LogHandler.hpp | 13 +++++++++++ ndb/include/logger/Logger.hpp | 5 +++- ndb/src/common/logger/FileLogHandler.cpp | 17 ++++++++++---- ndb/src/common/logger/LogHandler.cpp | 29 +++++++++++++++++++++--- ndb/src/common/logger/Logger.cpp | 11 ++++++++- ndb/src/common/logger/SysLogHandler.cpp | 1 + ndb/src/mgmsrv/MgmtSrvr.cpp | 14 ++++++++++-- 7 files changed, 79 insertions(+), 11 deletions(-) diff --git a/ndb/include/logger/LogHandler.hpp b/ndb/include/logger/LogHandler.hpp index 7df6ad864e5..8b9aa43d7a9 100644 --- a/ndb/include/logger/LogHandler.hpp +++ b/ndb/include/logger/LogHandler.hpp @@ -125,6 +125,18 @@ public: */ void setErrorCode(int code); + /** + * Returns the error string. + */ + char* getErrorStr(); + + /** + * Sets the error string. + * + * @param str the error string. + */ + void setErrorStr(char* str); + /** * Parse logstring parameters * @@ -195,6 +207,7 @@ private: const char* m_pDateTimeFormat; int m_errorCode; + char* m_errorStr; // for handling repeated messages unsigned m_count_repeated_messages; diff --git a/ndb/include/logger/Logger.hpp b/ndb/include/logger/Logger.hpp index ee762098fb6..3414468d42d 100644 --- a/ndb/include/logger/Logger.hpp +++ b/ndb/include/logger/Logger.hpp @@ -178,8 +178,11 @@ public: * Add a new handler * * @param logstring string describing the handler to add + * @param err OS errno in event of error + * @param len max length of errStr buffer + * @param errStr logger error string in event of error */ - bool addHandler(const BaseString &logstring); + bool addHandler(const BaseString &logstring, int *err, int len, char* errStr); /** * Remove a log handler. diff --git a/ndb/src/common/logger/FileLogHandler.cpp b/ndb/src/common/logger/FileLogHandler.cpp index 8678b999b6f..3d29e63ac1f 100644 --- a/ndb/src/common/logger/FileLogHandler.cpp +++ b/ndb/src/common/logger/FileLogHandler.cpp @@ -187,6 +187,7 @@ FileLogHandler::setParam(const BaseString ¶m, const BaseString &value){ return setMaxSize(value); if(param == "maxfiles") return setMaxFiles(value); + setErrorStr("Invalid parameter"); return false; } @@ -196,16 +197,18 @@ FileLogHandler::setFilename(const BaseString &filename) { if(m_pLogFile) delete m_pLogFile; m_pLogFile = new File_class(filename.c_str(), "a+"); - open(); - return true; + return open(); } bool FileLogHandler::setMaxSize(const BaseString &size) { char *end; long val = strtol(size.c_str(), &end, 0); /* XXX */ - if(size.c_str() == end) + if(size.c_str() == end || val < 0) + { + setErrorStr("Invalid file size"); return false; + } if(end[0] == 'M') val *= 1024*1024; if(end[0] == 'k') @@ -220,8 +223,11 @@ bool FileLogHandler::setMaxFiles(const BaseString &files) { char *end; long val = strtol(files.c_str(), &end, 0); - if(files.c_str() == end) + if(files.c_str() == end || val < 1) + { + setErrorStr("Invalid maximum number of files"); return false; + } m_maxNoFiles = val; return true; @@ -230,6 +236,9 @@ FileLogHandler::setMaxFiles(const BaseString &files) { bool FileLogHandler::checkParams() { if(m_pLogFile == NULL) + { + setErrorStr("Log file cannot be null."); return false; + } return true; } diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp index 521bd346fd3..c11f962d4fb 100644 --- a/ndb/src/common/logger/LogHandler.cpp +++ b/ndb/src/common/logger/LogHandler.cpp @@ -23,7 +23,8 @@ // LogHandler::LogHandler() : m_pDateTimeFormat("%d-%.2d-%.2d %.2d:%.2d:%.2d"), - m_errorCode(0) + m_errorCode(0), + m_errorStr(NULL) { m_max_repeat_frequency= 3; // repeat messages maximum every 3 seconds m_count_repeated_messages= 0; @@ -155,6 +156,19 @@ LogHandler::setErrorCode(int code) m_errorCode = code; } + +char* +LogHandler::getErrorStr() +{ + return m_errorStr; +} + +void +LogHandler::setErrorStr(char* str) +{ + m_errorStr= str; +} + bool LogHandler::parseParams(const BaseString &_params) { Vector v_args; @@ -165,9 +179,18 @@ LogHandler::parseParams(const BaseString &_params) { for(size_t i=0; i < v_args.size(); i++) { Vector v_param_value; if(v_args[i].split(v_param_value, "=", 2) != 2) + { ret = false; - else if (!setParam(v_param_value[0], v_param_value[1])) - ret = false; + setErrorStr("Can't find key=value pair."); + } + else + { + v_param_value[0].trim(" \t"); + if (!setParam(v_param_value[0], v_param_value[1])) + { + ret = false; + } + } } if(!checkParams()) diff --git a/ndb/src/common/logger/Logger.cpp b/ndb/src/common/logger/Logger.cpp index 4a48236053d..48e084a782b 100644 --- a/ndb/src/common/logger/Logger.cpp +++ b/ndb/src/common/logger/Logger.cpp @@ -167,7 +167,7 @@ Logger::addHandler(LogHandler* pHandler) } bool -Logger::addHandler(const BaseString &logstring) { +Logger::addHandler(const BaseString &logstring, int *err, int len, char* errStr) { size_t i; Vector logdest; Vectorloghandlers; @@ -200,9 +200,18 @@ Logger::addHandler(const BaseString &logstring) { handler = new ConsoleLogHandler(); if(handler == NULL) + { + snprintf(errStr,len,"Could not create log destination: %s", + logdest[i].c_str()); DBUG_RETURN(false); + } if(!handler->parseParams(params)) + { + *err= handler->getErrorCode(); + if(handler->getErrorStr()) + strncpy(errStr, handler->getErrorStr(), len); DBUG_RETURN(false); + } loghandlers.push_back(handler); } diff --git a/ndb/src/common/logger/SysLogHandler.cpp b/ndb/src/common/logger/SysLogHandler.cpp index 5b1b8d85ca7..c7fcb102dd4 100644 --- a/ndb/src/common/logger/SysLogHandler.cpp +++ b/ndb/src/common/logger/SysLogHandler.cpp @@ -154,5 +154,6 @@ SysLogHandler::setFacility(const BaseString &facility) { return true; } } + setErrorStr("Invalid syslog facility name"); return false; } diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 3ee0dc6e750..47d156c1f9e 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -179,6 +179,8 @@ MgmtSrvr::startEventLog() } const char * tmp; + char errStr[100]; + int err= 0; BaseString logdest; char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId); NdbAutoPtr tmp_aptr(clusterLog); @@ -192,9 +194,17 @@ MgmtSrvr::startEventLog() logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6", clusterLog); } - if(!g_eventLogger.addHandler(logdest)) { + errStr[0]='\0'; + if(!g_eventLogger.addHandler(logdest, &err, sizeof(errStr), errStr)) { ndbout << "Warning: could not add log destination \"" - << logdest.c_str() << "\"" << endl; + << logdest.c_str() << "\". Reason: "; + if(err) + ndbout << strerror(err); + if(err && errStr[0]!='\0') + ndbout << ", "; + if(errStr[0]!='\0') + ndbout << errStr; + ndbout << endl; } } From 38229d741298901be174f03f5cc05841db0e81ad Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 00:13:18 +1100 Subject: [PATCH 10/37] BUG#12124 ndb_mgm -e "# stop" does not allow stopping ndb_mgmd processes on other systems WL#2703 restart for ndb_mgmd Solving two problems with one stone. Allows the stopping and restarting of mgm nodes other than the one the mgmclient is connected to. ndb/include/mgmapi/mgmapi.h: Add the internal ndb_mgm_end_session command. This will unreserve the nodeid we have allocated synchronously. Otherwise we can't do a restart of a node really quickly as the nodeids are cleaned up after the connection to mgmd is closed. ndb/include/mgmcommon/ConfigRetriever.hpp: Allow configuration on if end_session is going to be called on object destruction. We need to set this to false for ndbd as we fork() ndb/src/common/mgmcommon/ConfigRetriever.cpp: When destroying ConfigRetreiver, ndb_mgm_end_session - i.e. deallocate the nodeid ndb/src/common/util/SocketServer.cpp: When destroying a SocketServer, close the server socket. ndb/src/kernel/main.cpp: don't purge allocated resources when cleaning up in parent process (nodeid) ndb/src/kernel/vm/Configuration.cpp: have option end_session to closeConfiguration ndb/src/kernel/vm/Configuration.hpp: have option end_session to closeConfiguration ndb/src/mgmapi/mgmapi.cpp: Implement ndb_mgm_end_session ndb/src/mgmclient/CommandInterpreter.cpp: Correct output of STOP as we can now stop mgmd as well as ndbd ndb/src/mgmsrv/MgmtSrvr.cpp: Add code into start for connecting to our own mgmd. Create sendStopMgmd() which does the same job as sendSTOP_REQ, but for ndb_mgmd Allow stopping of other ndb_mgmd processes by creating a connection to them and issuing the stop command When stopping all nodes, stop other ndb_mgmd processes as well. Remove set_connect_string. Replace with connect_to_self. This is a much better way of doing things. ndb/src/mgmsrv/MgmtSrvr.hpp: add connect_to_self and remove set_connect_string. ndb/src/mgmsrv/Services.cpp: Add endSession. - delete Allocated_resources for this connection - create new Allocated_resources for this connection conceivably you could keep the socket open across node restarts (and even possibly get a different node id). But I wouldn't try it and expect happiness. ndb/src/mgmsrv/Services.hpp: Add endSession ndb/src/mgmsrv/main.cpp: allow mgmd to be restarted. - add g_RestartServer flag - move connecting to our own mgmd into MgmtSrvr (where it belongs) - output correct Shutdown/Restart message on shutdown/restart --- ndb/include/mgmapi/mgmapi.h | 16 +++ ndb/include/mgmcommon/ConfigRetriever.hpp | 3 + ndb/src/common/mgmcommon/ConfigRetriever.cpp | 3 + ndb/src/common/util/SocketServer.cpp | 2 + ndb/src/kernel/main.cpp | 5 +- ndb/src/kernel/vm/Configuration.cpp | 3 +- ndb/src/kernel/vm/Configuration.hpp | 2 +- ndb/src/mgmapi/mgmapi.cpp | 19 +++ ndb/src/mgmclient/CommandInterpreter.cpp | 23 ++- ndb/src/mgmsrv/MgmtSrvr.cpp | 141 +++++++++++++++++-- ndb/src/mgmsrv/MgmtSrvr.hpp | 11 +- ndb/src/mgmsrv/Services.cpp | 15 +- ndb/src/mgmsrv/Services.hpp | 1 + ndb/src/mgmsrv/main.cpp | 55 +++----- 14 files changed, 239 insertions(+), 60 deletions(-) diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h index 36dee7193c7..6e2d53abcf3 100644 --- a/ndb/include/mgmapi/mgmapi.h +++ b/ndb/include/mgmapi/mgmapi.h @@ -993,6 +993,22 @@ extern "C" { int ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned version, int nodetype); + /** + * End Session + * + * This function tells the mgm server to free all resources associated with + * this connection. It will also close it. + * + * This differs from just disconnecting as we now synchronously clean up, + * so that a quickly restarting server that needs the same node id can + * get it when it restarts. + * + * @param handle NDB management handle + * @return 0 on success + * + * @note you still have to destroy the NdbMgmHandle. + */ + int ndb_mgm_end_session(NdbMgmHandle handle); /** * Get the node id of the mgm server we're connected to diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp index c0b877af07d..1b4ecd56f80 100644 --- a/ndb/include/mgmcommon/ConfigRetriever.hpp +++ b/ndb/include/mgmcommon/ConfigRetriever.hpp @@ -78,6 +78,7 @@ public: const char *get_connectstring(char *buf, int buf_sz) const; NdbMgmHandle get_mgmHandle() { return m_handle; }; NdbMgmHandle* get_mgmHandlePtr() { return &m_handle; }; + void end_session(bool end) { m_end_session= end; }; Uint32 get_configuration_nodeid() const; private: @@ -92,6 +93,8 @@ private: void setError(ErrorType, const char * errorMsg); Uint32 _ownNodeId; + bool m_end_session; + /* Uint32 m_mgmd_port; const char *m_mgmd_host; diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index a44550da48b..fb3531d81f6 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -52,6 +52,7 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string, m_version = version; m_node_type = node_type; _ownNodeId= 0; + m_end_session= true; m_handle= ndb_mgm_create_handle(); @@ -73,6 +74,8 @@ ConfigRetriever::~ConfigRetriever() { DBUG_ENTER("ConfigRetriever::~ConfigRetriever"); if (m_handle) { + if(m_end_session) + ndb_mgm_end_session(m_handle); ndb_mgm_disconnect(m_handle); ndb_mgm_destroy_handle(&m_handle); } diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp index 15dca2d96b1..481c656b78b 100644 --- a/ndb/src/common/util/SocketServer.cpp +++ b/ndb/src/common/util/SocketServer.cpp @@ -42,6 +42,8 @@ SocketServer::~SocketServer() { delete m_sessions[i].m_session; } for(i = 0; icloseConfiguration(); + theConfig->closeConfiguration(false); int status = 0, error_exit = 0, signum = 0; while(waitpid(child, &status, 0) != child); diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp index 46e237d1fe6..0fca1841a15 100644 --- a/ndb/src/kernel/vm/Configuration.cpp +++ b/ndb/src/kernel/vm/Configuration.cpp @@ -172,7 +172,8 @@ Configuration::~Configuration(){ } void -Configuration::closeConfiguration(){ +Configuration::closeConfiguration(bool end_session){ + m_config_retriever->end_session(end_session); if (m_config_retriever) { delete m_config_retriever; } diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp index 5043d1f0bee..243ecbee4e7 100644 --- a/ndb/src/kernel/vm/Configuration.hpp +++ b/ndb/src/kernel/vm/Configuration.hpp @@ -35,7 +35,7 @@ public: void fetch_configuration(); void setupConfiguration(); - void closeConfiguration(); + void closeConfiguration(bool end_session= true); bool lockPagesInMainMemory() const; diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index a69a61dcda7..c1fb4c3e87f 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -2321,4 +2321,23 @@ int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length) DBUG_RETURN(0); } +extern "C" +int ndb_mgm_end_session(NdbMgmHandle handle) +{ + DBUG_ENTER("ndb_mgm_end_session"); + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + SocketOutputStream s_output(handle->socket); + s_output.println("end session"); + s_output.println(""); + + SocketInputStream in(handle->socket, handle->read_timeout); + char buf[32]; + + in.gets(buf, sizeof(buf)); + + DBUG_RETURN(0); +} + template class Vector*>; diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 0b1b2e3a087..74d7f879f9c 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -1000,26 +1000,21 @@ CommandInterpreter::executeShutdown(char* parameters) int result = 0; result = ndb_mgm_stop(m_mgmsrv, 0, 0); if (result < 0) { - ndbout << "Shutdown off NDB Cluster storage node(s) failed." << endl; + ndbout << "Shutdown of NDB Cluster node(s) failed." << endl; printError(); return result; } - ndbout << result << " NDB Cluster storage node(s) have shutdown." << endl; + ndbout << result << " NDB Cluster node(s) have shutdown." << endl; int mgm_id= 0; - for(int i=0; i < state->no_of_nodes; i++) { - if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM && - state->node_states[i].version != 0){ - if (mgm_id == 0) - mgm_id= state->node_states[i].node_id; - else { - ndbout << "Unable to locate management server, " - << "shutdown manually with STOP" - << endl; - return 1; - } - } + mgm_id= ndb_mgm_get_mgmd_nodeid(m_mgmsrv); + if (mgm_id == 0) + { + ndbout << "Unable to locate management server, " + << "shutdown manually with STOP" + << endl; + return 1; } result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id); diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 34a0adf46b9..bfa9f67b793 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -60,6 +60,9 @@ #include +extern bool g_StopServer; +extern bool g_RestartServer; + //#define MGM_SRV_DEBUG #ifdef MGM_SRV_DEBUG #define DEBUG(x) do ndbout << x << endl; while(0) @@ -373,7 +376,8 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server, _ownReference(0), theSignalIdleList(NULL), theWaitState(WAIT_SUBSCRIBE_CONF), - m_event_listner(this) + m_event_listner(this), + m_local_mgm_handle(0) { DBUG_ENTER("MgmtSrvr::MgmtSrvr"); @@ -541,6 +545,8 @@ MgmtSrvr::check_start() bool MgmtSrvr::start(BaseString &error_string) { + int mgm_connect_result; + DBUG_ENTER("MgmtSrvr::start"); if (_props == NULL) { if (!check_start()) { @@ -578,6 +584,13 @@ MgmtSrvr::start(BaseString &error_string) DBUG_RETURN(false); } + if((mgm_connect_result= connect_to_self()) < 0) + { + ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)", + mgm_connect_result); + ndbout_c("This is probably a bug."); + } + TransporterRegistry *reg = theFacade->get_registry(); for(unsigned int i=0;im_transporter_interface.size();i++) { BaseString msg; @@ -835,9 +848,81 @@ MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address) return 0; } +int MgmtSrvr::sendStopMgmd(NodeId nodeId, + bool abort, + bool stop, + bool restart, + bool nostart, + bool initialStart) +{ + const char* hostname; + Uint32 port; + BaseString connect_string; + + { + Guard g(m_configMutex); + { + ndb_mgm_configuration_iterator + iter(* _config->m_configValues, CFG_SECTION_NODE); + + if(iter.first()) return SEND_OR_RECEIVE_FAILED; + if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED; + if(iter.get(CFG_NODE_HOST, &hostname)) return SEND_OR_RECEIVE_FAILED; + } + { + ndb_mgm_configuration_iterator + iter(* _config->m_configValues, CFG_SECTION_NODE); + + if(iter.first()) return SEND_OR_RECEIVE_FAILED; + if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED; + if(iter.get(CFG_MGM_PORT, &port)) return SEND_OR_RECEIVE_FAILED; + } + if( strlen(hostname) == 0 ) + return SEND_OR_RECEIVE_FAILED; + } + connect_string.assfmt("%s:%u",hostname,port); + + DBUG_PRINT("info",("connect string: %s",connect_string.c_str())); + + NdbMgmHandle h= ndb_mgm_create_handle(); + if ( h && connect_string.length() > 0 ) + { + ndb_mgm_set_connectstring(h,connect_string.c_str()); + if(ndb_mgm_connect(h,1,0,0)) + { + DBUG_PRINT("info",("failed ndb_mgm_connect")); + return SEND_OR_RECEIVE_FAILED; + } + if(!restart) + { + if(ndb_mgm_stop(h, 1, (const int*)&nodeId) < 0) + { + return SEND_OR_RECEIVE_FAILED; + } + } + else + { + int nodes[1]; + nodes[0]= (int)nodeId; + if(ndb_mgm_restart2(h, 1, nodes, initialStart, nostart, abort) < 0) + { + return SEND_OR_RECEIVE_FAILED; + } + } + } + ndb_mgm_destroy_handle(&h); + + return 0; +} + /* * Common method for handeling all STOP_REQ signalling that * is used by Stopping, Restarting and Single user commands + * + * In the event that we need to stop a mgmd, we create a mgm + * client connection to that mgmd and stop it that way. + * This allows us to stop mgm servers when there isn't any real + * distributed communication up. */ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, @@ -849,6 +934,8 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, bool nostart, bool initialStart) { + int error = 0; + stoppedNodes.clear(); SignalSender ss(theFacade); @@ -887,18 +974,34 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, NodeBitmask nodes; if (nodeId) { + if(nodeId==getOwnNodeId()) + { + if(restart) + g_RestartServer= true; + g_StopServer= true; + return 0; + } + if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB) { int r; - if((r = okToSendTo(nodeId, true)) != 0) - return r; - } - { + if((r= okToSendTo(nodeId, true)) != 0) + return r; if (ss.sendSignal(nodeId, &ssig) != SEND_OK) return SEND_OR_RECEIVE_FAILED; } + else if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM) + { + error= sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart); + if(error==0) + stoppedNodes.set(nodeId); + return error; + } + else + return WRONG_PROCESS_TYPE; nodes.set(nodeId); } else + { while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) { if(okToSendTo(nodeId, true) == 0) @@ -908,9 +1011,17 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, nodes.set(nodeId); } } + nodeId= 0; + while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)) + { + if(nodeId==getOwnNodeId()) + continue; + if(sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart)==0) + stoppedNodes.set(nodeId); + } + } // now wait for the replies - int error = 0; while (!nodes.isclear()) { SimpleSignal *signal = ss.waitFor(); @@ -2446,9 +2557,23 @@ void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd) } } -int MgmtSrvr::set_connect_string(const char *str) +int MgmtSrvr::connect_to_self(void) { - return ndb_mgm_set_connectstring(m_config_retriever->get_mgmHandle(),str); + int r= 0; + m_local_mgm_handle= ndb_mgm_create_handle(); + snprintf(m_local_mgm_connect_string,sizeof(m_local_mgm_connect_string), + "localhost:%u",getPort()); + ndb_mgm_set_connectstring(m_local_mgm_handle, m_local_mgm_connect_string); + + if((r= ndb_mgm_connect(m_local_mgm_handle, 0, 0, 0)) < 0) + { + ndb_mgm_destroy_handle(&m_local_mgm_handle); + return r; + } + // TransporterRegistry now owns this NdbMgmHandle and will destroy it. + theFacade->get_registry()->set_mgm_handle(m_local_mgm_handle); + + return 0; } diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index 600d168ee08..46bdb112cb9 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -471,7 +471,7 @@ public: int getConnectionDbParameter(int node1, int node2, int param, int *value, BaseString& msg); - int set_connect_string(const char *str); + int connect_to_self(void); void transporter_connect(NDB_SOCKET_TYPE sockfd); @@ -487,6 +487,13 @@ private: int send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type); + int sendStopMgmd(NodeId nodeId, + bool abort, + bool stop, + bool restart, + bool nostart, + bool initialStart); + int sendSTOP_REQ(NodeId nodeId, NodeBitmask &stoppedNodes, Uint32 singleUserNodeId, @@ -629,6 +636,8 @@ private: // signal arrives. // We wait in receiveOptimisedResponse and signal in handleReceivedSignal. + NdbMgmHandle m_local_mgm_handle; + char m_local_mgm_connect_string[20]; class TransporterFacade * theFacade; int sendVersionReq( int processId, Uint32 &version, const char **address); diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index ee24cf18941..80f0aa2eda8 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -203,6 +203,8 @@ ParserRow commands[] = { MGM_CMD("bye", &MgmApiSession::bye, ""), + MGM_CMD("end session", &MgmApiSession::endSession, ""), + MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""), MGM_ARG("node", Int, Mandatory, "Node"), MGM_ARG("category", Int, Mandatory, "Event category"), @@ -719,10 +721,21 @@ MgmApiSession::dumpState(Parser::Context &, void MgmApiSession::bye(Parser::Context &, - Properties const &) { + Properties const &) { m_stop = true; } +void +MgmApiSession::endSession(Parser::Context &, + Properties const &) { + if(m_allocated_resources) + delete m_allocated_resources; + + m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); + + m_output->println("end session reply"); +} + void MgmApiSession::setClusterLogLevel(Parser::Context &, Properties const &args) { diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp index 30f220cd060..f97223750a1 100644 --- a/ndb/src/mgmsrv/Services.hpp +++ b/ndb/src/mgmsrv/Services.hpp @@ -79,6 +79,7 @@ public: void start(Parser_t::Context &ctx, const class Properties &args); void startAll(Parser_t::Context &ctx, const class Properties &args); void bye(Parser_t::Context &ctx, const class Properties &args); + void endSession(Parser_t::Context &ctx, const class Properties &args); void setLogLevel(Parser_t::Context &ctx, const class Properties &args); void setClusterLogLevel(Parser_t::Context &ctx, const class Properties &args); diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index f0c2ac298a5..e8a2a366dc9 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -132,6 +132,7 @@ static MgmGlobals *glob= 0; * Global variables */ bool g_StopServer; +bool g_RestartServer; extern EventLogger g_eventLogger; extern int global_mgmt_server_check; @@ -191,7 +192,19 @@ static void usage() */ int main(int argc, char** argv) { + int mgm_connect_result; + NDB_INIT(argv[0]); + + int ho_error; +#ifndef DBUG_OFF + opt_debug= "d:t:O,/tmp/ndb_mgmd.trace"; +#endif + if ((ho_error=handle_options(&argc, &argv, my_long_options, + ndb_std_get_one_option))) + exit(ho_error); + +start: glob= new MgmGlobals; /** @@ -208,14 +221,6 @@ int main(int argc, char** argv) const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; load_defaults("my",load_default_groups,&argc,&argv); - int ho_error; -#ifndef DBUG_OFF - opt_debug= "d:t:O,/tmp/ndb_mgmd.trace"; -#endif - if ((ho_error=handle_options(&argc, &argv, my_long_options, - ndb_std_get_one_option))) - exit(ho_error); - if (opt_interactive || opt_non_interactive || g_print_full_config) { @@ -293,34 +298,12 @@ int main(int argc, char** argv) goto error_end; } - /* Construct a fake connectstring to connect back to ourselves */ - char connect_str[20]; - if(!opt_connect_str) { - snprintf(connect_str,20,"localhost:%u",glob->mgmObject->getPort()); - opt_connect_str= connect_str; - } - glob->mgmObject->set_connect_string(opt_connect_str); - if(!glob->mgmObject->check_start()){ ndbout_c("Unable to check start management server."); ndbout_c("Probably caused by illegal initial configuration file."); goto error_end; } - /* - * Connect back to ourselves so we can use mgmapi to fetch - * config info - */ - int mgm_connect_result; - mgm_connect_result = glob->mgmObject->get_config_retriever()-> - do_connect(0,0,0); - - if(mgm_connect_result<0) { - ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)", - mgm_connect_result); - ndbout_c("This is probably a bug."); - } - if (opt_daemon) { // Become a daemon char *lockfile= NdbConfig_PidFileName(glob->localNodeId); @@ -361,6 +344,7 @@ int main(int argc, char** argv) g_eventLogger.info(msg); g_StopServer = false; + g_RestartServer= false; glob->socketServer->startServer(); #if ! defined NDB_OSE && ! defined NDB_SOFTOSE @@ -378,14 +362,19 @@ int main(int argc, char** argv) while(g_StopServer != true) NdbSleep_MilliSleep(500); } - - g_eventLogger.info("Shutting down server..."); + + if(g_RestartServer) + g_eventLogger.info("Restarting server..."); + else + g_eventLogger.info("Shutting down server..."); glob->socketServer->stopServer(); - glob->mgmObject->get_config_retriever()->disconnect(); + // We disconnect from the ConfigRetreiver mgmd when we delete glob below glob->socketServer->stopSessions(true); g_eventLogger.info("Shutdown complete"); the_end: delete glob; + if(g_RestartServer) + goto start; ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); return 0; error_end: From 07eca7f96272f9440528e6640e4e2a89233e5beb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 12:55:30 +0100 Subject: [PATCH 11/37] Increase the version number to 4.1.18 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 9afd2034796..b3daaa5731d 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,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, 4.1.17) +AM_INIT_AUTOMAKE(mysql, 4.1.18) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -16,7 +16,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=4 NDB_VERSION_MINOR=1 -NDB_VERSION_BUILD=17 +NDB_VERSION_BUILD=18 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 91b4e6b54424d858b5521cf3299726aef94d6632 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 18:51:08 +0400 Subject: [PATCH 12/37] BUG#3074: Unversioned symbols in shared library libmysqlclient versioning when linked with GNU ld. BitKeeper/etc/ignore: Added libmysql/libmysql.ver to the ignore list configure.in: libmysqlclient versioning when linked with GNU ld. libmysql/Makefile.shared: libmysqlclient versioning when linked with GNU ld. libmysql/libmysql.ver.in: New BitKeeper file ``libmysql/libmysql.ver.in'' --- .bzrignore | 1 + configure.in | 11 ++++++++++- libmysql/Makefile.shared | 2 +- libmysql/libmysql.ver.in | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 libmysql/libmysql.ver.in diff --git a/.bzrignore b/.bzrignore index d8be10eacdb..414a40ef1eb 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1057,3 +1057,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +libmysql/libmysql.ver diff --git a/configure.in b/configure.in index 9afd2034796..6ac6f77b318 100644 --- a/configure.in +++ b/configure.in @@ -11,7 +11,8 @@ AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 DOT_FRM_VERSION=6 # See the libtool docs for information on how to do shared lib versions. -SHARED_LIB_VERSION=14:0:0 +SHARED_LIB_MAJOR_VERSION=14 +SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=4 @@ -68,6 +69,7 @@ AC_DEFINE_UNQUOTED([PROTOCOL_VERSION], [$PROTOCOL_VERSION], AC_SUBST(DOT_FRM_VERSION) AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION], [Version of .frm files]) +AC_SUBST(SHARED_LIB_MAJOR_VERSION) AC_SUBST(SHARED_LIB_VERSION) AC_SUBST(AVAILABLE_LANGUAGES) AC_SUBST(AVAILABLE_LANGUAGES_ERRORS) @@ -431,6 +433,13 @@ then fi fi +# libmysqlclient versioning when linked with GNU ld. +if $LD --version 2>/dev/null|grep -q GNU; then + LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmysql/libmysql.ver" + AC_CONFIG_FILES(libmysql/libmysql.ver) +fi +AC_SUBST(LD_VERSION_SCRIPT) + # Avoid bug in fcntl on some versions of linux AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os") # Any wariation of Linux diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index bb4d252f385..3f72049bf43 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -75,7 +75,7 @@ mysysobjects2 = my_lib.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ $(sql_cmn_objects) $(vio_objects) $(sqlobjects) -target_ldflags = -version-info @SHARED_LIB_VERSION@ +target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@ vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo CLEANFILES = $(target_libadd) $(SHLIBOBJS) \ $(target) diff --git a/libmysql/libmysql.ver.in b/libmysql/libmysql.ver.in new file mode 100644 index 00000000000..20eb0fd41bb --- /dev/null +++ b/libmysql/libmysql.ver.in @@ -0,0 +1 @@ +libmysqlclient_@SHARED_LIB_MAJOR_VERSION@ { global: *; }; From 22bc685dbf3769e4df9aedf139635c8b85bdeb37 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 23:19:43 +0300 Subject: [PATCH 13/37] A fix and a test case for Bug#16144 "mysql_stmt_attr_get type error": use the right type in mysql_stmt_attr_get libmysql/libmysql.c: Fix Bug#16144 "mysql_stmt_attr_get type error" tests/mysql_client_test.c: A test case for Bug#16144 --- libmysql/libmysql.c | 2 +- tests/mysql_client_test.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 7c6d140d2ef..921f042922a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2733,7 +2733,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, { switch (attr_type) { case STMT_ATTR_UPDATE_MAX_LENGTH: - *(unsigned long *) value= stmt->update_max_length; + *(my_bool*) value= stmt->update_max_length; break; default: return TRUE; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index f0566995262..797a0b1b8d7 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11753,6 +11753,25 @@ static void test_bug12925() } +/* Bug #16144: mysql_stmt_attr_get type error */ + +static void test_bug16144() +{ + const my_bool flag_orig= (my_bool) 0xde; + my_bool flag= flag_orig; + MYSQL_STMT *stmt; + myheader("test_bug16144"); + + /* Check that attr_get returns correct data on little and big endian CPUs */ + stmt= mysql_stmt_init(mysql); + mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*) &flag); + mysql_stmt_attr_get(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &flag); + DIE_UNLESS(flag == flag_orig); + + mysql_stmt_close(stmt); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -11974,6 +11993,7 @@ static struct my_tests_st my_tests[]= { { "test_bug12001", test_bug12001 }, { "test_bug11718", test_bug11718 }, { "test_bug12925", test_bug12925 }, + { "test_bug16144", test_bug16144 }, { 0, 0 } }; From 74f499faded76c73f68167cae30e8e0a927d96c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jan 2006 15:02:03 +0300 Subject: [PATCH 14/37] Applied patch recieved from Marko: Make innodb_flush_log_at_trx_commit a settable global variable. innobase/include/srv0srv.h: Change the type of srv_flush_log_at_trx_commit. innobase/srv/srv0srv.c: Change the type of srv_flush_log_at_trx_commit. sql/ha_innodb.cc: Remove innobase_flush_log_at_trx_commit. (Set srv_flush_log_at_trx_commit directly). sql/ha_innodb.h: Remove innobase_flush_log_at_trx_commit. (Set srv_flush_log_at_trx_commit directly). sql/mysqld.cc: Bypass the variable innobase innobase_flush_log_at_trx_commit. sql/set_var.cc: Make innodb_flush_log_at_trx_commit a settable global variable. --- innobase/include/srv0srv.h | 2 +- innobase/srv/srv0srv.c | 2 +- sql/ha_innodb.cc | 4 +--- sql/ha_innodb.h | 2 +- sql/mysqld.cc | 4 ++-- sql/set_var.cc | 6 +++++- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 99ea4f2de27..23c9ef1e221 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -77,7 +77,7 @@ extern ulint srv_n_log_groups; extern ulint srv_n_log_files; extern ulint srv_log_file_size; extern ulint srv_log_buffer_size; -extern ulint srv_flush_log_at_trx_commit; +extern ulong srv_flush_log_at_trx_commit; extern byte srv_latin1_ordering[256];/* The sort order table of the latin1 character set */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 6e0b9b23266..694345c4142 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -113,7 +113,7 @@ ulint srv_n_log_groups = ULINT_MAX; ulint srv_n_log_files = ULINT_MAX; ulint srv_log_file_size = ULINT_MAX; /* size in database pages */ ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */ -ulint srv_flush_log_at_trx_commit = 1; +ulong srv_flush_log_at_trx_commit = 1; byte srv_latin1_ordering[256] /* The sort order table of the latin1 character set. The following table is diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index c0f8559ab29..e66e79fde29 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -167,7 +167,6 @@ char* innobase_unix_file_flush_method = NULL; /* Below we have boolean-valued start-up parameters, and their default values */ -uint innobase_flush_log_at_trx_commit = 1; ulong innobase_fast_shutdown = 1; my_bool innobase_log_archive = FALSE;/* unused */ my_bool innobase_use_doublewrite = TRUE; @@ -1341,7 +1340,6 @@ innobase_init(void) srv_log_archive_on = (ulint) innobase_log_archive; #endif /* UNIV_LOG_ARCHIVE */ srv_log_buffer_size = (ulint) innobase_log_buffer_size; - srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit; /* We set srv_pool_size here in units of 1 kB. InnoDB internally changes the value so that it becomes the number of database pages. */ @@ -1816,7 +1814,7 @@ innobase_commit_complete( trx->active_trans = 0; - if (srv_flush_log_at_trx_commit == 0) { + if (UNIV_UNLIKELY(srv_flush_log_at_trx_commit == 0)) { return(0); } diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 58051624f89..aa8506abe6d 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -200,7 +200,6 @@ class ha_innobase: public handler extern struct show_var_st innodb_status_variables[]; extern uint innobase_init_flags, innobase_lock_type; -extern uint innobase_flush_log_at_trx_commit; extern ulong innobase_cache_size, innobase_fast_shutdown; extern ulong innobase_large_page_size; extern char *innobase_home, *innobase_tmpdir, *innobase_logdir; @@ -238,6 +237,7 @@ extern ulong srv_n_free_tickets_to_enter; extern ulong srv_thread_sleep_delay; extern ulong srv_thread_concurrency; extern ulong srv_commit_concurrency; +extern ulong srv_flush_log_at_trx_commit; } extern TYPELIB innobase_lock_typelib; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 80b22f726ae..08a47ca70f5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4823,8 +4823,8 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, (gptr*) &innobase_file_per_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).", - (gptr*) &innobase_flush_log_at_trx_commit, - (gptr*) &innobase_flush_log_at_trx_commit, + (gptr*) &srv_flush_log_at_trx_commit, + (gptr*) &srv_flush_log_at_trx_commit, 0, GET_UINT, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD, "With which method to flush data.", (gptr*) &innobase_unix_file_flush_method, diff --git a/sql/set_var.cc b/sql/set_var.cc index f10da4ad9ba..d945e0842e4 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -422,6 +422,9 @@ sys_var_long_ptr sys_innodb_thread_concurrency("innodb_thread_concurrency", &srv_thread_concurrency); sys_var_long_ptr sys_innodb_commit_concurrency("innodb_commit_concurrency", &srv_commit_concurrency); +sys_var_long_ptr sys_innodb_flush_log_at_trx_commit( + "innodb_flush_log_at_trx_commit", + &srv_flush_log_at_trx_commit); #endif /* Condition pushdown to storage engine */ @@ -726,6 +729,7 @@ sys_var *sys_variables[]= &sys_innodb_thread_sleep_delay, &sys_innodb_thread_concurrency, &sys_innodb_commit_concurrency, + &sys_innodb_flush_log_at_trx_commit, #endif &sys_trust_routine_creators, &sys_trust_function_creators, @@ -831,7 +835,6 @@ struct show_var_st init_vars[]= { {sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS}, {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG }, {"innodb_file_per_table", (char*) &innobase_file_per_table, SHOW_MY_BOOL}, - {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT}, {"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR}, {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG }, @@ -851,6 +854,7 @@ struct show_var_st init_vars[]= { {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS}, {sys_innodb_thread_concurrency.name, (char*) &sys_innodb_thread_concurrency, SHOW_SYS}, {sys_innodb_thread_sleep_delay.name, (char*) &sys_innodb_thread_sleep_delay, SHOW_SYS}, + {sys_innodb_flush_log_at_trx_commit.name, (char*) &sys_innodb_flush_log_at_trx_commit, SHOW_SYS}, #endif {sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS}, {sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS}, From e3f0690d9bff930075ff644c8abeadddbc59bade Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jan 2006 15:20:56 +0300 Subject: [PATCH 15/37] Applied patch recieved from Marko: Make innodb_thread_concurrency 0 by default, and extend the usable range from 0 to 1000 (0 disables the thread throttling). innobase/include/srv0srv.h: Remove SRV_CONCURRENCY_THRESHOLD. The magic value is 0 from now on. innobase/srv/srv0srv.c: Remove SRV_CONCURRENCY_THRESHOLD. The magic value is 0 from now on. mysql-test/r/innodb.result: innodb_thread_concurrency is 0..1000 now, and the default is 0. mysql-test/t/innodb.test: innodb_thread_concurrency is 0..1000 now. sql/ha_innodb.cc: Remove SRV_CONCURRENCY_THRESHOLD. The magic value is 0 from now on. sql/mysqld.cc: innodb_thread_concurrency is 0..1000 now, and 0 (the default) disables the thread throttling. --- innobase/include/srv0srv.h | 1 - innobase/srv/srv0srv.c | 9 +++++---- mysql-test/r/innodb.result | 6 +++--- mysql-test/t/innodb.test | 2 +- sql/ha_innodb.cc | 4 ++-- sql/mysqld.cc | 6 ++++-- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 23c9ef1e221..f379efa98eb 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -195,7 +195,6 @@ extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs, #define kernel_mutex (*kernel_mutex_temp) #define SRV_MAX_N_IO_THREADS 100 -#define SRV_CONCURRENCY_THRESHOLD 20 /* Array of English strings describing the current state of an i/o handler thread */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 694345c4142..fe9e08d65be 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -258,9 +258,10 @@ threads waiting for locks are not counted into the number because otherwise we could get a deadlock. MySQL creates a thread for each user session, and semaphore contention and convoy problems can occur withput this restriction. Value 10 should be good if there are less than 4 processors + 4 disks in the -computer. Bigger computers need bigger values. */ +computer. Bigger computers need bigger values. Value 0 will disable the +concurrency check. */ -ulong srv_thread_concurrency = SRV_CONCURRENCY_THRESHOLD; +ulong srv_thread_concurrency = 0; ulong srv_commit_concurrency = 0; os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data @@ -1141,7 +1142,7 @@ srv_conc_force_enter_innodb( trx_t* trx) /* in: transaction object associated with the thread */ { - if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) { + if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } @@ -1167,7 +1168,7 @@ srv_conc_force_exit_innodb( { srv_conc_slot_t* slot = NULL; - if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) { + if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 973ad72042e..0816d0de43c 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1821,15 +1821,15 @@ Variable_name Value innodb_sync_spin_loops 20 show variables like "innodb_thread_concurrency"; Variable_name Value -innodb_thread_concurrency 20 -set global innodb_thread_concurrency=1000; +innodb_thread_concurrency 0 +set global innodb_thread_concurrency=1001; show variables like "innodb_thread_concurrency"; Variable_name Value innodb_thread_concurrency 1000 set global innodb_thread_concurrency=0; show variables like "innodb_thread_concurrency"; Variable_name Value -innodb_thread_concurrency 1 +innodb_thread_concurrency 0 set global innodb_thread_concurrency=16; show variables like "innodb_thread_concurrency"; Variable_name Value diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 7ae2b6d4ac2..8d2f18e2362 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1316,7 +1316,7 @@ show variables like "innodb_sync_spin_loops"; # Test for innodb_thread_concurrency variable show variables like "innodb_thread_concurrency"; -set global innodb_thread_concurrency=1000; +set global innodb_thread_concurrency=1001; show variables like "innodb_thread_concurrency"; set global innodb_thread_concurrency=0; show variables like "innodb_thread_concurrency"; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e66e79fde29..b33d2dfbd97 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -338,7 +338,7 @@ innodb_srv_conc_enter_innodb( /*=========================*/ trx_t* trx) /* in: transaction handle */ { - if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) { + if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } @@ -355,7 +355,7 @@ innodb_srv_conc_exit_innodb( /*========================*/ trx_t* trx) /* in: transaction handle */ { - if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) { + if (UNIV_LIKELY(!srv_thread_concurrency)) { return; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 08a47ca70f5..f738bb7cee1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5504,9 +5504,11 @@ log and this option does nothing anymore.", (gptr*) &srv_n_spin_wait_rounds, 0, GET_LONG, REQUIRED_ARG, 20L, 0L, ~0L, 0, 1L, 0}, {"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY, - "Helps in performance tuning in heavily concurrent environments.", + "Helps in performance tuning in heavily concurrent environments. " + "Sets the maximum number of threads allowed inside InnoDB. Value 0" + " will disable the thread throttling.", (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency, - 0, GET_LONG, REQUIRED_ARG, 20, 1, 1000, 0, 1, 0}, + 0, GET_LONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0}, {"innodb_commit_concurrency", OPT_INNODB_THREAD_CONCURRENCY, "Helps in performance tuning in heavily concurrent environments.", (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency, From 1e8e302effdb998223c65ebfe8dbea2d01a8385c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jan 2006 22:50:31 +0300 Subject: [PATCH 16/37] A fix and a test case for Bug#15613 "libmysqlclient API function mysql_stmt_prepare returns wrong field length" sql/protocol.cc: A fix for Bug#15613: make sure that result set column length is evaluated correctly for BLOB/TEXT columns. tests/mysql_client_test.c: A test case for Bug#15613 --- sql/protocol.cc | 18 +++++++++-- tests/mysql_client_test.c | 65 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index 6a17ae2f95b..a2287740f1e 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -565,9 +565,23 @@ bool Protocol::send_fields(List *list, uint flag) else { /* With conversion */ + uint max_char_len; int2store(pos, thd_charset->number); - uint char_len= field.length / item->collation.collation->mbmaxlen; - int4store(pos+2, char_len * thd_charset->mbmaxlen); + /* + For TEXT/BLOB columns, field_length describes the maximum data + length in bytes. There is no limit to the number of characters + that a TEXT column can store, as long as the data fits into + the designated space. + For the rest of textual columns, field_length is evaluated as + char_count * mbmaxlen, where character count is taken from the + definition of the column. In other words, the maximum number + of characters here is limited by the column definition. + */ + max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB && + field.type <= (int) MYSQL_TYPE_BLOB) ? + field.length / item->collation.collation->mbminlen : + field.length / item->collation.collation->mbmaxlen; + int4store(pos+2, max_char_len * thd_charset->mbmaxlen); } pos[6]= field.type; int2store(pos+7,field.flags); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 797a0b1b8d7..91c2ab9205d 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11772,6 +11772,70 @@ static void test_bug16144() } +/* + Bug #15613: "libmysqlclient API function mysql_stmt_prepare returns wrong + field length" +*/ + +static void test_bug15613() +{ + MYSQL_STMT *stmt; + const char *stmt_text; + MYSQL_RES *metadata; + MYSQL_FIELD *field; + int rc; + myheader("test_bug15613"); + + /* I. Prepare the table */ + rc= mysql_query(mysql, "set names latin1"); + myquery(rc); + mysql_query(mysql, "drop table if exists t1"); + rc= mysql_query(mysql, + "create table t1 (t text character set utf8, " + "tt tinytext character set utf8, " + "mt mediumtext character set utf8, " + "lt longtext character set utf8, " + "vl varchar(255) character set latin1," + "vb varchar(255) character set binary," + "vu varchar(255) character set utf8)"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + + /* II. Check SELECT metadata */ + stmt_text= ("select t, tt, mt, lt, vl, vb, vu from t1"); + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_fields(metadata); + if (!opt_silent) + { + printf("Field lengths (client character set is latin1):\n" + "text character set utf8:\t\t%lu\n" + "tinytext character set utf8:\t\t%lu\n" + "mediumtext character set utf8:\t\t%lu\n" + "longtext character set utf8:\t\t%lu\n" + "varchar(255) character set latin1:\t%lu\n" + "varchar(255) character set binary:\t%lu\n" + "varchar(255) character set utf8:\t%lu\n", + field[0].length, field[1].length, field[2].length, field[3].length, + field[4].length, field[5].length, field[6].length); + } + DIE_UNLESS(field[0].length == 65535); + DIE_UNLESS(field[1].length == 255); + DIE_UNLESS(field[2].length == 16777215); + DIE_UNLESS(field[3].length == 4294967295UL); + DIE_UNLESS(field[4].length == 255); + DIE_UNLESS(field[5].length == 255); + DIE_UNLESS(field[6].length == 255); + + /* III. Cleanup */ + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); + rc= mysql_query(mysql, "set names default"); + myquery(rc); + mysql_stmt_close(stmt); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -11994,6 +12058,7 @@ static struct my_tests_st my_tests[]= { { "test_bug11718", test_bug11718 }, { "test_bug12925", test_bug12925 }, { "test_bug16144", test_bug16144 }, + { "test_bug15613", test_bug15613 }, { 0, 0 } }; From a6c68c25c965599c92adec3a770e1d68bbbdaff5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jan 2006 10:44:44 +0100 Subject: [PATCH 17/37] Update the spec file for the shared compat RPM with version info. support-files/MySQL-shared-compat.spec.sh: Prevent "libndbclient" (which is not included in the "shared compat" RPM) from breaking the RPM packaging. Also, adapt the specification to the newer versions of the older release families. This needs to be repeated periodically. Take care of the RPM build version: For 4.1.16, it is 4.1.16-1 ! --- support-files/MySQL-shared-compat.spec.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/support-files/MySQL-shared-compat.spec.sh b/support-files/MySQL-shared-compat.spec.sh index ffc96fd6fff..72ebf4d4d2b 100644 --- a/support-files/MySQL-shared-compat.spec.sh +++ b/support-files/MySQL-shared-compat.spec.sh @@ -23,16 +23,19 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # Temple Place, Suite 330, Boston, MA 02111-1307 USA +# For 5.0 and up, this is needed because of "libndbclient". +%define _unpackaged_files_terminate_build 0 + # # Change this to match the version of the shared libs you want to include # %define version50 @MYSQL_NO_DASH_VERSION@ -%define version41 4.1.9 -%define version40 4.0.23 +%define version41 4.1.16 +%define version40 4.0.26 %define version3 3.23.58 Name: MySQL-shared-compat -Packager: Lenz Grimmer +Packager: MySQL Product Engineering team Vendor: MySQL AB License: GPL Group: Applications/Databases @@ -47,7 +50,7 @@ Summary: MySQL shared client libraries for MySQL %{version}, %{version41}, # We simply use the "MySQL-shared" subpackages as input sources instead of # rebuilding all from source Source0: MySQL-shared-%{version50}-0.%{_arch}.rpm -Source1: MySQL-shared-%{version41}-0.%{_arch}.rpm +Source1: MySQL-shared-%{version41}-1.%{_arch}.rpm Source2: MySQL-shared-%{version40}-0.%{_arch}.rpm Source3: MySQL-shared-%{version3}-1.%{_arch}.rpm # No need to include the RPMs once more - they can be downloaded seperately From 71f54b97cbb6dc31c31046ef07831af15cc2ed2e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jan 2006 22:50:54 +1100 Subject: [PATCH 18/37] small typo fixes mysql-test/ndb/ndbcluster.sh: small fix to make ndb_mgmd run ndb/tools/ndb_size.pl: small typo --- mysql-test/ndb/ndbcluster.sh | 2 +- ndb/tools/ndb_size.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index 16bb3a9b122..d3471b6cfde 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -135,7 +135,7 @@ if [ ! -x "$exec_waiter" ]; then fi exec_mgmtclient="$exec_mgmtclient --no-defaults $NDB_MGM_EXTRA_OPTS" -exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults $NDB_MGMD_EXTRA_OPTS" +exec_mgmtsrvr="$exec_mgmtsrvr $NDB_MGMD_EXTRA_OPTS" exec_ndb="$exec_ndb --no-defaults $NDBD_EXTRA_OPTS" exec_waiter="$exec_waiter --no-defaults" diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl index e0085c619f0..c285a7590fd 100644 --- a/ndb/tools/ndb_size.pl +++ b/ndb/tools/ndb_size.pl @@ -147,7 +147,7 @@ foreach(@{$tables}) { my $fixed= 1+$size; my @dynamic=$dbh->selectrow_array("select avg(length(`" - .$name. + .$name ."`)) from `".$table.'`'); $dynamic[0]=0 if !$dynamic[0]; @realsize= ($fixed,$fixed,ceil($dynamic[0])); From 2e60e21d349fe309fdfbd30a7c07d608e2171141 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jan 2006 00:06:17 +1100 Subject: [PATCH 19/37] fix ndb_mgmd --no-defaults option processing ndb/src/mgmsrv/main.cpp: fix --no-defaults option processing --- ndb/src/mgmsrv/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index e8a2a366dc9..5960a3517b5 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -196,6 +196,9 @@ int main(int argc, char** argv) NDB_INIT(argv[0]); + const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; #ifndef DBUG_OFF opt_debug= "d:t:O,/tmp/ndb_mgmd.trace"; @@ -217,9 +220,6 @@ start: #endif global_mgmt_server_check = 1; - - const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; - load_defaults("my",load_default_groups,&argc,&argv); if (opt_interactive || opt_non_interactive || From f7eefc02008739f0776a439e87b293a723babaaa Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jan 2006 00:08:26 +1100 Subject: [PATCH 20/37] reintroduce --no-defaults to ndb_mgmd mysql-test/ndb/ndbcluster.sh: have made a real fix for mgmd not starting with --no-defaults. re-introduce it to the test suite --- mysql-test/ndb/ndbcluster.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index d3471b6cfde..16bb3a9b122 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -135,7 +135,7 @@ if [ ! -x "$exec_waiter" ]; then fi exec_mgmtclient="$exec_mgmtclient --no-defaults $NDB_MGM_EXTRA_OPTS" -exec_mgmtsrvr="$exec_mgmtsrvr $NDB_MGMD_EXTRA_OPTS" +exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults $NDB_MGMD_EXTRA_OPTS" exec_ndb="$exec_ndb --no-defaults $NDBD_EXTRA_OPTS" exec_waiter="$exec_waiter --no-defaults" From de9318556774688e36ff2b9800ead04ed7b71093 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jan 2006 15:36:41 +0100 Subject: [PATCH 21/37] Fix option type error, crashes on 64-bit big endian. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f738bb7cee1..7f835c0e8e0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4825,7 +4825,7 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).", (gptr*) &srv_flush_log_at_trx_commit, (gptr*) &srv_flush_log_at_trx_commit, - 0, GET_UINT, OPT_ARG, 1, 0, 2, 0, 0, 0}, + 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD, "With which method to flush data.", (gptr*) &innobase_unix_file_flush_method, (gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, From b60fc2cee8dfce23bc8a7113649e6c5534ad1392 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jan 2006 16:13:04 +0100 Subject: [PATCH 22/37] Post-review fixes (BUG#15658). sql/sp_head.cc: Post-review fix. sql/sp_head.h: Post-review fix. sql/sql_yacc.yy: Post-review fix. --- sql/sp_head.cc | 22 +++++++++++----------- sql/sp_head.h | 2 +- sql/sql_yacc.yy | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9c86ebfddf4..f42fbef82e3 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -387,19 +387,19 @@ sp_name_current_db_new(THD *thd, LEX_STRING name) } /* - * Check that the name 'ident' is ok. It's assumed to be an 'ident' - * from the parser, so we only have to check length and trailing spaces. - * The former is a standard requirement (and 'show status' assumes a - * non-empty name), the latter is a mysql:ism as trailing spaces are - * removed by get_field(). - * - * RETURN - * TRUE - bad name - * FALSE - name is ok - */ + Check that the name 'ident' is ok. It's assumed to be an 'ident' + from the parser, so we only have to check length and trailing spaces. + The former is a standard requirement (and 'show status' assumes a + non-empty name), the latter is a mysql:ism as trailing spaces are + removed by get_field(). + + RETURN + TRUE - bad name + FALSE - name is ok +*/ bool -sp_name_check(LEX_STRING ident) +check_routine_name(LEX_STRING ident) { return (!ident.str || !ident.str[0] || ident.str[ident.length-1] == ' '); } diff --git a/sql/sp_head.h b/sql/sp_head.h index d912cfeaac3..858bf523a07 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -104,7 +104,7 @@ sp_name * sp_name_current_db_new(THD *thd, LEX_STRING name); bool -sp_name_check(LEX_STRING name); +check_routine_name(LEX_STRING name); class sp_head :private Query_arena { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2face8238b8..41552100264 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1293,7 +1293,7 @@ sp_name: my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); YYABORT; } - if (sp_name_check($3)) + if (check_routine_name($3)) { my_error(ER_SP_WRONG_NAME, MYF(0), $3.str); YYABORT; @@ -1303,7 +1303,7 @@ sp_name: } | ident { - if (sp_name_check($1)) + if (check_routine_name($1)) { my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); YYABORT; From 7fc2604cd78dee435805cb79b9a51dd88a1e3c61 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jan 2006 17:55:54 +0100 Subject: [PATCH 23/37] Fixed BUG#15866: Thread stack limit insufficient for recursive call "fib(20)" Lowered the parameter to 10, and also renamed non-standard table names to t3. mysql-test/r/sp.result: Updated results. mysql-test/r/sp_trans.result: Updated results. mysql-test/t/sp.test: Renamed fac, primes and fib tables to t3. Lowered fib() test parameter to 10 (20 hit the stack overrun check on some machines). mysql-test/t/sp_trans.test: Added drop of t3 for safety. (Might be left from sp.test after certain test failures.) --- mysql-test/r/sp.result | 46 +++++++++++++++++------------------ mysql-test/r/sp_trans.result | 2 +- mysql-test/t/sp.test | 47 ++++++++++++++++++------------------ mysql-test/t/sp_trans.test | 2 +- 4 files changed, 49 insertions(+), 48 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 19f3d033f53..63ab2098d5f 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1178,8 +1178,8 @@ drop view v2| delete from t1 | delete from t2 | drop table t4| -drop table if exists fac| -create table fac (n int unsigned not null primary key, f bigint unsigned)| +drop table if exists t3| +create table t3 (n int unsigned not null primary key, f bigint unsigned)| drop procedure if exists ifac| create procedure ifac(n int unsigned) begin @@ -1189,13 +1189,13 @@ set n = 20; # bigint overflow otherwise end if; while i <= n do begin -insert into test.fac values (i, fac(i)); +insert into test.t3 values (i, fac(i)); set i = i + 1; end; end while; end| call ifac(20)| -select * from fac| +select * from t3| n f 1 1 2 2 @@ -1217,7 +1217,7 @@ n f 18 6402373705728000 19 121645100408832000 20 2432902008176640000 -drop table fac| +drop table t3| show function status like '%f%'| Db Name Type Definer Modified Created Security_type Comment test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER @@ -1225,12 +1225,12 @@ drop procedure ifac| drop function fac| show function status like '%f%'| Db Name Type Definer Modified Created Security_type Comment -drop table if exists primes| -create table primes ( +drop table if exists t3| +create table t3 ( i int unsigned not null primary key, p bigint unsigned not null )| -insert into primes values +insert into t3 values ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13), ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31), (10, 37), (11, 41), (12, 43), (13, 47), (14, 53), @@ -1253,7 +1253,7 @@ set b = b+200, s = 0; else begin declare p bigint unsigned; -select t.p into p from test.primes t where t.i = s; +select t.p into p from test.t3 t where t.i = s; if b+p > r then set pp = 1; leave again; @@ -1278,7 +1278,7 @@ begin declare pp bool default 0; call opp(p, pp); if pp then -insert into test.primes values (i, p); +insert into test.t3 values (i, p); set i = i+1; end if; set p = p+2; @@ -1299,7 +1299,7 @@ set b = b+200, s = 0; else begin declare p bigint unsigned; -select t.p into p from test.primes t where t.i = s; +select t.p into p from test.t3 t where t.i = s; if b+p > r then set pp = 1; leave again; @@ -1318,47 +1318,47 @@ Db Name Type Definer Modified Created Security_type Comment test ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER test opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER call ip(200)| -select * from primes where i=45 or i=100 or i=199| +select * from t3 where i=45 or i=100 or i=199| i p 45 211 100 557 199 1229 -drop table primes| +drop table t3| drop procedure opp| drop procedure ip| show procedure status like '%p%'| Db Name Type Definer Modified Created Security_type Comment -drop table if exists fib| -create table fib ( f bigint unsigned not null )| +drop table if exists t3| +create table t3 ( f bigint unsigned not null )| drop procedure if exists fib| create procedure fib(n int unsigned) begin if n > 1 then begin declare x, y bigint unsigned; -declare c cursor for select f from fib order by f desc limit 2; +declare c cursor for select f from t3 order by f desc limit 2; open c; fetch c into y; fetch c into x; close c; -insert into fib values (x+y); +insert into t3 values (x+y); call fib(n-1); end; end if; end| set @@max_sp_recursion_depth= 20| -insert into fib values (0), (1)| +insert into t3 values (0), (1)| call fib(3)| -select * from fib order by f asc| +select * from t3 order by f asc| f 0 1 1 2 -delete from fib| -insert into fib values (0), (1)| +delete from t3| +insert into t3 values (0), (1)| call fib(20)| -select * from fib order by f asc| +select * from t3 order by f asc| f 0 1 @@ -1381,7 +1381,7 @@ f 2584 4181 6765 -drop table fib| +drop table t3| drop procedure fib| set @@max_sp_recursion_depth= 0| drop procedure if exists bar| diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result index 8f2bd9985fc..e9289cf01c7 100644 --- a/mysql-test/r/sp_trans.result +++ b/mysql-test/r/sp_trans.result @@ -1,4 +1,4 @@ -drop table if exists t1, t2; +drop table if exists t1, t2, t3; drop procedure if exists bug8850| create table t1 (a int) engine=innodb| create procedure bug8850() diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 68ce9cdb118..f9b218967dd 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1419,9 +1419,9 @@ drop table t4| # fac --disable_warnings -drop table if exists fac| +drop table if exists t3| --enable_warnings -create table fac (n int unsigned not null primary key, f bigint unsigned)| +create table t3 (n int unsigned not null primary key, f bigint unsigned)| --disable_warnings drop procedure if exists ifac| @@ -1435,15 +1435,15 @@ begin end if; while i <= n do begin - insert into test.fac values (i, fac(i)); + insert into test.t3 values (i, fac(i)); set i = i + 1; end; end while; end| call ifac(20)| -select * from fac| -drop table fac| +select * from t3| +drop table t3| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' show function status like '%f%'| drop procedure ifac| @@ -1455,15 +1455,15 @@ show function status like '%f%'| # primes --disable_warnings -drop table if exists primes| +drop table if exists t3| --enable_warnings -create table primes ( +create table t3 ( i int unsigned not null primary key, p bigint unsigned not null )| -insert into primes values +insert into t3 values ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13), ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31), (10, 37), (11, 41), (12, 43), (13, 47), (14, 53), @@ -1492,7 +1492,7 @@ begin begin declare p bigint unsigned; - select t.p into p from test.primes t where t.i = s; + select t.p into p from test.t3 t where t.i = s; if b+p > r then set pp = 1; leave again; @@ -1523,7 +1523,7 @@ begin call opp(p, pp); if pp then - insert into test.primes values (i, p); + insert into test.t3 values (i, p); set i = i+1; end if; set p = p+2; @@ -1545,8 +1545,8 @@ call ip(200)| # 45 211 # 100 557 # 199 1229 -select * from primes where i=45 or i=100 or i=199| -drop table primes| +select * from t3 where i=45 or i=100 or i=199| +drop table t3| drop procedure opp| drop procedure ip| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' @@ -1556,9 +1556,9 @@ show procedure status like '%p%'| # Fibonacci, for recursion test. (Yet Another Numerical series :) # --disable_warnings -drop table if exists fib| +drop table if exists t3| --enable_warnings -create table fib ( f bigint unsigned not null )| +create table t3 ( f bigint unsigned not null )| # We deliberately do it the awkward way, fetching the last two # values from the table, in order to exercise various statements @@ -1571,13 +1571,13 @@ begin if n > 1 then begin declare x, y bigint unsigned; - declare c cursor for select f from fib order by f desc limit 2; + declare c cursor for select f from t3 order by f desc limit 2; open c; fetch c into y; fetch c into x; close c; - insert into fib values (x+y); + insert into t3 values (x+y); call fib(n-1); end; end if; @@ -1588,22 +1588,23 @@ set @@max_sp_recursion_depth= 20| # Minimum test: recursion of 3 levels -insert into fib values (0), (1)| +insert into t3 values (0), (1)| call fib(3)| -select * from fib order by f asc| +select * from t3 order by f asc| -delete from fib| +delete from t3| -# Original test: 20 levels (may run into memory limits!) +# The original test, 20 levels, ran into memory limits on some machines +# and builds. Try 10 instead... -insert into fib values (0), (1)| +insert into t3 values (0), (1)| call fib(20)| -select * from fib order by f asc| -drop table fib| +select * from t3 order by f asc| +drop table t3| drop procedure fib| set @@max_sp_recursion_depth= 0| diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test index 308d4ad5c33..b9bd4c938b3 100644 --- a/mysql-test/t/sp_trans.test +++ b/mysql-test/t/sp_trans.test @@ -5,7 +5,7 @@ -- source include/have_innodb.inc --disable_warnings -drop table if exists t1, t2; +drop table if exists t1, t2, t3; --enable_warnings delimiter |; From 1fe1288417285cc6f5c95388bcc3305cfcebc0be Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jan 2006 08:32:22 +0100 Subject: [PATCH 24/37] Fix of fix for BUG#15866. (Actually change the fib() call in sp.test) mysql-test/r/sp.result: Updated results. mysql-test/t/sp.test: Actually change the fib(20) into fib(10). (Doh!) --- mysql-test/r/sp.result | 12 +----------- mysql-test/t/sp.test | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 63ab2098d5f..904cd7d8642 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1357,7 +1357,7 @@ f 2 delete from t3| insert into t3 values (0), (1)| -call fib(20)| +call fib(10)| select * from t3 order by f asc| f 0 @@ -1371,16 +1371,6 @@ f 21 34 55 -89 -144 -233 -377 -610 -987 -1597 -2584 -4181 -6765 drop table t3| drop procedure fib| set @@max_sp_recursion_depth= 0| diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f9b218967dd..8235686a74a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1601,7 +1601,7 @@ delete from t3| insert into t3 values (0), (1)| -call fib(20)| +call fib(10)| select * from t3 order by f asc| drop table t3| From b688b196979b8385a7463e8dcd83afdd0af6ca69 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jan 2006 15:59:22 +0300 Subject: [PATCH 25/37] Fix for BUG#15588: String overrun during sp-vars.test The bug appears after implementation of WL#2984 (Make stored routine variables work according to the standard). mysql-test/r/type_varchar.result: Update result file. mysql-test/t/type_varchar.test: Add a test for BUG#15588. sql/field.cc: - use memmove() instead of memcpy() -- after implementation of WL#2984 (Make stored routine variables work according to the standard) it is possible to store in the field the value from this field. For instance, this can happen for the following statement: SET sp_var = SUBSTR(sp_var, 1, 3); sql/sp_head.cc: - Work correctly with String: - String length has to be be reset before use; - qs_append() does not allocate memory, so the memory should be reserved beforehand. sql/sql_select.cc: Polishing: should have been done in WL#2984. --- mysql-test/r/type_varchar.result | 7 +++++++ mysql-test/t/type_varchar.test | 16 +++++++++++++++ sql/field.cc | 4 ++-- sql/sp_head.cc | 35 ++++++++++++++++++++++---------- sql/sql_select.cc | 2 +- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index e3b12cc36e3..e74850bba33 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -415,3 +415,10 @@ t1 CREATE TABLE `t1` ( KEY `index1` (`f1`(10)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index 1a3a93018a4..2d2314f0a29 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -130,3 +130,19 @@ show create table t1; alter table t1 modify f1 tinytext; show create table t1; drop table t1; + +# +# BUG#15588: String overrun +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; diff --git a/sql/field.cc b/sql/field.cc index df76eb729f8..0d48d4ae004 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5873,7 +5873,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) field_length/ field_charset->mbmaxlen, &well_formed_error); - memcpy(ptr,from,copy_length); + memmove(ptr, from, copy_length); /* Append spaces if the string was shorter than the field. */ if (copy_length < field_length) @@ -6266,7 +6266,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) field_length/ field_charset->mbmaxlen, &well_formed_error); - memcpy(ptr + length_bytes, from, copy_length); + memmove(ptr + length_bytes, from, copy_length); if (length_bytes == 1) *ptr= (uchar) copy_length; else diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f42fbef82e3..ae27b910304 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -105,21 +105,27 @@ sp_get_item_value(Item *item, String *str) case STRING_RESULT: { - char buf_holder[STRING_BUFFER_USUAL_SIZE]; - String buf(buf_holder, sizeof(buf_holder), &my_charset_latin1); String *result= item->val_str(str); if (!result) return NULL; - buf.append('_'); - buf.append(result->charset()->csname); - buf.append('\''); - buf.append(*result); - buf.append('\''); - str->copy(buf); + { + char buf_holder[STRING_BUFFER_USUAL_SIZE]; + String buf(buf_holder, sizeof(buf_holder), result->charset()); - return str; + /* We must reset length of the buffer, because of String specificity. */ + buf.length(0); + + buf.append('_'); + buf.append(result->charset()->csname); + buf.append('\''); + buf.append(*result); + buf.append('\''); + str->copy(buf); + + return str; + } } case ROW_RESULT: @@ -3085,9 +3091,16 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) void sp_instr_set_case_expr::print(String *str) { - str->append(STRING_WITH_LEN("set_case_expr ")); + const char CASE_EXPR_TAG[]= "set_case_expr "; + const int CASE_EXPR_TAG_LEN= sizeof(CASE_EXPR_TAG) - 1; + const int INT_STRING_MAX_LEN= 10; + + /* We must call reserve(), because qs_append() doesn't care about memory. */ + str->reserve(CASE_EXPR_TAG_LEN + INT_STRING_MAX_LEN + 2); + + str->qs_append(CASE_EXPR_TAG, CASE_EXPR_TAG_LEN); str->qs_append(m_case_expr_id); - str->append(' '); + str->qs_append(' '); m_case_expr->print(str); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index be255d1f790..1037f490397 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9046,7 +9046,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List &field_list) ++field; } - *field= NULL; /* mark the end of the list */ + *field= NULL; /* mark the end of the list */ s->blob_field[blob_count]= 0; /* mark the end of the list */ s->blob_fields= blob_count; From ff3079c8d0f27a54b55cb2685aa9fd1cb498bc1a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jan 2006 17:21:39 +0300 Subject: [PATCH 26/37] Test case for BUG#16621: INSERTs in Stored Procedures causes data corruption in the Binary Log. mysql-test/r/rpl_sp.result: Update result file. mysql-test/t/rpl_sp.test: Add test case for BUG#16621: INSERTs in Stored Procedures causes data corruption in the Binary Log. --- mysql-test/r/rpl_sp.result | 13 +++++++++++++ mysql-test/t/rpl_sp.test | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index c9a9e162fa6..7180b677b8e 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -401,5 +401,18 @@ drop function f1; select * from t1; a 1 +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(col VARCHAR(10)); +CREATE PROCEDURE p1(arg VARCHAR(10)) +INSERT INTO t1 VALUES(arg); +CALL p1('test'); +SELECT * FROM t1; +col +test +SELECT * FROM t1; +col +test +DROP PROCEDURE p1; drop table t1; reset master; diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index 8fa330584e2..c0eaf6f817f 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -401,6 +401,42 @@ sync_slave_with_master; connection slave; select * from t1; +# +# Bug#16621 "INSERTs in Stored Procedures causes data corruption in the Binary +# Log for 5.0.18" +# + +# Prepare environment. + +connection master; + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +# Test case. + +CREATE TABLE t1(col VARCHAR(10)); + +CREATE PROCEDURE p1(arg VARCHAR(10)) + INSERT INTO t1 VALUES(arg); + +CALL p1('test'); + +SELECT * FROM t1; + +sync_slave_with_master; +connection slave; + +SELECT * FROM t1; + +# Cleanup. + +connection master; + +DROP PROCEDURE p1; + # cleanup connection master; drop table t1; From a207c820e02d2fd9d25f06dcdea555410eaa1bb5 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Jan 2006 04:49:26 -0800 Subject: [PATCH 27/37] Turns out that the bulk interface was not well documented. I fixed the issue in archive and I will go and update the comments in handler next. I should probably also look through the other engines and see if this an issue elsewhere as well. sql/ha_archive.cc: Fixed for bulk_insert --- sql/ha_archive.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index c60d40c2685..68219151186 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -135,6 +135,13 @@ static HASH archive_open_tables; #define DATA_BUFFER_SIZE 2 // Size of the data used in the data file #define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption +/* + Number of rows that will force a bulk insert. +*/ +#define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2 + + + /* dummy handlerton - only to have something to return from archive_db_init */ handlerton archive_hton = { "ARCHIVE", @@ -1026,7 +1033,8 @@ void ha_archive::info(uint flag) void ha_archive::start_bulk_insert(ha_rows rows) { DBUG_ENTER("ha_archive::start_bulk_insert"); - bulk_insert= TRUE; + if (!rows || rows >= ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT) + bulk_insert= TRUE; DBUG_VOID_RETURN; } From 49a09cc3397581d120d097f06b5b807925cfec8a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Jan 2006 21:50:54 +0400 Subject: [PATCH 28/37] Merging mysql-test/r/func_gconcat.result: merging mysql-test/r/type_float.result: merging --- mysql-test/r/func_gconcat.result | 6 +++--- mysql-test/r/type_float.result | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 057c4990309..2a36e6fe17b 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -131,9 +131,9 @@ grp group_concat(a separator "")+0 3 456789 select grp, group_concat(a separator "")+0.0 from t1 group by grp; grp group_concat(a separator "")+0.0 -1 1 -2 23 -3 456789 +1 1.0 +2 23.0 +3 456789.0 select grp, ROUND(group_concat(a separator "")) from t1 group by grp; grp ROUND(group_concat(a separator "")) 1 1 diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 86c89231cc4..fb8d0515c18 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -245,22 +245,22 @@ show warnings; Level Code Message desc t1; Field Type Null Key Default Extra -x double 0 +x decimal(21,2) unsigned NO 0.00 drop table t1; create table t1 select 0.0 x; desc t1; Field Type Null Key Default Extra -x double(3,1) 0.0 +x decimal(2,1) unsigned NO 0.0 create table t2 select 105213674794682365.00 y; desc t2; Field Type Null Key Default Extra -y double(21,2) 0.00 +y decimal(20,2) unsigned NO 0.00 create table t3 select x+y a from t1,t2; show warnings; Level Code Message desc t3; Field Type Null Key Default Extra -a double 0 +a decimal(21,2) unsigned NO 0.00 drop table t1,t2,t3; create table t1 (s1 float(0,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). From 0ee28e1a4daca25f85ced473b2014e868ae341f8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jan 2006 17:15:33 +0400 Subject: [PATCH 29/37] BUG#16489 - utf8 + fulltext leads to corrupt index file. Fixed that UPDATE statement crashes multi-byte charset fulltext index. myisam/ft_update.c: Fixed that UPDATE statement crashes multi-byte charset fulltext index. While updating, always rewrite multi-byte charset fulltext index. mysql-test/r/fulltext2.result: Added a testcase for BUG#16489. mysql-test/t/fulltext2.test: Added a testcase for BUG#16489. --- myisam/ft_update.c | 4 ++++ mysql-test/r/fulltext2.result | 5 +++++ mysql-test/t/fulltext2.test | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/myisam/ft_update.c b/myisam/ft_update.c index beccc062270..8f2b2bce101 100644 --- a/myisam/ft_update.c +++ b/myisam/ft_update.c @@ -170,6 +170,10 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2) FT_SEG_ITERATOR ftsi1, ftsi2; CHARSET_INFO *cs=info->s->keyinfo[keynr].seg->charset; DBUG_ENTER("_mi_ft_cmp"); +#ifndef MYSQL_HAS_TRUE_CTYPE_IMPLEMENTATION + if (cs->mbmaxlen > 1) + DBUG_RETURN(THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT); +#endif _mi_ft_segiterator_init(info, keynr, rec1, &ftsi1); _mi_ft_segiterator_init(info, keynr, rec2, &ftsi2); diff --git a/mysql-test/r/fulltext2.result b/mysql-test/r/fulltext2.result index 72c6b2d22ed..f6a4b20bc22 100644 --- a/mysql-test/r/fulltext2.result +++ b/mysql-test/r/fulltext2.result @@ -234,5 +234,10 @@ insert into t1 values('test test '),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); delete from t1 limit 1; +truncate table t1; +insert into t1 values('ab c d'); +update t1 set a='ab c d'; +select * from t1 where match a against('ab c' in boolean mode); +a drop table t1; set names latin1; diff --git a/mysql-test/t/fulltext2.test b/mysql-test/t/fulltext2.test index 7a7b572d58f..fd97f795534 100644 --- a/mysql-test/t/fulltext2.test +++ b/mysql-test/t/fulltext2.test @@ -209,6 +209,14 @@ insert into t1 values('test test '),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); delete from t1 limit 1; + +# +# BUG#16489: utf8 + fulltext leads to corrupt index file. +# +truncate table t1; +insert into t1 values('ab c d'); +update t1 set a='ab c d'; +select * from t1 where match a against('ab c' in boolean mode); drop table t1; set names latin1; From 1dcfe028a7e5509489cf2db5db37c3e2c6705d76 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jan 2006 18:03:09 +0200 Subject: [PATCH 30/37] BUG#15699, failure to apply ignore rule for unexisting table. Since replication rules execute after `mysql_multi_update_prepare' returns we delay to `break' in case this functions returns non-zero (some tables are not found) for to examine if there is an ignore rule for a not-found table. By doing that it is guaranteed do/ignore replication rules logically preceed opening table routine. sql/sql_parse.cc: BUG#15699. We delay to `break' in case of unexisted tables for multi-update. First it is checked whether an ignore rule for such a table exists. More to the fix: if (opt_readonly && ...' in two places got be idented because it were enclosed explicitly into corresponding `else' groups. For that the preceding lines with `else' were changed in to be `else {'. This grouping is necessary to avoid any inattentive insertion in between of `else' and belonging to the else `if (opt_readonly && ...' statement. mysql-test/r/rpl_multi_update4.result: New BitKeeper file ``mysql-test/r/rpl_multi_update4.result'' mysql-test/t/rpl_multi_update4-slave.opt: New BitKeeper file ``mysql-test/t/rpl_multi_update4-slave.opt'' mysql-test/t/rpl_multi_update4.test: New BitKeeper file ``mysql-test/t/rpl_multi_update4.test'' --- mysql-test/r/rpl_multi_update4.result | 25 +++++++++ mysql-test/t/rpl_multi_update4-slave.opt | 1 + mysql-test/t/rpl_multi_update4.test | 44 ++++++++++++++++ sql/sql_parse.cc | 65 +++++++++++++++--------- 4 files changed, 110 insertions(+), 25 deletions(-) create mode 100644 mysql-test/r/rpl_multi_update4.result create mode 100644 mysql-test/t/rpl_multi_update4-slave.opt create mode 100644 mysql-test/t/rpl_multi_update4.test diff --git a/mysql-test/r/rpl_multi_update4.result b/mysql-test/r/rpl_multi_update4.result new file mode 100644 index 00000000000..f6dde65a35d --- /dev/null +++ b/mysql-test/r/rpl_multi_update4.result @@ -0,0 +1,25 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +drop database if exists d1; +drop database if exists d2; +drop database if exists d2; +create database d1; +create table d1.t0 (id int); +create database d2; +use d2; +create table t1 (id int); +create table t2 (id int); +insert into t1 values (1), (2), (3), (4), (5); +insert into t2 select id + 3 from t1; +update t1 join t2 using (id) set t1.id = 0; +insert into d1.t0 values (0); +use d1; +select * from t0 where id=0; +id +0 +drop database d1; +drop database d2; diff --git a/mysql-test/t/rpl_multi_update4-slave.opt b/mysql-test/t/rpl_multi_update4-slave.opt new file mode 100644 index 00000000000..fea27db43ee --- /dev/null +++ b/mysql-test/t/rpl_multi_update4-slave.opt @@ -0,0 +1 @@ +--replicate-wild-do-table=d1.% diff --git a/mysql-test/t/rpl_multi_update4.test b/mysql-test/t/rpl_multi_update4.test new file mode 100644 index 00000000000..3d909b8e5cd --- /dev/null +++ b/mysql-test/t/rpl_multi_update4.test @@ -0,0 +1,44 @@ +# Let's verify that multi-update is not always skipped by slave if +# some replicate-* rules exist. +# (BUG#15699) + +source include/master-slave.inc; + +### Clean-up + +connection master; +--disable_warnings +drop database if exists d1; +drop database if exists d2; + +connection slave; +drop database if exists d2; +--enable_warnings + +### Test + +connection master; +create database d1; # accepted by slave +create table d1.t0 (id int); +create database d2; # ignored by slave +use d2; +create table t1 (id int); +create table t2 (id int); +insert into t1 values (1), (2), (3), (4), (5); +insert into t2 select id + 3 from t1; +# a problematic query which must be filter out by slave +update t1 join t2 using (id) set t1.id = 0; +insert into d1.t0 values (0); # replication works + +sync_slave_with_master; +use d1; +#connection slave; +select * from t0 where id=0; # must find + +### Clean-up +connection master; +drop database d1; +drop database d2; + + +# End of test diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index df366643cf9..1cbc616f63f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2415,23 +2415,26 @@ mysql_execute_command(THD *thd) } } else -#endif /* HAVE_REPLICATION */ - - /* - When option readonly is set deny operations which change non-temporary - tables. Except for the replication thread and the 'super' users. - */ - if (opt_readonly && - !(thd->security_ctx->master_access & SUPER_ACL) && - uc_update_queries[lex->sql_command] && - !((lex->sql_command == SQLCOM_CREATE_TABLE) && - (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && - ((lex->sql_command != SQLCOM_UPDATE_MULTI) && - some_non_temp_table_to_be_updated(thd, all_tables))) { - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); - DBUG_RETURN(-1); - } +#endif /* HAVE_REPLICATION */ + /* + When option readonly is set deny operations which change non-temporary + tables. Except for the replication thread and the 'super' users. + */ + if (opt_readonly && + !(thd->security_ctx->master_access & SUPER_ACL) && + uc_update_queries[lex->sql_command] && + !((lex->sql_command == SQLCOM_CREATE_TABLE) && + (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && + ((lex->sql_command != SQLCOM_UPDATE_MULTI) && + some_non_temp_table_to_be_updated(thd, all_tables))) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); + DBUG_RETURN(-1); + } +#ifdef HAVE_REPLICATION + } /* endif unlikely slave */ +#endif if(lex->orig_sql_command == SQLCOM_END) statistic_increment(thd->status_var.com_stat[lex->sql_command], &LOCK_status); @@ -3232,8 +3235,7 @@ end_with_restore_list: else res= 0; - if ((res= mysql_multi_update_prepare(thd))) - break; + res= mysql_multi_update_prepare(thd); #ifdef HAVE_REPLICATION /* Check slave filtering rules */ @@ -3241,20 +3243,33 @@ end_with_restore_list: { if (all_tables_not_ok(thd, all_tables)) { + if (res!= 0) + { + res= 0; /* don't care of prev failure */ + thd->clear_error(); /* filters are of highest prior */ + } /* we warn the slave SQL thread */ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); break; } + if (res) + break; } else -#endif /* HAVE_REPLICATION */ - if (opt_readonly && - !(thd->security_ctx->master_access & SUPER_ACL) && - some_non_temp_table_to_be_updated(thd, all_tables)) { - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); - break; - } +#endif /* HAVE_REPLICATION */ + if (res) + break; + if (opt_readonly && + !(thd->security_ctx->master_access & SUPER_ACL) && + some_non_temp_table_to_be_updated(thd, all_tables)) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); + break; + } +#ifdef HAVE_REPLICATION + } /* unlikely */ +#endif res= mysql_multi_update(thd, all_tables, &select_lex->item_list, From 03ad365b00c446a6da418cb9112448449f2e5a45 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jan 2006 21:35:11 +0300 Subject: [PATCH 31/37] Changes after initial patch to #15787 zlib/Makefile.am: Added a reference to ../include for my_config.h zlib/README.MySQL: Updated a readme file to emphasize which files we what to keep an eye on in case of zlib upgrade. zlib/zconf.h: restored a code for standard platform dependant definitions --- zlib/Makefile.am | 2 ++ zlib/README.MySQL | 9 +++++++++ zlib/zconf.h | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/zlib/Makefile.am b/zlib/Makefile.am index 11b1991fa62..71619ce40c1 100644 --- a/zlib/Makefile.am +++ b/zlib/Makefile.am @@ -16,6 +16,8 @@ # Process this file with automake to create Makefile.in +INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include + pkglib_LTLIBRARIES=libz.la libz_la_LDFLAGS= -version-info 3:3:2 diff --git a/zlib/README.MySQL b/zlib/README.MySQL index 355dfb62d71..c17d3eeb6f9 100644 --- a/zlib/README.MySQL +++ b/zlib/README.MySQL @@ -5,3 +5,12 @@ original zlib distribution. You can find the original distribution at http://www.gzip.org/zlib/ or http://www.zlib.net/ + +Revision history: + +20.01.2006. The following files were changed as part of #15787 fix: + makefile.am + gzio.c + zconf.h + README.mysql + diff --git a/zlib/zconf.h b/zlib/zconf.h index f786a20a6f9..d983fa3eed4 100644 --- a/zlib/zconf.h +++ b/zlib/zconf.h @@ -288,7 +288,7 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +#ifdef HAVE_UNISTD_H # include /* for off_t */ # include /* for SEEK_* and off_t */ # ifdef VMS From fbc24f3376a6eb7e119af9fa6c32ca797ce1c5c0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jan 2006 15:59:08 +0400 Subject: [PATCH 32/37] Fix for bug#15851 Unlistable directories yield no info from information_schema to skip directories which are not allowed for read mysql-test/r/information_schema.result: Fix for bug#15851 Unlistable directories yield no info from information_schema test result mysql-test/t/information_schema.test: Fix for bug#15851 Unlistable directories yield no info from information_schema test case --- mysql-test/r/information_schema.result | 5 +++++ mysql-test/t/information_schema.test | 10 ++++++++++ mysys/my_lib.c | 2 ++ 3 files changed, 17 insertions(+) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index e7d82f48691..074b68881af 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1084,3 +1084,8 @@ DROP TABLE t1; DROP VIEW v1; DROP FUNCTION func1; DROP FUNCTION func2; +create database mysqltest; +create table mysqltest.t1(a int); +select table_schema from information_schema.tables where table_schema='mysqltest'; +table_schema +drop database mysqltest; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index f835a7148a2..323c6b37059 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -790,3 +790,13 @@ DROP TABLE t1; DROP VIEW v1; DROP FUNCTION func1; DROP FUNCTION func2; + +# +# Bug #15851 Unlistable directories yield no info from information_schema +# +create database mysqltest; +create table mysqltest.t1(a int); +--exec chmod -r $MYSQL_TEST_DIR/var/master-data/mysqltest +select table_schema from information_schema.tables where table_schema='mysqltest'; +--exec chmod +r $MYSQL_TEST_DIR/var/master-data/mysqltest +drop database mysqltest; diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 1908c70f407..4ca343064d3 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -170,6 +170,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags) bzero(finfo.mystat, sizeof(MY_STAT)); VOID(strmov(tmp_file,dp->d_name)); VOID(my_stat(tmp_path, finfo.mystat, MyFlags)); + if (!(finfo.mystat->st_mode & MY_S_IREAD)) + continue; } else finfo.mystat= NULL; From 333b1f8594922647278808a4c114c16695551343 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jan 2006 16:48:19 +0400 Subject: [PATCH 33/37] Fix for bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema(2nd ver) Fill schema tables with data before filesort if it's necessary mysql-test/r/information_schema.result: Fix for bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema(2nd ver) test result mysql-test/t/information_schema.test: Fix for bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema(2nd ver) test case --- mysql-test/r/information_schema.result | 8 ++++++++ mysql-test/t/information_schema.test | 9 +++++++++ sql/sql_prepare.cc | 2 ++ sql/sql_select.cc | 6 ++++++ sql/sql_show.cc | 12 +++++++++++- sql/table.h | 1 + 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 074b68881af..08d698092e2 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1089,3 +1089,11 @@ create table mysqltest.t1(a int); select table_schema from information_schema.tables where table_schema='mysqltest'; table_schema drop database mysqltest; +select column_type, group_concat(table_schema, '.', table_name), count(*) as num +from information_schema.columns where +table_schema='information_schema' and +(column_type = 'varchar(7)' or column_type = 'varchar(20)') +group by column_type order by num; +column_type group_concat(table_schema, '.', table_name) num +varchar(20) information_schema.COLUMNS 1 +varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2 diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 323c6b37059..85d56bfc78b 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -800,3 +800,12 @@ create table mysqltest.t1(a int); select table_schema from information_schema.tables where table_schema='mysqltest'; --exec chmod +r $MYSQL_TEST_DIR/var/master-data/mysqltest drop database mysqltest; + +# +# Bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema +# +select column_type, group_concat(table_schema, '.', table_name), count(*) as num +from information_schema.columns where +table_schema='information_schema' and +(column_type = 'varchar(7)' or column_type = 'varchar(20)') +group by column_type order by num; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index ffbbf0c6476..68f033f78fe 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2111,6 +2111,8 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) were closed in the end of previous prepare or execute call. */ tables->table= 0; + /* Reset is_schema_table_processed value(needed for I_S tables */ + tables->is_schema_table_processed= FALSE; if (tables->prep_on_expr) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1037f490397..95da0e6263a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11582,6 +11582,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, goto err; } } + + /* Fill schema tables with data before filesort if it's necessary */ + if ((join->select_lex->options & OPTION_SCHEMA_TABLE) && + get_schema_tables_result(join)) + goto err; + if (table->s->tmp_table) table->file->info(HA_STATUS_VARIABLE); // Get record count table->sort.found_records=filesort(thd, table,sortorder, length, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 17a8c846944..1f776d815df 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3845,7 +3845,16 @@ bool get_schema_tables_result(JOIN *join) TABLE_LIST *table_list= tab->table->pos_in_table_list; if (table_list->schema_table && thd->fill_derived_tables()) { - if (&lex->unit != lex->current_select->master_unit()) // is subselect + bool is_subselect= (&lex->unit != lex->current_select->master_unit()); + /* + The schema table is already processed and + the statement is not a subselect. + So we don't need to handle this table again. + */ + if (table_list->is_schema_table_processed && !is_subselect) + continue; + + if (is_subselect) // is subselect { table_list->table->file->extra(HA_EXTRA_RESET_STATE); table_list->table->file->delete_all_rows(); @@ -3858,6 +3867,7 @@ bool get_schema_tables_result(JOIN *join) if (table_list->schema_table->fill_table(thd, table_list, tab->select_cond)) result= 1; + table_list->is_schema_table_processed= TRUE; } } thd->no_warnings_for_error= 0; diff --git a/sql/table.h b/sql/table.h index ce0616a6833..947316e253f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -515,6 +515,7 @@ typedef struct st_table_list st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; + bool is_schema_table_processed; /* True when the view field translation table is used to convert schema table fields for backwards compatibility with SHOW command. From c20d947470b08491e5a7f9bb85d187cb6e7bd669 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Feb 2006 13:36:07 +0300 Subject: [PATCH 34/37] Yet another addition to the fix for BUG#9412 "Triggers: should have trigger privilege". Corrected addition of TRIGGER privilege by "mysql_fix_privilege_tables" script. Problem with it should have been caught by system_mysql_db/system_mysql_db_fix tests but they were disabled. Enabled them back. mysql-test/r/system_mysql_db.result: Updated test results after addition of TRIGGER privilege. mysql-test/t/disabled.def: Enabled back test system_mysql_db/system_mysql_db_fix tests. scripts/mysql_fix_privilege_tables.sql: Corrected addition of TRIGGER privilege. --- mysql-test/r/system_mysql_db.result | 5 ++++- mysql-test/t/disabled.def | 2 -- scripts/mysql_fix_privilege_tables.sql | 6 +++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 5f801ee71c5..bed5a2d4903 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -46,6 +46,7 @@ db CREATE TABLE `db` ( `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Event_priv` enum('N','Y') character set utf8 NOT NULL default 'N', + `Trigger_priv` enum('N','Y') character set utf8 NOT NULL default 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' @@ -71,6 +72,7 @@ host CREATE TABLE `host` ( `Create_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N', + `Trigger_priv` enum('N','Y') character set utf8 NOT NULL default 'N', PRIMARY KEY (`Host`,`Db`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges' show create table user; @@ -106,6 +108,7 @@ user CREATE TABLE `user` ( `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Create_user_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Event_priv` enum('N','Y') character set utf8 NOT NULL default 'N', + `Trigger_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `ssl_type` enum('','ANY','X509','SPECIFIED') character set utf8 NOT NULL default '', `ssl_cipher` blob NOT NULL, `x509_issuer` blob NOT NULL, @@ -134,7 +137,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Table_name` char(64) collate utf8_bin NOT NULL default '', `Grantor` char(77) collate utf8_bin NOT NULL default '', `Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, - `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') character set utf8 NOT NULL default '', + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') character set utf8 NOT NULL default '', `Column_priv` set('Select','Insert','Update','References') character set utf8 NOT NULL default '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index b3bec0a8ad6..a6903b6fa23 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -27,8 +27,6 @@ rpl_sp : Bug #16456 #ndb_dd_disk2memory : Bug #16466 ndb_autodiscover : Needs to be fixed w.r.t binlog ndb_autodiscover2 : Needs to be fixed w.r.t binlog -system_mysql_db : Needs fixing -system_mysql_db_fix : Needs fixing #ndb_alter_table_row : sometimes wrong error 1015!=1046 ndb_gis : garbled msgs from corrupt THD* diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 73b4ce32640..0fbaf7bec8a 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -674,5 +674,9 @@ ALTER TABLE event ADD sql_mode SET @hadTriggerPriv := 0; SELECT @hadTriggerPriv :=1 FROM user WHERE Trigger_priv LIKE '%'; -ALTER TABLE user add Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; +ALTER TABLE user ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Event_priv; +ALTER TABLE host ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; +ALTER TABLE db ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; +ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') COLLATE utf8_general_ci DEFAULT '' NOT NULL; + UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0; From 16a849f257d01ad1e03b37b4aa421559143e053f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Feb 2006 19:40:58 +0100 Subject: [PATCH 35/37] storage/example/ha_example.cc Copied from the general tree, to solve a build problem: ChangeSet 1.2121.1.5 2006/02/02 11:02:09 stewart@mysql.com build fix when building with example storage engine. storage/example/ha_example.cc: Copied from the general tree, to solve a build problem: ChangeSet 1.2121.1.5 2006/02/02 11:02:09 stewart@mysql.com build fix when building with example storage engine. --- storage/example/ha_example.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index 30034496291..0e9dcf231d9 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -106,6 +106,7 @@ handlerton example_hton= { NULL, /* Partition flags */ NULL, /* Alter table flags */ NULL, /* Alter tablespace */ + NULL, /* Fill Files table */ HTON_CAN_RECREATE }; From 733b1c4005965af7fe60d3bcf314567c0c6e7b09 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Feb 2006 01:49:33 +0300 Subject: [PATCH 36/37] Copied patch for BUG#15588 (BUG#16621) from 5.0 into 5.1-release. sql/field.cc: Use memmove() instead of memcpy() -- after implementation of WL#2984 (Make stored routine variables work according to the standard) it is possible to store in the field the value from this field. For instance, this can happen for the following statement: SET sp_var = SUBSTR(sp_var, 1, 3); sql/sp_head.cc: Work correctly with String: - String length has to be be reset before use; - qs_append() does not allocate memory, so the memory should be reserved beforehand. --- sql/field.cc | 4 ++-- sql/sp_head.cc | 37 +++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 37cab37f7d2..0045c3ece8d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5880,7 +5880,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) field_length/ field_charset->mbmaxlen, &well_formed_error); - memcpy(ptr,from,copy_length); + memmove(ptr,from,copy_length); /* Append spaces if the string was shorter than the field. */ if (copy_length < field_length) @@ -6296,7 +6296,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) field_length/ field_charset->mbmaxlen, &well_formed_error); - memcpy(ptr + length_bytes, from, copy_length); + memmove(ptr + length_bytes, from, copy_length); if (length_bytes == 1) *ptr= (uchar) copy_length; else diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 33eb652208f..0119bac22f0 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -105,21 +105,27 @@ sp_get_item_value(Item *item, String *str) case STRING_RESULT: { - char buf_holder[STRING_BUFFER_USUAL_SIZE]; - String buf(buf_holder, sizeof(buf_holder), &my_charset_latin1); String *result= item->val_str(str); if (!result) return NULL; - buf.append('_'); - buf.append(result->charset()->csname); - buf.append('\''); - buf.append(*result); - buf.append('\''); - str->copy(buf); - - return str; + { + char buf_holder[STRING_BUFFER_USUAL_SIZE]; + String buf(buf_holder, sizeof (buf_holder), result->charset()); + + /* We must reset length of the buffer, because of String specificity. */ + buf.length(0); + + buf.append('_'); + buf.append(result->charset()->csname); + buf.append('\''); + buf.append(*result); + buf.append('\''); + str->copy(buf); + + return str; + } } case ROW_RESULT: @@ -3076,9 +3082,16 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) void sp_instr_set_case_expr::print(String *str) { - str->append(STRING_WITH_LEN("set_case_expr ")); + const char CASE_EXPR_TAG[]= "set_case_expr "; + const int CASE_EXPR_TAG_LEN= sizeof(CASE_EXPR_TAG) - 1; + const int INT_STRING_MAX_LEN= 10; + + /* We must call reserve(), because qs_append() doesn't care about memory. */ + str->reserve(CASE_EXPR_TAG_LEN + INT_STRING_MAX_LEN + 2); + + str->qs_append(CASE_EXPR_TAG, CASE_EXPR_TAG_LEN); str->qs_append(m_case_expr_id); - str->append(' '); + str->qs_append(' '); m_case_expr->print(str); } From ef31f48de6b9e9d8d516d3fb8813b5971b7c02e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Feb 2006 23:21:17 +0300 Subject: [PATCH 37/37] A post-merge fix. --- mysql-test/r/information_schema.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 51d75e7ec41..fe3c409744d 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1137,8 +1137,8 @@ table_schema='information_schema' and (column_type = 'varchar(7)' or column_type = 'varchar(20)') group by column_type order by num; column_type group_concat(table_schema, '.', table_name) num -varchar(20) information_schema.COLUMNS 1 varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2 +varchar(20) information_schema.COLUMNS,information_schema.FILES,information_schema.FILES,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PLUGINS 6 select * from information_schema.engines WHERE ENGINE="MyISAM"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS MyISAM ENABLED Default engine as of MySQL 3.23 with great performance NO NO NO