From c6979413068e165de4471e0b9389baf9a9543a44 Mon Sep 17 00:00:00 2001 From: "ingo@mysql.com" <> Date: Tue, 24 Aug 2004 12:58:12 +0200 Subject: [PATCH 001/143] Enabled mysqltest for MASTER_PORT replacement. Replaced fixed port numbers by MASTER_PORT replacement. This allows for a set of ports per tree and hence parallel testing on multiple trees. --- BitKeeper/etc/logging_ok | 1 + client/mysqltest.c | 46 +++++++++++++++++++++-------- mysql-test/r/rpl000014.result | 8 ++--- mysql-test/r/rpl000015.result | 6 ++-- mysql-test/r/rpl_rotate_logs.result | 6 ++-- mysql-test/t/rpl000001.test | 2 +- mysql-test/t/rpl000014.test | 8 ++--- mysql-test/t/rpl000015.test | 6 ++-- mysql-test/t/rpl_rotate_logs.test | 6 ++-- 9 files changed, 55 insertions(+), 34 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index e0a0f4304fb..d025a25f5c5 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -11,6 +11,7 @@ greg@mysql.com guilhem@mysql.com heikki@donna.mysql.fi heikki@hundin.mysql.fi +ingo@mysql.com jani@hynda.mysql.fi jorge@linux.jorge.mysql.com konstantin@mysql.com diff --git a/client/mysqltest.c b/client/mysqltest.c index 18fafff275e..afd78ac6fb4 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -220,7 +220,8 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname); void reject_dump(const char* record_file, char* buf, int size); int close_connection(struct st_query* q); -VAR* var_get(const char* var_name, const char** var_name_end, int raw); +VAR* var_get(const char* var_name, const char** var_name_end, int raw, + my_bool ignore_not_existing); int eval_expr(VAR* v, const char* p, const char** p_end); /* Definitions for replace */ @@ -277,7 +278,7 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char* query) } else { - if(!(v = var_get(p, &p, 0))) + if(!(v = var_get(p, &p, 0, 0))) die("Bad variable in eval"); dynstr_append_mem(query_eval, v->str_val, v->str_val_len); } @@ -486,7 +487,8 @@ static int check_result(DYNAMIC_STRING* ds, const char* fname, return error; } -VAR* var_get(const char* var_name, const char** var_name_end, int raw) +VAR* var_get(const char* var_name, const char** var_name_end, int raw, + my_bool ignore_not_existing) { int digit; VAR* v; @@ -507,7 +509,11 @@ VAR* var_get(const char* var_name, const char** var_name_end, int raw) ++var_name; } if(var_name == save_var_name) + { + if (ignore_not_existing) + return 0; die("Empty variable"); + } if(!(v = (VAR*)hash_search(&var_hash, save_var_name, var_name - save_var_name))) @@ -629,7 +635,7 @@ int eval_expr(VAR* v, const char* p, const char** p_end) VAR* vp; if (*p == '$') { - if ((vp = var_get(p,p_end,0))) + if ((vp = var_get(p,p_end,0, 0))) { memcpy(v, vp, sizeof(*v)); return 0; @@ -671,7 +677,7 @@ int do_inc(struct st_query* q) { char* p=q->first_argument; VAR* v; - v = var_get(p, 0, 1); + v = var_get(p, 0, 1, 0); v->int_val++; v->int_dirty = 1; return 0; @@ -681,7 +687,7 @@ int do_dec(struct st_query* q) { char* p=q->first_argument; VAR* v; - v = var_get(p, 0, 1); + v = var_get(p, 0, 1, 0); v->int_val--; v->int_dirty = 1; return 0; @@ -909,14 +915,16 @@ static void get_ints(uint *to,struct st_query* q) /* Get a string; Return ptr to end of string Strings may be surrounded by " or ' + + If string is a '$variable', return the value of the variable. */ -static void get_string(char **to_ptr, char **from_ptr, - struct st_query* q) +static char *get_string(char **to_ptr, char **from_ptr, + struct st_query* q) { reg1 char c,sep; - char *to= *to_ptr, *from= *from_ptr; + char *to= *to_ptr, *from= *from_ptr, *start=to; DBUG_ENTER("get_string"); /* Find separator */ @@ -969,6 +977,19 @@ static void get_string(char **to_ptr, char **from_ptr, *to++ =0; /* End of string marker */ *to_ptr= to; *from_ptr= from; + + /* Check if this was a variable */ + if (*start == '$') + { + const char *end= --to; + VAR *var=var_get(start, &end, 0, 1); + if (var && to == (char*) end+1) + { + DBUG_PRINT("info",("get_string: '%s' -> '%s'", start, var->str_val)); + DBUG_RETURN(var->str_val); /* return found variable value */ + } + } + DBUG_RETURN(start); } @@ -994,13 +1015,12 @@ static void get_replace(struct st_query *q) start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); while (*from) { - char *to=buff; - get_string(&buff, &from, q); + char *to; + to= get_string(&buff, &from, q); if (!*from) die("Wrong number of arguments to replace in %s\n", q->query); insert_pointer_name(&from_array,to); - to=buff; - get_string(&buff, &from, q); + to= get_string(&buff, &from, q); insert_pointer_name(&to_array,to); } for (i=1,pos=word_end_chars ; i < 256 ; i++) diff --git a/mysql-test/r/rpl000014.result b/mysql-test/r/rpl000014.result index a47c3c91c1d..2a2a9bafa11 100644 --- a/mysql-test/r/rpl000014.result +++ b/mysql-test/r/rpl000014.result @@ -1,13 +1,13 @@ File Position Binlog_do_db Binlog_ignore_db master-bin.001 73 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 1 master-bin.001 73 Yes 0 0 +127.0.0.1 root MASTER_PORT 1 master-bin.001 73 Yes 0 0 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 1 master-bin.001 73 No 0 0 +127.0.0.1 root MASTER_PORT 1 master-bin.001 73 No 0 0 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 1 master-bin.001 73 Yes 0 0 +127.0.0.1 root MASTER_PORT 1 master-bin.001 73 Yes 0 0 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 1 master-bin.001 173 Yes 0 0 +127.0.0.1 root MASTER_PORT 1 master-bin.001 173 Yes 0 0 File Position Binlog_do_db Binlog_ignore_db master-bin.001 73 n diff --git a/mysql-test/r/rpl000015.result b/mysql-test/r/rpl000015.result index 58487af27f8..79856748f58 100644 --- a/mysql-test/r/rpl000015.result +++ b/mysql-test/r/rpl000015.result @@ -3,11 +3,11 @@ master-bin.001 73 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter 0 0 0 No 0 0 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 test 9998 60 4 No 0 0 +127.0.0.1 test MASTER_PORT 60 4 No 0 0 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 60 4 No 0 0 +127.0.0.1 root MASTER_PORT 60 4 No 0 0 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 60 master-bin.001 73 Yes 0 0 +127.0.0.1 root MASTER_PORT 60 master-bin.001 73 Yes 0 0 n 10 45 diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index cf432d07b08..a711811d768 100644 --- a/mysql-test/r/rpl_rotate_logs.result +++ b/mysql-test/r/rpl_rotate_logs.result @@ -1,5 +1,5 @@ Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 60 master-bin.001 387 Yes 0 0 +127.0.0.1 root MASTER_PORT 60 master-bin.001 387 Yes 0 0 s Could not break slave Tried hard @@ -12,7 +12,7 @@ testing temporary tables Log_name master-bin.003 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 60 master-bin.003 329 Yes 0 0 +127.0.0.1 root MASTER_PORT 60 master-bin.003 329 Yes 0 0 m 34 65 @@ -29,6 +29,6 @@ master-bin.006 490 a testing temporary tables part 2 Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter -127.0.0.1 root 9999 60 master-bin.006 490 Yes 0 0 +127.0.0.1 root MASTER_PORT 60 master-bin.006 490 Yes 0 0 count(*) 100 diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test index 6a827368fa4..e69ed9987d1 100644 --- a/mysql-test/t/rpl000001.test +++ b/mysql-test/t/rpl000001.test @@ -61,7 +61,7 @@ sleep 2; # The following test can't be done because the result of Pos will differ # on different computers -# --replace_result 9306 9999 3334 9999 3335 9999 +# --replace_result $MASTER_MYPORT MASTER_PORT # show slave status; set sql_slave_skip_counter=1; diff --git a/mysql-test/t/rpl000014.test b/mysql-test/t/rpl000014.test index b501d63b10e..e98471657ac 100644 --- a/mysql-test/t/rpl000014.test +++ b/mysql-test/t/rpl000014.test @@ -4,18 +4,18 @@ show master status; save_master_pos; connection slave; sync_with_master; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; change master to master_log_pos=73; slave stop; change master to master_log_pos=73; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; slave start; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; change master to master_log_pos=173; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; connection master; show master status; diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test index 73a10bed7b3..d3c30c19cc1 100644 --- a/mysql-test/t/rpl000015.test +++ b/mysql-test/t/rpl000015.test @@ -8,15 +8,15 @@ connection slave; reset slave; show slave status; change master to master_host='127.0.0.1'; ---replace_result 3306 9998 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT show slave status; eval change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=$MASTER_MYPORT; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; slave start; sync_with_master; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; connection master; drop table if exists t1; diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index ab88def5b2d..92baba5f737 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -40,7 +40,7 @@ insert into t1 values('Could not break slave'),('Tried hard'); save_master_pos; connection slave; sync_with_master; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; select * from t1; connection master; @@ -96,7 +96,7 @@ insert into t2 values (65); save_master_pos; connection slave; sync_with_master; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; select * from t2; @@ -126,7 +126,7 @@ connection slave; sync_with_master; select * from t4; ---replace_result 9306 9999 3334 9999 3335 9999 +--replace_result $MASTER_MYPORT MASTER_PORT show slave status; # because of concurrent insert, the table may not be up to date # if we do not lock From 3acccb988a7fba5f075acf7615bc0ec7f8548366 Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Fri, 27 Aug 2004 16:43:01 +0500 Subject: [PATCH 002/143] A fix (Bug #5232: CREATE TABLE ... SELECT can deadlock itself). --- mysql-test/r/merge.result | 9 +++++++++ mysql-test/t/merge.test | 14 ++++++++++++++ sql/sql_parse.cc | 13 +++++++++++++ 3 files changed, 36 insertions(+) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 7b2b9a47b0f..3585b8b0018 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -610,3 +610,12 @@ x y 1 3 1 2 drop table t1,t2,t3; +create table t1 (a int); +create table t2 (a int); +insert into t1 values (0); +insert into t2 values (1); +create table t3 engine=merge union=(t1, t2) select * from t1; +INSERT TABLE 't1' isn't allowed in FROM table list +create table t3 engine=merge union=(t1, t2) select * from t2; +INSERT TABLE 't2' isn't allowed in FROM table list +drop table t1, t2; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 76382a9cd99..57770dc0a0b 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -250,3 +250,17 @@ select * from t3 where x = 1 and y < 5 order by y; # Bug is that followng query returns empty set while it must be same as above select * from t3 where x = 1 and y < 5 order by y desc; drop table t1,t2,t3; + +# +# Bug#5232: CREATE TABLE ... SELECT +# + +create table t1 (a int); +create table t2 (a int); +insert into t1 values (0); +insert into t2 values (1); +--error 1093 +create table t3 engine=merge union=(t1, t2) select * from t1; +--error 1093 +create table t3 engine=merge union=(t1, t2) select * from t2; +drop table t1, t2; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 14fc748c288..e95c52f1e48 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1655,6 +1655,19 @@ mysql_execute_command(void) net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); DBUG_VOID_RETURN; } + if (lex->create_info.used_fields & HA_CREATE_USED_UNION) + { + TABLE_LIST *tab; + for (tab= tables; tab; tab= tab->next) + { + if (check_dup(tables->db, tab->real_name, + (TABLE_LIST*)lex->create_info.merge_list.first)) + { + net_printf(&thd->net, ER_INSERT_TABLE_USED, tab->real_name); + DBUG_VOID_RETURN; + } + } + } if (tables->next) { TABLE_LIST *table; From b93a973b1203b969fef15ef8c10d0d494423f9ed Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Tue, 31 Aug 2004 21:27:58 +0500 Subject: [PATCH 003/143] Added global my_getopt_error_reporter function pointer which is used in the handle_options() function (instead of using additional handle_option() parameter). The default value of the my_getopt_error_reporter is default_reporter(). One can set it to other functions if case of need. --- client/mysql.cc | 2 +- client/mysqladmin.c | 2 +- client/mysqlbinlog.cc | 2 +- client/mysqlcheck.c | 2 +- client/mysqldump.c | 2 +- client/mysqlimport.c | 2 +- client/mysqlmanager-pwgen.c | 2 +- client/mysqlmanagerc.c | 2 +- client/mysqlshow.c | 2 +- client/mysqltest.c | 2 +- extra/my_print_defaults.c | 2 +- extra/mysql_install.c | 2 +- extra/mysql_waitpid.c | 2 +- extra/perror.c | 2 +- extra/resolve_stack_dump.c | 2 +- extra/resolveip.c | 2 +- include/my_getopt.h | 10 ++-- isam/isamchk.c | 2 +- isam/pack_isam.c | 2 +- myisam/mi_test1.c | 2 +- myisam/myisam_ftdump.c | 2 +- myisam/myisamchk.c | 2 +- myisam/myisampack.c | 2 +- mysys/my_getopt.c | 101 ++++++++++++++++++++---------------- sql/gen_lex_hash.cc | 2 +- sql/mysqld.cc | 4 +- tools/mysqlmanager.c | 2 +- 27 files changed, 87 insertions(+), 76 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 73067700656..154695aa9e5 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -759,7 +759,7 @@ static int get_options(int argc, char **argv) opt_max_allowed_packet= *mysql_params->p_max_allowed_packet; opt_net_buffer_length= *mysql_params->p_net_buffer_length; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, 0))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); *mysql_params->p_max_allowed_packet= opt_max_allowed_packet; diff --git a/client/mysqladmin.c b/client/mysqladmin.c index e2843685d50..3bc11ec0fb0 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -254,7 +254,7 @@ int main(int argc,char *argv[]) mysql_init(&mysql); load_defaults("my",load_default_groups,&argc,&argv); save_argv = argv; /* Save for free_defaults */ - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, 0))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) { free_defaults(save_argv); exit(ho_error); diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 93e0b98b1e5..7c3d22c4900 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -559,7 +559,7 @@ static int parse_args(int *argc, char*** argv) result_file = stdout; load_defaults("my",load_default_groups,argc,argv); - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); return 0; diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 718b92da466..1c5638f3c52 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -273,7 +273,7 @@ static int get_options(int *argc, char ***argv) load_defaults("my", load_default_groups, argc, argv); - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, 0))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (!what_to_do) diff --git a/client/mysqldump.c b/client/mysqldump.c index c0ef07a7670..6dad8182b87 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -413,7 +413,7 @@ static int get_options(int *argc, char ***argv) md_result_file= stdout; load_defaults("my",load_default_groups,argc,argv); - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, 0))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); *mysql_params->p_max_allowed_packet= opt_max_allowed_packet; diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 751379591ff..ca53b74c119 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -206,7 +206,7 @@ static int get_options(int *argc, char ***argv) { int ho_error; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, 0))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (enclosed && opt_enclosed) diff --git a/client/mysqlmanager-pwgen.c b/client/mysqlmanager-pwgen.c index dc845008ce0..57d91b52f49 100644 --- a/client/mysqlmanager-pwgen.c +++ b/client/mysqlmanager-pwgen.c @@ -95,7 +95,7 @@ int parse_args(int argc, char** argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); return 0; diff --git a/client/mysqlmanagerc.c b/client/mysqlmanagerc.c index 78485427473..0001a0266e6 100644 --- a/client/mysqlmanagerc.c +++ b/client/mysqlmanagerc.c @@ -133,7 +133,7 @@ int parse_args(int argc, char **argv) load_defaults("my",load_default_groups,&argc,&argv); default_argv= argv; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); return 0; diff --git a/client/mysqlshow.c b/client/mysqlshow.c index cabe55cd95e..1a9aec02955 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -261,7 +261,7 @@ get_options(int *argc,char ***argv) { int ho_error; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, 0))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (tty_password) diff --git a/client/mysqltest.c b/client/mysqltest.c index df54b60dc97..2ec07692a4d 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2062,7 +2062,7 @@ int parse_args(int argc, char **argv) load_defaults("my",load_default_groups,&argc,&argv); default_argv= argv; - if ((handle_options(&argc, &argv, my_long_options, get_one_option, 0))) + if ((handle_options(&argc, &argv, my_long_options, get_one_option))) exit(1); if (argc > 1) diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index 515e816f473..f8a7995432b 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -100,7 +100,7 @@ static int get_options(int *argc,char ***argv) { int ho_error; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (*argc < 1) diff --git a/extra/mysql_install.c b/extra/mysql_install.c index ab44e1a055b..e2783f906b9 100644 --- a/extra/mysql_install.c +++ b/extra/mysql_install.c @@ -218,7 +218,7 @@ static int parse_args(int argc, char **argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); return 0; diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c index 0894d81a5ae..c228cc52c8b 100644 --- a/extra/mysql_waitpid.c +++ b/extra/mysql_waitpid.c @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) progname= argv[0]; - if (handle_options(&argc, &argv, my_long_options, get_one_option, NULL)) + if (handle_options(&argc, &argv, my_long_options, get_one_option)) exit(-1); if (!argv[0] || !argv[1] || (pid= atoi(argv[0])) <= 0 || (t= atoi(argv[1])) <= 0) diff --git a/extra/perror.c b/extra/perror.c index 212b313ade4..b4aeaf00671 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -145,7 +145,7 @@ static int get_options(int *argc,char ***argv) { int ho_error; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (!*argc && !print_all_codes) diff --git a/extra/resolve_stack_dump.c b/extra/resolve_stack_dump.c index 8b72ab1d864..c54f17a186e 100644 --- a/extra/resolve_stack_dump.c +++ b/extra/resolve_stack_dump.c @@ -121,7 +121,7 @@ static int parse_args(int argc, char **argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); /* diff --git a/extra/resolveip.c b/extra/resolveip.c index 23ea34abc42..d3caa9e1d45 100644 --- a/extra/resolveip.c +++ b/extra/resolveip.c @@ -90,7 +90,7 @@ static int get_options(int *argc,char ***argv) { int ho_error; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (*argc == 0) diff --git a/include/my_getopt.h b/include/my_getopt.h index f5b847f7dda..e602773e181 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -50,15 +50,15 @@ struct my_option int app_type; /* To be used by an application */ }; -extern char *disabled_my_option; -extern my_bool my_getopt_print_errors; - typedef my_bool (* my_get_one_option) (int, const struct my_option *, char * ); typedef void (* my_error_reporter) (enum loglevel level, const char *format, ... ); +extern char *disabled_my_option; +extern my_bool my_getopt_print_errors; +extern my_error_reporter my_getopt_error_reporter; + extern int handle_options (int *argc, char ***argv, - const struct my_option *longopts, my_get_one_option, - my_error_reporter ); + const struct my_option *longopts, my_get_one_option); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); diff --git a/isam/isamchk.c b/isam/isamchk.c index 8603b436841..daa9464eb4f 100644 --- a/isam/isamchk.c +++ b/isam/isamchk.c @@ -670,7 +670,7 @@ static void get_options(register int *argc, register char ***argv) if (isatty(fileno(stdout))) testflag|=T_WRITE_LOOP; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (*argc == 0) diff --git a/isam/pack_isam.c b/isam/pack_isam.c index 59594ccc929..b2e21afc743 100644 --- a/isam/pack_isam.c +++ b/isam/pack_isam.c @@ -353,7 +353,7 @@ static void get_options(int *argc, char ***argv) { int ho_error; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); my_progname= argv[0][0]; diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c index 88e6c5c89d3..8ea97c8e489 100644 --- a/myisam/mi_test1.c +++ b/myisam/mi_test1.c @@ -643,7 +643,7 @@ static void get_options(int argc, char *argv[]) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); return; diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c index 35182bc8abb..838f90feae5 100644 --- a/myisam/myisam_ftdump.c +++ b/myisam/myisam_ftdump.c @@ -66,7 +66,7 @@ int main(int argc,char *argv[]) struct { MI_INFO *info; } aio0, *aio=&aio0; /* for GWS_IN_USE */ MY_INIT(argv[0]); - if (error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL)) + if (error=handle_options(&argc, &argv, my_long_options, get_one_option)) exit(error); if (count || dump) verbose=0; diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index e8e85345897..5377ecc18a5 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -677,7 +677,7 @@ static void get_options(register int *argc,register char ***argv) if (isatty(fileno(stdout))) check_param.testflag|=T_WRITE_LOOP; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); /* If using repair, then update checksum if one uses --update-state */ diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 51f8ad1bb11..872fcb49faf 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -350,7 +350,7 @@ static void get_options(int *argc,char ***argv) if (isatty(fileno(stdout))) write_loop=1; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (!*argc) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index f9df4afb55d..71f8819756a 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -22,6 +22,9 @@ #include #include +static void default_reporter(enum loglevel level, const char *format, ...); +my_error_reporter my_getopt_error_reporter= &default_reporter; + static int findopt(char *optpat, uint length, const struct my_option **opt_res, char **ffname); @@ -56,7 +59,8 @@ char *disabled_my_option= (char*) "0"; my_bool my_getopt_print_errors= 1; -void default_reporter(enum loglevel level, const char *format, ...) +static void default_reporter(enum loglevel level __attribute__((unused)), + const char *format, ...) { va_list args; va_start(args, format); @@ -76,8 +80,7 @@ void default_reporter(enum loglevel level, const char *format, ...) int handle_options(int *argc, char ***argv, const struct my_option *longopts, - my_get_one_option get_one_option, - my_error_reporter reporter) + my_get_one_option get_one_option) { uint opt_found, argvpos= 0, length, i; my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used, @@ -91,9 +94,6 @@ int handle_options(int *argc, char ***argv, (*argv)++; /* --- || ---- */ init_variables(longopts); - if (! reporter) - reporter= &default_reporter; - for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { char *cur_arg= *pos; @@ -118,8 +118,9 @@ int handle_options(int *argc, char ***argv, if (!*++pos) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: Option '-O' requires an argument\n", progname); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Option '-O' requires an argument\n", + progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -135,9 +136,9 @@ int handle_options(int *argc, char ***argv, if (!*cur_arg) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: Option '--set-variable' requires an argument\n", - progname); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Option '--set-variable' requires an argument\n", + progname); return EXIT_ARGUMENT_REQUIRED; } } @@ -149,9 +150,9 @@ int handle_options(int *argc, char ***argv, if (!*++pos) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: Option '--set-variable' requires an argument\n", - progname); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Option '--set-variable' requires an argument\n", + progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -210,10 +211,11 @@ int handle_options(int *argc, char ***argv, if (opt_found > 1) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: ambiguous option '--%s-%s' (--%s-%s)\n", - progname, special_opt_prefix[i], cur_arg, - special_opt_prefix[i], prev_found); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: ambiguous option '--%s-%s' (--%s-%s)\n", + progname, special_opt_prefix[i], + cur_arg, special_opt_prefix[i], + prev_found); return EXIT_AMBIGUOUS_OPTION; } switch (i) { @@ -245,16 +247,20 @@ int handle_options(int *argc, char ***argv, if (must_be_var) { if (my_getopt_print_errors) - reporter(option_is_loose ? WARNING_LEVEL : ERROR_LEVEL, - "%s: unknown variable '%s'\n", progname, cur_arg); + my_getopt_error_reporter(option_is_loose ? + WARNING_LEVEL : ERROR_LEVEL, + "%s: unknown variable '%s'\n", + progname, cur_arg); if (!option_is_loose) return EXIT_UNKNOWN_VARIABLE; } else { if (my_getopt_print_errors) - reporter(option_is_loose ? WARNING_LEVEL : ERROR_LEVEL, - "%s: unknown option '--%s'\n", progname, cur_arg); + my_getopt_error_reporter(option_is_loose ? + WARNING_LEVEL : ERROR_LEVEL, + "%s: unknown option '--%s'\n", + progname, cur_arg); if (!option_is_loose) return EXIT_UNKNOWN_OPTION; } @@ -270,23 +276,27 @@ int handle_options(int *argc, char ***argv, if (must_be_var) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, "%s: variable prefix '%s' is not unique\n", - progname, cur_arg); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: variable prefix '%s' is not unique\n", + progname, cur_arg); return EXIT_VAR_PREFIX_NOT_UNIQUE; } else { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, "%s: ambiguous option '--%s' (%s, %s)\n", - progname, cur_arg, prev_found, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: ambiguous option '--%s' (%s, %s)\n", + progname, cur_arg, prev_found, + optp->name); return EXIT_AMBIGUOUS_OPTION; } } if (must_be_var && optp->var_type == GET_NO_ARG) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, "%s: option '%s' cannot take an argument\n", - progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '%s' cannot take an argument\n", + progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } if (optp->arg_type == NO_ARG) @@ -294,9 +304,9 @@ int handle_options(int *argc, char ***argv, if (optend && optp->var_type != GET_BOOL) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: option '--%s' cannot take an argument\n", - progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '--%s' cannot take an argument\n", + progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } if (optp->var_type == GET_BOOL) @@ -333,9 +343,9 @@ int handle_options(int *argc, char ***argv, if (!*++pos) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: option '--%s' requires an argument\n", - progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '--%s' requires an argument\n", + progname, optp->name); return EXIT_ARGUMENT_REQUIRED; } argument= *pos; @@ -384,9 +394,9 @@ int handle_options(int *argc, char ***argv, if (!pos[1]) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: option '-%c' requires an argument\n", - progname, optp->id); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '-%c' requires an argument\n", + progname, optp->id); return EXIT_ARGUMENT_REQUIRED; } argument= *++pos; @@ -396,9 +406,9 @@ int handle_options(int *argc, char ***argv, } if ((error= setval(optp, argument, set_maximum_value))) { - reporter(ERROR_LEVEL, - "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Error while setting value '%s' to '%s'\n", + progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); @@ -408,8 +418,9 @@ int handle_options(int *argc, char ***argv, if (!opt_found) { if (my_getopt_print_errors) - reporter(ERROR_LEVEL, - "%s: unknown option '-%c'\n", progname, *optend); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: unknown option '-%c'\n", + progname, *optend); return EXIT_UNKNOWN_OPTION; } } @@ -418,9 +429,9 @@ int handle_options(int *argc, char ***argv, } if ((error= setval(optp, argument, set_maximum_value))) { - reporter(ERROR_LEVEL, - "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Error while setting value '%s' to '%s'\n", + progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 72ab1184533..1e78aa35195 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -384,7 +384,7 @@ static int get_options(int argc, char **argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, 0))) + if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); if (argc >= 1) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1068c5ec9a1..1e682e16d1f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5119,8 +5119,8 @@ static void get_options(int argc,char **argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, - option_error_reporter))) + my_getopt_error_reporter= option_error_reporter; + if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); #if defined(HAVE_BROKEN_REALPATH) diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c index 12b5519ae9c..ade6da895c6 100644 --- a/tools/mysqlmanager.c +++ b/tools/mysqlmanager.c @@ -1333,7 +1333,7 @@ static int parse_args(int argc, char **argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL))) + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); return 0; From 3f0f1a4fb2b3b1b8e60471a5ef8a83e2b978acda Mon Sep 17 00:00:00 2001 From: "mwagner@here.mwagner.org" <> Date: Tue, 31 Aug 2004 13:29:28 -0500 Subject: [PATCH 004/143] Do-compile: Remove --warnings for mysql-test-run. Devs don't use it, and Serg says it's not needed anymore. --- Build-tools/Do-compile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index 1650e3d4a09..f92af463a0a 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -361,7 +361,7 @@ if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest) log_timestamp(); system("mkdir $bench_tmpdir") if (! -d $bench_tmpdir); safe_cd("${test_dir}/mysql-test"); - check_system("./mysql-test-run --warnings --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful"); + check_system("./mysql-test-run --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful"); } # From e27714591161894ee4a2e966ff142cb91a547052 Mon Sep 17 00:00:00 2001 From: "patg@krsna.patg.net" <> Date: Tue, 31 Aug 2004 18:59:41 -0700 Subject: [PATCH 005/143] mysqld_safe.sh: bug #5001, added conditional if to test if port set, then only kill the processes for this port, not all processes (in the case of this bug where multiple servers are killed.) The change to the 'grep' to make sure mysqld_safe isn't killed was per Serg's discovery that mysqld_safe would get killed. In my testing, in killing one of the pids for a running server, the "if test ! -f $pid_file" was the case that evaluated as true, so in order to test, I had to comment that block out. --- scripts/mysqld_safe.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 7b77bf449cd..8ad2ee1df4d 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -311,6 +311,7 @@ do fi if test ! -f $pid_file # This is removed if normal shutdown then + echo "STOPPING server from pid file $pid_file" break fi @@ -321,12 +322,24 @@ do # but should work for the rest of the servers. # The only thing is ps x => redhat 5 gives warnings when using ps -x. # kill -9 is used or the process won't react on the kill. - numofproces=`ps xa | grep -v "grep" | grep -c $ledir/$MYSQLD` + if test -n "$mysql_tcp_port" + then + numofproces=`ps xa | grep -v "grep" | grep $ledir/$MYSQLD| grep -c "port=$mysql_tcp_port"` + else + numofproces=`ps xa | grep -v "grep" | grep -c $ledir/$MYSQLD` + fi + echo -e "\nNumber of processes running now: $numofproces" | tee -a $err_log I=1 while test "$I" -le "$numofproces" do - PROC=`ps xa | grep $ledir/$MYSQLD | grep -v "grep" | sed -n '$p'` + if test -n "$mysql_tcp_port" + then + PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "port=$mysql_tcp_port" | sed -n '$p'` + else + PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | sed -n '$p'` + fi + for T in $PROC do break From 9e2e71816f42fbfe9e04a1433dd8e03ad5411c56 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Wed, 1 Sep 2004 12:36:01 +0200 Subject: [PATCH 006/143] Correct a typo error: cpp symbol is "BIG_TABLES", not "BIG_FILES" (backport from 4.1). --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 7853b615ae0..30a546ec5d9 100644 --- a/configure.in +++ b/configure.in @@ -939,8 +939,8 @@ MAX_CXX_OPTIMIZE="-O3" # workaround for Sun Forte/x86 see BUG#4681 case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in *solaris*-i?86-no) - CFLAGS="$CFLAGS -DBIG_FILES" - CXXFLAGS="$CXXFLAGS -DBIG_FILES" + CFLAGS="$CFLAGS -DBIG_TABLES" + CXXFLAGS="$CXXFLAGS -DBIG_TABLES" ;; *) ;; esac From 40c0fde904cac1335f93e54fb3e40d4c5dc4fedb Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 1 Sep 2004 16:41:09 +0300 Subject: [PATCH 007/143] ha_innodb.cc: If ALTER TABLE ... DROP FOREIGN KEY ... fails because of a wrong constraint name, return a table handler error number 150 instead of 152; the value 152 was misleading, as it referred to '152 = Cannot delete a parent row', whereas '150 = Foreign key constraint is incorrectly formed' is less misleading --- sql/ha_innodb.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 3d3aca9cfd5..1572e22d6f7 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -285,8 +285,9 @@ convert_error_code_to_mysql( } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) { - return(HA_ERR_ROW_IS_REFERENCED); - + return(HA_ERR_CANNOT_ADD_FOREIGN); /* TODO: This is a bit + misleading, a new MySQL error + code should be introduced */ } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) { return(HA_ERR_CRASHED); From 80879cffe627e555561f07e30779340e1b5c1c58 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 1 Sep 2004 16:04:01 +0200 Subject: [PATCH 008/143] - removed swedish errmsg.OLD --- sql/share/swedish/errmsg.OLD | 221 ----------------------------------- 1 file changed, 221 deletions(-) delete mode 100644 sql/share/swedish/errmsg.OLD diff --git a/sql/share/swedish/errmsg.OLD b/sql/share/swedish/errmsg.OLD deleted file mode 100644 index 3dd14c8b613..00000000000 --- a/sql/share/swedish/errmsg.OLD +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ - -"hashchk", -"isamchk", -"NO", -"YES", -"Kan inte skapa filen: '%-.64s' (Felkod: %d)", -"Kan inte skapa tabellen: '%-.64s' (Felkod: %d)", -"Kan inte skapa databasen '%-.64s'. (Felkod: %d)", -"Databasen '%-.64s' existerar redan", -"Kan inte radera databasen '%-.64s'. Databasen finns inte", -"Fel vid radering av databasen (Kan inte radera '%-.64s'. Felkod: %d)", -"Fel vid radering av databasen (Kan inte radera biblioteket '%-.64s'. Felkod: %d)", -"Kan inte radera filen: '%-.64s' (Felkod: %d)", -"Hittar inte posten i systemregistret", -"Kan inte läsa filinformationen (stat) från '%-.64s' (Felkod: %d)", -"Kan inte inte läsa aktivt bibliotek. (Felkod: %d)", -"Kan inte låsa filen. (Felkod: %d)", -"Kan inte använda: '%-.64s'. (Felkod: %d)", -"Hittar inte filen: '%-.64s'. (Felkod: %d)", -"Kan inte läsa från bibliotek '%-.64s'. (Felkod: %d)", -"Kan inte byta till: '%-.64s'. (Felkod: %d)", -"Posten har förändrats sedan den lästes i register '%-.64s'", -"Disken är full (%s). Väntar tills det finns ledigt utrymme....", -"Kan inte skriva, dubbel söknyckel i register '%-.64s'", -"Fick fel vid stängning av '%-.64s' (Felkod: %d)", -"Fick fel vid läsning av '%-.64s' (Felkod %d)", -"Kan inte byta namn från '%-.64s' till '%-.64s' (Felkod: %d)", -"Fick fel vid skrivning till '%-.64s' (Felkod %d)", -"'%-.64s' är låst mot användning", -"Sorteringen avbruten", -"Formulär '%-.64s' finns inte i '%-.64s'", -"Fick felkod %d från databashanteraren", -"Registrets databas har inte denna facilitet", -"Hittar inte posten", -"Felaktig fil: '%-.64s'", -"Fatalt fel vid hantering av register '%-.64s'. Kör en reparation", -"Gammal nyckelfil '%-.64s'; Reparera registret", -"'%-.64s' är skyddad mot förändring", -"Oväntat slut på minnet, starta om programmet och försök på nytt (Behövde %d bytes)", -"Sorteringsbufferten räcker inte till. Kontrollera startparametrarna", -"Oväntat filslut vid läsning från '%-.64s' (Felkod: %d)", -"För många anslutningar", -"Fick slut på minnet. Kontrollera ifall mysqld eller någon annan process använder allt tillgängligt minne. Ifall inte, försök använda 'ulimit' eller allokera mera swap", -"Kan inte hitta 'hostname' för din adress", -"Fel vid initiering av kommunikationen med klienten", -"Användare '%-.32s@%-.64s' är ej berättigad att använda databasen %-.64s", -"Användare '%-.32s@%-.64s' är ej berättigad att logga in (Använder lösen: %s)", -"Ingen databas i användning", -"Okänt commando", -"Kolumn '%-.64s' får inte vara NULL", -"Okänd database '%-.64s'", -"Tabellen '%-.64s' finns redan", -"Okänd tabell '%-.64s'", -"Kolumn: '%-.64s' i %s är inte unik", -"Servern går nu ned", -"Okänd kolumn '%-.64s' i %s", -"'%-.64s' finns inte i GROUP BY", -"Kan inte använda GROUP BY med '%-.64s'", -"Kommandot har både sum functions och enkla funktioner", -"Antalet kolumner motsvarar inte antalet värden", -"Kolumn namn '%-.64s' är för långt", -"Kolumn namn '%-64s finns flera gånger", -"Nyckel namn '%-.64s' finns flera gånger", -"Dubbel nyckel '%-.64s' för nyckel: %d", -"Felaktigt kolumn typ för kolumn: '%-.64s'", -"%s nära '%-.64s' på rad %d", -"Frågan var tom", -"Icke unikt tabell/alias: '%-.64s'", -"Ogiltigt DEFAULT värde för '%-.64s'", -"Flera PRIMARY KEY använda", -"För många nycklar använda. Man får ha högst %d nycklar", -"För många nyckel delar använda. Man får ha högst %d nyckeldelar", -"För lång nyckel. Högsta tillåtna nyckellängd är %d", -"Nyckel kolumn '%-.64s' finns inte", -"En BLOB '%-.64s' kan inte vara nyckel med den använda tabellen typen", -"För stor kolumnlängd angiven för '%-.64s' (max= %d). Använd en BLOB instället", -"Det får finnas endast ett AUTO_INCREMENT fält och detta måste vara en nyckel", -"%s: klar att ta emot klienter\n", -"%s: Normal avslutning\n", -"%s: Fick signal %d. Avslutar!\n", -"%s: Avslutning klar\n", -"%s: Stänger av tråd %ld användare: '%-.64s'\n", -"Kan inte skapa IP socket", -"Tabellen '%-.64s' har inget index som motsvarar det angivna i CREATE INDEX. Skapa om tabellen", -"Fält separatorerna är inte emotsägande eller för långa. Kontrollera mot manualen", -"Man kan inte använda fast radlängd med blobs. Använd 'fields terminated by'." -"Textfilen '%' måste finnas i databas biblioteket eller vara läsbar för alla", -"Filen '%-.64s' existerar redan", -"Rader: %ld Bortagna: %ld Dubletter: %ld Varningar: %ld", -"Rader: %ld Dubletter: %ld", -"Felaktig delnyckel. Nyckeldelen är inte en sträng eller den angivna längden är längre än kolumnlängden", -"Man kan inte radera alla fält med ALTER TABLE. Använd DROP TABLE istället", -"Kan inte ta bort '%-.64s'. Kontrollera att fältet/nyckel finns", -"Rader: %ld Dubletter: %ld Varningar: %ld", -"INSERT table '%-.64s' får inte finnas i FROM tabell-listan", -"Finns inget thread med id %lu", -"Du är inte ägare till thread %lu", -"Inga tabeller angivna", -"För många alternativ till kolumn %s för SET", -"Kan inte generera ett unikt filnamn %s.(1-999)\n", -"Tabell '%-.64s' kan inte uppdateras emedan den är låst för läsning", -"Tabell '%-.64s' är inte låst med LOCK TABLES", -"BLOB fält '%-.64s' kan inte ha ett DEFAULT värde" -"Felaktigt databas namn '%-.64s'", -"Felaktigt tabell namn '%-.64s'", -"Den angivna frågan skulle troligen ta mycket long tid! Kontrollar din WHERE och använd SET OPTION SQL_BIG_SELECTS=1 ifall du vill hantera stora joins", -"Oidentifierat fel", -"Okänd procedur: %s", -"Felaktigt antal parametrar till procedur %s", -"Felaktiga parametrar till procedur %s", -"Okänd tabell '%-.64s' i '%-.64s'", -"Fält '%-.64s' är redan använt", -"Felaktig användning av SQL grupp function", -"Tabell '%-.64s' har en extension som inte finns i denna version av MySQL", -"Tabeller måste ha minst 1 kolumn", -"Tabellen '%-.64s' är full", -"Okänt karaktärset: '%-.64s'", -"För många tabeller. MySQL can ha högst %d tabeller i en och samma join" -"För många fält", -"För stor total rad längd. Den högst tillåtna rad-längden, förutom BLOBs, är %d. Ändra några av dina fält till BLOB", -"Tråd-stacken tog slut: Har använt %ld av %ld bytes. Använd 'mysqld -O thread_stack=#' ifall du behöver en större stack", -"Felaktigt referens i OUTER JOIN. Kontrollera ON uttrycket", -"Kolumn '%-.32s' är använd med UNIQUE eller INDEX men är inte definerad med NOT NULL", -"Kan inte ladda funktionen '%-.64s'", -"Kan inte initialisera funktionen '%-.64s'; '%-.80s'", -"Man får inte ange sökväg för dynamiska bibliotek", -"Funktionen '%-.64s' finns redan", -"Kan inte öppna det dynamiska biblioteket '%-.64s' (Felkod: %d %s)", -"Hittar inte funktionen '%-.64s' in det dynamiska biblioteket", -"Funktionen '%-.64s' är inte definierad", -"Denna dator '%-.64s' är blockerad pga många felaktig paket. Gör 'mysqladmin flush-hosts' för att ta bort alla blockeringarna", -"Denna dator '%-.64s' har inte privileger att använda denna MySQL server", -"Du använder MySQL som en anonym användare och som sådan får du inte ändra ditt lösenord", -"För att ändra lösenord för andra måste du ha rättigheter att uppdatera mysql databasen", -"Hittade inte användaren i 'user' tabellen", -"Rader: %ld Uppdaterade: %ld Varningar: %ld", -"Kan inte skapa en ny tråd (errno %d)" -"Antalet kolumner motsvarar inte antalet värden på rad: %ld", -"Kunde inte stänga och öppna tabell: '%-.64s', -"Felaktig använding av NULL", -"Fix fel '%-.64s' från REGEXP", -"Man får ha både GROUP kolumner (MIN(),MAX(),COUNT()...) och fält i en fråga om man inte har en GROUP BY del", -"Det finns inget privilegium definierat för användare '%-.32s' på '%-.64s'", -"%-.16s ej tillåtet för '%-.32s@%-.64s' för tabell '%-.64s'", -"%-.16s ej tillåtet för '%-.32s@%-.64s'\n för kolumn '%-.64s' i tabell '%-.64s'", -"Felaktigt GRANT privilegium använt", -"Felaktigt maskinnamn eller användarnamn använt med GRANT", -"Det finns ingen tabell som heter '%-64s.%s'" -"Det finns inget privilegium definierat för användare '%-.32s' på '%-.64s' för tabell '%-.64s'", -"Du kan inte använda detta kommando med denna MySQL version", -"Du har något fel i din syntax", -"DELAYED INSERT tråden kunde inte låsa tabell '%-.64s'", -"Det finns redan 'max_delayed_threads' trådar i använding", -"Avbröt länken för tråd %ld till db: '%-.64s' användare: '%-.64s' (%s)", -"Kommunkationspaketet är större än 'max_allowed_packet'", -"Fick läsfel från klienten vid läsning från 'PIPE'", -"Fick fatalt fel från 'fcntl()'", -"Kommunikationspaketen kom i fel ordning", -"Kunde inte packa up kommunikationspaketet", -"Fick ett fel vid läsning från klienten", -"Fick 'timeout' vid läsning från klienten", -"Fick ett fel vid skrivning till klienten", -"Fick 'timeout' vid skrivning till klienten", -"Resultat strängen är längre än max_allowed_packet", -"Den använda tabell typen kan inte hantera BLOB/TEXT kolumner", -"Den använda tabell typen kan inte hantera AUTO_INCREMENT kolumner", -"INSERT DELAYED kan inte användas med tabell '%-.64s', emedan den är låst med LOCK TABLES", -"Felaktigt column namn '%-.100s'", -"Den använda tabell typen kan inte indexera kolumn '%-.64s'", -"Tabellerna i MERGE tabellen är inte identiskt definierade", -"Kan inte skriva till tabell '%-.64s'; UNIQUE test", -"Du har inte angett en nyckel längd för BLOB '%-.64s'", -"Alla delar av en PRIMARY KEY måste vara NOT NULL; Om du vill ha en nyckel med NULL, använd UNIQUE istället", -"Resultet bestod av mera än en rad", -"Denna tabell typ kräver en PRIMARY KEY", -"Denna version av MySQL är inte kompilerad med RAID", -"Du använder 'säker uppdaterings mod' och försökte uppdatera en table utan en WHERE sats som använder sig av en nyckel", -"Nyckel '%-.64s' finns inte in tabell '%-.64s'", -"Kan inte öppna tabellen", -"Tabellhanteraren för denna tabell kan inte göra check/repair", -"Du får inte utföra detta kommando i en transaktion", -"Fick fel %d vid COMMIT", -"Fick fel %d vid ROLLBACK", -"Fick fel %d vid FLUSH_LOGS", -"Fick fel %d vid CHECKPOINT", -"Avbröt länken för tråd %ld till db: '%-.64s' användare: '%-.32s' Host: '%-.64s' (%.-64s)", -"Tabellhanteraren klarar inte en binär kopiering av tabellen", -"Binärloggen stängdes medan vi gjorde FLUSH MASTER", -"Failed rebuilding the index of dumped table '%-.64s'", -"Fick en master: '%-.64s'", -"Fick nätverksfel vid läsning från master", -"Fick nätverksfel vid skrivning till master", -"Hittar inte ett FULLTEXT index i kolumnlistan", -"Kan inte exekvera kommandot emedan du har en låst tabell eller an aktiv transaktion", -"Okänd system variabel '%-.64'", -"Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE", -"Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", -"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", -"Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", -"Denna operation kan inte göras under replikering; Gör SLAVE STOP först", -"Denna operation kan endast göras under replikering; Konfigurera slaven och gör SLAVE START", -"Servern är inte konfigurerade som en replikations slav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO", -"Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'", -"Kunde inte starta en tråd för replikering", -"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar", -"Man kan endast använda konstant-uttryck med SET", -"Fick inte ett lås i tid", -"Antal lås överskrider antalet reserverade lås", -"Updaterings-lås kan inte göras när man använder READ UNCOMMITTED", -"DROP DATABASE är inte tillåtet när man har ett globalt läs-lås", -"CREATE DATABASE är inte tillåtet när man har ett globalt läs-lås", -"Felaktiga argument till %s", -"%-.32s@%-.64s har inte rättigheter att skapa nya användare", -"Fick fel vid anslutning till master: %-.128s", -"Fick fel vid utförande av command på mastern: %-.128s", -"Fick fel vid utförande av %s: %-.128s", -"Felaktig använding av %s and %s", -"SELECT kommandona har olika antal kolumner" -"Kan inte utföra kommandot emedan du har ett READ lås", From ca42de54a1607823836f73b4eb5b30ded2a60c33 Mon Sep 17 00:00:00 2001 From: "miguel@hegel.txg.br" <> Date: Wed, 1 Sep 2004 14:02:11 -0300 Subject: [PATCH 009/143] Fix for bug #5302 --- sql/mysqld.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1e682e16d1f..8236e5d9842 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2669,6 +2669,13 @@ server."); pthread_mutex_unlock(&LOCK_thread_count); } #else +#ifdef __WIN__ + if ( !have_tcpip || opt_disable_networking) + { + sql_print_error("Without TCP/IP or use of --skip-networking results in no available interfaces"); + unireg_abort(1); + } +#endif handle_connections_sockets(0); #ifdef EXTRA_DEBUG2 sql_print_error("Exiting main thread"); From fc118875961eb6b656b4ed95a205f1e8eccbdc4c Mon Sep 17 00:00:00 2001 From: "miguel@hegel.txg.br" <> Date: Thu, 2 Sep 2004 01:17:28 -0300 Subject: [PATCH 010/143] Fix for bug #5302 --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8236e5d9842..670e6a5a63e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2672,7 +2672,7 @@ server."); #ifdef __WIN__ if ( !have_tcpip || opt_disable_networking) { - sql_print_error("Without TCP/IP or use of --skip-networking results in no available interfaces"); + sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces"); unireg_abort(1); } #endif From f7bc60e0fc0848b441103a0303237031c56949cc Mon Sep 17 00:00:00 2001 From: "paul@kite-hub.kitebird.com" <> Date: Thu, 2 Sep 2004 18:12:05 -0500 Subject: [PATCH 011/143] errmsg.txt: Add GPL comment --- sql/share/czech/errmsg.txt | 16 ++++++++++++++++ sql/share/danish/errmsg.txt | 17 +++++++++++++++-- sql/share/dutch/errmsg.txt | 18 ++++++++++++++++-- sql/share/english/errmsg.txt | 17 +++++++++++++++-- sql/share/estonian/errmsg.txt | 19 ++++++++++++++++--- sql/share/french/errmsg.txt | 17 +++++++++++++++-- sql/share/german/errmsg.txt | 18 ++++++++++++++++-- sql/share/greek/errmsg.txt | 17 +++++++++++++++-- sql/share/hungarian/errmsg.txt | 20 ++++++++++++++++++-- sql/share/italian/errmsg.txt | 17 +++++++++++++++-- sql/share/japanese/errmsg.txt | 19 +++++++++++++++++-- sql/share/korean/errmsg.txt | 17 +++++++++++++++-- sql/share/norwegian-ny/errmsg.txt | 17 +++++++++++++++-- sql/share/norwegian/errmsg.txt | 17 +++++++++++++++-- sql/share/polish/errmsg.txt | 18 ++++++++++++++++-- sql/share/portuguese/errmsg.txt | 19 +++++++++++++++++-- sql/share/romanian/errmsg.txt | 18 ++++++++++++++++-- sql/share/russian/errmsg.txt | 20 ++++++++++++++++++-- sql/share/slovak/errmsg.txt | 17 +++++++++++++++-- sql/share/spanish/errmsg.txt | 19 +++++++++++++++++-- sql/share/swedish/errmsg.txt | 17 +++++++++++++++-- sql/share/ukrainian/errmsg.txt | 20 +++++++++++++++++--- 22 files changed, 350 insertions(+), 44 deletions(-) diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index b6737df91e1..88ecaed386b 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -1,3 +1,19 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* Modifikoval Petr -B©najdr, snajdr@pvt.net, snajdr@cpress.cz v.0.01 ISO LATIN-8852-2 diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index ba50c78e92c..6210bf7788c 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Knud Riishøjgård knudriis@post.tele.dk 99 && Carsten H. Pedersen, carsten.pedersen@bitbybit.dk oct. 1999 / aug. 2001. */ diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 1b9c1025e69..c3607f4cd0f 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -1,6 +1,20 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind +/* Copyright (C) 2003 MySQL AB + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Dutch error messages (share/dutch/errmsg.txt) 2001-08-02 - Arjen Lentz (agl@bitbike.com) Completed earlier partial translation; worked on consistency and spelling. diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index edbf2357ff8..796751210dc 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ "hashchk", "isamchk", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 8ec5d4b29f0..8157a33836e 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -1,9 +1,22 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* - Copyright Abandoned 1997 MySQL AB - This file is public domain and comes with NO WARRANTY of any kind Esialgne tõlge: Tõnu Samuel (tonu@spam.ee) Parandanud ja täiendanud: Indrek Siitan (tfr@mysql.com) - */ "hashchk", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 3c5c827aa62..3c88ccc0378 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ "hashchk", "isamchk", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 3960dcc2122..91f3f91a464 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -1,6 +1,20 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind +/* Copyright (C) 2003 MySQL AB + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Dirk Munzinger (dmun@4t2.com) Version: 07.06.2001 */ diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 3e9a68f2b4b..aff7f8ba3c2 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ "hashchk", "isamchk", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 9da878981b0..60dc3204bb4 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -1,7 +1,23 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Translated by Feher Peter. Forditotta Feher Peter (feherp@mail.matav.hu) 1998 Updated May, 2000 - This file is public domain and comes with NO WARRANTY of any kind */ +*/ "hashchk", "isamchk", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 30dff93ebef..c51c69cf298 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ "hashchk", "isamchk", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 7e267261a2e..fb604923e4e 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -1,5 +1,20 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* 3.22.10-beta euc-japanese (ujis) text */ diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 1ad5432f4db..764cbb78740 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This È­ÀÏ is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ "hashchk", "isamchk", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 234a53b53fb..424530ecf87 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Roy-Magne Mo rmo@www.hivolda.no 97 */ diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index e582786dc6e..73314ea647b 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Roy-Magne Mo rmo@www.hivolda.no 97 */ diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index a4d11046ea4..f24a54ec8e8 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -1,6 +1,20 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind +/* Copyright (C) 2003 MySQL AB + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Changed by Jaroslaw Lewandowski Charset ISO-8859-2 */ diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 14c14270dc0..2810ac134b1 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -1,6 +1,21 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* Updated by Thiago Delgado Pinto - thiagodp@ieg.com.br - 06.07.2002 */ + "hashchk", "isamchk", "NÃO", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 8d2decdf23f..552b532c0a2 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -1,6 +1,20 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind +/* Copyright (C) 2003 MySQL AB + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Translated into Romanian by Stefan Saroiu e-mail: tzoompy@cs.washington.edu */ diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 42845b57d76..172ee97c883 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -1,6 +1,22 @@ -/* Copyright 2003 MySQL AB; +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Translation done in 2003 by Egor Egorov; Ensita.NET, http://www.ensita.net/ - This file is public domain and comes with NO WARRANTY of any kind */ +*/ /* charset: KOI8-R */ "hashchk", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 52ed69a238d..8467fad5b11 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Translated from both E n g l i s h & C z e c h error messages diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 2ed3c19b68e..4ab76a64ca7 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -1,5 +1,20 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Traduccion por Miguel Angel Fernandez Roiz -- LoboCom Sistemas, s.l. From June 28, 2001 translated by Miguel Solorzano miguel@mysql.com */ "hashchk", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 4fd05875b43..352a226ef23 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -1,5 +1,18 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ "hashchk", "isamchk", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 6036f4be2d5..188523ecf45 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -1,6 +1,20 @@ -/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB - * This ÆÁÊÌ is public domain and comes with NO WARRANTY of any kind - * +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* * Ukrainian translation by Roman Festchook * Encoding: KOI8-U * Version: 13/09/2001 mysql-3.23.41 From f888026fdca8d3ee61d8b2fcac032cf0264b54c0 Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Thu, 2 Sep 2004 22:06:30 -0700 Subject: [PATCH 012/143] select.result, select.test: Added a test case for bug #5333. null_key.result, key_primary.result: Made covering index usable for const tables. sql_select.cc: Made covering index usable for const tables: downported the corresponding code from 4.1. Simultaneously fixed bug #5333 reported for 4.1. The bug was due to the fact that field index in join structures was always set to 0 for const tables. --- mysql-test/r/key_primary.result | 2 +- mysql-test/r/null_key.result | 2 +- mysql-test/r/select.result | 16 ++++++++++++++++ mysql-test/t/select.test | 21 +++++++++++++++++++++ sql/sql_select.cc | 11 ++++++++++- 5 files changed, 49 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/key_primary.result b/mysql-test/r/key_primary.result index 87289f1cf54..3216ead667b 100644 --- a/mysql-test/r/key_primary.result +++ b/mysql-test/r/key_primary.result @@ -13,7 +13,7 @@ t1 AB% describe select * from t1 where t1="ABC"; table type possible_keys key key_len ref rows Extra -t1 const PRIMARY PRIMARY 3 const 1 +t1 const PRIMARY PRIMARY 3 const 1 Using index describe select * from t1 where t1="ABCD"; Comment Impossible WHERE noticed after reading const tables diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 009a3e06eb2..41b0ae26617 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -12,7 +12,7 @@ table type possible_keys key key_len ref rows Extra t1 ref a,b a 9 const,const 1 Using where; Using index explain select * from t1 where a=2 and b = 2; table type possible_keys key key_len ref rows Extra -t1 const a,b a 9 const,const 1 +t1 const a,b a 9 const,const 1 Using index explain select * from t1 where a<=>b limit 2; table type possible_keys key key_len ref rows Extra t1 index NULL a 9 NULL 12 Using where; Using index diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 206fa507615..ce5ea94a08e 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2327,3 +2327,19 @@ select * from t2,t3 where t2.s = t3.s; s s two two drop table t1, t2, t3; +CREATE TABLE t1 ( +i int(11) NOT NULL default '0', +c char(10) NOT NULL default '', +PRIMARY KEY (i), +UNIQUE KEY c (c) +) TYPE=MyISAM; +INSERT INTO t1 VALUES (1,'a'); +INSERT INTO t1 VALUES (2,'b'); +INSERT INTO t1 VALUES (3,'c'); +EXPLAIN SELECT i FROM t1 WHERE i=1; +table type possible_keys key key_len ref rows Extra +t1 const PRIMARY PRIMARY 4 const 1 Using index +EXPLAIN SELECT i FROM t1 WHERE i=1; +table type possible_keys key key_len ref rows Extra +t1 const PRIMARY PRIMARY 4 const 1 Using index +DROP TABLE t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 7cb157f194e..dae44159683 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1874,3 +1874,24 @@ select * from t3 where s = 'one'; select * from t1,t2 where t1.s = t2.s; select * from t2,t3 where t2.s = t3.s; drop table t1, t2, t3; + +# +# Covering index is mentioned in EXPLAIN output for const tables (bug #5333) +# + +CREATE TABLE t1 ( + i int(11) NOT NULL default '0', + c char(10) NOT NULL default '', + PRIMARY KEY (i), + UNIQUE KEY c (c) +) TYPE=MyISAM; + +INSERT INTO t1 VALUES (1,'a'); +INSERT INTO t1 VALUES (2,'b'); +INSERT INTO t1 VALUES (3,'c'); + +EXPLAIN SELECT i FROM t1 WHERE i=1; + +EXPLAIN SELECT i FROM t1 WHERE i=1; + +DROP TABLE t1; \ No newline at end of file diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 882f345a1ca..d2b9f9d4588 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4901,6 +4901,15 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) } else { + if (!table->key_read && + (table->used_keys & ((key_map) 1 << tab->ref.key)) && + !table->no_keyread && + (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY) + { + table->key_read=1; + table->file->extra(HA_EXTRA_KEYREAD); + tab->index= tab->ref.key; + } if ((error=join_read_const(tab))) { tab->info="unique row not found"; @@ -7617,7 +7626,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, sprintf(buff3,"%.0f",join->best_positions[i].records_read); item_list.push_back(new Item_string(buff3,strlen(buff3))); my_bool key_read=table->key_read; - if (tab->type == JT_NEXT && + if ((tab->type == JT_NEXT || tab->type == JT_CONST) && ((table->used_keys & ((key_map) 1 << tab->index)))) key_read=1; From 3c85a363e596d23450511362b357fd2a76f0c13b Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Fri, 3 Sep 2004 19:26:11 +0500 Subject: [PATCH 013/143] A fix (bug #2631: mlockall called after dropping root permissions). --- sql/mysqld.cc | 124 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 87 insertions(+), 37 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 670e6a5a63e..06599cf0ea7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -414,6 +414,7 @@ char mysql_real_data_home[FN_REFLEN], max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file; char *language_ptr= language; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; +struct passwd *user_info; #ifndef EMBEDDED_LIBRARY bool mysql_embedded=0; #else @@ -1028,27 +1029,26 @@ static void set_ports() } } -/* Change to run as another user if started with --user */ -static void set_user(const char *user) +static struct passwd *check_user(const char *user) { -#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) - struct passwd *ent; +#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) + struct passwd *user_info; uid_t user_id= geteuid(); - - // don't bother if we aren't superuser + + // Don't bother if we aren't superuser if (user_id) { if (user) { - /* Don't give a warning, if real user is same as given with --user */ - struct passwd *user_info= getpwnam(user); + // Don't give a warning, if real user is same as given with --user + user_info= getpwnam(user); if ((!user_info || user_id != user_info->pw_uid) && - global_system_variables.log_warnings) - fprintf(stderr, - "Warning: One can only use the --user switch if running as root\n"); + global_system_variables.log_warnings) + fprintf(stderr, + "Warning: One can only use the --user switch if running as root\n"); } - return; + return NULL; } if (!user) { @@ -1057,38 +1057,52 @@ static void set_user(const char *user) fprintf(stderr,"Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n"); unireg_abort(1); } - return; + return NULL; } if (!strcmp(user,"root")) - return; // Avoid problem with dynamic libraries - - uid_t uid; - if (!(ent = getpwnam(user))) + return NULL; // Avoid problem with dynamic libraries + if (!(user_info= getpwnam(user))) { - // allow a numeric uid to be used + // Allow a numeric uid to be used const char *pos; - for (pos=user; isdigit(*pos); pos++) ; - if (*pos) // Not numeric id - { - fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user); - unireg_abort(1); - } - uid=atoi(user); // Use numberic uid + for (pos= user; isdigit(*pos); pos++); + if (*pos) // Not numeric id + goto err; + if (!(user_info= getpwuid(atoi(user)))) + goto err; + else + return user_info; } else { -#ifdef HAVE_INITGROUPS - initgroups((char*) user,ent->pw_gid); -#endif - if (setgid(ent->pw_gid) == -1) - { - sql_perror("setgid"); - unireg_abort(1); - } - uid=ent->pw_uid; + return user_info; } - if (setuid(uid) == -1) +err: + fprintf(stderr, + "Fatal error: Can't change to run as user '%s'. Please check that the user exists!\n", + user); + unireg_abort(1); + return NULL; +#else + return NULL; +#endif +} + + +static void set_user(const char *user, struct passwd *user_info) +{ +#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) + DBUG_ASSERT(user_info); +#ifdef HAVE_INITGROUPS + initgroups((char*) user, user_info->pw_gid); +#endif + if (setgid(user_info->pw_gid) == -1) + { + sql_perror("setgid"); + unireg_abort(1); + } + if (setuid(user_info->pw_uid) == -1) { sql_perror("setuid"); unireg_abort(1); @@ -1096,6 +1110,24 @@ static void set_user(const char *user) #endif } +static void set_effective_user(struct passwd *user_info) +{ +#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) + DBUG_ASSERT(user_info); + if (setegid(user_info->pw_gid) == -1) + { + sql_perror("setegid"); + unireg_abort(1); + } + if (seteuid(user_info->pw_uid) == -1) + { + sql_perror("seteuid"); + unireg_abort(1); + } +#endif +} + + /* Change root user if started with --chroot */ static void set_root(const char *path) @@ -1171,7 +1203,18 @@ static void server_init(void) unireg_abort(1); } } - set_user(mysqld_user); // Works also with mysqld_user==NULL + + if ((user_info= check_user(mysqld_user))) + { +#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) + if (locked_in_memory && !getuid()) + set_effective_user(user_info); + else + set_user(mysqld_user, user_info); +#else + set_user(mysqld_user, user_info); +#endif + } #ifdef __NT__ /* create named pipe */ @@ -2466,8 +2509,13 @@ You should consider changing lower_case_table_names to 1 or 2", } ha_key_cache(); #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) - if (locked_in_memory && !geteuid()) + if (locked_in_memory && !getuid()) { + if (seteuid(0) == -1) + { // this should never happen + sql_perror("seteuid"); + unireg_abort(1); + } if (mlockall(MCL_CURRENT)) { if (global_system_variables.log_warnings) @@ -2475,6 +2523,8 @@ You should consider changing lower_case_table_names to 1 or 2", } else locked_in_memory=1; + if (user_info) + set_user(mysqld_user, user_info); } #else locked_in_memory=0; From f91ca0bd660bd1d2449a3d5b3141b1a4d7dfb443 Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Fri, 3 Sep 2004 19:59:29 +0500 Subject: [PATCH 014/143] A fix (Bug #4980: union statement with () union () order by produces wrong explain). --- mysql-test/r/union.result | 9 ++++++++- mysql-test/t/union.test | 9 +++++++++ sql/sql_union.cc | 4 ++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 4b9555c334b..8f33bc4c316 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l table type possible_keys key key_len ref rows Extra t1 ALL NULL NULL NULL NULL 4 t2 ALL NULL NULL NULL NULL 4 Using filesort -t1 ALL NULL NULL NULL NULL 4 (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; a b 1 a @@ -424,8 +423,16 @@ create table t1 select a from t1 union select a from t2; INSERT TABLE 't1' isn't allowed in FROM table list select a from t1 union select a from t2 order by t2.a; Unknown column 't2.a' in 'ORDER BY' +drop table t1; drop table t1,t2; select length(version()) > 1 as `*` UNION select 2; * 1 2 +create table t1 (a int); +insert into t1 values (0), (3), (1), (2); +explain (select * from t1) union (select * from t1) order by a; +table type possible_keys key key_len ref rows Extra +t1 ALL NULL NULL NULL NULL 4 +t1 ALL NULL NULL NULL NULL 4 +drop table t1; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index c978aef9ce0..65b062d663f 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -228,6 +228,7 @@ create temporary table t1 select a from t1 union select a from t2; create table t1 select a from t1 union select a from t2; --error 1054 select a from t1 union select a from t2 order by t2.a; +drop table t1; # Drop temporary table drop table t1,t2; # @@ -236,3 +237,11 @@ drop table t1,t2; select length(version()) > 1 as `*` UNION select 2; +# +# Bug #4980: problem with explain +# + +create table t1 (a int); +insert into t1 values (0), (3), (1), (2); +explain (select * from t1) union (select * from t1) order by a; +drop table t1; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8088737c0de..f79ff7967db 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -148,6 +148,10 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) { ha_rows records_at_start; lex->select=sl; +#if MYSQL_VERSION_ID < 40100 + if (describe && sl->linkage == NOT_A_SELECT) + break; // Skip extra item in case of 'explain' +#endif /* Don't use offset for the last union if there is no braces */ if (sl != lex_sl) { From 38f462ae6f8ae71157520b27abf3f7abc6858eff Mon Sep 17 00:00:00 2001 From: "paul@kite-hub.kitebird.com" <> Date: Fri, 3 Sep 2004 10:56:55 -0500 Subject: [PATCH 015/143] sql_yacc.yy: Allow FROM or IN in SHOW KEYS, as in other SHOW statements. --- sql/sql_yacc.yy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2199a0c8be5..6b073db2e36 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2917,7 +2917,7 @@ show_param: lex->select->select_limit= lex->thd->variables.select_limit; lex->select->offset_limit= 0L; } limit_clause - | keys_or_index FROM table_ident opt_db + | keys_or_index from_or_in table_ident opt_db { Lex->sql_command= SQLCOM_SHOW_KEYS; if ($4) From 7ac525fc1b5b7c9097274ee539572ede892636c6 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Sun, 5 Sep 2004 11:27:31 +0200 Subject: [PATCH 016/143] union.test: drop table added --- .bzrignore | 1 + mysql-test/r/union.result | 1 + mysql-test/t/union.test | 1 + 3 files changed, 3 insertions(+) diff --git a/.bzrignore b/.bzrignore index 8583b7ef437..1d14c09a602 100644 --- a/.bzrignore +++ b/.bzrignore @@ -545,3 +545,4 @@ vio/test-sslserver vio/viotest-ssl scripts/make_win_binary_distribution EXCEPTIONS-CLIENT +support-files/my-innodb-heavy-4G.cnf diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 4b9555c334b..45866cdf495 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -420,6 +420,7 @@ a (SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1; Wrong usage/placement of 'SQL_CALC_FOUND_ROWS' create temporary table t1 select a from t1 union select a from t2; +drop table t1; create table t1 select a from t1 union select a from t2; INSERT TABLE 't1' isn't allowed in FROM table list select a from t1 union select a from t2 order by t2.a; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index c978aef9ce0..2bcd50b11de 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -224,6 +224,7 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1; (SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1; create temporary table t1 select a from t1 union select a from t2; +drop table t1; --error 1093 create table t1 select a from t1 union select a from t2; --error 1054 From 92be15da12144dedd798dbe63830154834be03bd Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Mon, 6 Sep 2004 16:48:11 +0500 Subject: [PATCH 017/143] A fix (bug #2205 USE database doesn't work after DROP database + CREATE database) (Jani's CS 1.1675 04/01/05 21:45:14 was adapted an aplied). --- client/mysql.cc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 154695aa9e5..1858699e8da 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2200,8 +2200,9 @@ static int com_source(String *buffer, char *line) static int com_use(String *buffer __attribute__((unused)), char *line) { - char *tmp; - char buff[256]; + char *tmp, buff[FN_REFLEN + 1]; + MYSQL_RES *res; + MYSQL_ROW row; while (isspace(*line)) line++; @@ -2214,6 +2215,30 @@ com_use(String *buffer __attribute__((unused)), char *line) put_info("USE must be followed by a database name",INFO_ERROR); return 0; } + /* + We need to recheck the current database, because it may change + under our feet, for example if DROP DATABASE or RENAME DATABASE + (latter one not yet available by the time the comment was written) + */ + current_db= 0; // Let's reset current_db, assume it's gone + /* + We don't care about in case of an error below because current_db + was just set to 0. + */ + if (!mysql_query(&mysql, "SELECT DATABASE()") && + (res= mysql_use_result(&mysql))) + { + row= mysql_fetch_row(res); + if (row[0] && + (!current_db || cmp_database(current_db, row[0]))) + { + my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); + current_db= my_strdup(row[0], MYF(MY_WME)); + } + (void) mysql_fetch_row(res); // Read eof + mysql_free_result(res); + } + if (!current_db || cmp_database(current_db,tmp)) { if (one_database) From 130d2fd57f4903fdc0d215f154f72eea6953840a Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Mon, 6 Sep 2004 22:20:40 +0200 Subject: [PATCH 018/143] bug#5389 merge.test fails on qnx - uninitalized variable in myrg_open() --- myisammrg/myrg_open.c | 28 ++++++++++++++-------------- mysql-test/r/union.result | 1 - mysql-test/t/union.test | 1 - sql/log.cc | 20 +++++++++++++------- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index 4c6ffb98ad5..a59ccb7d966 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -34,14 +34,17 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { int save_errno,errpos=0; uint files=0,i,dir_length,length,key_parts; - ulonglong file_offset; + ulonglong file_offset=0; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; MYRG_INFO *m_info=0; File fd; IO_CACHE file; MI_INFO *isam=0; + uint found_merge_insert_method= 0; DBUG_ENTER("myrg_open"); + LINT_INIT(key_parts); + bzero((char*) &file,sizeof(file)); if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4), O_RDONLY | O_SHARE,MYF(0))) < 0) @@ -69,10 +72,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) continue; /* Skip empty lines */ if (buff[0] == '#') { - if( !strncmp(buff+1,"INSERT_METHOD=",14)) + if (!strncmp(buff+1,"INSERT_METHOD=",14)) { /* Lookup insert method */ int tmp=find_type(buff+15,&merge_insert_method,2); - m_info->merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); + found_merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); } continue; /* Skip comments */ } @@ -84,8 +87,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) VOID(cleanup_dirname(buff,name_buff)); } if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) - goto err; - if (!m_info) + goto err; + if (!m_info) /* First file */ { key_parts=isam->s->base.key_parts; if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) + @@ -97,15 +100,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { m_info->open_tables=(MYRG_TABLE *) (m_info+1); m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files); + m_info->tables= files; + files= 0; } - else - { - m_info->open_tables=0; - m_info->rec_per_key_part=0; - } - m_info->tables=files; m_info->reclength=isam->s->base.reclength; - file_offset=files=0; errpos=3; } m_info->open_tables[files].table= isam; @@ -122,14 +120,16 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) m_info->del+= isam->state->del; m_info->data_file_length+= isam->state->data_file_length; for (i=0; i < key_parts; i++) - m_info->rec_per_key_part[i]+=isam->s->state.rec_per_key_part[i] / m_info->tables; + m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] / + m_info->tables); } if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO), - MYF(MY_WME|MY_ZEROFILL)))) + MYF(MY_WME | MY_ZEROFILL)))) goto err; /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */ m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA); + m_info->merge_insert_method= found_merge_insert_method; if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L) { diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 79c589774d8..0db18b090bc 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -424,7 +424,6 @@ create table t1 select a from t1 union select a from t2; INSERT TABLE 't1' isn't allowed in FROM table list select a from t1 union select a from t2 order by t2.a; Unknown column 't2.a' in 'ORDER BY' -drop table t1; drop table t1,t2; select length(version()) > 1 as `*` UNION select 2; * diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index e55cb3ea272..eb2d8dd6efa 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -229,7 +229,6 @@ drop table t1; create table t1 select a from t1 union select a from t2; --error 1054 select a from t1 union select a from t2 order by t2.a; -drop table t1; # Drop temporary table drop table t1,t2; # diff --git a/sql/log.cc b/sql/log.cc index 55ef2e72960..151d613f637 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1221,7 +1221,7 @@ bool MYSQL_LOG::write(Log_event* event_info) if (e.write(file)) goto err; } -#if MYSQL_VERSION_ID < 40100 +#if MYSQL_VERSION_ID < 40100 if (thd->variables.convert_set) { Query_log_event e(thd, "SET CHARACTER SET DEFAULT", 25, 0); @@ -1761,15 +1761,21 @@ void print_buffer_to_file(enum loglevel level, const char *buffer) skr=time(NULL); localtime_r(&skr, &tm_tmp); start=&tm_tmp; +#if MYSQL_VERSION_ID > 40100 fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n", - start->tm_year % 100, - start->tm_mon+1, - start->tm_mday, - start->tm_hour, - start->tm_min, - start->tm_sec, +#else + fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d %s\n", +#endif + start->tm_year % 100, + start->tm_mon+1, + start->tm_mday, + start->tm_hour, + start->tm_min, + start->tm_sec, +#if MYSQL_VERSION_ID > 40100 (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ? "WARNING" : "INFORMATION"), +#endif buffer); fflush(stderr); From 01ad1bb569c3361ae1b7935022122cdd2f2a0358 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Mon, 6 Sep 2004 22:30:16 +0200 Subject: [PATCH 019/143] Dependency fix. We observed that doing any change to class THD in sql_class.h resulted in mysqld going crazy (parsing errors, query cache errors in query_cache.test). This is because sql_yacc.cc depends on several .h files but those were not listed in the dependencies of sql_yacc.o. The present patch does fix the issue; but my auto*-expert colleagues may have a better one. --- sql/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index 0a664a120a5..0fc81a48c63 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -108,7 +108,7 @@ gen_lex_hash.o: gen_lex_hash.cc lex.h sql_yacc.cc: sql_yacc.yy sql_yacc.h: sql_yacc.yy -sql_yacc.o: sql_yacc.cc sql_yacc.h +sql_yacc.o: sql_yacc.cc sql_yacc.h $(noinst_HEADERS) @echo "Note: The following compile may take a long time." @echo "If it fails, re-run configure with --with-low-memory" $(CXXCOMPILE) $(LM_CFLAGS) -c $< From 99444c3311ff822fed4146102ad54bec9a6ce44c Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Mon, 6 Sep 2004 22:47:26 +0200 Subject: [PATCH 020/143] Replacing class Disable_binlog by macros. Patch already approved by Monty. --- sql/log.cc | 16 ---------------- sql/sql_class.h | 21 --------------------- sql/sql_table.cc | 47 ++++++++++++++++++++++++++++------------------- 3 files changed, 28 insertions(+), 56 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 55ef2e72960..a864943edf8 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1682,22 +1682,6 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg) } -Disable_binlog::Disable_binlog(THD *thd_arg) : - thd(thd_arg), - save_options(thd_arg->options), save_master_access(thd_arg->master_access) -{ - thd_arg->options&= ~OPTION_BIN_LOG; - thd_arg->master_access|= SUPER_ACL; // unneeded in 4.1 -}; - - -Disable_binlog::~Disable_binlog() -{ - thd->options= save_options; - thd->master_access= save_master_access; -} - - /* Check if a string is a valid number diff --git a/sql/sql_class.h b/sql/sql_class.h index 30947041b7d..d362a90b7df 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -638,27 +638,6 @@ public: #define SYSTEM_THREAD_SLAVE_IO 2 #define SYSTEM_THREAD_SLAVE_SQL 4 -/* - Disables binary logging for one thread, and resets it back to what it was - before being disabled. - Some functions (like the internal mysql_create_table() when it's called by - mysql_alter_table()) must NOT write to the binlog (binlogging is done at the - at a later stage of the command already, and must be, for locking reasons); - so we internally disable it temporarily by creating the Disable_binlog - object and reset the state by destroying the object (don't forget that! or - write code so that the object gets automatically destroyed when leaving a - block, see example in sql_table.cc). -*/ -class Disable_binlog { -private: - THD *thd; - ulong save_options; - ulong save_master_access; -public: - Disable_binlog(THD *thd_arg); - ~Disable_binlog(); -}; - /* Used to hold information about file and file structure in exchainge via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 96eebd98ac3..c712167bfc1 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -30,6 +30,16 @@ #include #endif +#include "sql_acl.h" // for SUPER_ACL +# define tmp_disable_binlog(A) \ + ulong save_options= (A)->options, save_master_access= (A)->master_access; \ + (A)->options&= ~OPTION_BIN_LOG; \ + (A)->master_access|= SUPER_ACL; /* unneeded in 4.1 */ + +#define reenable_binlog(A) \ + (A)->options= save_options; \ + (A)->master_access= save_master_access; + extern HASH open_cache; static const char *primary_key_name="PRIMARY"; @@ -840,9 +850,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, MYSQL_LOCK **lock) { TABLE tmp_table; // Used during 'create_field()' - TABLE *table; + TABLE *table= 0; tmp_table.table_name=0; - Disable_binlog disable_binlog(thd); DBUG_ENTER("create_table_from_items"); /* Add selected items to field list */ @@ -872,23 +881,25 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, extra_fields->push_back(cr_field); } /* create and lock table */ - /* QQ: This should be done atomic ! */ - /* We don't log the statement, it will be logged later */ - if (mysql_create_table(thd,db,name,create_info,*extra_fields, - *keys,0)) - DBUG_RETURN(0); + /* QQ: create and open should be done atomic ! */ /* + We don't log the statement, it will be logged later. If this is a HEAP table, the automatic DELETE FROM which is written to the binlog when a HEAP table is opened for the first time since startup, must not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we don't want to delete from it) 2) it would be written before the CREATE - TABLE, which is a wrong order. So we keep binary logging disabled. + TABLE, which is a wrong order. So we keep binary logging disabled when we + open_table(). */ - if (!(table=open_table(thd,db,name,name,(bool*) 0))) + tmp_disable_binlog(thd); + if (!mysql_create_table(thd,db,name,create_info,*extra_fields,*keys,0)) { - quick_rm_table(create_info->db_type,db,table_case_name(create_info,name)); - DBUG_RETURN(0); + if (!(table=open_table(thd,db,name,name,(bool*) 0))) + quick_rm_table(create_info->db_type,db,table_case_name(create_info,name)); } + reenable_binlog(thd); + if (!table) + DBUG_RETURN(0); table->reginfo.lock_type=TL_WRITE; if (!((*lock)=mysql_lock_tables(thd,&table,1))) { @@ -1925,14 +1936,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, else create_info->data_file_name=create_info->index_file_name=0; { - /* - We don't log the statement, it will be logged later. Using a block so - that disable_binlog is deleted when we leave it in either way. - */ - Disable_binlog disable_binlog(thd); - if ((error=mysql_create_table(thd, new_db, tmp_name, - create_info, - create_list,key_list,1))) + /* We don't log the statement, it will be logged later. */ + tmp_disable_binlog(thd); + int error= mysql_create_table(thd, new_db, tmp_name, + create_info,create_list,key_list,1); + reenable_binlog(thd); + if (error) DBUG_RETURN(error); } if (table->tmp_table) From c0aba1ab98e81eeb6ae24501dd1abcbe6bb9efa7 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Mon, 6 Sep 2004 22:48:42 +0200 Subject: [PATCH 021/143] Bug #5413 mysqlcheck segfaults when user has to few permissions --- client/mysqlcheck.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 1c5638f3c52..8764611adf4 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -413,18 +413,18 @@ static int process_all_tables_in_db(char *database) LINT_INIT(res); if (use_db(database)) return 1; - if (!(mysql_query(sock, "SHOW TABLES") || - (res = mysql_store_result(sock)))) + if (mysql_query(sock, "SHOW TABLES") || + !((res= mysql_store_result(sock)))) return 1; if (opt_all_in_1) { - /* + /* We need table list in form `a`, `b`, `c` that's why we need 4 more chars added to to each table name space is for more readable output in logs and in case of error */ - + char *tables, *end; uint tot_length = 0; From de5d1e780ebb5dab1d06a7788709bbccb67da0ed Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Mon, 6 Sep 2004 23:20:33 +0200 Subject: [PATCH 022/143] Fix of previous push. --- sql/sql_table.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c712167bfc1..e2e186abb0d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1938,8 +1938,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, { /* We don't log the statement, it will be logged later. */ tmp_disable_binlog(thd); - int error= mysql_create_table(thd, new_db, tmp_name, - create_info,create_list,key_list,1); + error= mysql_create_table(thd, new_db, tmp_name, + create_info,create_list,key_list,1); reenable_binlog(thd); if (error) DBUG_RETURN(error); From 56b4c316333399b9290369dee399dadd1eb96297 Mon Sep 17 00:00:00 2001 From: "jani@rhols221.adsl.netsonic.fi" <> Date: Tue, 7 Sep 2004 11:40:27 +0300 Subject: [PATCH 023/143] Fixed Bug#3645, "PROCEDURE ANALYSE() recommends illegal FLOAT columns". --- sql/sql_analyse.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 3847849d6a7..0723c274a17 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -810,6 +810,13 @@ void field_real::get_opt_type(String *answer, if (min_arg >= 0) answer->append(" UNSIGNED"); } + else if (item->decimals == NOT_FIXED_DEC) + { + if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) + answer->append("FLOAT", 5); + else + answer->append("DOUBLE", 6); + } else { if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) From 06954e0f6d06357820cd43181f17510778c7e662 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 7 Sep 2004 11:15:23 +0200 Subject: [PATCH 024/143] A new test for the fix for BUG#4500 ("SET CHARACTER SET replicates incorrectly"). As I cannot be 100% sure that there won't be issues with some of our exotic platforms (who knows if the charset of will play fair?), I'll send an email to the build guys. Well, this holds if bk does not crash on binary chars of this cset. --- mysql-test/r/rpl_set_charset.result | 51 +++++++++++++++++++++++++++++ mysql-test/t/rpl_set_charset.test | 40 ++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 mysql-test/r/rpl_set_charset.result create mode 100644 mysql-test/t/rpl_set_charset.test diff --git a/mysql-test/r/rpl_set_charset.result b/mysql-test/r/rpl_set_charset.result new file mode 100644 index 00000000000..b2bfa3678a9 --- /dev/null +++ b/mysql-test/r/rpl_set_charset.result @@ -0,0 +1,51 @@ +slave stop; +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; +slave start; +drop database if exists mysqltest1; +create database mysqltest1 /*!40100 character set latin2 */; +use mysqltest1; +drop table if exists t1; +create table t1 (a varchar(255) character set latin2, b varchar(4)); +SET CHARACTER SET cp1250_latin2; +INSERT INTO t1 VALUES ('ŠŒŽ','80'); +INSERT INTO t1 VALUES ('šœžŸ','90'); +INSERT INTO t1 VALUES ('£¥ª¯','A0'); +INSERT INTO t1 VALUES ('³¹º¼¾¿','B0'); +INSERT INTO t1 VALUES ('ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ','C0'); +INSERT INTO t1 VALUES ('ÐÑÒÓÔÕÖרÙÚÛÜÝÞß','D0'); +INSERT INTO t1 VALUES ('àáâãäåæçèéêëìíîï','E0'); +INSERT INTO t1 VALUES ('ðñòóôõö÷øùúûüýþÿ','F0'); +select "--- on master ---"; +--- on master --- +--- on master --- +select hex(a),b from t1 order by b; +hex(a) b +A9A6ABAEAC 80 +B9B6BBBEBC 90 +A3A1AAAF A0 +B3B1BAA5B5BF B0 +C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0 +D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0 +E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0 +F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0 +show binlog events from 1979; +Log_name Pos Event_type Server_id Orig_log_pos Info +master-bin.001 1979 Query 1 1979 use `mysqltest1`; SET CHARACTER SET DEFAULT +use mysqltest1; +select "--- on slave ---"; +--- on slave --- +--- on slave --- +select hex(a),b from t1 order by b; +hex(a) b +A9A6ABAEAC 80 +B9B6BBBEBC 90 +A3A1AAAF A0 +B3B1BAA5B5BF B0 +C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0 +D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0 +E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0 +F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0 +drop table t1; diff --git a/mysql-test/t/rpl_set_charset.test b/mysql-test/t/rpl_set_charset.test new file mode 100644 index 00000000000..6aa864b1008 --- /dev/null +++ b/mysql-test/t/rpl_set_charset.test @@ -0,0 +1,40 @@ +source include/master-slave.inc; +--disable_warnings +drop database if exists mysqltest1; +# 4.1 bases its conversion on the db's charset, +# while 4.0 uses the part of "SET CHARACTER SET" after "_". +# So for 4.1 we add a clause to CREATE DATABASE. +create database mysqltest1 /*!40100 character set latin2 */; +use mysqltest1; +drop table if exists t1; +--enable_warnings +create table t1 (a varchar(255) character set latin2, b varchar(4)); +SET CHARACTER SET cp1250_latin2; +INSERT INTO t1 VALUES ('ŠŒŽ','80'); +INSERT INTO t1 VALUES ('šœžŸ','90'); +INSERT INTO t1 VALUES ('£¥ª¯','A0'); +INSERT INTO t1 VALUES ('³¹º¼¾¿','B0'); +INSERT INTO t1 VALUES ('ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ','C0'); +INSERT INTO t1 VALUES ('ÐÑÒÓÔÕÖרÙÚÛÜÝÞß','D0'); +INSERT INTO t1 VALUES ('àáâãäåæçèéêëìíîï','E0'); +INSERT INTO t1 VALUES ('ðñòóôõö÷øùúûüýþÿ','F0'); +select "--- on master ---"; +select hex(a),b from t1 order by b; +# It's complicated to verify that the charset is reset to default in +# the binlog after each query, except by checking the binlog. When you +# merge this into 4.1/5.0, the 1979 will have to be changed; all you have +# to do is read the var/log/master-bin.0*01 with mysqlbinlog, verify +# that a SET CHARACTER SET DEFAULT is just after the last INSERT, and +# replace 1979 by its position (the "# at" line above the SET). +show binlog events from 1979; +save_master_pos; +connection slave; +sync_with_master; +use mysqltest1; +select "--- on slave ---"; +select hex(a),b from t1 order by b; +connection master; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; From 00830a11fc7febcca4d95439b70d6526e9ee192c Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Tue, 7 Sep 2004 14:24:47 +0500 Subject: [PATCH 025/143] A fix (Bug #5432: Is this a leak in mysql console client?) --- client/mysql.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 1858699e8da..3cc8b41af66 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2220,7 +2220,9 @@ com_use(String *buffer __attribute__((unused)), char *line) under our feet, for example if DROP DATABASE or RENAME DATABASE (latter one not yet available by the time the comment was written) */ - current_db= 0; // Let's reset current_db, assume it's gone + /* Let's reset current_db, assume it's gone */ + my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); + current_db= 0; /* We don't care about in case of an error below because current_db was just set to 0. @@ -2229,10 +2231,8 @@ com_use(String *buffer __attribute__((unused)), char *line) (res= mysql_use_result(&mysql))) { row= mysql_fetch_row(res); - if (row[0] && - (!current_db || cmp_database(current_db, row[0]))) + if (row[0]) { - my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); current_db= my_strdup(row[0], MYF(MY_WME)); } (void) mysql_fetch_row(res); // Read eof From 001dfd3d484534b9c36988f193c13620e7ca249e Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 7 Sep 2004 13:36:27 +0200 Subject: [PATCH 026/143] cleanup --- mysql-test/r/rpl_set_charset.result | 1 + mysql-test/t/rpl_set_charset.test | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mysql-test/r/rpl_set_charset.result b/mysql-test/r/rpl_set_charset.result index b2bfa3678a9..7297d80865b 100644 --- a/mysql-test/r/rpl_set_charset.result +++ b/mysql-test/r/rpl_set_charset.result @@ -49,3 +49,4 @@ D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0 E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0 F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0 drop table t1; +drop database mysqltest1; diff --git a/mysql-test/t/rpl_set_charset.test b/mysql-test/t/rpl_set_charset.test index 6aa864b1008..dcfc11bf25e 100644 --- a/mysql-test/t/rpl_set_charset.test +++ b/mysql-test/t/rpl_set_charset.test @@ -38,3 +38,5 @@ drop table t1; save_master_pos; connection slave; sync_with_master; +connection master; +drop database mysqltest1; From 707def6fd0914e673cd9bde1271a59de2af5ef2c Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 7 Sep 2004 13:48:38 +0200 Subject: [PATCH 027/143] better fix for bug#5001 --- scripts/mysqld_safe.sh | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 8ad2ee1df4d..b9e7ce21f79 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -322,36 +322,26 @@ do # but should work for the rest of the servers. # The only thing is ps x => redhat 5 gives warnings when using ps -x. # kill -9 is used or the process won't react on the kill. - if test -n "$mysql_tcp_port" - then - numofproces=`ps xa | grep -v "grep" | grep $ledir/$MYSQLD| grep -c "port=$mysql_tcp_port"` - else - numofproces=`ps xa | grep -v "grep" | grep -c $ledir/$MYSQLD` - fi + numofproces=`ps xa | grep -v "grep" | grep "$ledir/$MYSQLD\>" | grep -c "pid-file=$pid_file"` echo -e "\nNumber of processes running now: $numofproces" | tee -a $err_log I=1 while test "$I" -le "$numofproces" do - if test -n "$mysql_tcp_port" - then - PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "port=$mysql_tcp_port" | sed -n '$p'` - else - PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | sed -n '$p'` - fi + PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "pid-file=$pid_file" | sed -n '$p'` - for T in $PROC - do - break - done - # echo "TEST $I - $T **" - if kill -9 $T - then - echo "$MYSQLD process hanging, pid $T - killed" | tee -a $err_log - else - break - fi - I=`expr $I + 1` + for T in $PROC + do + break + done + # echo "TEST $I - $T **" + if kill -9 $T + then + echo "$MYSQLD process hanging, pid $T - killed" | tee -a $err_log + else + break + fi + I=`expr $I + 1` done fi echo "`date +'%y%m%d %H:%M:%S'` mysqld restarted" | tee -a $err_log @@ -359,3 +349,4 @@ done echo "`date +'%y%m%d %H:%M:%S'` mysqld ended" | tee -a $err_log echo "" | tee -a $err_log + From 3dd35e1ab67cf6213b96bf9cd6ad2917ef412591 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 7 Sep 2004 14:20:48 +0200 Subject: [PATCH 028/143] clean up at end of test (thanks serg) --- mysql-test/r/rpl_set_charset.result | 1 - mysql-test/t/rpl_set_charset.test | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/mysql-test/r/rpl_set_charset.result b/mysql-test/r/rpl_set_charset.result index 7297d80865b..9c7ea73c741 100644 --- a/mysql-test/r/rpl_set_charset.result +++ b/mysql-test/r/rpl_set_charset.result @@ -48,5 +48,4 @@ C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0 D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0 E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0 F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0 -drop table t1; drop database mysqltest1; diff --git a/mysql-test/t/rpl_set_charset.test b/mysql-test/t/rpl_set_charset.test index dcfc11bf25e..bd68ce17bbc 100644 --- a/mysql-test/t/rpl_set_charset.test +++ b/mysql-test/t/rpl_set_charset.test @@ -34,9 +34,7 @@ use mysqltest1; select "--- on slave ---"; select hex(a),b from t1 order by b; connection master; -drop table t1; +drop database mysqltest1; save_master_pos; connection slave; sync_with_master; -connection master; -drop database mysqltest1; From 168e4c9c6b476e7153860dc66ef8e18beabccd14 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 7 Sep 2004 14:57:54 +0200 Subject: [PATCH 029/143] when we update thd->db in replication, it's safer to update thd->db_length too. This does not fix any known bug, but is still a good idea. --- sql/log_event.cc | 14 ++++++++++---- sql/slave.cc | 13 +++++++++---- sql/sql_db.cc | 9 +++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 5526795c9d1..f707eabebd5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1806,7 +1806,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) { int expected_error, actual_error= 0; init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size,0); - thd->db= (char*) rewrite_db(db); + thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed /* InnoDB internally stores the master log position it has processed so far; @@ -1836,6 +1836,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) { thd->set_time((time_t)when); thd->current_tablenr = 0; + /* + We cannot use db_len from event to fill thd->db_length, because + rewrite_db() may have changed db. + */ + thd->db_length= thd->db ? strlen(thd->db) : 0; thd->query_length= q_len; thd->query= (char *) query; VOID(pthread_mutex_lock(&LOCK_thread_count)); @@ -1930,7 +1935,7 @@ end: VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db= 0; // prevent db from being freed thd->query= 0; // just to be sure - thd->query_length= 0; + thd->query_length= thd->db_length =0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); close_thread_tables(thd); free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); @@ -1968,7 +1973,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { char *load_data_query= 0; init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size, 0); - thd->db= (char*) rewrite_db(db); + thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed DBUG_ASSERT(thd->query == 0); clear_all_errors(thd, rli); @@ -2001,6 +2006,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { thd->set_time((time_t)when); thd->current_tablenr = 0; + thd->db_length= thd->db ? strlen(thd->db) : 0; VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -2117,7 +2123,7 @@ Slave: load data infile on table '%s' at log position %s in log \ VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db= 0; thd->query= 0; - thd->query_length= 0; + thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); close_thread_tables(thd); if (load_data_query) diff --git a/sql/slave.cc b/sql/slave.cc index 4416a2544ef..18e0ec5929f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1124,6 +1124,7 @@ slaves can't replicate a 5.0 or newer master."; Used by fetch_master_table (used by LOAD TABLE tblname FROM MASTER and LOAD DATA FROM MASTER). Drops the table (if 'overwrite' is true) and recreates it from the dump. Honours replication inclusion/exclusion rules. + db must be non-zero (guarded by assertion). RETURN VALUES 0 success @@ -1134,8 +1135,8 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, const char* table_name, bool overwrite) { ulong packet_len = my_net_read(net); // read create table statement - char *query; - char* save_db; + char *query, *save_db; + uint32 save_db_length; Vio* save_vio; HA_CHECK_OPT check_opt; TABLE_LIST tables; @@ -1193,9 +1194,13 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, thd->proc_info = "Creating table from master dump"; // save old db in case we are creating in a different database save_db = thd->db; + save_db_length= thd->db_length; thd->db = (char*)db; + DBUG_ASSERT(thd->db); + thd->db_length= strlen(thd->db); mysql_parse(thd, thd->query, packet_len); // run create table thd->db = save_db; // leave things the way the were before + thd->db_length= save_db_length; thd->options = save_options; if (thd->query_error) @@ -2689,7 +2694,7 @@ err: IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety - thd->query_length = 0; + thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { @@ -2838,7 +2843,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ err: VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety - thd->query_length = 0; + thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->proc_info = "Waiting for slave mutex on exit"; pthread_mutex_lock(&rli->run_lock); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 3d877403813..c8874701aa1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -385,6 +385,15 @@ err: } +/* + Changes the current database. + + NOTES + Do as little as possible in this function, as it is not called for the + replication slave SQL thread (for that thread, setting of thd->db is done + in ::exec_event() methods of log_event.cc). +*/ + bool mysql_change_db(THD *thd,const char *name) { int length, db_length; From b0784773a75e39299bcd8c3aa1446d1cbd064715 Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Tue, 7 Sep 2004 10:03:46 -0700 Subject: [PATCH 030/143] select.test: Added newline at the end of file. --- mysql-test/t/select.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index dae44159683..03490360b35 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1894,4 +1894,4 @@ EXPLAIN SELECT i FROM t1 WHERE i=1; EXPLAIN SELECT i FROM t1 WHERE i=1; -DROP TABLE t1; \ No newline at end of file +DROP TABLE t1; From 7a845e43ad5b7a29431cfa4383e0785a84489416 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 8 Sep 2004 14:24:13 +0300 Subject: [PATCH 031/143] InnoDB: Update links to the user manual --- innobase/btr/btr0btr.c | 4 ++-- innobase/buf/buf0buf.c | 6 +++--- innobase/dict/dict0dict.c | 9 ++++++--- innobase/fsp/fsp0fsp.c | 6 +++--- innobase/log/log0log.c | 5 ++--- innobase/log/log0recv.c | 6 +++--- innobase/os/os0file.c | 31 +++++++++++++++++++------------ innobase/row/row0mysql.c | 20 ++++++++++++-------- innobase/ut/ut0dbg.c | 5 +++-- 9 files changed, 53 insertions(+), 39 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 81eb32467ad..d1ef1a77a9f 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -609,8 +609,8 @@ btr_page_get_father_for_rec( fputs( "InnoDB: You should dump + drop + reimport the table to fix the\n" "InnoDB: corruption. If the crash happens at the database startup, see\n" -"InnoDB: section 6.1 of http://www.innodb.com/ibman.php about forcing\n" -"InnoDB: recovery. Then dump + drop + reimport.\n", stderr); +"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html about\n" +"InnoDB: forcing recovery. Then dump + drop + reimport.\n", stderr); } ut_a(btr_node_ptr_get_child_page_no(node_ptr) == diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index b744430a76e..aea3932eda7 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1561,9 +1561,9 @@ buf_page_io_complete( "InnoDB: by dumping, dropping, and reimporting\n" "InnoDB: the corrupt table. You can use CHECK\n" "InnoDB: TABLE to scan your table for corruption.\n" - "InnoDB: Look also at section 6.1 of\n" - "InnoDB: http://www.innodb.com/ibman.php about\n" - "InnoDB: forcing recovery.\n", stderr); + "InnoDB: See also " + "http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" + "InnoDB: about forcing recovery.\n", stderr); if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { fputs( diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index ccaa5720c20..573b9ef49f1 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2020,7 +2020,8 @@ dict_foreign_error_report( fputs("\nThe index in the foreign key in table is ", file); ut_print_name(file, fk->foreign_index->name); fputs( -"See http://www.innodb.com/ibman.php for correct foreign key definition.\n", +"\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" +"for correct foreign key definition.\n", file); } mutex_exit(&dict_foreign_err_mutex); @@ -2856,7 +2857,8 @@ col_loop1: ut_print_name(ef, name); fprintf(ef, " where the columns appear\n" "as the first columns. Constraint:\n%s\n" -"See http://www.innodb.com/ibman.php for correct foreign key definition.\n", +"nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" +"for correct foreign key definition.\n", start_of_latest_foreign); mutex_exit(&dict_foreign_err_mutex); @@ -3121,7 +3123,8 @@ try_find_index: "Cannot find an index in the referenced table where the\n" "referenced columns appear as the first columns, or column types\n" "in the table and the referenced table do not match for constraint.\n" -"See http://www.innodb.com/ibman.php for correct foreign key definition.\n", +"See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" +"for correct foreign key definition.\n", start_of_latest_foreign); mutex_exit(&dict_foreign_err_mutex); diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c index 53f5e885df8..cb74c720ad9 100644 --- a/innobase/fsp/fsp0fsp.c +++ b/innobase/fsp/fsp0fsp.c @@ -2701,9 +2701,9 @@ fseg_free_page_low( "InnoDB: database!\n", page); crash: fputs( -"InnoDB: If the InnoDB recovery crashes here, see section 6.1\n" -"InnoDB: of http://www.innodb.com/ibman.php about forcing recovery.\n", - stderr); +"InnoDB: Please refer to\n" +"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" +"InnoDB: about forcing recovery.\n", stderr); ut_error; } diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index 381d11e4cce..79432fbd511 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -685,10 +685,9 @@ failure: "InnoDB: To get mysqld to start up, set innodb_thread_concurrency in my.cnf\n" "InnoDB: to a lower value, for example, to 8. After an ERROR-FREE shutdown\n" "InnoDB: of mysqld you can adjust the size of ib_logfiles, as explained in\n" -"InnoDB: section 5 of http://www.innodb.com/ibman.php", +"InnoDB: http://dev.mysql.com/doc/mysql/en/Adding_and_removing.html\n" +"InnoDB: Cannot continue operation. Calling exit(1).\n", (ulong)srv_thread_concurrency); - fprintf(stderr, -"InnoDB: Cannot continue operation. Calling exit(1).\n"); exit(1); } diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 51941a14656..52e0b99cb24 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -514,8 +514,8 @@ recv_find_max_checkpoint( "InnoDB: If this error appears when you are creating an InnoDB database,\n" "InnoDB: the problem may be that during an earlier attempt you managed\n" "InnoDB: to create the InnoDB data files, but log file creation failed.\n" -"InnoDB: If that is the case, please refer to section 3.1 of\n" -"InnoDB: http://www.innodb.com/ibman.php\n"); +"InnoDB: If that is the case, please refer to\n" +"InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n"); return(DB_ERROR); } @@ -1840,7 +1840,7 @@ recv_report_corrupt_log( "InnoDB: far enough in recovery! Please run CHECK TABLE\n" "InnoDB: on your InnoDB tables to check that they are ok!\n" "InnoDB: If mysqld crashes after this recovery, look at\n" - "InnoDB: section 6.1 of http://www.innodb.com/ibman.php\n" + "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" "InnoDB: about forcing recovery.\n", stderr); fflush(stderr); diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 56f01568ead..9aa077d162e 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -212,7 +212,8 @@ os_file_get_last_error(void) ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Operating system error number %lu in a file operation.\n" - "InnoDB: See http://www.innodb.com/ibman.php for installation help.\n", + "InnoDB: See http://dev.mysql.com/doc/mysql/en/InnoDB.html\n" + "InnoDB: for installation help.\n", err); if (err == ERROR_PATH_NOT_FOUND) { @@ -227,8 +228,9 @@ os_file_get_last_error(void) "InnoDB: of the same name as a data file.\n"); } else { fprintf(stderr, - "InnoDB: See section 13.2 at http://www.innodb.com/ibman.php\n" - "InnoDB: about operating system error numbers.\n"); + "InnoDB: Some operating system error numbers are described at\n" + "InnoDB: " + "http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n"); } } @@ -251,7 +253,8 @@ os_file_get_last_error(void) fprintf(stderr, " InnoDB: Operating system error number %lu in a file operation.\n" - "InnoDB: See http://www.innodb.com/ibman.php for installation help.\n", + "InnoDB: See http://dev.mysql.com/doc/mysql/en/InnoDB.html\n" + "InnoDB: for installation help.\n", err); if (err == ENOENT) { @@ -270,8 +273,9 @@ os_file_get_last_error(void) } fprintf(stderr, - "InnoDB: See also section 13.2 at http://www.innodb.com/ibman.php\n" - "InnoDB: about operating system error numbers.\n"); + "InnoDB: Some operating system error numbers are described at\n" + "InnoDB: " + "http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n"); } } @@ -1465,8 +1469,9 @@ retry: fprintf(stderr, " InnoDB: Error: File pointer positioning to file %s failed at\n" "InnoDB: offset %lu %lu. Operating system error number %lu.\n" -"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.php\n" -"InnoDB: what the error number means.\n", +"InnoDB: Some operating system error numbers are described at\n" +"InnoDB: " +"http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n", name, offset_high, offset, (ulint)GetLastError()); @@ -1523,8 +1528,9 @@ retry: } fprintf(stderr, -"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.php\n" -"InnoDB: about operating system error numbers.\n"); +"InnoDB: Some operating system error numbers are described at\n" +"InnoDB: " +"http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n"); os_has_said_disk_full = TRUE; } @@ -1558,8 +1564,9 @@ retry: } fprintf(stderr, -"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.php\n" -"InnoDB: about operating system error numbers.\n"); +"InnoDB: Some operating system error numbers are described at\n" +"InnoDB: " +"http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n"); os_has_said_disk_full = TRUE; } diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 70743e3a753..a23444df4ef 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -310,8 +310,9 @@ handle_new_error: "InnoDB: a case of widespread corruption, dump all InnoDB\n" "InnoDB: tables and recreate the whole InnoDB tablespace.\n" "InnoDB: If the mysqld server crashes after the startup or when\n" - "InnoDB: you dump the tables, look at section 6.1 of\n" - "InnoDB: http://www.innodb.com/ibman.php for help.\n", stderr); + "InnoDB: you dump the tables, look at\n" + "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html" + " for help.\n", stderr); } else { fprintf(stderr, "InnoDB: unknown error code %lu\n", err); @@ -1551,8 +1552,9 @@ row_create_table_for_mysql( "InnoDB: database and moving the .frm file to the current database.\n" "InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n" "InnoDB: succeed.\n" - "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.php\n", stderr); + "InnoDB: You can look for further help from\n" + "InnoDB: http://dev.mysql.com/doc/mysql/en/" + "InnoDB_troubleshooting_datadict.html\n", stderr); } trx->error_state = DB_SUCCESS; @@ -2089,8 +2091,9 @@ row_drop_table_for_mysql( "InnoDB: data dictionary though MySQL is trying to drop it.\n" "InnoDB: Have you copied the .frm file of the table to the\n" "InnoDB: MySQL database directory from another database?\n" - "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.php\n", stderr); + "InnoDB: You can look for further help from\n" + "InnoDB: http://dev.mysql.com/doc/mysql/en/" + "InnoDB_troubleshooting_datadict.html\n", stderr); goto funct_exit; } @@ -2588,8 +2591,9 @@ row_rename_table_for_mysql( ut_print_name(stderr, old_name); fputs(" to it.\n" "InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n" - "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.php\n" + "InnoDB: You can look for further help from\n" + "InnoDB: http://dev.mysql.com/doc/mysql/en/" + "InnoDB_troubleshooting_datadict.html\n" "InnoDB: If table ", stderr); ut_print_name(stderr, new_name); fputs( diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c index 2a0cfe1f13a..0f6a27d35d9 100644 --- a/innobase/ut/ut0dbg.c +++ b/innobase/ut/ut0dbg.c @@ -31,8 +31,9 @@ const char* ut_dbg_msg_trap = "InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n" "InnoDB: If you get repeated assertion failures or crashes, even\n" "InnoDB: immediately after the mysqld startup, there may be\n" -"InnoDB: corruption in the InnoDB tablespace. See section 6.1 of\n" -"InnoDB: http://www.innodb.com/ibman.php about forcing recovery.\n"; +"InnoDB: corruption in the InnoDB tablespace. Please refer to\n" +"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" +"InnoDB: about forcing recovery.\n"; const char* ut_dbg_msg_stop = "InnoDB: Thread %lu stopped in file %s line %lu\n"; From 2b8b1a399ac9bd2d6293c6e0232ac9abe64ece58 Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Wed, 8 Sep 2004 16:45:03 +0500 Subject: [PATCH 032/143] A fix (bug #3120: 'mysqladmin ping' - return error code). --- client/mysqladmin.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/client/mysqladmin.c b/client/mysqladmin.c index 3bc11ec0fb0..153fcdde96d 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -246,7 +246,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), int main(int argc,char *argv[]) { - int error, ho_error; + int error= 0, ho_error; MYSQL mysql; char **commands, **save_argv; @@ -285,10 +285,25 @@ int main(int argc,char *argv[]) opt_ssl_capath, opt_ssl_cipher); #endif if (sql_connect(&mysql, option_wait)) - error = 1; + { + unsigned int err= mysql_errno(&mysql); + if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR) + error= 1; + else + { + /* Return 0 if all commands are PING */ + for (; argc > 0; argv++, argc--) + { + if (find_type(argv[0], &command_typelib, 2) != ADMIN_PING) + { + error= 1; + break; + } + } + } + } else { - error = 0; while (!interrupted && (!opt_count_iterations || nr_iterations)) { new_line = 0; From 751071a6773db42da4b2d5e4060d6b0377d151c1 Mon Sep 17 00:00:00 2001 From: "rburnett@build.mysql.com" <> Date: Wed, 8 Sep 2004 16:31:01 +0200 Subject: [PATCH 033/143] [This patch has already been approved by Serge. I am recommitting and pushing from a new repository because there were other changesets that couldn't be pushed.] BUG# 5229 --password=foobar does not override the empty 'password' option in the my.cnf This is a backport of a change made by jani in the 4.1 tree. mysql.cc: Add tty_password=0 in the p case handling in get_one_option --- client/mysql.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mysql.cc b/client/mysql.cc index 3cc8b41af66..7d1b6af2c37 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -689,6 +689,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), while (*argument) *argument++= 'x'; // Destroy argument if (*start) start[1]=0 ; + tty_password= 0; } else tty_password= 1; From df461bdeaba8dddf8056430c48926ac4a614a7cd Mon Sep 17 00:00:00 2001 From: "brian@brian-akers-computer.local" <> Date: Wed, 8 Sep 2004 18:26:19 -0700 Subject: [PATCH 034/143] Updating the headers on a few files to include GPL header. --- BitKeeper/etc/logging_ok | 1 + sql/repl_failsafe.cc | 2 -- sql/repl_failsafe.h | 16 ++++++++++++++++ sql/slave.h | 16 ++++++++++++++++ sql/sql_repl.cc | 2 -- sql/sql_repl.h | 16 ++++++++++++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 698f7655b6e..ca4a56eb210 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -20,6 +20,7 @@ bar@mysql.com bell@laptop.sanja.is.com.ua bell@sanja.is.com.ua bk@admin.bk +brian@brian-akers-computer.local carsten@tsort.bitbybit.dk davida@isil.mysql.com dlenev@brandersnatch.localdomain diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 604938a8ed0..9fa6ea843f1 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -14,8 +14,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// Sasha Pachev is currently in charge of this file - #include "mysql_priv.h" #include "repl_failsafe.h" #include "sql_repl.h" diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h index ae8bb2bc4d5..eb0e97c2820 100644 --- a/sql/repl_failsafe.h +++ b/sql/repl_failsafe.h @@ -1,3 +1,19 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sasha + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef REPL_FAILSAFE_H #define REPL_FAILSAFE_H diff --git a/sql/slave.h b/sql/slave.h index 0cd8545338d..eb54e258a96 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -1,3 +1,19 @@ +/* Copyright (C) 2000-2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef SLAVE_H #define SLAVE_H diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index cff36eaa388..514fed226d2 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -14,8 +14,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// Sasha Pachev is currently in charge of this file - #include "mysql_priv.h" #include "sql_repl.h" #include "sql_acl.h" diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 570c41c98f7..5eac754c25c 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -1,3 +1,19 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sasha + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include "slave.h" typedef struct st_slave_info From cda336b9289be4368998986eaed2c7439e59a82e Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Thu, 9 Sep 2004 12:23:10 +0500 Subject: [PATCH 035/143] Bug #5447 Select does not find records Note, there is no need to propagate this change into 4.1. --- mysql-test/r/ctype_latin1_de.result | 15 +++++++++++++++ mysql-test/t/ctype_latin1_de.test | 14 ++++++++++++++ strings/ctype-latin1_de.c | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result index 28394d9533a..c4bf6b5a3a9 100644 --- a/mysql-test/r/ctype_latin1_de.result +++ b/mysql-test/r/ctype_latin1_de.result @@ -267,3 +267,18 @@ select * from t1 where word like CAST(0xDF as CHAR); word word2 ß ß drop table t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( +autor varchar(80) NOT NULL default '', +PRIMARY KEY (autor) +); +INSERT INTO t1 VALUES ('Powell, B.'),('Powell, Bud.'),('Powell, L. H.'),('Power, H.'), +('Poynter, M. A. L. Lane'),('Poynting, J. H. und J. J. Thomson.'),('Pozzi, S(amuel-Jean).'), +('Pozzi, Samuel-Jean.'),('Pozzo, A.'),('Pozzoli, Serge.'); +SELECT * FROM t1 WHERE autor LIKE 'Poz%' ORDER BY autor; +autor +Pozzi, S(amuel-Jean). +Pozzi, Samuel-Jean. +Pozzo, A. +Pozzoli, Serge. +DROP TABLE t1; diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test index 3a0f2658969..d6c12683d94 100644 --- a/mysql-test/t/ctype_latin1_de.test +++ b/mysql-test/t/ctype_latin1_de.test @@ -72,3 +72,17 @@ select * from t1 where word like 'AE'; select * from t1 where word like 0xDF; select * from t1 where word like CAST(0xDF as CHAR); drop table t1; + +# +# Bug #5447 Select does not find records +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( + autor varchar(80) NOT NULL default '', + PRIMARY KEY (autor) +); +INSERT INTO t1 VALUES ('Powell, B.'),('Powell, Bud.'),('Powell, L. H.'),('Power, H.'), +('Poynter, M. A. L. Lane'),('Poynting, J. H. und J. J. Thomson.'),('Pozzi, S(amuel-Jean).'), +('Pozzi, Samuel-Jean.'),('Pozzo, A.'),('Pozzoli, Serge.'); +SELECT * FROM t1 WHERE autor LIKE 'Poz%' ORDER BY autor; +DROP TABLE t1; diff --git a/strings/ctype-latin1_de.c b/strings/ctype-latin1_de.c index 5b7a68fb967..bc4327e921d 100644 --- a/strings/ctype-latin1_de.c +++ b/strings/ctype-latin1_de.c @@ -248,7 +248,7 @@ int my_strxfrm_latin1_de(uchar * dest, const uchar * src, int len) */ #define min_sort_char ((char) 0) -#define max_sort_char ((char) 255) +#define max_sort_char ((char) 0xF7) #define wild_one '_' #define wild_many '%' From 42419a875a9c1057cc84759b2a4aa7c7279cba3b Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Thu, 9 Sep 2004 17:00:46 +0200 Subject: [PATCH 036/143] - two small fixups for the mysql-copyright scripts: remove the autom4te.cache directory and update the headers of the message files. --- Build-tools/mysql-copyright | 4 ++++ Build-tools/mysql-copyright-2 | 1 + 2 files changed, 5 insertions(+) diff --git a/Build-tools/mysql-copyright b/Build-tools/mysql-copyright index ad4547b493c..a1869304ba7 100755 --- a/Build-tools/mysql-copyright +++ b/Build-tools/mysql-copyright @@ -125,6 +125,10 @@ sub main print "\"./configure\" was not produced, exiting!\n"; exit(0); } + if (-d "autom4te.cache") { + print "Trying to delete autom4te.cache dir\n" if $opt_verbose; + system("rm -rf autom4te.cache") or print "Unable to delete autom4te.cache dir: $!\n"; + } } # fix file copyrights diff --git a/Build-tools/mysql-copyright-2 b/Build-tools/mysql-copyright-2 index a1a870526da..2ea2e8ef441 100755 --- a/Build-tools/mysql-copyright-2 +++ b/Build-tools/mysql-copyright-2 @@ -90,6 +90,7 @@ sub add_copyright $ARGV =~ /\.cc$/ || $ARGV =~ /\.h$/ || $ARGV =~ /\.cpp$/ || + $ARGV =~ /\.txt$/ || $ARGV =~ /\.yy$/) { $start_copyright="/* "; From 82afd016d292625afe3b57d588750b935db41358 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 9 Sep 2004 19:19:29 +0200 Subject: [PATCH 037/143] Prevent some combinations of autotools and libtool version from generating a non-working top level 'libtool'. --- ltmain.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ltmain.sh b/ltmain.sh index 62b9ed17e3f..92e438cbda6 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -51,6 +51,9 @@ fi # libtool 1.4.2 workaround SED=${SED:-sed} +# workaround against unset 'max_cmd_len': assume at least 4 kB +max_cmd_len=${max_cmd_len:-4096} + # The name of this program. progname=`$echo "$0" | ${SED} 's%^.*/%%'` modename="$progname" From c998fbdb8cc942a47bb24841678b7d0387c0e55a Mon Sep 17 00:00:00 2001 From: "matt@mysql.com" <> Date: Fri, 10 Sep 2004 00:08:12 +0200 Subject: [PATCH 038/143] configure.in: Updated to 4.0.22 --- BitKeeper/etc/logging_ok | 1 + configure.in | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index ca4a56eb210..d65810bb708 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -67,6 +67,7 @@ kostja@oak.local lenz@kallisto.mysql.com lenz@mysql.com marko@hundin.mysql.fi +matt@mysql.com miguel@hegel.(none) miguel@hegel.br miguel@hegel.local diff --git a/configure.in b/configure.in index 30a546ec5d9..c3978ff32d1 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.21) +AM_INIT_AUTOMAKE(mysql, 4.0.22) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From fd17beb0d9027dbe6657b91d6abf761fab1cffda Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Fri, 10 Sep 2004 13:44:06 +0300 Subject: [PATCH 039/143] dict0dict.c: Fixed typo --- innobase/dict/dict0dict.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 573b9ef49f1..bd07c5abffe 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2857,7 +2857,7 @@ col_loop1: ut_print_name(ef, name); fprintf(ef, " where the columns appear\n" "as the first columns. Constraint:\n%s\n" -"nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" +"See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" "for correct foreign key definition.\n", start_of_latest_foreign); mutex_exit(&dict_foreign_err_mutex); From 4c7c2343c75e4bf8cf9973d3710deb1be1eb329b Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 11 Sep 2004 09:37:16 +0300 Subject: [PATCH 040/143] os0file.c: Add more precise diagnostics about the state of the I/O threads of InnoDB; print in SHOW INNODB STATUS if the event wait semaphore of each I/O thread is set --- innobase/os/os0file.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 9aa077d162e..70ef8f55b98 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2588,6 +2588,8 @@ restart: /* NOTE! We only access constant fields in os_aio_array. Therefore we do not have to acquire the protecting mutex yet */ + srv_set_io_thread_op_info(global_segment, + "looking for i/o requests (a)"); ut_ad(os_aio_validate()); ut_ad(segment < array->n_segments); @@ -2606,6 +2608,9 @@ restart: os_mutex_enter(array->mutex); + srv_set_io_thread_op_info(global_segment, + "looking for i/o requests (b)"); + /* Check if there is a slot for which the i/o has already been done */ @@ -2718,6 +2723,8 @@ consecutive_loop: } } + srv_set_io_thread_op_info(global_segment, "consecutive i/o requests"); + /* We have now collected n_consecutive i/o requests in the array; allocate a single buffer which can hold all data, and perform the i/o */ @@ -2861,6 +2868,8 @@ slot_io_done: return(ret); wait_for_io: + srv_set_io_thread_op_info(global_segment, "resetting wait event"); + /* We wait here until there again can be i/os in the segment of this thread */ @@ -2952,9 +2961,15 @@ os_aio_print( ulint i; for (i = 0; i < srv_n_file_io_threads; i++) { - fprintf(file, "I/O thread %lu state: %s (%s)\n", i, + fprintf(file, "I/O thread %lu state: %s (%s)", i, srv_io_thread_op_info[i], srv_io_thread_function[i]); + + if (os_aio_segment_wait_events[i]->is_set) { + fprintf(file, " ev set"); + } + + fprintf(file, "\n"); } fputs("Pending normal aio reads:", file); From 7aa25240f7724230507f29ab4bfa0c25c4b66ac4 Mon Sep 17 00:00:00 2001 From: "hf@deer.(none)" <> Date: Mon, 13 Sep 2004 12:13:24 +0500 Subject: [PATCH 041/143] Fix for bug #4809 (Backticks not handled in mysql) --- client/mysql.cc | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 7d1b6af2c37..4aac548a065 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2201,17 +2201,49 @@ static int com_source(String *buffer, char *line) static int com_use(String *buffer __attribute__((unused)), char *line) { - char *tmp, buff[FN_REFLEN + 1]; + char tmp[FN_REFLEN], buff[FN_REFLEN + 1]; MYSQL_RES *res; MYSQL_ROW row; + char *c_buff, *c_tmp; while (isspace(*line)) line++; strnmov(buff,line,sizeof(buff)-1); // Don't destroy history if (buff[0] == '\\') // Short command buff[1]=' '; - tmp=(char *) strtok(buff," \t;"); // Skip connect command - if (!tmp || !(tmp=(char *) strtok(NullS," \t;"))) + c_buff= buff; + while ((*c_buff != ' ') && (*c_buff != '\t')) // Skip connect command + c_buff++; + c_buff++; + + while ((*c_buff == ' ') || (*c_buff == '\t')) + c_buff++; + c_tmp= tmp; + if (*c_buff == '`') // Handling backticks + { + c_buff++; + for (; *c_buff; c_tmp++) + { + if (*c_buff == '`') + { + if (c_buff[1] == '`') + { + *c_tmp= '`'; + c_buff+= 2; + } + else + break; + } + else + *c_tmp= *(c_buff++); + } + } + else + for (; !strchr(" \t;", *c_buff); c_buff++, c_tmp++) + *c_tmp= *c_buff; + *c_tmp= '\0'; + + if (!*tmp) { put_info("USE must be followed by a database name",INFO_ERROR); return 0; From 2488b827de39fd3dbad5aa6b6fa04e6fd07981f1 Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Mon, 13 Sep 2004 14:25:43 +0500 Subject: [PATCH 042/143] A fix (bug #5498 TRIM fails with LEADING or TRAILING if remstr = str). --- mysql-test/r/func_str.result | 6 ++++++ mysql-test/t/func_str.test | 7 +++++++ sql/item_strfunc.cc | 6 +++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 12c1cf78f7c..b4d1be5bd54 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -282,3 +282,9 @@ NULL NULL 1 1 n two 'two' 0 0 'two' four 'four' 0 0 'four' drop table t1; +select trim(trailing 'foo' from 'foo'); +trim(trailing 'foo' from 'foo') + +select trim(leading 'foo' from 'foo'); +trim(leading 'foo' from 'foo') + diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 9b0c076f23e..ba6a8b55236 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -172,3 +172,10 @@ create table t1(a char(4)); insert into t1 values ('one'),(NULL),('two'),('four'); select a, quote(a), isnull(quote(a)), quote(a) is null, ifnull(quote(a), 'n') from t1; drop table t1; + +# +# Bug #5498: TRIM fails with LEADING or TRAILING if remstr = str +# + +select trim(trailing 'foo' from 'foo'); +select trim(leading 'foo' from 'foo'); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 5d017b3a27a..9248cbc0217 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1135,7 +1135,7 @@ String *Item_func_ltrim::val_str(String *str) { const char *r_ptr=remove_str->ptr(); end-=remove_length; - while (ptr < end && !memcmp(ptr,r_ptr,remove_length)) + while (ptr <= end && !memcmp(ptr, r_ptr, remove_length)) ptr+=remove_length; end+=remove_length; } @@ -1206,8 +1206,8 @@ String *Item_func_rtrim::val_str(String *str) else #endif /* USE_MB */ { - while (ptr + remove_length < end && - !memcmp(end-remove_length,r_ptr,remove_length)) + while (ptr + remove_length <= end && + !memcmp(end-remove_length, r_ptr, remove_length)) end-=remove_length; } } From d6b4c4f90e6037bdb949029f119b9e6950660a85 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 13 Sep 2004 19:05:39 +0300 Subject: [PATCH 043/143] row0mysql.h: Improve the comment on stored_select_lock_type ha_innodb.cc: Let InnoDB remember select_lock_type inside LOCK TABLES, also over plain consistent read SELECTs; fix Bug #5538 : assertion failure when using mysqldump with the -l option; in MERGING this patch to 4.1, there may be PROBLEMS; that is because previous patch was never merged to 4.1; Heikki Tuuri has to polish the code in 4.1 after this patch has been merged. --- innobase/include/row0mysql.h | 8 +++-- sql/ha_innodb.cc | 65 +++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 0ab70db2dea..bbd90434f39 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -508,9 +508,11 @@ struct row_prebuilt_struct { dtuple_t* clust_ref; /* prebuilt dtuple used in sel/upd/del */ ulint select_lock_type;/* LOCK_NONE, LOCK_S, or LOCK_X */ - ulint stored_select_lock_type;/* inside LOCK TABLES, either - LOCK_S or LOCK_X depending on the lock - type */ + ulint stored_select_lock_type;/* this field is used to + remember the original select_lock_type + that was decided in ha_innodb.cc, + ::store_lock(), ::external_lock(), + etc. */ ulint mysql_row_len; /* length in bytes of a row in the MySQL format */ ulint n_rows_fetched; /* number of rows fetched after diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 1572e22d6f7..b9d898d5bd1 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -767,6 +767,7 @@ ha_innobase::init_table_handle_for_HANDLER(void) if the trx isolation level would have been specified as SERIALIZABLE */ prebuilt->select_lock_type = LOCK_NONE; + prebuilt->stored_select_lock_type = LOCK_NONE; /* Always fetch all columns in the index record */ @@ -4562,40 +4563,40 @@ ha_innobase::start_stmt( prebuilt->select_lock_type = LOCK_X; } else { - /* When we first come here after LOCK TABLES, - select_lock_type is set to LOCK_S or LOCK_X. Store the value - in case we run also consistent reads and need to restore the - value later. */ + if (trx->isolation_level != TRX_ISO_SERIALIZABLE + && thd->lex.sql_command == SQLCOM_SELECT + && thd->lex.lock_option == TL_READ) { + + /* For other than temporary tables, we obtain + no lock for consistent read (plain SELECT). */ - if (prebuilt->select_lock_type != LOCK_NONE) { - prebuilt->stored_select_lock_type = - prebuilt->select_lock_type; + prebuilt->select_lock_type = LOCK_NONE; + } else { + /* Not a consistent read: restore the + select_lock_type value. The value of + stored_select_lock_type was decided in: + 1) ::store_lock(), + 2) ::external_lock(), and + 3) ::init_table_handle_for_HANDLER(). */ + + prebuilt->select_lock_type = + prebuilt->stored_select_lock_type; } if (prebuilt->stored_select_lock_type != LOCK_S && prebuilt->stored_select_lock_type != LOCK_X) { fprintf(stderr, -"InnoDB: Error: select_lock_type is %lu inside ::start_stmt()!\n", +"InnoDB: Error: stored_select_lock_type is %lu inside ::start_stmt()!\n", prebuilt->stored_select_lock_type); - ut_error; - } + /* Set the value to LOCK_X: this is just fault + tolerance, we do not know what the correct value + should be! */ - if (thd->lex.sql_command == SQLCOM_SELECT - && thd->lex.lock_option == TL_READ) { - - /* For other than temporary tables, we obtain - no lock for consistent read (plain SELECT) */ - - prebuilt->select_lock_type = LOCK_NONE; - } else { - /* Not a consistent read: restore the - select_lock_type value */ - prebuilt->select_lock_type = - prebuilt->stored_select_lock_type; + prebuilt->select_lock_type = LOCK_X; } } - + /* Set the MySQL flag to mark that there is an active transaction */ thd->transaction.all.innodb_active_trans = 1; @@ -4656,6 +4657,7 @@ ha_innobase::external_lock( /* If this is a SELECT, then it is in UPDATE TABLE ... or SELECT ... FOR UPDATE */ prebuilt->select_lock_type = LOCK_X; + prebuilt->stored_select_lock_type = LOCK_X; } if (lock_type != F_UNLCK) { @@ -4910,14 +4912,22 @@ ha_innobase::store_lock( { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - if (lock_type == TL_READ_WITH_SHARED_LOCKS || + if ((lock_type == TL_READ && thd->in_lock_tables) || + (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) || + lock_type == TL_READ_WITH_SHARED_LOCKS || lock_type == TL_READ_NO_INSERT) { - /* This is a SELECT ... IN SHARE MODE, or - we are doing a complex SQL statement like + /* The OR cases above are in this order: + 1) MySQL is doing LOCK TABLES ... READ LOCAL, or + 2) (we do not know when TL_READ_HIGH_PRIORITY is used), or + 3) this is a SELECT ... IN SHARE MODE, or + 4) we are doing a complex SQL statement like INSERT INTO ... SELECT ... and the logical logging (MySQL - binlog) requires the use of a locking read */ + binlog) requires the use of a locking read, or + MySQL is doing LOCK TABLES ... READ. */ prebuilt->select_lock_type = LOCK_S; + prebuilt->stored_select_lock_type = LOCK_S; + } else if (lock_type != TL_IGNORE) { /* In ha_berkeley.cc there is a comment that MySQL @@ -4928,6 +4938,7 @@ ha_innobase::store_lock( here even if this would be SELECT ... FOR UPDATE */ prebuilt->select_lock_type = LOCK_NONE; + prebuilt->stored_select_lock_type = LOCK_NONE; } if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { From fd7dde7cafb84fdb3e3bd33aaf6453e948c2eb41 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 13 Sep 2004 20:08:09 +0300 Subject: [PATCH 044/143] sync0arr.c: Correct the comment on the 'waiting' field in sync_cell_struct --- innobase/sync/sync0arr.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index 176aedb6ae3..09ddfd1d309 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -61,10 +61,7 @@ struct sync_cell_struct { thread */ ibool waiting; /* TRUE if the thread has already called sync_array_event_wait - on this cell but not yet - sync_array_free_cell (which - actually resets wait_object and thus - whole cell) */ + on this cell */ ibool event_set; /* TRUE if the event is set */ os_event_t event; /* operating system event semaphore handle */ From 484d54b2317aa833e9f9edcaba584aa768387191 Mon Sep 17 00:00:00 2001 From: "patg@krsna.patg.net" <> Date: Tue, 14 Sep 2004 12:23:18 -0700 Subject: [PATCH 045/143] fixed bug 5531 --- scripts/mysqlhotcopy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index af4e6084c59..2256e028eb4 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -77,7 +77,7 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory] --record_log_pos=# record slave and master status in specified db.table --chroot=# base directory of chroot jail in which mysqld operates - Try \'perldoc $0 for more complete documentation\' + Try \'perldoc $0\' for more complete documentation\' _OPTIONS sub usage { From 78fa3aeff4ee40212ccc28d87aa8031fb1773bdf Mon Sep 17 00:00:00 2001 From: "patg@krsna.patg.net" <> Date: Tue, 14 Sep 2004 14:10:29 -0700 Subject: [PATCH 046/143] another small change for bug 5531 --- scripts/mysqlhotcopy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 2256e028eb4..b90ca4dc7c0 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -77,7 +77,7 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory] --record_log_pos=# record slave and master status in specified db.table --chroot=# base directory of chroot jail in which mysqld operates - Try \'perldoc $0\' for more complete documentation\' + Try \'perldoc $0\' for more complete documentation _OPTIONS sub usage { From e58c9579fe56dc267be056fca4aa75ac8112d955 Mon Sep 17 00:00:00 2001 From: "vva@eagle.mysql.r18.ru" <> Date: Thu, 16 Sep 2004 16:10:14 +0500 Subject: [PATCH 047/143] Fixed Bug #5492 "set @@session.read_rnd_buffer_size=33554432" crashes server on query incremented size of allocated buffer in the init_rr_cache(sql/records.cc) ( We are going to read the last three bytes of the buffer via uint3korr This macro reads actually 4 bytes (for speed) So, we have to allocate one more byte at the end of the buffer to avoid memory assertion fault ) --- sql/records.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sql/records.cc b/sql/records.cc index 415e75a467b..a2c6eb0a040 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -249,9 +249,15 @@ static int init_rr_cache(READ_RECORD *info) rec_cache_size=info->cache_records*info->reclength; info->rec_cache_size=info->cache_records*info->ref_length; + /* + We are going to read the last three bytes of the buffer via uint3korr + This macro reads actually 4 bytes (for speed) + So, we have to allocate one more byte at the end of the buffer + to avoid memory assertion fault + */ if (info->cache_records <= 2 || !(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records* - info->struct_length, + info->struct_length+1, MYF(0)))) DBUG_RETURN(1); #ifdef HAVE_purify From 6083e00d7381ddbcdeadc39a5acff5017439c188 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 16 Sep 2004 20:50:24 +0300 Subject: [PATCH 048/143] dict0dict.h, dict0dict.c, row0row.c, pars0opt.c: Fix bug #5180: having a column prefix index in the primary key, and the same column fully in a secondary key could cause an assertion failure in row_build_row_ref() --- innobase/dict/dict0dict.c | 10 +++++++--- innobase/include/dict0dict.h | 6 ++++-- innobase/pars/pars0opt.c | 13 +++++++++++++ innobase/row/row0row.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index bd07c5abffe..61bf3fae137 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -526,8 +526,10 @@ dict_index_contains_col_or_prefix( } /************************************************************************ -Looks for a matching field in an index. The column and the prefix len have -to be the same. */ +Looks for a matching field in an index. The column has to be the same. The +column in index must be complete, or must contain a prefix longer than the +column in index2. That is, we must be able to construct the prefix in index2 +from the prefix in index. */ ulint dict_index_get_nth_field_pos( @@ -555,7 +557,9 @@ dict_index_get_nth_field_pos( field = dict_index_get_nth_field(index, pos); if (field->col == field2->col - && field->prefix_len == field2->prefix_len) { + && (field->prefix_len == 0 + || (field->prefix_len >= field2->prefix_len + && field2->prefix_len != 0))) { return(pos); } diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index 835c2c2b2e6..9940be9832d 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -566,8 +566,10 @@ dict_index_contains_col_or_prefix( dict_index_t* index, /* in: index */ ulint n); /* in: column number */ /************************************************************************ -Looks for a matching field in an index. The column and the prefix len has -to be the same. */ +Looks for a matching field in an index. The column has to be the same. The +column in index must be complete, or must contain a prefix longer than the +column in index2. That is, we must be able to construct the prefix in index2 +from the prefix in index. */ ulint dict_index_get_nth_field_pos( diff --git a/innobase/pars/pars0opt.c b/innobase/pars/pars0opt.c index 5cc2e39b438..51aaf02b736 100644 --- a/innobase/pars/pars0opt.c +++ b/innobase/pars/pars0opt.c @@ -1094,6 +1094,19 @@ opt_clust_access( for (i = 0; i < n_fields; i++) { pos = dict_index_get_nth_field_pos(index, clust_index, i); + ut_a(pos != ULINT_UNDEFINED); + + /* We optimize here only queries to InnoDB's internal system + tables, and they should not contain column prefix indexes. */ + + if (dict_index_get_nth_field(index, pos)->prefix_len != 0 + || dict_index_get_nth_field(clust_index, i) + ->prefix_len != 0) { + fprintf(stderr, +"InnoDB: Error in pars0opt.c: table %s has prefix_len != 0\n", + index->table_name); + } + *(plan->clust_map + i) = pos; ut_ad((pos != ULINT_UNDEFINED) diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c index 680539764fd..f075caa7d75 100644 --- a/innobase/row/row0row.c +++ b/innobase/row/row0row.c @@ -334,6 +334,7 @@ row_build_row_ref( ulint ref_len; ulint pos; byte* buf; + ulint clust_col_prefix_len; ulint i; ut_ad(index && rec && heap); @@ -366,6 +367,22 @@ row_build_row_ref( field = rec_get_nth_field(rec, pos, &len); dfield_set_data(dfield, field, len); + + /* If the primary key contains a column prefix, then the + secondary index may contain a longer prefix of the same + column, or the full column, and we must adjust the length + accordingly. */ + + clust_col_prefix_len = + dict_index_get_nth_field(clust_index, i)->prefix_len; + + if (clust_col_prefix_len > 0) { + if (len != UNIV_SQL_NULL + && len > clust_col_prefix_len) { + + dfield_set_len(dfield, clust_col_prefix_len); + } + } } ut_ad(dtuple_check_typed(ref)); @@ -396,6 +413,7 @@ row_build_row_ref_in_tuple( ulint len; ulint ref_len; ulint pos; + ulint clust_col_prefix_len; ulint i; ut_a(ref && index && rec); @@ -433,6 +451,22 @@ row_build_row_ref_in_tuple( field = rec_get_nth_field(rec, pos, &len); dfield_set_data(dfield, field, len); + + /* If the primary key contains a column prefix, then the + secondary index may contain a longer prefix of the same + column, or the full column, and we must adjust the length + accordingly. */ + + clust_col_prefix_len = + dict_index_get_nth_field(clust_index, i)->prefix_len; + + if (clust_col_prefix_len > 0) { + if (len != UNIV_SQL_NULL + && len > clust_col_prefix_len) { + + dfield_set_len(dfield, clust_col_prefix_len); + } + } } ut_ad(dtuple_check_typed(ref)); From 0b6dc4938838c32c51b4c3633551711110229dc4 Mon Sep 17 00:00:00 2001 From: "antony@ltantony.rdg.cyberkinetica.homeunix.net" <> Date: Fri, 17 Sep 2004 12:07:59 +0100 Subject: [PATCH 049/143] Bug#5553 - Multi table UPDATE IGNORE fails on dup key We don't want the update to abort when IGNORE is specified --- BitKeeper/etc/logging_ok | 1 + mysql-test/r/update.result | 37 +++++++++++++++++++++++++++++++++++++ mysql-test/t/update.test | 33 +++++++++++++++++++++++++++++++++ sql/sql_update.cc | 8 ++++++-- 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index d65810bb708..d427be619b8 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -9,6 +9,7 @@ acurtis@pcgem.rdg.cyberkinetica.com ahlentz@co3064164-a.rochd1.qld.optusnet.com.au akishkin@work.mysql.com antony@ltantony.dsl-verizon.net +antony@ltantony.rdg.cyberkinetica.homeunix.net arjen@bitbike.com arjen@co3064164-a.bitbike.com arjen@fred.bitbike.com diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 11aff8fe50a..c9405d71237 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -166,3 +166,40 @@ F1 F2 F3 cnt groupid 2 0 1 2 4 2 2 0 1 7 drop table t1; +CREATE TABLE t1 ( +`colA` int(10) unsigned NOT NULL auto_increment, +`colB` int(11) NOT NULL default '0', +PRIMARY KEY (`colA`) +); +INSERT INTO t1 VALUES (4433,5424); +CREATE TABLE t2 ( +`colC` int(10) unsigned NOT NULL default '0', +`colA` int(10) unsigned NOT NULL default '0', +`colD` int(10) unsigned NOT NULL default '0', +`colE` int(10) unsigned NOT NULL default '0', +`colF` int(10) unsigned NOT NULL default '0', +PRIMARY KEY (`colC`,`colA`,`colD`,`colE`) +); +INSERT INTO t2 VALUES (3,4433,10005,495,500); +INSERT INTO t2 VALUES (3,4433,10005,496,500); +INSERT INTO t2 VALUES (3,4433,10009,494,500); +INSERT INTO t2 VALUES (3,4433,10011,494,500); +INSERT INTO t2 VALUES (3,4433,10005,497,500); +INSERT INTO t2 VALUES (3,4433,10013,489,500); +INSERT INTO t2 VALUES (3,4433,10005,494,500); +INSERT INTO t2 VALUES (3,4433,10005,493,500); +INSERT INTO t2 VALUES (3,4433,10005,492,500); +UPDATE IGNORE t2,t1 set t2.colE = t2.colE + 1,colF=0 WHERE t1.colA = t2.colA AND (t1.colB & 4096) > 0 AND (colE + 1) < colF; +SELECT * FROM t2; +colC colA colD colE colF +3 4433 10005 495 500 +3 4433 10005 496 500 +3 4433 10009 495 0 +3 4433 10011 495 0 +3 4433 10005 498 0 +3 4433 10013 490 0 +3 4433 10005 494 500 +3 4433 10005 493 500 +3 4433 10005 492 500 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 2e739dd927d..1850564418c 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -122,3 +122,36 @@ insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6), delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3); select * from t1; drop table t1; + +# +# Bug#5553 - Multi table UPDATE IGNORE fails on duplicate keys +# + +CREATE TABLE t1 ( + `colA` int(10) unsigned NOT NULL auto_increment, + `colB` int(11) NOT NULL default '0', + PRIMARY KEY (`colA`) +); +INSERT INTO t1 VALUES (4433,5424); +CREATE TABLE t2 ( + `colC` int(10) unsigned NOT NULL default '0', + `colA` int(10) unsigned NOT NULL default '0', + `colD` int(10) unsigned NOT NULL default '0', + `colE` int(10) unsigned NOT NULL default '0', + `colF` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`colC`,`colA`,`colD`,`colE`) +); +INSERT INTO t2 VALUES (3,4433,10005,495,500); +INSERT INTO t2 VALUES (3,4433,10005,496,500); +INSERT INTO t2 VALUES (3,4433,10009,494,500); +INSERT INTO t2 VALUES (3,4433,10011,494,500); +INSERT INTO t2 VALUES (3,4433,10005,497,500); +INSERT INTO t2 VALUES (3,4433,10013,489,500); +INSERT INTO t2 VALUES (3,4433,10005,494,500); +INSERT INTO t2 VALUES (3,4433,10005,493,500); +INSERT INTO t2 VALUES (3,4433,10005,492,500); +UPDATE IGNORE t2,t1 set t2.colE = t2.colE + 1,colF=0 WHERE t1.colA = t2.colA AND (t1.colB & 4096) > 0 AND (colE + 1) < colF; +SELECT * FROM t2; +DROP TABLE t1; +DROP TABLE t2; + diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 02d2fe2c442..d51c81ee127 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -792,9 +792,13 @@ bool multi_update::send_data(List ¬_used_values) if ((error=table->file->update_row(table->record[1], table->record[0]))) { - table->file->print_error(error,MYF(0)); updated--; - DBUG_RETURN(1); + if (handle_duplicates != DUP_IGNORE || + error != HA_ERR_FOUND_DUPP_KEY) + { + table->file->print_error(error,MYF(0)); + DBUG_RETURN(1); + } } } } From c03049dfd98c91e5c5e37b8c7ba55279e63d2c71 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Fri, 17 Sep 2004 17:16:02 +0300 Subject: [PATCH 050/143] InnoDB: Corrected typos in DBUG_ statements --- sql/ha_innodb.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index b9d898d5bd1..f149af85b3f 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3049,7 +3049,7 @@ ha_innobase::index_last( { int error; - DBUG_ENTER("index_first"); + DBUG_ENTER("index_last"); statistic_increment(ha_read_last_count, &LOCK_status); error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY); @@ -4110,7 +4110,7 @@ ha_innobase::info( if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { - return; + DBUG_VOID_RETURN; } /* We do not know if MySQL can call this function before calling From 276622c92d6ff6c43383019b2eeb94c84018cd3a Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Sat, 18 Sep 2004 13:06:44 +0400 Subject: [PATCH 051/143] Fix for bug #5595: NULLIF() IS NULL returns false if NULLIF() returns NULL --- mysql-test/r/func_if.result | 3 +++ mysql-test/t/func_if.test | 4 ++++ sql/item_cmpfunc.cc | 9 +++++++++ sql/item_cmpfunc.h | 1 + 4 files changed, 17 insertions(+) diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index aee54ede324..72226588de3 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -64,3 +64,6 @@ select if(1>2,a,avg(a)) from t1; if(1>2,a,avg(a)) 1.5000 drop table t1; +SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL; +NULLIF(5,5) IS NULL NULLIF(5,5) IS NOT NULL +1 0 diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 5e605dbe97b..f78cb5ade55 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -47,3 +47,7 @@ insert t1 values (1),(2); select if(1>2,a,avg(a)) from t1; drop table t1; +# +# Bug #5595 NULLIF() IS NULL returns false if NULLIF() returns NULL +# +SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 013304d9df5..fbc1ad97e76 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -654,6 +654,15 @@ Item_func_nullif::val_str(String *str) return res; } + +bool +Item_func_nullif::is_null() +{ + if (!(this->*cmp_func)()) + return null_value=1; + return 0; +} + /* CASE expression Return the matching ITEM or NULL if all compares (including else) failed diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 236ebb8d28b..8f1aa525190 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -240,6 +240,7 @@ public: void fix_length_and_dec(); const char *func_name() const { return "nullif"; } table_map not_null_tables() const { return 0; } + bool is_null(); }; From 7afb03b7edb9037212b5da39db4350c4eeeca72c Mon Sep 17 00:00:00 2001 From: "ingo@mysql.com" <> Date: Sat, 18 Sep 2004 20:33:39 +0200 Subject: [PATCH 052/143] bug#2831 - --extenral-locking does not fully work with --myisam-recover. Changed the semantics of open_count so that it is decremented at every unlock (if it was incremented due to data changes). So it indicates a crash, if it is non-zero after a lock. The table will then be repaired. --- myisam/mi_close.c | 3 +- myisam/mi_locking.c | 83 ++++++++++++++++++++++++++++++++++++++++++--- sql/ha_myisam.cc | 24 +++++++++++-- sql/sql_table.cc | 12 +++++-- 4 files changed, 111 insertions(+), 11 deletions(-) diff --git a/myisam/mi_close.c b/myisam/mi_close.c index dbaaebb1143..47308a5e9eb 100644 --- a/myisam/mi_close.c +++ b/myisam/mi_close.c @@ -70,7 +70,8 @@ int mi_close(register MI_INFO *info) error=my_errno; if (share->kfile >= 0) { - if (share->mode != O_RDONLY && mi_is_crashed(info)) + /* We must always flush the state with the current open_count. */ + if (share->mode != O_RDONLY) mi_state_info_write(share->kfile, &share->state, 1); if (my_close(share->kfile,MYF(0))) error = my_errno; diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index f3bfa8deb90..8a140a8b6fb 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -26,6 +26,9 @@ #include #endif +static int mi_unlock_open_count(MI_INFO *info, my_bool write_info); + + /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */ int mi_lock_database(MI_INFO *info, int lock_type) @@ -35,7 +38,12 @@ int mi_lock_database(MI_INFO *info, int lock_type) MYISAM_SHARE *share=info->s; uint flag; DBUG_ENTER("mi_lock_database"); - DBUG_PRINT("info",("lock_type: %d", lock_type)); + DBUG_PRINT("enter",("mi_lock_database: lock_type %d, old lock %d" + ", r_locks %u, w_locks %u", lock_type, + info->lock_type, share->r_locks, share->w_locks)); + DBUG_PRINT("enter",("mi_lock_database: gl._changed %d, open_count %u '%s'", + share->global_changed, share->state.open_count, + share->index_file_name)); if (share->options & HA_OPTION_READ_ONLY_DATA || info->lock_type == lock_type) @@ -54,7 +62,6 @@ int mi_lock_database(MI_INFO *info, int lock_type) { switch (lock_type) { case F_UNLCK: - DBUG_PRINT("info", ("old lock: %d", info->lock_type)); if (info->lock_type == F_RDLCK) count= --share->r_locks; else @@ -83,7 +90,8 @@ int mi_lock_database(MI_INFO *info, int lock_type) share->state.process= share->last_process=share->this_process; share->state.unique= info->last_unique= info->this_unique; share->state.update_count= info->last_loop= ++info->this_loop; - if (mi_state_info_write(share->kfile, &share->state, 1)) + if (mi_unlock_open_count(info, FALSE) || + mi_state_info_write(share->kfile, &share->state, 1)) error=my_errno; share->changed=0; if (myisam_flush) @@ -98,6 +106,19 @@ int mi_lock_database(MI_INFO *info, int lock_type) if (error) mi_mark_crashed(info); } + else + { + /* + There are chances that _mi_mark_file_changed() has been called, + while share->changed remained FALSE. Consequently, we need to + clear the open_count even when share->changed is FALSE. Note, + that mi_unlock_open_count() will only clear the open_count when + it is set and only write the status to file, if it changes it + and we are running --with-external-locking. + */ + if (mi_unlock_open_count(info, ! my_disable_locking)) + error= my_errno; + } if (info->lock_type != F_EXTRA_LCK) { if (share->r_locks) @@ -122,10 +143,15 @@ int mi_lock_database(MI_INFO *info, int lock_type) case F_RDLCK: if (info->lock_type == F_WRLCK) { /* Change RW to READONLY */ + /* + mysqld does not turn write locks to read locks, + so we're never here in mysqld. + */ if (share->w_locks == 1) { flag=1; - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, + if (mi_unlock_open_count(info, ! my_disable_locking) || + my_lock(share->kfile,lock_type,0L,F_TO_EOF, MYF(MY_SEEK_NOT_DONE))) { error=my_errno; @@ -153,6 +179,14 @@ int mi_lock_database(MI_INFO *info, int lock_type) my_errno=error; break; } + if (share->state.open_count) + { + DBUG_PRINT("error",("RD: Table has not been correctly unlocked" + ": open_count %d '%s'", + share->state.open_count, + share->index_file_name)); + mi_mark_crashed(info); + } } VOID(_mi_test_if_changed(info)); share->r_locks++; @@ -198,6 +232,14 @@ int mi_lock_database(MI_INFO *info, int lock_type) my_errno=error; break; } + if (share->state.open_count) + { + DBUG_PRINT("error",("WR: Table has not been correctly unlocked" + ": open_count %d '%s'", + share->state.open_count, + share->index_file_name)); + mi_mark_crashed(info); + } } } } @@ -459,3 +501,36 @@ int _mi_decrement_open_count(MI_INFO *info) } return test(lock_error || write_error); } + +/* + Decrement open_count in preparation for unlock. + + SYNOPSIS + mi_unlock_open_count() + info Pointer to the MI_INFO structure. + write_info If info must be written when changed. + + RETURN + 0 OK +*/ + +static int mi_unlock_open_count(MI_INFO *info, my_bool write_info) +{ + int rc= 0; + MYISAM_SHARE *share=info->s; + + DBUG_ENTER("mi_unlock_open_count"); + DBUG_PRINT("enter",("mi_unlock_open_count: gl._changed %d open_count %d '%s'", + share->global_changed, share->state.open_count, + share->index_file_name)); + if (share->global_changed) + { + share->global_changed= 0; + if (share->state.open_count) + share->state.open_count--; + if (write_info) + rc= _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE); + } + DBUG_RETURN(rc); +} + diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index d5bbf9b5a92..2b7b8f436b1 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1000,9 +1000,27 @@ int ha_myisam::delete_table(const char *name) int ha_myisam::external_lock(THD *thd, int lock_type) { - return mi_lock_database(file, !table->tmp_table ? - lock_type : ((lock_type == F_UNLCK) ? - F_UNLCK : F_EXTRA_LCK)); + int rc; + + while ((! (rc= mi_lock_database(file, !table->tmp_table ? + lock_type : ((lock_type == F_UNLCK) ? + F_UNLCK : F_EXTRA_LCK)))) && + mi_is_crashed(file) && (myisam_recover_options != HA_RECOVER_NONE)) + { + /* + check_and_repair() implicitly write locks the table, unless a + LOCK TABLES is in effect. It should be safer to always write lock here. + The implicit lock by check_and_repair() will then be a no-op. + check_and_repair() does not restore the original lock, but unlocks the + table. So we have to get the requested lock type again. And then to + check, if the table has been crashed again meanwhile by another server. + If anything fails, we break. + */ + if (((lock_type != F_WRLCK) && (rc= mi_lock_database(file, F_WRLCK))) || + (rc= check_and_repair(thd))) + break; + } + return rc; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e2e186abb0d..0dd5c65bf79 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2208,7 +2208,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, if (!(copy= new Copy_field[to->fields])) DBUG_RETURN(-1); /* purecov: inspected */ - to->file->external_lock(thd,F_WRLCK); + if (to->file->external_lock(thd, F_WRLCK)) + { + /* We must always unlock, even when lock failed. */ + (void) to->file->external_lock(thd, F_UNLCK); + DBUG_RETURN(-1); + } to->file->extra(HA_EXTRA_WRITE_CACHE); from->file->info(HA_STATUS_VARIABLE); to->file->deactivate_non_unique_index(from->file->records); @@ -2308,11 +2313,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, error=1; if (ha_commit(thd)) error=1; - if (to->file->external_lock(thd,F_UNLCK)) - error=1; err: free_io_cache(from); *copied= found_count; *deleted=delete_count; + /* we must always unlock the table on return. */ + if (to->file->external_lock(thd,F_UNLCK)) + error=1; DBUG_RETURN(error > 0 ? -1 : 0); } From 704e0968d2a136c818887d01978210ba9318a669 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Sun, 19 Sep 2004 14:48:41 +0400 Subject: [PATCH 053/143] Change www.mysql.com -> dev.mysql.com in a reference to how to resolve stack trace documentation. --- sql/stacktrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 73a7ecdc7ba..fa9ab093f26 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -197,7 +197,7 @@ terribly wrong...\n"); fprintf(stderr, "Stack trace seems successful - bottom reached\n"); end: - fprintf(stderr, "Please read http://www.mysql.com/doc/en/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\ + fprintf(stderr, "Please read http://dev.mysql.com/doc/mysql/en/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\ stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } From 62a42f7f5723214393a4e3c57098a5466f58e985 Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Sun, 19 Sep 2004 16:15:01 +0500 Subject: [PATCH 054/143] A fix (Bug #5415: Table marked as crashed after DELETE queries). --- sql/sql_delete.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 555e63b9e32..92193e3abf2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -282,6 +282,8 @@ multi_delete::initialize_tables(JOIN *join) walk=walk->next; /* Don't use KEYREAD optimization on this table */ tbl->no_keyread=1; + /* Don't use record cache */ + tbl->no_cache= 1; tbl->used_keys= 0; if (tbl->file->has_transactions()) log_delayed= transactional_tables= 1; From 87a8e833aeeb8c8bdf89de493279e4a68bb92709 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Mon, 20 Sep 2004 17:58:11 +0200 Subject: [PATCH 055/143] When coyright text is changed, autotools must be run after all other actions, as otherwise timestamps of "config.h.in" will cause re-run on compilation machine (fatal version problem!). --- Build-tools/mysql-copyright | 140 ++++++++++++++++++++++++++++-------- 1 file changed, 112 insertions(+), 28 deletions(-) diff --git a/Build-tools/mysql-copyright b/Build-tools/mysql-copyright index a1869304ba7..251a6c78d23 100755 --- a/Build-tools/mysql-copyright +++ b/Build-tools/mysql-copyright @@ -1,9 +1,9 @@ -#!/usr/bin/perl -i +#!/usr/bin/perl -wi # Untar a MySQL distribution, change the copyright texts, # pack it up again to a given directory -$VER="1.3"; +$VER="1.4"; use Cwd; use File::Basename; @@ -79,7 +79,7 @@ sub main $newdistname .= $suffix if $win_flag; } # find out the extract path (should be same as distname!) - chomp($destdir = `tar ztf ../$distfile | head -1`); + chomp($destdir= `tar ztf ../$distfile | head -1`); # remove slash from the end $destdir= substr($destdir, 0, -1); @@ -104,37 +104,25 @@ sub main unlink("$destdir/COPYING", "$destdir/EXCEPTIONS-CLIENT"); copy("$WD/Docs/MySQLEULA.txt", "$destdir"); - # remove readline subdir and update configure accordingly - system("rm -rf $destdir/cmd-line-utils/readline"); - if ($win_flag) { - chdir("$destdir") or (print "$! Unable to change directory to $destdir!\n" && exit(0)); - } else { - chdir("$destdir"); - unlink ("configure") or die "Can't delete $destdir/configure: $!\n"; - open(CONFIGURE,"; - close(CONFIGURE); - $configure =~ s|cmd\-line\-utils/readline/Makefile dnl\n?||g; - open(CONFIGURE,">configure.in") or die "$! Unable to open configure.in to write to!\n"; - print CONFIGURE $configure; - close(CONFIGURE); - `aclocal && autoheader && aclocal && automake && autoconf`; - if (! -f "configure") { - print "\"./configure\" was not produced, exiting!\n"; - exit(0); - } - if (-d "autom4te.cache") { - print "Trying to delete autom4te.cache dir\n" if $opt_verbose; - system("rm -rf autom4te.cache") or print "Unable to delete autom4te.cache dir: $!\n"; - } + # remove subdirectories 'bdb', 'cmd-line-utils/readline' + # (latter does not apply to 4.0, but is in different place there!) + my @extra_fat= ('bdb', 'cmd-line-utils/readline'); + + foreach my $fat (@extra_fat) + { + &trim_the_fat($fat); } # fix file copyrights &fix_usage_copyright(); &add_copyright(); + # fix LICENSE tag in include/mysql_version.h + &fix_mysql_version(); + + # apply "autotools" - must be last to ensure proper timestamps + &run_autotools(); + # rename the directory with new distribution name chdir("$WD/$dir"); print "renaming $destdir $newdistname\n" if $opt_verbose; @@ -160,6 +148,101 @@ sub main exit(0); } +#### +#### This function will s/GPL/Commercial/ in include/mysql_version.h for the +#### LICENSE tag. +#### +sub fix_mysql_version +{ + my $cwd= getcwd(); + chdir("$destdir"); + my $header_file= (-f 'include/mysql_version.h.in')? 'include/mysql_version.h.in' : 'include/mysql_version.h'; + + open(MYSQL_VERSION,"<$header_file") or die "Unable to open $header_file for read: $!\n"; + undef $/; + my $mysql_version= ; + close(MYSQL_VERSION); + + $mysql_version=~ s/\#define LICENSE[\s\t]+GPL/#define LICENSE Commercial/; + + open(MYSQL_VERSION,">$header_file") or die "Unable to open $header_file for write: $!\n"; + print MYSQL_VERSION $mysql_version; + close(MYSQL_VERSION); + chdir("$cwd"); +} + +#### +#### This function will remove unwanted parts of a src tree for the mysqlcom +#### distributions. +#### +sub trim_the_fat +{ + my $the_fat= shift; + my $cwd= getcwd(); + + chdir("$destdir"); + if ( -d "${the_fat}" ) + { + system("rm -rf ${the_fat}"); + if (!$win_flag) + { + open(CONFIG_IN,"; + close(CONFIG_IN); + + # + # If $the_fat Makefile line closes the parenthesis, then + # replace that line with just the closing parenthesis. + # + if ($config_in=~ m|${the_fat}/Makefile\)\n?|) + { + $config_in=~ s|${the_fat}/Makefile(\)\n?)|$1|; + } + # + # Else just delete the line + # + else + { + $config_in=~ s|${the_fat}/Makefile dnl\n?||; + } + + open(CONFIG_IN,">configure.in") or die "Unable to open configure.in for write: $!\n"; + print CONFIG_IN $config_in; + close(CONFIG_IN); + } + } + chdir("$cwd"); +} + + +#### +#### This function will run the autotools on the reduced source tree. +#### +sub run_autotools +{ + my $cwd= getcwd(); + + if (!$win_flag) + { + chdir("$destdir"); + unlink ("configure") or die "Can't delete $destdir/configure: $!\n"; + + # File "configure.in" has already been modified by "trim_the_fat()" + + `aclocal && autoheader && aclocal && automake && autoconf`; + die "'./configure' was not produced!" unless (-f "configure"); + + if (-d "autom4te.cache") { + print "Trying to delete autom4te.cache dir\n" if $opt_verbose; + system("rm -rf autom4te.cache") or print "Unable to delete autom4te.cache dir: $!\n"; + } + + chdir("$cwd"); + } +} + + #### #### mysqld and MySQL client programs have a usage printed with --help. #### This usage includes a copyright, which needs to be modified @@ -191,6 +274,7 @@ sub add_copyright foreach my $file (@files) { next if ! -f $file; + next if -B $file; print "processing file $file in cwd $cwd\n" if $opt_verbose; `$WD/Build-tools/mysql-copyright-2 "$file"`; } From 389d418cd201b1dbc25f4ca96134c29c0dc9080d Mon Sep 17 00:00:00 2001 From: "antony@ltantony.rdg.cyberkinetica.homeunix.net" <> Date: Wed, 22 Sep 2004 11:28:37 +0100 Subject: [PATCH 056/143] Bug#5655 - mysqldump fields-escaped-by behaviour Fix initialization --- client/mysqldump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 6dad8182b87..49822f0bee0 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -150,7 +150,7 @@ static struct my_option my_long_options[] = "Fields in the i.file are opt. enclosed by ...", (gptr*) &opt_enclosed, (gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...", - (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, NO_ARG, 0, 0, 0, 0, 0, 0}, + (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"first-slave", 'x', "Locks all tables across all databases.", (gptr*) &opt_first_slave, (gptr*) &opt_first_slave, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, From 6e0ba8e615a7d58277dd4b78def08c7af02c3a10 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Wed, 22 Sep 2004 16:29:15 +0400 Subject: [PATCH 057/143] Fix for BUG#4785: * myisampack leaves key_file_length value from original table * myisamchk uses this value when calculating key file pointer length --- include/myisam.h | 1 + myisam/mi_check.c | 2 +- myisam/mi_create.c | 13 +++++++++---- myisam/myisampack.c | 6 +++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index 87a40b50c73..cad48e2d331 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -96,6 +96,7 @@ typedef struct st_mi_create_info ha_rows reloc_rows; ulonglong auto_increment; ulonglong data_file_length; + ulonglong key_file_length; uint raid_type,raid_chunks; ulong raid_chunksize; uint old_options; diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 078f7787dc3..e78d831fde7 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3520,7 +3520,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename) create_info.raid_chunksize= share.base.raid_chunksize; create_info.language = (param->language ? param->language : share.state.header.language); - + create_info.key_file_length= status_info.key_file_length; /* We don't have to handle symlinks here because we are using HA_DONT_TOUCH_DATA */ if (mi_create(filename, diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 328450c70db..99e9ca5ba5f 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -46,7 +46,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, ulong reclength, real_reclength,min_pack_length; char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr; ulong pack_reclength; - ulonglong tot_length,max_rows; + ulonglong tot_length,max_rows, tmp; enum en_fieldtype type; MYISAM_SHARE share; MI_KEYDEF *keydef,tmp_keydef; @@ -442,10 +442,15 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.state.auto_increment=ci->auto_increment; share.options=options; share.base.rec_reflength=pointer; + /* Get estimate for index file length (this may be wrong for FT keys) */ + tmp= (tot_length + max_key_block_length * keys * + MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH; + /* + use maximum of key_file_length we calculated and key_file_length value we + got from MYI file header (see also myisampack.c:save_state) + */ share.base.key_reflength= - mi_get_pointer_length((tot_length + max_key_block_length * keys * - MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH, - 3); + mi_get_pointer_length(max(ci->key_file_length,tmp),3); share.base.keys= share.state.header.keys = keys; share.state.header.uniques= uniques; mi_int2store(share.state.header.key_parts,key_segs); diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 872fcb49faf..4b784641266 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -2041,7 +2041,11 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->state.split=(ha_rows) mrg->records; share->state.version=(ulong) time((time_t*) 0); share->state.key_map=0; - share->state.state.key_file_length=share->base.keystart; + /* + Don't save key_file_length here, keep key_file_length of original file + so "myisamchk -rq" can use this value (this is necessary because index + size cannot be easily calculated for fulltext keys) + */ for (key=0 ; key < share->base.keys ; key++) share->state.key_root[key]= HA_OFFSET_ERROR; for (key=0 ; key < share->state.header.max_block_size ; key++) From 564b8edb456601583fbd602b061a21cc78ebbd6f Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Thu, 23 Sep 2004 14:43:31 +0200 Subject: [PATCH 058/143] Fix for BUG#5711 "replication SQL thread does not abort on SQL syntax error": in net_printf(), we fill net->last_* variables for the slave SQL thread to know the error. --- sql/net_pkg.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc index cc9147fe90a..df77d0347f2 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -132,6 +132,10 @@ net_printf(NET *net, uint errcode, ...) length=sizeof(net->last_error)-1; /* purecov: inspected */ va_end(args); + /* Replication slave relies on net->last_* to see if there was error */ + net->last_errno= errcode; + strmake(net->last_error, text_pos, sizeof(net->last_error)-1); + if (net->vio == 0) { if (thd && thd->bootstrap) From 6ba5a570094716dcf294253738f15bdbb8aa2f80 Mon Sep 17 00:00:00 2001 From: "rburnett@build.mysql.com" <> Date: Thu, 23 Sep 2004 17:53:46 +0200 Subject: [PATCH 059/143] os0file.c: Added #ifdef around is_set in os_aio_print --- innobase/os/os0file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 70ef8f55b98..b09c48319c3 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2965,9 +2965,11 @@ os_aio_print( srv_io_thread_op_info[i], srv_io_thread_function[i]); +#ifndef __WIN__ if (os_aio_segment_wait_events[i]->is_set) { fprintf(file, " ev set"); } +#endif fprintf(file, "\n"); } From de9a058bfe17e2cd4f628d712b70f7af854e58e5 Mon Sep 17 00:00:00 2001 From: "rburnett@build.mysql.com" <> Date: Fri, 24 Sep 2004 09:00:14 +0200 Subject: [PATCH 060/143] Bug #5539 SHOW DATABASES LIKE and symlinks sql_show.cc: Added wild card check to symdir block in mysql_find_files --- sql/sql_show.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6784cd64465..d82af1a6242 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -204,7 +204,8 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, if (end != buff && end[-1] == FN_LIBCHAR) end[-1]= 0; // Remove end FN_LIBCHAR if (!my_stat(buff, &status, MYF(0)) || - !MY_S_ISDIR(status.st_mode)) + !MY_S_ISDIR(status.st_mode) || + (wild && wild_compare(file->name, wild, 0))) continue; } else From 53d0daa3a0e5548e8226d228727ed056fb82fb99 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Fri, 24 Sep 2004 11:54:37 +0200 Subject: [PATCH 061/143] Fix for BUG#3248 "Doc says MyISAM warns if disk full but it does not": we force the message to the error log, and we make it more informative; we treat EDQUOT like ENOSPC. --- mysys/errors.c | 2 +- mysys/my_fstream.c | 14 ++++++++------ mysys/my_pread.c | 9 +++++---- mysys/my_write.c | 5 +++-- mysys/mysys_priv.h | 8 ++++++++ sql/mysqld.cc | 5 ++--- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/mysys/errors.c b/mysys/errors.c index 7d755718b16..e21609f6e94 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -41,7 +41,7 @@ const char * NEAR globerrs[GLOBERRS]= "Can't change dir to '%s' (Errcode: %d)", "Warning: '%s' had %d links", "%d files and %d streams is left open\n", - "Disk is full writing '%s'. Waiting for someone to free space...", + "Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... Retry in %d secs", "Can't create directory '%s' (Errcode: %d)", "Character set '%s' is not a compiled character set and is not specified in the '%s' file", "Out of resources when opening file '%s' (Errcode: %d)", diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index 94f3aaf3464..0ad789e98ac 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -114,13 +114,15 @@ uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags) if (my_thread_var->abort) MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ #endif - if (errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL)) + if ((errno == ENOSPC || errno == EDQUOT) && + (MyFlags & MY_WAIT_IF_FULL)) { - if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE)) - my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH)); - sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); - VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0))); - continue; + if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE)) + my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH), + "[stream]",my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC); + VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC)); + VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0))); + continue; } #endif if (ferror(stream) || (MyFlags & (MY_NABP | MY_FNABP))) diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 661ef48ab3e..f76233fc4cc 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -115,11 +115,12 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, if (my_thread_var->abort) MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ #endif - if (my_errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL)) + if ((my_errno == ENOSPC || my_errno == EDQUOT) && + (MyFlags & MY_WAIT_IF_FULL)) { if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE)) my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH), - my_filename(Filedes)); + my_filename(Filedes),my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC); VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC)); continue; } @@ -131,7 +132,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, { if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), + my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG), my_filename(Filedes),my_errno); } DBUG_RETURN(MY_FILE_ERROR); /* Error on read */ @@ -142,4 +143,4 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, if (MyFlags & (MY_NABP | MY_FNABP)) DBUG_RETURN(0); /* Want only errors */ DBUG_RETURN(writenbytes+written); /* purecov: inspected */ -} /* my_write */ +} /* my_pwrite */ diff --git a/mysys/my_write.c b/mysys/my_write.c index 61fd6097e28..da378d115f1 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -48,12 +48,13 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) if (my_thread_var->abort) MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ #endif - if (my_errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL) && + if ((my_errno == ENOSPC || my_errno == EDQUOT) && + (MyFlags & MY_WAIT_IF_FULL) && (uint) writenbytes != (uint) -1) { if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE)) my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH), - my_filename(Filedes)); + my_filename(Filedes),my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC); VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC)); continue; } diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index f79431a0b0b..d7aee04ae20 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -29,3 +29,11 @@ extern pthread_mutex_t THR_LOCK_charset; #else #include #endif + +/* + EDQUOT is used only in 3 C files only in mysys/. If it does not exist on + system, we set it to some value which can never happen. +*/ +#ifndef EDQUOT +#define EDQUOT (-1) +#endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 06599cf0ea7..834cff0d869 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2080,8 +2080,7 @@ static void check_data_home(const char *path) /* ARGSUSED */ -extern "C" int my_message_sql(uint error, const char *str, - myf MyFlags __attribute__((unused))) +extern "C" int my_message_sql(uint error, const char *str, myf MyFlags) { NET *net; DBUG_ENTER("my_message_sql"); @@ -2094,7 +2093,7 @@ extern "C" int my_message_sql(uint error, const char *str, net->last_errno=error ? error : ER_UNKNOWN_ERROR; } } - else + if (!net || MyFlags & ME_NOREFRESH) sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */ DBUG_RETURN(0); } From e47decfa7f2e984558d3dc48d19dd94d8ec0b956 Mon Sep 17 00:00:00 2001 From: "ingo@mysql.com" <> Date: Fri, 24 Sep 2004 18:39:25 +0200 Subject: [PATCH 062/143] BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. --- mysql-test/r/flush_table.result | 101 +++-- mysql-test/r/handler.result | 244 ++++++++++++ mysql-test/t/flush_table.test | 84 ++--- mysql-test/t/handler.test | 204 ++++++++++ sql/mysql_priv.h | 11 +- sql/sql_base.cc | 6 +- sql/sql_class.cc | 15 +- sql/sql_class.h | 1 + sql/sql_handler.cc | 644 +++++++++++++++++++++++--------- sql/sql_table.cc | 6 +- 10 files changed, 999 insertions(+), 317 deletions(-) diff --git a/mysql-test/r/flush_table.result b/mysql-test/r/flush_table.result index cfba428e2e8..ff69291193f 100644 --- a/mysql-test/r/flush_table.result +++ b/mysql-test/r/flush_table.result @@ -7,58 +7,6 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -drop database if exists test_test; -create database test_test; -use test_test; -create table t1(table_id char(20) primary key); -insert into t1 values ('test_test.t1'); -insert into t1 values (''); -handler t1 open; -handler t1 read first limit 9; -table_id -test_test.t1 - -create table t2(table_id char(20) primary key); -insert into t2 values ('test_test.t2'); -insert into t2 values (''); -handler t2 open; -handler t2 read first limit 9; -table_id -test_test.t2 - -use test; -drop table if exists t1; -create table t1(table_id char(20) primary key); -insert into t1 values ('test.t1'); -insert into t1 values (''); -handler t1 open; -handler t1 read first limit 9; -table_id -test.t1 - -use test; -handler test.t1 read first limit 9; -table_id -test.t1 - -handler test.t2 read first limit 9; -Unknown table 't2' in HANDLER -handler test_test.t1 read first limit 9; -table_id -test_test.t1 - -handler test_test.t2 read first limit 9; -table_id -test_test.t2 - -handler test_test.t1 close; -drop table test_test.t1; -handler test_test.t2 close; -drop table test_test.t2; -drop database test_test; -use test; -handler test.t1 close; -drop table test.t1; drop table if exists t1; drop table if exists t2; create table t1(table_id char(20) primary key); @@ -84,14 +32,23 @@ test.t2 flush tables; handler a1 read first limit 9; -Unknown table 'a1' in HANDLER +table_id +test.t1 + handler a2 read first limit 9; -Unknown table 'a2' in HANDLER +table_id +test.t1 + handler t2 read first limit 9; -Unknown table 't2' in HANDLER +table_id +test.t2 + handler t1 open as a1; +Not unique table/alias: 'a1' handler t1 open as a2; +Not unique table/alias: 'a2' handler t2 open; +Not unique table/alias: 't2' handler a1 read first limit 9; table_id test.t1 @@ -106,15 +63,43 @@ test.t2 flush table t1; handler a1 read first limit 9; -Unknown table 'a1' in HANDLER +table_id +test.t1 + handler a2 read first limit 9; -Unknown table 'a2' in HANDLER +table_id +test.t1 + handler t2 read first limit 9; table_id test.t2 flush table t2; handler t2 close; -Unknown table 't2' in HANDLER drop table t1; drop table t2; +create table t1(table_id char(20) primary key); +insert into t1 values ('Record-01'); +insert into t1 values ('Record-02'); +insert into t1 values ('Record-03'); +insert into t1 values ('Record-04'); +insert into t1 values ('Record-05'); +handler t1 open; +handler t1 read first limit 1; +table_id +Record-01 +handler t1 read next limit 1; +table_id +Record-02 +handler t1 read next limit 1; +table_id +Record-03 +flush table t1; +handler t1 read next limit 1; +table_id +Record-01 +handler t1 read next limit 1; +table_id +Record-02 +handler t1 close; +drop table t1; diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result index 50d51cf14f4..5af153930d5 100644 --- a/mysql-test/r/handler.result +++ b/mysql-test/r/handler.result @@ -203,3 +203,247 @@ handler t1 read a=(1) where b=1; a b handler t1 close; drop table t1; +drop database if exists test_test; +create database test_test; +use test_test; +create table t1(table_id char(20) primary key); +insert into t1 values ('test_test.t1'); +insert into t1 values (''); +handler t1 open; +handler t1 read first limit 9; +table_id +test_test.t1 + +create table t2(table_id char(20) primary key); +insert into t2 values ('test_test.t2'); +insert into t2 values (''); +handler t2 open; +handler t2 read first limit 9; +table_id +test_test.t2 + +use test; +drop table if exists t1; +create table t1(table_id char(20) primary key); +insert into t1 values ('test.t1'); +insert into t1 values (''); +handler t1 open; +Not unique table/alias: 't1' +use test; +handler test.t1 read first limit 9; +Unknown table 'test.t1' in HANDLER +handler test_test.t1 read first limit 9; +table_id +test_test.t1 + +handler t1 read first limit 9; +table_id +test_test.t1 + +handler test_test.t2 read first limit 9; +table_id +test_test.t2 + +handler t2 read first limit 9; +table_id +test_test.t2 + +handler test_test.t1 close; +handler t1 close; +Unknown table 't1' in HANDLER +drop table test_test.t1; +handler test_test.t2 close; +handler t2 close; +Unknown table 't2' in HANDLER +drop table test_test.t2; +drop database test_test; +use test; +handler test.t1 close; +Unknown table 'test.t1' in HANDLER +handler t1 close; +Unknown table 't1' in HANDLER +drop table test.t1; +drop database if exists test_test; +drop table if exists t1; +drop table if exists t2; +drop table if exists t3; +create database test_test; +use test_test; +create table t1 (c1 char(20)); +insert into t1 values ('test_test.t1'); +create table t3 (c1 char(20)); +insert into t3 values ('test_test.t3'); +handler t1 open; +handler t1 read first limit 9; +c1 +test_test.t1 +handler t1 open h1; +handler h1 read first limit 9; +c1 +test_test.t1 +use test; +create table t1 (c1 char(20)); +create table t2 (c1 char(20)); +create table t3 (c1 char(20)); +insert into t1 values ('t1'); +insert into t2 values ('t2'); +insert into t3 values ('t3'); +handler t1 open; +Not unique table/alias: 't1' +handler t2 open t1; +Not unique table/alias: 't1' +handler t3 open t1; +Not unique table/alias: 't1' +handler t1 read first limit 9; +c1 +test_test.t1 +handler test.t1 close; +Unknown table 'test.t1' in HANDLER +handler test.t1 open h1; +Not unique table/alias: 'h1' +handler test_test.t1 open h1; +Not unique table/alias: 'h1' +handler test_test.t3 open h3; +handler test.t1 open h2; +handler t1 read first limit 9; +c1 +test_test.t1 +handler h1 read first limit 9; +c1 +test_test.t1 +handler h2 read first limit 9; +c1 +t1 +handler h3 read first limit 9; +c1 +test_test.t3 +handler test.h2 read first limit 9; +c1 +t1 +handler test.h1 close; +Unknown table 'test.h1' in HANDLER +handler test_test.t1 close; +handler test_test.h1 close; +handler h2 close; +handler t1 read first limit 9; +Unknown table 't1' in HANDLER +handler h1 read first limit 9; +Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +Unknown table 'h2' in HANDLER +handler h3 read first limit 9; +c1 +test_test.t3 +handler test_test.h3 read first limit 9; +c1 +test_test.t3 +use test_test; +handler h3 read first limit 9; +c1 +test_test.t3 +handler test.h3 read first limit 9; +Unknown table 'test.h3' in HANDLER +handler test_test.h3 close; +use test; +drop table t3; +drop table t2; +drop table t1; +drop database test_test; +create table t1 (c1 char(20)); +insert into t1 values ("t1"); +handler t1 open as h1; +handler h1 read first limit 9; +c1 +t1 +create table t2 (c1 char(20)); +insert into t2 values ("t2"); +handler t2 open as h2; +handler h2 read first limit 9; +c1 +t2 +create table t3 (c1 char(20)); +insert into t3 values ("t3"); +handler t3 open as h3; +handler h3 read first limit 9; +c1 +t3 +create table t4 (c1 char(20)); +insert into t4 values ("t4"); +handler t4 open as h4; +handler h4 read first limit 9; +c1 +t4 +create table t5 (c1 char(20)); +insert into t5 values ("t5"); +handler t5 open as h5; +handler h5 read first limit 9; +c1 +t5 +alter table t1 engine=MyISAM; +handler h1 read first limit 9; +Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +c1 +t2 +handler h3 read first limit 9; +c1 +t3 +handler h4 read first limit 9; +c1 +t4 +handler h5 read first limit 9; +c1 +t5 +alter table t5 engine=MyISAM; +handler h1 read first limit 9; +Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +c1 +t2 +handler h3 read first limit 9; +c1 +t3 +handler h4 read first limit 9; +c1 +t4 +handler h5 read first limit 9; +Unknown table 'h5' in HANDLER +alter table t3 engine=MyISAM; +handler h1 read first limit 9; +Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +c1 +t2 +handler h3 read first limit 9; +Unknown table 'h3' in HANDLER +handler h4 read first limit 9; +c1 +t4 +handler h5 read first limit 9; +Unknown table 'h5' in HANDLER +handler h2 close; +handler h4 close; +handler t1 open as h1_1; +handler t1 open as h1_2; +handler t1 open as h1_3; +handler h1_1 read first limit 9; +c1 +t1 +handler h1_2 read first limit 9; +c1 +t1 +handler h1_3 read first limit 9; +c1 +t1 +alter table t1 engine=MyISAM; +handler h1_1 read first limit 9; +Unknown table 'h1_1' in HANDLER +handler h1_2 read first limit 9; +Unknown table 'h1_2' in HANDLER +handler h1_3 read first limit 9; +Unknown table 'h1_3' in HANDLER +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; diff --git a/mysql-test/t/flush_table.test b/mysql-test/t/flush_table.test index ad81f266afc..58c12bad3fa 100644 --- a/mysql-test/t/flush_table.test +++ b/mysql-test/t/flush_table.test @@ -12,63 +12,10 @@ flush table t1; check table t1; drop table t1; -# -# Check if two database names beginning the same are seen as different. -# -# This database begins like the usual 'test' database. -# ---disable_warnings -drop database if exists test_test; ---enable_warnings -create database test_test; -use test_test; -create table t1(table_id char(20) primary key); -insert into t1 values ('test_test.t1'); -insert into t1 values (''); -handler t1 open; -handler t1 read first limit 9; -create table t2(table_id char(20) primary key); -insert into t2 values ('test_test.t2'); -insert into t2 values (''); -handler t2 open; -handler t2 read first limit 9; -# -# This is the usual 'test' database. -# -use test; ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1(table_id char(20) primary key); -insert into t1 values ('test.t1'); -insert into t1 values (''); -handler t1 open; -handler t1 read first limit 9; -# -# Check accesibility of all the tables. -# -use test; -handler test.t1 read first limit 9; ---error 1109; -handler test.t2 read first limit 9; -handler test_test.t1 read first limit 9; -handler test_test.t2 read first limit 9; -# -# Cleanup. -# -handler test_test.t1 close; -drop table test_test.t1; -handler test_test.t2 close; -drop table test_test.t2; -drop database test_test; -# -use test; -handler test.t1 close; -drop table test.t1; - # # In the following test FLUSH TABLES produces a deadlock -# (hang forever) if the fix for bug#3565 is missing. +# (hang forever) if the fix for BUG #3565 is missing. +# And it shows that handler tables are re-opened after flush (BUG #4286). # --disable_warnings drop table if exists t1; @@ -87,28 +34,43 @@ handler a1 read first limit 9; handler a2 read first limit 9; handler t2 read first limit 9; flush tables; ---error 1109; handler a1 read first limit 9; ---error 1109; handler a2 read first limit 9; ---error 1109; handler t2 read first limit 9; # +--error 1066 handler t1 open as a1; +--error 1066 handler t1 open as a2; +--error 1066 handler t2 open; handler a1 read first limit 9; handler a2 read first limit 9; handler t2 read first limit 9; flush table t1; ---error 1109; handler a1 read first limit 9; ---error 1109; handler a2 read first limit 9; handler t2 read first limit 9; flush table t2; ---error 1109; handler t2 close; drop table t1; drop table t2; +# +# The fix for BUG #4286 cannot restore the position after a flush. +# +create table t1(table_id char(20) primary key); +insert into t1 values ('Record-01'); +insert into t1 values ('Record-02'); +insert into t1 values ('Record-03'); +insert into t1 values ('Record-04'); +insert into t1 values ('Record-05'); +handler t1 open; +handler t1 read first limit 1; +handler t1 read next limit 1; +handler t1 read next limit 1; +flush table t1; +handler t1 read next limit 1; +handler t1 read next limit 1; +handler t1 close; +drop table t1; diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test index 1f7f32c930a..53fe8c0a059 100644 --- a/mysql-test/t/handler.test +++ b/mysql-test/t/handler.test @@ -135,3 +135,207 @@ handler t1 read a=(1) where b=1; handler t1 close; drop table t1; +# +# Check if two database names beginning the same are seen as different. +# +# This database begins like the usual 'test' database. +# +--disable_warnings +drop database if exists test_test; +--enable_warnings +create database test_test; +use test_test; +create table t1(table_id char(20) primary key); +insert into t1 values ('test_test.t1'); +insert into t1 values (''); +handler t1 open; +handler t1 read first limit 9; +create table t2(table_id char(20) primary key); +insert into t2 values ('test_test.t2'); +insert into t2 values (''); +handler t2 open; +handler t2 read first limit 9; +# +# This is the usual 'test' database. +# +use test; +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1(table_id char(20) primary key); +insert into t1 values ('test.t1'); +insert into t1 values (''); +--error 1066 +handler t1 open; +# +# Check accesibility of all the tables. +# +use test; +--error 1109; +handler test.t1 read first limit 9; +handler test_test.t1 read first limit 9; +handler t1 read first limit 9; +handler test_test.t2 read first limit 9; +handler t2 read first limit 9; +# +# Cleanup. +# + +handler test_test.t1 close; +--error 1109; +handler t1 close; +drop table test_test.t1; +handler test_test.t2 close; +--error 1109; +handler t2 close; +drop table test_test.t2; +drop database test_test; +# +use test; +--error 1109; +handler test.t1 close; +--error 1109; +handler t1 close; +drop table test.t1; + +# +# BUG#4335 +# +--disable_warnings +drop database if exists test_test; +drop table if exists t1; +drop table if exists t2; +drop table if exists t3; +--enable_warnings +create database test_test; +use test_test; +create table t1 (c1 char(20)); +insert into t1 values ('test_test.t1'); +create table t3 (c1 char(20)); +insert into t3 values ('test_test.t3'); +handler t1 open; +handler t1 read first limit 9; +handler t1 open h1; +handler h1 read first limit 9; +use test; +create table t1 (c1 char(20)); +create table t2 (c1 char(20)); +create table t3 (c1 char(20)); +insert into t1 values ('t1'); +insert into t2 values ('t2'); +insert into t3 values ('t3'); +--error 1066 +handler t1 open; +--error 1066 +handler t2 open t1; +--error 1066 +handler t3 open t1; +handler t1 read first limit 9; +--error 1109 +handler test.t1 close; +--error 1066 +handler test.t1 open h1; +--error 1066 +handler test_test.t1 open h1; +handler test_test.t3 open h3; +handler test.t1 open h2; +handler t1 read first limit 9; +handler h1 read first limit 9; +handler h2 read first limit 9; +handler h3 read first limit 9; +handler test.h2 read first limit 9; +--error 1109 +handler test.h1 close; +handler test_test.t1 close; +handler test_test.h1 close; +handler h2 close; +--error 1109 +handler t1 read first limit 9; +--error 1109 +handler h1 read first limit 9; +--error 1109 +handler h2 read first limit 9; +handler h3 read first limit 9; +handler test_test.h3 read first limit 9; +use test_test; +handler h3 read first limit 9; +--error 1109 +handler test.h3 read first limit 9; +handler test_test.h3 close; +use test; +drop table t3; +drop table t2; +drop table t1; +drop database test_test; + +# +# Test if fix for BUG#4286 correctly closes handler tables. +# +create table t1 (c1 char(20)); +insert into t1 values ("t1"); +handler t1 open as h1; +handler h1 read first limit 9; +create table t2 (c1 char(20)); +insert into t2 values ("t2"); +handler t2 open as h2; +handler h2 read first limit 9; +create table t3 (c1 char(20)); +insert into t3 values ("t3"); +handler t3 open as h3; +handler h3 read first limit 9; +create table t4 (c1 char(20)); +insert into t4 values ("t4"); +handler t4 open as h4; +handler h4 read first limit 9; +create table t5 (c1 char(20)); +insert into t5 values ("t5"); +handler t5 open as h5; +handler h5 read first limit 9; +# close first +alter table t1 engine=MyISAM; +--error 1109; +handler h1 read first limit 9; +handler h2 read first limit 9; +handler h3 read first limit 9; +handler h4 read first limit 9; +handler h5 read first limit 9; +# close last +alter table t5 engine=MyISAM; +--error 1109; +handler h1 read first limit 9; +handler h2 read first limit 9; +handler h3 read first limit 9; +handler h4 read first limit 9; +--error 1109; +handler h5 read first limit 9; +# close middle +alter table t3 engine=MyISAM; +--error 1109; +handler h1 read first limit 9; +handler h2 read first limit 9; +--error 1109; +handler h3 read first limit 9; +handler h4 read first limit 9; +--error 1109; +handler h5 read first limit 9; +handler h2 close; +handler h4 close; +# close all depending handler tables +handler t1 open as h1_1; +handler t1 open as h1_2; +handler t1 open as h1_3; +handler h1_1 read first limit 9; +handler h1_2 read first limit 9; +handler h1_3 read first limit 9; +alter table t1 engine=MyISAM; +--error 1109; +handler h1_1 read first limit 9; +--error 1109; +handler h1_2 read first limit 9; +--error 1109; +handler h1_3 read first limit 9; +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index acc07eb6188..8b41774e970 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -540,12 +540,15 @@ int mysql_find_files(THD *thd,List *files, const char *db, const char *path, const char *wild, bool dir); /* sql_handler.cc */ -int mysql_ha_open(THD *thd, TABLE_LIST *tables); -int mysql_ha_close(THD *thd, TABLE_LIST *tables, - bool dont_send_ok=0, bool dont_lock=0, bool no_alias=0); -int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed=0); +int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0); +int mysql_ha_close(THD *thd, TABLE_LIST *tables); int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List *,enum ha_rkey_function,Item *,ha_rows,ha_rows); +int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags); +/* mysql_ha_flush mode_flags bits */ +#define MYSQL_HA_CLOSE_FINAL 0x00 +#define MYSQL_HA_REOPEN_ON_USAGE 0x01 +#define MYSQL_HA_FLUSH_ALL 0x02 /* sql_base.cc */ void set_item_name(Item *item,char *pos,uint length); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8fd7273fd78..1ecd606f7d9 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -389,7 +389,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, thd->proc_info="Flushing tables"; close_old_data_files(thd,thd->open_tables,1,1); - mysql_ha_close_list(thd, tables); + mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL); bool found=1; /* Wait until all threads has closed all the tables we had locked */ DBUG_PRINT("info", ("Waiting for others threads to close their open tables")); @@ -859,7 +859,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, } /* close handler tables which are marked for flush */ - mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1); + mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE); for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; table && table->in_use ; @@ -1226,7 +1226,7 @@ bool wait_for_tables(THD *thd) { thd->some_tables_deleted=0; close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0); - mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1); + mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE); if (!table_is_used(thd->open_tables,1)) break; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index eb6e74a58c4..c829778151b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -78,9 +78,9 @@ extern "C" void free_user_var(user_var_entry *entry) ** Thread specific functions ****************************************************************************/ -THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), - insert_id_used(0),rand_used(0),in_lock_tables(0), - global_read_lock(0),bootstrap(0) +THD::THD():user_time(0),global_read_lock(0),fatal_error(0), + last_insert_id_used(0),insert_id_used(0),rand_used(0), + in_lock_tables(0),bootstrap(0) { host=user=priv_user=db=query=ip=0; host_or_ip= "connecting host"; @@ -90,6 +90,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), query_error=0; next_insert_id=last_insert_id=0; open_tables=temporary_tables=handler_tables=0; + hash_clear(&handler_tables_hash); current_tablenr=0; handler_items=0; tmp_table=0; @@ -215,11 +216,9 @@ void THD::cleanup(void) lock=locked_tables; locked_tables=0; close_thread_tables(this); } - if (handler_tables) - { - open_tables=handler_tables; handler_tables=0; - close_thread_tables(this); - } + mysql_ha_flush(this, (TABLE_LIST*) 0, + MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL); + hash_free(&handler_tables_hash); close_temporary_tables(this); hash_free(&user_vars); if (global_read_lock) diff --git a/sql/sql_class.h b/sql/sql_class.h index 30947041b7d..d84a5ba88ff 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -421,6 +421,7 @@ public: and are still in use by this thread */ TABLE *open_tables,*temporary_tables, *handler_tables; + HASH handler_tables_hash; // TODO: document the variables below MYSQL_LOCK *lock,*locked_tables; ULL *ull; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 272289b6176..f056651919f 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -17,10 +17,6 @@ /* HANDLER ... commands - direct access to ISAM */ -#include "mysql_priv.h" -#include "sql_select.h" -#include - /* TODO: HANDLER blabla OPEN [ AS foobar ] [ (column-list) ] @@ -38,34 +34,215 @@ all the sql_alloc'ed memory. It's harder to work around... */ +/* + There are two containers holding information about open handler tables. + The first is 'thd->handler_tables'. It is a linked list of TABLE objects. + It is used like 'thd->open_tables' in the table cache. The trick is to + exchange these two lists during open and lock of tables. Thus the normal + table cache code can be used. + The second container is a HASH. It holds objects of the type TABLE_LIST. + Despite its name, no lists of tables but only single structs are hashed + (the 'next' pointer is always NULL). The reason for theis second container + is, that we want handler tables to survive FLUSH TABLE commands. A table + affected by FLUSH TABLE must be closed so that other threads are not + blocked by handler tables still in use. Since we use the normal table cache + functions with 'thd->handler_tables', the closed tables are removed from + this list. Hence we need the original open information for the handler + table in the case that it is used again. This information is handed over + to mysql_ha_open() as a TABLE_LIST. So we store this information in the + second container, where it is not affected by FLUSH TABLE. The second + container is implemented as a hash for performance reasons. Consequently, + we use it not only for re-opening a handler table, but also for the + HANDLER ... READ commands. For this purpose, we store a pointer to the + TABLE structure (in the first container) in the TBALE_LIST object in the + second container. When the table is flushed, the pointer is cleared. +*/ + +#include "mysql_priv.h" +#include "sql_select.h" +#include + +#define HANDLER_TABLES_HASH_SIZE 120 + +static enum enum_ha_read_modes rkey_to_rnext[]= + { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV }; + #define HANDLER_TABLES_HACK(thd) { \ TABLE *tmp=thd->open_tables; \ thd->open_tables=thd->handler_tables; \ thd->handler_tables=tmp; } -static TABLE **find_table_ptr_by_name(THD *thd,const char *db, - const char *table_name, - bool is_alias, bool dont_lock, - bool *was_flushed); +static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, int mode_flags); -int mysql_ha_open(THD *thd, TABLE_LIST *tables) + +/* + Get hash key and hash key length. + + SYNOPSIS + mysql_ha_hash_get_key() + tables Pointer to the hash object. + key_len_p (out) Pointer to the result for key length. + first Unused. + + DESCRIPTION + The hash object is an TABLE_LIST struct. + The hash key is the alias name. + The hash key length is the alias name length plus one for the + terminateing NUL character. + + RETURN + Pointer to the TABLE_LIST struct. +*/ + +static char *mysql_ha_hash_get_key(TABLE_LIST *tables, uint *key_len_p, + my_bool first __attribute__((unused))) { - HANDLER_TABLES_HACK(thd); - int err=open_tables(thd,tables); - HANDLER_TABLES_HACK(thd); - if (err) - return -1; + *key_len_p= strlen(tables->alias) + 1 ; /* include '\0' in comparisons */ + return tables->alias; +} - // there can be only one table in *tables - if (!(tables->table->file->table_flags() & HA_CAN_SQL_HANDLER)) + +/* + Free an hash object. + + SYNOPSIS + mysql_ha_hash_free() + tables Pointer to the hash object. + + DESCRIPTION + The hash object is an TABLE_LIST struct. + + RETURN + Nothing +*/ + +static void mysql_ha_hash_free(TABLE_LIST *tables) +{ + my_free((char*) tables, MYF(0)); +} + + +/* + Open a HANDLER table. + + SYNOPSIS + mysql_ha_open() + thd Thread identifier. + tables A list of tables with the first entry to open. + reopen Re-open a previously opened handler table. + + DESCRIPTION + Though this function takes a list of tables, only the first list entry + will be opened. + 'reopen' is set when a handler table is to be re-opened. In this case, + 'tables' is the pointer to the hashed TABLE_LIST object which has been + saved on the original open. + 'reopen' is also used to suppress the sending of an 'ok' message or + error messages. + + RETURN + 0 ok + != 0 error +*/ + +int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) +{ + TABLE_LIST *hash_tables; + char *db; + char *name; + char *alias; + uint dblen; + uint namelen; + uint aliaslen; + int err; + DBUG_ENTER("mysql_ha_open"); + DBUG_PRINT("enter",("mysql_ha_open: '%s'.'%s' as '%s' reopen %d", + tables->db, tables->real_name, tables->alias, reopen)); + + if (! hash_inited(&thd->handler_tables_hash)) { - my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias); - mysql_ha_close(thd, tables,1); - return -1; + /* + HASH entries are of type TABLE_LIST. + */ + if (hash_init(&thd->handler_tables_hash, HANDLER_TABLES_HASH_SIZE, 0, 0, + (hash_get_key) mysql_ha_hash_get_key, + (hash_free_key) mysql_ha_hash_free, 0)) + goto err; + } + else if (! reopen) /* Otherwise we have 'tables' already. */ + { + if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias, + strlen(tables->alias) + 1)) + { + DBUG_PRINT("info",("mysql_ha_open: duplicate '%s'", tables->alias)); + if (! reopen) + my_printf_error(ER_NONUNIQ_TABLE, ER(ER_NONUNIQ_TABLE), + MYF(0), tables->alias); + goto err; + } } - send_ok(&thd->net); - return 0; + /* + open_tables() will set 'tables->table' if successful. + It must be NULL for a real open when calling open_tables(). + */ + DBUG_ASSERT(! tables->table); + HANDLER_TABLES_HACK(thd); + err=open_tables(thd,tables); + HANDLER_TABLES_HACK(thd); + if (err) + goto err; + + /* There can be only one table in '*tables'. */ + if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER)) + { + if (! reopen) + my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias); + mysql_ha_close(thd, tables); + goto err; + } + + if (! reopen) + { + /* copy the TABLE_LIST struct */ + dblen= strlen(tables->db) + 1; + namelen= strlen(tables->real_name) + 1; + aliaslen= strlen(tables->alias) + 1; + if (!(my_multi_malloc(MYF(MY_WME), + &hash_tables, sizeof(*hash_tables), + &db, dblen, + &name, namelen, + &alias, aliaslen, + NullS))) + { + DBUG_PRINT("exit",("mysql_ha_open: malloc ERROR")); + goto err; + } + /* structure copy */ + *hash_tables= *tables; + hash_tables->db= db; + hash_tables->real_name= name; + hash_tables->alias= alias; + memcpy(hash_tables->db, tables->db, dblen); + memcpy(hash_tables->real_name, tables->real_name, namelen); + memcpy(hash_tables->alias, tables->alias, aliaslen); + + /* add to hash */ + if (hash_insert(&thd->handler_tables_hash, (byte*) hash_tables)) + { + mysql_ha_close(thd, tables); + goto err; + } + } + + if (! reopen) + send_ok(&thd->net); + DBUG_PRINT("exit",("mysql_ha_open: OK")); + DBUG_RETURN(0); + +err: + DBUG_PRINT("exit",("mysql_ha_open: ERROR")); + DBUG_RETURN(-1); } @@ -76,145 +253,185 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables) mysql_ha_close() thd Thread identifier. tables A list of tables with the first entry to close. - dont_send_ok Suppresses the commands' ok message and - error message and error return. - dont_lock Suppresses the normal locking of LOCK_open. DESCRIPTION Though this function takes a list of tables, only the first list entry will be closed. Broadcasts a COND_refresh condition. - If mysql_ha_close() is not called from the parser, 'dont_send_ok' - must be set. - If the caller did already lock LOCK_open, it must set 'dont_lock'. - - IMPLEMENTATION - find_table_ptr_by_name() closes the table, if a FLUSH TABLE is outstanding. - It returns a NULL pointer in this case, but flags the situation in - 'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages - is suppressed. RETURN - 0 ok - -1 error + 0 ok + != 0 error */ -int mysql_ha_close(THD *thd, TABLE_LIST *tables, - bool dont_send_ok, bool dont_lock, bool no_alias) +int mysql_ha_close(THD *thd, TABLE_LIST *tables) { + TABLE_LIST *hash_tables; TABLE **table_ptr; - bool was_flushed; + bool was_flushed= FALSE; + bool not_opened; + DBUG_ENTER("mysql_ha_close"); + DBUG_PRINT("enter",("mysql_ha_close: '%s'.'%s' as '%s'", + tables->db, tables->real_name, tables->alias)); - table_ptr= find_table_ptr_by_name(thd, tables->db, tables->alias, - !no_alias, dont_lock, &was_flushed); - if (*table_ptr) + if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, + (byte*) tables->alias, + strlen(tables->alias) + 1))) { - if (!dont_lock) - VOID(pthread_mutex_lock(&LOCK_open)); - if (close_thread_table(thd, table_ptr)) + /* + Though we could take the table pointer from hash_tables->table, + we must follow the thd->handler_tables chain anyway, as we need the + address of the 'next' pointer referencing this table + for close_thread_table(). + */ + for (table_ptr= &(thd->handler_tables); + *table_ptr && (*table_ptr != hash_tables->table); + table_ptr= &(*table_ptr)->next); + +#if MYSQL_VERSION_ID < 40100 + if (*tables->db && strcmp(hash_tables->db, tables->db)) { - /* Tell threads waiting for refresh that something has happened */ - VOID(pthread_cond_broadcast(&COND_refresh)); + DBUG_PRINT("info",("mysql_ha_close: wrong db")); + hash_tables= NULL; } - if (!dont_lock) - VOID(pthread_mutex_unlock(&LOCK_open)); - } - else if (!was_flushed && !dont_send_ok) - { - my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), - tables->alias, "HANDLER"); - return -1; - } - if (!dont_send_ok) - send_ok(&thd->net); - return 0; -} - - -/* - Close a list of HANDLER tables. - - SYNOPSIS - mysql_ha_close_list() - thd Thread identifier. - tables The list of tables to close. If NULL, - close all HANDLER tables. - flushed Close only tables which are marked flushed. - Used only if tables is NULL. - - DESCRIPTION - The list of HANDLER tables may be NULL, in which case all HANDLER - tables are closed. Broadcasts a COND_refresh condition, for - every table closed. If 'tables' is NULL and 'flushed' is set, - all HANDLER tables marked for flush are closed. - The caller must lock LOCK_open. - - IMPLEMENTATION - find_table_ptr_by_name() closes the table, if it is marked for flush. - It returns a NULL pointer in this case, but flags the situation in - 'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages - is suppressed. - - RETURN - 0 ok -*/ - -int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed) -{ - TABLE_LIST *tl_item; - TABLE **table_ptr; - - if (tables) - { - for (tl_item= tables ; tl_item; tl_item= tl_item->next) + else +#endif { - mysql_ha_close(thd, tl_item, /*dont_send_ok*/ 1, - /*dont_lock*/ 1, /*no_alias*/ 1); - } - } - else - { - table_ptr= &(thd->handler_tables); - while (*table_ptr) - { - if (! flushed || ((*table_ptr)->version != refresh_version)) + if (*table_ptr) { + VOID(pthread_mutex_lock(&LOCK_open)); if (close_thread_table(thd, table_ptr)) { /* Tell threads waiting for refresh that something has happened */ VOID(pthread_cond_broadcast(&COND_refresh)); } - continue; + VOID(pthread_mutex_unlock(&LOCK_open)); } - table_ptr= &((*table_ptr)->next); + + hash_delete(&thd->handler_tables_hash, (byte*) hash_tables); } } - return 0; + + if (! hash_tables) + { +#if MYSQL_VERSION_ID < 40100 + char buff[MAX_DBKEY_LENGTH]; + if (*tables->db) + strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS); + else + strncpy(buff, tables->alias, sizeof(buff)); + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + buff, "HANDLER"); +#else + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + tables->alias, "HANDLER"); +#endif + DBUG_PRINT("exit",("mysql_ha_close: ERROR")); + DBUG_RETURN(-1); + } + + send_ok(&thd->net); + DBUG_PRINT("exit",("mysql_ha_close: OK")); + DBUG_RETURN(0); } -static enum enum_ha_read_modes rkey_to_rnext[]= - { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV }; +/* + Read from a HANDLER table. + SYNOPSIS + mysql_ha_read() + thd Thread identifier. + tables A list of tables with the first entry to read. + mode + keyname + key_expr + ha_rkey_mode + cond + select_limit + offset_limit + + RETURN + 0 ok + != 0 error +*/ + int mysql_ha_read(THD *thd, TABLE_LIST *tables, enum enum_ha_read_modes mode, char *keyname, List *key_expr, enum ha_rkey_function ha_rkey_mode, Item *cond, ha_rows select_limit,ha_rows offset_limit) { - int err, keyno=-1; - bool was_flushed; - TABLE *table= *find_table_ptr_by_name(thd, tables->db, tables->alias, - /*is_alias*/ 1, /*dont_lock*/ 0, - &was_flushed); + TABLE_LIST *hash_tables; + TABLE *table; + int err; + int keyno=-1; + uint num_rows; + bool was_flushed; + MYSQL_LOCK *lock; + DBUG_ENTER("mysql_ha_read"); + DBUG_PRINT("enter",("mysql_ha_read: '%s'.'%s' as '%s'", + tables->db, tables->real_name, tables->alias)); + + List list; + list.push_front(new Item_field(NULL,NULL,"*")); + List_iterator it(list); + it++; + + if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, + (byte*) tables->alias, + strlen(tables->alias) + 1))) + { + table= hash_tables->table; + DBUG_PRINT("info",("mysql_ha_read: found in hash '%s'.'%s' as '%s' tab %p", + hash_tables->db, hash_tables->real_name, + hash_tables->alias, table)); + if (!table) + { + /* + The handler table has been closed. Re-open it. + */ + if (mysql_ha_open(thd, hash_tables, 1)) + { + DBUG_PRINT("exit",("mysql_ha_read: reopen failed")); + goto err0; + } + + table= hash_tables->table; + DBUG_PRINT("info",("mysql_ha_read: re-opened '%s'.'%s' as '%s' tab %p", + hash_tables->db, hash_tables->real_name, + hash_tables->alias, table)); + } + +#if MYSQL_VERSION_ID < 40100 + if (*tables->db && strcmp(table->table_cache_key, tables->db)) + { + DBUG_PRINT("info",("mysql_ha_read: wrong db")); + table= NULL; + } +#endif + } + else + table= NULL; + if (!table) { - my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0), - tables->alias,"HANDLER"); - return -1; +#if MYSQL_VERSION_ID < 40100 + char buff[MAX_DBKEY_LENGTH]; + if (*tables->db) + strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS); + else + strncpy(buff, tables->alias, sizeof(buff)); + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + buff, "HANDLER"); +#else + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + tables->alias, "HANDLER"); +#endif + goto err0; } tables->table=table; if (cond && cond->fix_fields(thd,tables)) - return -1; + goto err0; table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it @@ -224,24 +441,19 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, { my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0), keyname,tables->alias); - return -1; + goto err0; } table->file->index_init(keyno); } - List list; - list.push_front(new Item_field(NULL,NULL,"*")); - List_iterator it(list); - uint num_rows; - it++; - - insert_fields(thd,tables,tables->db,tables->alias,&it); + if (insert_fields(thd,tables,tables->db,tables->alias,&it)) + goto err0; select_limit+=offset_limit; send_fields(thd,list,1); HANDLER_TABLES_HACK(thd); - MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1); + lock= mysql_lock_tables(thd, &tables->table, 1); HANDLER_TABLES_HACK(thd); byte *key; @@ -363,83 +575,155 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ok: mysql_unlock_tables(thd,lock); send_eof(&thd->net); - return 0; + DBUG_PRINT("exit",("mysql_ha_read: OK")); + DBUG_RETURN(0); err: mysql_unlock_tables(thd,lock); err0: - return -1; + DBUG_PRINT("exit",("mysql_ha_read: ERROR")); + DBUG_RETURN(-1); } /* - Find a HANDLER table by name. + Flush (close) a list of HANDLER tables. SYNOPSIS - find_table_ptr_by_name() + mysql_ha_flush() thd Thread identifier. - db Database (schema) name. - table_name Table name ;-). - is_alias Table name may be an alias name. - dont_lock Suppresses the normal locking of LOCK_open. + tables The list of tables to close. If NULL, + close all HANDLER tables [marked as flushed]. + mode_flags MYSQL_HA_CLOSE_FINAL finally close the table. + MYSQL_HA_REOPEN_ON_USAGE mark for reopen. + MYSQL_HA_FLUSH_ALL flush all tables, not only + those marked for flush. DESCRIPTION - Find the table 'db'.'table_name' in the list of HANDLER tables of the - thread 'thd'. If the table has been marked by FLUSH TABLE(S), close it, - flag this situation in '*was_flushed' and broadcast a COND_refresh - condition. - An empty database (schema) name matches all database (schema) names. - If the caller did already lock LOCK_open, it must set 'dont_lock'. + The list of HANDLER tables may be NULL, in which case all HANDLER + tables are closed (if MYSQL_HA_FLUSH_ALL) is set. + If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set, + all HANDLER tables marked for flush are closed. + Broadcasts a COND_refresh condition, for every table closed. + The caller must lock LOCK_open. - IMPLEMENTATION - Just in case that the table is twice in 'thd->handler_tables' (!?!), - the loop does not break when the table was flushed. If another table - by that name was found and not flushed, '*was_flushed' is cleared again, - since a pointer to an open HANDLER table is returned. + NOTE + Since mysql_ha_flush() is called when the base table has to be closed, + we compare real table names, not aliases. Hence, database names matter. RETURN - *was_flushed Table has been closed due to FLUSH TABLE. - NULL A HANDLER Table by that name does not exist (any more). - != NULL Pointer to the TABLE structure. + 0 ok */ -static TABLE **find_table_ptr_by_name(THD *thd, const char *db, - const char *table_name, - bool is_alias, bool dont_lock, - bool *was_flushed) +int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags) { - int dblen; - TABLE **table_ptr; + TABLE_LIST **tmp_tables_p; + TABLE_LIST *tmp_tables; + TABLE **table_ptr; + bool was_flushed; + DBUG_ENTER("mysql_ha_flush"); + DBUG_PRINT("enter",("mysql_ha_flush: tables %p mode_flags 0x%02x", + tables, mode_flags)); - DBUG_ASSERT(db); - dblen= *db ? strlen(db)+1 : 0; - table_ptr= &(thd->handler_tables); - *was_flushed= FALSE; - - for (TABLE *table=*table_ptr; table ; table=*table_ptr) + if (tables) { - if ((!dblen || !memcmp(table->table_cache_key, db, dblen)) && - !my_strcasecmp((is_alias ? table->table_name : table->real_name), - table_name)) + /* Close all tables in the list. */ + for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next) { - if (table->version != refresh_version) + DBUG_PRINT("info",("mysql_ha_flush: in tables list '%s'.'%s' as '%s'", + tmp_tables->db, tmp_tables->real_name, + tmp_tables->alias)); + /* Close all currently open handler tables with the same base table. */ + table_ptr= &(thd->handler_tables); + while (*table_ptr) { - if (!dont_lock) - VOID(pthread_mutex_lock(&LOCK_open)); - if (close_thread_table(thd, table_ptr)) + if ((! *tmp_tables->db || + ! my_strcasecmp((*table_ptr)->table_cache_key, tmp_tables->db)) && + ! my_strcasecmp((*table_ptr)->real_name, tmp_tables->real_name)) { - /* Tell threads waiting for refresh that something has happened */ - VOID(pthread_cond_broadcast(&COND_refresh)); + DBUG_PRINT("info",("mysql_ha_flush: *table_ptr '%s'.'%s' as '%s'", + (*table_ptr)->table_cache_key, + (*table_ptr)->real_name, + (*table_ptr)->table_name)); + mysql_ha_flush_table(thd, table_ptr, mode_flags); + continue; } - if (!dont_lock) - VOID(pthread_mutex_unlock(&LOCK_open)); - *was_flushed= TRUE; + table_ptr= &(*table_ptr)->next; + } + /* end of handler_tables list */ + } + /* end of flush tables list */ + } + else + { + /* Close all currently open tables [which are marked for flush]. */ + table_ptr= &(thd->handler_tables); + while (*table_ptr) + { + if ((mode_flags & MYSQL_HA_FLUSH_ALL) || + ((*table_ptr)->version != refresh_version)) + { + mysql_ha_flush_table(thd, table_ptr, mode_flags); continue; } - *was_flushed= FALSE; - break; + table_ptr= &(*table_ptr)->next; } - table_ptr=&(table->next); } - return table_ptr; + + DBUG_PRINT("exit",("mysql_ha_flush: OK")); + DBUG_RETURN(0); +} + +/* + Flush (close) a table. + + SYNOPSIS + mysql_ha_flush_table() + thd Thread identifier. + table The table to close. + mode_flags MYSQL_HA_CLOSE_FINAL finally close the table. + MYSQL_HA_REOPEN_ON_USAGE mark for reopen. + + DESCRIPTION + Broadcasts a COND_refresh condition, for every table closed. + The caller must lock LOCK_open. + + RETURN + 0 ok +*/ + +static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, int mode_flags) +{ + TABLE_LIST *hash_tables; + TABLE *table= *table_ptr; + bool was_flushed; + DBUG_ENTER("mysql_ha_flush_table"); + DBUG_PRINT("info",("mysql_ha_flush_table: '%s'.'%s' as '%s' flags 0x%02x", + table->table_cache_key, table->real_name, + table->table_name, mode_flags)); + + if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, + (*table_ptr)->table_name, + strlen((*table_ptr)->table_name) + 1))) + { + if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE)) + { + /* This is a final close. Remove from hash. */ + hash_delete(&thd->handler_tables_hash, (byte*) hash_tables); + } + else + { + /* Mark table as closed, ready for re-open. */ + hash_tables->table= NULL; + } + } + + if (close_thread_table(thd, table_ptr)) + { + /* Tell threads waiting for refresh that something has happened */ + VOID(pthread_cond_broadcast(&COND_refresh)); + } + + DBUG_PRINT("exit",("mysql_ha_flush_table: OK")); + DBUG_RETURN(0); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 96eebd98ac3..b218a224977 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -176,7 +176,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, for (table=tables ; table ; table=table->next) { char *db=table->db; - mysql_ha_close(thd, table, /*dont_send_ok*/ 1, /*dont_lock*/ 1); + mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL); if (!close_temporary_table(thd, db, table->real_name)) { tmp_table_deleted=1; @@ -1242,7 +1242,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, if (send_fields(thd, field_list, 1)) DBUG_RETURN(-1); - mysql_ha_close(thd, tables, /*dont_send_ok*/ 1, /*dont_lock*/ 1); + mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL); for (table = tables; table; table = table->next) { char table_name[NAME_LEN*2+2]; @@ -1503,7 +1503,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } used_fields=create_info->used_fields; - mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1); + mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL); if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) DBUG_RETURN(-1); From 2bff96e2918c8e1810055fd9b80a7b709811c0b7 Mon Sep 17 00:00:00 2001 From: "rburnett@build.mysql.com" <> Date: Sat, 25 Sep 2004 18:43:07 +0200 Subject: [PATCH 063/143] Bug #5539 SHOW DATABASES LIKE and symlinks sql_show.cc: Made change suggested by Serge. REmoved else in mysql_find_files so symlink files fall through to the wildcard check --- sql/sql_show.cc | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d82af1a6242..2506033cda5 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -193,28 +193,23 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, { /* Return databases */ #ifdef USE_SYMDIR char *ext; + char buff[FN_REFLEN]; if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym")) { /* Only show the sym file if it points to a directory */ - char buff[FN_REFLEN], *end; - MY_STAT status; + char *end; *ext=0; /* Remove extension */ unpack_dirname(buff, file->name); end= strend(buff); if (end != buff && end[-1] == FN_LIBCHAR) end[-1]= 0; // Remove end FN_LIBCHAR - if (!my_stat(buff, &status, MYF(0)) || - !MY_S_ISDIR(status.st_mode) || - (wild && wild_compare(file->name, wild, 0))) - continue; - } - else + if (!my_stat(buff, file->mystat, MYF(0))) + continue; + } #endif - { if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) || (wild && wild_compare(file->name,wild, 0))) continue; - } } else { From 42b063c3b47a784c2286a0c840b9158e8fa3e85f Mon Sep 17 00:00:00 2001 From: "hartmut@mysql.com" <> Date: Sun, 26 Sep 2004 15:24:57 +0200 Subject: [PATCH 064/143] make --with-openssl work with parameters as expected, old options for include path and library settings still work for backwards compatibility (fix for BUG #5494) --- BitKeeper/etc/logging_ok | 1 + acinclude.m4 | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index d427be619b8..8f9c0f60122 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -35,6 +35,7 @@ greg@mysql.com guilhem@mysql.com gweir@build.mysql.com gweir@work.mysql.com +hartmut@mysql.com heikki@donna.mysql.fi heikki@hundin.mysql.fi heikki@rescue. diff --git a/acinclude.m4 b/acinclude.m4 index a88957ea3df..6c567f00765 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -788,7 +788,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [ AC_DEFUN(MYSQL_CHECK_OPENSSL, [ AC_MSG_CHECKING(for OpenSSL) AC_ARG_WITH([openssl], - [ --with-openssl Include the OpenSSL support], + [ --with-openssl[=DIR] Include the OpenSSL support], [openssl="$withval"], [openssl=no]) @@ -806,8 +806,19 @@ AC_MSG_CHECKING(for OpenSSL) [openssl_libs="$withval"], [openssl_libs=""]) - if test "$openssl" = "yes" + if test "$openssl" != "no" then + if test "$openssl" != "yes" + then + if test -z "$openssl_includes" + then + openssl_includes="$openssl/include" + fi + if test -z "$openssl_libs" + then + openssl_libs="$openssl/lib" + fi + fi MYSQL_FIND_OPENSSL([$openssl_includes], [$openssl_libs]) #force VIO use vio_dir="vio" @@ -843,6 +854,14 @@ AC_MSG_CHECKING(for OpenSSL) NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs" else AC_MSG_RESULT(no) + if test ! -z "$openssl_includes" + then + AC_MSG_ERROR(Can't have --with-openssl-includes without --with-openssl); + fi + if test ! -z "$openssl_libs" + then + AC_MSG_ERROR(Can't have --with-openssl-libs without --with-openssl); + fi fi AC_SUBST(openssl_libs) AC_SUBST(openssl_includes) From 5c8eb7066762fc4a864f9690f839933186ef54d5 Mon Sep 17 00:00:00 2001 From: "hartmut@mysql.com" <> Date: Sun, 26 Sep 2004 15:27:13 +0200 Subject: [PATCH 065/143] added --without-man option similar to --without-docs (part of BUG#5379) --- Makefile.am | 2 +- configure.in | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index fb0735b562c..1609b5a1da1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS = foreign EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT SUBDIRS = . include @docs_dirs@ @readline_dir@ \ @thread_dirs@ pstack @sql_client_dirs@ \ - @sql_server_dirs@ scripts man tests \ + @sql_server_dirs@ scripts @man_dirs@ tests \ BUILD netware os2 @libmysqld_dirs@ \ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@ diff --git a/configure.in b/configure.in index c3978ff32d1..37b0432b98d 100644 --- a/configure.in +++ b/configure.in @@ -2181,6 +2181,21 @@ else fi AC_SUBST(docs_dirs) +# Shall we build the man pages? +AC_ARG_WITH(man, + [ --without-man Skip building of the man pages.], + [with_man=$withval], + [with_man=yes] +) + +if test "$with_man" = "yes" +then + man_dirs="man" +else + man_dirs="" +fi +AC_SUBST(man_dirs) + # Shall we build the bench code? AC_ARG_WITH(bench, [ --without-bench Skip building of the benchmark suite.], From 263b33e12dd1776dce3ea62b544bab52e2307d4d Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Mon, 27 Sep 2004 00:50:00 +0400 Subject: [PATCH 066/143] Fix for bug #4131 "TIMESTAMP columns missing minutes and seconds when using GROUP BY" Now we are setting Field_timestamp::field_length to 19 in open_table() if we are in new mode (and we are restoring it back when we are coming back to normal mode). This also should solve potential problems with some of LOAD DATA INFILE and SELECT * INTO in this mode. --- mysql-test/r/type_timestamp.result | 60 +++++++++++++++++++++++++----- mysql-test/t/type_timestamp.test | 32 ++++++++++++++++ sql/field.cc | 24 +++--------- sql/field.h | 13 ++++++- sql/sql_base.cc | 25 +++++++++++++ sql/sql_parse.cc | 11 ++++++ sql/table.h | 8 ++++ 7 files changed, 144 insertions(+), 29 deletions(-) diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 752a5045eb0..6253fa96ba8 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -122,40 +122,41 @@ t2 t4 t6 t8 t10 t12 t14 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 drop table t1; +set new=0; create table t1 (t1 timestamp default '2003-01-01 00:00:00', t2 timestamp default '2003-01-01 00:00:00'); set TIMESTAMP=1000000000; insert into t1 values(); select * from t1; t1 t2 -2001-09-09 04:46:40 2003-01-01 00:00:00 +20010909044640 20030101000000 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `t1` timestamp(14) NOT NULL, - `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00' + `t2` timestamp(14) NOT NULL default '20030101000000' ) TYPE=MyISAM show columns from t1; Field Type Null Key Default Extra t1 timestamp(14) YES NULL -t2 timestamp(14) YES 2003-01-01 00:00:00 +t2 timestamp(14) YES 20030101000000 show columns from t1 like 't2'; Field Type Null Key Default Extra -t2 timestamp(14) YES 2003-01-01 00:00:00 +t2 timestamp(14) YES 20030101000000 create table t2 (select * from t1); show create table t2; Table Create Table t2 CREATE TABLE `t2` ( `t1` timestamp(14) NOT NULL, - `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00' + `t2` timestamp(14) NOT NULL default '20030101000000' ) TYPE=MyISAM alter table t1 add column t0 timestamp first; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `t0` timestamp(14) NOT NULL, - `t1` timestamp(14) NOT NULL default '2003-01-01 00:00:00', - `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00' + `t1` timestamp(14) NOT NULL default '20030101000000', + `t2` timestamp(14) NOT NULL default '20030101000000' ) TYPE=MyISAM drop table t1,t2; create table t1 (ts1 timestamp, ts2 timestamp); @@ -164,8 +165,8 @@ insert into t1 values (); insert into t1 values (DEFAULT, DEFAULT); select * from t1; ts1 ts2 -2001-09-09 04:46:40 0000-00-00 00:00:00 -2001-09-09 04:46:40 0000-00-00 00:00:00 +20010909044640 00000000000000 +20010909044640 00000000000000 drop table t1; create table t1 (ts timestamp(19)); show create table t1; @@ -179,3 +180,44 @@ select * from t1; ts 2001-09-09 04:46:40 drop table t1; +set new=1; +create table t1 (a char(2), t timestamp); +insert into t1 values ('a', '2004-01-01 00:00:00'), ('a', '2004-01-01 01:00:00'), +('b', '2004-02-01 00:00:00'); +select max(t) from t1 group by a; +max(t) +2004-01-01 01:00:00 +2004-02-01 00:00:00 +drop table t1; +create table t1 (ts1 timestamp); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `ts1` timestamp(19) NOT NULL +) TYPE=MyISAM +alter table t1 add ts2 timestamp; +set new=0; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `ts1` timestamp(19) NOT NULL, + `ts2` timestamp(19) NOT NULL default '0000-00-00 00:00:00' +) TYPE=MyISAM +drop table t1; +create table t1 (ts1 timestamp); +insert into t1 values ('2004-01-01 00:00:00'), ('2004-01-01 01:00:00'); +select * from t1; +ts1 +20040101000000 +20040101010000 +set new=1; +select * from t1; +ts1 +2004-01-01 00:00:00 +2004-01-01 01:00:00 +set new=0; +select * from t1; +ts1 +20040101000000 +20040101010000 +drop table t1; diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index 92bd20e846e..464ee63c137 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -71,6 +71,7 @@ select * from t1; set new=1; select * from t1; drop table t1; +set new=0; # # Bug #1885, bug #2539. @@ -116,3 +117,34 @@ set TIMESTAMP=1000000000; insert into t1 values (); select * from t1; drop table t1; + +# +# Test for bug #4131, TIMESTAMP columns missing minutes and seconds when +# using GROUP BY in @@new=1 mode. +# +set new=1; +create table t1 (a char(2), t timestamp); +insert into t1 values ('a', '2004-01-01 00:00:00'), ('a', '2004-01-01 01:00:00'), + ('b', '2004-02-01 00:00:00'); +select max(t) from t1 group by a; +drop table t1; + +# +# More --new mode tests +# Both columns created before and during alter should have same length. +# +create table t1 (ts1 timestamp); +show create table t1; +alter table t1 add ts2 timestamp; +set new=0; +show create table t1; +drop table t1; +# Selecting from table in --new mode should not affect further selects. +create table t1 (ts1 timestamp); +insert into t1 values ('2004-01-01 00:00:00'), ('2004-01-01 01:00:00'); +select * from t1; +set new=1; +select * from t1; +set new=0; +select * from t1; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 394d53238c2..69ee6606be4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2467,8 +2467,7 @@ void Field_double::sql_type(String &res) const enum Item_result Field_timestamp::result_type() const { - return (!current_thd->variables.new_mode && - (field_length == 8 || field_length == 14) ? INT_RESULT : + return ((field_length == 8 || field_length == 14) ? INT_RESULT : STRING_RESULT); } @@ -2480,6 +2479,9 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, :Field_num(ptr_arg, len_arg, (uchar*) 0,0, unireg_check_arg, field_name_arg, table_arg, 0, 1, 1) +#if MYSQL_VERSION_ID < 40100 + , orig_field_length(len_arg) +#endif { if (table && !table->timestamp_field) { @@ -2697,7 +2699,7 @@ String *Field_timestamp::val_str(String *val_buffer, time_t time_arg; struct tm *l_time; struct tm tm_tmp; - my_bool new_format= (current_thd->variables.new_mode) || field_length == 19, + my_bool new_format= field_length == 19, full_year=(field_length == 8 || field_length == 14 || new_format); int real_field_length= new_format ? 19 : field_length; @@ -2859,22 +2861,6 @@ void Field_timestamp::set_time() longstore(ptr,tmp); } -/* - This is an exact copy of Field_num except that 'length' is depending - on --new mode -*/ - -void Field_timestamp::make_field(Send_field *field) -{ - field->table_name=table_name; - field->col_name=field_name; - /* If --new, then we are using "YYYY-MM-DD HH:MM:SS" format */ - field->length= current_thd->variables.new_mode ? 19 : field_length; - field->type=type(); - field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags; - field->decimals=dec; -} - /**************************************************************************** ** time type diff --git a/sql/field.h b/sql/field.h index d25ce8d4774..c42f5f63f0c 100644 --- a/sql/field.h +++ b/sql/field.h @@ -546,6 +546,13 @@ public: class Field_timestamp :public Field_num { +#if MYSQL_VERSION_ID < 40100 + /* + We save the original field length here because field_length is + changed to a mock value in case when the 'new_mode' is in effect. + */ + uint32 orig_field_length; +#endif public: Field_timestamp(char *ptr_arg, uint32 len_arg, enum utype unireg_check_arg, const char *field_name_arg, @@ -587,7 +594,11 @@ public: void fill_and_store(char *from,uint len); bool get_date(TIME *ltime,bool fuzzydate); bool get_time(TIME *ltime); - void make_field(Send_field *field); + +#if MYSQL_VERSION_ID < 40100 + friend TABLE *open_table(THD *thd,const char *db,const char *table_name, + const char *alias,bool *refresh); +#endif }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8fd7273fd78..c9d6ca87fdb 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -941,6 +941,31 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, for (uint i=0 ; i < table->fields ; i++) table->field[i]->table_name=table->table_name; } +#if MYSQL_VERSION_ID < 40100 + /* + If per-connection "new" variable (represented by variables.new_mode) + is set then we should pretend that the length of TIMESTAMP field is 19. + The cheapest (from perfomance viewpoint) way to achieve that is to set + field_length of all Field_timestamp objects in a table after opening + it (to 19 if new_mode is true or to original field length otherwise). + We save value of new_mode variable in TABLE::timestamp_mode to + not perform this setup if new_mode value is the same between sequential + table opens. + */ + my_bool new_mode= thd->variables.new_mode; + if (table->timestamp_mode != new_mode) + { + for (uint i=0 ; i < table->fields ; i++) + { + Field *field= table->field[i]; + + if (field->type() == FIELD_TYPE_TIMESTAMP) + field->field_length= new_mode ? 19 : + ((Field_timestamp *)(field))->orig_field_length; + } + table->timestamp_mode= new_mode; + } +#endif /* These variables are also set in reopen_table() */ table->tablenr=thd->current_tablenr++; table->used_fields=0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 14fc748c288..4f1a0589db1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3229,7 +3229,18 @@ bool add_field_to_list(char *field_name, enum_field_types type, } break; case FIELD_TYPE_TIMESTAMP: +#if MYSQL_VERSION_ID < 40100 + /* + When in in --new mode, we should create TIMESTAMP(19) fields by default; + otherwise we will have problems with ALTER TABLE changing lengths of + existing TIMESTAMP fields to 19 and adding new fields with length 14. + */ + if (thd->variables.new_mode) + new_field->length= 19; + else if (!length) +#else if (!length) +#endif new_field->length= 14; // Full date YYYYMMDDHHMMSS else if (new_field->length != 19) { diff --git a/sql/table.h b/sql/table.h index f3b0e148cc0..84df7ba127e 100644 --- a/sql/table.h +++ b/sql/table.h @@ -106,6 +106,14 @@ struct st_table { *found_next_number_field, /* Set on open */ *rowid_field; Field_timestamp *timestamp_field; +#if MYSQL_VERSION_ID < 40100 + /* + Indicates whenever we have to set field_length members of all TIMESTAMP + fields to 19 (to honour 'new_mode' variable) or to original + field_length values. + */ + my_bool timestamp_mode; +#endif my_string comment; /* Comment about table */ REGINFO reginfo; /* field connections */ MEM_ROOT mem_root; From f7b6a99d50709525bfeca917f879008955c060d8 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Wed, 29 Sep 2004 23:25:32 +0400 Subject: [PATCH 067/143] Fix for BUG#4785 part two: * If at least one of indexes is disabled, use data file size as an estimate for key file size. * Added handling for joined tables. --- myisam/myisampack.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 4b784641266..5efd6b3a7fd 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -111,6 +111,8 @@ typedef struct st_isam_mrg { uint ref_length; uint max_blob_length; my_off_t records; + /* true if at least one source file has at least one disabled index */ + my_bool src_file_has_indexes_disabled; } PACK_MRG_INFO; @@ -413,9 +415,16 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count) mrg->current=0; mrg->file=(MI_INFO**) my_malloc(sizeof(MI_INFO*)*count,MYF(MY_FAE)); mrg->free_file=1; + mrg->src_file_has_indexes_disabled= 0; for (i=0; i < count ; i++) { - if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY))) + if ((mrg->file[i]=open_isam_file(names[i],O_RDONLY))) + { + mrg->src_file_has_indexes_disabled |= + (mrg->file[i]->s->state.key_map != + (1ULL << mrg->file[i]->s->base.keys) - 1); + } + else goto error; } /* Check that files are identical */ @@ -2040,12 +2049,21 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->state.dellink= HA_OFFSET_ERROR; share->state.split=(ha_rows) mrg->records; share->state.version=(ulong) time((time_t*) 0); - share->state.key_map=0; + if (share->state.key_map != (1ULL << share->base.keys) - 1) + { + /* + Some indexes are disabled, cannot use current key_file_length value + as an estimate of upper bound of index file size. Use packed data file + size instead. + */ + share->state.state.key_file_length= new_length; + } /* - Don't save key_file_length here, keep key_file_length of original file - so "myisamchk -rq" can use this value (this is necessary because index - size cannot be easily calculated for fulltext keys) + If there are no disabled indexes, keep key_file_length value from + original file so "myisamchk -rq" can use this value (this is necessary + because index size cannot be easily calculated for fulltext keys) */ + share->state.key_map=0; for (key=0 ; key < share->base.keys ; key++) share->state.key_root[key]= HA_OFFSET_ERROR; for (key=0 ; key < share->state.header.max_block_size ; key++) @@ -2054,8 +2072,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->changed=1; /* Force write of header */ share->state.open_count=0; share->global_changed=0; - VOID(my_chsize(share->kfile, share->state.state.key_file_length, 0, - MYF(0))); + VOID(my_chsize(share->kfile, share->base.keystart, 0, MYF(0))); if (share->base.keys) isamchk_neaded=1; DBUG_RETURN(mi_state_info_write(share->kfile,&share->state,1+2)); @@ -2078,7 +2095,12 @@ static int save_state_mrg(File file,PACK_MRG_INFO *mrg,my_off_t new_length, state.state.del=0; state.state.empty=0; state.state.records=state.split=(ha_rows) mrg->records; - state.state.key_file_length=isam_file->s->base.keystart; + /* See comment above in save_state about key_file_length handling. */ + if (mrg->src_file_has_indexes_disabled) + { + isam_file->s->state.state.key_file_length= + max(isam_file->s->state.state.key_file_length, new_length); + } state.dellink= HA_OFFSET_ERROR; state.version=(ulong) time((time_t*) 0); state.key_map=0; From b7f35f00cb52494a8fa1b2201d3b4950e9e2db6f Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 30 Sep 2004 19:05:33 +0200 Subject: [PATCH 068/143] Solve compile problem for 4.0.22 on hpita2. (Backport of a 4.1 change) --- sql/mysqld.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 834cff0d869..89d71ecbfa2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1114,14 +1114,14 @@ static void set_effective_user(struct passwd *user_info) { #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) DBUG_ASSERT(user_info); - if (setegid(user_info->pw_gid) == -1) + if (setregid((gid_t)-1,user_info->pw_gid) == -1) { - sql_perror("setegid"); + sql_perror("setregid"); unireg_abort(1); } - if (seteuid(user_info->pw_uid) == -1) + if (setreuid((uid_t)-1,user_info->pw_uid) == -1) { - sql_perror("seteuid"); + sql_perror("setreuid"); unireg_abort(1); } #endif @@ -2510,9 +2510,9 @@ You should consider changing lower_case_table_names to 1 or 2", #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) if (locked_in_memory && !getuid()) { - if (seteuid(0) == -1) + if (setreuid((uid_t)-1,0) == -1) { // this should never happen - sql_perror("seteuid"); + sql_perror("setreuid"); unireg_abort(1); } if (mlockall(MCL_CURRENT)) From 4ec50dc4d7b216489eda1da5d0053dad30fd738f Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Fri, 1 Oct 2004 16:23:54 +0500 Subject: [PATCH 069/143] delete.result, delete.test: A fix (bug #5733: Table handler error with self-join multi-table DELETE). records.cc: A fix (bug #5733: Table handler error with self-join multi-table DELETE). --- mysql-test/r/delete.result | 11 +++++++++++ mysql-test/t/delete.test | 10 ++++++++++ sql/records.cc | 27 ++++++++++++++++++--------- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index abc8245e69f..7353e687ae7 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -50,3 +50,14 @@ select count(*) from t1; count(*) 0 drop table t1; +create table t1 (a int not null auto_increment primary key, b char(32)); +insert into t1 (b) values ('apple'), ('apple'); +select * from t1; +a b +1 apple +2 apple +delete t1 from t1, t1 as t2 where t1.b = t2.b and t1.a > t2.a; +select * from t1; +a b +1 apple +drop table t1; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 904d959d148..07cb9155b3f 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -61,3 +61,13 @@ select count(*) from t1; drop table t1; +# +# Bug #5733: Table handler error with self-join multi-table DELETE +# + +create table t1 (a int not null auto_increment primary key, b char(32)); +insert into t1 (b) values ('apple'), ('apple'); +select * from t1; +delete t1 from t1, t1 as t2 where t1.b = t2.b and t1.a > t2.a; +select * from t1; +drop table t1; diff --git a/sql/records.cc b/sql/records.cc index 415e75a467b..02ae2e06141 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -131,17 +131,26 @@ void end_read_record(READ_RECORD *info) static int rr_quick(READ_RECORD *info) { - int tmp=info->select->quick->get_next(); - if (tmp) + int tmp; + while ((tmp= info->select->quick->get_next())) { - if (tmp == HA_ERR_END_OF_FILE) - tmp= -1; - else + if (info->thd->killed) { - if (info->print_error) - info->file->print_error(tmp,MYF(0)); - if (tmp < 0) // Fix negative BDB errno - tmp=1; + my_error(ER_SERVER_SHUTDOWN, MYF(0)); + return 1; + } + if (tmp != HA_ERR_RECORD_DELETED) + { + if (tmp == HA_ERR_END_OF_FILE) + tmp= -1; + else + { + if (info->print_error) + info->file->print_error(tmp,MYF(0)); + if (tmp < 0) // Fix negative BDB errno + tmp=1; + } + break; } } return tmp; From 2973a047eab453bae86705c33e901a947a0e6db7 Mon Sep 17 00:00:00 2001 From: "antony@ltantony.rdg.cyberkinetica.homeunix.net" <> Date: Sun, 3 Oct 2004 00:20:47 +0100 Subject: [PATCH 070/143] Bug#4118: multi-table UPDATE takes WRITE lock on read table Ensures that WRITE lock is not obtained on all tables referenced. --- mysql-test/r/lock_multi.result | 12 ++++ mysql-test/r/multi_update.result | 1 - mysql-test/t/lock_multi.test | 24 +++++++ mysql-test/t/multi_update.test | 2 - sql/sql_parse.cc | 31 +++++---- sql/sql_update.cc | 106 ++++++++++++++++++++++++++----- sql/sql_yacc.yy | 12 +++- 7 files changed, 155 insertions(+), 33 deletions(-) diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index b808fca0acf..b5672fe1791 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -17,6 +17,18 @@ unlock tables; n 1 drop table t1; +create table t1 (a int, b int); +create table t2 (c int, d int); +insert into t1 values(1,1); +insert into t1 values(2,2); +insert into t2 values(1,2); +lock table t1 read; + update t1,t2 set c=a where b=d; +select c from t2; +c +2 +drop table t1; +drop table t2; create table t1 (a int); create table t2 (a int); lock table t1 write, t2 write; diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 12cb965f045..fc414f2f46b 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -151,7 +151,6 @@ Table 't2' was locked with a READ lock and can't be updated UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n; Table 't2' was locked with a READ lock and can't be updated UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; -Table 't2' was locked with a READ lock and can't be updated unlock tables; LOCK TABLES t1 write, t2 write; UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 0295fca29e7..e20f8163751 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -50,6 +50,30 @@ connection reader; reap; drop table t1; +# +# Test problem when using locks with multi-updates +# It should not block when multi-update is reading on a read-locked table +# + +connection locker; +create table t1 (a int, b int); +create table t2 (c int, d int); +insert into t1 values(1,1); +insert into t1 values(2,2); +insert into t2 values(1,2); +lock table t1 read; +connection writer; +--sleep 2 +send update t1,t2 set c=a where b=d; +connection reader; +--sleep 2 +select c from t2; +connection writer; +reap; +connection locker; +drop table t1; +drop table t2; + # # Test problem when using locks on many tables and droping a table that # is to-be-locked by another thread diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 39ea136bde1..3494126f890 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -151,8 +151,6 @@ LOCK TABLES t1 write, t2 read; DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n; --error 1099 UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n; -# The following should be fixed to not give an error ---error 1099 UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; unlock tables; LOCK TABLES t1 write, t2 write; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e95c52f1e48..894fa355262 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1927,21 +1927,26 @@ mysql_execute_command(void) send_error(&thd->net,ER_WRONG_VALUE_COUNT); DBUG_VOID_RETURN; } - if (select_lex->table_list.elements == 1) + if (check_one_table_access(thd, UPDATE_ACL, tables, 0)) + goto error; /* purecov: inspected */ + + + res= mysql_update(thd,tables, + select_lex->item_list, + lex->value_list, + select_lex->where, + (ORDER *) select_lex->order_list.first, + select_lex->select_limit, + lex->duplicates); + break; + case SQLCOM_MULTI_UPDATE: + if (check_db_used(thd,tables)) + goto error; + if (select_lex->item_list.elements != lex->value_list.elements) { - if (check_one_table_access(thd, UPDATE_ACL, tables, 0)) - goto error; /* purecov: inspected */ - - - res= mysql_update(thd,tables, - select_lex->item_list, - lex->value_list, - select_lex->where, - (ORDER *) select_lex->order_list.first, - select_lex->select_limit, - lex->duplicates); + send_error(&thd->net,ER_WRONG_VALUE_COUNT); + DBUG_VOID_RETURN; } - else { const char *msg= 0; TABLE_LIST *table; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d51c81ee127..a17742df03b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -401,25 +401,101 @@ int mysql_multi_update(THD *thd, int res; multi_update *result; TABLE_LIST *tl; + const bool locked= !(thd->locked_tables); DBUG_ENTER("mysql_multi_update"); - if ((res=open_and_lock_tables(thd,table_list))) - DBUG_RETURN(res); - - thd->select_limit=HA_POS_ERROR; - - /* - Ensure that we have update privilege for all tables and columns in the - SET part - */ - for (tl= table_list ; tl ; tl=tl->next) + for (;;) { - TABLE *table= tl->table; - table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege); - } + table_map update_map= 0; + int tnr= 0; + + if ((res= open_tables(thd, table_list))) + DBUG_RETURN(res); - if (setup_fields(thd, table_list, *fields, 1, 0, 0)) - DBUG_RETURN(-1); + /* + Only need to call lock_tables if (thd->locked_tables == NULL) + */ + if (locked && ((res= lock_tables(thd, table_list)))) + DBUG_RETURN(res); + + thd->select_limit=HA_POS_ERROR; + + /* + Ensure that we have update privilege for all tables and columns in the + SET part + While we are here, initialize the table->map field. + */ + for (tl= table_list ; tl ; tl=tl->next) + { + TABLE *table= tl->table; + table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege); + table->map= (table_map) 1 << (tnr++); + } + + if (!setup_fields(thd, table_list, *fields, 1, 0, 0)) + { + List_iterator_fast field_it(*fields); + Item_field *item; + + while ((item= (Item_field *) field_it++)) + update_map|= item->used_tables(); + + DBUG_PRINT("info",("update_map=0x%08x", update_map)); + } + else + DBUG_RETURN(-1); + + /* + Unlock the tables in preparation for relocking + */ + if (locked) + { + pthread_mutex_lock(&LOCK_open); + mysql_unlock_tables(thd, thd->lock); + thd->lock= 0; + pthread_mutex_unlock(&LOCK_open); + } + + /* + Set the table locking strategy according to the update map + */ + for (tl= table_list ; tl ; tl=tl->next) + { + TABLE *table= tl->table; + if (update_map & table->map) + { + DBUG_PRINT("info",("setting table `%s` for update", tl->alias)); + tl->lock_type= thd->lex.lock_option; + tl->updating= 1; + } + else + { + DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias)); + tl->lock_type= TL_READ; + tl->updating= 0; + } + if (locked) + tl->table->reginfo.lock_type= tl->lock_type; + } + + /* + Relock the tables + */ + if (!(res=lock_tables(thd,table_list))) + break; + + if (!locked) + DBUG_RETURN(res); + + List_iterator_fast field_it(*fields); + Item_field *item; + + while ((item= (Item_field *) field_it++)) + /* item->cleanup(); XXX Use this instead in MySQL 4.1+ */ + item->field= item->result_field= 0; + + close_thread_tables(thd); + } /* Count tables and setup timestamp handling diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6b073db2e36..7b72c73a915 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2751,10 +2751,18 @@ update: lex->select->order_list.next= (byte**) &lex->select->order_list.first; } opt_low_priority opt_ignore join_table_list - SET update_list where_clause opt_order_clause delete_limit_clause + SET update_list { - set_lock_for_tables($3); + if (Lex->select->table_list.elements > 1) + { + LEX *lex=Lex; + lex->sql_command= SQLCOM_MULTI_UPDATE; + lex->lock_option= $3; + } + else + set_lock_for_tables($3); } + where_clause opt_order_clause delete_limit_clause {} ; update_list: From 634df1c19c5ab526fecd532285dd880b425da9f8 Mon Sep 17 00:00:00 2001 From: "dellis@goetia.(none)" <> Date: Sun, 3 Oct 2004 10:00:26 -0500 Subject: [PATCH 071/143] mysqld.cc: BUG #5731 Restrict key_buffer_size to 4GB on 64 bit platforms --- BitKeeper/etc/logging_ok | 1 + sql/mysqld.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 8f9c0f60122..66002912edf 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -24,6 +24,7 @@ bk@admin.bk brian@brian-akers-computer.local carsten@tsort.bitbybit.dk davida@isil.mysql.com +dellis@goetia.(none) dlenev@brandersnatch.localdomain dlenev@build.mysql.com dlenev@mysql.com diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 834cff0d869..c256c335399 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4144,7 +4144,7 @@ replicating a LOAD DATA INFILE command", {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL, - REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, + REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (uint32) ~0, MALLOC_OVERHEAD, IO_SIZE, 0}, {"long_query_time", OPT_LONG_QUERY_TIME, "Log all queries that have taken more than long_query_time seconds to execute to file.", From d5728b91bb69536281ed47b4ab67510bf11d71a0 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Mon, 4 Oct 2004 16:24:37 +0300 Subject: [PATCH 072/143] InnoDB: make ALTER TABLE to work on table names containing '#' (Bug #5856) --- innobase/dict/dict0dict.c | 22 ++++++++++++++++------ innobase/row/row0mysql.c | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 61bf3fae137..4340934ab3d 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2500,7 +2500,9 @@ dict_strip_comments( char* str; char* sptr; char* ptr; - + /* unclosed quote character (0 if none) */ + char quote = 0; + str = mem_alloc(strlen(sql_string) + 1); sptr = sql_string; @@ -2515,8 +2517,18 @@ scan_more: return(str); } - - if (*sptr == '#' + + if (*sptr == quote) { + /* Closing quote character: do not look for + starting quote or comments. */ + quote = 0; + } else if (quote) { + /* Within quotes: do not look for + starting quotes or comments. */ + } else if (*sptr == '"' || *sptr == '`') { + /* Starting quote: remember the quote character. */ + quote = *sptr; + } else if (*sptr == '#' || (0 == memcmp("-- ", sptr, 3))) { for (;;) { /* In Unix a newline is 0x0A while in Windows @@ -2531,9 +2543,7 @@ scan_more: sptr++; } - } - - if (*sptr == '/' && *(sptr + 1) == '*') { + } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') { for (;;) { if (*sptr == '*' && *(sptr + 1) == '/') { diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index a23444df4ef..a884dc8d9ef 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2051,6 +2051,7 @@ row_drop_table_for_mysql( memcpy(sql, str1, (sizeof str1) - 1); memcpy(sql + (sizeof str1) - 1, quoted_name, namelen); memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2); + mem_free(quoted_name); /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ From 91e8afac376aaf557124e0fa12d2cc30371d60b2 Mon Sep 17 00:00:00 2001 From: "vva@eagle.mysql.r18.ru" <> Date: Mon, 4 Oct 2004 23:26:42 +0500 Subject: [PATCH 073/143] patch fixing after review on patch-fixing of Bug #5492 "set @@session.read_rnd_buffer_size=33554432" crashes server on query 1. added warning comments for uint3korr (need one more byte allocated) 2. unsigned long in uint3korr was replaced by unsigned int to avoid problems on 64-bits platforms 3. shorten warning comments in init_rr_cache in sql/records.cc --- include/config-win.h | 8 +++++++- include/my_global.h | 8 +++++++- sql/records.cc | 7 +------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/config-win.h b/include/config-win.h index bb6d663bd8d..152e85c8e68 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -218,7 +218,13 @@ inline double ulonglong2double(ulonglong value) ((uint32) (uchar) (A)[0]))) #define sint4korr(A) (*((long *) (A))) #define uint2korr(A) (*((uint16 *) (A))) -#define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF) +/* + ATTENTION ! + + Please, note, uint3korr reads 4 bytes (not 3) ! + It means, that you have to provide enough allocated space ! +*/ +#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF) #define uint4korr(A) (*((unsigned long *) (A))) #define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\ (((uint32) ((uchar) (A)[1])) << 8) +\ diff --git a/include/my_global.h b/include/my_global.h index f24fc05471e..6871dfbf6c6 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -898,7 +898,13 @@ typedef char bool; /* Ordinary boolean values 0 1 */ (((uint32) ((uchar) (A)[1])) << 8) +\ (((uint32) ((uchar) (A)[2])) << 16)) #else -#define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF) +/* + ATTENTION ! + + Please, note, uint3korr reads 4 bytes (not 3) ! + It means, that you have to provide enough allocated space ! +*/ +#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF) #endif #define uint4korr(A) (*((unsigned long *) (A))) #define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\ diff --git a/sql/records.cc b/sql/records.cc index a2c6eb0a040..7cbb1ab3205 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -249,12 +249,7 @@ static int init_rr_cache(READ_RECORD *info) rec_cache_size=info->cache_records*info->reclength; info->rec_cache_size=info->cache_records*info->ref_length; - /* - We are going to read the last three bytes of the buffer via uint3korr - This macro reads actually 4 bytes (for speed) - So, we have to allocate one more byte at the end of the buffer - to avoid memory assertion fault - */ + // We have to allocate one more byte to use uint3korr (see comments for it) if (info->cache_records <= 2 || !(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records* info->struct_length+1, From b4ee4d358a316b1bba5dbb4faf51e6d0f7ab0e33 Mon Sep 17 00:00:00 2001 From: "rburnett@build.mysql.com" <> Date: Mon, 4 Oct 2004 20:26:43 +0200 Subject: [PATCH 074/143] Bug #5829 mysqlimport garbles path of the file to be imported Original code was checking ! unix_socket for local_file flag. This doesn't work and so was removed. Now to import a local file, you must use the --local command line option. mysqlimport.c: Removed check of unix_socket to set local_file --- client/mysqlimport.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index ca53b74c119..50c3a26a882 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -246,10 +246,8 @@ static int write_to_table(char *filename, MYSQL *sock) DBUG_ENTER("write_to_table"); DBUG_PRINT("enter",("filename: %s",filename)); - local_file= sock->unix_socket == 0 || opt_local_file; - fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */ - if (local_file) + if (! opt_local_file) strmov(hard_path,filename); else my_load_path(hard_path, filename, NULL); /* filename includes the path */ @@ -268,7 +266,7 @@ static int write_to_table(char *filename, MYSQL *sock) to_unix_path(hard_path); if (verbose) { - if (local_file) + if (opt_local_file) fprintf(stdout, "Loading data from LOCAL file: %s into %s\n", hard_path, tablename); else @@ -277,7 +275,7 @@ static int write_to_table(char *filename, MYSQL *sock) } sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'", opt_low_priority ? "LOW_PRIORITY" : "", - local_file ? "LOCAL" : "", hard_path); + opt_local_file ? "LOCAL" : "", hard_path); end= strend(sql_statement); if (replace) end= strmov(end, " REPLACE"); From 2ffb87f6a5ce686e10d486c3d2276be4b4ed6a08 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Tue, 5 Oct 2004 14:47:10 +0300 Subject: [PATCH 075/143] Fix for wrongly calculated Examined_rows in 4.0 UNION's. --- sql/sql_union.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sql/sql_union.cc b/sql/sql_union.cc index f79ff7967db..f9c21079851 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -39,6 +39,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) TABLE_LIST *first_table=(TABLE_LIST *)lex->select_lex.table_list.first; TMP_TABLE_PARAM tmp_table_param; select_union *union_result; + ha_rows examined_rows= 0; DBUG_ENTER("mysql_union"); /* Fix tables 'to-be-unioned-from' list to point at opened tables */ @@ -202,6 +203,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) union_result); if (res) goto exit; + examined_rows+= thd->examined_row_count; /* Needed for the following test and for records_at_start in next loop */ table->file->info(HA_STATUS_VARIABLE); if (found_rows_for_union & sl->options) @@ -258,12 +260,15 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) if (describe) thd->select_limit= HA_POS_ERROR; // no limit - res=mysql_select(thd,&result_table_list, + res= mysql_select(thd,&result_table_list, item_list, NULL, (describe) ? 0 : order, (ORDER*) NULL, NULL, (ORDER*) NULL, thd->options, result); if (!res) - thd->limit_found_rows = (ulonglong)table->file->records + add_rows; + { + thd->limit_found_rows= (ulonglong)table->file->records + add_rows; + thd->examined_row_count+= examined_rows; + } } } From ee3b6340b03b303997fc6bb54499b9ead0316025 Mon Sep 17 00:00:00 2001 From: "hf@deer.(none)" <> Date: Tue, 5 Oct 2004 21:19:40 +0500 Subject: [PATCH 076/143] Fix for #5730 (Query cache crashes server) Recusive part leads to stack overflow --- sql/sql_cache.cc | 75 ++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 5118421464b..60f0cfadc8e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1843,7 +1843,6 @@ inline ulong Query_cache::get_min_append_result_data_size() /* Allocate one or more blocks to hold data */ - my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, ulong data_len, Query_cache_block *query_block, @@ -1851,55 +1850,55 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, { ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) + ALIGN_SIZE(sizeof(Query_cache_result))); - ulong len= data_len + all_headers_len; - ulong align_len= ALIGN_SIZE(len); - DBUG_ENTER("Query_cache::allocate_data_chain"); - DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", - data_len, all_headers_len)); - ulong min_size = (first_block_arg ? get_min_first_result_data_size(): get_min_append_result_data_size()); - *result_block = allocate_block(max(min_size, align_len), - min_result_data_size == 0, - all_headers_len + min_result_data_size, - 1); - my_bool success = (*result_block != 0); - if (success) + Query_cache_block *prev_block= NULL; + Query_cache_block *new_block; + DBUG_ENTER("Query_cache::allocate_data_chain"); + DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", + data_len, all_headers_len)); + + do { - Query_cache_block *new_block= *result_block; + ulong len= data_len + all_headers_len; + ulong align_len= ALIGN_SIZE(len); + + if (!(new_block= allocate_block(max(min_size, align_len), + min_result_data_size == 0, + all_headers_len + min_result_data_size, + 1))) + { + DBUG_PRINT("warning", ("Can't allocate block for results")); + DBUG_RETURN(FALSE); + } + new_block->n_tables = 0; - new_block->used = 0; + new_block->used = min(len, new_block->length); new_block->type = Query_cache_block::RES_INCOMPLETE; new_block->next = new_block->prev = new_block; Query_cache_result *header = new_block->result(); header->parent(query_block); - if (new_block->length < len) - { - /* - We got less memory then we need (no big memory blocks) => - Continue to allocated more blocks until we got everything we need. - */ - Query_cache_block *next_block; - if ((success = allocate_data_chain(&next_block, - len - new_block->length, - query_block, first_block_arg))) - double_linked_list_join(new_block, next_block); - } - if (success) - { - new_block->used = min(len, new_block->length); - - DBUG_PRINT("qcache", ("Block len %lu used %lu", + DBUG_PRINT("qcache", ("Block len %lu used %lu", new_block->length, new_block->used)); - } + + if (prev_block) + double_linked_list_join(prev_block, new_block); else - DBUG_PRINT("warning", ("Can't allocate block for continue")); - } - else - DBUG_PRINT("warning", ("Can't allocate block for results")); - DBUG_RETURN(success); + *result_block= new_block; + if (new_block->length >= len) + break; + + /* + We got less memory then we need (no big memory blocks) => + Continue to allocated more blocks until we got everything we need. + */ + data_len= len - new_block->length; + prev_block= new_block; + } while(1); + + DBUG_RETURN(TRUE); } /***************************************************************************** From c27d22b44e3ced4156da003fc23d8f5720ab2515 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 6 Oct 2004 01:24:21 +0300 Subject: [PATCH 077/143] Reverted patch for new usage of open_count as it caused more problems than it solved Cleaned up patch for checking locks for multi-table updates --- myisam/mi_close.c | 9 +++- myisam/mi_locking.c | 117 +++++++++++++------------------------------- sql/ha_myisam.cc | 26 ++-------- sql/handler.cc | 2 +- sql/sql_acl.cc | 2 +- sql/sql_table.cc | 6 +-- sql/sql_update.cc | 112 +++++++++++++++++++++++++----------------- 7 files changed, 116 insertions(+), 158 deletions(-) diff --git a/myisam/mi_close.c b/myisam/mi_close.c index 47308a5e9eb..2712f0ca283 100644 --- a/myisam/mi_close.c +++ b/myisam/mi_close.c @@ -70,8 +70,13 @@ int mi_close(register MI_INFO *info) error=my_errno; if (share->kfile >= 0) { - /* We must always flush the state with the current open_count. */ - if (share->mode != O_RDONLY) + /* + If we are crashed, we can safely flush the current state as it will + not change the crashed state. + We can NOT write the state in other cases as other threads + may be using the file at this point + */ + if (share->mode != O_RDONLY && mi_is_crashed(info)) mi_state_info_write(share->kfile, &share->state, 1); if (my_close(share->kfile,MYF(0))) error = my_errno; diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 8a140a8b6fb..1efd203dc5f 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -19,16 +19,26 @@ reads info from a isam-table. Must be first request before doing any furter calls to any isamfunktion. Is used to allow many process use the same isamdatabase. - */ +*/ + +/* + state.open_count in the .MYI file is used the following way: + - For the first change of the file in this process it's incremented with + mi_mark_file_change(). (We have a write lock on the file in this case) + - In mi_close() it's decremented by _mi_decrement_open_count() if it + was incremented in the same process. + + This mean that if we are the only process using the file, the open_count + tells us if the MYISAM file wasn't properly closed. (This is true if + my_disable_locking is set). +*/ + #include "myisamdef.h" #ifdef __WIN__ #include #endif -static int mi_unlock_open_count(MI_INFO *info, my_bool write_info); - - /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */ int mi_lock_database(MI_INFO *info, int lock_type) @@ -38,17 +48,17 @@ int mi_lock_database(MI_INFO *info, int lock_type) MYISAM_SHARE *share=info->s; uint flag; DBUG_ENTER("mi_lock_database"); - DBUG_PRINT("enter",("mi_lock_database: lock_type %d, old lock %d" - ", r_locks %u, w_locks %u", lock_type, - info->lock_type, share->r_locks, share->w_locks)); - DBUG_PRINT("enter",("mi_lock_database: gl._changed %d, open_count %u '%s'", + DBUG_PRINT("enter",("lock_type: %d old lock %d r_locks: %u w_locks: %u " + "global_changed: %d open_count: %u name: '%s'", + lock_type, info->lock_type, share->r_locks, + share->w_locks, share->global_changed, share->state.open_count, share->index_file_name)); if (share->options & HA_OPTION_READ_ONLY_DATA || info->lock_type == lock_type) DBUG_RETURN(0); - if (lock_type == F_EXTRA_LCK) + if (lock_type == F_EXTRA_LCK) /* Used by TMP tables */ { ++share->w_locks; ++share->tot_locks; @@ -90,8 +100,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) share->state.process= share->last_process=share->this_process; share->state.unique= info->last_unique= info->this_unique; share->state.update_count= info->last_loop= ++info->this_loop; - if (mi_unlock_open_count(info, FALSE) || - mi_state_info_write(share->kfile, &share->state, 1)) + if (mi_state_info_write(share->kfile, &share->state, 1)) error=my_errno; share->changed=0; if (myisam_flush) @@ -106,19 +115,6 @@ int mi_lock_database(MI_INFO *info, int lock_type) if (error) mi_mark_crashed(info); } - else - { - /* - There are chances that _mi_mark_file_changed() has been called, - while share->changed remained FALSE. Consequently, we need to - clear the open_count even when share->changed is FALSE. Note, - that mi_unlock_open_count() will only clear the open_count when - it is set and only write the status to file, if it changes it - and we are running --with-external-locking. - */ - if (mi_unlock_open_count(info, ! my_disable_locking)) - error= my_errno; - } if (info->lock_type != F_EXTRA_LCK) { if (share->r_locks) @@ -142,16 +138,17 @@ int mi_lock_database(MI_INFO *info, int lock_type) break; case F_RDLCK: if (info->lock_type == F_WRLCK) - { /* Change RW to READONLY */ + { /* + Change RW to READONLY + mysqld does not turn write locks to read locks, so we're never here in mysqld. */ if (share->w_locks == 1) { flag=1; - if (mi_unlock_open_count(info, ! my_disable_locking) || - my_lock(share->kfile,lock_type,0L,F_TO_EOF, + if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, MYF(MY_SEEK_NOT_DONE))) { error=my_errno; @@ -179,14 +176,6 @@ int mi_lock_database(MI_INFO *info, int lock_type) my_errno=error; break; } - if (share->state.open_count) - { - DBUG_PRINT("error",("RD: Table has not been correctly unlocked" - ": open_count %d '%s'", - share->state.open_count, - share->index_file_name)); - mi_mark_crashed(info); - } } VOID(_mi_test_if_changed(info)); share->r_locks++; @@ -232,14 +221,6 @@ int mi_lock_database(MI_INFO *info, int lock_type) my_errno=error; break; } - if (share->state.open_count) - { - DBUG_PRINT("error",("WR: Table has not been correctly unlocked" - ": open_count %d '%s'", - share->state.open_count, - share->index_file_name)); - mi_mark_crashed(info); - } } } } @@ -375,9 +356,10 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer) } /* _mi_readinfo */ - /* Every isam-function that uppdates the isam-database must! end */ - /* with this request */ - /* ARGSUSED */ +/* + Every isam-function that uppdates the isam-database MUST end with this + request +*/ int _mi_writeinfo(register MI_INFO *info, uint operation) { @@ -450,6 +432,8 @@ int _mi_mark_file_changed(MI_INFO *info) { char buff[3]; register MYISAM_SHARE *share=info->s; + DBUG_ENTER("_mi_mark_file_changed"); + if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed) { share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED | @@ -463,12 +447,12 @@ int _mi_mark_file_changed(MI_INFO *info) { mi_int2store(buff,share->state.open_count); buff[2]=1; /* Mark that it's changed */ - return (my_pwrite(share->kfile,buff,sizeof(buff), - sizeof(share->state.header), - MYF(MY_NABP))); + DBUG_RETURN(my_pwrite(share->kfile,buff,sizeof(buff), + sizeof(share->state.header), + MYF(MY_NABP))); } } - return 0; + DBUG_RETURN(0); } @@ -501,36 +485,3 @@ int _mi_decrement_open_count(MI_INFO *info) } return test(lock_error || write_error); } - -/* - Decrement open_count in preparation for unlock. - - SYNOPSIS - mi_unlock_open_count() - info Pointer to the MI_INFO structure. - write_info If info must be written when changed. - - RETURN - 0 OK -*/ - -static int mi_unlock_open_count(MI_INFO *info, my_bool write_info) -{ - int rc= 0; - MYISAM_SHARE *share=info->s; - - DBUG_ENTER("mi_unlock_open_count"); - DBUG_PRINT("enter",("mi_unlock_open_count: gl._changed %d open_count %d '%s'", - share->global_changed, share->state.open_count, - share->index_file_name)); - if (share->global_changed) - { - share->global_changed= 0; - if (share->state.open_count) - share->state.open_count--; - if (write_info) - rc= _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE); - } - DBUG_RETURN(rc); -} - diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 2b7b8f436b1..3bfee7cdd79 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -998,32 +998,14 @@ int ha_myisam::delete_table(const char *name) return mi_delete_table(name); } + int ha_myisam::external_lock(THD *thd, int lock_type) { - int rc; - - while ((! (rc= mi_lock_database(file, !table->tmp_table ? - lock_type : ((lock_type == F_UNLCK) ? - F_UNLCK : F_EXTRA_LCK)))) && - mi_is_crashed(file) && (myisam_recover_options != HA_RECOVER_NONE)) - { - /* - check_and_repair() implicitly write locks the table, unless a - LOCK TABLES is in effect. It should be safer to always write lock here. - The implicit lock by check_and_repair() will then be a no-op. - check_and_repair() does not restore the original lock, but unlocks the - table. So we have to get the requested lock type again. And then to - check, if the table has been crashed again meanwhile by another server. - If anything fails, we break. - */ - if (((lock_type != F_WRLCK) && (rc= mi_lock_database(file, F_WRLCK))) || - (rc= check_and_repair(thd))) - break; - } - return rc; + return mi_lock_database(file, !table->tmp_table ? + lock_type : ((lock_type == F_UNLCK) ? + F_UNLCK : F_EXTRA_LCK)); } - THR_LOCK_DATA **ha_myisam::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) diff --git a/sql/handler.cc b/sql/handler.cc index 9eb129fab45..65078a485c5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -348,7 +348,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) if (trans == &thd->transaction.all && my_b_tell(&thd->transaction.trans_log)) { - if (error= wait_if_global_read_lock(thd, 0, 0)) + if ((error= wait_if_global_read_lock(thd, 0, 0))) { /* Note that ROLLBACK [TO SAVEPOINT] does not have this test; it's diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 58d0fe9a7fa..6e782f81ae5 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -469,7 +469,7 @@ static ulong get_sort(uint count,...) uint chars= 0; uint wild_pos= 0; /* first wildcard position */ - if (start= str) + if ((start= str)) { for (; *str ; str++) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0dd5c65bf79..6561af9c841 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2209,11 +2209,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, DBUG_RETURN(-1); /* purecov: inspected */ if (to->file->external_lock(thd, F_WRLCK)) - { - /* We must always unlock, even when lock failed. */ - (void) to->file->external_lock(thd, F_UNLCK); DBUG_RETURN(-1); - } to->file->extra(HA_EXTRA_WRITE_CACHE); from->file->info(HA_STATUS_VARIABLE); to->file->deactivate_non_unique_index(from->file->records); @@ -2313,11 +2309,11 @@ copy_data_between_tables(TABLE *from,TABLE *to, error=1; if (ha_commit(thd)) error=1; + err: free_io_cache(from); *copied= found_count; *deleted=delete_count; - /* we must always unlock the table on return. */ if (to->file->external_lock(thd,F_UNLCK)) error=1; DBUG_RETURN(error > 0 ? -1 : 0); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a17742df03b..cdcc90e8651 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -386,6 +386,24 @@ err: Update multiple tables from join ***************************************************************************/ +/* + Get table map for list of Item_field +*/ + +static table_map get_table_map(List *items) +{ + List_iterator_fast item_it(*items); + Item_field *item; + table_map map= 0; + + while ((item= (Item_field *) item_it++)) + map|= item->used_tables(); + DBUG_PRINT("info",("table_map: 0x%08x", map)); + return map; +} + + + /* Setup multi-update handling and call SELECT to do the join */ @@ -401,59 +419,45 @@ int mysql_multi_update(THD *thd, int res; multi_update *result; TABLE_LIST *tl; - const bool locked= !(thd->locked_tables); + const bool using_lock_tables= thd->locked_tables != 0; DBUG_ENTER("mysql_multi_update"); + thd->select_limit= HA_POS_ERROR; + for (;;) { - table_map update_map= 0; - int tnr= 0; + table_map update_map; + int tnr; if ((res= open_tables(thd, table_list))) DBUG_RETURN(res); - /* - Only need to call lock_tables if (thd->locked_tables == NULL) - */ - if (locked && ((res= lock_tables(thd, table_list)))) + /* Only need to call lock_tables if we are not using LOCK TABLES */ + if (!using_lock_tables && ((res= lock_tables(thd, table_list)))) DBUG_RETURN(res); - thd->select_limit=HA_POS_ERROR; - /* Ensure that we have update privilege for all tables and columns in the SET part While we are here, initialize the table->map field. */ - for (tl= table_list ; tl ; tl=tl->next) + for (tl= table_list,tnr=0 ; tl ; tl=tl->next) { TABLE *table= tl->table; table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege); table->map= (table_map) 1 << (tnr++); } - if (!setup_fields(thd, table_list, *fields, 1, 0, 0)) - { - List_iterator_fast field_it(*fields); - Item_field *item; - - while ((item= (Item_field *) field_it++)) - update_map|= item->used_tables(); - - DBUG_PRINT("info",("update_map=0x%08x", update_map)); - } - else + if (setup_fields(thd, table_list, *fields, 1, 0, 0)) DBUG_RETURN(-1); - /* - Unlock the tables in preparation for relocking - */ - if (locked) + update_map= get_table_map(fields); + + /* Unlock the tables in preparation for relocking */ + if (!using_lock_tables) { - pthread_mutex_lock(&LOCK_open); mysql_unlock_tables(thd, thd->lock); thd->lock= 0; - pthread_mutex_unlock(&LOCK_open); } /* @@ -474,26 +478,48 @@ int mysql_multi_update(THD *thd, tl->lock_type= TL_READ; tl->updating= 0; } - if (locked) + if (!using_lock_tables) tl->table->reginfo.lock_type= tl->lock_type; } + /* Relock the tables with the correct modes */ + res= lock_tables(thd,table_list); + if (using_lock_tables) + { + if (res) + DBUG_RETURN(res); + break; // Don't have to do setup_field() + } + /* - Relock the tables + We must setup fields again as the file may have been reopened + during lock_tables */ - if (!(res=lock_tables(thd,table_list))) + + { + List_iterator_fast field_it(*fields); + Item_field *item; + + while ((item= (Item_field *) field_it++)) +#if MYSQL_VERSION < 40100 + item->field= item->result_field= 0; +#else + item->cleanup(); +#endif + } + if (setup_fields(thd, table_list, *fields, 1, 0, 0)) + DBUG_RETURN(-1); + /* + If lock succeded and the table map didn't change since the above lock + we can continue. + */ + if (!res && update_map == get_table_map(fields)) break; - - if (!locked) - DBUG_RETURN(res); - - List_iterator_fast field_it(*fields); - Item_field *item; - - while ((item= (Item_field *) field_it++)) - /* item->cleanup(); XXX Use this instead in MySQL 4.1+ */ - item->field= item->result_field= 0; + /* + There was some very unexpected changes in the table definition between + open tables and lock tables. Close tables and try again. + */ close_thread_tables(thd); } @@ -548,7 +574,7 @@ int multi_update::prepare(List ¬_used_values) { TABLE_LIST *table_ref; SQL_LIST update; - table_map tables_to_update= 0; + table_map tables_to_update; Item_field *item; List_iterator_fast field_it(*fields); List_iterator_fast value_it(*values); @@ -559,8 +585,7 @@ int multi_update::prepare(List ¬_used_values) thd->cuted_fields=0L; thd->proc_info="updating main table"; - while ((item= (Item_field *) field_it++)) - tables_to_update|= item->used_tables(); + tables_to_update= get_table_map(fields); if (!tables_to_update) { @@ -624,7 +649,6 @@ int multi_update::prepare(List ¬_used_values) /* Split fields into fields_for_table[] and values_by_table[] */ - field_it.rewind(); while ((item= (Item_field *) field_it++)) { Item *value= value_it++; From 97febc4dc418a666ba3325f892d97c2bdb9e232c Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 6 Oct 2004 17:20:39 +0300 Subject: [PATCH 078/143] Code cleanups while doing review of pushed code --- myisam/mi_locking.c | 32 ++++++++++++---------- sql/mysql_priv.h | 2 +- sql/sql_handler.cc | 66 +++++++++++++++++++++------------------------ 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 1efd203dc5f..d5212cdee47 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -21,19 +21,6 @@ isamdatabase. */ -/* - state.open_count in the .MYI file is used the following way: - - For the first change of the file in this process it's incremented with - mi_mark_file_change(). (We have a write lock on the file in this case) - - In mi_close() it's decremented by _mi_decrement_open_count() if it - was incremented in the same process. - - This mean that if we are the only process using the file, the open_count - tells us if the MYISAM file wasn't properly closed. (This is true if - my_disable_locking is set). -*/ - - #include "myisamdef.h" #ifdef __WIN__ #include @@ -426,7 +413,24 @@ int _mi_test_if_changed(register MI_INFO *info) } /* _mi_test_if_changed */ -/* Put a mark in the .MYI file that someone is updating the table */ +/* + Put a mark in the .MYI file that someone is updating the table + + + DOCUMENTATION + + state.open_count in the .MYI file is used the following way: + - For the first change of the .MYI file in this process open_count is + incremented by mi_mark_file_change(). (We have a write lock on the file + when this happens) + - In mi_close() it's decremented by _mi_decrement_open_count() if it + was incremented in the same process. + + This mean that if we are the only process using the file, the open_count + tells us if the MYISAM file wasn't properly closed. (This is true if + my_disable_locking is set). +*/ + int _mi_mark_file_changed(MI_INFO *info) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8b41774e970..b5e571e74d0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -544,7 +544,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0); int mysql_ha_close(THD *thd, TABLE_LIST *tables); int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List *,enum ha_rkey_function,Item *,ha_rows,ha_rows); -int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags); +int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags); /* mysql_ha_flush mode_flags bits */ #define MYSQL_HA_CLOSE_FINAL 0x00 #define MYSQL_HA_REOPEN_ON_USAGE 0x01 diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index f056651919f..44ffb713dcc 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -72,7 +72,7 @@ static enum enum_ha_read_modes rkey_to_rnext[]= thd->open_tables=thd->handler_tables; \ thd->handler_tables=tmp; } -static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, int mode_flags); +static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags); /* @@ -156,8 +156,9 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) uint aliaslen; int err; DBUG_ENTER("mysql_ha_open"); - DBUG_PRINT("enter",("mysql_ha_open: '%s'.'%s' as '%s' reopen %d", - tables->db, tables->real_name, tables->alias, reopen)); + DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d", + tables->db, tables->real_name, tables->alias, + (int) reopen)); if (! hash_inited(&thd->handler_tables_hash)) { @@ -174,7 +175,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias, strlen(tables->alias) + 1)) { - DBUG_PRINT("info",("mysql_ha_open: duplicate '%s'", tables->alias)); + DBUG_PRINT("info",("duplicate '%s'", tables->alias)); if (! reopen) my_printf_error(ER_NONUNIQ_TABLE, ER(ER_NONUNIQ_TABLE), MYF(0), tables->alias); @@ -214,10 +215,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) &name, namelen, &alias, aliaslen, NullS))) - { - DBUG_PRINT("exit",("mysql_ha_open: malloc ERROR")); goto err; - } /* structure copy */ *hash_tables= *tables; hash_tables->db= db; @@ -237,11 +235,11 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) if (! reopen) send_ok(&thd->net); - DBUG_PRINT("exit",("mysql_ha_open: OK")); + DBUG_PRINT("exit",("OK")); DBUG_RETURN(0); err: - DBUG_PRINT("exit",("mysql_ha_open: ERROR")); + DBUG_PRINT("exit",("ERROR")); DBUG_RETURN(-1); } @@ -270,7 +268,7 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables) bool was_flushed= FALSE; bool not_opened; DBUG_ENTER("mysql_ha_close"); - DBUG_PRINT("enter",("mysql_ha_close: '%s'.'%s' as '%s'", + DBUG_PRINT("enter",("'%s'.'%s' as '%s'", tables->db, tables->real_name, tables->alias)); if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, @@ -290,7 +288,7 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables) #if MYSQL_VERSION_ID < 40100 if (*tables->db && strcmp(hash_tables->db, tables->db)) { - DBUG_PRINT("info",("mysql_ha_close: wrong db")); + DBUG_PRINT("info",("wrong db")); hash_tables= NULL; } else @@ -325,12 +323,12 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables) my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), tables->alias, "HANDLER"); #endif - DBUG_PRINT("exit",("mysql_ha_close: ERROR")); + DBUG_PRINT("exit",("ERROR")); DBUG_RETURN(-1); } send_ok(&thd->net); - DBUG_PRINT("exit",("mysql_ha_close: OK")); + DBUG_PRINT("exit", ("OK")); DBUG_RETURN(0); } @@ -368,7 +366,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, bool was_flushed; MYSQL_LOCK *lock; DBUG_ENTER("mysql_ha_read"); - DBUG_PRINT("enter",("mysql_ha_read: '%s'.'%s' as '%s'", + DBUG_PRINT("enter",("'%s'.'%s' as '%s'", tables->db, tables->real_name, tables->alias)); List list; @@ -381,9 +379,9 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, strlen(tables->alias) + 1))) { table= hash_tables->table; - DBUG_PRINT("info",("mysql_ha_read: found in hash '%s'.'%s' as '%s' tab %p", - hash_tables->db, hash_tables->real_name, - hash_tables->alias, table)); + DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p", + hash_tables->db, hash_tables->real_name, + hash_tables->alias, table)); if (!table) { /* @@ -391,12 +389,12 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, */ if (mysql_ha_open(thd, hash_tables, 1)) { - DBUG_PRINT("exit",("mysql_ha_read: reopen failed")); + DBUG_PRINT("exit",("reopen failed")); goto err0; } table= hash_tables->table; - DBUG_PRINT("info",("mysql_ha_read: re-opened '%s'.'%s' as '%s' tab %p", + DBUG_PRINT("info",("re-opened '%s'.'%s' as '%s' tab %p", hash_tables->db, hash_tables->real_name, hash_tables->alias, table)); } @@ -404,7 +402,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, #if MYSQL_VERSION_ID < 40100 if (*tables->db && strcmp(table->table_cache_key, tables->db)) { - DBUG_PRINT("info",("mysql_ha_read: wrong db")); + DBUG_PRINT("info",("wrong db")); table= NULL; } #endif @@ -575,12 +573,13 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ok: mysql_unlock_tables(thd,lock); send_eof(&thd->net); - DBUG_PRINT("exit",("mysql_ha_read: OK")); + DBUG_PRINT("exit",("OK")); DBUG_RETURN(0); + err: mysql_unlock_tables(thd,lock); err0: - DBUG_PRINT("exit",("mysql_ha_read: ERROR")); + DBUG_PRINT("exit",("ERROR")); DBUG_RETURN(-1); } @@ -614,24 +613,23 @@ err0: 0 ok */ -int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags) +int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags) { TABLE_LIST **tmp_tables_p; TABLE_LIST *tmp_tables; TABLE **table_ptr; bool was_flushed; DBUG_ENTER("mysql_ha_flush"); - DBUG_PRINT("enter",("mysql_ha_flush: tables %p mode_flags 0x%02x", - tables, mode_flags)); + DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags)); if (tables) { /* Close all tables in the list. */ for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next) { - DBUG_PRINT("info",("mysql_ha_flush: in tables list '%s'.'%s' as '%s'", - tmp_tables->db, tmp_tables->real_name, - tmp_tables->alias)); + DBUG_PRINT("info-in-tables-list",("'%s'.'%s' as '%s'", + tmp_tables->db, tmp_tables->real_name, + tmp_tables->alias)); /* Close all currently open handler tables with the same base table. */ table_ptr= &(thd->handler_tables); while (*table_ptr) @@ -640,7 +638,7 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags) ! my_strcasecmp((*table_ptr)->table_cache_key, tmp_tables->db)) && ! my_strcasecmp((*table_ptr)->real_name, tmp_tables->real_name)) { - DBUG_PRINT("info",("mysql_ha_flush: *table_ptr '%s'.'%s' as '%s'", + DBUG_PRINT("info",("*table_ptr '%s'.'%s' as '%s'", (*table_ptr)->table_cache_key, (*table_ptr)->real_name, (*table_ptr)->table_name)); @@ -669,7 +667,6 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags) } } - DBUG_PRINT("exit",("mysql_ha_flush: OK")); DBUG_RETURN(0); } @@ -691,15 +688,15 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags) 0 ok */ -static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, int mode_flags) +static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) { TABLE_LIST *hash_tables; TABLE *table= *table_ptr; bool was_flushed; DBUG_ENTER("mysql_ha_flush_table"); - DBUG_PRINT("info",("mysql_ha_flush_table: '%s'.'%s' as '%s' flags 0x%02x", - table->table_cache_key, table->real_name, - table->table_name, mode_flags)); + DBUG_PRINT("enter",("'%s'.'%s' as '%s' flags: 0x%02x", + table->table_cache_key, table->real_name, + table->table_name, mode_flags)); if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, (*table_ptr)->table_name, @@ -723,7 +720,6 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, int mode_flags) VOID(pthread_cond_broadcast(&COND_refresh)); } - DBUG_PRINT("exit",("mysql_ha_flush_table: OK")); DBUG_RETURN(0); } From badf8e715ab56bb112a541877709472f4047eb4b Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Thu, 7 Oct 2004 15:58:47 +0300 Subject: [PATCH 079/143] InnoDB: tolerate system clock glitches a little better in the error monitor thread. (Bug #5898) --- innobase/include/sync0arr.h | 4 +++- innobase/srv/srv0srv.c | 20 ++++++++++++++++---- innobase/sync/sync0arr.c | 15 +++++++-------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h index 4324f2d3f2c..73496a2ea84 100644 --- a/innobase/include/sync0arr.h +++ b/innobase/include/sync0arr.h @@ -97,9 +97,11 @@ sync_arr_wake_threads_if_sema_free(void); /************************************************************************** Prints warnings of long semaphore waits to stderr. */ -void +ibool sync_array_print_long_waits(void); /*=============================*/ + /* out: TRUE if fatal semaphore wait threshold + was exceeded */ /************************************************************************ Validates the integrity of the wait array. Checks that the number of reserved cells equals the count variable. */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index d799ada1e20..0643ab96c1d 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1754,7 +1754,8 @@ srv_error_monitor_thread( /* in: a dummy parameter required by os_thread_create */ { - ulint cnt = 0; + /* number of successive fatal timeouts observed */ + ulint fatal_cnt = 0; #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Error monitor thread starts, id %lu\n", @@ -1763,8 +1764,6 @@ srv_error_monitor_thread( loop: srv_error_monitor_active = TRUE; - cnt++; - os_thread_sleep(2000000); if (difftime(time(NULL), srv_last_monitor_time) > 60) { @@ -1774,7 +1773,20 @@ loop: srv_refresh_innodb_monitor_stats(); } - sync_array_print_long_waits(); + if (sync_array_print_long_waits()) { + fatal_cnt++; + if (fatal_cnt > 5) { + + fprintf(stderr, +"InnoDB: Error: semaphore wait has lasted > %lu seconds\n" +"InnoDB: We intentionally crash the server, because it appears to be hung.\n", + srv_fatal_semaphore_wait_threshold); + + ut_error; + } + } else { + fatal_cnt = 0; + } /* Flush stderr so that a database user gets the output to possible MySQL error file */ diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index 09ddfd1d309..a443d630425 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -889,15 +889,18 @@ sync_arr_wake_threads_if_sema_free(void) /************************************************************************** Prints warnings of long semaphore waits to stderr. */ -void +ibool sync_array_print_long_waits(void) /*=============================*/ + /* out: TRUE if fatal semaphore wait threshold + was exceeded */ { sync_cell_t* cell; ibool old_val; ibool noticed = FALSE; ulint i; ulint fatal_timeout = srv_fatal_semaphore_wait_threshold; + ibool fatal = FALSE; for (i = 0; i < sync_primary_wait_array->n_cells; i++) { @@ -914,13 +917,7 @@ sync_array_print_long_waits(void) if (cell->wait_object != NULL && difftime(time(NULL), cell->reservation_time) > fatal_timeout) { - - fprintf(stderr, -"InnoDB: Error: semaphore wait has lasted > %lu seconds\n" -"InnoDB: We intentionally crash the server, because it appears to be hung.\n", - fatal_timeout); - - ut_error; + fatal = TRUE; } } @@ -948,6 +945,8 @@ sync_array_print_long_waits(void) fprintf(stderr, "InnoDB: ###### Diagnostic info printed to the standard error stream\n"); } + + return(fatal); } /************************************************************************** From c73cd9ff8a91bfed583245d1096e2906d098deda Mon Sep 17 00:00:00 2001 From: "jani@a80-186-41-201.elisa-laajakaista.fi" <> Date: Thu, 7 Oct 2004 20:30:30 +0300 Subject: [PATCH 080/143] Fixed Bug#5575, mysqlhotcopy is broken when using --noindices --- BitKeeper/etc/logging_ok | 1 + scripts/mysqlhotcopy.sh | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 8f9c0f60122..8347685b9b2 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -47,6 +47,7 @@ igor@hundin.mysql.fi igor@rurik.mysql.com ingo@mysql.com jani@a80-186-24-72.elisa-laajakaista.fi +jani@a80-186-41-201.elisa-laajakaista.fi jani@dsl-jkl1657.dial.inet.fi jani@hynda.(none) jani@hynda.mysql.fi diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index b90ca4dc7c0..f9e29e33195 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -8,7 +8,7 @@ use File::Path; use DBI; use Sys::Hostname; use File::Copy; -use File::Temp; +use File::Temp qw(tempfile); =head1 NAME @@ -39,7 +39,7 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome. # Documentation continued at end of file -my $VERSION = "1.21"; +my $VERSION = "1.22"; my $opt_tmpdir = $ENV{TMPDIR} || "/tmp"; @@ -654,8 +654,8 @@ sub copy_index } elsif ($opt{method} =~ /^scp\b/) { - my ($fh, $tmp)=tempfile('mysqlhotcopy-XXXXXX', DIR => $opt_tmpdir); - die "Can\'t create/open file in $opt_tmpdir\n"; + my ($fh, $tmp)= tempfile('mysqlhotcopy-XXXXXX', DIR => $opt_tmpdir) or + die "Can\'t create/open file in $opt_tmpdir\n"; if (syswrite($fh,$buff) != length($buff)) { die "Error when writing data to $tmp: $!\n"; From d2a5548431e2baa4d7f76145673be58c424b2cfe Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Fri, 8 Oct 2004 16:32:56 +0300 Subject: [PATCH 081/143] Using MySQL 4.0 with privilege tables from 5.0 caused a crash. (Fixed this by backporting some logic from 4.1) --- sql/sql_acl.cc | 56 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6e782f81ae5..b3bc5a1e4f2 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -106,7 +106,7 @@ static HASH acl_check_hosts, hash_tables; static DYNAMIC_ARRAY acl_wild_hosts; static hash_filo *acl_cache; static uint grant_version=0; -static ulong get_access(TABLE *form,uint fieldnr); +static ulong get_access(TABLE *form, uint fieldnr, uint *next_field); static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b); static ulong get_sort(uint count,...); static void init_check_host(void); @@ -191,7 +191,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ACL_HOST host; update_hostname(&host.host,get_field(&mem, table,0)); host.db= get_field(&mem, table,1); - host.access= get_access(table,2); + host.access= get_access(table,2,0); host.access= fix_rights_for_db(host.access); host.sort= get_sort(2,host.host.hostname,host.db); #ifndef TO_BE_REMOVED @@ -241,14 +241,15 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) user.host.hostname ? user.host.hostname : ""); /* purecov: tested */ continue; /* purecov: tested */ } + uint next_field; get_salt_from_password(user.salt,user.password); - user.access=get_access(table,3) & GLOBAL_ACLS; + user.access=get_access(table,3,&next_field) & GLOBAL_ACLS; user.sort=get_sort(2,user.host.hostname,user.user); user.hostname_length= (user.host.hostname ? (uint) strlen(user.host.hostname) : 0); if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */ { - char *ssl_type=get_field(&mem, table, 24); + char *ssl_type=get_field(&mem, table, next_field++); if (!ssl_type) user.ssl_type=SSL_TYPE_NONE; else if (!strcmp(ssl_type, "ANY")) @@ -258,16 +259,16 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) else /* !strcmp(ssl_type, "SPECIFIED") */ user.ssl_type=SSL_TYPE_SPECIFIED; - user.ssl_cipher= get_field(&mem, table, 25); - user.x509_issuer= get_field(&mem, table, 26); - user.x509_subject= get_field(&mem, table, 27); + user.ssl_cipher= get_field(&mem, table, next_field++); + user.x509_issuer= get_field(&mem, table, next_field++); + user.x509_subject= get_field(&mem, table, next_field++); - char *ptr = get_field(&mem, table, 28); - user.user_resource.questions=atoi(ptr); - ptr = get_field(&mem, table, 29); - user.user_resource.updates=atoi(ptr); - ptr = get_field(&mem, table, 30); - user.user_resource.connections=atoi(ptr); + char *ptr = get_field(&mem, table, next_field++); + user.user_resource.questions= ptr ? atoi(ptr) : 0; + ptr = get_field(&mem, table, next_field++); + user.user_resource.updates= ptr ? atoi(ptr): 0; + ptr = get_field(&mem, table, next_field++); + user.user_resource.connections=ptr ? atoi(ptr) : 0; if (user.user_resource.questions || user.user_resource.updates || user.user_resource.connections) mqh_used=1; @@ -313,7 +314,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) continue; } db.user=get_field(&mem, table,2); - db.access=get_access(table,3); + db.access=get_access(table,3,0); db.access=fix_rights_for_db(db.access); db.sort=get_sort(3,db.host.hostname,db.db,db.user); #ifndef TO_BE_REMOVED @@ -423,11 +424,24 @@ void acl_reload(THD *thd) /* Get all access bits from table after fieldnr - We know that the access privileges ends when there is no more fields - or the field is not an enum with two elements. + + IMPLEMENTATION + We know that the access privileges ends when there is no more fields + or the field is not an enum with two elements. + + SYNOPSIS + get_access() + form an open table to read privileges from. + The record should be already read in table->record[0] + fieldnr number of the first privilege (that is ENUM('N','Y') field + next_field on return - number of the field next to the last ENUM + (unless next_field == 0) + + RETURN VALUE + privilege mask */ -static ulong get_access(TABLE *form, uint fieldnr) +static ulong get_access(TABLE *form, uint fieldnr, uint *next_field) { ulong access_bits=0,bit; char buff[2]; @@ -437,12 +451,14 @@ static ulong get_access(TABLE *form, uint fieldnr) for (pos=form->field+fieldnr, bit=1; *pos && (*pos)->real_type() == FIELD_TYPE_ENUM && ((Field_enum*) (*pos))->typelib->count == 2 ; - pos++ , bit<<=1) + pos++, fieldnr++, bit<<=1) { (*pos)->val_str(&res,&res); if (toupper(res[0]) == 'Y') access_bits|= bit; } + if (next_field) + *next_field=fieldnr; return access_bits; } @@ -1395,7 +1411,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, if (priv & rights) // set requested privileges (*tmp_field)->store(&what,1); } - rights=get_access(table,3); + rights=get_access(table,3,0); DBUG_PRINT("info",("table->fields: %d",table->fields)); if (table->fields >= 31) /* From 4.0.0 we have more fields */ { @@ -1554,7 +1570,7 @@ static int replace_db_table(TABLE *table, const char *db, if (priv & store_rights) // do it if priv is chosen table->field [i]->store(&what,1); // set requested privileges } - rights=get_access(table,3); + rights=get_access(table,3,0); rights=fix_rights_for_db(rights); if (old_row_exists) From af3681f2d910caa0b08add974ca5375345d22782 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 9 Oct 2004 14:13:40 +0300 Subject: [PATCH 082/143] trx0rec.c: Fix bug #5960: if one updated a column so that its size changed, or updated it to an externally stored (TEXT or BLOB) value, then ANOTHER externally stored column would show up as 512 bytes of good data + 20 bytes of garbage in a consistent read that fetched the old version of the row --- innobase/trx/trx0rec.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c index 79fad312e8e..0e1842ef4a0 100644 --- a/innobase/trx/trx0rec.c +++ b/innobase/trx/trx0rec.c @@ -1257,7 +1257,7 @@ trx_undo_prev_version_build( ibool dummy_extern; byte* buf; ulint err; - ulint i; + #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); #endif /* UNIV_SYNC_DEBUG */ @@ -1367,7 +1367,18 @@ trx_undo_prev_version_build( } if (row_upd_changes_field_size_or_external(rec, index, update)) { + ulint* ext_vect; + ulint n_ext_vect; + /* We have to set the appropriate extern storage bits in the + old version of the record: the extern bits in rec for those + fields that update does NOT update, as well as the the bits for + those fields that update updates to become externally stored + fields. Store the info to ext_vect: */ + + ext_vect = mem_alloc(sizeof(ulint) * rec_get_n_fields(rec)); + n_ext_vect = btr_push_update_extern_fields(ext_vect, rec, + update); entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); row_upd_index_replace_new_col_vals(entry, index, update, heap); @@ -1375,6 +1386,11 @@ trx_undo_prev_version_build( buf = mem_heap_alloc(heap, rec_get_converted_size(entry)); *old_vers = rec_convert_dtuple_to_rec(buf, entry); + + /* Now set the extern bits in the old version of the record */ + rec_set_field_extern_bits(*old_vers, ext_vect, n_ext_vect, + NULL); + mem_free(ext_vect); } else { buf = mem_heap_alloc(heap, rec_get_size(rec)); @@ -1383,15 +1399,5 @@ trx_undo_prev_version_build( row_upd_rec_in_place(*old_vers, update); } - for (i = 0; i < upd_get_n_fields(update); i++) { - - if (upd_get_nth_field(update, i)->extern_storage) { - - rec_set_nth_field_extern_bit(*old_vers, - upd_get_nth_field(update, i)->field_no, - TRUE, NULL); - } - } - return(DB_SUCCESS); } From 13af58aab6e009a024ce7f910ffb1ddd31e32b1c Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Mon, 11 Oct 2004 11:01:38 +0200 Subject: [PATCH 083/143] Fix for BUG#5949 "error code 1223 in binlog when using innobackup": when one connection had done FLUSH TABLES WITH READ LOCK, some updates, and then COMMIT, it was accepted but my_error() was called and so, while client got no error, error was logged in binlog. We now don't call my_error() in this case; we assume the connection know what it does. This problem was specific to 4.0.21. The change is needed to make replication work with existing versions of innobackup. --- mysql-test/r/rpl_commit_after_flush.result | 13 +++++++++++++ mysql-test/t/rpl_commit_after_flush.test | 17 +++++++++++++++++ sql/lock.cc | 10 ++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/rpl_commit_after_flush.result create mode 100644 mysql-test/t/rpl_commit_after_flush.test diff --git a/mysql-test/r/rpl_commit_after_flush.result b/mysql-test/r/rpl_commit_after_flush.result new file mode 100644 index 00000000000..8cdc7e986ab --- /dev/null +++ b/mysql-test/r/rpl_commit_after_flush.result @@ -0,0 +1,13 @@ +slave stop; +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; +slave start; +create table t1 (a int) type=innodb; +begin; +insert into t1 values(1); +flush tables with read lock; +commit; +unlock tables; +drop table t1; diff --git a/mysql-test/t/rpl_commit_after_flush.test b/mysql-test/t/rpl_commit_after_flush.test new file mode 100644 index 00000000000..edbbd1bfad6 --- /dev/null +++ b/mysql-test/t/rpl_commit_after_flush.test @@ -0,0 +1,17 @@ +source include/master-slave.inc; +source include/have_innodb.inc; +create table t1 (a int) type=innodb; +begin; +insert into t1 values(1); +flush tables with read lock; +commit; +save_master_pos; +connection slave; +sync_with_master; +# cleanup +connection master; +unlock tables; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; diff --git a/sql/lock.cc b/sql/lock.cc index dd2b61b65d2..bf0160291f8 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -751,9 +751,15 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commi { if (thd->global_read_lock) // This thread had the read locks { - my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0)); + if (is_not_commit) + my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0)); (void) pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(1); + /* + We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does. + This allowance is needed to not break existing versions of innobackup + which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT. + */ + DBUG_RETURN(is_not_commit); } old_message=thd->enter_cond(&COND_refresh, &LOCK_open, "Waiting for release of readlock"); From 41ab008a366b67d13431cf4977572713b9e1939e Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Tue, 12 Oct 2004 18:12:00 +0300 Subject: [PATCH 084/143] ha_innodb.cc: Change error code to HA_ERR_ROW_IS_REFERENCED if we cannot DROP a parent table referenced by a FOREIGN KEY constraint; this error number is less misleading than the previous value HA_ERR_CANNOT_ADD_FOREIGN, but misleading still; we should introduce to 5.0 a proper MySQL error code --- sql/ha_innodb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f149af85b3f..fa9537b3217 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -285,7 +285,7 @@ convert_error_code_to_mysql( } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) { - return(HA_ERR_CANNOT_ADD_FOREIGN); /* TODO: This is a bit + return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit misleading, a new MySQL error code should be introduced */ } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) { From edb93ca441df3257bccc320496a765b93779ce66 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 13 Oct 2004 22:54:21 +0300 Subject: [PATCH 085/143] Added startup option and settable session variable innodb_table_locks_old_behavior: do not acquire an InnoDB table lock for LOCK TABLES, as in mysql-4.0.18 and earlier. --- sql/ha_innodb.cc | 3 ++- sql/mysqld.cc | 7 ++++++- sql/set_var.cc | 4 ++++ sql/sql_class.h | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index fa9537b3217..44d050d14aa 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4693,7 +4693,8 @@ ha_innobase::external_lock( } if (prebuilt->select_lock_type != LOCK_NONE) { - if (thd->in_lock_tables) { + if (thd->in_lock_tables && + !thd->variables.innodb_table_locks_old_behavior) { ulint error; error = row_lock_table_for_mysql(prebuilt); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 89d71ecbfa2..8b478882451 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3526,6 +3526,7 @@ enum options_mysqld { OPT_INNODB_FORCE_RECOVERY, OPT_INNODB_STATUS_FILE, OPT_INNODB_MAX_DIRTY_PAGES_PCT, + OPT_INNODB_TABLE_LOCKS_OLD_BEHAVIOR, OPT_BDB_CACHE_SIZE, OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_MAX_LOCK, @@ -3699,7 +3700,11 @@ struct my_option my_long_options[] = {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT, "Percentage of dirty pages allowed in bufferpool", (gptr*) &srv_max_buf_pool_modified_pct, (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, - + {"innodb_table_locks_old_behavior", OPT_INNODB_TABLE_LOCKS_OLD_BEHAVIOR, + "Disable InnoDB locking in LOCK TABLES", + (gptr*) &global_system_variables.innodb_table_locks_old_behavior, + (gptr*) &global_system_variables.innodb_table_locks_old_behavior, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif /* End HAVE_INNOBASE_DB */ {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/sql/set_var.cc b/sql/set_var.cc index 4b66a621f62..9b2db7a0802 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -263,6 +263,8 @@ sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", #ifdef HAVE_INNOBASE_DB sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct", &srv_max_buf_pool_modified_pct); +sys_var_thd_bool sys_innodb_table_locks_old_behavior("innodb_table_locks_old_behavior", + &SV::innodb_table_locks_old_behavior); #endif @@ -449,6 +451,7 @@ sys_var *sys_variables[]= &sys_os, #ifdef HAVE_INNOBASE_DB &sys_innodb_max_dirty_pages_pct, + &sys_innodb_table_locks_old_behavior, #endif &sys_unique_checks }; @@ -520,6 +523,7 @@ struct show_var_st init_vars[]= { {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, + {sys_innodb_table_locks_old_behavior.name, (char*) &sys_innodb_table_locks_old_behavior, 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}, diff --git a/sql/sql_class.h b/sql/sql_class.h index af53574eeaf..8c383d5848d 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -338,6 +338,9 @@ struct system_variables my_bool low_priority_updates; my_bool new_mode; my_bool query_cache_wlock_invalidate; +#ifdef HAVE_INNOBASE_DB + my_bool innodb_table_locks_old_behavior; +#endif /* HAVE_INNOBASE_DB */ CONVERT *convert_set; }; From 150ab94e0adec270d7a106d629e8963f43cf612d Mon Sep 17 00:00:00 2001 From: "ingo@mysql.com" <> Date: Thu, 14 Oct 2004 20:02:56 +0200 Subject: [PATCH 086/143] BUG#5625 - MyISAM Index corruption on ALTER TABLE x ENABLE KEYS due to full tmpdir. Added a try to a normal repair() if repair_by_sort() failed. This was not done with ENABLE KEYS and OPTIMIZE TABLE. Fixed error code handling in mysql_alter_table(). --- sql/ha_myisam.cc | 18 ++++++++++++++++-- sql/sql_table.cc | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 2b7b8f436b1..71623238bd9 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -525,6 +525,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) { + int error; if (!file) return HA_ADMIN_INTERNAL_ERROR; MI_CHECK param; @@ -534,7 +535,14 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) param.testflag = (check_opt->flags | T_SILENT | T_FORCE_CREATE | T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX); param.sort_buffer_length= check_opt->sort_buffer_size; - return repair(thd,param,1); + if ((error= repair(thd,param,1)) && param.retry_repair) + { + sql_print_warning("Warning: Optimize table got errno %d, retrying", + my_errno); + param.testflag&= ~T_REP_BY_SORT; + error= repair(thd,param,1); + } + return error; } @@ -744,7 +752,13 @@ bool ha_myisam::activate_all_index(THD *thd) param.myf_rw&= ~MY_WAIT_IF_FULL; param.sort_buffer_length= thd->variables.myisam_sort_buff_size; param.tmpdir=mysql_tmpdir; - error=repair(thd,param,0) != HA_ADMIN_OK; + if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair) + { + sql_print_warning("Warning: Enabling keys got errno %d, retrying", + my_errno); + param.testflag&= ~(T_REP_BY_SORT | T_QUICK); + error= (repair(thd,param,0) != HA_ADMIN_OK); + } info(HA_STATUS_CONST); thd->proc_info=save_proc_info; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a15f8b65006..0f2116dbcdb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1614,7 +1614,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, VOID(pthread_mutex_lock(&LOCK_open)); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); VOID(pthread_mutex_unlock(&LOCK_open)); - error= table->file->activate_all_index(thd); + error= (table->file->activate_all_index(thd) ? -1 : 0); /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: From b50688d5e9c7163da29336d803d24a3735aac5b6 Mon Sep 17 00:00:00 2001 From: "hartmut@mysql.com" <> Date: Fri, 15 Oct 2004 15:33:30 +0200 Subject: [PATCH 087/143] the $^ directive is a GNU make extension and not really needed here so lets get rid of it (Bug #6112) --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 37b0432b98d..d4073ea441b 100644 --- a/configure.in +++ b/configure.in @@ -40,12 +40,12 @@ do case $host_os in netware* | modesto*) echo "$i/errmsg.sys: $i/errmsg.txt - \$(top_builddir)/extra/comp_err.linux \$^ $i/errmsg.sys" \ + \$(top_builddir)/extra/comp_err.linux $i/errmsg.txt $i/errmsg.sys" \ >> $AVAILABLE_LANGUAGES_ERRORS_RULES ;; *) echo "$i/errmsg.sys: $i/errmsg.txt - \$(top_builddir)/extra/comp_err \$^ $i/errmsg.sys" \ + \$(top_builddir)/extra/comp_err $i/errmsg.txt $i/errmsg.sys" \ >> $AVAILABLE_LANGUAGES_ERRORS_RULES ;; esac From 1d3fea70f89b7b7cf1d820c79924be400d1bec75 Mon Sep 17 00:00:00 2001 From: "paul@ice.snake.net" <> Date: Fri, 15 Oct 2004 23:12:15 -0500 Subject: [PATCH 088/143] texi2html: Changes parsing of @image argument. --- BitKeeper/etc/logging_ok | 1 + Docs/Support/texi2html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index d025a25f5c5..7a4086b9711 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -36,6 +36,7 @@ mwagner@cash.mwagner.org nick@mysql.com nick@nick.leippe.com paul@central.snake.net +paul@ice.snake.net paul@teton.kitebird.com salle@geopard.(none) salle@geopard.online.bg diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html index 5dda7c8bbd5..8067d8f72ce 100755 --- a/Docs/Support/texi2html +++ b/Docs/Support/texi2html @@ -1811,7 +1811,7 @@ sub fix_image { my($text) = @_; my($arg1, $ext); - $text =~ /^([^,]*)$/; + $text =~ /^([^,]*)/; die "error in image: '$text'" unless defined($1); $arg1 = $1; $arg1 =~ s/@@/@/g; From 1524f2d89dc35c15aeb74af77492e4665311457d Mon Sep 17 00:00:00 2001 From: "paul@ice.snake.net" <> Date: Fri, 15 Oct 2004 23:16:02 -0500 Subject: [PATCH 089/143] texi2html: Change parsing of @image argument. --- Docs/Support/texi2html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html index 5dda7c8bbd5..8067d8f72ce 100755 --- a/Docs/Support/texi2html +++ b/Docs/Support/texi2html @@ -1811,7 +1811,7 @@ sub fix_image { my($text) = @_; my($arg1, $ext); - $text =~ /^([^,]*)$/; + $text =~ /^([^,]*)/; die "error in image: '$text'" unless defined($1); $arg1 = $1; $arg1 =~ s/@@/@/g; From b9509655a52f629802358ac23d5533337a09ba1e Mon Sep 17 00:00:00 2001 From: "dellis@goetia.(none)" <> Date: Sun, 17 Oct 2004 18:44:51 -0500 Subject: [PATCH 090/143] mysqld.cc: BUG #5731 key_buffer_size not properly restricted to 4GB; use UINT_MAX32 for clarity. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c256c335399..ff867b010b0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4144,7 +4144,7 @@ replicating a LOAD DATA INFILE command", {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL, - REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (uint32) ~0, MALLOC_OVERHEAD, + REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, UINT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, {"long_query_time", OPT_LONG_QUERY_TIME, "Log all queries that have taken more than long_query_time seconds to execute to file.", From c01c8f99ea16fb2029efade30b8bf18ae314c03a Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Tue, 19 Oct 2004 09:50:47 +0500 Subject: [PATCH 091/143] libmysql.c: New function mysql_hex_string() --- libmysql/libmysql.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index a591ad9317d..9257bf0efd0 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3153,6 +3153,39 @@ void my_net_local_init(NET *net) net->max_packet_size= max(net_buffer_length, max_allowed_packet); } +/* + This function is used to create HEX string that you + can use in a SQL statement in of the either ways: + INSERT INTO blob_column VALUES (0xAABBCC); (any MySQL version) + INSERT INTO blob_column VALUES (X'AABBCC'); (4.1 and higher) + + The string in "from" is encoded to a HEX string. + The result is placed in "to" and a terminating null byte is appended. + + The string pointed to by "from" must be "length" bytes long. + You must allocate the "to" buffer to be at least length*2+1 bytes long. + Each character needs two bytes, and you need room for the terminating + null byte. When mysql_hex_string() returns, the contents of "to" will + be a null-terminated string. The return value is the length of the + encoded string, not including the terminating null character. +*/ + +unsigned long +mysql_hex_string(char *to, const char *from, unsigned long length) +{ + char *to0= to; + const char *end; + static char hex[]= "0123456789ABCDEF"; + + for (end= from + length; from < end; from++) + { + *to++= hex[((unsigned char) *from) >> 4]; + *to++= hex[((unsigned char) *from) & 0x0F]; + } + *to= '\0'; + return to-to0; +} + /* Add escape characters to a string (blob?) to make it suitable for a insert to should at least have place for length*2+1 chars From 72fca68a1ddfd41bb1a95c3b423f98f2b438f271 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Tue, 19 Oct 2004 11:54:33 +0300 Subject: [PATCH 092/143] fixed retsult code --- sql/sql_parse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9e0853a370b..1fe9e5093eb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1765,7 +1765,7 @@ mysql_execute_command(void) if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) { net_printf(&thd->net,ER_WRONG_TABLE_NAME,lex->name); - res=0; + res= 1; break; } if (!select_lex->db) From 462aed6c991fe5645759b40fb25f83826d76e50d Mon Sep 17 00:00:00 2001 From: "paul@ice.snake.net" <> Date: Tue, 19 Oct 2004 07:44:20 -0500 Subject: [PATCH 093/143] libmysql.c: Add note to mysql_hex_string() comment. --- libmysql/libmysql.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 9257bf0efd0..73f8f8f8b0b 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3168,6 +3168,9 @@ void my_net_local_init(NET *net) null byte. When mysql_hex_string() returns, the contents of "to" will be a null-terminated string. The return value is the length of the encoded string, not including the terminating null character. + + The return value does not contain any leading 0x or a leading X' and + trailing '. The caller must supply whichever of those is desired. */ unsigned long From 20ac420eb1900b3fa21a6b1cd772b51eb6f7c1c4 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Tue, 19 Oct 2004 18:58:53 +0300 Subject: [PATCH 094/143] trx0rec.c: test --- innobase/trx/trx0rec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c index 0e1842ef4a0..a5623b4d0c7 100644 --- a/innobase/trx/trx0rec.c +++ b/innobase/trx/trx0rec.c @@ -1377,7 +1377,7 @@ trx_undo_prev_version_build( fields. Store the info to ext_vect: */ ext_vect = mem_alloc(sizeof(ulint) * rec_get_n_fields(rec)); - n_ext_vect = btr_push_update_extern_fields(ext_vect, rec, + n_ext_vect = btr_push_update_extern_fields(ext_vect, rec, update); entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); From 1f8b3d0f22070d450226ef4f6e0e31c8ef8cd401 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 20 Oct 2004 11:24:08 +0300 Subject: [PATCH 095/143] Code cleanups (done during review of new code) Rename innodb_table_locks_old_behavior -> innodb_table_locks Set innodb_table_locks to off by default to get same behaviour as in MySQL 4.0.20 (This means that Innodb ignore table locks by default, which makes it easier to combine MyISAM and InnoDB to simulate a transaction) --- libmysql/libmysql.c | 10 +++---- myisam/myisampack.c | 12 ++++----- mysql-test/r/innodb-lock.result | 26 +++++++++++++++++++ mysql-test/t/innodb-lock.test | 46 ++++++++++++++++++++++++++++++++- sql/ha_innodb.cc | 2 +- sql/mysqld.cc | 10 +++---- sql/set_var.cc | 8 +++--- sql/sql_class.h | 2 +- 8 files changed, 91 insertions(+), 25 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 9257bf0efd0..09675bc7fab 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3170,20 +3170,18 @@ void my_net_local_init(NET *net) encoded string, not including the terminating null character. */ -unsigned long -mysql_hex_string(char *to, const char *from, unsigned long length) +ulong mysql_hex_string(char *to, const char *from, ulong length) { char *to0= to; const char *end; - static char hex[]= "0123456789ABCDEF"; for (end= from + length; from < end; from++) { - *to++= hex[((unsigned char) *from) >> 4]; - *to++= hex[((unsigned char) *from) & 0x0F]; + *to++= _dig_vec[((unsigned char) *from) >> 4]; + *to++= _dig_vec[((unsigned char) *from) & 0x0F]; } *to= '\0'; - return to-to0; + return (ulong) (to-to0); } /* diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 5efd6b3a7fd..0dde1916f03 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -418,14 +418,12 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count) mrg->src_file_has_indexes_disabled= 0; for (i=0; i < count ; i++) { - if ((mrg->file[i]=open_isam_file(names[i],O_RDONLY))) - { - mrg->src_file_has_indexes_disabled |= - (mrg->file[i]->s->state.key_map != - (1ULL << mrg->file[i]->s->base.keys) - 1); - } - else + if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY))) goto error; + + mrg->src_file_has_indexes_disabled|= ((mrg->file[i]->s->state.key_map != + (((ulonglong) 1) << + mrg->file[i]->s->base. keys) - 1)); } /* Check that files are identical */ for (j=0 ; j < count-1 ; j++) diff --git a/mysql-test/r/innodb-lock.result b/mysql-test/r/innodb-lock.result index cf00adb30ae..f87f221ea66 100644 --- a/mysql-test/r/innodb-lock.result +++ b/mysql-test/r/innodb-lock.result @@ -1,4 +1,30 @@ drop table if exists t1; +select @@innodb_table_locks; +@@innodb_table_locks +0 +set @@innodb_table_locks=1; +create table t1 (id integer, x integer) engine=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; +id x +0 0 +set autocommit=0; +lock table t1 write; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +commit; +update t1 set x=2 where id = 0; +commit; +unlock tables; +select * from t1; +id x +0 2 +commit; +drop table t1; +set @@innodb_table_locks=0; create table t1 (id integer, x integer) engine=INNODB; insert into t1 values(0, 0); set autocommit=0; diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test index 43a175508b4..11395b301c4 100644 --- a/mysql-test/t/innodb-lock.test +++ b/mysql-test/t/innodb-lock.test @@ -5,9 +5,17 @@ connect (con2,localhost,root,,); drop table if exists t1; # -# Testing of explicit table locks +# Check and select innodb lock type # +select @@innodb_table_locks; + +# +# Testing of explicit table locks with enforced table locks +# + +set @@innodb_table_locks=1; + connection con1; create table t1 (id integer, x integer) engine=INNODB; insert into t1 values(0, 0); @@ -38,3 +46,39 @@ select * from t1; commit; drop table t1; + +# +# Try with old lock method (where LOCK TABLE is ignored) +# + +set @@innodb_table_locks=0; + +create table t1 (id integer, x integer) engine=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; + +connection con2; +set autocommit=0; + +# The following statement should hang because con1 is locking the page +--send +lock table t1 write; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +update t1 set x=2 where id = 0; +commit; +unlock tables; + +connection con1; +select * from t1; +commit; + +drop table t1; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 44d050d14aa..e747ff3210c 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4694,7 +4694,7 @@ ha_innobase::external_lock( if (prebuilt->select_lock_type != LOCK_NONE) { if (thd->in_lock_tables && - !thd->variables.innodb_table_locks_old_behavior) { + thd->variables.innodb_table_locks) { ulint error; error = row_lock_table_for_mysql(prebuilt); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 226d4c113a5..b7eafcbcc14 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3526,7 +3526,7 @@ enum options_mysqld { OPT_INNODB_FORCE_RECOVERY, OPT_INNODB_STATUS_FILE, OPT_INNODB_MAX_DIRTY_PAGES_PCT, - OPT_INNODB_TABLE_LOCKS_OLD_BEHAVIOR, + OPT_INNODB_TABLE_LOCKS, OPT_BDB_CACHE_SIZE, OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_MAX_LOCK, @@ -3700,10 +3700,10 @@ struct my_option my_long_options[] = {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT, "Percentage of dirty pages allowed in bufferpool", (gptr*) &srv_max_buf_pool_modified_pct, (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, - {"innodb_table_locks_old_behavior", OPT_INNODB_TABLE_LOCKS_OLD_BEHAVIOR, - "Disable InnoDB locking in LOCK TABLES", - (gptr*) &global_system_variables.innodb_table_locks_old_behavior, - (gptr*) &global_system_variables.innodb_table_locks_old_behavior, + {"innodb_table_locks", OPT_INNODB_TABLE_LOCKS, + "If Innodb should enforce LOCK TABLE", + (gptr*) &global_system_variables.innodb_table_locks, + (gptr*) &global_system_variables.innodb_table_locks, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif /* End HAVE_INNOBASE_DB */ {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, diff --git a/sql/set_var.cc b/sql/set_var.cc index 9b2db7a0802..a6a5ea72c71 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -263,8 +263,8 @@ sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", #ifdef HAVE_INNOBASE_DB sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct", &srv_max_buf_pool_modified_pct); -sys_var_thd_bool sys_innodb_table_locks_old_behavior("innodb_table_locks_old_behavior", - &SV::innodb_table_locks_old_behavior); +sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks", + &SV::innodb_table_locks); #endif @@ -451,7 +451,7 @@ sys_var *sys_variables[]= &sys_os, #ifdef HAVE_INNOBASE_DB &sys_innodb_max_dirty_pages_pct, - &sys_innodb_table_locks_old_behavior, + &sys_innodb_table_locks, #endif &sys_unique_checks }; @@ -523,7 +523,7 @@ struct show_var_st init_vars[]= { {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, - {sys_innodb_table_locks_old_behavior.name, (char*) &sys_innodb_table_locks_old_behavior, SHOW_SYS}, + {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, 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}, diff --git a/sql/sql_class.h b/sql/sql_class.h index 8c383d5848d..4250ebdd568 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -339,7 +339,7 @@ struct system_variables my_bool new_mode; my_bool query_cache_wlock_invalidate; #ifdef HAVE_INNOBASE_DB - my_bool innodb_table_locks_old_behavior; + my_bool innodb_table_locks; #endif /* HAVE_INNOBASE_DB */ CONVERT *convert_set; From b32ffec8fdc9d05377e69c8b1abb92d562670324 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 20 Oct 2004 16:04:28 +0300 Subject: [PATCH 096/143] Fix test case for innodb-lock --- mysql-test/r/innodb-lock.result | 30 +++++++++++------- mysql-test/t/innodb-lock-master.opt | 1 + mysql-test/t/innodb-lock.test | 47 ++++++++++++++++++----------- mysys/thr_lock.c | 12 ++++++-- sql/mysqld.cc | 2 +- sql/sql_base.cc | 2 ++ 6 files changed, 62 insertions(+), 32 deletions(-) create mode 100644 mysql-test/t/innodb-lock-master.opt diff --git a/mysql-test/r/innodb-lock.result b/mysql-test/r/innodb-lock.result index f87f221ea66..407a85ed038 100644 --- a/mysql-test/r/innodb-lock.result +++ b/mysql-test/r/innodb-lock.result @@ -1,7 +1,7 @@ -drop table if exists t1; select @@innodb_table_locks; @@innodb_table_locks -0 +1 +drop table if exists t1; set @@innodb_table_locks=1; create table t1 (id integer, x integer) engine=INNODB; insert into t1 values(0, 0); @@ -25,24 +25,32 @@ id x commit; drop table t1; set @@innodb_table_locks=0; -create table t1 (id integer, x integer) engine=INNODB; -insert into t1 values(0, 0); -set autocommit=0; +create table t1 (id integer primary key, x integer) engine=INNODB; +insert into t1 values(0, 0),(1,1),(2,2); +commit; SELECT * from t1 where id = 0 FOR UPDATE; id x 0 0 set autocommit=0; +set @@innodb_table_locks=0; lock table t1 write; -update t1 set x=1 where id = 0; -select * from t1; +update t1 set x=10 where id = 2; +SELECT * from t1 where id = 2; id x -0 1 +2 2 +UPDATE t1 set x=3 where id = 2; commit; -update t1 set x=2 where id = 0; +SELECT * from t1; +id x +0 0 +1 1 +2 3 commit; unlock tables; +commit; select * from t1; id x -0 2 -commit; +0 0 +1 1 +2 10 drop table t1; diff --git a/mysql-test/t/innodb-lock-master.opt b/mysql-test/t/innodb-lock-master.opt new file mode 100644 index 00000000000..403fcde87ed --- /dev/null +++ b/mysql-test/t/innodb-lock-master.opt @@ -0,0 +1 @@ +--innodb-table-lock=1 diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test index 11395b301c4..430369f4fda 100644 --- a/mysql-test/t/innodb-lock.test +++ b/mysql-test/t/innodb-lock.test @@ -1,9 +1,5 @@ -- source include/have_innodb.inc -connect (con1,localhost,root,,); -connect (con2,localhost,root,,); -drop table if exists t1; - # # Check and select innodb lock type # @@ -14,6 +10,14 @@ select @@innodb_table_locks; # Testing of explicit table locks with enforced table locks # +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +drop table if exists t1; + +# +# Testing of explicit table locks with enforced table locks +# + set @@innodb_table_locks=1; connection con1; @@ -48,37 +52,44 @@ commit; drop table t1; # -# Try with old lock method (where LOCK TABLE is ignored) +# Try with old lock method (where LOCK TABLE is ignored by InnoDB) # set @@innodb_table_locks=0; -create table t1 (id integer, x integer) engine=INNODB; -insert into t1 values(0, 0); -set autocommit=0; +create table t1 (id integer primary key, x integer) engine=INNODB; +insert into t1 values(0, 0),(1,1),(2,2); +commit; SELECT * from t1 where id = 0 FOR UPDATE; connection con2; set autocommit=0; +set @@innodb_table_locks=0; -# The following statement should hang because con1 is locking the page ---send +# The following statement should work becase innodb doesn't check table locks lock table t1 write; ---sleep 2; connection con1; -update t1 set x=1 where id = 0; -select * from t1; -commit; + +# This will be locked by MySQL +--send +update t1 set x=10 where id = 2; +--sleep 2 connection con2; -reap; -update t1 set x=2 where id = 0; + +# Note that we will get a deadlock if we try to select any rows marked +# for update by con1 ! + +SELECT * from t1 where id = 2; +UPDATE t1 set x=3 where id = 2; +commit; +SELECT * from t1; commit; unlock tables; connection con1; -select * from t1; +reap; commit; - +select * from t1; drop table t1; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index d5236cb1ef9..935ed4ea282 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -552,8 +552,14 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) !lock->write_wait.data && lock->write.data->type == TL_WRITE_ALLOW_WRITE)) { - /* We have already got a write lock or all locks are - TL_WRITE_ALLOW_WRITE */ + /* + We have already got a write lock or all locks are + TL_WRITE_ALLOW_WRITE + */ + DBUG_PRINT("info", ("write_wait.data: 0x%lx old_type: %d", + (ulong) lock->write_wait.data, + lock->write.data->type)); + (*lock->write.last)=data; /* Add to running fifo */ data->prev=lock->write.last; lock->write.last= &data->next; @@ -568,6 +574,8 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) } else { + DBUG_PRINT("info", ("write_wait.data: 0x%lx", + (ulong) lock->write_wait.data)); if (!lock->write_wait.data) { /* no scheduled write locks */ if (lock_type == TL_WRITE_CONCURRENT_INSERT && diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b7eafcbcc14..5838bd909dd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3704,7 +3704,7 @@ struct my_option my_long_options[] = "If Innodb should enforce LOCK TABLE", (gptr*) &global_system_variables.innodb_table_locks, (gptr*) &global_system_variables.innodb_table_locks, - 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, #endif /* End HAVE_INNOBASE_DB */ {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9810ec6c3d6..72400bf0abb 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -826,6 +826,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, DBUG_RETURN(0); } table->query_id=thd->query_id; + DBUG_PRINT("info",("Using temporary table")); goto reset; } } @@ -840,6 +841,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, table->query_id != thd->query_id) { table->query_id=thd->query_id; + DBUG_PRINT("info",("Using locked table")); goto reset; } } From b4773b590a8826bb927ec0a676304586f014053e Mon Sep 17 00:00:00 2001 From: "paul@kite-hub.kitebird.com" <> Date: Thu, 21 Oct 2004 12:08:51 -0500 Subject: [PATCH 097/143] texi2html: Update texi2html with version from mysqldoc repository. (Please merge this forward to 4.0, 4.1, 5.0.) --- BitKeeper/etc/logging_ok | 1 + Docs/Support/texi2html | 98 ++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 7a4086b9711..b82221bfb95 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -37,6 +37,7 @@ nick@mysql.com nick@nick.leippe.com paul@central.snake.net paul@ice.snake.net +paul@kite-hub.kitebird.com paul@teton.kitebird.com salle@geopard.(none) salle@geopard.online.bg diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html index 8067d8f72ce..f13c006c7dc 100755 --- a/Docs/Support/texi2html +++ b/Docs/Support/texi2html @@ -1,4 +1,4 @@ -#!PATH_TO_PERL -*- perl -*- +#!/usr/bin/perl # Add path to perl on the previous line and make this executable # if you want to use this as a normal script. 'di '; @@ -12,7 +12,7 @@ #-############################################################################## # @(#)texi2html 1.52 971230 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch -# Enhanced by David Axmark, david@detron.se +# Enhanced by David Axmark # The man page for this program is included at the end of this file and can be # viewed using the command 'nroff -man texi2html'. @@ -40,8 +40,7 @@ $NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names $XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE) $ERROR = "***"; # prefix for errors and warnings -$THISPROG = "texi2html 1.52 (hacked by david\@detron.se)"; # program name and version -$HOMEPAGE = "http://www.mathematik.uni-kl.de/~obachman/Texi2html/"; # program home page +$THISPROG = "texi2html 1.52 (with additions by MySQL AB)"; # program name and version $TODAY = &pretty_date; # like "20 September 1993" $SPLITTAG = "\n"; # tag to know where to split $PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections @@ -114,10 +113,12 @@ $html2_doctype = '", # HTML+ + "*", "
", # HTML+ " ", " ", "\n", "\n", "|", "", @@ -134,6 +135,8 @@ $html2_doctype = '', # paragraph break + 'br', '

', # paragraph break 'bullet', '*', 'copyright', '(C)', + 'registeredsymbol', '(R)', 'dots', '...', 'equiv', '==', 'error', 'error-->', @@ -161,27 +165,28 @@ $html2_doctype = '\n", __LINE__)); + push(@lines, &debug("\n", __LINE__)); } else { warn "$ERROR Bad table line: $_"; } @@ -873,7 +887,7 @@ READ_LINE: while ($_ = &next_line) &simple_substitutions; s/\@value{($VARRE)}/$value{$1}/eg; s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4 - s|\s+\@tab\s*| \n", __LINE__)) unless $html_element eq 'TABLE'; &html_pop_if('TR'); - $what =~ s|\s+\@tab\s*|
|g if ($in_multitable); + s/(^|\s+)\@tab\s*/ <\/TD> /g if ($in_multitable); # # analyze the tag again @@ -885,7 +899,7 @@ READ_LINE: while ($_ = &next_line) $name =~ s/\s+$//; $level = $sec2level{$tag}; $name = &update_sec_num($tag, $level) . " $name" - if $number_sections && $tag !~ /^unnumbered/; + if $number_sections && $tag !~ /^unnumbered/ && $tag ne 'subsubheading'; if ($tag =~ /heading$/) { push(@lines, &html_debug("\n", __LINE__)); if ($html_element ne 'body') { @@ -1079,7 +1093,7 @@ EOC push(@lines, &debug("
|g; + $what =~ s/(^|\s+)\@tab\s*/ <\/TD> /g; push(@lines, &debug("
$what\n", __LINE__)); &html_push('TR'); if ($deferred_ref) @@ -1463,11 +1477,7 @@ print "# end of pass 4\n" if $verbose; # # #---############################################################################ -$header = < -EOT - + $header = ''; $full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document"; $title = $value{'_settitle'} || $full_title; $_ = &substitute_style($full_title); @@ -1815,8 +1825,10 @@ sub fix_image die "error in image: '$text'" unless defined($1); $arg1 = $1; $arg1 =~ s/@@/@/g; - $ext = "jpg" if -f "$arg1.jpg"; - $ext = "gif" if -f "$arg1.gif"; + foreach (@include_dirs) { + $ext = "jpg" if -f "$_/$arg1.jpg"; + $ext = "gif" if -f "$_/$arg1.gif"; + } if (defined($ext)) { ""; @@ -2010,7 +2022,7 @@ sub print_toplevel_header { local($_); - &print_header; # pass given arg... + &print_header unless $opt_empty_headers; # pass given arg... print FILE $full_title; if ($value{'_subtitle'}) { $value{'_subtitle'} =~ s/\n+$//; @@ -2042,13 +2054,7 @@ EOT sub print_toplevel_footer { - &print_ruler; - print FILE <texi2html -translator version 1.52 (extended by davida\@detron.se).

-EOT - &print_footer; + &print_footer unless $opt_empty_headers; } sub protect_texi @@ -2065,8 +2071,10 @@ sub protect_html { local($what) = @_; # protect & < > - # Avoid loop in & replacement. This instead bugs out for &# in text.. - $what =~ s/\&([^#]|$)/\&\#38;$1/g; + # hack for the two entity-like variable reference in existing examples + $what =~ s/\&(length|ts);/\&\#38;$1;/g; + # this leaves alone entities, but encodes standalone ampersands + $what =~ s/\&(?!([a-z0-9]+|#\d+);)/\&\#38;/ig; $what =~ s/\/\&\#62;/g; # but recognize some HTML things From ded12c828ded747d2f76c97addb4b4a6677594fe Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Thu, 21 Oct 2004 23:56:12 +0300 Subject: [PATCH 098/143] Check of temporary tables hiding for query fetched from QC (BUG#6084) --- mysql-test/r/query_cache.result | 13 +++++++++++++ mysql-test/t/query_cache.test | 12 ++++++++++++ sql/sql_cache.cc | 32 +++++++++++++++++++++++++++++++- sql/sql_cache.h | 3 +++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a9e9f167e5f..85fe77b1f10 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -704,4 +704,17 @@ Qcache_queries_in_cache 1 unlock table; drop table t1,t2; set query_cache_wlock_invalidate=default; +CREATE TABLE t1 (id INT PRIMARY KEY); +insert into t1 values (1),(2),(3); +select * from t1; +id +1 +2 +3 +create temporary table t1 (a int not null auto_increment +primary key); +select * from t1; +a +drop table t1; +drop table t1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 8a07c0a53a0..61fbadde1e1 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -521,4 +521,16 @@ unlock table; drop table t1,t2; set query_cache_wlock_invalidate=default; +# +# hiding real table stored in query cache by temporary table +# +CREATE TABLE t1 (id INT PRIMARY KEY); +insert into t1 values (1),(2),(3); +select * from t1; +create temporary table t1 (a int not null auto_increment +primary key); +select * from t1; +drop table t1; +drop table t1; + set GLOBAL query_cache_size=0; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 60f0cfadc8e..8e953e223a9 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -971,9 +971,38 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) for (; block_table != block_table_end; block_table++) { TABLE_LIST table_list; - bzero((char*) &table_list,sizeof(table_list)); + TABLE *tmptable; Query_cache_table *table = block_table->parent; + + /* + Check that we have not temporary tables with same names of tables + of this query. If we have such tables, we will not send data from + query cache, because temporary tables hide real tables by which + query in query cache was made. + */ + for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next) + { + if (tmptable->key_length - 8 == table->key_len() && + !memcmp(tmptable->table_cache_key, table->data(), + table->key_len())) + { + DBUG_PRINT("qcache", + ("Temporary table detected: '%s.%s'", + table_list.db, table_list.alias)); + STRUCT_UNLOCK(&structure_guard_mutex); + /* + We should not store result of this query because it contain + temporary tables => assign following wariable to make check + faster. + */ + thd->safe_to_cache_query=0; + BLOCK_UNLOCK_RD(query_block); + DBUG_RETURN(-1); + } + } + + bzero((char*) &table_list,sizeof(table_list)); table_list.db = table->db(); table_list.alias= table_list.real_name= table->table(); if (check_table_access(thd,SELECT_ACL,&table_list,1)) @@ -2066,6 +2095,7 @@ Query_cache::insert_table(uint key_len, char *key, } char *db = header->db(); header->table(db + db_length + 1); + header->key_len(key_len); } Query_cache_block_table *list_root = table_block->table(0); diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 0c6579250ab..454f0318c12 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -144,10 +144,13 @@ struct Query_cache_query struct Query_cache_table { char *tbl; + uint32 key_length; inline char *db() { return (char *) data(); } inline char *table() { return tbl; } inline void table(char *table) { tbl = table; } + inline uint32 key_len() { return key_length; } + inline void key_len(uint32 len) { key_length= len; } inline gptr data() { return (gptr)(((byte*)this)+ From 215cd1e4a39f5844df1b1be51dfba7ab1f964f31 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 22 Oct 2004 00:25:57 +0300 Subject: [PATCH 099/143] row0mysql.c, row0ins.c: Fix bug #5961: release the dictionary latch during a long cascaded FOREIGN KEY operation, so that we do not starve other users --- innobase/row/row0ins.c | 17 +++++++++++++++++ innobase/row/row0mysql.c | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 458970da4e2..b9f860903cb 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -966,6 +966,23 @@ row_ins_foreign_check_on_constraint( err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); + + if (foreign->foreign_table->n_foreign_key_checks_running == 0) { + fprintf(stderr, +"InnoDB: error: table %s has the counter 0 though there is\n" +"InnoDB: a FOREIGN KEY check running on it.\n", + foreign->foreign_table->name); + } + + /* Release the data dictionary latch for a while, so that we do not + starve other threads from doing CREATE TABLE etc. if we have a huge + cascaded operation running. The counter n_foreign_key_checks_running + will prevent other users from dropping or ALTERing the table when we + release the latch. */ + + row_mysql_unfreeze_data_dictionary(thr_get_trx(thr)); + row_mysql_freeze_data_dictionary(thr_get_trx(thr)); + mtr_start(mtr); /* Restore pcur position */ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index a884dc8d9ef..3eb4f0de60e 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2156,8 +2156,8 @@ row_drop_table_for_mysql( fputs(" InnoDB: You are trying to drop table ", stderr); ut_print_name(stderr, table->name); fputs("\n" - "InnoDB: though there are foreign key check running on it.\n" - "InnoDB: Adding the table to the background drop queue.\n", + "InnoDB: though there is a foreign key check running on it.\n" + "InnoDB: Adding the table to the background drop queue.\n", stderr); row_add_table_to_background_drop_list(table); From dd1b2ace33134dcf188f17261ea854fdda227a7e Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 22 Oct 2004 10:45:00 +0300 Subject: [PATCH 100/143] os0file.c: Add typecast from ulint to ssize_t in pread and pwrite, so that the type is according to the Linux man page; this will probably not help to fix the HP-UX 32-bit pwrite failure, since the compiler should do the appropriate typecasts anyway --- innobase/os/os0file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index b09c48319c3..6ed3720cc84 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -1186,7 +1186,7 @@ os_file_pread( os_file_n_pending_preads++; os_mutex_exit(os_file_count_mutex); - n_bytes = pread(file, buf, n, offs); + n_bytes = pread(file, buf, (ssize_t)n, offs); os_mutex_enter(os_file_count_mutex); os_file_n_pending_preads--; @@ -1211,7 +1211,7 @@ os_file_pread( return(ret); } - ret = read(file, buf, n); + ret = read(file, buf, (ssize_t)n); os_mutex_exit(os_file_seek_mutexes[i]); @@ -1261,7 +1261,7 @@ os_file_pwrite( os_file_n_pending_pwrites++; os_mutex_exit(os_file_count_mutex); - ret = pwrite(file, buf, n, offs); + ret = pwrite(file, buf, (ssize_t)n, offs); os_mutex_enter(os_file_count_mutex); os_file_n_pending_pwrites--; @@ -1296,7 +1296,7 @@ os_file_pwrite( return(ret); } - ret = write(file, buf, n); + ret = write(file, buf, (ssize_t)n); if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC From 6b6692dc4d3d54d844e91105de8ce32c55e5d43d Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Fri, 22 Oct 2004 19:27:43 +0400 Subject: [PATCH 101/143] Part of fix for bug #6081 "Call to deprecated mysql_create_db() function crashes server" (in 4.0 we fix only connection stalling in case of error, crash itself is fixed in 4.1, the test case for this code is also there). --- sql/sql_parse.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9e0853a370b..7c21a5af2a6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1142,7 +1142,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (check_access(thd,CREATE_ACL,db,0,1)) break; mysql_log.write(thd,command,packet); - mysql_create_db(thd,(lower_case_table_names == 2 ? alias : db),0,0); + if (mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db), + 0, 0) < 0) + send_error(&thd->net, thd->killed ? ER_SERVER_SHUTDOWN : 0); break; } case COM_DROP_DB: // QQ: To be removed @@ -1163,7 +1165,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } mysql_log.write(thd,command,db); - mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db), 0, 0); + if (mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db), + 0, 0) < 0) + send_error(&thd->net, thd->killed ? ER_SERVER_SHUTDOWN : 0); break; } case COM_BINLOG_DUMP: From ce93a3c202912569b9274f13a93daeec9a20b910 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Fri, 22 Oct 2004 22:51:04 +0300 Subject: [PATCH 102/143] postreview fixes --- sql/mysql_priv.h | 1 + sql/sql_base.cc | 5 +++-- sql/sql_cache.cc | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b5e571e74d0..b123927d09e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -551,6 +551,7 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags); #define MYSQL_HA_FLUSH_ALL 0x02 /* sql_base.cc */ +#define TMP_TABLE_KEY_EXTRA 8 void set_item_name(Item *item,char *pos,uint length); bool add_field_to_list(char *field_name, enum enum_field_types type, char *length, char *decimal, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 72400bf0abb..ddc81053357 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -816,8 +816,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, for (table=thd->temporary_tables; table ; table=table->next) { - if (table->key_length == key_length+8 && - !memcmp(table->table_cache_key,key,key_length+8)) + if (table->key_length == key_length + TMP_TABLE_KEY_EXTRA && + !memcmp(table->table_cache_key, key, + key_length + TMP_TABLE_KEY_EXTRA)) { if (table->query_id == thd->query_id) { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 8e953e223a9..f503a63e752 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -983,7 +983,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) */ for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next) { - if (tmptable->key_length - 8 == table->key_len() && + if (tmptable->key_length - TMP_TABLE_KEY_EXTRA == table->key_len() && !memcmp(tmptable->table_cache_key, table->data(), table->key_len())) { @@ -993,7 +993,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) STRUCT_UNLOCK(&structure_guard_mutex); /* We should not store result of this query because it contain - temporary tables => assign following wariable to make check + temporary tables => assign following variable to make check faster. */ thd->safe_to_cache_query=0; From b5f49a3abd515faafed24164e4d01c1a6c5dcc42 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 27 Oct 2004 13:33:11 +0300 Subject: [PATCH 103/143] Backport innodb_max_purge_lag from 4.1 --- innobase/include/srv0srv.h | 2 ++ innobase/include/trx0sys.h | 4 ++++ innobase/row/row0mysql.c | 17 +++++++++++++++++ innobase/srv/srv0srv.c | 6 ++++++ innobase/trx/trx0purge.c | 38 ++++++++++++++++++++++++++++++++++++++ innobase/trx/trx0rseg.c | 7 ++++++- sql/ha_innodb.h | 1 + sql/mysqld.cc | 6 ++++++ sql/set_var.cc | 4 ++++ 9 files changed, 84 insertions(+), 1 deletion(-) diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 57ca1f84f26..c76a1917615 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -99,6 +99,7 @@ extern ibool srv_use_doublewrite_buf; extern ibool srv_set_thread_priorities; extern int srv_query_thread_priority; +extern ulint srv_max_purge_lag; /*-------------------------------------------*/ extern ulint srv_n_rows_inserted; @@ -152,6 +153,7 @@ extern ulint srv_test_array_size; extern ulint srv_activity_count; extern ulint srv_fatal_semaphore_wait_threshold; +extern ulint srv_dml_needed_delay; extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs, query threads, and lock table: we allocate diff --git a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h index c7ef4d1929d..4d83c5eeaae 100644 --- a/innobase/include/trx0sys.h +++ b/innobase/include/trx0sys.h @@ -419,6 +419,10 @@ struct trx_sys_struct{ trx_rseg_t* rseg_array[TRX_SYS_N_RSEGS]; /* Pointer array to rollback segments; NULL if slot not in use */ + ulint rseg_history_len;/* Length of the TRX_RSEG_HISTORY + list (update undo logs for committed + transactions), protected by + rseg->mutex */ UT_LIST_BASE_NODE_T(read_view_t) view_list; /* List of read views sorted on trx no, biggest first */ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 3eb4f0de60e..78b2aa8e28f 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -89,6 +89,19 @@ row_mysql_is_system_table( || 0 == strcmp(name + 6, "user") || 0 == strcmp(name + 6, "db")); } + +/*********************************************************************** +Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */ +static +void +row_mysql_delay_if_needed(void) +/*===========================*/ +{ + if (srv_dml_needed_delay) { + os_thread_sleep(srv_dml_needed_delay); + } +} + /*********************************************************************** Reads a MySQL format variable-length field (like VARCHAR) length and returns pointer to the field data. */ @@ -856,6 +869,8 @@ row_insert_for_mysql( trx->op_info = (char *) "inserting"; + row_mysql_delay_if_needed(); + trx_start_if_not_started(trx); if (node == NULL) { @@ -1071,6 +1086,8 @@ row_update_for_mysql( trx->op_info = (char *) "updating or deleting"; + row_mysql_delay_if_needed(); + trx_start_if_not_started(trx); node = prebuilt->upd_node; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 0643ab96c1d..0a814268a36 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -58,6 +58,10 @@ ulint srv_activity_count = 0; /* The following is the maximum allowed duration of a lock wait. */ ulint srv_fatal_semaphore_wait_threshold = 600; +/* How much data manipulation language (DML) statements need to be delayed, +in microseconds, in order to reduce the lagging of the purge thread. */ +ulint srv_dml_needed_delay = 0; + ibool srv_lock_timeout_and_monitor_active = FALSE; ibool srv_error_monitor_active = FALSE; @@ -841,6 +845,8 @@ srv_general_init(void) /*======================= InnoDB Server FIFO queue =======================*/ +/* Maximum allowable purge history length. <=0 means 'infinite'. */ +ulint srv_max_purge_lag = 0; /************************************************************************* Puts an OS thread to wait if there are too many concurrent threads diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c index a8b6b9fcc21..d772af47b29 100644 --- a/innobase/trx/trx0purge.c +++ b/innobase/trx/trx0purge.c @@ -295,6 +295,9 @@ trx_purge_add_update_undo_to_history( /* Add the log as the first in the history list */ flst_add_first(rseg_header + TRX_RSEG_HISTORY, undo_header + TRX_UNDO_HISTORY_NODE, mtr); + mutex_enter(&kernel_mutex); + trx_sys->rseg_history_len++; + mutex_exit(&kernel_mutex); /* Write the trx number to the undo log header */ mlog_write_dulint(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr); @@ -386,6 +389,12 @@ loop: flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY, log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr); + + mutex_enter(&kernel_mutex); + ut_ad(trx_sys->rseg_history_len >= n_removed_logs); + trx_sys->rseg_history_len -= n_removed_logs; + mutex_exit(&kernel_mutex); + freed = FALSE; while (!freed) { @@ -470,6 +479,11 @@ loop: } if (cmp >= 0) { + mutex_enter(&kernel_mutex); + ut_a(trx_sys->rseg_history_len >= n_removed_logs); + trx_sys->rseg_history_len -= n_removed_logs; + mutex_exit(&kernel_mutex); + flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY, log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr); @@ -1031,6 +1045,30 @@ trx_purge(void) purge_sys->view = NULL; mem_heap_empty(purge_sys->heap); + /* Determine how much data manipulation language (DML) statements + need to be delayed in order to reduce the lagging of the purge + thread. */ + srv_dml_needed_delay = 0; /* in microseconds; default: no delay */ + + /* If we cannot advance the 'purge view' because of an old + 'consistent read view', then the DML statements cannot be delayed. + Also, srv_max_purge_lag <= 0 means 'infinity'. */ + if (srv_max_purge_lag > 0 + && !UT_LIST_GET_LAST(trx_sys->view_list)) { + float ratio = (float) trx_sys->rseg_history_len + / srv_max_purge_lag; + if (ratio > ULINT_MAX / 10000) { + /* Avoid overflow: maximum delay is 4295 seconds */ + srv_dml_needed_delay = ULINT_MAX; + } else if (ratio > 1) { + /* If the history list length exceeds the + innodb_max_purge_lag, the + data manipulation statements are delayed + by at least 5000 microseconds. */ + srv_dml_needed_delay = (ulint) ((ratio - .5) * 10000); + } + } + purge_sys->view = read_view_oldest_copy_or_open_new(NULL, purge_sys->heap); mutex_exit(&kernel_mutex); diff --git a/innobase/trx/trx0rseg.c b/innobase/trx/trx0rseg.c index e3885c86def..a01d4bb835d 100644 --- a/innobase/trx/trx0rseg.c +++ b/innobase/trx/trx0rseg.c @@ -135,6 +135,7 @@ trx_rseg_mem_create( trx_ulogf_t* undo_log_hdr; fil_addr_t node_addr; ulint sum_of_undo_sizes; + ulint len; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); @@ -166,7 +167,9 @@ trx_rseg_mem_create( MLOG_4BYTES, mtr) + 1 + sum_of_undo_sizes; - if (flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr) > 0) { + len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr); + if (len > 0) { + trx_sys->rseg_history_len += len; node_addr = trx_purge_get_log_from_hist( flst_get_last(rseg_header + TRX_RSEG_HISTORY, @@ -206,6 +209,8 @@ trx_rseg_list_and_array_init( UT_LIST_INIT(trx_sys->rseg_list); + trx_sys->rseg_history_len = 0; + for (i = 0; i < TRX_SYS_N_RSEGS; i++) { page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr); diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 5736f70c65c..74acc0640c9 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -207,6 +207,7 @@ extern my_bool innobase_log_archive, innobase_create_status_file; extern "C" { extern ulong srv_max_buf_pool_modified_pct; +extern ulong srv_max_purge_lag; } extern TYPELIB innobase_lock_typelib; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5838bd909dd..d36b441ac9a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3520,6 +3520,7 @@ enum options_mysqld { OPT_INNODB_LOG_BUFFER_SIZE, OPT_INNODB_BUFFER_POOL_SIZE, OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE, + OPT_INNODB_MAX_PURGE_LAG, OPT_INNODB_FILE_IO_THREADS, OPT_INNODB_LOCK_WAIT_TIMEOUT, OPT_INNODB_THREAD_CONCURRENCY, @@ -3700,6 +3701,11 @@ struct my_option my_long_options[] = {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT, "Percentage of dirty pages allowed in bufferpool", (gptr*) &srv_max_buf_pool_modified_pct, (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, + {"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG, + "", + (gptr*) &srv_max_purge_lag, + (gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L, + 0, 1L, 0}, {"innodb_table_locks", OPT_INNODB_TABLE_LOCKS, "If Innodb should enforce LOCK TABLE", (gptr*) &global_system_variables.innodb_table_locks, diff --git a/sql/set_var.cc b/sql/set_var.cc index a6a5ea72c71..d5aadbfbdab 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -263,6 +263,8 @@ sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", #ifdef HAVE_INNOBASE_DB sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct", &srv_max_buf_pool_modified_pct); +sys_var_long_ptr sys_innodb_max_purge_lag("innodb_max_purge_lag", + &srv_max_purge_lag); sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks", &SV::innodb_table_locks); #endif @@ -451,6 +453,7 @@ sys_var *sys_variables[]= &sys_os, #ifdef HAVE_INNOBASE_DB &sys_innodb_max_dirty_pages_pct, + &sys_innodb_max_purge_lag, &sys_innodb_table_locks, #endif &sys_unique_checks @@ -523,6 +526,7 @@ struct show_var_st init_vars[]= { {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, + {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS}, #endif {sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS}, From cee5d36be8f37fdba0df14f1445a3804d7c0d915 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Wed, 27 Oct 2004 17:54:10 +0200 Subject: [PATCH 104/143] Change 'Build-tools/mysql-copyright' to ensure the receiving machines will build without trying to re-run autotools. (Backport from 4.1.7 for 4.0.22) --- Build-tools/mysql-copyright | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Build-tools/mysql-copyright b/Build-tools/mysql-copyright index 251a6c78d23..81d6d761498 100755 --- a/Build-tools/mysql-copyright +++ b/Build-tools/mysql-copyright @@ -3,7 +3,7 @@ # Untar a MySQL distribution, change the copyright texts, # pack it up again to a given directory -$VER="1.4"; +$VER="1.5"; use Cwd; use File::Basename; @@ -103,9 +103,8 @@ sub main unlink("$destdir/PUBLIC", "$destdir/README"); unlink("$destdir/COPYING", "$destdir/EXCEPTIONS-CLIENT"); copy("$WD/Docs/MySQLEULA.txt", "$destdir"); - + # remove subdirectories 'bdb', 'cmd-line-utils/readline' - # (latter does not apply to 4.0, but is in different place there!) my @extra_fat= ('bdb', 'cmd-line-utils/readline'); foreach my $fat (@extra_fat) @@ -116,7 +115,7 @@ sub main # fix file copyrights &fix_usage_copyright(); &add_copyright(); - + # fix LICENSE tag in include/mysql_version.h &fix_mysql_version(); @@ -135,7 +134,6 @@ sub main # remove temporary directory chdir($WD) or print "$! Unable to move up one dir\n"; - `cd $WD`; my $cwd = getcwd(); print "current dir is $cwd\n" if $opt_verbose ; if (-e $dir) { @@ -146,7 +144,7 @@ sub main } } exit(0); -} +} #### #### This function will s/GPL/Commercial/ in include/mysql_version.h for the @@ -175,6 +173,7 @@ sub fix_mysql_version #### This function will remove unwanted parts of a src tree for the mysqlcom #### distributions. #### + sub trim_the_fat { my $the_fat= shift; @@ -219,6 +218,7 @@ sub trim_the_fat #### #### This function will run the autotools on the reduced source tree. #### + sub run_autotools { my $cwd= getcwd(); @@ -230,7 +230,14 @@ sub run_autotools # File "configure.in" has already been modified by "trim_the_fat()" - `aclocal && autoheader && aclocal && automake && autoconf`; + # It must be ensured that the timestamps of the relevant files are really + # ascending, for otherwise the Makefile may cause a re-run of these + # autotools. Experience shows that deletion is the only safe way. + unlink ("config.h.in") or die "Can't delete $destdir/config.h.in: $!\n"; + unlink ("aclocal.m4") or die "Can't delete $destdir/aclocal.m4: $!\n"; + + # These sleep commands also ensure the ascending order. + `aclocal && sleep 2 && autoheader && sleep 2 && automake && sleep 2 && autoconf`; die "'./configure' was not produced!" unless (-f "configure"); if (-d "autom4te.cache") { From d5691702d78c703f92c13396cc901baffbffdd19 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 27 Oct 2004 18:57:49 +0300 Subject: [PATCH 105/143] Fix when compiling without InnoDB --- mysql-test/r/innodb-lock.result | 1 + mysql-test/t/innodb-lock-master.opt | 1 - mysql-test/t/innodb-lock.test | 5 +++++ 3 files changed, 6 insertions(+), 1 deletion(-) delete mode 100644 mysql-test/t/innodb-lock-master.opt diff --git a/mysql-test/r/innodb-lock.result b/mysql-test/r/innodb-lock.result index 407a85ed038..4ace4065c34 100644 --- a/mysql-test/r/innodb-lock.result +++ b/mysql-test/r/innodb-lock.result @@ -1,3 +1,4 @@ +set global innodb_table_locks=1; select @@innodb_table_locks; @@innodb_table_locks 1 diff --git a/mysql-test/t/innodb-lock-master.opt b/mysql-test/t/innodb-lock-master.opt deleted file mode 100644 index 403fcde87ed..00000000000 --- a/mysql-test/t/innodb-lock-master.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb-table-lock=1 diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test index 430369f4fda..a3b6f8993f2 100644 --- a/mysql-test/t/innodb-lock.test +++ b/mysql-test/t/innodb-lock.test @@ -4,6 +4,8 @@ # Check and select innodb lock type # +set global innodb_table_locks=1; + select @@innodb_table_locks; # @@ -12,7 +14,10 @@ select @@innodb_table_locks; connect (con1,localhost,root,,); connect (con2,localhost,root,,); + +--disable_warnings drop table if exists t1; +--enable_warnings # # Testing of explicit table locks with enforced table locks From 8e53b2d602b9dc190bd82afddb4f6e8eb77dbad1 Mon Sep 17 00:00:00 2001 From: "paul@kite-hub.kitebird.com" <> Date: Wed, 27 Oct 2004 13:44:31 -0500 Subject: [PATCH 106/143] texi2html: Updated version of texi2html so that 4.0.22 HTML manual doesn't turn out all goofy. --- Docs/Support/texi2html | 98 +++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html index 8067d8f72ce..f13c006c7dc 100755 --- a/Docs/Support/texi2html +++ b/Docs/Support/texi2html @@ -1,4 +1,4 @@ -#!PATH_TO_PERL -*- perl -*- +#!/usr/bin/perl # Add path to perl on the previous line and make this executable # if you want to use this as a normal script. 'di '; @@ -12,7 +12,7 @@ #-############################################################################## # @(#)texi2html 1.52 971230 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch -# Enhanced by David Axmark, david@detron.se +# Enhanced by David Axmark # The man page for this program is included at the end of this file and can be # viewed using the command 'nroff -man texi2html'. @@ -40,8 +40,7 @@ $NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names $XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE) $ERROR = "***"; # prefix for errors and warnings -$THISPROG = "texi2html 1.52 (hacked by david\@detron.se)"; # program name and version -$HOMEPAGE = "http://www.mathematik.uni-kl.de/~obachman/Texi2html/"; # program home page +$THISPROG = "texi2html 1.52 (with additions by MySQL AB)"; # program name and version $TODAY = &pretty_date; # like "20 September 1993" $SPLITTAG = "\n"; # tag to know where to split $PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections @@ -114,10 +113,12 @@ $html2_doctype = '", # HTML+ + "*", "
", # HTML+ " ", " ", "\n", "\n", "|", "", @@ -134,6 +135,8 @@ $html2_doctype = '', # paragraph break + 'br', '

', # paragraph break 'bullet', '*', 'copyright', '(C)', + 'registeredsymbol', '(R)', 'dots', '...', 'equiv', '==', 'error', 'error-->', @@ -161,27 +165,28 @@ $html2_doctype = '\n", __LINE__)); + push(@lines, &debug("\n", __LINE__)); } else { warn "$ERROR Bad table line: $_"; } @@ -873,7 +887,7 @@ READ_LINE: while ($_ = &next_line) &simple_substitutions; s/\@value{($VARRE)}/$value{$1}/eg; s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4 - s|\s+\@tab\s*| \n", __LINE__)) unless $html_element eq 'TABLE'; &html_pop_if('TR'); - $what =~ s|\s+\@tab\s*|
|g if ($in_multitable); + s/(^|\s+)\@tab\s*/ <\/TD> /g if ($in_multitable); # # analyze the tag again @@ -885,7 +899,7 @@ READ_LINE: while ($_ = &next_line) $name =~ s/\s+$//; $level = $sec2level{$tag}; $name = &update_sec_num($tag, $level) . " $name" - if $number_sections && $tag !~ /^unnumbered/; + if $number_sections && $tag !~ /^unnumbered/ && $tag ne 'subsubheading'; if ($tag =~ /heading$/) { push(@lines, &html_debug("\n", __LINE__)); if ($html_element ne 'body') { @@ -1079,7 +1093,7 @@ EOC push(@lines, &debug("
|g; + $what =~ s/(^|\s+)\@tab\s*/ <\/TD> /g; push(@lines, &debug("
$what\n", __LINE__)); &html_push('TR'); if ($deferred_ref) @@ -1463,11 +1477,7 @@ print "# end of pass 4\n" if $verbose; # # #---############################################################################ -$header = < -EOT - + $header = ''; $full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document"; $title = $value{'_settitle'} || $full_title; $_ = &substitute_style($full_title); @@ -1815,8 +1825,10 @@ sub fix_image die "error in image: '$text'" unless defined($1); $arg1 = $1; $arg1 =~ s/@@/@/g; - $ext = "jpg" if -f "$arg1.jpg"; - $ext = "gif" if -f "$arg1.gif"; + foreach (@include_dirs) { + $ext = "jpg" if -f "$_/$arg1.jpg"; + $ext = "gif" if -f "$_/$arg1.gif"; + } if (defined($ext)) { ""; @@ -2010,7 +2022,7 @@ sub print_toplevel_header { local($_); - &print_header; # pass given arg... + &print_header unless $opt_empty_headers; # pass given arg... print FILE $full_title; if ($value{'_subtitle'}) { $value{'_subtitle'} =~ s/\n+$//; @@ -2042,13 +2054,7 @@ EOT sub print_toplevel_footer { - &print_ruler; - print FILE <texi2html -translator version 1.52 (extended by davida\@detron.se).

-EOT - &print_footer; + &print_footer unless $opt_empty_headers; } sub protect_texi @@ -2065,8 +2071,10 @@ sub protect_html { local($what) = @_; # protect & < > - # Avoid loop in & replacement. This instead bugs out for &# in text.. - $what =~ s/\&([^#]|$)/\&\#38;$1/g; + # hack for the two entity-like variable reference in existing examples + $what =~ s/\&(length|ts);/\&\#38;$1;/g; + # this leaves alone entities, but encodes standalone ampersands + $what =~ s/\&(?!([a-z0-9]+|#\d+);)/\&\#38;/ig; $what =~ s/\/\&\#62;/g; # but recognize some HTML things From 6b720d93be6c63b4f340ef1add6db4cb96f90fe2 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 27 Oct 2004 21:51:27 +0200 Subject: [PATCH 107/143] - Applied some Windows portability fixes for myisampack.c and sql_handler.cc (backports from fixes made in 4.1) --- myisam/myisampack.c | 2 +- sql/sql_handler.cc | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 0dde1916f03..9f4e3bde65a 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -2047,7 +2047,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->state.dellink= HA_OFFSET_ERROR; share->state.split=(ha_rows) mrg->records; share->state.version=(ulong) time((time_t*) 0); - if (share->state.key_map != (1ULL << share->base.keys) - 1) + if (share->state.key_map != (((ulonglong)1) << share->base.keys) - 1) { /* Some indexes are disabled, cannot use current key_file_length value diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 44ffb713dcc..5bfcc897fc7 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -265,8 +265,6 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables) { TABLE_LIST *hash_tables; TABLE **table_ptr; - bool was_flushed= FALSE; - bool not_opened; DBUG_ENTER("mysql_ha_close"); DBUG_PRINT("enter",("'%s'.'%s' as '%s'", tables->db, tables->real_name, tables->alias)); @@ -363,7 +361,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, int err; int keyno=-1; uint num_rows; - bool was_flushed; MYSQL_LOCK *lock; DBUG_ENTER("mysql_ha_read"); DBUG_PRINT("enter",("'%s'.'%s' as '%s'", @@ -615,10 +612,8 @@ err0: int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags) { - TABLE_LIST **tmp_tables_p; TABLE_LIST *tmp_tables; TABLE **table_ptr; - bool was_flushed; DBUG_ENTER("mysql_ha_flush"); DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags)); @@ -692,14 +687,13 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) { TABLE_LIST *hash_tables; TABLE *table= *table_ptr; - bool was_flushed; DBUG_ENTER("mysql_ha_flush_table"); DBUG_PRINT("enter",("'%s'.'%s' as '%s' flags: 0x%02x", table->table_cache_key, table->real_name, table->table_name, mode_flags)); if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (*table_ptr)->table_name, + (byte*) (*table_ptr)->table_name, strlen((*table_ptr)->table_name) + 1))) { if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE)) From 8894a6bb73be7cfdc649a97e08c0ad4888cc14f3 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Thu, 28 Oct 2004 21:14:00 +0300 Subject: [PATCH 108/143] close table before next iteration of table proccesing in mysql_admin_table (to allow open next table) --- sql/sql_table.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8190e31bc0b..65690e56039 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1268,9 +1268,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, if (prepare_func) { switch ((*prepare_func)(thd, table, check_opt)) { - case 1: continue; // error, message written to net - case -1: goto err; // error, message could be written to net - default: ; // should be 0 otherwise + case 1: // error, message written to net + close_thread_tables(thd); + continue; + case -1: // error, message could be written to net + goto err; + default: // should be 0 otherwise + ; } } From 35e8670301f854b5b1541cd39deaab2f0c046bbd Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 29 Oct 2004 09:24:21 +0200 Subject: [PATCH 109/143] - bumped up version number from 4.0.22 to 4.0.23 in configure.in - tagged ChangeSet@1.2048.1.2 as "mysql-4.0.22" --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index d4073ea441b..d4ede468435 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.22) +AM_INIT_AUTOMAKE(mysql, 4.0.23) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From d22a24d871bc3bfaec17621d23352f2da9473569 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 31 Oct 2004 15:43:29 +0200 Subject: [PATCH 110/143] row0mysql.c, pars0pars.c, eval0eval.c, dict0load.c, dict0dict.c, dict0crea.c: Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it dict0dict.c: Fix bug #3478: InnoDB's FOREIGN KEY tables treated table and database names as case-insensitive; RENAME TABLE t to T would hang in an endless loop if t had a foreign key constraint defined on it; fix also a hang that would occur if one tried in ALTER TABLE or RENAME TABLE to create a foreign key constraint name that collided with another existing name --- innobase/dict/dict0crea.c | 16 +++++++++++++++- innobase/dict/dict0dict.c | 4 ++-- innobase/dict/dict0load.c | 21 ++++++++++++++++++--- innobase/eval/eval0eval.c | 18 +++++++++++++++++- innobase/pars/pars0pars.c | 8 ++++++-- innobase/row/row0mysql.c | 15 +++++++++++---- 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index 31a601e68b0..e8261ab1e91 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -1011,6 +1011,12 @@ dict_create_or_check_foreign_constraint_tables(void) there are 2 secondary indexes on SYS_FOREIGN, and they are defined just like below */ + /* NOTE: when designing InnoDB's foreign key support in 2001, we made + an error and made the table names and the foreign key id of type + 'CHAR' (internally, really a VARCHAR). We should have made the type + VARBINARY, like in other InnoDB system tables, to get a clean + design. */ + str = (char *) "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n" "BEGIN\n" @@ -1227,9 +1233,17 @@ loop: fputs(".\nA foreign key constraint of name ", ef); ut_print_name(ef, foreign->id); fputs("\nalready exists." - " (Note that internally InnoDB adds 'databasename/'\n" + " (Note that internally InnoDB adds 'databasename/'\n" "in front of the user-defined constraint name).\n", ef); + fputs("Note that InnoDB's FOREIGN KEY system tables store\n" + "constraint names as case-insensitive, with the\n" + "MySQL standard latin1_swedish_ci collation. If you\n" + "create tables or databases whose names differ only in\n" + "the character case, then collisions in constraint\n" + "names can occur. Workaround: name your constraints\n" + "explicitly with unique names.\n", + ef); mutex_exit(&dict_foreign_err_mutex); diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 4340934ab3d..5ca31ecd422 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -132,7 +132,7 @@ dict_index_build_internal_non_clust( dict_index_t* index); /* in: user representation of a non-clustered index */ /************************************************************************** -Removes a foreign constraint struct from the dictionet cache. */ +Removes a foreign constraint struct from the dictionary cache. */ static void dict_foreign_remove_from_cache( @@ -581,7 +581,7 @@ dict_table_get_on_id( dict_table_t* table; if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0 - || trx->dict_operation) { + || trx->dict_operation_lock_mode == RW_X_LATCH) { /* It is a system table which will always exist in the table cache: we avoid acquiring the dictionary mutex, because if we are doing a rollback to handle an error in TABLE diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 6a4d4c86824..a4637e09d07 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -19,6 +19,7 @@ Created 4/24/1996 Heikki Tuuri #include "mach0data.h" #include "dict0dict.h" #include "dict0boot.h" +#include "rem0cmp.h" /************************************************************************ Finds the first table name in the given database. */ @@ -1121,12 +1122,26 @@ loop: rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field(rec, 0, &len); - /* Check if the table name in record is the one searched for */ - if (len != ut_strlen(table_name) - || 0 != ut_memcmp(field, table_name, len)) { + /* Check if the table name in the record is the one searched for; the + following call does the comparison in the latin1_swedish_ci + charset-collation, in a case-insensitive way. */ + if (0 != cmp_data_data(dfield_get_type(dfield), + dfield_get_data(dfield), dfield_get_len(dfield), + field, len)) { + goto load_next_index; } + + /* Since table names in SYS_FOREIGN are stored in a case-insensitive + order, we have to check that the table name matches also in a binary + string comparison. On Unix, MySQL allows table names that only differ + in character case. */ + + if (0 != ut_memcmp(field, table_name, len)) { + + goto next_rec; + } if (rec_get_deleted_flag(rec)) { diff --git a/innobase/eval/eval0eval.c b/innobase/eval/eval0eval.c index ebb6cb1b7d9..5b2d1f857b1 100644 --- a/innobase/eval/eval0eval.c +++ b/innobase/eval/eval0eval.c @@ -627,7 +627,11 @@ eval_concat( } /********************************************************************* -Evaluates a predefined function node. */ +Evaluates a predefined function node. If the first argument is an integer, +this function looks at the second argument which is the integer length in +bytes, and converts the integer to a VARCHAR. +If the first argument is of some other type, this function converts it to +BINARY. */ UNIV_INLINE void eval_to_binary( @@ -638,12 +642,24 @@ eval_to_binary( que_node_t* arg2; dfield_t* dfield; byte* str1; + ulint len; ulint len1; arg1 = func_node->args; str1 = dfield_get_data(que_node_get_val(arg1)); + if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) { + + len = dfield_get_len(que_node_get_val(arg1)); + + dfield = que_node_get_val(func_node); + + dfield_set_data(dfield, str1, len); + + return; + } + arg2 = que_node_get_next(arg1); len1 = (ulint)eval_node_get_int_val(arg2); diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c index a4124672df0..5be0e52d0c8 100644 --- a/innobase/pars/pars0pars.c +++ b/innobase/pars/pars0pars.c @@ -259,9 +259,13 @@ pars_resolve_func_data_type( dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); } else if (func == PARS_TO_BINARY_TOKEN) { - ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT); - dtype_set(que_node_get_data_type(node), DATA_VARCHAR, + if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) { + dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); + } else { + dtype_set(que_node_get_data_type(node), DATA_BINARY, + 0, 0, 0); + } } else if (func == PARS_TO_NUMBER_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_VARCHAR); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 78b2aa8e28f..2e8f7121d2c 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1981,7 +1981,8 @@ row_drop_table_for_mysql( "WHILE found = 1 LOOP\n" " SELECT ID INTO foreign_id\n" " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = table_name;\n" + " WHERE FOR_NAME = table_name\n" + " AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE" @@ -2381,7 +2382,8 @@ row_rename_table_for_mysql( "WHILE found = 1 LOOP\n" " SELECT ID INTO foreign_id\n" " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = old_table_name;\n" + " WHERE FOR_NAME = old_table_name\n" + " AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE\n" @@ -2414,7 +2416,8 @@ row_rename_table_for_mysql( " END IF;\n" "END LOOP;\n" "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n" - "WHERE REF_NAME = old_table_name;\n"; + "WHERE REF_NAME = old_table_name\n" + " AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n"; static const char str5[] = "END;\n"; @@ -2602,7 +2605,11 @@ row_rename_table_for_mysql( if (err == DB_DUPLICATE_KEY) { ut_print_timestamp(stderr); - fputs(" InnoDB: Error: table ", stderr); + fputs( + " InnoDB: Error; possible reasons:\n" + "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n" + "InnoDB: to have the same internal name in case-insensitive comparison.\n" + "InnoDB: 2) table ", stderr); ut_print_name(stderr, new_name); fputs(" exists in the InnoDB internal data\n" "InnoDB: dictionary though MySQL is trying rename table ", stderr); From a3294186ec089d4b6abf318894e36cbf042f72c6 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Mon, 1 Nov 2004 12:08:44 +0200 Subject: [PATCH 111/143] mysqld.cc: Describe innodb_max_purge_lag Improve description of innodb_table_locks --- sql/mysqld.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d36b441ac9a..768acd77c27 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3702,12 +3702,12 @@ struct my_option my_long_options[] = "Percentage of dirty pages allowed in bufferpool", (gptr*) &srv_max_buf_pool_modified_pct, (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, {"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG, - "", + "Desired maximum length of the purge queue (0 = no limit)", (gptr*) &srv_max_purge_lag, (gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1L, 0}, {"innodb_table_locks", OPT_INNODB_TABLE_LOCKS, - "If Innodb should enforce LOCK TABLE", + "Enable InnoDB locking in LOCK TABLES", (gptr*) &global_system_variables.innodb_table_locks, (gptr*) &global_system_variables.innodb_table_locks, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, From 10291f36647dfdf072db440c14a4faa5d072a371 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Mon, 1 Nov 2004 18:15:45 +0100 Subject: [PATCH 112/143] Ensure that a source distribution contains 'libmysql/libmysql.def' which is needed for Netware ports. --- libmysql/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index fefed7f079c..3c4e98e5053 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -31,7 +31,7 @@ include $(srcdir)/Makefile.shared libmysqlclient_la_SOURCES = $(target_sources) libmysqlclient_la_LIBADD = $(target_libadd) libmysqlclient_la_LDFLAGS = $(target_ldflags) -EXTRA_DIST = Makefile.shared +EXTRA_DIST = Makefile.shared libmysql.def # This is called from the toplevel makefile link_sources: From 22269d451af650f887a7679ba6fffe7577d1c007 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Tue, 2 Nov 2004 13:21:11 +0200 Subject: [PATCH 113/143] ha_innodb.cc: Backport Jan's fix of the LOAD DATA INFILE REPLACE duplicate key error bug (Bug #5835) to 4.0 --- sql/ha_innodb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e747ff3210c..d57a9f73c91 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2285,7 +2285,9 @@ ha_innobase::write_row( if (error == DB_DUPLICATE_KEY && (user_thd->lex.sql_command == SQLCOM_REPLACE || user_thd->lex.sql_command - == SQLCOM_REPLACE_SELECT)) { + == SQLCOM_REPLACE_SELECT + || (user_thd->lex.sql_command == SQLCOM_LOAD + && user_thd->lex.duplicates == DUP_REPLACE))) { skip_auto_inc_decr= TRUE; } From b0510c7fd46f462f9456d16cb8cba58d1dbe12c1 Mon Sep 17 00:00:00 2001 From: "tim@siva.hindu.god" <> Date: Tue, 2 Nov 2004 17:53:25 -0700 Subject: [PATCH 114/143] Portability fixes to mysqld_safe for non-Linux systems. Fix FIND_PROC for Solaris test, and fix if @IS_LINUX@ test in mysqld_safe itself. --- BitKeeper/etc/logging_ok | 1 + configure.in | 2 +- scripts/mysqld_safe.sh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 060586b6874..a716afb2392 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -139,6 +139,7 @@ tim@bitch.mysql.fi tim@black.box tim@hundin.mysql.fi tim@sand.box +tim@siva.hindu.god tim@threads.polyesthetic.msg tim@white.box tim@work.mysql.com diff --git a/configure.in b/configure.in index d4ede468435..97a59258ba8 100644 --- a/configure.in +++ b/configure.in @@ -444,7 +444,7 @@ if $PS p $$ 2> /dev/null | grep $0 > /dev/null then FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null" # Solaris -elif $PS -p $$ 2> /dev/null | grep $0 > /dev/null +elif $PS -fp $$ 2> /dev/null | grep $0 > /dev/null then FIND_PROC="$PS -p \$\$PID | grep mysqld > /dev/null" # BSD style diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index b9e7ce21f79..da7e06f6c05 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -315,7 +315,7 @@ do break fi - if test @IS_LINUX@ -a $KILL_MYSQLD -eq 1 + if @IS_LINUX@ && test $KILL_MYSQLD -eq 1 then # Test if one process was hanging. # This is only a fix for Linux (running as base 3 mysqld processes) From b58cb6b50f5f311afc07ea035993e49c342a9422 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 3 Nov 2004 14:56:48 +0200 Subject: [PATCH 115/143] InnoDB: fix bugs in the FOREIGN KEY parser (Bug #6340) --- innobase/dict/dict0dict.c | 55 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 5ca31ecd422..aa5bab210ef 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -604,7 +604,7 @@ dict_table_get_on_id( } /************************************************************************ -Looks for column n postion in the clustered index. */ +Looks for column n position in the clustered index. */ ulint dict_table_get_nth_col_pos( @@ -2140,8 +2140,8 @@ dict_foreign_add_to_cache( /************************************************************************* Scans from pointer onwards. Stops if is at the start of a copy of -'string' where characters are compared without case sensitivity. Stops -also at '\0'. */ +'string' where characters are compared without case sensitivity, and +only outside `` or "" quotes. Stops also at '\0'. */ static const char* dict_scan_to( @@ -2150,31 +2150,34 @@ dict_scan_to( const char* ptr, /* in: scan from */ const char* string) /* in: look for this */ { - ibool success; - ulint i; -loop: - if (*ptr == '\0') { - return(ptr); - } - - success = TRUE; - - for (i = 0; i < ut_strlen(string); i++) { - if (toupper((ulint)(ptr[i])) != toupper((ulint)(string[i]))) { - success = FALSE; + char quote = '\0'; + for (; *ptr; ptr++) { + if (*ptr == quote) { + /* Closing quote character: do not look for + starting quote or the keyword. */ + quote = '\0'; + } else if (quote) { + /* Within quotes: do nothing. */ + } else if (*ptr == '`' || *ptr == '"') { + /* Starting quote: remember the quote character. */ + quote = *ptr; + } else { + /* Outside quotes: look for the keyword. */ + ulint i; + for (i = 0; string[i]; i++) { + if (toupper((ulint)(ptr[i])) + != toupper((ulint)(string[i]))) { + goto nomatch; + } + } break; + nomatch: + ; } } - if (success) { - - return(ptr); - } - - ptr++; - - goto loop; + return(ptr); } /************************************************************************* @@ -2762,13 +2765,13 @@ loop: ut_a(success); - if (!isspace(*ptr)) { + if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') { goto loop; } - do { + while (isspace(*ptr)) { ptr++; - } while (isspace(*ptr)); + } /* read constraint name unless got "CONSTRAINT FOREIGN" */ if (ptr != ptr2) { From fa21feda932a9ccc68142dd04b18fe37daf15655 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Wed, 3 Nov 2004 17:59:03 +0000 Subject: [PATCH 116/143] Fix for bug #6387 "Queried timestamp values do not match the inserted value if server runs in time zone with leap seconds". Now in my_gmt_sec() function we take into account difference between our target and estimation in seconds part. --- mysql-test/Makefile.am | 2 + .../r/have_moscow_leap_timezone.require | 2 + mysql-test/r/timezone3.result | 41 ++++++++++++ mysql-test/std_data/Moscow_leap | Bin 0 -> 991 bytes mysql-test/t/timezone3-master.opt | 1 + mysql-test/t/timezone3.test | 59 ++++++++++++++++++ sql/time.cc | 23 +++++-- 7 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 mysql-test/r/have_moscow_leap_timezone.require create mode 100644 mysql-test/r/timezone3.result create mode 100644 mysql-test/std_data/Moscow_leap create mode 100644 mysql-test/t/timezone3-master.opt create mode 100644 mysql-test/t/timezone3.test diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index ba96c5947ba..8b0c096120a 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -32,6 +32,7 @@ dist-hook: $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.001 $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data install-data-local: $(mkinstalldirs) \ @@ -50,6 +51,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data SUFFIXES = .sh diff --git a/mysql-test/r/have_moscow_leap_timezone.require b/mysql-test/r/have_moscow_leap_timezone.require new file mode 100644 index 00000000000..f27452d7770 --- /dev/null +++ b/mysql-test/r/have_moscow_leap_timezone.require @@ -0,0 +1,2 @@ +from_unixtime(1072904422) +2004-01-01 00:00:00 diff --git a/mysql-test/r/timezone3.result b/mysql-test/r/timezone3.result new file mode 100644 index 00000000000..2135dd33511 --- /dev/null +++ b/mysql-test/r/timezone3.result @@ -0,0 +1,41 @@ +drop table if exists t1; +create table t1 (i int, c varchar(20)); +insert into t1 values +(unix_timestamp("2004-01-01 00:00:00"), "2004-01-01 00:00:00"); +insert into t1 values +(unix_timestamp("2004-03-28 01:59:59"), "2004-03-28 01:59:59"), +(unix_timestamp("2004-03-28 02:30:00"), "2004-03-28 02:30:00"), +(unix_timestamp("2004-03-28 03:00:00"), "2004-03-28 03:00:00"); +insert into t1 values +(unix_timestamp('2004-05-01 00:00:00'),'2004-05-01 00:00:00'); +insert into t1 values +(unix_timestamp('2004-10-31 01:00:00'),'2004-10-31 01:00:00'), +(unix_timestamp('2004-10-31 02:00:00'),'2004-10-31 02:00:00'), +(unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59'), +(unix_timestamp('2004-10-31 04:00:00'),'2004-10-31 04:00:00'), +(unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59'); +insert into t1 values +(unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'), +(unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00'); +select i, from_unixtime(i), c from t1; +i from_unixtime(i) c +1072904422 2004-01-01 00:00:00 2004-01-01 00:00:00 +1080428421 2004-03-28 01:59:59 2004-03-28 01:59:59 +1080428422 2004-03-28 03:00:00 2004-03-28 02:30:00 +1080428422 2004-03-28 03:00:00 2004-03-28 03:00:00 +1083355222 2004-05-01 00:00:00 2004-05-01 00:00:00 +1099170022 2004-10-31 01:00:00 2004-10-31 01:00:00 +1099177222 2004-10-31 02:00:00 2004-10-31 02:00:00 +1099180821 2004-10-31 02:59:59 2004-10-31 02:59:59 +1099184422 2004-10-31 04:00:00 2004-10-31 04:00:00 +1099180821 2004-10-31 02:59:59 2004-10-31 02:59:59 +362793608 1981-07-01 03:59:59 1981-07-01 03:59:59 +362793610 1981-07-01 04:00:00 1981-07-01 04:00:00 +drop table t1; +create table t1 (ts timestamp); +insert into t1 values (19730101235900), (20040101235900); +select * from t1; +ts +19730101235900 +20040101235900 +drop table t1; diff --git a/mysql-test/std_data/Moscow_leap b/mysql-test/std_data/Moscow_leap new file mode 100644 index 0000000000000000000000000000000000000000..4994c005595dc06bc6d288e9ecea38307ce11c82 GIT binary patch literal 991 zcmWHE%1mRx1Ux_?5EcXCMkrfucD&q;xptps%+q==G4H!&$NZKEi3K-uITkXAX)Lr^ z=CDK{_rMZcqYX<%Gd3)>Wj?T6&NX1`63GNn_2oCkB<^^LbKH&+|HXe=;uYU*$=l98 zQfDULk>0c5kIb5he`M!0{gvw}{wrUT@>d}z^si!!+g~Lg^MA@V8vj&uB>$<(aQ#!` z{{3H_RlQ#Qt3-pwQ}GF!75gV>UbzsUb!4-n_Le)1I!n$r=}y_#q}Q^(S-)gKvq8$l zX2aOMEJj5$Sd4AwvzP=`v6{*@vYHviu$ui%X0wp4XtTKM%4YdHs?BPzI-B)vn>L$e z&TY24<=X7pRNL%lGqgFRv9~$4$g(-PzHD<&{?F#3db-Wk`5~Jd>)JMV<-=_5?@qCK zGB0KGJhz6;>v21q_qskdpEHZweESO6{MNL#`R4_(1@xr11%~If1?70Q1)B%7h4^T< zg^C-sh3W9Ng?$%kixAafi@5f!E%GZ5Thz82ZP8cWvBk{)$`-rj0$W`Db+-5^o7fWK zcd{kco@-08pUsvWyP+*bzLqW3c2Zj!$IP~L*^;*O7u9VUf5X}`PsFxm-L+`TUSZ#s zb1alCw?nZlZ<#q;eg<<}L7OC7VW0wAQR;8DVnZgj64$$Ir260> zt>VH8w#s*V+p0Enu~na&-&QkoSzGP8#&46d#rKnxUM*#tJ2k#)%%MxX^u>}~Q*K$@8| zJ(w9tvv7N~wE$^WUTyAHAkD_lW6uVp*#+JfwF7Amp>xZCE@I#moqwtmNOOrd{Nn=B z+>%L#-9Va0R`nGqd+{pXdJ1$i1E1==xqU#IU%mb!KadvC3ivt!NDJy1X#)MhAfzW8 nGYLow8$4GL2GSzNJ3OWUX;HHt0iX}T*%U}IFfalEm;ogKHtY+x literal 0 HcmV?d00001 diff --git a/mysql-test/t/timezone3-master.opt b/mysql-test/t/timezone3-master.opt new file mode 100644 index 00000000000..6910e6e6e8d --- /dev/null +++ b/mysql-test/t/timezone3-master.opt @@ -0,0 +1 @@ +--timezone=:$MYSQL_TEST_DIR/std_data/Moscow_leap diff --git a/mysql-test/t/timezone3.test b/mysql-test/t/timezone3.test new file mode 100644 index 00000000000..8910783cd85 --- /dev/null +++ b/mysql-test/t/timezone3.test @@ -0,0 +1,59 @@ +# +# Test of handling time zone with leap seconds. +# +# This test should be run with TZ=:$MYSQL_TEST_DIR/std_data/Moscow_leap +# This implies that this test should be run only on systems that interpret +# characters after colon in TZ variable as path to zoneinfo file. +# +# Check that we have successfully set time zone with leap seconds. +--require r/have_moscow_leap_timezone.require +disable_query_log; +select from_unixtime(1072904422); +enable_query_log; + +# Initial clean-up +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# Let us check behavior of conversion from broken-down representation +# to time_t representation, for normal, non-existent and ambigious dates +# (This check is similar to the one in timezone2.test in 4.1) +# +create table t1 (i int, c varchar(20)); +# Normal value without DST +insert into t1 values + (unix_timestamp("2004-01-01 00:00:00"), "2004-01-01 00:00:00"); +# Values around and in spring time-gap +insert into t1 values + (unix_timestamp("2004-03-28 01:59:59"), "2004-03-28 01:59:59"), + (unix_timestamp("2004-03-28 02:30:00"), "2004-03-28 02:30:00"), + (unix_timestamp("2004-03-28 03:00:00"), "2004-03-28 03:00:00"); +# Normal value with DST +insert into t1 values + (unix_timestamp('2004-05-01 00:00:00'),'2004-05-01 00:00:00'); +# Ambiguos values (also check for determenism) +insert into t1 values + (unix_timestamp('2004-10-31 01:00:00'),'2004-10-31 01:00:00'), + (unix_timestamp('2004-10-31 02:00:00'),'2004-10-31 02:00:00'), + (unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59'), + (unix_timestamp('2004-10-31 04:00:00'),'2004-10-31 04:00:00'), + (unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59'); +# Test of leap +insert into t1 values + (unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'), + (unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00'); + +select i, from_unixtime(i), c from t1; +drop table t1; + +# +# Test for bug #6387 "Queried timestamp values do not match the +# inserted". my_gmt_sec() function was not working properly if we +# had time zone with leap seconds +# +create table t1 (ts timestamp); +insert into t1 values (19730101235900), (20040101235900); +select * from t1; +drop table t1; diff --git a/sql/time.cc b/sql/time.cc index 0363d764100..38670db054f 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -81,6 +81,10 @@ long my_gmt_sec(TIME *t, long *my_timezone) I couldn't come up with a better way to get a repeatable result :( We can't use mktime() as it's buggy on many platforms and not thread safe. + + Note: this code assumes that our time_t estimation is not too far away + from real value (we assume that localtime_r(tmp) will return something + within 24 hrs from t) which is probably true for all current time zones. */ tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - (long) days_at_timestart)*86400L + (long) t->hour*3600L + @@ -93,7 +97,8 @@ long my_gmt_sec(TIME *t, long *my_timezone) for (loop=0; loop < 2 && (t->hour != (uint) l_time->tm_hour || - t->minute != (uint) l_time->tm_min); + t->minute != (uint) l_time->tm_min || + t->second != (uint) l_time->tm_sec); loop++) { /* One check should be enough ? */ /* Get difference in days */ @@ -103,15 +108,22 @@ long my_gmt_sec(TIME *t, long *my_timezone) else if (days > 1) days= -1; diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) + - (long) (60*((int) t->minute - (int) l_time->tm_min))); + (long) (60*((int) t->minute - (int) l_time->tm_min)) + + (long) ((int) t->second - (int) l_time->tm_sec)); current_timezone+= diff+3600; // Compensate for -3600 above tmp+= (time_t) diff; localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; } /* - Fix that if we are in the not existing daylight saving time hour - we move the start of the next real hour + Fix that if we are in the non existing daylight saving time hour + we move the start of the next real hour. + + This code doesn't handle such exotical thing as time-gaps whose length + is more than one hour or non-integer (latter can theoretically happen + if one of seconds will be removed due leap correction, or because of + general time correction like it happened for Africa/Monrovia time zone + in year 1972). */ if (loop == 2 && t->hour != (uint) l_time->tm_hour) { @@ -121,7 +133,8 @@ long my_gmt_sec(TIME *t, long *my_timezone) else if (days > 1) days= -1; diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour))+ - (long) (60*((int) t->minute - (int) l_time->tm_min))); + (long) (60*((int) t->minute - (int) l_time->tm_min)) + + (long) ((int) t->second - (int) l_time->tm_sec)); if (diff == 3600) tmp+=3600 - t->minute*60 - t->second; // Move to next hour else if (diff == -3600) From cb0bd6f57d87ad2bc3691a9dce013ce7e9419cd7 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 4 Nov 2004 11:18:12 +0100 Subject: [PATCH 117/143] The files stored in "Docs/Images" within the "mysqldocs" BK tree must be included in the source tar-ball for distribution. This is done by using the "DISTFILES" macro in a new "Docs/Images/Makefile". As the source BK tree does not contain these files, they are copied from the "mysqldocs" tree at release build time. This changeset relies on "bk commit - mysqldoc tree (joerg:1.2276)" of today. --- Build-tools/Bootstrap | 4 ++++ Docs/Images/Makefile.am | 35 +++++++++++++++++++++++++++++++++++ Docs/Makefile.am | 2 ++ configure.in | 2 +- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Docs/Images/Makefile.am diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap index 8cad093bc5f..e21179fe78c 100755 --- a/Build-tools/Bootstrap +++ b/Build-tools/Bootstrap @@ -288,6 +288,10 @@ unless ($opt_skip_manual) system ("bk cat $opt_docdir/Docs/$file.texi > $target_dir/Docs/$file.texi") == 0 or &abort("Could not update $file.texi in $target_dir/Docs/!"); } + system ("rm $target_dir/Docs/Images/Makefile*") == 0 + or &abort("Could not remove Makefiles in $target_dir/Docs/Images/!"); + system ("cp $opt_docdir/Docs/Images/*.* $target_dir/Docs/Images") == 0 + or &abort("Could not copy image files in $target_dir/Docs/Images/!"); } # diff --git a/Docs/Images/Makefile.am b/Docs/Images/Makefile.am new file mode 100644 index 00000000000..b57d701d8a0 --- /dev/null +++ b/Docs/Images/Makefile.am @@ -0,0 +1,35 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA + +## Process this file with automake to create Makefile.in + +# This is a dummy file to satisfy the hierarchy of Makefiles. +# When a release is built, the true Makefile will be copied +# together with the "real" files in this directory. + +EXTRA_DIST = + +# Nothing to create in this dummy directory. +all: + : + +# Nothing to cleanup in this dummy directory. +clean: + : + +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/Docs/Makefile.am b/Docs/Makefile.am index a4e8e14a38d..e53ea195d94 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -24,6 +24,8 @@ BUILT_SOURCES = $(targets) manual_toc.html include.texi EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \ INSTALL-BINARY reservedwords.texi +SUBDIRS = Images + all: $(targets) txt_files txt_files: ../INSTALL-SOURCE ../COPYING ../EXCEPTIONS-CLIENT \ diff --git a/configure.in b/configure.in index d4ede468435..0c520ca8980 100644 --- a/configure.in +++ b/configure.in @@ -2711,7 +2711,7 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile dnl pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl merge/Makefile dbug/Makefile scripts/Makefile dnl include/Makefile sql-bench/Makefile tools/Makefile dnl - tests/Makefile Docs/Makefile support-files/Makefile dnl + tests/Makefile Docs/Makefile Docs/Images/Makefile support-files/Makefile dnl support-files/MacOSX/Makefile mysql-test/Makefile dnl netware/Makefile dnl include/mysql_version.h dnl From 1869cd9f837e58adc709514d0133fd5c6323aa9b Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Thu, 4 Nov 2004 19:19:23 +0100 Subject: [PATCH 118/143] Fix for BUG##5714 "Insert into MyISAM table and select ... for update]": the fact that the transaction log is empty does not mean we're not in a transaction (it could be BEGIN; SELECT * FOR UPDATE FROM ibtable: then we don't want to commit now, even if the statement is a MyISAM update). With a testcase. --- mysql-test/r/mix_innodb_myisam_binlog.result | 21 ++++++++++++ .../t/mix_innodb_myisam_binlog-master.opt | 1 + mysql-test/t/mix_innodb_myisam_binlog.test | 32 +++++++++++++++++++ sql/log.cc | 3 +- 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 mysql-test/t/mix_innodb_myisam_binlog-master.opt diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result index 7b266544c92..93a647f673c 100644 --- a/mysql-test/r/mix_innodb_myisam_binlog.result +++ b/mysql-test/r/mix_innodb_myisam_binlog.result @@ -177,4 +177,25 @@ master-bin.001 79 Query 1 79 use `test`; BEGIN master-bin.001 119 Query 1 79 use `test`; insert into t1 values(16) master-bin.001 179 Query 1 79 use `test`; insert into t1 values(18) master-bin.001 239 Query 1 239 use `test`; COMMIT +delete from t1; +delete from t2; +alter table t2 type=MyISAM; +insert into t1 values (1); +begin; +select * from t1 for update; +a +1 +select (@before:=unix_timestamp())*0; +(@before:=unix_timestamp())*0 +0 +begin; + select * from t1 for update; +insert into t2 values (20); +Lock wait timeout exceeded; Try restarting transaction +select (@after:=unix_timestamp())*0; +(@after:=unix_timestamp())*0 +0 +select (@after-@before) >= 2; +(@after-@before) >= 2 +1 drop table t1,t2; diff --git a/mysql-test/t/mix_innodb_myisam_binlog-master.opt b/mysql-test/t/mix_innodb_myisam_binlog-master.opt new file mode 100644 index 00000000000..cb48f1aaf60 --- /dev/null +++ b/mysql-test/t/mix_innodb_myisam_binlog-master.opt @@ -0,0 +1 @@ +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test index be45c2c3133..5f3b778c61a 100644 --- a/mysql-test/t/mix_innodb_myisam_binlog.test +++ b/mysql-test/t/mix_innodb_myisam_binlog.test @@ -175,4 +175,36 @@ select a from t1 order by a; # check that savepoints work :) show binlog events from 79; +# Test for BUG#5714, where a MyISAM update in the transaction used to +# release row-level locks in InnoDB + +connect (con3,localhost,root,,); + +connection con3; +delete from t1; +delete from t2; +--disable_warnings +alter table t2 type=MyISAM; +--enable_warnings +insert into t1 values (1); +begin; +select * from t1 for update; + +connection con2; +select (@before:=unix_timestamp())*0; # always give repeatable output +begin; +send select * from t1 for update; + +connection con3; +insert into t2 values (20); + +connection con2; +--error 1205 +reap; +select (@after:=unix_timestamp())*0; # always give repeatable output +# verify that innodb_lock_wait_timeout was exceeded. When there was +# the bug, the reap would return immediately after the insert into t2. +select (@after-@before) >= 2; + +# cleanup drop table t1,t2; diff --git a/sql/log.cc b/sql/log.cc index fee77b38f21..aa5d9d8753b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1254,7 +1254,8 @@ bool MYSQL_LOG::write(Log_event* event_info) if (flush_io_cache(file)) goto err; - if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log)) + if (opt_using_transactions && + !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { /* LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog From e9c50b8773f81515a1d538bf30c86895ba1c9ed8 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Fri, 5 Nov 2004 09:00:04 +0400 Subject: [PATCH 119/143] libmysql.def, libmysql.c: Clean-ups --- libmysql/libmysql.c | 2 +- libmysql/libmysql.def | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 9257bf0efd0..2257ae739eb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3170,7 +3170,7 @@ void my_net_local_init(NET *net) encoded string, not including the terminating null character. */ -unsigned long +ulong STDCALL mysql_hex_string(char *to, const char *from, unsigned long length) { char *to0= to; diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index b0433a34cb3..51a4edda5aa 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -11,6 +11,7 @@ EXPORTS mysql_errno mysql_error mysql_escape_string + mysql_hex_string mysql_fetch_field mysql_fetch_field_direct mysql_fetch_fields From 0a375d4b72a9af2b93da5eaa65423b4b365dce49 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Fri, 5 Nov 2004 09:07:07 +0400 Subject: [PATCH 120/143] libmysql.c: After-merge clean-up --- libmysql/libmysql.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 2250111f5a0..47f28e296b2 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3173,7 +3173,8 @@ void my_net_local_init(NET *net) trailing '. The caller must supply whichever of those is desired. */ -ulong mysql_hex_string(char *to, const char *from, ulong length) +ulong STDCALL +mysql_hex_string(char *to, const char *from, ulong length) { char *to0= to; const char *end; From 630ea6e63c02c4ba2dbf8a811a7c35fdda370174 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Fri, 5 Nov 2004 09:23:53 +0400 Subject: [PATCH 121/143] client_priv.h: Backport --hex-blob to 4.0 --- client/client_priv.h | 3 ++- client/mysqldump.c | 56 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index 5029f219494..016c9e5ee80 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -38,4 +38,5 @@ enum options_client { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE, OPT_DELETE_MASTER_LOGS, - OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION, OPT_FRM }; + OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION, OPT_FRM, + OPT_HEXBLOB }; diff --git a/client/mysqldump.c b/client/mysqldump.c index 49822f0bee0..a78eee3794a 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -78,7 +78,8 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick=0, extended_insert = 0, opt_alldbs=0,opt_create_db=0,opt_first_slave=0, opt_autocommit=0,opt_master_data,opt_disable_keys=0,opt_xml=0, opt_delete_master_logs=0, tty_password=0, - opt_single_transaction=0, opt_comments= 0; + opt_single_transaction=0, opt_comments= 0, + opt_hex_blob; static ulong opt_max_allowed_packet, opt_net_buffer_length; static MYSQL mysql_connection,*sock=0; static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, @@ -248,6 +249,8 @@ static struct my_option my_long_options[] = {"comments", 'i', "Write additional information.", (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"hex-blob", OPT_HEXBLOB, "Dump BLOBs in HEX.", + (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1104,6 +1107,7 @@ static void dumpTable(uint numFields, char *table) for (i = 0; i < mysql_num_fields(res); i++) { + int is_blob; if (!(field = mysql_fetch_field(res))) { sprintf(query,"%s: Not enough fields from table %s! Aborting.\n", @@ -1112,6 +1116,13 @@ static void dumpTable(uint numFields, char *table) error= EX_CONSCHECK; goto err; } + + is_blob= (opt_hex_blob && (field->flags & BINARY_FLAG) && + (field->type == FIELD_TYPE_STRING || + field->type == FIELD_TYPE_BLOB || + field->type == FIELD_TYPE_LONG_BLOB || + field->type == FIELD_TYPE_MEDIUM_BLOB || + field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0; if (extended_insert) { ulong length = lengths[i]; @@ -1126,18 +1137,37 @@ static void dumpTable(uint numFields, char *table) { if (!IS_NUM_FIELD(field)) { + /* + "length * 2 + 2" is OK for both HEX and non-HEX modes: + - In HEX mode we need exactly 2 bytes per character + plus 2 bytes for '0x' prefix. + - In non-HEX mode we need up to 2 bytes per character, + plus 2 bytes for leading and trailing '\'' characters. + */ if (dynstr_realloc(&extended_row,length * 2+2)) { fputs("Aborting dump (out of memory)",stderr); error= EX_EOM; goto err; } - dynstr_append(&extended_row,"\'"); - extended_row.length += + if (opt_hex_blob && is_blob) + { + dynstr_append(&extended_row, "0x"); + extended_row.length+= mysql_hex_string(extended_row.str + + extended_row.length, + row[i], length); + extended_row.str[extended_row.length]= '\0'; + } + else + { + dynstr_append(&extended_row,"\'"); + extended_row.length += mysql_real_escape_string(&mysql_connection, - &extended_row.str[extended_row.length],row[i],length); - extended_row.str[extended_row.length]='\0'; - dynstr_append(&extended_row,"\'"); + &extended_row.str[extended_row.length], + row[i],length); + extended_row.str[extended_row.length]='\0'; + dynstr_append(&extended_row,"\'"); + } } else { @@ -1180,7 +1210,19 @@ static void dumpTable(uint numFields, char *table) if (opt_xml) print_quoted_xml(md_result_file, field->name, row[i], lengths[i]); - else + else if (opt_hex_blob && is_blob) + { /* sakaik got this idea. */ + ulong counter; + char xx[4]; + unsigned char *ptr= row[i]; + fputs("0x", md_result_file); + for (counter = 0; counter < lengths[i]; counter++) + { + sprintf(xx, "%02X", ptr[counter]); + fputs(xx, md_result_file); + } + } + else unescape(md_result_file, row[i], lengths[i]); } else From 5e2b6e3035e6943f0fa8de61d1b8bdcf198617a6 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Fri, 5 Nov 2004 15:22:03 +0100 Subject: [PATCH 122/143] Change "Bootstrap" so that it will not fail on BK source trees of other versions; this is important because this 4.0 "Bootstrap" is the one generally used on host "build". --- Build-tools/Bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap index e21179fe78c..a7d347ba32f 100755 --- a/Build-tools/Bootstrap +++ b/Build-tools/Bootstrap @@ -288,7 +288,7 @@ unless ($opt_skip_manual) system ("bk cat $opt_docdir/Docs/$file.texi > $target_dir/Docs/$file.texi") == 0 or &abort("Could not update $file.texi in $target_dir/Docs/!"); } - system ("rm $target_dir/Docs/Images/Makefile*") == 0 + system ("rm -f $target_dir/Docs/Images/Makefile*") == 0 or &abort("Could not remove Makefiles in $target_dir/Docs/Images/!"); system ("cp $opt_docdir/Docs/Images/*.* $target_dir/Docs/Images") == 0 or &abort("Could not copy image files in $target_dir/Docs/Images/!"); From b911810af7930beaaea78c1a407b08b1bd29c1ab Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Fri, 5 Nov 2004 20:33:56 +0400 Subject: [PATCH 123/143] mysqldump.c: Dump VARCHAR(n) BINARY in HEX if --hex-blob too. --- client/mysqldump.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mysqldump.c b/client/mysqldump.c index a78eee3794a..0e840512ba0 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1119,6 +1119,7 @@ static void dumpTable(uint numFields, char *table) is_blob= (opt_hex_blob && (field->flags & BINARY_FLAG) && (field->type == FIELD_TYPE_STRING || + field->type == FIELD_TYPE_VAR_STRING || field->type == FIELD_TYPE_BLOB || field->type == FIELD_TYPE_LONG_BLOB || field->type == FIELD_TYPE_MEDIUM_BLOB || From 083a2f5613362353a935434130febef98009b0b5 Mon Sep 17 00:00:00 2001 From: "jani@a193-229-222-105.elisa-laajakaista.fi" <> Date: Fri, 5 Nov 2004 18:59:19 +0200 Subject: [PATCH 124/143] Changed default.c so that it now checks for my.ini and then my.cnf from the default directories. --- BitKeeper/etc/logging_ok | 1 + mysys/default.c | 89 ++++++++++++++++++++++------------------ 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a716afb2392..01b9190b044 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -47,6 +47,7 @@ hf@genie.(none) igor@hundin.mysql.fi igor@rurik.mysql.com ingo@mysql.com +jani@a193-229-222-105.elisa-laajakaista.fi jani@a80-186-24-72.elisa-laajakaista.fi jani@a80-186-41-201.elisa-laajakaista.fi jani@dsl-jkl1657.dial.inet.fi diff --git a/mysys/default.c b/mysys/default.c index 81290322223..ed7f4b47097 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -60,11 +60,7 @@ DATADIR, NullS, }; -#define default_ext ".cnf" /* extension for config file */ -#ifdef __WIN__ -#include -#define windows_ext ".ini" -#endif +static const char *f_extensions[]= { ".ini", ".cnf", 0 }; static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc, const char *dir, const char *config_file, @@ -115,7 +111,8 @@ int load_defaults(const char *conf_file, const char **groups, uint args_used=0; int error= 0; MEM_ROOT alloc; - char *ptr,**res; + char *ptr, **res, **ext; + DBUG_ENTER("load_defaults"); init_alloc_root(&alloc,512,0); @@ -169,38 +166,43 @@ int load_defaults(const char *conf_file, const char **groups, } else if (dirname_length(conf_file)) { - if ((error= search_default_file(&args, &alloc, NullS, conf_file, - default_ext, &group)) < 0) - goto err; + for (ext= (char**) f_extensions; *ext; *ext++) + if ((error= search_default_file(&args, &alloc, NullS, conf_file, + *ext, &group)) < 0) + goto err; } else { #ifdef __WIN__ char system_dir[FN_REFLEN]; GetWindowsDirectory(system_dir,sizeof(system_dir)); - if ((search_default_file(&args, &alloc, system_dir, conf_file, - windows_ext, &group))) - goto err; + for (ext= (char**) f_extensions; *ext; *ext++) + if ((search_default_file(&args, &alloc, system_dir, conf_file, + *ext, &group))) + goto err; #endif #if defined(__EMX__) || defined(OS2) - if (getenv("ETC") && - (search_default_file(&args, &alloc, getenv("ETC"), conf_file, - default_ext, &group)) < 0) - goto err; + for (ext= (char**) f_extensions; *ext; *ext++) + if (getenv("ETC") && + (search_default_file(&args, &alloc, getenv("ETC"), conf_file, + *ext, &group)) < 0) + goto err; #endif for (dirs=default_directories ; *dirs; dirs++) { if (**dirs) { - if (search_default_file(&args, &alloc, *dirs, conf_file, - default_ext, &group) < 0) - goto err; + for (ext= (char**) f_extensions; *ext; *ext++) + if (search_default_file(&args, &alloc, *dirs, conf_file, + *ext, &group) < 0) + goto err; } else if (defaults_extra_file) { - if (search_default_file(&args, &alloc, NullS, defaults_extra_file, - default_ext, &group) < 0) - goto err; /* Fatal error */ + for (ext= (char**) f_extensions; ext; ext++) + if (search_default_file(&args, &alloc, NullS, defaults_extra_file, + *ext, &group) < 0) + goto err; /* Fatal error */ } } } @@ -478,8 +480,9 @@ void print_defaults(const char *conf_file, const char **groups) #ifdef __WIN__ bool have_ext=fn_ext(conf_file)[0] != 0; #endif - char name[FN_REFLEN]; + char name[FN_REFLEN], **ext; const char **dirs; + puts("\nDefault options are read from the following files in the given order:"); if (dirname_length(conf_file)) @@ -488,27 +491,35 @@ void print_defaults(const char *conf_file, const char **groups) { #ifdef __WIN__ GetWindowsDirectory(name,sizeof(name)); - printf("%s\\%s%s ",name,conf_file,have_ext ? "" : windows_ext); + if (have_ext) + for (ext= (char**) f_extensions; *ext; *ext++) + printf("%s\\%s%s ", name, conf_file, *ext); + else + printf("%s\\%s ", name, conf_file); #endif #if defined(__EMX__) || defined(OS2) - if (getenv("ETC")) - printf("%s\\%s%s ", getenv("ETC"), conf_file, default_ext); + for (ext= (char**) f_extensions; *ext; *ext++) + if (getenv("ETC")) + printf("%s\\%s%s ", getenv("ETC"), conf_file, *ext); #endif for (dirs=default_directories ; *dirs; dirs++) { - const char *pos; - char *end; - if (**dirs) - pos= *dirs; - else if (defaults_extra_file) - pos= defaults_extra_file; - else - continue; - end=convert_dirname(name, pos, NullS); - if (name[0] == FN_HOMELIB) /* Add . to filenames in home */ - *end++='.'; - strxmov(end,conf_file,default_ext," ",NullS); - fputs(name,stdout); + for (ext= (char**) f_extensions; *ext; *ext++) + { + const char *pos; + char *end; + if (**dirs) + pos= *dirs; + else if (defaults_extra_file) + pos= defaults_extra_file; + else + continue; + end= convert_dirname(name, pos, NullS); + if (name[0] == FN_HOMELIB) /* Add . to filenames in home */ + *end++='.'; + strxmov(end, conf_file, *ext, " ", NullS); + fputs(name,stdout); + } } puts(""); } From bfdf57ef31174814cdec5e275d710b4a48dc55c7 Mon Sep 17 00:00:00 2001 From: "jani@a193-229-222-105.elisa-laajakaista.fi" <> Date: Fri, 5 Nov 2004 23:58:30 +0200 Subject: [PATCH 125/143] Fixed a typo that caused segmentation fault when using --defaults-extra-file option. --- mysys/default.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/default.c b/mysys/default.c index ed7f4b47097..416de09b661 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -199,7 +199,7 @@ int load_defaults(const char *conf_file, const char **groups, } else if (defaults_extra_file) { - for (ext= (char**) f_extensions; ext; ext++) + for (ext= (char**) f_extensions; *ext; *ext++) if (search_default_file(&args, &alloc, NullS, defaults_extra_file, *ext, &group) < 0) goto err; /* Fatal error */ From a83f8e60abfacc06d440996e3b3206e834bdb85c Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Tue, 9 Nov 2004 00:19:39 +0400 Subject: [PATCH 126/143] mysql.h: Adding a prototype for the new function. --- include/mysql.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mysql.h b/include/mysql.h index 8abeb86e32a..08ea2da2e58 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -392,6 +392,8 @@ unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); unsigned long STDCALL mysql_escape_string(char *to,const char *from, unsigned long from_length); +unsigned long STDCALL mysql_hex_string(char *to,const char *from, + unsigned long from_length); unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); From 0d0ed072da20c4af7a2433e21206aec773482b49 Mon Sep 17 00:00:00 2001 From: "paul@kite-hub.kitebird.com" <> Date: Tue, 9 Nov 2004 11:03:02 -0600 Subject: [PATCH 127/143] Alphabetize some out-of-order options in option structure. Revise the --hex-blob help message string. (This will need revising after merge to 4.1, too, but the CHAR BINARY and VARCHAR BINARY data types will be BINARY and VARBINRY.) --- client/mysqldump.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 0e840512ba0..58d601654a4 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -114,6 +114,9 @@ static struct my_option my_long_options[] = {"character-sets-dir", OPT_CHARSETS_DIR, "Directory where character sets are", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"comments", 'i', "Write additional information.", + (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG, + 1, 0, 0, 0, 0, 0}, {"complete-insert", 'c', "Use complete insert statements.", (gptr*) &cFlag, (gptr*) &cFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", @@ -166,6 +169,9 @@ static struct my_option my_long_options[] = 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"hex-blob", OPT_HEXBLOB, "Dump binary strings (CHAR BINARY, " + "VARCHAR BINARY, BLOB) in hexadecimal format.", + (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Connect to host.", (gptr*) ¤t_host, (gptr*) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...", @@ -180,10 +186,6 @@ static struct my_option my_long_options[] = "Wrap tables with autocommit/commit statements.", (gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"single-transaction", OPT_TRANSACTION, - "Dump all tables in single transaction to get consistent snapshot. Mutually exclusive with --lock-tables.", - (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, GET_BOOL, NO_ARG, - 0, 0, 0, 0, 0, 0}, {"no-create-db", 'n', "'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given.}", (gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0, @@ -192,9 +194,6 @@ static struct my_option my_long_options[] = (gptr*) &tFlag, (gptr*) &tFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-data", 'd', "No row information.", (gptr*) &dFlag, (gptr*) &dFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"set-variable", 'O', - "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"opt", OPT_OPTIMIZE, "Same as --add-drop-table --add-locks --all --quick --extended-insert --lock-tables --disable-keys", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -216,6 +215,13 @@ static struct my_option my_long_options[] = {"result-file", 'r', "Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"set-variable", 'O', + "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"single-transaction", OPT_TRANSACTION, + "Dump all tables in single transaction to get consistent snapshot. Mutually exclusive with --lock-tables.", + (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"socket", 'S', "Socket file to use for connection.", (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -246,11 +252,6 @@ static struct my_option my_long_options[] = (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L, MALLOC_OVERHEAD-1024, 1024, 0}, - {"comments", 'i', "Write additional information.", - (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG, - 1, 0, 0, 0, 0, 0}, - {"hex-blob", OPT_HEXBLOB, "Dump BLOBs in HEX.", - (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; From 0c4363b6d0257d4234b12367c7746257f9472f17 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Wed, 10 Nov 2004 15:07:55 +0100 Subject: [PATCH 128/143] Fix for BUG#6522 "Replication fails due to a rolled back transaction in the binlog" When we are writing a transaction to the binlog, we log BEGIN/COMMIT with zero error code. Example: all statements of trans succeeded, connection lost and so implicit rollback: we don't want ER_NET* errors to be logged in the BEGIN/ROLLBACK events, while statement events have 0. If there was really a serious error code, it's already in the statement events. --- sql/log.cc | 9 +++++++++ sql/sql_table.cc | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index aa5d9d8753b..b2d015c1a14 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1370,6 +1370,14 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback) */ { Query_log_event qinfo(thd, "BEGIN", 5, TRUE); + /* + Imagine this is rollback due to net timeout, after all statements of + the transaction succeeded. Then we want a zero-error code in BEGIN. + In other words, if there was a really serious error code it's already + in the statement's events. + This is safer than thd->clear_error() against kills at shutdown. + */ + qinfo.error_code= 0; /* Now this Query_log_event has artificial log_pos 0. It must be adjusted to reflect the real position in the log. Not doing it would confuse the @@ -1403,6 +1411,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback) commit_or_rollback ? "COMMIT" : "ROLLBACK", commit_or_rollback ? 6 : 8, TRUE); + qinfo.error_code= 0; qinfo.set_log_pos(this); if (qinfo.write(&log_file) || flush_io_cache(&log_file)) goto err; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 65690e56039..1e5237b1428 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -911,7 +911,6 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, } table->file->extra(HA_EXTRA_WRITE_CACHE); DBUG_RETURN(table); - /* Note that leaving the function resets binlogging properties */ } From 4f0421787936ead1927aa3d33d6942023559ad4a Mon Sep 17 00:00:00 2001 From: "jani@a80-186-24-72.elisa-laajakaista.fi" <> Date: Thu, 11 Nov 2004 16:20:39 +0200 Subject: [PATCH 129/143] Removed check for .ini file elsewhere, except on Windows. --- mysys/default.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysys/default.c b/mysys/default.c index 416de09b661..d260dd4b370 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -60,7 +60,11 @@ DATADIR, NullS, }; +#ifdef __WIN__ static const char *f_extensions[]= { ".ini", ".cnf", 0 }; +#else +static const char *f_extensions[]= { ".cnf", 0 }; +#endif static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc, const char *dir, const char *config_file, From 98df9313c014310890dc744a6913e8f71260999c Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Thu, 11 Nov 2004 18:20:40 +0400 Subject: [PATCH 130/143] A fix (bug #6564: QUOTE(NULL) returns NULL, not the string 'NULL') --- mysql-test/r/func_str.result | 5 ++++- mysql-test/t/func_str.test | 6 ++++++ sql/item_strfunc.cc | 14 +++++++++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index b4d1be5bd54..d38a2edfa1a 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -167,6 +167,9 @@ length(quote(concat(char(0),"test"))) select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235)))); hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235)))) 27E0E3E6E7E8EAEB27 +select concat('a', quote(NULL)); +concat('a', quote(NULL)) +aNULL select reverse(""); reverse("") @@ -278,7 +281,7 @@ insert into t1 values ('one'),(NULL),('two'),('four'); select a, quote(a), isnull(quote(a)), quote(a) is null, ifnull(quote(a), 'n') from t1; a quote(a) isnull(quote(a)) quote(a) is null ifnull(quote(a), 'n') one 'one' 0 0 'one' -NULL NULL 1 1 n +NULL NULL 0 0 NULL two 'two' 0 0 'two' four 'four' 0 0 'four' drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index ba6a8b55236..1ae4db3a42a 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -69,6 +69,12 @@ select quote(1/0), quote('\0\Z'); select length(quote(concat(char(0),"test"))); select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235)))); +# +# Bug #6564: QUOTE(NULL +# + +select concat('a', quote(NULL)); + # # Wrong usage of functions # diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9248cbc0217..53a9d3fe219 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2142,9 +2142,12 @@ String* Item_func_inet_ntoa::val_str(String* str) This function is very useful when you want to generate SQL statements - RETURN VALUES + NOTE + QUOTE(NULL) returns the string 'NULL' (4 letters, without quotes). + + RETURN VALUES str Quoted string - NULL Argument to QUOTE() was NULL or out of memory. + NULL Out of memory. */ #define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7)) @@ -2168,7 +2171,12 @@ String *Item_func_quote::val_str(String *str) String *arg= args[0]->val_str(str); uint arg_length, new_length; if (!arg) // Null argument - goto null; + { + str->copy("NULL", 4); // Return the string 'NULL' + null_value= 0; + return str; + } + arg_length= arg->length(); new_length= arg_length+2; /* for beginning and ending ' signs */ From 54dac2cfacd931a3afc972d380ae2a27ee38be6b Mon Sep 17 00:00:00 2001 From: "jani@a80-186-24-72.elisa-laajakaista.fi" <> Date: Thu, 11 Nov 2004 16:59:36 +0200 Subject: [PATCH 131/143] Some code clean-up and optimization. --- mysys/default.c | 90 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index d260dd4b370..16e166a3ca5 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -68,7 +68,12 @@ static const char *f_extensions[]= { ".cnf", 0 }; static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc, const char *dir, const char *config_file, - const char *ext, TYPELIB *group); + TYPELIB *group); + +static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, + const char *dir, const char *ext, + const char *config_file, + TYPELIB *group); static char *remove_end_comment(char *ptr); @@ -164,15 +169,16 @@ int load_defaults(const char *conf_file, const char **groups, goto err; if (forced_default_file) { - if ((error= search_default_file(&args, &alloc, "", - forced_default_file, "", &group)) < 0) + if ((error= search_default_file_with_ext(&args, &alloc, "", "", + forced_default_file, + &group)) < 0) goto err; } else if (dirname_length(conf_file)) { for (ext= (char**) f_extensions; *ext; *ext++) if ((error= search_default_file(&args, &alloc, NullS, conf_file, - *ext, &group)) < 0) + &group)) < 0) goto err; } else @@ -180,33 +186,31 @@ int load_defaults(const char *conf_file, const char **groups, #ifdef __WIN__ char system_dir[FN_REFLEN]; GetWindowsDirectory(system_dir,sizeof(system_dir)); - for (ext= (char**) f_extensions; *ext; *ext++) - if ((search_default_file(&args, &alloc, system_dir, conf_file, - *ext, &group))) - goto err; + if ((search_default_file(&args, &alloc, system_dir, conf_file, &group))) + goto err; #endif #if defined(__EMX__) || defined(OS2) - for (ext= (char**) f_extensions; *ext; *ext++) - if (getenv("ETC") && - (search_default_file(&args, &alloc, getenv("ETC"), conf_file, - *ext, &group)) < 0) - goto err; + { + const char *etc; + if ((etc= getenv("ETC")) && + (search_default_file(&args, &alloc, etc, conf_file, + &group)) < 0) + goto err; + } #endif for (dirs=default_directories ; *dirs; dirs++) { if (**dirs) { - for (ext= (char**) f_extensions; *ext; *ext++) - if (search_default_file(&args, &alloc, *dirs, conf_file, - *ext, &group) < 0) - goto err; + if (search_default_file(&args, &alloc, *dirs, conf_file, + &group) < 0) + goto err; } else if (defaults_extra_file) { - for (ext= (char**) f_extensions; *ext; *ext++) - if (search_default_file(&args, &alloc, NullS, defaults_extra_file, - *ext, &group) < 0) - goto err; /* Fatal error */ + if (search_default_file(&args, &alloc, NullS, defaults_extra_file, + &group) < 0) + goto err; /* Fatal error */ } } } @@ -267,11 +271,28 @@ void free_defaults(char **argv) } +static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, + const char *dir, + const char *config_file, TYPELIB *group) +{ + char **ext; + + for (ext= (char**) f_extensions; *ext; *ext++) + { + int error; + if ((error= search_default_file_with_ext(args, alloc, dir, *ext, + config_file, group)) < 0) + return error; + } + return 0; +} + + /* Open a configuration file (if exists) and read given options from it SYNOPSIS - search_default_file() + search_default_file_with_ext() args Store pointer to found options here alloc Allocate strings in this object dir directory to read @@ -286,9 +307,10 @@ void free_defaults(char **argv) 2 File is not a regular file (Warning) */ -static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, - const char *dir, const char *config_file, - const char *ext, TYPELIB *group) +static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, + const char *dir, const char *ext, + const char *config_file, + TYPELIB *group) { char name[FN_REFLEN+10],buff[4096],*ptr,*end,*value,*tmp; FILE *fp; @@ -482,7 +504,7 @@ static char *remove_end_comment(char *ptr) void print_defaults(const char *conf_file, const char **groups) { #ifdef __WIN__ - bool have_ext=fn_ext(conf_file)[0] != 0; + my_bool have_ext= fn_ext(conf_file)[0] != 0; #endif char name[FN_REFLEN], **ext; const char **dirs; @@ -495,16 +517,24 @@ void print_defaults(const char *conf_file, const char **groups) { #ifdef __WIN__ GetWindowsDirectory(name,sizeof(name)); - if (have_ext) + if (!have_ext) + { for (ext= (char**) f_extensions; *ext; *ext++) printf("%s\\%s%s ", name, conf_file, *ext); + } else printf("%s\\%s ", name, conf_file); #endif #if defined(__EMX__) || defined(OS2) - for (ext= (char**) f_extensions; *ext; *ext++) - if (getenv("ETC")) - printf("%s\\%s%s ", getenv("ETC"), conf_file, *ext); + { + const char *etc; + + if ((etc= getenv("ETC"))) + { + for (ext= (char**) f_extensions; *ext; *ext++) + printf("%s\\%s%s ", etc, conf_file, *ext); + } + } #endif for (dirs=default_directories ; *dirs; dirs++) { From 2ad7d5c662d785664ac3690240e89ce8d11ed21f Mon Sep 17 00:00:00 2001 From: "acurtis@pcgem.rdg.cyberkinetica.com" <> Date: Thu, 11 Nov 2004 20:59:03 +0000 Subject: [PATCH 132/143] Bug#6123 - GRANT USAGE creates useless mysql.db row Prevent creation of a row which grants no rights Test included --- mysql-test/r/grant.result | 6 ++++++ mysql-test/t/grant.test | 9 +++++++++ sql/sql_acl.cc | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index d4d8dd1f026..f0e5d16e916 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -150,3 +150,9 @@ GRANT SELECT ON `ab%`.* TO 'test11'@'localhost' GRANT SELECT ON `a%`.* TO 'test11'@'localhost' delete from mysql.user where user='test11'; delete from mysql.db where user='test11'; +create database db6123; +grant usage on db6123.* to test6123 identified by 'magic123'; +select host,db,user,select_priv,insert_priv from mysql.db where db="db6123"; +host db user select_priv insert_priv +delete from mysql.user where user='test6123'; +drop database db6123; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index a278b9d5928..21173a356ce 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -105,3 +105,12 @@ flush privileges; show grants for test11@localhost; delete from mysql.user where user='test11'; delete from mysql.db where user='test11'; + +# +# Bug#6123: GRANT USAGE inserts useless Db row +# +create database db6123; +grant usage on db6123.* to test6123 identified by 'magic123'; +select host,db,user,select_priv,insert_priv from mysql.db where db="db6123"; +delete from mysql.user where user='test6123'; +drop database db6123; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b3bc5a1e4f2..67ca62357ec 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1587,7 +1587,7 @@ static int replace_db_table(TABLE *table, const char *db, goto table_error; /* purecov: deadcode */ } } - else if ((error=table->file->write_row(table->record[0]))) + else if (rights && (error=table->file->write_row(table->record[0]))) { if (error && error != HA_ERR_FOUND_DUPP_KEY) /* purecov: inspected */ goto table_error; /* purecov: deadcode */ @@ -1597,6 +1597,7 @@ static int replace_db_table(TABLE *table, const char *db, if (old_row_exists) acl_update_db(combo.user.str,combo.host.str,db,rights); else + if (rights) acl_insert_db(combo.user.str,combo.host.str,db,rights); table->file->index_end(); DBUG_RETURN(0); From 76b8c8747dd175ccd4706ccc209ebdb478c1c1d5 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Fri, 12 Nov 2004 19:22:58 +0200 Subject: [PATCH 133/143] Removed an unneccessary for() and variable. --- mysys/default.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index 16e166a3ca5..364b2037f67 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -120,7 +120,7 @@ int load_defaults(const char *conf_file, const char **groups, uint args_used=0; int error= 0; MEM_ROOT alloc; - char *ptr, **res, **ext; + char *ptr, **res; DBUG_ENTER("load_defaults"); @@ -176,10 +176,9 @@ int load_defaults(const char *conf_file, const char **groups, } else if (dirname_length(conf_file)) { - for (ext= (char**) f_extensions; *ext; *ext++) - if ((error= search_default_file(&args, &alloc, NullS, conf_file, - &group)) < 0) - goto err; + if ((error= search_default_file(&args, &alloc, NullS, conf_file, + &group)) < 0) + goto err; } else { From 79d8bde11ee6da9474a5b122c1739316f5adb120 Mon Sep 17 00:00:00 2001 From: "paul@kite-hub.kitebird.com" <> Date: Fri, 12 Nov 2004 14:15:06 -0600 Subject: [PATCH 134/143] Makefile.am: Add -acc flag for texi2html to handle accented characters. --- Docs/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Makefile.am b/Docs/Makefile.am index e53ea195d94..2f32dfca1b4 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -9,7 +9,7 @@ # If you know how to fix any of this more elegantly please mail # docs@mysql.com -TEXI2HTML_FLAGS = -iso -number +TEXI2HTML_FLAGS = -iso -number -acc DVIPS = dvips MAKEINFO = @MAKEINFO@ TEXINFO_TEX = Support/texinfo.tex From 3d67df4cff0b27865e49f6dab2ff44f416d1edfc Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Fri, 12 Nov 2004 22:55:00 +0100 Subject: [PATCH 135/143] wrong constant fixed - boolean fulltext searches like "+something +smth*" were stopping at docid 0xffffffff --- myisam/ft_boolean_search.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 13f46849210..97dfb18e5f9 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -161,7 +161,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end, if (param.trunc) ftbw->flags|=FTB_FLAG_TRUNC; ftbw->weight=weight; ftbw->up=up; - ftbw->docid[0]=ftbw->docid[1]=HA_POS_ERROR; + ftbw->docid[0]=ftbw->docid[1]=HA_OFFSET_ERROR; ftbw->ndepth= (param.yesno<0) + depth; memcpy(ftbw->word+1, w.pos, w.len); ftbw->word[0]=w.len; @@ -177,7 +177,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end, ftbe->weight=weight; ftbe->up=up; ftbe->ythresh=ftbe->yweaks=0; - ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR; + ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR; if ((ftbe->quot=param.quot)) ftb->with_scan|=2; if (param.yesno > 0) up->ythresh++; _ftb_parse_query(ftb, start, end, ftbe, depth+1); @@ -245,7 +245,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) ftbe->up->ythresh - ftbe->up->yweaks >1) /* 1 */ { FTB_EXPR *top_ftbe=ftbe->up->up; - ftbw->docid[0]=HA_POS_ERROR; + ftbw->docid[0]=HA_OFFSET_ERROR; for (ftbe=ftbw->up; ftbe != top_ftbe; ftbe=ftbe->up) if (ftbe->flags & FTB_FLAG_YES) ftbe->yweaks++; @@ -319,7 +319,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, default_charset_info : info->s->keyinfo[keynr].seg->charset); ftb->with_scan=0; - ftb->lastpos=HA_POS_ERROR; + ftb->lastpos=HA_OFFSET_ERROR; bzero(& ftb->no_dupes, sizeof(TREE)); init_alloc_root(&ftb->mem_root, 1024, 1024); @@ -342,7 +342,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, ftbe->quot=0; ftbe->up=0; ftbe->ythresh=ftbe->yweaks=0; - ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR; + ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR; ftb->root=ftbe; _ftb_parse_query(ftb, &query, query+query_len, ftbe, 0); ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, @@ -496,7 +496,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record) while (ftb->state == INDEX_SEARCH && (curdoc=((FTB_WORD *)queue_top(& ftb->queue))->docid[0]) != - HA_POS_ERROR) + HA_OFFSET_ERROR) { while (curdoc==(ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0]) { @@ -521,7 +521,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record) } if (r) /* not found */ { - ftbw->docid[0]=HA_POS_ERROR; + ftbw->docid[0]=HA_OFFSET_ERROR; if (ftbw->flags&FTB_FLAG_YES && ftbw->up->up==0) { /* @@ -580,7 +580,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) const byte *end; my_off_t docid=ftb->info->lastpos; - if (docid == HA_POS_ERROR) + if (docid == HA_OFFSET_ERROR) return -2.0; if (!ftb->queue.elements) return 0; @@ -592,9 +592,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) for (i=0; i < ftb->queue.elements; i++) { - ftb->list[i]->docid[1]=HA_POS_ERROR; + ftb->list[i]->docid[1]=HA_OFFSET_ERROR; for (x=ftb->list[i]->up; x; x=x->up) - x->docid[1]=HA_POS_ERROR; + x->docid[1]=HA_OFFSET_ERROR; } } From 5ddc564d892928e42f75adfa01bee3d50b416770 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Mon, 15 Nov 2004 16:11:13 +0300 Subject: [PATCH 136/143] Proposed fix for bug #6439 "from_unixtime() function returns wrong datetime values for too big argument". Added range checking for from_unixtime() argument, cleaned up code a bit. --- mysql-test/r/func_time.result | 6 ++++ mysql-test/t/func_time.test | 7 +++++ sql/item_timefunc.cc | 57 ++++++++++++++--------------------- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 877ca0e2d51..32034bf289d 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -470,3 +470,9 @@ unix_timestamp(@a) select unix_timestamp('1969-12-01 19:00:01'); unix_timestamp('1969-12-01 19:00:01') 0 +select from_unixtime(0); +from_unixtime(0) +NULL +select from_unixtime(2145916800); +from_unixtime(2145916800) +NULL diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index fffda12c14e..da18269cf6a 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -225,3 +225,10 @@ drop table t1,t2,t3; select @a:=FROM_UNIXTIME(1); select unix_timestamp(@a); select unix_timestamp('1969-12-01 19:00:01'); + +# +# Test for bug #6439 "unix_timestamp() function returns wrong datetime +# values for too big argument". It should return error instead. +# +select from_unixtime(0); +select from_unixtime(2145916800); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index ed950a33166..d188310be24 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -919,21 +919,14 @@ String *Item_func_date_format::val_str(String *str) String *Item_func_from_unixtime::val_str(String *str) { - struct tm tm_tmp,*start; - time_t tmp=(time_t) args[0]->val_int(); - if ((null_value=args[0]->null_value)) + TIME ltime; + if (get_date(<ime, 0)) return 0; - localtime_r(&tmp,&tm_tmp); - start=&tm_tmp; if (str->alloc(20)) return str; /* purecov: inspected */ sprintf((char*) str->ptr(),"%04d-%02d-%02d %02d:%02d:%02d", - (int) start->tm_year+1900, - (int) start->tm_mon+1, - (int) start->tm_mday, - (int) start->tm_hour, - (int) start->tm_min, - (int) start->tm_sec); + (int) ltime.year, (int) ltime.month, (int) ltime.day, + (int) ltime.hour, (int) ltime.minute, (int) ltime.second); str->length(19); return str; } @@ -941,37 +934,33 @@ String *Item_func_from_unixtime::val_str(String *str) longlong Item_func_from_unixtime::val_int() { - time_t tmp=(time_t) (ulong) args[0]->val_int(); - if ((null_value=args[0]->null_value)) + TIME ltime; + if (get_date(<ime, 0)) return 0; - struct tm tm_tmp,*start; - localtime_r(&tmp,&tm_tmp); - start= &tm_tmp; - return ((longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+ - (((uint) start->tm_mon+1)*100+ - (uint) start->tm_mday))*LL(1000000)+ - (longlong) ((ulong) ((uint) start->tm_hour)*10000L+ - (ulong) (((uint) start->tm_min)*100L+ - (uint) start->tm_sec))); + return ((longlong)(ltime.year*10000L+ltime.month*100+ltime.day)*LL(1000000)+ + (longlong)(ltime.hour*10000L+ltime.minute*100+ltime.second)); } bool Item_func_from_unixtime::get_date(TIME *ltime, bool fuzzy_date __attribute__((unused))) { - time_t tmp=(time_t) (ulong) args[0]->val_int(); - if ((null_value=args[0]->null_value)) + struct tm tm_tmp; + time_t tmp; + longlong arg= args[0]->val_int(); + if ((null_value= (args[0]->null_value || + arg < TIMESTAMP_MIN_VALUE || + arg > TIMESTAMP_MAX_VALUE))) return 1; - struct tm tm_tmp,*start; + tmp= arg; localtime_r(&tmp,&tm_tmp); - start= &tm_tmp; - ltime->year= start->tm_year+1900; - ltime->month= start->tm_mon+1; - ltime->day= start->tm_mday; - ltime->hour= start->tm_hour; - ltime->minute=start->tm_min; - ltime->second=start->tm_sec; - ltime->second_part=0; - ltime->neg=0; + ltime->year= tm_tmp.tm_year+1900; + ltime->month= tm_tmp.tm_mon+1; + ltime->day= tm_tmp.tm_mday; + ltime->hour= tm_tmp.tm_hour; + ltime->minute= tm_tmp.tm_min; + ltime->second= tm_tmp.tm_sec; + ltime->second_part= 0; + ltime->neg= 0; return 0; } From dd64377dc2eb6478e862929c9b47965f82a18b93 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Tue, 16 Nov 2004 20:37:42 +0200 Subject: [PATCH 137/143] ha_innodb.cc: Fix InnoDB bug #6287: if one uses INSERT IGNORE to insert several rows at a time, and the first inserts are ignored because of a duplicate key collision, then InnoDB in a replication slave assigns AUTO_INCREMENT values 1 bigger than in the master --- sql/ha_innodb.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index d57a9f73c91..91f92c8cadb 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2172,8 +2172,9 @@ ha_innobase::write_row( same SQL statement! */ if (auto_inc == 0 && user_thd->next_insert_id != 0) { - auto_inc = user_thd->next_insert_id; - auto_inc_counter_for_this_stat = auto_inc; + + auto_inc_counter_for_this_stat + = user_thd->next_insert_id; } if (auto_inc == 0 && auto_inc_counter_for_this_stat) { @@ -2181,14 +2182,14 @@ ha_innobase::write_row( this SQL statement with SET INSERT_ID. We must assign sequential values from the counter. */ - auto_inc_counter_for_this_stat++; - incremented_auto_inc_for_stat = TRUE; - auto_inc = auto_inc_counter_for_this_stat; /* We give MySQL a new value to place in the auto-inc column */ user_thd->next_insert_id = auto_inc; + + auto_inc_counter_for_this_stat++; + incremented_auto_inc_for_stat = TRUE; } if (auto_inc != 0) { From 2d8c21f700ceed83e5c7ef3ac20cccb434da48fb Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Wed, 17 Nov 2004 13:38:35 +0100 Subject: [PATCH 138/143] test for bug#5528 --- mysql-test/r/fulltext.result | 9 +++++++++ mysql-test/t/fulltext.test | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 19bd355f537..31be1881897 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -298,3 +298,12 @@ t1_id name t2_id t1_id name select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); t2_id t1_id name drop table t1,t2; +CREATE TABLE t1 (h text, FULLTEXT (h)); +INSERT INTO t1 VALUES ('Jesses Hasse Ling and his syncopators of Swing'); +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +select count(*) from t1; +count(*) +1 +drop table t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index bd887bc63ee..e46399bb876 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -240,3 +240,13 @@ select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); drop table t1,t2; +# +# icc -ip bug (ip = interprocedural optimization) +# bug#5528 +# +CREATE TABLE t1 (h text, FULLTEXT (h)); +INSERT INTO t1 VALUES ('Jesses Hasse Ling and his syncopators of Swing'); +REPAIR TABLE t1; +select count(*) from t1; +drop table t1; + From 7743dbbb56821c4ff45d892243d5acf0ee54e7a5 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Thu, 18 Nov 2004 22:59:17 +0100 Subject: [PATCH 139/143] When mysqlbinlog prints LOAD DATA INFILE, let it print the thread id. Some customer would have benefited much from this in his recovery. All this change does is adding one commented (#) line before the LOAD DATA command, so it is quite innocuous. --- sql/log_event.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index f707eabebd5..007bb6e7b85 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1612,7 +1612,7 @@ void Create_file_log_event::print(FILE* file, bool short_form, if (enable_local) { - Load_log_event::print(file, 1, last_db, !check_fname_outside_temp_buf()); + Load_log_event::print(file, short_form, last_db, !check_fname_outside_temp_buf()); /* That one is for "file_id: etc" below: in mysqlbinlog we want the #, in SHOW BINLOG EVENTS we don't. From dca2182fdc8d2eedeaebfd2fbec8cd07b8be3fb5 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Mon, 22 Nov 2004 18:37:30 +0100 Subject: [PATCH 140/143] ft_boolean_search.c: bug#6705 - (+trunc1* +trunc2*) fulltext.test, fulltext.result: bug#6705 --- myisam/ft_boolean_search.c | 4 ++-- mysql-test/r/fulltext.result | 8 ++++++++ mysql-test/t/fulltext.test | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 97dfb18e5f9..1958619c2dd 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -247,7 +247,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) FTB_EXPR *top_ftbe=ftbe->up->up; ftbw->docid[0]=HA_OFFSET_ERROR; for (ftbe=ftbw->up; ftbe != top_ftbe; ftbe=ftbe->up) - if (ftbe->flags & FTB_FLAG_YES) + if (!(ftbe->flags & FTB_FLAG_NO)) ftbe->yweaks++; ftbe=0; break; @@ -255,7 +255,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) } if (!ftbe) continue; - /* 3 */ + /* 4 */ if (!is_tree_inited(& ftb->no_dupes)) init_tree(& ftb->no_dupes,0,0,sizeof(my_off_t), _ftb_no_dupes_cmp,0,0,0); diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 31be1881897..50f0a1dc120 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -162,6 +162,14 @@ a select * from t1 where match a against ("+aaa10 +(bbb*)" in boolean mode); a aaa10 bbb20 +select * from t1 where match a against ("+(+aaa* +bbb1*)" in boolean mode); +a +aaa20 bbb15 +aaa30 bbb10 +select * from t1 where match a against ("(+aaa* +bbb1*)" in boolean mode); +a +aaa20 bbb15 +aaa30 bbb10 drop table t1; CREATE TABLE t1 ( id int(11), diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index e46399bb876..b44854860f9 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -87,6 +87,8 @@ select * from t1 where match a against ("+aaa* +bbb*" in boolean mode); select * from t1 where match a against ("+aaa* +bbb1*" in boolean mode); select * from t1 where match a against ("+aaa* +ccc*" in boolean mode); select * from t1 where match a against ("+aaa10 +(bbb*)" in boolean mode); +select * from t1 where match a against ("+(+aaa* +bbb1*)" in boolean mode); +select * from t1 where match a against ("(+aaa* +bbb1*)" in boolean mode); drop table t1; # From b7aa981578e03317128868d5011db33a08d0f74d Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Mon, 22 Nov 2004 19:18:35 +0100 Subject: [PATCH 141/143] "Table file %s was created in MySQL 4.1+" is an error, not a warning --- myisam/mi_open.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 944a8af01e9..339ce2de291 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -188,7 +188,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) share->state_diff_length=len-MI_STATE_INFO_SIZE; if (share->state.header.fulltext_keys) + { fprintf(stderr, "Warning: table file %s was created in MySQL 4.1+, use REPAIR TABLE ... USE_FRM to recreate it as a valid MySQL 4.0 table\n", name_buff); + my_errno=HA_ERR_UNSUPPORTED; + goto err; + } mi_state_info_read(disk_cache, &share->state); len= mi_uint2korr(share->state.header.base_info_length); From 134aa0b97b0aabc646916b70847048c11dbbe85b Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Tue, 23 Nov 2004 17:18:41 +0100 Subject: [PATCH 142/143] Change "Do-compile" to make automatic build log analysis easier and to run the standard tests with "--force" (default, can be switched off). --- Build-tools/Do-compile | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index f92af463a0a..af03f3209aa 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -10,7 +10,7 @@ use Sys::Hostname; $opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env=""; $opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix=""; $opt_tmp=$opt_version_suffix=""; -$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=0; +$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_one_error=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=0; $opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=$opt_clearlogs=$opt_without_ndbcluster=0; GetOptions( @@ -36,6 +36,7 @@ GetOptions( "no-test", "no-mysqltest", "no-benchmark", + "one-error", "perl-files=s", "perl-options=s", "raid", @@ -298,6 +299,7 @@ if ($opt_stage <= 2) $command=$make; $command.= " $opt_make_options" if (defined($opt_make_options) && $opt_make_options ne ""); safe_system($command); + print LOG "Do-compile: Build successful\n"; } # @@ -358,10 +360,16 @@ $ENV{"LD_LIBRARY_PATH"}= ("$test_dir/lib" . # if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest) { + my $force= ""; + if (!$opt_one_error) + { + $force= "--force"; # default + } log_timestamp(); system("mkdir $bench_tmpdir") if (! -d $bench_tmpdir); safe_cd("${test_dir}/mysql-test"); - check_system("./mysql-test-run --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful"); + check_system("./mysql-test-run $force --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful"); + # 'mysql-test-run' writes its own final message for log evaluation. } # @@ -535,7 +543,10 @@ Do not run any tests. Do not run the benchmark test (written in perl) --no-mysqltest -Do not run the the mysql-test-run test (Same as 'make test') +Do not run the mysql-test-run test (Same as 'make test') + +--one-error +Terminate the mysql-test-run test after the first difference (default: use '--force') --perl-files=list of files Compile and install the given perl modules. From cf722bc3f5040d447f657477485e362b967d1f3e Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Wed, 24 Nov 2004 15:24:23 +0100 Subject: [PATCH 143/143] Ensure consistent sources up to 5.0 where a C++ problem occurs. --- client/mysqladmin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqladmin.c b/client/mysqladmin.c index 153fcdde96d..978e0c7e88b 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -554,7 +554,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) { char *pos,buff[40]; ulong sec; - pos=strchr(status,' '); + pos= (char*) strchr(status,' '); *pos++=0; printf("%s\t\t\t",status); /* print label */ if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))