From 4352b9953a334e70ecff8f6e71a513d9fa95c40e Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Thu, 27 Feb 2003 22:26:09 +0200 Subject: [PATCH 001/188] fixed SQL_SELECT option with UNIONs --- mysql-test/r/query_cache.result | 11 ++++++++--- mysql-test/t/query_cache.test | 5 +++-- sql/sql_cache.cc | 2 +- sql/sql_yacc.yy | 5 ++++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 41fccc2743c..74dee666e05 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -237,13 +237,18 @@ a show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 -select sql_cache * from t1; +select sql_cache * from t1 union select * from t1; a 1 2 3 set query_cache_type=2; -select sql_cache * from t1; +select sql_cache * from t1 union select * from t1; +a +1 +2 +3 +select * from t1 union select sql_cache * from t1; a 1 2 @@ -253,7 +258,7 @@ Variable_name Value Qcache_hits 4 show status like "Qcache_queries_in_cache"; Variable_name Value -Qcache_queries_in_cache 1 +Qcache_queries_in_cache 2 set query_cache_type=on; reset query cache; show status like "Qcache_queries_in_cache"; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index dd092866e44..83c11978436 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -144,9 +144,10 @@ create table t1 (a int not null); insert into t1 values (1),(2),(3); select * from t1; show status like "Qcache_queries_in_cache"; -select sql_cache * from t1; +select sql_cache * from t1 union select * from t1; set query_cache_type=2; -select sql_cache * from t1; +select sql_cache * from t1 union select * from t1; +select * from t1 union select sql_cache * from t1; show status like "Qcache_hits"; show status like "Qcache_queries_in_cache"; set query_cache_type=on; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 64c62345182..ee62d7b16ed 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2439,7 +2439,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, if (lex->sql_command == SQLCOM_SELECT && (thd->variables.query_cache_type == 1 || - (thd->variables.query_cache_type == 2 && (lex->select->options & + (thd->variables.query_cache_type == 2 && (lex->select_lex.options & OPTION_TO_QUERY_CACHE))) && thd->safe_to_cache_query) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2f339f30eb4..0879995e733 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1530,7 +1530,10 @@ select_option: Select->options|= OPTION_FOUND_ROWS; } | SQL_NO_CACHE_SYM { current_thd->safe_to_cache_query=0; } - | SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; } + | SQL_CACHE_SYM + { + Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; + } | ALL {} ; From 018a9b70580dcb3ba2080c3b20c438f000ecc178 Mon Sep 17 00:00:00 2001 From: "serg@serg.mysql.com" <> Date: Mon, 17 Mar 2003 19:39:01 +0100 Subject: [PATCH 002/188] crash fix --- client/mysqldump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index d7d54a13c57..02e6186dbe8 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1500,7 +1500,7 @@ int main(int argc, char **argv) else { row = mysql_fetch_row(master); - if(row[0] && row[1]) { + if(row && row[0] && row[1]) { fprintf(md_result_file, "\n--\n-- Position to start replication from\n--\n\n"); fprintf(md_result_file, From 8d5fae86c7304d57bb7b3be5d301418809e12abc Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 19 Mar 2003 16:10:16 +0200 Subject: [PATCH 003/188] A fix for SHOW PROCESSLIST bug --- sql/sql_show.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 95197ecfc4b..23e5049636a 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1064,10 +1064,10 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) { if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1))) my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN, - "%s:%u", thd->host_or_ip, tmp->peer_port); + "%s:%u", tmp->host_or_ip, tmp->peer_port); } else - thd_info->host= thd->strdup(thd->host_or_ip); + thd_info->host= thd->strdup(tmp->host_or_ip); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; From f2b5f00563d5e68c0a3a980071b586deb63ac6a0 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 19 Mar 2003 17:25:59 +0200 Subject: [PATCH 004/188] A fix for the bug with setting of SQL_BIG_SELECTS option. --- sql/set_var.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/set_var.cc b/sql/set_var.cc index 9ae813e1c51..172939ce981 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -239,7 +239,7 @@ static sys_var_thd_bit sys_sql_big_tables("sql_big_tables", #endif static sys_var_thd_bit sys_big_selects("sql_big_selects", set_option_bit, - OPTION_BIG_TABLES); + OPTION_BIG_SELECTS); static sys_var_thd_bit sys_log_off("sql_log_off", set_option_bit, OPTION_LOG_OFF); From 8757ab32794b2b9842ab22510c485fed5f650507 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 19 Mar 2003 17:46:36 +0200 Subject: [PATCH 005/188] Fixed a bug when SELECT @@inexistent_variable caused the error in client - server protocl due to two net_printf() being sent to the client. --- sql/item_func.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index b6a64155ab5..15018085146 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2382,10 +2382,7 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name) char buff[MAX_SYS_VAR_LENGTH+3+8], *pos; if (!(var= find_sys_var(name.str))) - { - net_printf(&thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name.str); return 0; - } if (!(item=var->item(thd, var_type))) return 0; // Impossible thd->safe_to_cache_query=0; From e6a724fd8310ad14c08eff1a60517dbffaaa1cc9 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Thu, 20 Mar 2003 19:04:30 +0200 Subject: [PATCH 006/188] A fix for a bug when INSERT is attempted into a table with a BLOB and many NULL columns. It could be ported back to 3.23 too .... --- myisam/mi_dynrec.c | 2 +- mysql-test/r/myisam.result | 4 ++-- mysql-test/t/myisam.test | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index d33aa2718b7..bfee176807e 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -62,7 +62,7 @@ int _mi_write_blob_record(MI_INFO *info, const byte *record) extra= (ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+ MI_DYN_DELETE_BLOCK_HEADER+1); - reclength= (info->s->base.pack_reclength+ + reclength= (info->s->base.pack_reclength+ info->s->base.pack_bits+ _my_calc_total_blob_length(info,record)+ extra); #ifdef NOT_USED /* We now support big rows */ if (reclength > MI_DYN_MAX_ROW_LENGTH) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 3a3558eedcb..9a653aff99e 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -246,7 +246,7 @@ int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974 int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982 int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990 int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998 -int, i999 int, i1000 int) row_format=dynamic; +int, i999 int, i1000 int, b blob) row_format=dynamic; insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -285,7 +285,7 @@ insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "Sergei"); drop table if exists t1; CREATE TABLE `t1` ( `post_id` mediumint(8) unsigned NOT NULL auto_increment, diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index c96a21e73dd..2ae3c27f699 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -252,7 +252,7 @@ int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974 int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982 int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990 int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998 -int, i999 int, i1000 int) row_format=dynamic; +int, i999 int, i1000 int, b blob) row_format=dynamic; insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -291,7 +291,7 @@ insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "Sergei"); drop table if exists t1; # From 15f26dd560d2a45db232f320e03407d766b1ae28 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Thu, 20 Mar 2003 19:13:45 +0200 Subject: [PATCH 007/188] A test case for bug in record #166 : select @@not_a_variable closes the connection --- mysql-test/r/variables.result | 5 +++++ mysql-test/t/variables.test | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index ed477a8519b..1cc48d2aeac 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -335,3 +335,8 @@ Table Op Msg_type Msg_text test.t1 check status OK test.t2 check status OK drop table t1,t2; +select @@xxxxxxxxxx; +Unknown system variable 'xxxxxxxxxx' +select 1; +1 +1 diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 5863cb97d57..639a28edd38 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -241,3 +241,10 @@ select * from t2 where a=3; check table t1,t2; drop table t1,t2; +# +# error conditions +# + +--error 1193 +select @@xxxxxxxxxx; +select 1; From 8c36b3b4ec667c8bf8e9b331e2ab7b83c30d6eb2 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Mon, 24 Mar 2003 22:52:46 +0200 Subject: [PATCH 008/188] A fix for bug #176 code cleanup --- mysql-test/r/having.result | 7 +++++++ mysql-test/t/having.test | 4 ++++ sql/item.cc | 1 + sql/item_func.cc | 37 ++++++++++++++++++++----------------- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index a33ce457176..f113eb6ed49 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -63,3 +63,10 @@ Fld1 max(Fld2) 1 20 3 50 drop table t1; +create table t1 (id int not null, qty int not null); +insert into t1 values (1,2),(1,3),(2,4),(2,5); +select id, sum(qty) as sqty from t1 group by id having sqty>2; +id sqty +1 5 +2 9 +drop table t1; diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test index 8dd7606d82b..fd972fea1ad 100644 --- a/mysql-test/t/having.test +++ b/mysql-test/t/having.test @@ -60,3 +60,7 @@ select Fld1, max(Fld2) from t1 group by Fld1 having max(Fld2) is not null; select Fld1, max(Fld2) from t1 group by Fld1 having avg(Fld2) is not null; select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null; drop table t1; +create table t1 (id int not null, qty int not null); +insert into t1 values (1,2),(1,3),(2,4),(2,5); +select id, sum(qty) as sqty from t1 group by id having sqty>2; +drop table t1; diff --git a/sql/item.cc b/sql/item.cc index 0046f53c6fb..4fefae7358f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -665,6 +665,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables) maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; binary= (*ref)->binary; + with_sum_func= (*ref)->with_sum_func; } return 0; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 15018085146..6c23b0aa424 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -70,15 +70,16 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables) { // Print purify happy for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - if ((*arg)->fix_fields(thd,tables)) + Item *item=*arg; + if (item->fix_fields(thd,tables)) return 1; /* purecov: inspected */ - if ((*arg)->maybe_null) + if (item->maybe_null) maybe_null=1; - if ((*arg)->binary) + if (item->binary) binary=1; - with_sum_func= with_sum_func || (*arg)->with_sum_func; - used_tables_cache|=(*arg)->used_tables(); - const_item_cache&= (*arg)->const_item(); + with_sum_func= with_sum_func || item->with_sum_func; + used_tables_cache|=item->used_tables(); + const_item_cache&= item->const_item(); } } fix_length_and_dec(); @@ -91,12 +92,13 @@ void Item_func::split_sum_func(List &fields) Item **arg,**arg_end; for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM) - (*arg)->split_sum_func(fields); - else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM) + Item *item=*arg; + if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) + item->split_sum_func(fields); + else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) { fields.push_front(*arg); - *arg=new Item_ref((Item**) fields.head_ref(),0,(*arg)->name); + *arg=new Item_ref((Item**) fields.head_ref(),0,item->name); } } } @@ -1231,16 +1233,17 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, arg != arg_end ; arg++,i++) { - if ((*arg)->fix_fields(thd,tables)) + Item *item=*arg; + if (item->fix_fields(thd,tables)) return 1; - if ((*arg)->binary) + if (item->binary) func->binary=1; - if ((*arg)->maybe_null) + if (item->maybe_null) func->maybe_null=1; - func->with_sum_func= func->with_sum_func || (*arg)->with_sum_func; - used_tables_cache|=(*arg)->used_tables(); - const_item_cache&=(*arg)->const_item(); - f_args.arg_type[i]=(*arg)->result_type(); + func->with_sum_func= func->with_sum_func || item->with_sum_func; + used_tables_cache|=item->used_tables(); + const_item_cache&=item->const_item(); + f_args.arg_type[i]=item->result_type(); } if (!(buffers=new String[arg_count]) || !(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) || From 4d87fd034621da8a5ba192d88384c7df12ec378a Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Mon, 31 Mar 2003 09:49:09 +0300 Subject: [PATCH 009/188] fixed bug 209 (SQL_SELECT_LIMIT and query cache incompatibility) --- mysql-test/r/query_cache.result | 18 ++++++++++++++++++ mysql-test/t/query_cache.test | 17 ++++++++++++++--- sql/sql_cache.cc | 25 +++++++++++++++---------- sql/sql_parse.cc | 3 ++- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 936bbf30006..a55e05578e0 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -581,3 +581,21 @@ show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 drop table t1; +create table t1 (a int); +insert into t1 values (1),(2); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +select * from t1; +a +1 +2 +SET OPTION SQL_SELECT_LIMIT=1; +select * from t1; +a +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +SET OPTION SQL_SELECT_LIMIT=DEFAULT; +drop table t1; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 23950ce9caa..33f226f9253 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -401,7 +401,6 @@ select * from t1 where id=2; # # Load data invalidation test # - create table t1 (word char(20) not null); select * from t1; show status like "Qcache_queries_in_cache"; @@ -412,7 +411,6 @@ drop table t1; # # INTO OUTFILE/DUMPFILE test # - drop table if exists t1; create table t1 (a int); insert into t1 values (1),(2),(3); @@ -420,4 +418,17 @@ show status like "Qcache_queries_in_cache"; select * from t1 into outfile "query_caceh.out.file"; select * from t1 limit 1 into dumpfile "query_cache.dump.file"; show status like "Qcache_queries_in_cache"; -drop table t1; \ No newline at end of file +drop table t1; + +# +# test of SQL_SELECT_LIMIT +# +create table t1 (a int); +insert into t1 values (1),(2); +show status like "Qcache_queries_in_cache"; +select * from t1; +SET OPTION SQL_SELECT_LIMIT=1; +select * from t1; +show status like "Qcache_queries_in_cache"; +SET OPTION SQL_SELECT_LIMIT=DEFAULT; +drop table t1; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index ee62d7b16ed..59430d6a486 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -743,11 +743,11 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) if (query_cache_size == 0) DBUG_VOID_RETURN; - if ((local_tables = is_cacheable(thd, thd->query_length, + if ((local_tables= is_cacheable(thd, thd->query_length, thd->query, &thd->lex, tables_used))) { - NET *net = &thd->net; - byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0); + NET *net= &thd->net; + byte flags= (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0); STRUCT_LOCK(&structure_guard_mutex); if (query_cache_size == 0) @@ -775,8 +775,10 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) flags|= (byte) thd->variables.convert_set->number(); DBUG_ASSERT(thd->variables.convert_set->number() < 128); } - tot_length=thd->query_length+thd->db_length+2; - thd->query[tot_length-1] = (char) flags; + tot_length= thd->query_length+thd->db_length+2+sizeof(ha_rows); + thd->query[tot_length-1]= (char) flags; + memcpy((void *)(thd->query + (tot_length-sizeof(ha_rows)-1)), + (const void *)&thd->variables.select_limit, sizeof(ha_rows)); /* Check if another thread is processing the same query? */ Query_cache_block *competitor = (Query_cache_block *) @@ -910,7 +912,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) } Query_cache_block *query_block; - tot_length=query_length+thd->db_length+2; + tot_length= query_length+thd->db_length+2+sizeof(ha_rows); if (thd->db_length) { memcpy(sql+query_length+1, thd->db, thd->db_length); @@ -926,15 +928,18 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) Most significant bit - CLIENT_LONG_FLAG, Other - charset number (0 no charset convertion) */ - flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0); + flags= (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0); if (thd->variables.convert_set != 0) { - flags |= (byte) thd->variables.convert_set->number(); + flags|= (byte) thd->variables.convert_set->number(); DBUG_ASSERT(thd->variables.convert_set->number() < 128); } - sql[tot_length-1] = (char) flags; - query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql, + sql[tot_length-1]= (char) flags; + memcpy((void *)(sql + (tot_length-sizeof(ha_rows)-1)), + (const void *)&thd->variables.select_limit, sizeof(ha_rows)); + query_block= (Query_cache_block *) hash_search(&queries, (byte*) sql, tot_length); + /* Quick abort on unlocked data */ if (query_block == 0 || query_block->query()->result() == 0 || diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1bb1fd9d39a..9e222c4f944 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1029,7 +1029,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* We must allocate some extra memory for query cache */ if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), packet_length, - thd->db_length+2))) + thd->db_length+2+ + sizeof(ha_rows)))) break; thd->query[packet_length]=0; thd->packet.shrink(thd->variables.net_buffer_length);// Reclaim some memory From c588cf68892ee0dfbffaf4df6b76deca1da92d06 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 2 Apr 2003 17:05:34 +0300 Subject: [PATCH 010/188] A fix for a bug in multi-table updates which was always caused whenever a temporary MyISAM table had to be created from HEAP table. --- mysql-test/r/multi_update.result | 8 ++++++++ mysql-test/t/multi_update-master.opt | 1 + mysql-test/t/multi_update.test | 8 ++++++++ sql/sql_update.cc | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 mysql-test/t/multi_update-master.opt diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 0f3644f15bc..75c22caaa72 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -310,3 +310,11 @@ a b 8 3 9 3 drop table t1,t2; +CREATE TABLE t3 ( KEY1 varchar(50) NOT NULL default '', PARAM_CORR_DISTANCE_RUSH double default NULL, PARAM_CORR_DISTANCE_GEM double default NULL, PARAM_AVG_TARE double default NULL, PARAM_AVG_NB_DAYS double default NULL, PARAM_DEFAULT_PROP_GEM_SRVC varchar(50) default NULL, PARAM_DEFAULT_PROP_GEM_NO_ETIK varchar(50) default NULL, PARAM_SCENARIO_COSTS varchar(50) default NULL, PARAM_DEFAULT_WAGON_COST double default NULL, tmp int(11) default NULL, PRIMARY KEY (KEY1)) TYPE=MyISAM; +INSERT INTO t3 VALUES ('A',1,1,22,3.2,'R','R','BASE2',0.24,NULL); +create table t1 (A varchar(1)); +insert into t1 values ("A") ,("B"),("C"),("D"); +create table t2(Z varchar(15)); +insert into t2(Z) select concat(a.a,b.a,c.a,d.a) from t1 as a, t1 as b, t1 as c, t1 as d; +update t2,t3 set Z =param_scenario_costs; +drop table t1,t2,t3; diff --git a/mysql-test/t/multi_update-master.opt b/mysql-test/t/multi_update-master.opt new file mode 100644 index 00000000000..9f1a29461ff --- /dev/null +++ b/mysql-test/t/multi_update-master.opt @@ -0,0 +1 @@ +--set-variable=tmp_table_size=1024 diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index d5543f69bd5..04f3508e078 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -252,3 +252,11 @@ select * from t1; select * from t2; drop table t1,t2; +CREATE TABLE t3 ( KEY1 varchar(50) NOT NULL default '', PARAM_CORR_DISTANCE_RUSH double default NULL, PARAM_CORR_DISTANCE_GEM double default NULL, PARAM_AVG_TARE double default NULL, PARAM_AVG_NB_DAYS double default NULL, PARAM_DEFAULT_PROP_GEM_SRVC varchar(50) default NULL, PARAM_DEFAULT_PROP_GEM_NO_ETIK varchar(50) default NULL, PARAM_SCENARIO_COSTS varchar(50) default NULL, PARAM_DEFAULT_WAGON_COST double default NULL, tmp int(11) default NULL, PRIMARY KEY (KEY1)) TYPE=MyISAM; +INSERT INTO t3 VALUES ('A',1,1,22,3.2,'R','R','BASE2',0.24,NULL); +create table t1 (A varchar(1)); +insert into t1 values ("A") ,("B"),("C"),("D"); +create table t2(Z varchar(15)); +insert into t2(Z) select concat(a.a,b.a,c.a,d.a) from t1 as a, t1 as b, t1 as c, t1 as d; +update t2,t3 set Z =param_scenario_costs; +drop table t1,t2,t3; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 709f88726de..59c766e7a9f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -741,7 +741,7 @@ bool multi_update::send_data(List ¬_used_values) (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE)) { - if (create_myisam_from_heap(table, tmp_table_param + offset, error, 1)) + if (create_myisam_from_heap(tmp_table, tmp_table_param + offset, error, 1)) { do_update=0; DBUG_RETURN(1); // Not a table_is_full error From 14d961a033be864c292f0b0a3e10c8817d7cc9b8 Mon Sep 17 00:00:00 2001 From: "walrus@mysql.com" <> Date: Thu, 3 Apr 2003 21:51:14 +0600 Subject: [PATCH 011/188] test-transactions.sh: correct misprint in the test_update --- sql-bench/test-transactions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-bench/test-transactions.sh b/sql-bench/test-transactions.sh index b081b89fb69..8f92633524f 100644 --- a/sql-bench/test-transactions.sh +++ b/sql-bench/test-transactions.sh @@ -252,7 +252,7 @@ sub test_update for ($id=0 ; $id < $opt_loop_count ; $id++) { - do_query($dbh,"update bench1 set updated=1 where idn=$id"); + do_query($dbh,"update $table set updated=1 where idn=$id"); } $dbh->commit if (!$auto_commit); From 75015595b1c7cbdff9bf5578562018e0bb1960d8 Mon Sep 17 00:00:00 2001 From: "jani@hynda.(none)" <> Date: Thu, 3 Apr 2003 19:55:37 +0300 Subject: [PATCH 012/188] Fixed a bug when printing error messages. stdout and stderr were mixed wrongly sometimes. --- client/mysql.cc | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 377f4f08f63..d7aa0d1404d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2405,31 +2405,32 @@ select_limit, max_join_size); static int put_info(const char *str,INFO_TYPE info_type,uint error) { + FILE *file= (info_type == INFO_ERROR ? stderr : stdout); static int inited=0; if (status.batch) { if (info_type == INFO_ERROR) { - (void) fflush(stdout); - fprintf(stderr,"ERROR"); + (void) fflush(file); + fprintf(file,"ERROR"); if (error) - (void) fprintf(stderr," %d",error); + (void) fprintf(file," %d",error); if (status.query_start_line && line_numbers) { - (void) fprintf(stderr," at line %lu",status.query_start_line); + (void) fprintf(file," at line %lu",status.query_start_line); if (status.file_name) - (void) fprintf(stderr," in file: '%s'", status.file_name); + (void) fprintf(file," in file: '%s'", status.file_name); } - (void) fprintf(stderr,": %s\n",str); - (void) fflush(stderr); + (void) fprintf(file,": %s\n",str); + (void) fflush(file); if (!ignore_errors) return 1; } else if (info_type == INFO_RESULT && verbose > 1) - tee_puts(str, stdout); + tee_puts(str, file); if (unbuffered) - fflush(stdout); + fflush(file); return info_type == INFO_ERROR ? -1 : 0; } if (!opt_silent || info_type == INFO_ERROR) @@ -2447,17 +2448,17 @@ put_info(const char *str,INFO_TYPE info_type,uint error) putchar('\007'); /* This should make a bell */ vidattr(A_STANDOUT); if (error) - (void) tee_fprintf(stderr, "ERROR %d: ", error); + (void) tee_fprintf(file, "ERROR %d: ", error); else - tee_puts("ERROR: ", stdout); + tee_puts("ERROR: ", file); } else vidattr(A_BOLD); - (void) tee_puts(str, stdout); + (void) tee_puts(str, file); vidattr(A_NORMAL); } if (unbuffered) - fflush(stdout); + fflush(file); return info_type == INFO_ERROR ? -1 : 0; } From 10957fb0f358d534b1121433eea0c4f4064fdd76 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Thu, 3 Apr 2003 20:24:15 +0300 Subject: [PATCH 013/188] One test case, one bug fix and one new feature --- mysql-test/r/innodb.result | 9 +++++++++ mysql-test/t/innodb.test | 8 ++++++++ sql/sql_show.cc | 5 ++++- sql/sql_table.cc | 24 +++++++++++++++++------- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 48db5412da7..b12466983f8 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1201,3 +1201,12 @@ a b 8 5 9 5 drop table t1,t2; +CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) TYPE=MyISAM; +CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) TYPE=InnoDB; +SET AUTOCOMMIT=0; +INSERT INTO t1 ( B_ID ) VALUES ( 1 ); +INSERT INTO t2 ( NEXT_T ) VALUES ( 1 ); +ROLLBACK; +SELECT * FROM t1; +B_ID +drop table t1,t2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 2f7285e7898..9d614e8d163 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -797,3 +797,11 @@ select * from t1; select * from t2; drop table t1,t2; +CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) TYPE=MyISAM; +CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) TYPE=InnoDB; +SET AUTOCOMMIT=0; +INSERT INTO t1 ( B_ID ) VALUES ( 1 ); +INSERT INTO t2 ( NEXT_T ) VALUES ( 1 ); +ROLLBACK; +SELECT * FROM t1; +drop table t1,t2; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6e1cf2e8217..4d6f9d3490e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -728,7 +728,10 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) net_store_data(packet,convert,(const char*) pos); net_store_data(packet,convert,table->file->index_type(i)); /* Comment */ - net_store_data(packet,convert,""); + if (!(table->keys_in_use & ((key_map) 1 << i))) + net_store_data(packet,convert,"disabled",8); + else + net_store_data(packet,convert,""); if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) DBUG_RETURN(1); /* purecov: inspected */ } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0cdb0a7ff48..8cec738edb0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -912,12 +912,9 @@ mysql_rename_table(enum db_type base, Win32 clients must also have a WRITE LOCK on the table ! */ -bool close_cached_table(THD *thd,TABLE *table) +static void safe_remove_from_cache(THD *thd,TABLE *table) { - bool result=0; - DBUG_ENTER("close_cached_table"); - safe_mutex_assert_owner(&LOCK_open); - + DBUG_ENTER("safe_remove_from_cache"); if (table) { DBUG_PRINT("enter",("table: %s", table->real_name)); @@ -940,7 +937,18 @@ bool close_cached_table(THD *thd,TABLE *table) #endif /* When lock on LOCK_open is freed other threads can continue */ pthread_cond_broadcast(&COND_refresh); + } + DBUG_VOID_RETURN; +} +bool close_cached_table(THD *thd,TABLE *table) +{ + DBUG_ENTER("close_cached_table"); + safe_mutex_assert_owner(&LOCK_open); + + if (table) + { + safe_remove_from_cache(thd,table); /* Close lock if this is not got with LOCK TABLES */ if (thd->lock) { @@ -949,7 +957,7 @@ bool close_cached_table(THD *thd,TABLE *table) /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ thd->open_tables=unlink_open_table(thd,thd->open_tables,table); } - DBUG_RETURN(result); + DBUG_RETURN(0); } static int send_check_errmsg(THD* thd, TABLE_LIST* table, @@ -1456,9 +1464,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, case LEAVE_AS_IS: break; case ENABLE: - error=table->file->activate_all_index(thd); + safe_remove_from_cache(thd,table); + error= table->file->activate_all_index(thd); break; case DISABLE: + safe_remove_from_cache(thd,table); table->file->deactivate_non_unique_index(HA_POS_ERROR); break; } From 19ef95be2a3b39058625613389caf2f07341f515 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Thu, 3 Apr 2003 21:17:53 +0300 Subject: [PATCH 014/188] test case for displaying and correct functioning of ALTER TABLE ENABLE / DISABLE KEYS --- mysql-test/r/alter_table.result | 38 +++++++++++++++++++++++++++++++++ mysql-test/t/alter_table.test | 2 ++ 2 files changed, 40 insertions(+) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 096ef2fd79e..670ed172c76 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -92,6 +92,25 @@ key (n2, n3, n4, n1), key (n3, n4, n1, n2), key (n4, n1, n2, n3) ); alter table t1 disable keys; +show keys from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 n1 1 n1 A 0 NULL NULL BTREE +t1 1 n1_2 1 n1 A NULL NULL NULL BTREE disabled +t1 1 n1_2 2 n2 A NULL NULL NULL YES BTREE disabled +t1 1 n1_2 3 n3 A NULL NULL NULL YES BTREE disabled +t1 1 n1_2 4 n4 A NULL NULL NULL YES BTREE disabled +t1 1 n2 1 n2 A NULL NULL NULL YES BTREE disabled +t1 1 n2 2 n3 A NULL NULL NULL YES BTREE disabled +t1 1 n2 3 n4 A NULL NULL NULL YES BTREE disabled +t1 1 n2 4 n1 A NULL NULL NULL BTREE disabled +t1 1 n3 1 n3 A NULL NULL NULL YES BTREE disabled +t1 1 n3 2 n4 A NULL NULL NULL YES BTREE disabled +t1 1 n3 3 n1 A NULL NULL NULL BTREE disabled +t1 1 n3 4 n2 A NULL NULL NULL YES BTREE disabled +t1 1 n4 1 n4 A NULL NULL NULL YES BTREE disabled +t1 1 n4 2 n1 A NULL NULL NULL BTREE disabled +t1 1 n4 3 n2 A NULL NULL NULL YES BTREE disabled +t1 1 n4 4 n3 A NULL NULL NULL YES BTREE disabled insert into t1 values(10,RAND()*1000,RAND()*1000,RAND()); insert into t1 values(9,RAND()*1000,RAND()*1000,RAND()); insert into t1 values(8,RAND()*1000,RAND()*1000,RAND()); @@ -103,6 +122,25 @@ insert into t1 values(3,RAND()*1000,RAND()*1000,RAND()); insert into t1 values(2,RAND()*1000,RAND()*1000,RAND()); insert into t1 values(1,RAND()*1000,RAND()*1000,RAND()); alter table t1 enable keys; +show keys from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 n1 1 n1 A 10 NULL NULL BTREE +t1 1 n1_2 1 n1 A 10 NULL NULL BTREE +t1 1 n1_2 2 n2 A 10 NULL NULL YES BTREE +t1 1 n1_2 3 n3 A 10 NULL NULL YES BTREE +t1 1 n1_2 4 n4 A 10 NULL NULL YES BTREE +t1 1 n2 1 n2 A 10 NULL NULL YES BTREE +t1 1 n2 2 n3 A 10 NULL NULL YES BTREE +t1 1 n2 3 n4 A 10 NULL NULL YES BTREE +t1 1 n2 4 n1 A 10 NULL NULL BTREE +t1 1 n3 1 n3 A 10 NULL NULL YES BTREE +t1 1 n3 2 n4 A 10 NULL NULL YES BTREE +t1 1 n3 3 n1 A 10 NULL NULL BTREE +t1 1 n3 4 n2 A 10 NULL NULL YES BTREE +t1 1 n4 1 n4 A 10 NULL NULL YES BTREE +t1 1 n4 2 n1 A 10 NULL NULL BTREE +t1 1 n4 3 n2 A 10 NULL NULL YES BTREE +t1 1 n4 4 n3 A 10 NULL NULL YES BTREE drop table t1; create table t1 (i int unsigned not null auto_increment primary key); insert into t1 values (null),(null),(null),(null); diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 1c3987e2a31..d32c554aec8 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -86,6 +86,7 @@ create table t1 (n1 int not null, n2 int, n3 int, n4 float, key (n3, n4, n1, n2), key (n4, n1, n2, n3) ); alter table t1 disable keys; +show keys from t1; #let $1=10000; let $1=10; while ($1) @@ -94,6 +95,7 @@ while ($1) dec $1; } alter table t1 enable keys; +show keys from t1; drop table t1; # From 8aa753299082158d9f13843ee1ccb92078da19a5 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 3 Apr 2003 21:19:13 +0300 Subject: [PATCH 015/188] log.cc: Fix bug number 224: do not call ha_report_binlog_offset_and_commit() when a MyISAM table is updated; this also makes CREATE TABLE not to commit an InnoDB transaction, even when binlogging is enabled --- sql/log.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index 1e903613300..a2ed2b05d4e 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1120,9 +1120,16 @@ bool MYSQL_LOG::write(Log_event* event_info) the table handler commit here, protected by the LOCK_log mutex, because otherwise the transactions may end up in a different order in the table handler log! + + Note that we will NOT call ha_report_binlog_offset_and_commit() if + there are binlog events cached in the transaction cache. That is + because then the log event which we write to the binlog here is + not a transactional event. In versions < 4.0.13 before this fix this + caused an InnoDB transaction to be committed if in the middle there + was a MyISAM event! */ - if (file == &log_file) + if (file == &log_file && !my_b_tell(&thd->transaction.trans_log)) { /* LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog From 8611c34e5e08a5c92e84deaf86b74e5af448f7d0 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Thu, 3 Apr 2003 20:19:13 +0200 Subject: [PATCH 016/188] Explicit message to warn that logging (e.g. binary) is permanently turned off because of writing problems (such message would have been useful during a recent support task). --- sql/log.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index 1e903613300..2106cd9c3db 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -310,7 +310,10 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, DBUG_RETURN(0); err: - sql_print_error("Could not use %s for logging (error %d)", log_name, errno); + sql_print_error("Could not use %s for logging (error %d). \ +Turning logging off for the whole duration of the MySQL server process. \ +To turn it on again: fix the cause, \ +shutdown the MySQL server and restart it.", log_name, errno); if (file >= 0) my_close(file,MYF(0)); if (index_file_nr >= 0) From f33c6e7c83d48945c9f40cdb795edff7b97605e3 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Thu, 3 Apr 2003 20:19:14 +0200 Subject: [PATCH 017/188] More honest --master-ssl* options description. As these do nothing yet, better say it and see no traffic on bugs@ and support@. --- sql/mysqld.cc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bc5334ce674..6d86346455a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3379,23 +3379,27 @@ struct my_option my_long_options[] = (gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl", OPT_MASTER_SSL, - "Turn SSL on for replication. Be warned that is this is a relatively new feature.", + "Planned to enable the slave to connect to the master using SSL. Does nothing yet.", (gptr*) &master_ssl, (gptr*) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-key", OPT_MASTER_SSL_KEY, - "Master SSL keyfile name. Only applies if you have enabled master-ssl.", + "Master SSL keyfile name. Only applies if you have enabled master-ssl. Does \ +nothing yet.", (gptr*) &master_ssl_key, (gptr*) &master_ssl_key, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-cert", OPT_MASTER_SSL_CERT, - "Master SSL certificate file name. Only applies if you have enabled master-ssl.", + "Master SSL certificate file name. Only applies if you have enabled \ +master-ssl. Does nothing yet.", (gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-capath", OPT_MASTER_SSL_CAPATH, - "Master SSL CA path. Only applies if you have enabled master-ssl.", + "Master SSL CA path. Only applies if you have enabled master-ssl. \ +Does nothing yet.", (gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER, - "Master SSL cipher. Only applies if you have enabled master-ssl.", + "Master SSL cipher. Only applies if you have enabled master-ssl. \ +Does nothing yet.", (gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"myisam-recover", OPT_MYISAM_RECOVER, From cb68a2c7b168411d3345846cb7e52432e58c0d64 Mon Sep 17 00:00:00 2001 From: "walrus@mysql.com" <> Date: Fri, 4 Apr 2003 02:54:07 +0600 Subject: [PATCH 018/188] crash-me.sh: add sorted_group_by parameter --- sql-bench/crash-me.sh | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh index 61468d69fb1..ff649acdae4 100644 --- a/sql-bench/crash-me.sh +++ b/sql-bench/crash-me.sh @@ -2734,6 +2734,51 @@ assert("drop table crash_me_n $drop_attr"); +$key = 'sorted_group_by'; +$prompt = 'Group by always sorted'; +if (!defined($limits{$key})) +{ + save_incomplete($key,$prompt); + print "$prompt="; + safe_query_l($key,[ + "create table crash_me_t1 (a int not null, b int not null)", + "insert into crash_me_t1 values (1,1)", + "insert into crash_me_t1 values (1,2)", + "insert into crash_me_t1 values (3,1)", + "insert into crash_me_t1 values (3,2)", + "insert into crash_me_t1 values (2,2)", + "insert into crash_me_t1 values (2,1)", + "create table crash_me_t2 (a int not null, b int not null)", + "create index crash_me_t2_ind on crash_me_t2 (a)", + "insert into crash_me_t2 values (1,3)", + "insert into crash_me_t2 values (3,1)", + "insert into crash_me_t2 values (2,2)", + "insert into crash_me_t2 values (1,1)"]); + + my $bigqry = "select crash_me_t1.a,crash_me_t2.b from ". + "crash_me_t1,crash_me_t2 where crash_me_t1.a=crash_me_t2.a ". + "group by crash_me_t1.a,crash_me_t2.b"; + + my $limit='no'; + my $rs = get_recordset($key,$bigqry); + print_recordset($key,$rs); + if ( defined ($rs)) { + if (compare_recordset($key,$rs,[[1,1],[1,3],[2,2],[3,1]]) eq 0) + { + $limit='yes' + } + } else { + add_log($key,"error: ".$DBI::errstr); + } + + print "$limit\n"; + safe_query_l($key,["drop table crash_me_t1", + "drop table crash_me_t2"]); + save_config_data($key,$limit,$prompt); + +} else { + print "$prompt=$limits{$key} (cashed)\n"; +} # From f237ae457a0adc6daaeebb49293da435ef673076 Mon Sep 17 00:00:00 2001 From: "vva@eagle.mysql.r18.ru" <> Date: Thu, 3 Apr 2003 20:26:13 -0400 Subject: [PATCH 019/188] fux bug #183 --- BitKeeper/etc/logging_ok | 1 + sql/slave.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a6699f7c515..705b336440b 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -35,5 +35,6 @@ serg@build.mysql2.com serg@serg.mysql.com serg@sergbook.mysql.com sinisa@rhols221.adsl.netsonic.fi +vva@eagle.mysql.r18.ru walrus@mysql.com zak@balfor.local diff --git a/sql/slave.cc b/sql/slave.cc index ac65bd2bdc3..acc443b2296 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1139,7 +1139,7 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) List fields; lev->set_fields(fields); - thd->slave_proxy_id = thd->thread_id; + thd->slave_proxy_id = thread_id; thd->net.vio = net->vio; // mysql_load will use thd->net to read the file thd->net.pkt_nr = net->pkt_nr; From 17d1a669ed4866bf113984f05f2eecd6a8f28d3f Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 4 Apr 2003 10:14:06 +0300 Subject: [PATCH 020/188] log.cc: Fix crash in previous bug fix log.cc reported by Rob Lyon if --skip-innodb is specified --- sql/log.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index 2cb2e37be08..8a5aba5cd34 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1132,7 +1132,8 @@ bool MYSQL_LOG::write(Log_event* event_info) was a MyISAM event! */ - if (file == &log_file && !my_b_tell(&thd->transaction.trans_log)) + if (file == &log_file && opt_using_transactions + && !my_b_tell(&thd->transaction.trans_log)) { /* LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog From 9b0266a037ea926307765cbda39d2af4b2504b49 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Fri, 4 Apr 2003 17:43:54 +0200 Subject: [PATCH 021/188] Documented undocumented replication options, now that the manual is up-to-date. --- sql/mysqld.cc | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6d86346455a..4ae248acb67 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3321,7 +3321,7 @@ struct my_option my_long_options[] = (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"log-bin", OPT_BIN_LOG, - "Log queries in new binary format (for replication)", + "Log update queries in binary format", (gptr*) &opt_bin_logname, (gptr*) &opt_bin_logname, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-bin-index", OPT_BIN_LOG_INDEX, @@ -3375,7 +3375,8 @@ struct my_option my_long_options[] = (gptr*) &master_retry_count, (gptr*) &master_retry_count, 0, GET_ULONG, REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0}, {"master-info-file", OPT_MASTER_INFO_FILE, - "The location of the file that remembers where we left off on the master during the replication process. The default is `master.info' in the data directory. You should not need to change this.", + "The location and name of the file that remembers the master and where the I/O replication \ +thread is in the master's binlogs.", (gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl", OPT_MASTER_SSL, @@ -3498,10 +3499,13 @@ Does nothing yet.", {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented", (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"relay-log", OPT_RELAY_LOG, "Undocumented", + {"relay-log", OPT_RELAY_LOG, + "The location and name to use for relay logs", (gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"relay-log-index", OPT_RELAY_LOG_INDEX, "Undocumented", + {"relay-log-index", OPT_RELAY_LOG_INDEX, + "The location and name to use for the file that keeps a list of the last \ +relay logs", (gptr*) &opt_relaylog_index_name, (gptr*) &opt_relaylog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).", @@ -3563,10 +3567,14 @@ Does nothing yet.", {"skip-thread-priority", OPT_SKIP_PRIOR, "Don't give threads different priorities.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, "Undocumented", + {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, + "The location and name of the file that remembers where the SQL replication \ +thread is in the relay logs", (gptr*) &relay_log_info_file, (gptr*) &relay_log_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, "Undocumented", + {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, + "The location where the slave should put its temporary files when \ +replicating a LOAD DATA INFILE command", (gptr*) &slave_load_tmpdir, (gptr*) &slave_load_tmpdir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS, @@ -3892,7 +3900,7 @@ Does nothing yet.", (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0}, {"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT, - "Max space to use for all relay logs", + "Maximum space to use for all relay logs", (gptr*) &relay_log_space_limit, (gptr*) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L, (longlong) ULONG_MAX, 0, 1, 0}, From cc3ddf4b2d206c6389c441a45037ff5bbfc84a2b Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 7 Apr 2003 19:05:00 +0200 Subject: [PATCH 022/188] - don't add separate debug symbol file to the binary distribution, if it's built with debugging enabled or not stripped (save disk space) --- Build-tools/Do-compile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index add2ac86c81..b83eadcac63 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -276,7 +276,11 @@ if ($opt_stage <= 3) my $flags= ""; log_timestamp(); log_system("rm -fr mysql-3* mysql-4* $pwd/$host/*.tar.gz"); - log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat"); + # No need to add the debug symbols, if the binaries are not stripped (saves space) + unless ($opt_with_debug || $opt_no_strip) + { + log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat"); + } $flags.= "--no-strip" if ($opt_no_strip || $opt_with_debug); check_system("scripts/make_binary_distribution --tmp=$opt_tmp --suffix=$opt_suffix $flags",".tar.gz created"); From 9f6aa117694308387f13fd9e9d93339c9b5dce19 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Mon, 7 Apr 2003 21:36:45 +0300 Subject: [PATCH 023/188] Changed innobase_flush_log_at_trx_commit to be 1 as default Fixed problem with not freed thr_alarm() on slave connect --- mysql-test/t/rpl_alter.test | 22 +++++++++++----------- sql/ha_innobase.cc | 2 +- sql/mini_client.cc | 12 +++++------- sql/mysqld.cc | 8 ++++++-- sql/slave.cc | 5 +---- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/mysql-test/t/rpl_alter.test b/mysql-test/t/rpl_alter.test index a65605f703e..61ac55843cf 100644 --- a/mysql-test/t/rpl_alter.test +++ b/mysql-test/t/rpl_alter.test @@ -1,21 +1,21 @@ source include/master-slave.inc; connection master; use test; -drop database if exists d1; -create database d1; -create table d1.t1 ( n int); -alter table d1.t1 add m int; -insert into d1.t1 values (1,2); -create table d1.t2 (n int); -insert into d1.t2 values (45); -rename table d1.t2 to d1.t3, d1.t1 to d1.t2; +drop database if exists test_$1; +create database test_$1; +create table test_$1.t1 ( n int); +alter table test_$1.t1 add m int; +insert into test_$1.t1 values (1,2); +create table test_$1.t2 (n int); +insert into test_$1.t2 values (45); +rename table test_$1.t2 to test_$1.t3, test_$1.t1 to test_$1.t2; save_master_pos; connection slave; sync_with_master; -select * from d1.t2; -select * from d1.t3; +select * from test_$1.t2; +select * from test_$1.t3; connection master; -drop database d1; +drop database test_$1; save_master_pos; connection slave; sync_with_master; diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index c0aea197b1f..b8a794a61a0 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -113,7 +113,7 @@ my_bool innobase_fast_shutdown = TRUE; 2 : write to the log file at each commit, but flush to disk only once per second */ -long innobase_flush_log_at_trx_commit = 0; +long innobase_flush_log_at_trx_commit = 1; /* The following counter is used to convey information to InnoDB about server activity: in selects it is not sensible to call diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 453f27822d9..2c74eb96bf9 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -515,8 +515,6 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, host ? host : "(Null)", db ? db : "(Null)", user ? user : "(Null)")); - thr_alarm_init(&alarmed); - thr_alarm(&alarmed,(uint) net_read_timeout,&alarm_buff); bzero((char*) &mysql->options,sizeof(mysql->options)); net->vio = 0; /* If something goes wrong */ @@ -598,7 +596,11 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, host=LOCAL_HOST; sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); - if ((sock = socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR) + thr_alarm_init(&alarmed); + thr_alarm(&alarmed, net_read_timeout, &alarm_buff); + sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); + thr_end_alarm(&alarmed); + if (sock == SOCKET_ERROR) { net->last_errno=CR_IPSOCK_ERROR; sprintf(net->last_error,ER(net->last_errno),socket_errno); @@ -641,12 +643,8 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, socket_errno,host)); net->last_errno= CR_CONN_HOST_ERROR; sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); - if (thr_alarm_in_use(&alarmed)) - thr_end_alarm(&alarmed); goto error; } - if (thr_alarm_in_use(&alarmed)) - thr_end_alarm(&alarmed); } if (!net->vio || my_net_init(net, net->vio)) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9a227ef5034..a10ad60a3e7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1433,8 +1433,12 @@ static void *signal_hand(void *arg __attribute__((unused))) my_thread_init(); // Init new thread DBUG_ENTER("signal_hand"); - /* Setup alarm handler */ - init_thr_alarm(max_connections+max_insert_delayed_threads); + /* + Setup alarm handler + This should actually be '+ max_number_of_slaves' instead of +10, + but the +10 should be quite safe. + */ + init_thr_alarm(max_connections+max_insert_delayed_threads+10); #if SIGINT != THR_KILL_SIGNAL (void) sigemptyset(&set); // Setup up SIGINT for debug (void) sigaddset(&set,SIGINT); // For debugging diff --git a/sql/slave.cc b/sql/slave.cc index ac65bd2bdc3..cce13c5ea78 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -784,10 +784,7 @@ static int safe_sleep(THD* thd, int sec) */ thr_alarm(&alarmed, 2 * nap_time,&alarm_buff); sleep(nap_time); - // if we wake up before the alarm goes off, hit the button - // so it will not wake up the wife and kids :-) - if (thr_alarm_in_use(&alarmed)) - thr_end_alarm(&alarmed); + thr_end_alarm(&alarmed); if (slave_killed(thd)) return 1; From fa0741c918d0edd1a85e6776ee5863ccaaac9efd Mon Sep 17 00:00:00 2001 From: "hf@deer.mysql.r18.ru" <> Date: Tue, 8 Apr 2003 10:35:13 +0500 Subject: [PATCH 024/188] #244 bugfix (thread stack error message in embedded library) --- sql/mysql_priv.h | 5 +++++ sql/sql_parse.cc | 2 ++ 2 files changed, 7 insertions(+) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c6e205f4729..9617d19caae 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -330,7 +330,12 @@ void mysql_execute_command(void); bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); +#ifndef EMBEDDED_LIBRARY bool check_stack_overrun(THD *thd,char *dummy); +#else +#define check_stack_overrun(A, B) 0 +#endif + bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables); void table_cache_init(void); void table_cache_free(void); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9e222c4f944..0ffdb68a179 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2697,6 +2697,7 @@ static bool check_merge_table_access(THD *thd, char *db, #define used_stack(A,B) (long) (B - A) #endif +#ifndef EMBEDDED_LIBRARY bool check_stack_overrun(THD *thd,char *buf __attribute__((unused))) { long stack_used; @@ -2710,6 +2711,7 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused))) } return 0; } +#endif /* EMBEDDED_LIBRARY */ #define MY_YACC_INIT 1000 // Start with big alloc #define MY_YACC_MAX 32000 // Because of 'short' From cea01eccb876a5ab9ffc5f52a9480484f49f9f1a Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 9 Apr 2003 14:53:20 +0200 Subject: [PATCH 025/188] - don't override CXX if it's already defined --- BUILD/SETUP.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 9a092b84a8f..55b82e38d63 100644 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -71,4 +71,6 @@ else make=make fi -CXX=gcc +if test -z $CXX ; then + CXX=gcc +fi From c7891fe9bc5f82d3ff6cc7e0931ab29b52dfd960 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Wed, 9 Apr 2003 15:16:12 +0200 Subject: [PATCH 026/188] fix for #254 (3.23 master, 4.0 slave. Slave loss temp tables everytime FLUSH LOGS on master). This fix is less bad than the bug, it will cause a problem only maybe if the master dies the hard way (I say maybe because I could not cause a problem, and I don't see how it could happen). --- sql/log_event.cc | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 2040cebf17e..3b499b8d502 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1949,6 +1949,10 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, IMPLEMENTATION - To handle the case where the master died without a stop event, we clean up all temporary tables + locks that we got. + However, we don't clean temporary tables if the master was 3.23 + (this is because a 3.23 master writes a Start_log_event at every + binlog rotation; if we were not careful we would remove temp tables + on the slave when FLUSH LOGS is issued on the master). TODO - Remove all active user locks @@ -1959,13 +1963,18 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, int Start_log_event::exec_event(struct st_relay_log_info* rli) { - /* All temporary tables was deleted on the master */ - close_temporary_tables(thd); - /* - If we have old format, load_tmpdir is cleaned up by the I/O thread - */ if (!rli->mi->old_format) + { + /* + If 4.0 master, all temporary tables have been deleted on the master; + if 3.23 master, this is far from sure. + */ + close_temporary_tables(thd); + /* + If we have old format, load_tmpdir is cleaned up by the I/O thread + */ cleanup_load_tmpdir(); + } return Log_event::exec_event(rli); } @@ -1980,7 +1989,14 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli) int Stop_log_event::exec_event(struct st_relay_log_info* rli) { - // do not clean up immediately after rotate event + /* + do not clean up immediately after rotate event; + QQ: this should be a useless test: the only case when it is false is when + shutdown occured just after FLUSH LOGS. It has nothing to do with Rotate? + By the way, immediately after a Rotate + the I/O thread does not write the Stop to the relay log, + so we won't come here in that case. + */ if (rli->master_log_pos > BIN_LOG_HEADER_SIZE) { close_temporary_tables(thd); From ef39d2a669cdfee1802eed0eb2ae87ba429ef7e3 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 9 Apr 2003 21:19:53 +0200 Subject: [PATCH 027/188] - applied patch from provided by Christian Hammers from Debian to be able to run the script even if mysqld is not up and running on upgrade --- scripts/mysql_fix_privilege_tables.sh | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 09259779855..526b7ac91b3 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -1,14 +1,5 @@ #!/bin/sh -echo "This scripts updates the mysql.user, mysql.db, mysql.host and the" -echo "mysql.func tables to MySQL 3.22.14 and above." -echo "" -echo "This is needed if you want to use the new GRANT functions," -echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23" -echo "" -echo "If you get 'Access denied' errors, you should run this script again" -echo "and give the MySQL root user password as an argument!" - root_password="$1" host="localhost" user="root" @@ -20,6 +11,21 @@ else cmd="@bindir@/mysql -f --user=$user --password=$root_password --host=$host mysql" fi +# Debian addition +if [ "$1" = "--sql-only" ]; then + root_password="" + cmd="/usr/share/mysql/echo_stderr" +fi + +echo "This scripts updates the mysql.user, mysql.db, mysql.host and the" +echo "mysql.func tables to MySQL 3.22.14 and above." +echo "" +echo "This is needed if you want to use the new GRANT functions," +echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23" +echo "" +echo "If you get 'Access denied' errors, you should run this script again" +echo "and give the MySQL root user password as an argument!" + echo "Converting all privilege tables to MyISAM format" $cmd < Date: Wed, 9 Apr 2003 22:14:21 +0200 Subject: [PATCH 028/188] - worked around bug #235 (my-huge.cnf error) by reformatting the comments in the sample configuration files - reworked the replication options and comments a bit - added option "skip-networking" (commented out by default) to the sample configuration files (enhancement request from bug report #234) --- support-files/my-huge.cnf.sh | 54 +++++++++++++++++++++++++--------- support-files/my-large.cnf.sh | 49 +++++++++++++++++++++++++++--- support-files/my-medium.cnf.sh | 41 ++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 18 deletions(-) diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index 50a14b0fc96..b1cf295e429 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -31,27 +31,53 @@ set-variable = max_allowed_packet=1M set-variable = table_cache=512 set-variable = sort_buffer=2M set-variable = record_buffer=2M +set-variable = myisam_sort_buffer_size=64M set-variable = thread_cache=8 # Try number of CPU's*2 for thread_concurrency set-variable = thread_concurrency=8 -set-variable = myisam_sort_buffer_size=64M + +# Don't listen on a TCP/IP port at all. This can be a security enhancement, +# if all processes that need to connect to mysqld run on the same host. +# All interaction with mysqld must be made via Unix sockets or named pipes. +# Note that using this option without enabling named pipes on Windows +# (via the "pipe" option) will render mysqld useless! +# +#skip-networking # Replication Master Server (default) -log-bin # required for replication -server-id = 1 # required unique id between 1 and 2^32 - 1 - # defaults to 1 if master-host is not set - # but will not function as a master if omitted +# binary logging is required for replication +log-bin + +# required unique id between 1 and 2^32 - 1 +# defaults to 1 if master-host is not set +# but will not function as a master if omitted +server-id = 1 # Replication Slave Server (comment out master section to use this) -#master-host = # MUST BE SET -#master-user = # MUST BE SET -#master-password = # MUST BE SET -#master-port = # optional--defaults to 3306 -#log-bin # not required for slaves, but recommended -#server-id = 2 # required unique id between 2 and 2^32 - 1 - # (and different from the master) - # defaults to 2 if master-host is set - # but will not function as a slave if omitted +# +# required unique id between 2 and 2^32 - 1 +# (and different from the master) +# defaults to 2 if master-host is set +# but will not function as a slave if omitted +#server-id = 2 +# +# The replication master for this slave - required +#master-host = +# +# The username the slave will use for authentication when connecting +# to the master - required +#master-user = +# +# The password the slave will authenticate with when connecting to +# the master - required +#master-password = +# +# The port the master is listening on. +# optional - defaults to 3306 +#master-port = +# +# binary logging - not required for slaves, but recommended +#log-bin # Point the following paths to different dedicated disks #tmpdir = /tmp/ diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 3c388d611d8..861c2d59fb0 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -35,9 +35,54 @@ set-variable = myisam_sort_buffer_size=64M set-variable = thread_cache=8 # Try number of CPU's*2 for thread_concurrency set-variable = thread_concurrency=8 + +# Don't listen on a TCP/IP port at all. This can be a security enhancement, +# if all processes that need to connect to mysqld run on the same host. +# All interaction with mysqld must be made via Unix sockets or named pipes. +# Note that using this option without enabling named pipes on Windows +# (via the "pipe" option) will render mysqld useless! +# +#skip-networking + +# Replication Master Server (default) +# binary logging is required for replication log-bin + +# required unique id between 1 and 2^32 - 1 +# defaults to 1 if master-host is not set +# but will not function as a master if omitted server-id = 1 +# Replication Slave Server (comment out master section to use this) +# +# required unique id between 2 and 2^32 - 1 +# (and different from the master) +# defaults to 2 if master-host is set +# but will not function as a slave if omitted +#server-id = 2 +# +# The replication master for this slave - required +#master-host = +# +# The username the slave will use for authentication when connecting +# to the master - required +#master-user = +# +# The password the slave will authenticate with when connecting to +# the master - required +#master-password = +# +# The port the master is listening on. +# optional - defaults to 3306 +#master-port = +# +# binary logging - not required for slaves, but recommended +#log-bin + +# Point the following paths to different dedicated disks +#tmpdir = /tmp/ +#log-update = /path-to-dedicated-directory/hostname + # Uncomment the following if you are using BDB tables #set-variable = bdb_cache_size=64M #set-variable = bdb_max_lock=100000 @@ -57,10 +102,6 @@ server-id = 1 #innodb_flush_log_at_trx_commit=1 #set-variable = innodb_lock_wait_timeout=50 -# Point the following paths to different dedicated disks -#tmpdir = /tmp/ -#log-update = /path-to-dedicated-directory/hostname - [mysqldump] quick set-variable = max_allowed_packet=16M diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh index a92494358cb..b5ce3bc6ced 100644 --- a/support-files/my-medium.cnf.sh +++ b/support-files/my-medium.cnf.sh @@ -33,9 +33,50 @@ set-variable = table_cache=64 set-variable = sort_buffer=512K set-variable = net_buffer_length=8K set-variable = myisam_sort_buffer_size=8M + +# Don't listen on a TCP/IP port at all. This can be a security enhancement, +# if all processes that need to connect to mysqld run on the same host. +# All interaction with mysqld must be made via Unix sockets or named pipes. +# Note that using this option without enabling named pipes on Windows +# (via the "pipe" option) will render mysqld useless! +# +#skip-networking + +# Replication Master Server (default) +# binary logging is required for replication log-bin + +# required unique id between 1 and 2^32 - 1 +# defaults to 1 if master-host is not set +# but will not function as a master if omitted server-id = 1 +# Replication Slave Server (comment out master section to use this) +# +# required unique id between 2 and 2^32 - 1 +# (and different from the master) +# defaults to 2 if master-host is set +# but will not function as a slave if omitted +#server-id = 2 +# +# The replication master for this slave - required +#master-host = +# +# The username the slave will use for authentication when connecting +# to the master - required +#master-user = +# +# The password the slave will authenticate with when connecting to +# the master - required +#master-password = +# +# The port the master is listening on. +# optional - defaults to 3306 +#master-port = +# +# binary logging - not required for slaves, but recommended +#log-bin + # Point the following paths to different dedicated disks #tmpdir = /tmp/ #log-update = /path-to-dedicated-directory/hostname From dbe145f015a461f4951979d34bdb092efa7f2127 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Thu, 10 Apr 2003 20:03:52 +0200 Subject: [PATCH 029/188] - Fixed bug in "make DESTDIR= install" - the InnoDB static libraries always ended up in "dir..", even though they were not supposed to be installed anyway (they are only required at link time). Fixed it by replacing libs_LIBRARIES with noinst_LIBRARIES for all InnoDB Makefile.am files and by removing "libsdir = " from innobase/include/Makefile.i . --- innobase/btr/Makefile.am | 2 +- innobase/buf/Makefile.am | 2 +- innobase/com/Makefile.am | 2 +- innobase/data/Makefile.am | 2 +- innobase/dict/Makefile.am | 2 +- innobase/dyn/Makefile.am | 2 +- innobase/eval/Makefile.am | 2 +- innobase/fil/Makefile.am | 2 +- innobase/fsp/Makefile.am | 2 +- innobase/fut/Makefile.am | 2 +- innobase/ha/Makefile.am | 2 +- innobase/ibuf/Makefile.am | 2 +- innobase/include/Makefile.i | 2 -- innobase/lock/Makefile.am | 2 +- innobase/log/Makefile.am | 2 +- innobase/mach/Makefile.am | 2 +- innobase/mem/Makefile.am | 2 +- innobase/mtr/Makefile.am | 2 +- innobase/odbc/Makefile.am | 2 +- innobase/os/Makefile.am | 2 +- innobase/page/Makefile.am | 2 +- innobase/pars/Makefile.am | 2 +- innobase/que/Makefile.am | 2 +- innobase/read/Makefile.am | 2 +- innobase/rem/Makefile.am | 2 +- innobase/row/Makefile.am | 2 +- innobase/srv/Makefile.am | 2 +- innobase/sync/Makefile.am | 2 +- innobase/thr/Makefile.am | 2 +- innobase/trx/Makefile.am | 2 +- innobase/usr/Makefile.am | 2 +- innobase/ut/Makefile.am | 2 +- 32 files changed, 31 insertions(+), 33 deletions(-) diff --git a/innobase/btr/Makefile.am b/innobase/btr/Makefile.am index 6e3dd4fb007..ed61facb695 100644 --- a/innobase/btr/Makefile.am +++ b/innobase/btr/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libbtr.a +noinst_LIBRARIES = libbtr.a libbtr_a_SOURCES = btr0btr.c btr0cur.c btr0pcur.c btr0sea.c diff --git a/innobase/buf/Makefile.am b/innobase/buf/Makefile.am index b1463c2220e..3f56c8b02d7 100644 --- a/innobase/buf/Makefile.am +++ b/innobase/buf/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libbuf.a +noinst_LIBRARIES = libbuf.a libbuf_a_SOURCES = buf0buf.c buf0flu.c buf0lru.c buf0rea.c diff --git a/innobase/com/Makefile.am b/innobase/com/Makefile.am index 27ae396bc6e..a3d2f8a76c6 100644 --- a/innobase/com/Makefile.am +++ b/innobase/com/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libcom.a +noinst_LIBRARIES = libcom.a libcom_a_SOURCES = com0com.c com0shm.c diff --git a/innobase/data/Makefile.am b/innobase/data/Makefile.am index 0e502708e85..eeb6f129de0 100644 --- a/innobase/data/Makefile.am +++ b/innobase/data/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libdata.a +noinst_LIBRARIES = libdata.a libdata_a_SOURCES = data0data.c data0type.c diff --git a/innobase/dict/Makefile.am b/innobase/dict/Makefile.am index 693048b6784..0034d2f8f1e 100644 --- a/innobase/dict/Makefile.am +++ b/innobase/dict/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libdict.a +noinst_LIBRARIES = libdict.a libdict_a_SOURCES = dict0boot.c dict0crea.c dict0dict.c dict0load.c\ dict0mem.c diff --git a/innobase/dyn/Makefile.am b/innobase/dyn/Makefile.am index 79c0000868c..ec33a3c18a9 100644 --- a/innobase/dyn/Makefile.am +++ b/innobase/dyn/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libdyn.a +noinst_LIBRARIES = libdyn.a libdyn_a_SOURCES = dyn0dyn.c diff --git a/innobase/eval/Makefile.am b/innobase/eval/Makefile.am index 5dd0eab4c9b..aebffb91be3 100644 --- a/innobase/eval/Makefile.am +++ b/innobase/eval/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libeval.a +noinst_LIBRARIES = libeval.a libeval_a_SOURCES = eval0eval.c eval0proc.c diff --git a/innobase/fil/Makefile.am b/innobase/fil/Makefile.am index a9473fdb762..dc0baff7d1a 100644 --- a/innobase/fil/Makefile.am +++ b/innobase/fil/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libfil.a +noinst_LIBRARIES = libfil.a libfil_a_SOURCES = fil0fil.c diff --git a/innobase/fsp/Makefile.am b/innobase/fsp/Makefile.am index b3e9ab44d9b..edf06bda0d6 100644 --- a/innobase/fsp/Makefile.am +++ b/innobase/fsp/Makefile.am @@ -18,7 +18,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libfsp.a +noinst_LIBRARIES = libfsp.a libfsp_a_SOURCES = fsp0fsp.c diff --git a/innobase/fut/Makefile.am b/innobase/fut/Makefile.am index a4b1e30e03c..839fdb1580e 100644 --- a/innobase/fut/Makefile.am +++ b/innobase/fut/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libfut.a +noinst_LIBRARIES = libfut.a libfut_a_SOURCES = fut0fut.c fut0lst.c diff --git a/innobase/ha/Makefile.am b/innobase/ha/Makefile.am index ce846d37622..121bafe167d 100644 --- a/innobase/ha/Makefile.am +++ b/innobase/ha/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libha.a +noinst_LIBRARIES = libha.a libha_a_SOURCES = ha0ha.c hash0hash.c diff --git a/innobase/ibuf/Makefile.am b/innobase/ibuf/Makefile.am index 1c1d196c40c..fb813d38ee5 100644 --- a/innobase/ibuf/Makefile.am +++ b/innobase/ibuf/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libibuf.a +noinst_LIBRARIES = libibuf.a libibuf_a_SOURCES = ibuf0ibuf.c diff --git a/innobase/include/Makefile.i b/innobase/include/Makefile.i index 985ec525950..f3e3fbe989e 100644 --- a/innobase/include/Makefile.i +++ b/innobase/include/Makefile.i @@ -1,7 +1,5 @@ # Makefile included in Makefile.am in every subdirectory -libsdir = ../libs - INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../../include -I../../include # Don't update the files from bitkeeper diff --git a/innobase/lock/Makefile.am b/innobase/lock/Makefile.am index f9e1b227f3c..549eb2604e3 100644 --- a/innobase/lock/Makefile.am +++ b/innobase/lock/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = liblock.a +noinst_LIBRARIES = liblock.a liblock_a_SOURCES = lock0lock.c diff --git a/innobase/log/Makefile.am b/innobase/log/Makefile.am index 3910a25ab1a..2dbaf93e6d9 100644 --- a/innobase/log/Makefile.am +++ b/innobase/log/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = liblog.a +noinst_LIBRARIES = liblog.a liblog_a_SOURCES = log0log.c log0recv.c diff --git a/innobase/mach/Makefile.am b/innobase/mach/Makefile.am index 8195831e92e..ce827c8033f 100644 --- a/innobase/mach/Makefile.am +++ b/innobase/mach/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libmach.a +noinst_LIBRARIES = libmach.a libmach_a_SOURCES = mach0data.c diff --git a/innobase/mem/Makefile.am b/innobase/mem/Makefile.am index 84f642e4469..10b7771b580 100644 --- a/innobase/mem/Makefile.am +++ b/innobase/mem/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libmem.a +noinst_LIBRARIES = libmem.a libmem_a_SOURCES = mem0mem.c mem0pool.c diff --git a/innobase/mtr/Makefile.am b/innobase/mtr/Makefile.am index 972dcaca80e..1e93a34ce23 100644 --- a/innobase/mtr/Makefile.am +++ b/innobase/mtr/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libmtr.a +noinst_LIBRARIES = libmtr.a libmtr_a_SOURCES = mtr0mtr.c mtr0log.c diff --git a/innobase/odbc/Makefile.am b/innobase/odbc/Makefile.am index d1a47bd8c18..f4282ba3907 100644 --- a/innobase/odbc/Makefile.am +++ b/innobase/odbc/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libodbc.a +noinst_LIBRARIES = libodbc.a libodbc_a_SOURCES = odbc0odbc.c diff --git a/innobase/os/Makefile.am b/innobase/os/Makefile.am index b06670bc703..132ce07c83b 100644 --- a/innobase/os/Makefile.am +++ b/innobase/os/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libos.a +noinst_LIBRARIES = libos.a libos_a_SOURCES = os0proc.c os0shm.c os0sync.c os0thread.c os0file.c diff --git a/innobase/page/Makefile.am b/innobase/page/Makefile.am index 85fe585a633..2e260787438 100644 --- a/innobase/page/Makefile.am +++ b/innobase/page/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libpage.a +noinst_LIBRARIES = libpage.a libpage_a_SOURCES = page0page.c page0cur.c diff --git a/innobase/pars/Makefile.am b/innobase/pars/Makefile.am index e5611f9dfc6..2356f330486 100644 --- a/innobase/pars/Makefile.am +++ b/innobase/pars/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libpars.a +noinst_LIBRARIES = libpars.a noinst_HEADERS = pars0grm.h diff --git a/innobase/que/Makefile.am b/innobase/que/Makefile.am index b74d4dbf6a0..d9c046b4f4c 100644 --- a/innobase/que/Makefile.am +++ b/innobase/que/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libque.a +noinst_LIBRARIES = libque.a libque_a_SOURCES = que0que.c diff --git a/innobase/read/Makefile.am b/innobase/read/Makefile.am index 16224f4f7f4..7edf2a5a2e1 100644 --- a/innobase/read/Makefile.am +++ b/innobase/read/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libread.a +noinst_LIBRARIES = libread.a libread_a_SOURCES = read0read.c diff --git a/innobase/rem/Makefile.am b/innobase/rem/Makefile.am index ef0cde9bd7a..e2b2fdaf669 100644 --- a/innobase/rem/Makefile.am +++ b/innobase/rem/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = librem.a +noinst_LIBRARIES = librem.a librem_a_SOURCES = rem0rec.c rem0cmp.c diff --git a/innobase/row/Makefile.am b/innobase/row/Makefile.am index e4fcbe8f715..bd09f9a237d 100644 --- a/innobase/row/Makefile.am +++ b/innobase/row/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = librow.a +noinst_LIBRARIES = librow.a librow_a_SOURCES = row0ins.c row0mysql.c row0purge.c row0row.c row0sel.c\ row0uins.c row0umod.c row0undo.c row0upd.c row0vers.c diff --git a/innobase/srv/Makefile.am b/innobase/srv/Makefile.am index b4bdeb7c03b..752683b82b8 100644 --- a/innobase/srv/Makefile.am +++ b/innobase/srv/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libsrv.a +noinst_LIBRARIES = libsrv.a libsrv_a_SOURCES = srv0srv.c srv0que.c srv0start.c diff --git a/innobase/sync/Makefile.am b/innobase/sync/Makefile.am index 7504525bf84..4acd4516e35 100644 --- a/innobase/sync/Makefile.am +++ b/innobase/sync/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libsync.a +noinst_LIBRARIES = libsync.a libsync_a_SOURCES = sync0arr.c sync0ipm.c sync0rw.c sync0sync.c diff --git a/innobase/thr/Makefile.am b/innobase/thr/Makefile.am index 5f42138e734..62c39492c07 100644 --- a/innobase/thr/Makefile.am +++ b/innobase/thr/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libthr.a +noinst_LIBRARIES = libthr.a libthr_a_SOURCES = thr0loc.c diff --git a/innobase/trx/Makefile.am b/innobase/trx/Makefile.am index 63b2c52da33..9e2b3c398e3 100644 --- a/innobase/trx/Makefile.am +++ b/innobase/trx/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libtrx.a +noinst_LIBRARIES = libtrx.a libtrx_a_SOURCES = trx0purge.c trx0rec.c trx0roll.c trx0rseg.c\ trx0sys.c trx0trx.c trx0undo.c diff --git a/innobase/usr/Makefile.am b/innobase/usr/Makefile.am index a71d0d41ac0..bdcc832a76e 100644 --- a/innobase/usr/Makefile.am +++ b/innobase/usr/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libusr.a +noinst_LIBRARIES = libusr.a libusr_a_SOURCES = usr0sess.c diff --git a/innobase/ut/Makefile.am b/innobase/ut/Makefile.am index de3cf41b767..2fdbb99e0f3 100644 --- a/innobase/ut/Makefile.am +++ b/innobase/ut/Makefile.am @@ -17,7 +17,7 @@ include ../include/Makefile.i -libs_LIBRARIES = libut.a +noinst_LIBRARIES = libut.a libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c From ac8f4677d4d93e07b6d8373616ee604c41844d15 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 11 Apr 2003 13:02:16 +0200 Subject: [PATCH 030/188] - corrected shutdown priority on Red Hat (should be shut down very early) - adjusted LSB run levels to be identical as on Red Hat (2-5) --- support-files/mysql.server.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 7340cff9cad..1e328a4f625 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -10,7 +10,7 @@ # started and shut down when the systems goes down. # Comments to support chkconfig on RedHat Linux -# chkconfig: 2345 90 90 +# chkconfig: 2345 90 20 # description: A very fast and reliable SQL database engine. # Comments to support LSB init script conventions @@ -18,8 +18,8 @@ # Provides: mysql # Required-Start: $local_fs $network $remote_fs # Required-Stop: $local_fs $network $remote_fs -# Default-Start: 3 5 -# Default-Stop: 3 5 +# Default-Start: 2 3 4 5 +# Default-Stop: 2 3 4 5 # Short-Description: start and stop MySQL # Description: MySQL is a very fast and reliable SQL database engine. ### END INIT INFO From faad672620c9a3c12b782bde201a12f4b975394a Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 11 Apr 2003 17:07:58 +0200 Subject: [PATCH 031/188] Distribution cleanups: - added Dummy file Docs/manual_toc.html to make "make dist" happy if the real manual.texi has not been copied into Docs/ (which would make sure a "real" manual_toc.html would be created - fixed symlinking in the bdb subdirectory (docs are not included anyway) - added dist-hook to Makefile.am to remove superfluous SCCS directories from the source distribution --- Docs/manual_toc.html | 9 +++++ Makefile.am | 4 +++ bdb/dist/s_symlink | 80 ++++++++++++++++++++++---------------------- 3 files changed, 53 insertions(+), 40 deletions(-) create mode 100644 Docs/manual_toc.html diff --git a/Docs/manual_toc.html b/Docs/manual_toc.html new file mode 100644 index 00000000000..b9014e5efb9 --- /dev/null +++ b/Docs/manual_toc.html @@ -0,0 +1,9 @@ + + +Place holder for manual_toc.html + + +This is just a place holder for the autogenerated manual_toc.html +to make "make dist" happy. + + diff --git a/Makefile.am b/Makefile.am index 56aec377afb..b9e0e88ff77 100644 --- a/Makefile.am +++ b/Makefile.am @@ -79,6 +79,10 @@ init-db: all bin-dist: all $(top_builddir)/scripts/make_binary_distribution @MAKE_BINARY_DISTRIBUTION_OPTIONS@ +# Remove BK's "SCCS" subdirectories from source distribution +dist-hook: + rm -rf `find $(distdir) -type d -name SCCS` + tags: support-files/build-tags .PHONY: init-db bin-dist diff --git a/bdb/dist/s_symlink b/bdb/dist/s_symlink index 70efa445521..8c0e12dedd0 100755 --- a/bdb/dist/s_symlink +++ b/bdb/dist/s_symlink @@ -28,46 +28,46 @@ build db_stat/tags ../dist/tags build db_upgrade/tags ../dist/tags build db_verify/tags ../dist/tags build dbm/tags ../dist/tags -build docs_src/api_cxx/Makefile ../api_c/Makefile -build docs_src/api_cxx/m4.seealso ../api_c/m4.seealso -build docs_src/api_cxx/spell.ok ../api_c/spell.ok -build docs_src/api_java/Makefile ../api_c/Makefile -build docs_src/api_java/java_index.so ../api_cxx/cxx_index.so -build docs_src/api_java/m4.seealso ../api_c/m4.seealso -build docs_src/api_java/spell.ok ../api_c/spell.ok -build docs_src/api_tcl/spell.ok ../api_c/spell.ok -build docs_src/ref/am/spell.ok ../spell.ok -build docs_src/ref/am_conf/spell.ok ../spell.ok -build docs_src/ref/arch/spell.ok ../spell.ok -build docs_src/ref/build_unix/spell.ok ../spell.ok -build docs_src/ref/build_vxworks/spell.ok ../spell.ok -build docs_src/ref/build_win/spell.ok ../spell.ok -build docs_src/ref/cam/spell.ok ../spell.ok -build docs_src/ref/debug/spell.ok ../spell.ok -build docs_src/ref/distrib/spell.ok ../spell.ok -build docs_src/ref/dumpload/spell.ok ../spell.ok -build docs_src/ref/env/spell.ok ../spell.ok -build docs_src/ref/install/spell.ok ../spell.ok -build docs_src/ref/intro/spell.ok ../spell.ok -build docs_src/ref/java/spell.ok ../spell.ok -build docs_src/ref/lock/spell.ok ../spell.ok -build docs_src/ref/log/spell.ok ../spell.ok -build docs_src/ref/mp/spell.ok ../spell.ok -build docs_src/ref/perl/spell.ok ../spell.ok -build docs_src/ref/program/spell.ok ../spell.ok -build docs_src/ref/refs/spell.ok ../spell.ok -build docs_src/ref/rpc/spell.ok ../spell.ok -build docs_src/ref/sendmail/spell.ok ../spell.ok -build docs_src/ref/simple_tut/spell.ok ../spell.ok -build docs_src/ref/tcl/spell.ok ../spell.ok -build docs_src/ref/test/spell.ok ../spell.ok -build docs_src/ref/transapp/spell.ok ../spell.ok -build docs_src/ref/txn/spell.ok ../spell.ok -build docs_src/ref/upgrade.2.0/spell.ok ../spell.ok -build docs_src/ref/upgrade.3.0/spell.ok ../spell.ok -build docs_src/ref/upgrade.3.1/spell.ok ../spell.ok -build docs_src/ref/upgrade.3.2/spell.ok ../spell.ok -build docs_src/ref/xa/spell.ok ../spell.ok +# build docs_src/api_cxx/Makefile ../api_c/Makefile +# build docs_src/api_cxx/m4.seealso ../api_c/m4.seealso +# build docs_src/api_cxx/spell.ok ../api_c/spell.ok +# build docs_src/api_java/Makefile ../api_c/Makefile +# build docs_src/api_java/java_index.so ../api_cxx/cxx_index.so +# build docs_src/api_java/m4.seealso ../api_c/m4.seealso +# build docs_src/api_java/spell.ok ../api_c/spell.ok +# build docs_src/api_tcl/spell.ok ../api_c/spell.ok +# build docs_src/ref/am/spell.ok ../spell.ok +# build docs_src/ref/am_conf/spell.ok ../spell.ok +# build docs_src/ref/arch/spell.ok ../spell.ok +# build docs_src/ref/build_unix/spell.ok ../spell.ok +# build docs_src/ref/build_vxworks/spell.ok ../spell.ok +# build docs_src/ref/build_win/spell.ok ../spell.ok +# build docs_src/ref/cam/spell.ok ../spell.ok +# build docs_src/ref/debug/spell.ok ../spell.ok +# build docs_src/ref/distrib/spell.ok ../spell.ok +# build docs_src/ref/dumpload/spell.ok ../spell.ok +# build docs_src/ref/env/spell.ok ../spell.ok +# build docs_src/ref/install/spell.ok ../spell.ok +# build docs_src/ref/intro/spell.ok ../spell.ok +# build docs_src/ref/java/spell.ok ../spell.ok +# build docs_src/ref/lock/spell.ok ../spell.ok +# build docs_src/ref/log/spell.ok ../spell.ok +# build docs_src/ref/mp/spell.ok ../spell.ok +# build docs_src/ref/perl/spell.ok ../spell.ok +# build docs_src/ref/program/spell.ok ../spell.ok +# build docs_src/ref/refs/spell.ok ../spell.ok +# build docs_src/ref/rpc/spell.ok ../spell.ok +# build docs_src/ref/sendmail/spell.ok ../spell.ok +# build docs_src/ref/simple_tut/spell.ok ../spell.ok +# build docs_src/ref/tcl/spell.ok ../spell.ok +# build docs_src/ref/test/spell.ok ../spell.ok +# build docs_src/ref/transapp/spell.ok ../spell.ok +# build docs_src/ref/txn/spell.ok ../spell.ok +# build docs_src/ref/upgrade.2.0/spell.ok ../spell.ok +# build docs_src/ref/upgrade.3.0/spell.ok ../spell.ok +# build docs_src/ref/upgrade.3.1/spell.ok ../spell.ok +# build docs_src/ref/upgrade.3.2/spell.ok ../spell.ok +# build docs_src/ref/xa/spell.ok ../spell.ok build env/tags ../dist/tags build examples_c/tags ../dist/tags build examples_cxx/tags ../dist/tags From c3db30b5f19870ed2d5fefcb9cc4ef27fba95900 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Fri, 11 Apr 2003 20:09:24 +0300 Subject: [PATCH 032/188] Two bug fixes --- mysql-test/r/innodb.result | 10 ++++++++++ mysql-test/t/innodb.test | 5 +++++ sql/sql_select.cc | 2 ++ sql/sql_update.cc | 7 +++++++ 4 files changed, 24 insertions(+) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index b12466983f8..96bc66222d3 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1207,6 +1207,16 @@ SET AUTOCOMMIT=0; INSERT INTO t1 ( B_ID ) VALUES ( 1 ); INSERT INTO t2 ( NEXT_T ) VALUES ( 1 ); ROLLBACK; +Warning: Some non-transactional changed tables couldn't be rolled back SELECT * FROM t1; B_ID drop table t1,t2; +create table t1 ( pk int primary key, parent int not null, child int not null, index (parent) ) type = innodb; +insert into t1 values (1,0,4), (2,1,3), (3,2,1), (4,1,2); +select distinct parent,child from t1 order by parent; +parent child +0 4 +1 2 +1 3 +2 1 +drop table t1; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 9d614e8d163..b8929d5c4de 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -802,6 +802,11 @@ CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) TYPE=InnoDB; SET AUTOCOMMIT=0; INSERT INTO t1 ( B_ID ) VALUES ( 1 ); INSERT INTO t2 ( NEXT_T ) VALUES ( 1 ); +-- error 1196 ROLLBACK; SELECT * FROM t1; drop table t1,t2; +create table t1 ( pk int primary key, parent int not null, child int not null, index (parent) ) type = innodb; +insert into t1 values (1,0,4), (2,1,3), (3,2,1), (4,1,2); +select distinct parent,child from t1 order by parent; +drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 96de43ae55c..dfcbc5418cd 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -555,6 +555,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List &fields,COND *conds, /* Change DISTINCT to GROUP BY */ select_distinct= 0; no_order= !order; + if (order && skip_sort_order) + join.tmp_table_param.quick_group=0; if (all_order_fields_used) order=0; join.group=1; // For end_write_group diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 59c766e7a9f..de370ab92b5 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -478,7 +478,14 @@ int multi_update::prepare(List ¬_used_values) table->used_keys=0; table->pos_in_table_list= tl; } + else + { + table_ref->lock_type=TL_READ; + mysql_unlock_some_tables(thd,&table,1); + } } + + table_count= update.elements; update_tables= (TABLE_LIST*) update.first; From 5ae3989fe3dd1083c949ac57e108e78b80eb6749 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Mon, 14 Apr 2003 19:45:09 +0300 Subject: [PATCH 033/188] A fix for a bug with uncached database privileges. --- 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 0ffdb68a179..29bd1393322 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2550,7 +2550,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if ((thd->master_access & want_access) == want_access) { - *save_priv=thd->master_access; + *save_priv=thd->master_access | thd->db_access; DBUG_RETURN(FALSE); } if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) || From cf2ebdba328452268c397849060f64bbb33807ff Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Mon, 14 Apr 2003 20:58:41 +0300 Subject: [PATCH 034/188] Back porting a fix from 4.0 at customer's request --- 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 62c2f18c882..152d9c585ca 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2155,7 +2155,7 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, if ((thd->master_access & want_access) == want_access) { - *save_priv=thd->master_access; + *save_priv=thd->master_access | thd->db_access; return FALSE; } if ((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL) || From 0e76eab9d4bde843abc6bc589b889cd66e8de67d Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Mon, 14 Apr 2003 21:46:24 +0300 Subject: [PATCH 035/188] Fix for a NAN problem in FORMAT(...) string function .. --- mysql-test/r/func_misc.result | 3 +++ mysql-test/t/func_misc.test | 1 + sql/item_strfunc.cc | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 4eed80c4cc9..67f43ca5ba4 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -10,3 +10,6 @@ inet_aton("255.255.255.255.255") inet_aton("255.255.1.255") inet_aton("0.1.255") select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511); inet_ntoa(1099511627775) inet_ntoa(4294902271) inet_ntoa(511) NULL 255.255.1.255 0.0.1.255 +select format("nan",2); +format("nan",2) +nan diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index d48b17e87af..d9ae288cc59 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -7,3 +7,4 @@ select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.5555 select inet_ntoa(inet_aton("255.255.255.255.255.255.255.255")); select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255"); select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511); +select format("nan",2); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0f1ce8adba6..2496e1acabe 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1477,7 +1477,7 @@ String *Item_func_format::val_str(String *str) if (nr < 0) str_length--; // Don't count sign length=str->length()+(diff=(str_length- dec-1)/3); - if (diff) + if (diff && diff < 330) // size of buff ... { char *tmp,*pos; str=copy_if_not_alloced(&tmp_str,str,length); From 7fbc28c0740460ee5ed7bfbe1d82d438f6971b21 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 15 Apr 2003 16:11:37 +0200 Subject: [PATCH 036/188] - added missing dashes to parameter "open-files-limit" in mysqld_safe (bug #264) --- scripts/mysqld_safe.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 094b1fbfcd3..e400c27b84c 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -224,7 +224,7 @@ then if test -n "$open_files" then ulimit -n $open_files - args="open-files-limit=$open_files $args" + args="--open-files-limit=$open_files $args" fi if test -n "$core_file_size" then From 1e66aec50291b1470454108a0cad23dacbd8cd2c Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 15 Apr 2003 17:34:56 +0200 Subject: [PATCH 037/188] - Updated variable names that have been renamed in my.cnf example files (bug #223) - Added more detailed info about how to set up replication --- support-files/my-huge.cnf.sh | 39 +++++++++++++++++++++++++++++----- support-files/my-large.cnf.sh | 39 +++++++++++++++++++++++++++++----- support-files/my-medium.cnf.sh | 37 ++++++++++++++++++++++++++++---- support-files/my-small.cnf.sh | 16 ++++++++++---- 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index b1cf295e429..3362d5bd131 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -29,8 +29,8 @@ skip-locking set-variable = key_buffer=384M set-variable = max_allowed_packet=1M set-variable = table_cache=512 -set-variable = sort_buffer=2M -set-variable = record_buffer=2M +set-variable = sort_buffer_size=2M +set-variable = read_buffer_size=2M set-variable = myisam_sort_buffer_size=64M set-variable = thread_cache=8 # Try number of CPU's*2 for thread_concurrency @@ -53,7 +53,36 @@ log-bin # but will not function as a master if omitted server-id = 1 -# Replication Slave Server (comment out master section to use this) +# Replication Slave (comment out master section to use this) +# +# To configure this host as a replication slave, you can choose between +# two methods : +# +# 1) Use the CHANGE MASTER TO command (fully described in our manual) - +# the syntax is: +# +# CHANGE MASTER TO MASTER_HOST=, MASTER_PORT=, +# MASTER_USER=, MASTER_PASSWORD= ; +# +# where you replace , , by quoted strings and +# by the master's port number (3306 by default). +# +# Example: +# +# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306, +# MASTER_USER='joe', MASTER_PASSWORD='secret'; +# +# OR +# +# 2) Set the variables below. However, in case you choose this method, then +# start replication for the first time (even unsuccessfully, for example +# if you mistyped the password in master-password and the slave fails to +# connect), the slave will create a master.info file, and any later +# change in this file to the variables' values below will be ignored and +# overridden by the content of the master.info file, unless you shutdown +# the slave server, delete master.info and restart the slaver server. +# For that reason, you may want to leave the lines below untouched +# (commented) and instead use CHANGE MASTER TO (see above) # # required unique id between 2 and 2^32 - 1 # (and different from the master) @@ -113,13 +142,13 @@ no-auto-rehash [isamchk] set-variable = key_buffer=256M -set-variable = sort_buffer=256M +set-variable = sort_buffer_size=256M set-variable = read_buffer=2M set-variable = write_buffer=2M [myisamchk] set-variable = key_buffer=256M -set-variable = sort_buffer=256M +set-variable = sort_buffer_size=256M set-variable = read_buffer=2M set-variable = write_buffer=2M diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 861c2d59fb0..5bc3a8eb0c4 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -29,8 +29,8 @@ skip-locking set-variable = key_buffer=256M set-variable = max_allowed_packet=1M set-variable = table_cache=256 -set-variable = sort_buffer=1M -set-variable = record_buffer=1M +set-variable = sort_buffer_size=1M +set-variable = read_buffer_size=1M set-variable = myisam_sort_buffer_size=64M set-variable = thread_cache=8 # Try number of CPU's*2 for thread_concurrency @@ -53,7 +53,36 @@ log-bin # but will not function as a master if omitted server-id = 1 -# Replication Slave Server (comment out master section to use this) +# Replication Slave (comment out master section to use this) +# +# To configure this host as a replication slave, you can choose between +# two methods : +# +# 1) Use the CHANGE MASTER TO command (fully described in our manual) - +# the syntax is: +# +# CHANGE MASTER TO MASTER_HOST=, MASTER_PORT=, +# MASTER_USER=, MASTER_PASSWORD= ; +# +# where you replace , , by quoted strings and +# by the master's port number (3306 by default). +# +# Example: +# +# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306, +# MASTER_USER='joe', MASTER_PASSWORD='secret'; +# +# OR +# +# 2) Set the variables below. However, in case you choose this method, then +# start replication for the first time (even unsuccessfully, for example +# if you mistyped the password in master-password and the slave fails to +# connect), the slave will create a master.info file, and any later +# change in this file to the variables' values below will be ignored and +# overridden by the content of the master.info file, unless you shutdown +# the slave server, delete master.info and restart the slaver server. +# For that reason, you may want to leave the lines below untouched +# (commented) and instead use CHANGE MASTER TO (see above) # # required unique id between 2 and 2^32 - 1 # (and different from the master) @@ -113,13 +142,13 @@ no-auto-rehash [isamchk] set-variable = key_buffer=128M -set-variable = sort_buffer=128M +set-variable = sort_buffer_size=128M set-variable = read_buffer=2M set-variable = write_buffer=2M [myisamchk] set-variable = key_buffer=128M -set-variable = sort_buffer=128M +set-variable = sort_buffer_size=128M set-variable = read_buffer=2M set-variable = write_buffer=2M diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh index b5ce3bc6ced..084f23cbc94 100644 --- a/support-files/my-medium.cnf.sh +++ b/support-files/my-medium.cnf.sh @@ -30,7 +30,7 @@ skip-locking set-variable = key_buffer=16M set-variable = max_allowed_packet=1M set-variable = table_cache=64 -set-variable = sort_buffer=512K +set-variable = sort_buffer_size=512K set-variable = net_buffer_length=8K set-variable = myisam_sort_buffer_size=8M @@ -51,7 +51,36 @@ log-bin # but will not function as a master if omitted server-id = 1 -# Replication Slave Server (comment out master section to use this) +# Replication Slave (comment out master section to use this) +# +# To configure this host as a replication slave, you can choose between +# two methods : +# +# 1) Use the CHANGE MASTER TO command (fully described in our manual) - +# the syntax is: +# +# CHANGE MASTER TO MASTER_HOST=, MASTER_PORT=, +# MASTER_USER=, MASTER_PASSWORD= ; +# +# where you replace , , by quoted strings and +# by the master's port number (3306 by default). +# +# Example: +# +# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306, +# MASTER_USER='joe', MASTER_PASSWORD='secret'; +# +# OR +# +# 2) Set the variables below. However, in case you choose this method, then +# start replication for the first time (even unsuccessfully, for example +# if you mistyped the password in master-password and the slave fails to +# connect), the slave will create a master.info file, and any later +# change in this file to the variables' values below will be ignored and +# overridden by the content of the master.info file, unless you shutdown +# the slave server, delete master.info and restart the slaver server. +# For that reason, you may want to leave the lines below untouched +# (commented) and instead use CHANGE MASTER TO (see above) # # required unique id between 2 and 2^32 - 1 # (and different from the master) @@ -111,13 +140,13 @@ no-auto-rehash [isamchk] set-variable = key_buffer=20M -set-variable = sort_buffer=20M +set-variable = sort_buffer_size=20M set-variable = read_buffer=2M set-variable = write_buffer=2M [myisamchk] set-variable = key_buffer=20M -set-variable = sort_buffer=20M +set-variable = sort_buffer_size=20M set-variable = read_buffer=2M set-variable = write_buffer=2M diff --git a/support-files/my-small.cnf.sh b/support-files/my-small.cnf.sh index b8941184fe0..b11277c1b4a 100644 --- a/support-files/my-small.cnf.sh +++ b/support-files/my-small.cnf.sh @@ -29,10 +29,18 @@ socket = @MYSQL_UNIX_ADDR@ skip-locking set-variable = key_buffer=16K set-variable = max_allowed_packet=1M -set-variable = thread_stack=64K set-variable = table_cache=4 -set-variable = sort_buffer=64K +set-variable = sort_buffer_size=64K set-variable = net_buffer_length=2K +set-variable = thread_stack=64K + +# Don't listen on a TCP/IP port at all. This can be a security enhancement, +# if all processes that need to connect to mysqld run on the same host. +# All interaction with mysqld must be made via Unix sockets or named pipes. +# Note that using this option without enabling named pipes on Windows +# (via the "pipe" option) will render mysqld useless! +# +#skip-networking server-id = 1 # Uncomment the following if you want to log updates @@ -67,11 +75,11 @@ no-auto-rehash [isamchk] set-variable = key_buffer=8M -set-variable = sort_buffer=8M +set-variable = sort_buffer_size=8M [myisamchk] set-variable = key_buffer=8M -set-variable = sort_buffer=8M +set-variable = sort_buffer_size=8M [mysqlhotcopy] interactive-timeout From 3e6c350f6461b2dc4a2bb00143583dfcf3e38399 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Tue, 15 Apr 2003 22:04:16 +0300 Subject: [PATCH 038/188] Fixed bug in SUM() with NULL:s Added logging of warnings for failed connections with ssl. Fixed bug in symbolic link handling on Windows --- include/my_global.h | 5 ++++ mysql-test/r/func_group.result | 43 +++++++++++++++++++++++++++++++++- mysql-test/t/func_group.test | 21 +++++++++++++++++ sql/item_sum.cc | 13 +++++++--- sql/item_sum.h | 8 ++++--- sql/mysqld.cc | 13 ++++------ sql/net_serv.cc | 22 ++++++++--------- sql/sql_acl.cc | 12 ++++++++++ sql/sql_show.cc | 2 +- 9 files changed, 112 insertions(+), 27 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 39b6cada0e3..b6b2dfcda32 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -19,6 +19,11 @@ #ifndef _global_h #define _global_h +#ifndef EMBEDDED_LIBRARY +#define HAVE_REPLICATION +#define HAVE_EXTERNAL_CLIENT +#endif + #if defined( __EMX__) && !defined( MYSQL_SERVER) /* moved here to use below VOID macro redefinition */ #define INCL_BASE diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index b129beaac81..80ccb6c7bb8 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -47,7 +47,7 @@ sum(all a) count(all a) avg(all a) std(all a) bit_or(all a) bit_and(all a) min(a 21 6 3.5000 1.7078 7 0 1 6 E select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp; grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c) -NULL 0 0 NULL NULL 0 0 NULL NULL +NULL NULL 0 NULL NULL 0 0 NULL NULL 1 1 1 1.0000 0.0000 1 1 1 1 a a 2 5 2 2.5000 0.5000 3 2 2 3 b c 3 15 3 5.0000 0.8165 7 4 4 6 C E @@ -204,3 +204,44 @@ select max(t2.a1) from t1 left outer join t2 on t1.a2=t2.a1 and 1=0 where t2.a1= max(t2.a1) NULL drop table t1,t2; +CREATE TABLE t1 (a int, b int); +select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1; +count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +0 NULL NULL NULL NULL NULL -1 0 +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +insert into t1 values (1,null); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +1 0 NULL NULL NULL NULL NULL -1 0 +insert into t1 values (1,null); +insert into t1 values (2,null); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +1 0 NULL NULL NULL NULL NULL 0 0 +2 0 NULL NULL NULL NULL NULL 0 0 +select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +1 0 NULL NULL NULL NULL NULL -1 0 +2 0 NULL NULL NULL NULL NULL -1 0 +insert into t1 values (2,1); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +1 0 NULL NULL NULL NULL NULL 0 0 +2 1 1 1.0000 0.0000 1 1 0 1 +select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +1 0 NULL NULL NULL NULL NULL -1 0 +2 1 1 1.0000 0.0000 1 1 1 1 +insert into t1 values (3,1); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +1 0 NULL NULL NULL NULL NULL 0 0 +2 1 1 1.0000 0.0000 1 1 0 1 +3 1 1 1.0000 0.0000 1 1 1 1 +select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) +1 0 NULL NULL NULL NULL NULL -1 0 +2 1 1 1.0000 0.0000 1 1 1 1 +3 1 1 1.0000 0.0000 1 1 1 1 +drop table t1; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 1915c2172ad..40d829d3e70 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -126,3 +126,24 @@ select max(t1.a2) from t1 left outer join t2 on t1.a1=10 where t1.a1=20; select max(t1.a2) from t1 left outer join t2 on t1.a1=10 where t1.a1=10; select max(t2.a1) from t1 left outer join t2 on t1.a2=t2.a1 and 1=0 where t2.a1='AAA'; drop table t1,t2; + +# +# Test of group function and NULL values +# + +CREATE TABLE t1 (a int, b int); +select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1; +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +insert into t1 values (1,null); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +insert into t1 values (1,null); +insert into t1 values (2,null); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +insert into t1 values (2,1); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +insert into t1 values (3,1); +select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; +drop table t1; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index b6bbc12efd6..3a513505913 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -175,12 +175,14 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables) void Item_sum_sum::reset() { - null_value=0; sum=0.0; Item_sum_sum::add(); + null_value=1; sum=0.0; Item_sum_sum::add(); } bool Item_sum_sum::add() { sum+=args[0]->val(); + if (!args[0]->null_value) + null_value= 0; return 0; } @@ -566,8 +568,10 @@ void Item_sum_sum::reset_field() { double nr=args[0]->val(); // Nulls also return 0 float8store(result_field->ptr,nr); - null_value=0; - result_field->set_notnull(); + if (args[0]->null_value) + result_field->set_null(); + else + result_field->set_notnull(); } @@ -623,7 +627,10 @@ void Item_sum_sum::update_field(int offset) float8get(old_nr,res+offset); nr=args[0]->val(); if (!args[0]->null_value) + { old_nr+=nr; + result_field->set_notnull(); + } float8store(res,old_nr); } diff --git a/sql/item_sum.h b/sql/item_sum.h index 29ac1f1d1b1..2369b5d1d7e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -92,9 +92,6 @@ public: class Item_sum_int :public Item_sum_num { - void fix_length_and_dec() - { decimals=0; max_length=21; maybe_null=null_value=0; } - public: Item_sum_int(Item *item_par) :Item_sum_num(item_par) {} Item_sum_int(List &list) :Item_sum_num(list) {} @@ -102,6 +99,8 @@ public: String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { decimals=0; max_length=21; maybe_null=null_value=0; } }; @@ -118,6 +117,7 @@ class Item_sum_sum :public Item_sum_num double val(); void reset_field(); void update_field(int offset); + void no_rows_in_result() {} const char *func_name() const { return "sum"; } unsigned int size_of() { return sizeof(*this);} }; @@ -361,6 +361,8 @@ class Item_sum_bit :public Item_sum_int longlong val_int(); void reset_field(); unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4ae248acb67..24e343017e2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3562,7 +3562,7 @@ relay logs", {"skip-stack-trace", OPT_SKIP_STACK_TRACE, "Don't print a stack trace on failure", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables", + {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. Depricated option. Use --skip-symbolic-links instead", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-thread-priority", OPT_SKIP_PRIOR, "Don't give threads different priorities.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, @@ -3606,11 +3606,12 @@ replicating a LOAD DATA INFILE command", {"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running", (gptr*) &opt_external_locking, (gptr*) &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef USE_SYMDIR - {"use-symbolic-links", 's', "Enable symbolic link support", + {"use-symbolic-links", 's', "Enable symbolic link support. Depricated option; Use --symbolic-links instead", + (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG, + IF_PURIFY(0,1), 0, 0, 0, 0, 0}, + {"--symbolic-links", 's', "Enable symbolic link support", (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG, IF_PURIFY(0,1), 0, 0, 0, 0, 0}, -#endif {"user", 'u', "Run mysqld daemon as user", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit", 0, 0, 0, GET_NO_ARG, @@ -4424,9 +4425,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; myisam_concurrent_insert=0; myisam_recover_options= HA_RECOVER_NONE; - my_disable_symlinks=1; my_use_symdir=0; - have_symlink=SHOW_OPTION_DISABLED; ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE); #ifdef HAVE_QUERY_CACHE query_cache_size=0; @@ -4473,9 +4472,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), test_flags|=TEST_NO_STACKTRACE; break; case (int) OPT_SKIP_SYMLINKS: - my_disable_symlinks=1; my_use_symdir=0; - have_symlink=SHOW_OPTION_DISABLED; break; case (int) OPT_BIND_ADDRESS: if (argument && isdigit(argument[0])) diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 19f68e0b631..79d9041bb6d 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -47,13 +47,6 @@ can't normally do this the client should have a bigger max_allowed_packet. */ -#ifdef MYSQL_SERVER -#define USE_QUERY_CACHE -extern uint test_flags; -extern void query_cache_insert(NET *net, const char *packet, ulong length); -#else -#endif - #if defined(__WIN__) || !defined(MYSQL_SERVER) /* The following is because alarms doesn't work on windows. */ #define NO_ALARM @@ -62,15 +55,22 @@ extern void query_cache_insert(NET *net, const char *packet, ulong length); #ifndef NO_ALARM #include "my_pthread.h" void sql_print_error(const char *format,...); +#else +#define DONT_USE_THR_ALARM +#endif /* NO_ALARM */ + +#include "thr_alarm.h" + +#ifdef MYSQL_SERVER +#define USE_QUERY_CACHE +extern uint test_flags; +extern void query_cache_insert(NET *net, const char *packet, ulong length); extern ulong bytes_sent, bytes_received; extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received; #else #undef statistic_add #define statistic_add(A,B,C) -#define DONT_USE_THR_ALARM -#endif /* NO_ALARM */ - -#include "thr_alarm.h" +#endif #define TEST_BLOCKING 8 #define MAX_PACKET_LENGTH (256L*256L*256L-1) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e8cbba8aefa..9437e5ecb5b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -564,6 +564,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, user_access=acl_user->access; else { + if (global_system_variables.log_warnings) + sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'", + acl_user->ssl_cipher, + SSL_get_cipher(vio->ssl_)); user_access=NO_ACCESS; break; } @@ -581,6 +585,9 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, acl_user->x509_issuer, ptr)); if (strcmp(acl_user->x509_issuer, ptr)) { + if (global_system_variables.log_warnings) + sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'", + acl_user->x509_issuer, ptr); user_access=NO_ACCESS; free(ptr); break; @@ -596,7 +603,12 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, DBUG_PRINT("info",("comparing subjects: '%s' and '%s'", acl_user->x509_subject, ptr)); if (strcmp(acl_user->x509_subject,ptr)) + { + if (global_system_variables.log_warnings) + sql_print_error("X509 subject mismatch: '%s' vs '%s'", + acl_user->x509_subject, ptr); user_access=NO_ACCESS; + } else user_access=acl_user->access; free(ptr); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6e1cf2e8217..881e59ca53d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1225,7 +1225,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, case SHOW_RPL_STATUS: net_store_data(&packet2, rpl_status_type[(int)rpl_status]); break; -#ifndef EMBEDDED_LIBRARY +#ifdef HAVE_REPLICATION case SHOW_SLAVE_RUNNING: { LOCK_ACTIVE_MI; From 05817b7311aeb6935320247ea535db9c444a1b9a Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Wed, 16 Apr 2003 15:05:47 +0500 Subject: [PATCH 039/188] Fix bug: Crash server when grant ssl options are used and ssl handshake is not set --- sql/sql_acl.cc | 115 +++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9437e5ecb5b..8ee210f4e24 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -542,78 +542,79 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, break; case SSL_TYPE_X509: /* Client should have any valid certificate. */ /* - Connections with non-valid certificates are dropped already - in sslaccept() anyway, so we do not check validity here. + We need to check for absence of SSL because without SSL + we should reject connection. */ - if (SSL_get_peer_certificate(vio->ssl_)) + if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_)) user_access=acl_user->access; break; case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */ /* - We do not check for absence of SSL because without SSL it does - not pass all checks here anyway. - If cipher name is specified, we compare it to actual cipher in - use. + We need to check for absence of SSL because without SSL + we should reject connection. */ - if (acl_user->ssl_cipher) + if (vio_type(vio) == VIO_TYPE_SSL) { - DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'", - acl_user->ssl_cipher, - SSL_get_cipher(vio->ssl_))); - if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_))) - user_access=acl_user->access; - else + if (acl_user->ssl_cipher) { - if (global_system_variables.log_warnings) - sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'", - acl_user->ssl_cipher, - SSL_get_cipher(vio->ssl_)); - user_access=NO_ACCESS; - break; + DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'", + acl_user->ssl_cipher, + SSL_get_cipher(vio->ssl_))); + if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_))) + user_access=acl_user->access; + else + { + if (global_system_variables.log_warnings) + sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'", + acl_user->ssl_cipher, + SSL_get_cipher(vio->ssl_)); + user_access=NO_ACCESS; + break; + } } - } - /* Prepare certificate (if exists) */ - DBUG_PRINT("info",("checkpoint 1")); - X509* cert=SSL_get_peer_certificate(vio->ssl_); - DBUG_PRINT("info",("checkpoint 2")); - /* If X509 issuer is speified, we check it... */ - if (acl_user->x509_issuer) - { - DBUG_PRINT("info",("checkpoint 3")); - char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); - DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", - acl_user->x509_issuer, ptr)); - if (strcmp(acl_user->x509_issuer, ptr)) + /* Prepare certificate (if exists) */ + DBUG_PRINT("info",("checkpoint 1")); + X509* cert=SSL_get_peer_certificate(vio->ssl_); + DBUG_PRINT("info",("checkpoint 2")); + /* If X509 issuer is speified, we check it... */ + if (acl_user->x509_issuer) { - if (global_system_variables.log_warnings) - sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'", - acl_user->x509_issuer, ptr); - user_access=NO_ACCESS; + DBUG_PRINT("info",("checkpoint 3")); + char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); + DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", + acl_user->x509_issuer, ptr)); + if (strcmp(acl_user->x509_issuer, ptr)) + { + if (global_system_variables.log_warnings) + sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'", + acl_user->x509_issuer, ptr); + user_access=NO_ACCESS; + free(ptr); + break; + } + user_access=acl_user->access; free(ptr); - break; } - user_access=acl_user->access; - free(ptr); - } - DBUG_PRINT("info",("checkpoint 4")); - /* X509 subject is specified, we check it .. */ - if (acl_user->x509_subject) - { - char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); - DBUG_PRINT("info",("comparing subjects: '%s' and '%s'", - acl_user->x509_subject, ptr)); - if (strcmp(acl_user->x509_subject,ptr)) + DBUG_PRINT("info",("checkpoint 4")); + /* X509 subject is specified, we check it .. */ + if (acl_user->x509_subject) { - if (global_system_variables.log_warnings) - sql_print_error("X509 subject mismatch: '%s' vs '%s'", - acl_user->x509_subject, ptr); - user_access=NO_ACCESS; + char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); + DBUG_PRINT("info",("comparing subjects: '%s' and '%s'", + acl_user->x509_subject, ptr)); + if (strcmp(acl_user->x509_subject,ptr)) + { + if (global_system_variables.log_warnings) + sql_print_error("X509 subject mismatch: '%s' vs '%s'", + acl_user->x509_subject, ptr); + user_access=NO_ACCESS; + } + else + user_access=acl_user->access; + free(ptr); } - else - user_access=acl_user->access; - free(ptr); + break; } - break; } #else /* HAVE_OPENSSL */ user_access=acl_user->access; From 0f619263256b9c54e114afc705796837e439820f Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 16 Apr 2003 13:39:39 +0300 Subject: [PATCH 040/188] fix for a bug with two natural joins. --- mysql-test/r/join_outer.result | 12 ++++++++++++ mysql-test/t/join_outer.test | 9 +++++++++ sql/sql_yacc.yy | 4 ++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 6e69616b7c6..e68f3e6b006 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -652,3 +652,15 @@ fooID barID fooID 20 2 NULL 30 3 30 drop table t1,t2; +drop table if exists t3; +create table t1 (i int); +create table t2 (i int); +create table t3 (i int); +insert into t1 values(1),(2); +insert into t2 values(2),(3); +insert into t3 values(2),(4); +select * from t1 natural left join t2 natural left join t3; +i i i +1 NULL NULL +2 2 2 +drop table t1,t2,t3; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 71c3643b2f4..80fa6501758 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -416,3 +416,12 @@ explain select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30; select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30; select * from t2 left join t1 ignore index(primary) on t1.fooID = t2.fooID and t1.fooID = 30; drop table t1,t2; +drop table if exists t3; +create table t1 (i int); +create table t2 (i int); +create table t3 (i int); +insert into t1 values(1),(2); +insert into t2 values(2),(3); +insert into t3 values(2),(4); +select * from t1 natural left join t2 natural left join t3; +drop table t1,t2,t3; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 7cd0b9406ea..15917506ecf 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -495,8 +495,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); /* These don't actually affect the way the query is really evaluated, but they silence a few warnings for shift/reduce conflicts. */ %left ',' -%left STRAIGHT_JOIN JOIN_SYM -%nonassoc CROSS INNER_SYM NATURAL LEFT RIGHT +%left STRAIGHT_JOIN JOIN_SYM NATURAL +%nonassoc CROSS INNER_SYM LEFT RIGHT %type IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME From d2bfaed9c2261df5a5d7de7da9dbeb49bde38b8e Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Wed, 16 Apr 2003 17:25:05 +0500 Subject: [PATCH 041/188] Fix bug (273):The x509 cert issuer seems not to be checked against the CA --- vio/viossl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vio/viossl.c b/vio/viossl.c index cf1c98b5382..0f34a45f9aa 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -281,7 +281,8 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout); SSL_set_fd(vio->ssl_,vio->sd); SSL_set_accept_state(vio->ssl_); - if (SSL_do_handshake(vio->ssl_) < 1) + if (SSL_do_handshake(vio->ssl_) < 1 || + SSL_get_verify_result(vio->ssl_) != X509_V_OK) { DBUG_PRINT("error", ("SSL_do_handshake failure")); report_errors(); @@ -354,7 +355,8 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout) SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout); SSL_set_fd (vio->ssl_, vio->sd); SSL_set_connect_state(vio->ssl_); - if (SSL_do_handshake(vio->ssl_) < 1) + if (SSL_do_handshake(vio->ssl_) < 1 || + SSL_get_verify_result(vio->ssl_) != X509_V_OK) { DBUG_PRINT("error", ("SSL_do_handshake failure")); report_errors(); From cde0099e23654a34e35c0227141f91c7c0751842 Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Wed, 16 Apr 2003 17:47:36 +0500 Subject: [PATCH 042/188] Memory leak fixed. --- sql/mysqld.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 24e343017e2..df83d1909cb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -921,6 +921,8 @@ void clean_up(bool print_message) free_max_user_conn(); end_slave_list(); #ifdef HAVE_OPENSSL + if (ssl_acceptor_fd) + my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR)); free_des_key_file(); #endif /* HAVE_OPENSSL */ #ifdef USE_REGEX From f841b4ae234359210d240879236653db2dec7281 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 16 Apr 2003 16:45:01 +0300 Subject: [PATCH 043/188] Many files: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works --- innobase/buf/buf0flu.c | 12 +- innobase/dict/dict0crea.c | 8 + innobase/dict/dict0dict.c | 674 +++++++++++++++++++++++++++++------ innobase/dict/dict0load.c | 39 +- innobase/ibuf/ibuf0ibuf.c | 13 +- innobase/include/db0err.h | 2 + innobase/include/dict0dict.h | 35 ++ innobase/include/row0ins.h | 1 - innobase/lock/lock0lock.c | 42 ++- innobase/os/os0file.c | 22 +- innobase/row/row0ins.c | 160 ++++++++- innobase/row/row0mysql.c | 121 +++++-- innobase/row/row0sel.c | 35 +- innobase/row/row0upd.c | 2 +- innobase/srv/srv0srv.c | 22 +- innobase/ut/ut0ut.c | 2 +- sql/ha_innodb.cc | 14 + 17 files changed, 999 insertions(+), 205 deletions(-) diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 78bde60c9b2..516056b5174 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -106,7 +106,7 @@ buf_flush_ready_for_replace( BUF_BLOCK_FILE_PAGE and in the LRU list*/ { ut_ad(mutex_own(&(buf_pool->mutex))); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) || (block->buf_fix_count != 0) @@ -227,7 +227,9 @@ buf_flush_buffered_writes(void) } for (i = 0; i < trx_doublewrite->first_free; i++) { + block = trx_doublewrite->buf_block_arr[i]; + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (block->check_index_page_at_flush && !page_simple_validate(block->frame)) { @@ -236,10 +238,12 @@ buf_flush_buffered_writes(void) ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Apparent corruption of an index page\n" + " InnoDB: Apparent corruption of an index page n:o %lu in space %lu\n" "InnoDB: to be written to data file. We intentionally crash server\n" "InnoDB: to prevent corrupt data from ending up in data\n" - "InnoDB: files.\n"); + "InnoDB: files.\n", + block->offset, block->space); + ut_a(0); } } @@ -432,6 +436,8 @@ buf_flush_try_page( block = buf_page_hash_get(space, offset); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + if (flush_type == BUF_FLUSH_LIST && block && buf_flush_ready_for_flush(block, flush_type)) { diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index b0f84e5663a..3619ac02f4d 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -1173,6 +1173,7 @@ dict_create_add_foreigns_to_dictionary( if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) { fprintf(stderr, "InnoDB: table SYS_FOREIGN not found from internal data dictionary\n"); + return(DB_ERROR); } @@ -1259,6 +1260,13 @@ loop: "InnoDB: at http://www.innodb.com/ibman.html\n"); } + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Internal error in foreign key constraint creation for table %.500s.\n" +"See the MySQL .err log in the datadir for more information.\n", table->name); + mutex_exit(&dict_foreign_err_mutex); + return(error); } diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index c70e848c5c8..74fe5cd5b70 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -185,6 +185,12 @@ dict_foreign_free( /*==============*/ dict_foreign_t* foreign); /* in, own: foreign key struct */ +/* Buffer for storing detailed information about the latest foreig key +error */ +char* dict_foreign_err_buf = NULL; +mutex_t dict_foreign_err_mutex; /* mutex protecting the buffer */ + + /************************************************************************ Checks if the database name in two table names is the same. */ static @@ -573,6 +579,11 @@ dict_init(void) rw_lock_create(&dict_operation_lock); rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION); + + dict_foreign_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN); + dict_foreign_err_buf[0] = '\0'; + mutex_create(&dict_foreign_err_mutex); + mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH); } /************************************************************************** @@ -1818,6 +1829,7 @@ dict_foreign_add_to_cache( dict_foreign_t* for_in_cache = NULL; dict_index_t* index; ibool added_to_referenced_list = FALSE; + char* buf = dict_foreign_err_buf; ut_ad(mutex_own(&(dict_sys->mutex))); @@ -1850,9 +1862,29 @@ dict_foreign_add_to_cache( for_in_cache->foreign_index); if (index == NULL) { + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s:\n" +"there is no index in referenced table which would contain\n" +"the columns as the first columns, or the data types in the\n" +"referenced table do not match to the ones in table. Constraint:\n", + for_in_cache->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + for_in_cache, buf + strlen(buf)); + if (for_in_cache->foreign_index) { + sprintf(buf + strlen(buf), +"\nThe index in the foreign key in table is %.500s\n" +"See http://www.innodb.com/ibman.html about correct foreign key definition.\n", + for_in_cache->foreign_index->name); + } + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + if (for_in_cache == foreign) { mem_heap_free(foreign->heap); } + return(DB_CANNOT_ADD_CONSTRAINT); } @@ -1871,6 +1903,25 @@ dict_foreign_add_to_cache( for_in_cache->referenced_index); if (index == NULL) { + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s:\n" +"there is no index in the table which would contain\n" +"the columns as the first columns, or the data types in the\n" +"table do not match to the ones in the referenced table. Constraint:\n", + for_in_cache->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + for_in_cache, buf + strlen(buf)); + if (for_in_cache->foreign_index) { + sprintf(buf + strlen(buf), +"\nIndex of the foreign key in the referenced table is %.500s\n" +"See http://www.innodb.com/ibman.html about correct foreign key definition.\n", + for_in_cache->referenced_index->name); + } + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + if (for_in_cache == foreign) { if (added_to_referenced_list) { UT_LIST_REMOVE(referenced_list, @@ -2038,7 +2089,7 @@ dict_scan_col( if (*ptr == '`') { ptr++; } - + return(ptr); } @@ -2141,18 +2192,21 @@ dict_scan_table_name( } /************************************************************************* -Skips one 'word', like an id. For the lexical definition of 'word', see the -code below. */ +Scans an id. For the lexical definition of an 'id', see the code below. +Strips backquotes from around the id. */ static char* -dict_skip_word( -/*===========*/ +dict_scan_id( +/*=========*/ /* out: scanned to */ char* ptr, /* in: scanned to */ - ibool* success)/* out: TRUE if success, FALSE if just spaces left in - string */ + char** start, /* out: start of the id; NULL if no id was + scannable */ + ulint* len) /* out: length of the id */ { - *success = FALSE; + ibool scanned_backquote = FALSE; + + *start = NULL; while (isspace(*ptr)) { ptr++; @@ -2164,20 +2218,58 @@ dict_skip_word( } if (*ptr == '`') { + scanned_backquote = TRUE; ptr++; } - while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`' - && *ptr != '\0') { + *start = ptr; + + while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != ')' + && *ptr != '\0' && *ptr != '`') { ptr++; } - *success = TRUE; + *len = (ulint) (ptr - *start); + + if (scanned_backquote) { + if (*ptr == '`') { + ptr++; + } else { + /* Syntax error */ + *start = NULL; + } + } return(ptr); } +/************************************************************************* +Skips one id. */ +static +char* +dict_skip_word( +/*===========*/ + /* out: scanned to */ + char* ptr, /* in: scanned to */ + ibool* success)/* out: TRUE if success, FALSE if just spaces left in + string or a syntax error */ +{ + char* start; + ulint len; + + *success = FALSE; + + ptr = dict_scan_id(ptr, &start, &len); + + if (start) { + *success = TRUE; + } + + return(ptr); +} + +#ifdef currentlynotused /************************************************************************* Returns the number of opening brackets '(' subtracted by the number of closing brackets ')' between string and ptr. */ @@ -2204,6 +2296,106 @@ dict_bracket_count( return(count); } +#endif + +/************************************************************************* +Removes MySQL comments from an SQL string. A comment is either +(a) '#' to the end of the line, +(b) '--' to the end of the line, or +(c) '' till the next '' (like the familiar +C comment syntax). */ +static +char* +dict_strip_comments( +/*================*/ + /* out, own: SQL string stripped from + comments; the caller must free this + with mem_free()! */ + char* sql_string) /* in: SQL string */ +{ + char* str; + char* sptr; + char* ptr; + + str = mem_alloc(strlen(sql_string) + 1); + + sptr = sql_string; + ptr = str; + + for (;;) { + if (*sptr == '\0') { + *ptr = '\0'; + + return(str); + } + + if (*sptr == '#' + || (strlen(sptr) >= 3 && 0 == memcmp("-- ", sptr, 3))) { + for (;;) { + /* In Unix a newline is 0x0D while in Windows + it is 0x0A followed by 0x0D */ + + if (*sptr == (char)0x0A + || *sptr == (char)0x0D + || *sptr == '\0') { + + break; + } + + sptr++; + } + } + + if (strlen(sptr) >= 2 && *sptr == '/' && *(sptr + 1) == '*') { + for (;;) { + if (strlen(sptr) >= 2 + && *sptr == '*' && *(sptr + 1) == '/') { + + sptr += 2; + + break; + } + + if (*sptr == '\0') { + + break; + } + + sptr++; + } + } + + *ptr = *sptr; + + ptr++; + sptr++; + } +} + +/************************************************************************* +Reports a simple foreign key create clause syntax error. */ +static +void +dict_foreign_report_syntax_err( +/*===========================*/ + char* name, /* in: table name */ + char* start_of_latest_foreign,/* in: start of the foreign key clause + in the SQL string */ + char* ptr) /* in: place of the syntax error */ +{ + char* buf = dict_foreign_err_buf; + + mutex_enter(&dict_foreign_err_mutex); + + ut_sprintf_timestamp(buf); + + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s,\n%.500s.\n" +"Syntax error close to:\n%.500s\n", name, start_of_latest_foreign, ptr); + + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); +} /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign @@ -2211,10 +2403,10 @@ key constraints declared in the string. This function should be called after the indexes for a table have been created. Each foreign key constraint must be accompanied with indexes in both participating tables. The indexes are allowed to contain more fields than mentioned in the constraint. */ - +static ulint -dict_create_foreign_constraints( -/*============================*/ +dict_create_foreign_constraints_low( +/*================================*/ /* out: error code or DB_SUCCESS */ trx_t* trx, /* in: transaction */ char* sql_string, /* in: table create or ALTER TABLE @@ -2230,7 +2422,9 @@ dict_create_foreign_constraints( dict_table_t* referenced_table; dict_index_t* index; dict_foreign_t* foreign; - char* ptr = sql_string; + char* ptr = sql_string; + char* start_of_latest_foreign = sql_string; + char* buf = dict_foreign_err_buf; ibool success; ulint error; ulint i; @@ -2248,6 +2442,15 @@ dict_create_foreign_constraints( table = dict_table_get_low(name); if (table == NULL) { + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s.\n" +"Cannot find the table from the internal data dictionary of InnoDB.\n" +"Create table statement:\n%.2000\n", name, sql_string); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_ERROR); } loop: @@ -2263,6 +2466,8 @@ loop: return(error); } + start_of_latest_foreign = ptr; + ptr = dict_accept(ptr, (char *) "FOREIGN", &success); if (!isspace(*ptr)) { @@ -2283,13 +2488,19 @@ loop: ptr = dict_skip_word(ptr, &success); if (!success) { + dict_foreign_report_syntax_err(name, + start_of_latest_foreign, ptr); + return(DB_CANNOT_ADD_CONSTRAINT); } ptr = dict_accept(ptr, (char *) "(", &success); if (!success) { - return(DB_CANNOT_ADD_CONSTRAINT); + /* We do not flag a syntax error here because in an + ALTER TABLE we may also have DROP FOREIGN KEY abc */ + + goto loop; } } @@ -2300,6 +2511,15 @@ col_loop1: ptr = dict_scan_col(ptr, &success, table, columns + i, column_names + i, column_name_lens + i); if (!success) { + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s,\n%.500s.\n" +"Cannot resolve column name close to:\n%.500s\n", name, + start_of_latest_foreign, ptr); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2314,6 +2534,8 @@ col_loop1: ptr = dict_accept(ptr, (char *) ")", &success); if (!success) { + dict_foreign_report_syntax_err(name, start_of_latest_foreign, + ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2323,12 +2545,24 @@ col_loop1: index = dict_foreign_find_index(table, column_names, i, NULL); if (!index) { + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s:\n" +"There is no index in the table %.500s where the columns appear\n" +"as the first columns. Constraint:\n%.500s\n" +"See http://www.innodb.com/ibman.html for correct foreign key definition.\n", + name, name, start_of_latest_foreign); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, (char *) "REFERENCES", &success); if (!success || !isspace(*ptr)) { + dict_foreign_report_syntax_err(name, start_of_latest_foreign, + ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2358,6 +2592,15 @@ col_loop1: if (!success || (!referenced_table && trx->check_foreigns)) { dict_foreign_free(foreign); + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s,\n%.500s.\n" +"Cannot resolve table name close to:\n" +"%.500s\n", name, start_of_latest_foreign, ptr); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2365,7 +2608,8 @@ col_loop1: if (!success) { dict_foreign_free(foreign); - + dict_foreign_report_syntax_err(name, start_of_latest_foreign, + ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2380,6 +2624,15 @@ col_loop2: if (!success) { dict_foreign_free(foreign); + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s,\n%.500s\n" +"Cannot resolve column name close to:\n" +"%.500s\n", name, start_of_latest_foreign, ptr); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2394,6 +2647,8 @@ col_loop2: if (!success || foreign->n_fields != i) { dict_foreign_free(foreign); + dict_foreign_report_syntax_err(name, start_of_latest_foreign, + ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2416,9 +2671,10 @@ scan_on_conditions: ptr = dict_accept(ptr, "UPDATE", &success); if (!success) { - dict_foreign_free(foreign); + dict_foreign_report_syntax_err(name, + start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2454,6 +2710,8 @@ scan_on_conditions: if (!success) { dict_foreign_free(foreign); + dict_foreign_report_syntax_err(name, + start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2471,7 +2729,8 @@ scan_on_conditions: if (!success) { dict_foreign_free(foreign); - + dict_foreign_report_syntax_err(name, start_of_latest_foreign, + ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2479,7 +2738,8 @@ scan_on_conditions: if (!success) { dict_foreign_free(foreign); - + dict_foreign_report_syntax_err(name, start_of_latest_foreign, + ptr); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2493,6 +2753,15 @@ scan_on_conditions: dict_foreign_free(foreign); + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s,\n%.500s.\n" +"You have defined a SET NULL condition though some of the\n" +"columns is defined as NOT NULL.\n", name, start_of_latest_foreign); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_CANNOT_ADD_CONSTRAINT); } } @@ -2511,6 +2780,15 @@ try_find_index: dict_foreign_free(foreign); + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s,\n%.500s.\n" +"You have twice an ON DELETE clause or twice an ON UPDATE clause.\n", + name, start_of_latest_foreign); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2524,6 +2802,18 @@ try_find_index: foreign->foreign_index); if (!index) { dict_foreign_free(foreign); + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in foreign key constraint of table %.500s:\n" +"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%.500s\n" +"See http://www.innodb.com/ibman.html for correct foreign key definition.\n", + name, start_of_latest_foreign); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_CANNOT_ADD_CONSTRAINT); } } else { @@ -2564,6 +2854,165 @@ try_find_index: goto loop; } +/************************************************************************* +Scans a table create SQL string and adds to the data dictionary the foreign +key constraints declared in the string. This function should be called after +the indexes for a table have been created. Each foreign key constraint must +be accompanied with indexes in both participating tables. The indexes are +allowed to contain more fields than mentioned in the constraint. */ + +ulint +dict_create_foreign_constraints( +/*============================*/ + /* out: error code or DB_SUCCESS */ + trx_t* trx, /* in: transaction */ + char* sql_string, /* in: table create or ALTER TABLE + statement where foreign keys are declared like: + FOREIGN KEY (a, b) REFERENCES table2(c, d), + table2 can be written also with the database + name before it: test.table2; the default + database id the database of parameter name */ + char* name) /* in: table full name in the normalized form + database_name/table_name */ +{ + char* str; + ulint err; + + str = dict_strip_comments(sql_string); + + err = dict_create_foreign_constraints_low(trx, str, name); + + mem_free(str); + + return(err); +} + +/************************************************************************** +Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */ + +ulint +dict_foreign_parse_drop_constraints( +/*================================*/ + /* out: DB_SUCCESS or + DB_CANNOT_DROP_CONSTRAINT if + syntax error or the constraint + id does not match */ + mem_heap_t* heap, /* in: heap from which we can + allocate memory */ + trx_t* trx, /* in: transaction */ + dict_table_t* table, /* in: table */ + ulint* n, /* out: number of constraints + to drop */ + char*** constraints_to_drop) /* out: id's of the + constraints to drop */ +{ + dict_foreign_t* foreign; + ibool success; + char* str; + char* ptr; + char* buf = dict_foreign_err_buf; + char* start; + char* id; + ulint len; + + *n = 0; + + *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*)); + + str = dict_strip_comments(*(trx->mysql_query_str)); + ptr = str; + + ut_ad(mutex_own(&(dict_sys->mutex))); +loop: + ptr = dict_scan_to(ptr, (char *) "DROP"); + + if (*ptr == '\0') { + ut_a(*n < 1000); + + mem_free(str); + + return(DB_SUCCESS); + } + + ptr = dict_accept(ptr, (char *) "DROP", &success); + + if (!isspace(*ptr)) { + + goto loop; + } + + ptr = dict_accept(ptr, (char *) "FOREIGN", &success); + + if (!success) { + + goto loop; + } + + ptr = dict_accept(ptr, (char *) "KEY", &success); + + if (!success) { + + goto syntax_error; + } + + ptr = dict_scan_id(ptr, &start, &len); + + if (start == NULL) { + + goto syntax_error; + } + + id = mem_heap_alloc(heap, len + 1); + ut_memcpy(id, start, len); + id[len] = '\0'; + (*constraints_to_drop)[*n] = id; + (*n)++; + + /* Look for the given constraint id */ + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + + while (foreign != NULL) { + if (0 == ut_strcmp(foreign->id, id)) { + + /* Found */ + break; + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + + if (foreign == NULL) { + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Error in dropping of a foreign key constraint of table %.500s,\n" +"just before:\n%s\n in SQL command\n%s\nCannot find a constraint with the\n" +"given id %s.\n", table->name, ptr, str, id); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + + mem_free(str); + + return(DB_CANNOT_DROP_CONSTRAINT); + } + + goto loop; + +syntax_error: + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), +" Syntax error in dropping of a foreign key constraint of table %.500s,\n" +"close to:\n%s\n in SQL command\n%s\n", table->name, ptr, str); + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + + mem_free(str); + + return(DB_CANNOT_DROP_CONSTRAINT); +} + /*==================== END OF FOREIGN KEY PROCESSING ====================*/ /************************************************************************** @@ -3285,7 +3734,6 @@ dict_index_print_low( n_vals = index->stat_n_diff_key_vals[1]; } - printf( " INDEX: name %s, table name %s, id %lu %lu, fields %lu/%lu, type %lu\n", index->name, index->table_name, @@ -3326,6 +3774,99 @@ dict_field_print_low( printf(" %s", field->name); } +/************************************************************************** +Sprintfs to a string info on a foreign key of a table in a format suitable +for CREATE TABLE. */ + +char* +dict_print_info_on_foreign_key_in_create_format( +/*============================================*/ + /* out: how far in buf we printed */ + dict_foreign_t* foreign,/* in: foreign key constraint */ + char* buf) /* in: buffer of at least 5000 bytes */ +{ + char* buf2 = buf; + ulint i; + + buf2 += sprintf(buf2, ",\n CONSTRAINT `%s` FOREIGN KEY (", + foreign->id); + for (i = 0; i < foreign->n_fields; i++) { + if ((ulint)(buf2 - buf) >= 4000) { + + goto no_space; + } + buf2 += sprintf(buf2, "`%.250s`", + foreign->foreign_col_names[i]); + + if (i + 1 < foreign->n_fields) { + buf2 += sprintf(buf2, ", "); + } + } + + if (dict_tables_have_same_db(foreign->foreign_table_name, + foreign->referenced_table_name)) { + /* Do not print the database name of the referenced + table */ + buf2 += sprintf(buf2, ") REFERENCES `%.500s` (", + dict_remove_db_name( + foreign->referenced_table_name)); + } else { + buf2 += sprintf(buf2, ") REFERENCES `%.500s` (", + foreign->referenced_table_name); + /* Change the '/' in the table name to '.' */ + + for (i = ut_strlen(buf); i > 0; i--) { + if (buf[i] == '/') { + + buf[i] = '.'; + + break; + } + } + } + + for (i = 0; i < foreign->n_fields; i++) { + if ((ulint)(buf2 - buf) >= 4000) { + + goto no_space; + } + buf2 += sprintf(buf2, "`%.250s`", + foreign->referenced_col_names[i]); + if (i + 1 < foreign->n_fields) { + buf2 += sprintf(buf2, ", "); + } + } + + buf2 += sprintf(buf2, ")"); + + if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) { + buf2 += sprintf(buf2, " ON DELETE CASCADE"); + } + + if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) { + buf2 += sprintf(buf2, " ON DELETE SET NULL"); + } + + if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) { + buf2 += sprintf(buf2, " ON DELETE NO ACTION"); + } + + if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { + buf2 += sprintf(buf2, " ON UPDATE CASCADE"); + } + + if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { + buf2 += sprintf(buf2, " ON UPDATE SET NULL"); + } + + if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) { + buf2 += sprintf(buf2, " ON UPDATE NO ACTION"); + } + +no_space: + return(buf2); +} + /************************************************************************** Sprintfs to a string info on foreign keys of a table in a format suitable for CREATE TABLE. */ @@ -3335,13 +3876,12 @@ dict_print_info_on_foreign_keys_in_create_format( /*=============================================*/ char* buf, /* in: auxiliary buffer */ char* str, /* in/out: pointer to a string */ - ulint len, /* in: str has to be a buffer at least - len + 5000 bytes */ + ulint len, /* in: buf has to be a buffer of at least + len + 5000 bytes; str must have at least + len + 1 bytes */ dict_table_t* table) /* in: table */ { - dict_foreign_t* foreign; - ulint i; char* buf2; buf2 = buf; @@ -3357,78 +3897,12 @@ dict_print_info_on_foreign_keys_in_create_format( } while (foreign != NULL) { - buf2 += sprintf(buf2, ",\n FOREIGN KEY ("); + if ((ulint)(buf2 - buf) >= len) { + goto no_space; + } - for (i = 0; i < foreign->n_fields; i++) { - if ((ulint)(buf2 - buf) >= len) { - goto no_space; - } - buf2 += sprintf(buf2, "`%s`", - foreign->foreign_col_names[i]); - - if (i + 1 < foreign->n_fields) { - buf2 += sprintf(buf2, ", "); - } - } - - if (dict_tables_have_same_db(table->name, - foreign->referenced_table_name)) { - /* Do not print the database name of the referenced - table */ - buf2 += sprintf(buf2, ") REFERENCES `%s` (", - dict_remove_db_name( - foreign->referenced_table_name)); - } else { - buf2 += sprintf(buf2, ") REFERENCES `%s` (", - foreign->referenced_table_name); - /* Change the '/' in the table name to '.' */ - - for (i = ut_strlen(buf); i > 0; i--) { - if (buf[i] == '/') { - - buf[i] = '.'; - - break; - } - } - } - - for (i = 0; i < foreign->n_fields; i++) { - if ((ulint)(buf2 - buf) >= len) { - goto no_space; - } - buf2 += sprintf(buf2, "`%s`", - foreign->referenced_col_names[i]); - if (i + 1 < foreign->n_fields) { - buf2 += sprintf(buf2, ", "); - } - } - - buf2 += sprintf(buf2, ")"); - - if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) { - buf2 += sprintf(buf2, " ON DELETE CASCADE"); - } - - if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) { - buf2 += sprintf(buf2, " ON DELETE SET NULL"); - } - - if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) { - buf2 += sprintf(buf2, " ON DELETE NO ACTION"); - } - - if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) { - buf2 += sprintf(buf2, " ON UPDATE CASCADE"); - } - - if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) { - buf2 += sprintf(buf2, " ON UPDATE SET NULL"); - } - - if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) { - buf2 += sprintf(buf2, " ON UPDATE NO ACTION"); - } + buf2 = dict_print_info_on_foreign_key_in_create_format( + foreign, buf2); foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } @@ -3489,7 +3963,7 @@ dict_print_info_on_foreign_keys( goto no_space; } - buf2 += sprintf(buf2, "%s", + buf2 += sprintf(buf2, "%.500s", foreign->foreign_col_names[i]); if (i + 1 < foreign->n_fields) { @@ -3497,14 +3971,14 @@ dict_print_info_on_foreign_keys( } } - buf2 += sprintf(buf2, ") REFER %s(", + buf2 += sprintf(buf2, ") REFER %.500s(", foreign->referenced_table_name); for (i = 0; i < foreign->n_fields; i++) { if ((ulint)(buf2 - buf) >= len) { goto no_space; } - buf2 += sprintf(buf2, "%s", + buf2 += sprintf(buf2, "%.500s", foreign->referenced_col_names[i]); if (i + 1 < foreign->n_fields) { buf2 += sprintf(buf2, " "); diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index d8d426d2036..8f39605e493 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -456,7 +456,7 @@ dict_load_indexes( ut_ad(len == 8); id = mach_read_from_8(field); - ut_a(0 == ut_strcmp("NAME", + ut_a(0 == ut_strcmp((char*)"NAME", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_indexes), 4))->name)); @@ -515,7 +515,7 @@ dict_load_indexes( && ((type & DICT_CLUSTERED) || ((table == dict_sys->sys_tables) && (name_len == ut_strlen("ID_IND")) - && (0 == ut_memcmp(name_buf, "ID_IND", + && (0 == ut_memcmp(name_buf, (char*)"ID_IND", name_len))))) { /* The index was created in memory already in @@ -566,6 +566,7 @@ dict_load_table( char* buf; ulint space; ulint n_cols; + ulint err; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); @@ -674,8 +675,25 @@ dict_load_table( dict_load_indexes(table, heap); - ut_a(DB_SUCCESS == dict_load_foreigns(table->name)); + err = dict_load_foreigns(table->name); +/* + if (err != DB_SUCCESS) { + + mutex_enter(&dict_foreign_err_mutex); + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Error: could not make a foreign key definition to match\n" +"InnoDB: the foreign key table or the referenced table!\n" +"InnoDB: The data dictionary of InnoDB is corrupt. You may need to drop\n" +"InnoDB: and recreate the foreign key table or the referenced table.\n" +"InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n" +"InnoDB: Latest foreign key error printout:\n%s\n", dict_foreign_err_buf); + + mutex_exit(&dict_foreign_err_mutex); + } +*/ mem_heap_free(heap); return(table); @@ -978,8 +996,8 @@ dict_load_foreign( field = rec_get_nth_field(rec, 4, &len); - foreign->referenced_table_name = mem_heap_alloc(foreign->heap, 1 + len); - + foreign->referenced_table_name = mem_heap_alloc(foreign->heap, + 1 + len); ut_memcpy(foreign->referenced_table_name, field, len); foreign->referenced_table_name[len] = '\0'; @@ -988,10 +1006,19 @@ dict_load_foreign( dict_load_foreign_cols(id, foreign); + /* If the foreign table is not yet in the dictionary cache, we + have to load it so that we are able to make type comparisons + in the next function call. */ + + dict_table_get_low(foreign->foreign_table_name); + /* Note that there may already be a foreign constraint object in the dictionary cache for this constraint: then the following call only sets the pointers in it to point to the appropriate table - and index objects and frees the newly created object foreign. */ + and index objects and frees the newly created object foreign. + Adding to the cache should always succeed since we are not creating + a new foreign key constraint but loading one from the data + dictionary. */ err = dict_foreign_add_to_cache(foreign); diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index 5cd066afc27..187afa17047 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -2391,7 +2391,7 @@ ibuf_delete_rec( ut_ad(ibuf_inside()); - success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr); + success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr); if (success) { #ifdef UNIV_IBUF_DEBUG @@ -2401,7 +2401,7 @@ ibuf_delete_rec( return(FALSE); } - /* We have to resort to a pessimistic delete from ibuf */ + /* We have to resort to a pessimistic delete from ibuf */ btr_pcur_store_position(pcur, mtr); btr_pcur_commit_specify_mtr(pcur, mtr); @@ -2420,17 +2420,22 @@ ibuf_delete_rec( fprintf(stderr, "InnoDB: ibuf cursor restoration fails!\n"); fprintf(stderr, "InnoDB: ibuf record inserted to page %lu\n", page_no); + fflush(stderr); + rec_print(btr_pcur_get_rec(pcur)); rec_print(pcur->old_rec); dtuple_print(search_tuple); rec_print(page_rec_get_next(btr_pcur_get_rec(pcur))); + fflush(stdout); mtr_commit(mtr); fprintf(stderr, "InnoDB: Validating insert buffer tree:\n"); - ut_a(btr_validate_tree(ibuf_data->index->tree)); - fprintf(stderr, "InnoDB: Ibuf tree ok\n"); + ut_a(btr_validate_tree(ibuf_data->index->tree)); + + fprintf(stderr, "InnoDB: ibuf tree ok\n"); + fflush(stderr); } ut_a(success); diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h index c67c09bad27..ab7d0caa35c 100644 --- a/innobase/include/db0err.h +++ b/innobase/include/db0err.h @@ -44,6 +44,8 @@ Created 5/24/1996 Heikki Tuuri #define DB_CORRUPTION 39 /* data structure corruption noticed */ #define DB_COL_APPEARS_TWICE_IN_INDEX 40 /* InnoDB cannot handle an index where same column appears twice */ +#define DB_CANNOT_DROP_CONSTRAINT 40 /* dropping a foreign key constraint + from a table failed */ /* The following are partial failure codes */ #define DB_FAIL 1000 diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index b5e6e04a1de..600965700ed 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -219,6 +219,24 @@ dict_create_foreign_constraints( char* name); /* in: table full name in the normalized form database_name/table_name */ /************************************************************************** +Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */ + +ulint +dict_foreign_parse_drop_constraints( +/*================================*/ + /* out: DB_SUCCESS or + DB_CANNOT_DROP_CONSTRAINT if + syntax error or the constraint + id does not match */ + mem_heap_t* heap, /* in: heap from which we can + allocate memory */ + trx_t* trx, /* in: transaction */ + dict_table_t* table, /* in: table */ + ulint* n, /* out: number of constraints + to drop */ + char*** constraints_to_drop); /* out: id's of the + constraints to drop */ +/************************************************************************** Returns a table object and memoryfixes it. NOTE! This is a high-level function to be used mainly from outside the 'dict' directory. Inside this directory dict_table_get_low is usually the appropriate function. */ @@ -333,6 +351,16 @@ dict_print_info_on_foreign_keys( char* str, /* in/out: pointer to a string */ ulint len, /* in: space in str available for info */ dict_table_t* table); /* in: table */ +/************************************************************************** +Sprintfs to a string info on a foreign key of a table in a format suitable +for CREATE TABLE. */ + +char* +dict_print_info_on_foreign_key_in_create_format( +/*============================================*/ + /* out: how far in buf we printed */ + dict_foreign_t* foreign,/* in: foreign key constraint */ + char* buf); /* in: buffer of at least 5000 bytes */ /************************************************************************ Gets the first index on the table (the clustered index). */ UNIV_INLINE @@ -808,6 +836,13 @@ void dict_mutex_exit_for_mysql(void); /*===========================*/ +/* The following len must be at least 10000 bytes! */ +#define DICT_FOREIGN_ERR_BUF_LEN 10000 + +/* Buffer for storing detailed information about the latest foreig key +error */ +extern char* dict_foreign_err_buf; +extern mutex_t dict_foreign_err_mutex; /* mutex protecting the buffer */ extern dict_sys_t* dict_sys; /* the dictionary system */ extern rw_lock_t dict_operation_lock; diff --git a/innobase/include/row0ins.h b/innobase/include/row0ins.h index cc3b9fa7e9a..a5b4b74e7fc 100644 --- a/innobase/include/row0ins.h +++ b/innobase/include/row0ins.h @@ -35,7 +35,6 @@ row_ins_check_foreign_constraint( dictionary cache if they exist at all */ dict_table_t* table, /* in: if check_ref is TRUE, then the foreign table, else the referenced table */ - dict_index_t* index, /* in: index in table */ dtuple_t* entry, /* in: index entry for index */ que_thr_t* thr); /* in: query thread */ /************************************************************************* diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 7b08d6b89b8..4bb1d243ed4 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -3092,8 +3092,7 @@ lock_deadlock_recursive( err_buf += strlen(err_buf); err_buf += sprintf(err_buf, - " LATEST DETECTED DEADLOCK:\n" - "*** (1) TRANSACTION:\n"); + "\n*** (1) TRANSACTION:\n"); trx_print(err_buf, wait_lock->trx); err_buf += strlen(err_buf); @@ -3934,24 +3933,15 @@ lock_print_info( return; } - - buf += sprintf(buf, "Trx id counter %lu %lu\n", - ut_dulint_get_high(trx_sys->max_trx_id), - ut_dulint_get_low(trx_sys->max_trx_id)); - - buf += sprintf(buf, - "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n", - ut_dulint_get_high(purge_sys->purge_trx_no), - ut_dulint_get_low(purge_sys->purge_trx_no), - ut_dulint_get_high(purge_sys->purge_undo_no), - ut_dulint_get_low(purge_sys->purge_undo_no)); lock_mutex_enter_kernel(); - buf += sprintf(buf, - "Total number of lock structs in row lock hash table %lu\n", - lock_get_n_rec_locks()); if (lock_deadlock_found) { + + buf += sprintf(buf, +"------------------------\n" +"LATEST DETECTED DEADLOCK\n" +"------------------------\n"); if ((ulint)(buf_end - buf) < 100 + strlen(lock_latest_err_buf)) { @@ -3972,6 +3962,26 @@ lock_print_info( return; } + buf += sprintf(buf, +"------------\n" +"TRANSACTIONS\n" +"------------\n"); + + buf += sprintf(buf, "Trx id counter %lu %lu\n", + ut_dulint_get_high(trx_sys->max_trx_id), + ut_dulint_get_low(trx_sys->max_trx_id)); + + buf += sprintf(buf, + "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n", + ut_dulint_get_high(purge_sys->purge_trx_no), + ut_dulint_get_low(purge_sys->purge_trx_no), + ut_dulint_get_high(purge_sys->purge_undo_no), + ut_dulint_get_low(purge_sys->purge_undo_no)); + + buf += sprintf(buf, + "Total number of lock structs in row lock hash table %lu\n", + lock_get_n_rec_locks()); + buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n"); /* First print info on non-active transactions */ diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 6324fcdbef1..1d1d84adda7 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -214,9 +214,14 @@ os_file_get_last_error(void) "InnoDB: the directory. It may also be you have created a subdirectory\n" "InnoDB: of the same name as a data file.\n"); } else { - fprintf(stderr, - "InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" - "InnoDB: what the error number means.\n"); + if (strerror((int)err) != NULL) { + fprintf(stderr, + "InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err)); + } + + fprintf(stderr, + "InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n" + "InnoDB: about operating system error numbers.\n"); } } @@ -252,9 +257,14 @@ os_file_get_last_error(void) "InnoDB: The error means mysqld does not have the access rights to\n" "InnoDB: the directory.\n"); } else { - fprintf(stderr, - "InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" - "InnoDB: what the error number means or use the perror program of MySQL.\n"); + if (strerror((int)err) != NULL) { + fprintf(stderr, + "InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err)); + } + + fprintf(stderr, + "InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n" + "InnoDB: about operating system error numbers.\n"); } } diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 990ef99b2a4..1a616b74756 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -437,6 +437,111 @@ row_ins_cascade_calc_update_vec( return(n_fields_updated); } +/************************************************************************* +Reports a foreign key error associated with an update or a delete of a +parent table index entry. */ +static +void +row_ins_foreign_report_err( +/*=======================*/ + char* errstr, /* in: error string from the viewpoint + of the parent table */ + que_thr_t* thr, /* in: query thread whose run_node + is an update node */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + rec_t* rec, /* in: a matching index record in the + child table */ + dtuple_t* entry) /* in: index entry in the parent + table */ +{ + char* buf = dict_foreign_err_buf; + + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), " Transaction:\n"); + trx_print(buf + strlen(buf), thr_get_trx(thr)); + + sprintf(buf + strlen(buf), +"Foreign key constraint fails for table %.500s:\n", + foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + foreign, buf + strlen(buf)); + sprintf(buf + strlen(buf), "\n%s", errstr); + sprintf(buf + strlen(buf), +" in parent table, in index %.500s tuple:\n", + foreign->referenced_index->name); + if (entry) { + dtuple_sprintf(buf + strlen(buf), 1000, entry); + } + sprintf(buf + strlen(buf), +"\nBut in child table %.500s, in index %.500s, there is a record:\n", + foreign->foreign_table_name, foreign->foreign_index->name); + if (rec) { + rec_sprintf(buf + strlen(buf), 1000, rec); + } + sprintf(buf + strlen(buf), "\n"); + + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + + mutex_exit(&dict_foreign_err_mutex); +} + +/************************************************************************* +Reports a foreign key error to dict_foreign_err_buf when we are trying +to add an index entry to a child table. Note that the adding may be the result +of an update, too. */ +static +void +row_ins_foreign_report_add_err( +/*===========================*/ + que_thr_t* thr, /* in: query thread whose run_node + is an insert node */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + rec_t* rec, /* in: a record in the parent table: + it does not match entry because we + have an error! */ + dtuple_t* entry) /* in: index entry to insert in the + child table */ +{ + char* buf = dict_foreign_err_buf; + + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), " Transaction:\n"); + trx_print(buf + strlen(buf), thr_get_trx(thr)); + sprintf(buf + strlen(buf), +"Foreign key constraint fails for table %.500s:\n", + foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + foreign, buf + strlen(buf)); + sprintf(buf + strlen(buf), +"\nTrying to add in child table, in index %.500s tuple:\n", + foreign->foreign_index->name); + if (entry) { + dtuple_sprintf(buf + strlen(buf), 1000, entry); + } + sprintf(buf + strlen(buf), +"\nBut in parent table %.500s, in index %.500s,\n" +"the closest match we can find is record:\n", + foreign->referenced_table_name, + foreign->referenced_index->name); + if (rec && page_rec_is_supremum(rec)) { + /* If the cursor ended on a supremum record, it is better + to report the previous record in the error message, so that + the user gets a more descriptive error message. */ + rec = page_rec_get_prev(rec); + } + + if (rec) { + rec_sprintf(buf + strlen(buf), 1000, rec); + } + sprintf(buf + strlen(buf), "\n"); + + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + + mutex_exit(&dict_foreign_err_mutex); +} + /************************************************************************* Perform referential actions or checks when a parent row is deleted or updated and the constraint had an ON DELETE or ON UPDATE condition which was not @@ -453,6 +558,8 @@ row_ins_foreign_check_on_constraint( type is != 0 */ btr_pcur_t* pcur, /* in: cursor placed on a matching index record in the child table */ + dtuple_t* entry, /* in: index entry in the parent + table */ mtr_t* mtr) /* in: mtr holding the latch of pcur page */ { @@ -506,6 +613,10 @@ row_ins_foreign_check_on_constraint( return(DB_SUCCESS); } + row_ins_foreign_report_err((char*)"Trying to delete", + thr, foreign, + btr_pcur_get_rec(pcur), entry); + return(DB_ROW_IS_REFERENCED); } @@ -523,6 +634,10 @@ row_ins_foreign_check_on_constraint( return(DB_SUCCESS); } + row_ins_foreign_report_err((char*)"Trying to update", + thr, foreign, + btr_pcur_get_rec(pcur), entry); + return(DB_ROW_IS_REFERENCED); } @@ -580,6 +695,10 @@ row_ins_foreign_check_on_constraint( err = DB_ROW_IS_REFERENCED; + row_ins_foreign_report_err( +(char*)"Trying an update, possibly causing a cyclic cascaded update\n" +"in the child table,", thr, foreign, btr_pcur_get_rec(pcur), entry); + goto nonstandard_exit_func; } @@ -809,11 +928,10 @@ row_ins_check_foreign_constraint( dictionary cache if they exist at all */ dict_table_t* table, /* in: if check_ref is TRUE, then the foreign table, else the referenced table */ - dict_index_t* index __attribute__((unused)),/* in: index in table */ dtuple_t* entry, /* in: index entry for index */ que_thr_t* thr) /* in: query thread */ { - upd_node_t* upd_node; + upd_node_t* upd_node; dict_table_t* check_table; dict_index_t* check_index; ulint n_fields_cmp; @@ -824,6 +942,7 @@ row_ins_check_foreign_constraint( int cmp; ulint err; ulint i; + char* buf = dict_foreign_err_buf; mtr_t mtr; run_again: @@ -884,6 +1003,25 @@ run_again: if (check_table == NULL) { if (check_ref) { + mutex_enter(&dict_foreign_err_mutex); + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), " Transaction:\n"); + trx_print(buf + strlen(buf), thr_get_trx(thr)); + sprintf(buf + strlen(buf), +"Foreign key constraint fails for table %.500s:\n", + foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + foreign, buf + strlen(buf)); + sprintf(buf + strlen(buf), +"\nTrying to add to index %.500s tuple:\n", foreign->foreign_index->name); + dtuple_sprintf(buf + strlen(buf), 1000, entry); + sprintf(buf + strlen(buf), +"\nBut the parent table %.500s does not currently exist!\n", + foreign->referenced_table_name); + + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + mutex_exit(&dict_foreign_err_mutex); + return(DB_NO_REFERENCED_ROW); } @@ -949,7 +1087,8 @@ run_again: if (cmp == 0) { if (rec_get_deleted_flag(rec)) { - err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, + err = row_ins_set_shared_rec_lock( + LOCK_ORDINARY, rec, check_index, thr); if (err != DB_SUCCESS) { @@ -989,13 +1128,17 @@ run_again: err = row_ins_foreign_check_on_constraint( - thr, foreign, &pcur, &mtr); - + thr, foreign, &pcur, entry, + &mtr); if (err != DB_SUCCESS) { break; } } else { + row_ins_foreign_report_err( + (char*)"Trying to delete or update", + thr, foreign, rec, entry); + err = DB_ROW_IS_REFERENCED; break; } @@ -1012,6 +1155,8 @@ run_again: if (check_ref) { err = DB_NO_REFERENCED_ROW; + row_ins_foreign_report_add_err( + thr, foreign, rec, entry); } else { err = DB_SUCCESS; } @@ -1025,6 +1170,9 @@ next_rec: if (!moved) { if (check_ref) { + rec = btr_pcur_get_rec(&pcur); + row_ins_foreign_report_add_err( + thr, foreign, rec, entry); err = DB_NO_REFERENCED_ROW; } else { err = DB_SUCCESS; @@ -1100,7 +1248,7 @@ row_ins_check_foreign_constraints( } err = row_ins_check_foreign_constraint(TRUE, foreign, - table, index, entry, thr); + table, entry, thr); if (got_s_lock) { row_mysql_unfreeze_data_dictionary(trx); } diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 0ca1a7516e0..81ed94e2628 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -6,7 +6,7 @@ Contains also create table and other data dictionary operations. Created 9/17/2000 Heikki Tuuri *******************************************************/ - + #include "row0mysql.h" #ifdef UNIV_NONINL @@ -1156,7 +1156,7 @@ row_mysql_recover_tmp_table( return(DB_ERROR); } - if (0 == ut_memcmp(ptr, "/rsql", 5)) { + if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) { ptr++; *ptr = '#'; @@ -1280,10 +1280,10 @@ row_create_table_for_mysql( } trx->op_info = (char *) "creating table"; - - if (0 == ut_strcmp(table->name, "mysql/host") - || 0 == ut_strcmp(table->name, "mysql/user") - || 0 == ut_strcmp(table->name, "mysql/db")) { + + if (0 == ut_strcmp(table->name, (char*)"mysql/host") + || 0 == ut_strcmp(table->name, (char*)"mysql/user") + || 0 == ut_strcmp(table->name, (char*)"mysql/db")) { fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" @@ -1303,7 +1303,7 @@ row_create_table_for_mysql( if (namelen >= keywordlen && 0 == ut_memcmp(table->name + namelen - keywordlen, - "_recover_innodb_tmp_table", keywordlen)) { + (char*)"_recover_innodb_tmp_table", keywordlen)) { /* MySQL prevents accessing of tables whose name begins with #sql, that is temporary tables. If mysqld crashes in @@ -1371,7 +1371,7 @@ row_create_table_for_mysql( if (namelen >= keywordlen && 0 == ut_memcmp(table->name + namelen - keywordlen, - "innodb_mem_validate", keywordlen)) { + (char*)"innodb_mem_validate", keywordlen)) { /* We define here a debugging feature intended for developers */ @@ -1481,7 +1481,7 @@ row_create_index_for_mysql( if (namelen >= keywordlen && 0 == ut_memcmp( index->table_name + namelen - keywordlen, - "_recover_innodb_tmp_table", keywordlen)) { + (char*)"_recover_innodb_tmp_table", keywordlen)) { return(DB_SUCCESS); } @@ -1586,7 +1586,7 @@ row_table_add_foreign_constraints( if (namelen >= keywordlen && 0 == ut_memcmp( name + namelen - keywordlen, - "_recover_innodb_tmp_table", keywordlen)) { + (char*)"_recover_innodb_tmp_table", keywordlen)) { return(DB_SUCCESS); } @@ -1808,7 +1808,6 @@ row_drop_table_for_mysql( ulint len; ulint namelen; ulint keywordlen; - ulint rounds = 0; ibool locked_dictionary = FALSE; char buf[10000]; @@ -2155,7 +2154,7 @@ row_is_mysql_tmp_table_name( ulint i; for (i = 0; i <= ut_strlen(name) - 5; i++) { - if (ut_memcmp(name + i, "/#sql", 5) == 0) { + if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) { return(TRUE); } @@ -2177,12 +2176,16 @@ row_rename_table_for_mysql( { dict_table_t* table; que_thr_t* thr; - que_t* graph; + que_t* graph = NULL; ulint err; char* str1; char* str2; char* str3; + mem_heap_t* heap = NULL; + char** constraints_to_drop = NULL; + ulint n_constraints_to_drop = 0; ulint len; + ulint i; char buf[10000]; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -2200,10 +2203,10 @@ row_rename_table_for_mysql( trx_commit_for_mysql(trx); return(DB_ERROR); } - - if (0 == ut_strcmp(new_name, "mysql/host") - || 0 == ut_strcmp(new_name, "mysql/user") - || 0 == ut_strcmp(new_name, "mysql/db")) { + + if (0 == ut_strcmp(new_name, (char*)"mysql/host") + || 0 == ut_strcmp(new_name, (char*)"mysql/user") + || 0 == ut_strcmp(new_name, (char*)"mysql/db")) { fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" @@ -2217,6 +2220,19 @@ row_rename_table_for_mysql( trx->op_info = (char *) "renaming table"; trx_start_if_not_started(trx); + /* Serialize data dictionary operations with dictionary mutex: + no deadlocks can occur then in these operations */ + + row_mysql_lock_data_dictionary(trx); + + table = dict_table_get_low(old_name); + + if (!table) { + err = DB_TABLE_NOT_FOUND; + + goto funct_exit; + } + str1 = (char *) "PROCEDURE RENAME_TABLE_PROC () IS\n" "new_table_name CHAR;\n" @@ -2229,14 +2245,43 @@ row_rename_table_for_mysql( if (row_is_mysql_tmp_table_name(new_name)) { - /* We want to preserve the original foreign key - constraint definitions despite the name change */ + /* MySQL is doing an ALTER TABLE command and it renames the + original table to a temporary table name. We want to preserve + the original foreign key constraint definitions despite the + name change. An exception is those constraints for which + the ALTER TABLE contained DROP FOREIGN KEY .*/ - str3 = (char*) - "';\n" - "UPDATE SYS_TABLES SET NAME = new_table_name\n" - "WHERE NAME = old_table_name;\n" - "END;\n"; + heap = mem_heap_create(100); + + err = dict_foreign_parse_drop_constraints(heap, trx, + table, + &n_constraints_to_drop, + &constraints_to_drop); + if (err != DB_SUCCESS) { + + goto funct_exit; + } + + str3 = mem_heap_alloc(heap, + 1000 + 500 * n_constraints_to_drop); + *str3 = '\0'; + sprintf(str3, + "';\n" + "UPDATE SYS_TABLES SET NAME = new_table_name\n" + "WHERE NAME = old_table_name;\n"); + + for (i = 0; i < n_constraints_to_drop; i++) { + sprintf(str3 + strlen(str3), + "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n" + "DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n", + constraints_to_drop[i], + constraints_to_drop[i]); + } + + sprintf(str3 + strlen(str3), + "END;\n"); + + ut_a(strlen(str3) < 1000 + 500 * n_constraints_to_drop); } else { str3 = (char*) "';\n" @@ -2267,13 +2312,6 @@ row_rename_table_for_mysql( ut_memcpy(buf + len, str3, ut_strlen(str3) + 1); - /* Serialize data dictionary operations with dictionary mutex: - no deadlocks can occur then in these operations */ - - row_mysql_lock_data_dictionary(trx); - - table = dict_table_get_low(old_name); - graph = pars_sql(buf); ut_a(graph); @@ -2283,12 +2321,6 @@ row_rename_table_for_mysql( graph->fork_type = QUE_FORK_MYSQL_INTERFACE; - if (!table) { - err = DB_TABLE_NOT_FOUND; - - goto funct_exit; - } - ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0)); que_run_threads(thr); @@ -2329,6 +2361,13 @@ row_rename_table_for_mysql( if (row_is_mysql_tmp_table_name(old_name)) { + /* MySQL is doing an ALTER TABLE command and it + renames the created temporary table to the name + of the original table. In the ALTER TABLE we maybe + created some FOREIGN KEY constraints for the temporary + table. But we want to load also the foreign key + constraint definitions for the original table name. */ + err = dict_load_foreigns(new_name); if (err != DB_SUCCESS) { @@ -2354,7 +2393,13 @@ row_rename_table_for_mysql( funct_exit: row_mysql_unlock_data_dictionary(trx); - que_graph_free(graph); + if (graph) { + que_graph_free(graph); + } + + if (heap) { + mem_heap_free(heap); + } trx_commit_for_mysql(trx); diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 4bc81ad8a8e..40994c9962c 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2601,6 +2601,24 @@ row_search_for_mysql( printf("N tables locked %lu\n", trx->mysql_n_tables_locked); */ + /*-------------------------------------------------------------*/ + /* PHASE 0: Release a possible s-latch we are holding on the + adaptive hash index latch if there is someone waiting behind */ + + if (trx->has_search_latch + && btr_search_latch.writer != RW_LOCK_NOT_LOCKED) { + + /* There is an x-latch request on the adaptive hash index: + release the s-latch to reduce starvation and wait for + BTR_SEA_TIMEOUT rounds before trying to keep it again over + calls from MySQL */ + + rw_lock_s_unlock(&btr_search_latch); + trx->has_search_latch = FALSE; + + trx->search_latch_timeout = BTR_SEA_TIMEOUT; + } + /*-------------------------------------------------------------*/ /* PHASE 1: Try to pop the row from the prefetch cache */ @@ -2736,23 +2754,7 @@ row_search_for_mysql( NOT prepared to inserts interleaved with the SELECT, and if we try that, we can deadlock on the adaptive hash index semaphore! */ - - if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED) { - /* There is an x-latch request: release - a possible s-latch to reduce starvation - and wait for BTR_SEA_TIMEOUT rounds before - trying to keep it again over calls from - MySQL */ - if (trx->has_search_latch) { - rw_lock_s_unlock(&btr_search_latch); - trx->has_search_latch = FALSE; - } - - trx->search_latch_timeout = BTR_SEA_TIMEOUT; - - goto no_shortcut; - } #ifndef UNIV_SEARCH_DEBUG if (!trx->has_search_latch) { rw_lock_s_lock(&btr_search_latch); @@ -2810,7 +2812,6 @@ row_search_for_mysql( } } -no_shortcut: /*-------------------------------------------------------------*/ /* PHASE 3: Open or restore index cursor position */ diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index 64569bf3f96..5fce1c1861b 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -218,7 +218,7 @@ row_upd_check_references_constraints( being dropped while the check is running. */ err = row_ins_check_foreign_constraint(FALSE, foreign, - table, index, entry, thr); + table, entry, thr); if (foreign->foreign_table) { mutex_enter(&(dict_sys->mutex)); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index c6f3bd40dfe..ccb3755b252 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1869,11 +1869,11 @@ retry: /* Go to wait for the event; when a thread leaves InnoDB it will release this thread */ - trx->op_info = "waiting in InnoDB queue"; + trx->op_info = (char*)"waiting in InnoDB queue"; os_event_wait(slot->event); - trx->op_info = ""; + trx->op_info = (char*)""; os_fast_mutex_lock(&srv_conc_mutex); @@ -2346,12 +2346,22 @@ srv_sprintf_innodb_monitor( buf = buf + strlen(buf); ut_a(buf < buf_end + 1500); - buf += sprintf(buf, "------------\n" - "TRANSACTIONS\n" - "------------\n"); + if (*dict_foreign_err_buf != '\0') { + buf += sprintf(buf, + "------------------------\n" + "LATEST FOREIGN KEY ERROR\n" + "------------------------\n"); + + if (buf_end - buf > 6000) { + buf+= sprintf(buf, "%.4000s", dict_foreign_err_buf); + } + } + + ut_a(buf < buf_end + 1500); + lock_print_info(buf, buf_end); buf = buf + strlen(buf); - + buf += sprintf(buf, "--------\n" "FILE I/O\n" "--------\n"); diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c index bb5eb662cd7..95037ec3570 100644 --- a/innobase/ut/ut0ut.c +++ b/innobase/ut/ut0ut.c @@ -204,7 +204,7 @@ ut_get_year_month_day( cal_tm_ptr = localtime(&tm); - *year = (ulint)cal_tm_ptr->tm_year; + *year = (ulint)cal_tm_ptr->tm_year + 1900; *month = (ulint)cal_tm_ptr->tm_mon + 1; *day = (ulint)cal_tm_ptr->tm_mday; #endif diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index ea8eaf6653e..edafc142fd3 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -242,6 +242,10 @@ convert_error_code_to_mysql( return(HA_ERR_CANNOT_ADD_FOREIGN); + } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) { + + return(HA_WRONG_CREATE_OPTION); + } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) { return(HA_ERR_CRASHED); @@ -3048,6 +3052,9 @@ ha_innobase::create( trx_search_latch_release_if_reserved(parent_trx); trx = trx_allocate_for_mysql(); + + trx->mysql_thd = thd; + trx->mysql_query_str = &((*thd).query); if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { trx->check_foreigns = FALSE; @@ -3231,6 +3238,9 @@ ha_innobase::delete_table( trx = trx_allocate_for_mysql(); + trx->mysql_thd = current_thd; + trx->mysql_query_str = &((*current_thd).query); + name_len = strlen(name); assert(name_len < 1000); @@ -3309,6 +3319,8 @@ innobase_drop_database( casedn_str(namebuf); #endif trx = trx_allocate_for_mysql(); + trx->mysql_thd = current_thd; + trx->mysql_query_str = &((*current_thd).query); error = row_drop_database_for_mysql(namebuf, trx); @@ -3368,6 +3380,8 @@ ha_innobase::rename_table( } trx = trx_allocate_for_mysql(); + trx->mysql_thd = current_thd; + trx->mysql_query_str = &((*current_thd).query); name_len1 = strlen(from); name_len2 = strlen(to); From a671f80fba959e59cd9657399b38efd08d6a21d3 Mon Sep 17 00:00:00 2001 From: "hf@deer.mysql.r18.ru" <> Date: Wed, 16 Apr 2003 19:48:58 +0500 Subject: [PATCH 044/188] fix for bug #212 --- sql/sql_list.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_list.h b/sql/sql_list.h index 542eef623f0..d42c344957c 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -180,6 +180,8 @@ public: *new_list.last=current->next; current->info=new_list.first->info; current->next=new_list.first->next; + if ((list->last == ¤t->next) && (new_list.elements > 1)) + list->last= new_list.last; list->elements+=new_list.elements-1; } return ret_value; // return old element From 63f911733b4c6b2b13cb584dd287d143b4f98832 Mon Sep 17 00:00:00 2001 From: "miguel@hegel.local" <> Date: Wed, 16 Apr 2003 11:43:04 -0400 Subject: [PATCH 045/188] Exported functions required by MySQLCC --- VC++Files/libmysql/libmysql.def | 118 -------------------------------- libmysql/libmysql.def | 4 ++ 2 files changed, 4 insertions(+), 118 deletions(-) delete mode 100644 VC++Files/libmysql/libmysql.def diff --git a/VC++Files/libmysql/libmysql.def b/VC++Files/libmysql/libmysql.def deleted file mode 100644 index 3ddbe28bc83..00000000000 --- a/VC++Files/libmysql/libmysql.def +++ /dev/null @@ -1,118 +0,0 @@ -LIBRARY LIBMYSQL -DESCRIPTION 'MySQL 4.0 Client Library' -VERSION 4.0 -EXPORTS - mysql_affected_rows - mysql_close - mysql_data_seek - mysql_debug - mysql_dump_debug_info - mysql_eof - mysql_errno - mysql_error - mysql_escape_string - mysql_fetch_field - mysql_fetch_field_direct - mysql_fetch_fields - mysql_fetch_lengths - mysql_fetch_row - mysql_field_count - mysql_field_seek - mysql_field_tell - mysql_free_result - mysql_get_client_info - mysql_get_host_info - mysql_get_proto_info - mysql_get_server_info - mysql_info - mysql_init - mysql_insert_id - mysql_kill - mysql_list_dbs - mysql_list_fields - mysql_list_processes - mysql_list_tables - mysql_num_fields - mysql_num_rows - mysql_odbc_escape_string - mysql_options - mysql_ping - mysql_query - mysql_real_connect - mysql_real_query - mysql_refresh - mysql_row_seek - mysql_row_tell - mysql_select_db - mysql_shutdown - mysql_stat - mysql_store_result - mysql_thread_id - mysql_use_result - bmove_upp - delete_dynamic - _dig_vec - init_dynamic_array - insert_dynamic - int2str - is_prefix - list_add - list_delete - max_allowed_packet - my_casecmp - my_init - my_end - my_strdup - my_malloc - my_memdup - my_no_flags_free - my_realloc - my_thread_end - my_thread_init - net_buffer_length - set_dynamic - strcend - strdup_root - strfill - strinstr - strmake - strmov - strxmov - myodbc_remove_escape - mysql_thread_safe - mysql_character_set_name - mysql_change_user - mysql_send_query - mysql_read_query_result - mysql_real_escape_string - mysql_ssl_set - mysql_real_connect - mysql_master_query - mysql_master_send_query - mysql_slave_query - mysql_slave_send_query - mysql_enable_rpl_parse - mysql_disable_rpl_parse - mysql_rpl_parse_enabled - mysql_enable_reads_from_master - mysql_disable_reads_from_master - mysql_reads_from_master_enabled - mysql_rpl_query_type - mysql_rpl_probe - mysql_set_master - mysql_add_slave - - - - - - - - - - - - - - - diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 7f4edb445e1..baa8643b92d 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -107,6 +107,10 @@ EXPORTS my_print_variables getopt_ull_limit_value getopt_compare_strings + load_defaults + free_defaults + my_path + From f331568042eccc6859dff35142ff3c0a58190f89 Mon Sep 17 00:00:00 2001 From: "hf@deer.mysql.r18.ru" <> Date: Wed, 16 Apr 2003 21:37:22 +0500 Subject: [PATCH 046/188] Fix for #126 --- sql/ha_myisam.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index a1fb09d049b..aef9c09833a 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -486,7 +486,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) param.thd = thd; param.op_name = (char*) "repair"; param.testflag = ((check_opt->flags & ~(T_EXTEND)) | - T_SILENT | T_FORCE_CREATE | + T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM | (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT)); param.sort_buffer_length= check_opt->sort_buffer_size; start_records=file->state->records; From cc5d311121f572dccd4fcd8c7b8fd4571b4dbae2 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 16 Apr 2003 21:10:45 +0300 Subject: [PATCH 047/188] Fix for a bug with InnoDB SQL handler, when previous query failed and an attempt is made to read previous / next value. --- mysql-test/r/innodb_handler.result | 10 +++++++++- mysql-test/t/innodb_handler.test | 8 +++++++- sql/ha_innodb.cc | 3 +++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result index 321aedabdc7..949756a6546 100644 --- a/mysql-test/r/innodb_handler.result +++ b/mysql-test/r/innodb_handler.result @@ -139,4 +139,12 @@ a b alter table t1 type=innodb; handler t2 read first; Unknown table 't2' in HANDLER -drop table if exists t1; +drop table t1; +CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2)) TYPE=InnoDB; +INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2); +HANDLER t1 OPEN; +HANDLER t1 READ `primary` = (1, 1000); +no1 no2 +HANDLER t1 READ `primary` PREV; +no1 no2 +DROP TABLE t1; diff --git a/mysql-test/t/innodb_handler.test b/mysql-test/t/innodb_handler.test index c6448eba3ef..6777e4f49bd 100644 --- a/mysql-test/t/innodb_handler.test +++ b/mysql-test/t/innodb_handler.test @@ -72,5 +72,11 @@ alter table t1 type=innodb; --error 1109 handler t2 read first; -drop table if exists t1; +drop table t1; +CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2)) TYPE=InnoDB; +INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2); +HANDLER t1 OPEN; +HANDLER t1 READ `primary` = (1, 1000); +HANDLER t1 READ `primary` PREV; +DROP TABLE t1; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index edafc142fd3..d55595d4c84 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2579,6 +2579,9 @@ ha_innobase::general_fetch( ut_a(prebuilt->trx == (trx_t*) current_thd->transaction.all.innobase_tid); + if (table->status == STATUS_NOT_FOUND) + DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); + srv_conc_enter_innodb(prebuilt->trx); ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode, From c60ca95e06d13faf5aec67efbde8e2fc0ee2fb99 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 16 Apr 2003 21:36:42 +0300 Subject: [PATCH 048/188] row0sel.c: Fix crash in HANDLER PREV or NEXT if the cursor was positioned using a unique search condition on the primary key: in that case InnoDB does NOT store the cursor position for later fetch prev or next --- innobase/row/row0sel.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 40994c9962c..7e292bbb042 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2685,6 +2685,21 @@ row_search_for_mysql( mode = pcur->search_mode; } + if ((direction == ROW_SEL_NEXT || direction == ROW_SEL_PREV) + && pcur->old_stored != BTR_PCUR_OLD_STORED) { + + /* MySQL sometimes seems to do fetch next or fetch prev even + if the search condition is unique; this can, for example, + happen with the HANDLER commands; we do not store pcur position + in this case, so we cannot restore cursor position, and must + return immediately */ + + /* printf("%s record not found 1\n", index->name); */ + + trx->op_info = (char *) ""; + return(DB_RECORD_NOT_FOUND); + } + mtr_start(&mtr); /* In a search where at most one record in the index may match, we @@ -2717,21 +2732,6 @@ row_search_for_mysql( && !prebuilt->templ_contains_blob && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) { - if (direction == ROW_SEL_NEXT) { - /* MySQL sometimes seems to do fetch next even - if the search condition is unique; we do not store - pcur position in this case, so we cannot - restore cursor position, and must return - immediately */ - - mtr_commit(&mtr); - - /* printf("%s record not found 1\n", index->name); */ - - trx->op_info = (char *) ""; - return(DB_RECORD_NOT_FOUND); - } - ut_a(direction == 0); /* We cannot do fetch prev, as we have not stored the cursor position */ mode = PAGE_CUR_GE; From 65232a8535437e2b1728f2d3d390b7c27be64541 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 16 Apr 2003 22:24:58 +0300 Subject: [PATCH 049/188] undoing a fix --- sql/ha_innodb.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index d55595d4c84..edafc142fd3 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2579,9 +2579,6 @@ ha_innobase::general_fetch( ut_a(prebuilt->trx == (trx_t*) current_thd->transaction.all.innobase_tid); - if (table->status == STATUS_NOT_FOUND) - DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); - srv_conc_enter_innodb(prebuilt->trx); ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode, From 609c8d9c62db0a0695df8b7afe5c70dc238a5a1b Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 16 Apr 2003 22:50:12 +0300 Subject: [PATCH 050/188] row0ins.c: Fix bug: we did not allow ON DELETE SET NULL to modify the same table where the delete was made; we can allow it because that cannot produce infinite loops cascaded operations --- innobase/row/row0ins.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 1a616b74756..611f5cd30d1 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -678,16 +678,17 @@ row_ins_foreign_check_on_constraint( } } - /* We do not allow cyclic cascaded updating of the same - table. Check that we are not updating the same table which - is already being modified in this cascade chain. We have to - check this because the modification of the indexes of a - 'parent' table may still be incomplete, and we must avoid - seeing the indexes of the parent table in an inconsistent - state! In this way we also prevent possible infinite - update loops caused by cyclic cascaded updates. */ + /* We do not allow cyclic cascaded updating of the same table, except + in the case the update is the action of ON DELETE SET NULL, which + cannot lead to an infinite cycle. Check that we are not updating the + same table which is already being modified in this cascade chain. We + have to check this because the modification of the indexes of a + 'parent' table may still be incomplete, and we must avoid seeing the + indexes of the parent table in an inconsistent state! In this way we + also prevent possible infinite update loops caused by cyclic cascaded + updates. */ - if (!cascade->is_delete + if (!node->is_delete && row_ins_cascade_ancestor_updates_table(cascade, table)) { /* We do not know if this would break foreign key From 5112674d7079af706e93bca7e4de4c2a82b4ad87 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 16 Apr 2003 23:05:22 +0300 Subject: [PATCH 051/188] row0ins.c: Better fix for the ON DELETE SET NULL problem --- innobase/row/row0ins.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 611f5cd30d1..596273477aa 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -323,7 +323,7 @@ row_ins_clust_index_entry_by_modify( /************************************************************************* Returns TRUE if in a cascaded update/delete an ancestor node of node -updates table. */ +updates (not DELETE, but UPDATE) table. */ static ibool row_ins_cascade_ancestor_updates_table( @@ -341,7 +341,7 @@ row_ins_cascade_ancestor_updates_table( upd_node = parent; - if (upd_node->table == table) { + if (upd_node->table == table && upd_node->is_delete == FALSE) { return(TRUE); } @@ -678,17 +678,15 @@ row_ins_foreign_check_on_constraint( } } - /* We do not allow cyclic cascaded updating of the same table, except - in the case the update is the action of ON DELETE SET NULL, which - cannot lead to an infinite cycle. Check that we are not updating the - same table which is already being modified in this cascade chain. We - have to check this because the modification of the indexes of a - 'parent' table may still be incomplete, and we must avoid seeing the - indexes of the parent table in an inconsistent state! In this way we - also prevent possible infinite update loops caused by cyclic cascaded - updates. */ + /* We do not allow cyclic cascaded updating (DELETE is allowed, + but not UPDATE) of the same table, as this can lead to an infinite + cycle. Check that we are not updating the same table which is + already being modified in this cascade chain. We have to check + this also because the modification of the indexes of a 'parent' + table may still be incomplete, and we must avoid seeing the indexes + of the parent table in an inconsistent state! */ - if (!node->is_delete + if (!cascade->is_delete && row_ins_cascade_ancestor_updates_table(cascade, table)) { /* We do not know if this would break foreign key From 3a77f47a04cf20716cee8a205c49c65e6cfdbd91 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 17 Apr 2003 02:28:40 +0300 Subject: [PATCH 052/188] ha_innodb.cc, row0sel.c, row0mysql.c, row0mysql.h: Allow HANDLER PREV and NEXT also after positioning the cursor with a unique search on the primary key --- innobase/include/row0mysql.h | 10 +++++++++- innobase/row/row0mysql.c | 3 +++ innobase/row/row0sel.c | 26 +++++++++++++++----------- sql/ha_innodb.cc | 6 +++++- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 25d2ab77007..940b4c61b2f 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -419,13 +419,21 @@ struct row_prebuilt_struct { index where the ordering column is the row id: in this case this flag is set to TRUE */ - dict_index_t* index; /* current index for a search, if any */ + dict_index_t* index; /* current index for a search, if + any */ ulint read_just_key; /* set to 1 when MySQL calls ha_innobase::extra with the argument HA_EXTRA_KEYREAD; it is enough to read just columns defined in the index (i.e., no read of the clustered index record necessary) */ + ibool used_in_HANDLER;/* TRUE if we have been using this + handle in a MySQL HANDLER low level + index cursor command: then we must + store the pcur position even in a + unique search from a clustered index, + because HANDLER allows NEXT and PREV + in such a situation */ ulint template_type; /* ROW_MYSQL_WHOLE_ROW, ROW_MYSQL_REC_FIELDS, ROW_MYSQL_DUMMY_TEMPLATE, or diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 81ed94e2628..af4f484b43d 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -324,6 +324,9 @@ row_create_prebuilt( prebuilt->mysql_has_locked = FALSE; prebuilt->index = NULL; + + prebuilt->used_in_HANDLER = FALSE; + prebuilt->n_template = 0; prebuilt->mysql_template = NULL; diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 7e292bbb042..44dece3d64d 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2690,9 +2690,9 @@ row_search_for_mysql( /* MySQL sometimes seems to do fetch next or fetch prev even if the search condition is unique; this can, for example, - happen with the HANDLER commands; we do not store pcur position - in this case, so we cannot restore cursor position, and must - return immediately */ + happen with the HANDLER commands; we do not always store the + pcur position in this case, so we cannot restore cursor + position, and must return immediately */ /* printf("%s record not found 1\n", index->name); */ @@ -2703,13 +2703,13 @@ row_search_for_mysql( mtr_start(&mtr); /* In a search where at most one record in the index may match, we - can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete + can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete- marked matching record. - Note that in a unique secondary index there may be different delete + Note that in a unique secondary index there may be different delete- marked versions of a record where only the primary key values differ: thus in a secondary index we must use next-key locks when locking - delete marked records. */ + delete-marked records. */ if (match_mode == ROW_SEL_EXACT && index->type & DICT_UNIQUE @@ -2730,10 +2730,9 @@ row_search_for_mysql( if (unique_search && index->type & DICT_CLUSTERED && !prebuilt->templ_contains_blob + && !prebuilt->used_in_HANDLER && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) { - ut_a(direction == 0); /* We cannot do fetch prev, as we have - not stored the cursor position */ mode = PAGE_CUR_GE; unique_search_from_clust_index = TRUE; @@ -3217,11 +3216,16 @@ rec_loop: } } got_row: - /* TODO: should we in every case store the cursor position, even - if this is just a join, for example? */ + /* We have an optimization to save CPU time: if this is a consistent + read on a unique condition on the clustered index, then we do not + store the pcur position, because any fetch next or prev will anyway + return 'end of file'. An exception is the MySQL HANDLER command + where the user can move the cursor with PREV or NEXT even after + a unique search. */ if (!unique_search_from_clust_index - || prebuilt->select_lock_type == LOCK_X) { + || prebuilt->select_lock_type == LOCK_X + || prebuilt->used_in_HANDLER) { /* Inside an update always store the cursor position */ diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index edafc142fd3..30d44f183a4 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -601,7 +601,7 @@ innobase_invalidate_query_cache( Call this when you have opened a new table handle in HANDLER, before you call index_read_idx() etc. Actually, we can let the cursor stay open even over a transaction commit! Then you should call this before every operation, -fecth next etc. This function inits the necessary things even after a +fetch next etc. This function inits the necessary things even after a transaction commit. */ void @@ -648,6 +648,8 @@ ha_innobase::init_table_handle_for_HANDLER(void) we???? */ prebuilt->read_just_key = FALSE; + + prebuilt->used_in_HANDLER = TRUE; } /************************************************************************* @@ -4048,6 +4050,8 @@ ha_innobase::external_lock( trx->mysql_n_tables_locked = 0; + prebuilt->used_in_HANDLER = FALSE; + /* Here we release the search latch and InnoDB thread FIFO ticket if they were reserved. */ From f787cb14344d31be33e93f3cb4c62640fed66ed4 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 17 Apr 2003 02:51:50 +0300 Subject: [PATCH 053/188] row0sel.c: Do not allow InnoDB to cache result set in HANDLER because user can use PREV and NEXT and scroll the cursor --- innobase/row/row0sel.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 44dece3d64d..4732472d805 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2784,6 +2784,10 @@ row_search_for_mysql( } trx->op_info = (char *) ""; + + /* NOTE that we do NOT store the cursor + position */ + return(DB_SUCCESS); } else if (shortcut == SEL_EXHAUSTED) { @@ -2803,6 +2807,10 @@ row_search_for_mysql( } trx->op_info = (char *) ""; + + /* NOTE that we do NOT store the cursor + position */ + return(DB_RECORD_NOT_FOUND); } @@ -3183,6 +3191,7 @@ rec_loop: && prebuilt->select_lock_type == LOCK_NONE && !prebuilt->templ_contains_blob && !prebuilt->clust_index_was_generated + && !prebuilt->used_in_HANDLER && prebuilt->template_type != ROW_MYSQL_DUMMY_TEMPLATE) { @@ -3191,7 +3200,9 @@ rec_loop: update, that is why we require ...lock_type == LOCK_NONE. Since we keep space in prebuilt only for the BLOBs of a single row, we cannot cache rows in the case there - are BLOBs in the fields to be fetched. */ + are BLOBs in the fields to be fetched. In HANDLER we do + not cache rows because there the cursor is a scrollable + cursor. */ row_sel_push_cache_row_for_mysql(prebuilt, rec); @@ -3224,8 +3235,8 @@ got_row: a unique search. */ if (!unique_search_from_clust_index - || prebuilt->select_lock_type == LOCK_X - || prebuilt->used_in_HANDLER) { + || prebuilt->select_lock_type == LOCK_X + || prebuilt->used_in_HANDLER) { /* Inside an update always store the cursor position */ From b914d2e3cc3f4e336535340a2a4172b064d4143b Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 18 Apr 2003 18:42:43 +0300 Subject: [PATCH 054/188] ha_innodb.h, ha_innodb.cc: Make InnoDB to restore old active_index value after a table scan: MySQL may assume that a scan does NOT change active_index; this partially fixes bug 241 of UPDATE ... ORDER BY ... but it still remains that MySQL actually ignores the ORDER BY for both MyISAM and InnoDB tables log0recv.c: Use fflush to make sure report of a corrupt log record is printed to .err log before mysqld crashes --- innobase/log/log0recv.c | 11 +++++-- sql/ha_innodb.cc | 71 +++++++++++++++++++++++++---------------- sql/ha_innodb.h | 10 +++++- 3 files changed, 60 insertions(+), 32 deletions(-) diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index dfe67c444b4..47833214d15 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -1825,7 +1825,12 @@ recv_report_corrupt_log( "InnoDB: WARNING: the log file may have been corrupt and it\n" "InnoDB: is possible that the log scan did not proceed\n" "InnoDB: far enough in recovery! Please run CHECK TABLE\n" - "InnoDB: on your InnoDB tables to check that they are ok!\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.html\n" + "InnoDB: about forcing recovery.\n"); + + fflush(stderr); } /*********************************************************** @@ -2462,7 +2467,7 @@ recv_recovery_from_checkpoint_start( log_hdr_buf, max_cp_group); if (0 == ut_memcmp(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, - "ibbackup", ut_strlen("ibbackup"))) { + (byte*)"ibbackup", ut_strlen((char*)"ibbackup"))) { /* This log file was created by ibbackup --restore: print a note to the user about it */ @@ -2473,7 +2478,7 @@ recv_recovery_from_checkpoint_start( /* Wipe over the label now */ ut_memcpy(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, - " ", 4); + (char*)" ", 4); /* Write to the log file to wipe over the label */ fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, max_cp_group->space_id, diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 30d44f183a4..53f9c31ef5b 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2026,7 +2026,8 @@ calc_row_difference( upd_t* uvect, /* in/out: update vector */ mysql_byte* old_row, /* in: old row in MySQL format */ mysql_byte* new_row, /* in: new row in MySQL format */ - struct st_table* table, /* in: table in MySQL data dictionary */ + struct st_table* table, /* in: table in MySQL data + dictionary */ mysql_byte* upd_buff, /* in: buffer to use */ row_prebuilt_t* prebuilt, /* in: InnoDB prebuilt struct */ THD* thd) /* in: user thread */ @@ -2076,8 +2077,10 @@ calc_row_difference( case DATA_VARCHAR: case DATA_BINARY: case DATA_VARMYSQL: - o_ptr = row_mysql_read_var_ref_noninline(&o_len, o_ptr); - n_ptr = row_mysql_read_var_ref_noninline(&n_len, n_ptr); + o_ptr = row_mysql_read_var_ref_noninline(&o_len, + o_ptr); + n_ptr = row_mysql_read_var_ref_noninline(&n_len, + n_ptr); default: ; } @@ -2489,46 +2492,48 @@ ha_innobase::change_active_index( index, even if it was internally generated by InnoDB */ { - row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - KEY* key=0; - statistic_increment(ha_read_key_count, &LOCK_status); - DBUG_ENTER("change_active_index"); + row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; + KEY* key=0; + statistic_increment(ha_read_key_count, &LOCK_status); + DBUG_ENTER("change_active_index"); - ut_a(prebuilt->trx == + ut_a(prebuilt->trx == (trx_t*) current_thd->transaction.all.innobase_tid); - active_index = keynr; + active_index = keynr; - if (keynr != MAX_KEY && table->keys > 0) { - key = table->key_info + active_index; + if (keynr != MAX_KEY && table->keys > 0) { + key = table->key_info + active_index; - prebuilt->index = dict_table_get_index_noninline( + prebuilt->index = dict_table_get_index_noninline( prebuilt->table, key->name); - } else { - prebuilt->index = dict_table_get_first_index_noninline( + } else { + prebuilt->index = dict_table_get_first_index_noninline( prebuilt->table); - } + } - if (!prebuilt->index) { - sql_print_error("Innodb could not find key n:o %u with name %s from dict cache for table %s", keynr, key ? key->name : "NULL", prebuilt->table->name); - DBUG_RETURN(1); - } + if (!prebuilt->index) { + sql_print_error( +"Innodb could not find key n:o %u with name %s from dict cache for table %s", + keynr, key ? key->name : "NULL", prebuilt->table->name); + DBUG_RETURN(1); + } - assert(prebuilt->search_tuple != 0); + assert(prebuilt->search_tuple != 0); - dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields); + dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields); - dict_index_copy_types(prebuilt->search_tuple, prebuilt->index, + dict_index_copy_types(prebuilt->search_tuple, prebuilt->index, prebuilt->index->n_fields); - /* Maybe MySQL changes the active index for a handle also - during some queries, we do not know: then it is safest to build - the template such that all columns will be fetched. */ + /* Maybe MySQL changes the active index for a handle also + during some queries, we do not know: then it is safest to build + the template such that all columns will be fetched. */ - build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW); + build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW); - DBUG_RETURN(0); + DBUG_RETURN(0); } /************************************************************************** @@ -2721,6 +2726,11 @@ ha_innobase::rnd_init( row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; + /* Store the active index value so that we can restore the original + value after a scan */ + + active_index_before_scan = active_index; + if (prebuilt->clust_index_was_generated) { err = change_active_index(MAX_KEY); } else { @@ -2733,13 +2743,18 @@ ha_innobase::rnd_init( } /********************************************************************* -Ends a table scan ???????????????? */ +Ends a table scan. */ int ha_innobase::rnd_end(void) /*======================*/ /* out: 0 or error number */ { + /* Restore the old active_index back; MySQL may assume that a table + scan does not change active_index */ + + change_active_index(active_index_before_scan); + return(index_end()); } diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 8031fa0aa29..08eeac6baeb 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -58,7 +58,15 @@ class ha_innobase: public handler ulong start_of_scan; /* this is set to 1 when we are starting a table scan but have not yet fetched any row, else 0 */ - + uint active_index_before_scan; + /* since a table scan in InnoDB is + always done through an index, a table + scan may change active_index; but + MySQL may assume that active_index + after a table scan is the same as + before; we store the value here so + that we can restore the value after + a scan */ uint last_match_mode;/* match mode of the latest search: ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX, or undefined */ From e1b68cf1118026dbd5f1d5c5f289bd60cf129770 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 18 Apr 2003 22:06:10 +0300 Subject: [PATCH 055/188] ha_innodb.cc: Prevent crash if MySQL calls rnd_end WITOUT calling rnd_init first: only restore active_index if it the old value was pushed in rnd_init Initialize active_index to a sensible value: prevent crash if we restore it to the original value after an table scan --- sql/ha_innodb.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 53f9c31ef5b..d066a00afed 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1182,6 +1182,9 @@ ha_innobase::open( last_query_id = (ulong)-1; + active_index = 0; + active_index_before_scan = (uint)-1; /* undefined value */ + if (!(share=get_share(name))) DBUG_RETURN(1); @@ -2751,9 +2754,16 @@ ha_innobase::rnd_end(void) /* out: 0 or error number */ { /* Restore the old active_index back; MySQL may assume that a table - scan does not change active_index */ + scan does not change active_index. We only restore the value if + MySQL has called rnd_init before: sometimes MySQL seems to call + rnd_end WITHOUT calling rnd_init. */ - change_active_index(active_index_before_scan); + if (active_index_before_scan != (uint)-1) { + + change_active_index(active_index_before_scan); + + active_index_before_scan = (uint)-1; + } return(index_end()); } From 90e23ebe947d683b31ea1b78ad22270c7c728c2c Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 19 Apr 2003 20:09:01 +0300 Subject: [PATCH 056/188] buf0buf.c: Do not set buffer pool to zero when we start up: that takes too much time for big buffer pools; Purify users must define UNIV_SET_MEM_TO_ZERO in univ.i to eliminate spurious (?) Purify warnings --- innobase/buf/buf0buf.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index bbce52f0b00..82a2d19695a 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -480,9 +480,6 @@ buf_pool_create( block = buf_pool_get_nth_block(buf_pool, i); - /* Wipe contents of page to eliminate a Purify warning */ - memset(block->frame, '\0', UNIV_PAGE_SIZE); - UT_LIST_ADD_FIRST(free, buf_pool->free, block); } From d91d6d5e2ee17104974e337dfe9569db0be844c8 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Sat, 19 Apr 2003 23:18:35 +0300 Subject: [PATCH 057/188] Three bug fixes and one fix being undone. --- mysql-test/r/innodb_handler.result | 1 + sql/sql_db.cc | 7 +++++++ sql/sql_update.cc | 5 ----- strings/ctype-tis620.c | 5 +++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result index 949756a6546..8aa5309308f 100644 --- a/mysql-test/r/innodb_handler.result +++ b/mysql-test/r/innodb_handler.result @@ -147,4 +147,5 @@ HANDLER t1 READ `primary` = (1, 1000); no1 no2 HANDLER t1 READ `primary` PREV; no1 no2 +1 275 DROP TABLE t1; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 900c87d83a5..d33a87f0893 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -351,6 +351,13 @@ bool mysql_change_db(THD *thd,const char *name) x_free(dbname); DBUG_RETURN(1); } + if (dbname[0] == '`' && dbname[db_length-1] == '`') + { + int counter=1; + for (; counter < db_length - 1; counter++) + dbname[counter-1]=dbname[counter]; + dbname[(db_length= counter)-1]='\0'; + } DBUG_PRINT("info",("Use database: %s", dbname)); if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index de370ab92b5..19961f5d9e1 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -478,11 +478,6 @@ int multi_update::prepare(List ¬_used_values) table->used_keys=0; table->pos_in_table_list= tl; } - else - { - table_ref->lock_type=TL_READ; - mysql_unlock_some_tables(thd,&table,1); - } } diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index d5181dc4db0..6dd3641381a 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -491,7 +491,7 @@ static uchar* thai2sortable(const uchar * tstr,uint len) return((uchar*) tstr); } pLeft4 = pRight4;*/ - while(len--) { + while((len--)) { if(isldvowel(*p) && isconsnt(p[1])) { *pRight1++ = t_ctype[p[1]][0]; *pRight2++ = t_ctype[p[1]][1]; @@ -501,7 +501,8 @@ static uchar* thai2sortable(const uchar * tstr,uint len) *pRight2++ = t_ctype[*p][1]; *pRight3++ = t_ctype[*p][2]; /* *pRight4++ = t_ctype[*p][3]; */ - len--; + if (!(len--)) + break; p += 2; } else { *pRight1 = t_ctype[*p][0]; From 4f77f6a4d81924f22f854d0073872c8fe2451005 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 20 Apr 2003 19:36:09 +0300 Subject: [PATCH 058/188] univ.i: If HAVE_purify is defined, define UNIV_SET_MEM_TO_ZERO to eliminate Purify warnings --- innobase/include/univ.i | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/innobase/include/univ.i b/innobase/include/univ.i index bf606efcf64..e29f3ec92e1 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -100,6 +100,15 @@ memory is read outside the allocated blocks. */ #define YYDEBUG 1 +#ifdef HAVE_purify +/* The following sets all new allocated memory to zero before use: +this can be used to eliminate unnecessary Purify warnings, but note that +it also masks many bugs Purify could detect. For detailed Purify analysis it +is best to remove the define below and look through the warnings one +by one. */ +#define UNIV_SET_MEM_TO_ZERO +#endif + /* #define UNIV_SQL_DEBUG #define UNIV_LOG_DEBUG From ea0dbedcb1e3331482b3f72794bd6ff54601fb0c Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 21 Apr 2003 12:56:54 +0300 Subject: [PATCH 059/188] buf0buf.c: No buffer pool activity in SHOW INNODB STATUS actually meant no page gets --- innobase/buf/buf0buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 82a2d19695a..42799da9d7c 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1904,7 +1904,7 @@ buf_print_io( / (buf_pool->n_page_gets - buf_pool->n_page_gets_old))); } else { buf += sprintf(buf, - "No buffer pool activity since the last printout\n"); + "No buffer pool page gets since the last printout\n"); } buf_pool->n_page_gets_old = buf_pool->n_page_gets; From 5c754e11f1c46ecf94bf99fcc55a4867db255cd1 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Mon, 21 Apr 2003 14:11:17 +0300 Subject: [PATCH 060/188] Dropping out deprecated OPTION from the error messages. --- sql/share/czech/errmsg.txt | 2 +- sql/share/danish/errmsg.txt | 2 +- sql/share/dutch/errmsg.txt | 2 +- sql/share/english/errmsg.txt | 2 +- sql/share/estonian/errmsg.txt | 2 +- sql/share/french/errmsg.txt | 2 +- sql/share/german/errmsg.txt | 2 +- sql/share/greek/errmsg.txt | 2 +- sql/share/hungarian/errmsg.txt | 2 +- sql/share/italian/errmsg.txt | 2 +- sql/share/japanese/errmsg.txt | 2 +- sql/share/korean/errmsg.txt | 2 +- sql/share/norwegian-ny/errmsg.txt | 2 +- sql/share/norwegian/errmsg.txt | 2 +- sql/share/portuguese/errmsg.txt | 2 +- sql/share/romanian/errmsg.txt | 2 +- sql/share/russian/errmsg.txt | 2 +- sql/share/slovak/errmsg.txt | 2 +- sql/share/spanish/errmsg.txt | 2 +- sql/share/swedish/errmsg.txt | 2 +- sql/share/ukrainian/errmsg.txt | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index f169d6f85f1..f5e879679cc 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -114,7 +114,7 @@ "Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu", "Nep-Bøípustné jméno databáze '%-.64s'", "Nep-Bøípustné jméno tabulky '%-.64s'", -"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET OPTION SQL_BIG_SELECTS=1", +"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1", "Nezn-Bámá chyba", "Nezn-Bámá procedura %s", "Chybn-Bý poèet parametrù procedury %s", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 06c63e47a73..13c061d50a1 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -108,7 +108,7 @@ "BLOB feltet '%-.64s' kan ikke have en standard værdi", "Ugyldigt database navn '%-.64s'", "Ugyldigt tabel navn '%-.64s'", -"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET OPTION SQL_BIG_SELECTS=1 hvis udtrykket er korrekt", +"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt", "Ukendt fejl", "Ukendt procedure %s", "Forkert antal parametre til proceduren %s", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 452a330b61b..45dbd663fec 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -116,7 +116,7 @@ "Blob veld '%-.64s' can geen standaardwaarde bevatten", "Databasenaam '%-.64s' is niet getoegestaan", "Niet toegestane tabelnaam '%-.64s'", -"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET OPTION SQL_BIG_SELECTS=1 als het stament in orde is.", +"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is.", "Onbekende Fout", "Onbekende procedure %s", "Foutief aantal parameters doorgegeven aan procedure %s", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 023cd7bc73e..19de162b3fb 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -105,7 +105,7 @@ "BLOB column '%-.64s' can't have a default value", "Incorrect database name '%-.100s'", "Incorrect table name '%-.100s'", -"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok", +"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET SQL_BIG_SELECTS=1 if the SELECT is ok", "Unknown error", "Unknown procedure '%-.64s'", "Incorrect parameter count to procedure '%-.64s'", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index d0a30b2f434..c1b98d12b3a 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -110,7 +110,7 @@ "BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust", "Vigane andmebaasi nimi '%-.100s'", "Vigane tabeli nimi '%-.100s'", -"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET OPTION SQL_BIG_SELECTS=1", +"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1", "Tundmatu viga", "Tundmatu protseduur '%-.64s'", "Vale parameetrite hulk protseduurile '%-.64s'", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 08aa5760d6c..242343769e6 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -105,7 +105,7 @@ "BLOB '%-.64s' ne peut avoir de valeur par défaut", "Nom de base de donnée illégal: '%-.64s'", "Nom de table illégal: '%-.64s'", -"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET OPTION SQL_BIG_SELECTS=1 si SELECT se passe bien", +"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien", "Erreur inconnue", "Procédure %s inconnue", "Mauvais nombre de paramètres pour la procedure %s", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 42e8c6f069b..10ec359abe8 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -108,7 +108,7 @@ "BLOB-Feld '%-.64s' kann keinen Vorgabewert (Default-Value) besitzen.", "Unerlaubter Datenbankname '%-.64s'.", "Unerlaubter Tabellenname '%-.64s'.", -"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen und SET OPTION SQL_BIG_SELECTS=1 verwenden, sofern SELECT ok ist.", +"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen und SET SQL_BIG_SELECTS=1 verwenden, sofern SELECT ok ist.", "Unbekannter Fehler.", "Unbekannte Procedure %-.64s.", "Falsche Parameterzahl für Procedure %-.64s.", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index c212c5b5703..11534d9e11b 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -105,7 +105,7 @@ "Ôá Blob ðåäßá '%-.64s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)", "ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'", "ËÜèïò üíïìá ðßíáêá '%-.100s'", -"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET OPTION SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü", +"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü", "ÐñïÝêõøå Üãíùóôï ëÜèïò", "Áãíùóôç äéáäéêáóßá '%-.64s'", "ËÜèïò áñéèìüò ðáñáìÝôñùí óôç äéáäéêáóßá '%-.64s'", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 5e8affe32b7..f8c5dbcc836 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -107,7 +107,7 @@ "A(z) '%-.64s' blob objektumnak nem lehet alapertelmezett erteke", "Hibas adatbazisnev: '%-.100s'", "Hibas tablanev: '%-.100s'", -"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET OPTION SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok", +"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok", "Ismeretlen hiba", "Ismeretlen eljaras: '%-.64s'", "Rossz parameter a(z) '%-.64s'eljaras szamitasanal", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 3fdea588bf3..a82b0cdf18f 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -105,7 +105,7 @@ "Il campo BLOB '%-.64s' non puo` avere un valore di default", "Nome database errato '%-.100s'", "Nome tabella errato '%-.100s'", -"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET OPTION SQL_BIG_SELECTS=1 se e` tutto a posto.", +"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto.", "Errore sconosciuto", "Procedura '%-.64s' sconosciuta", "Numero di parametri errato per la procedura '%-.64s'", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index f9c1645419d..850fc5f22bc 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -107,7 +107,7 @@ "BLOB column '%-.64s' can't have a default value", "»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹", "»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹", -"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok", +"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET SQL_BIG_SELECTS=1 if the SELECT is ok", "Unknown error", "Unknown procedure '%-.64s'", "Incorrect parameter count to procedure '%-.64s'", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 82d5a5ecfbe..c57723f81e6 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -105,7 +105,7 @@ "BLOB Ä®·³ '%-.64s' ´Â µðÆúÆ® °ªÀ» °¡Áú ¼ö ¾ø½À´Ï´Ù.", "'%-.100s' µ¥ÀÌŸº£À̽ºÀÇ À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.", "'%-.100s' Å×À̺í À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.", -"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET OPTION SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.", +"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.", "¾Ë¼ö ¾ø´Â ¿¡·¯ÀÔ´Ï´Ù.", "¾Ë¼ö ¾ø´Â ¼öÇ๮ : '%-.64s'", "'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆÄ¶ó¸ÞÅÍ", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index a218d5873b0..e331854ff68 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -107,7 +107,7 @@ "Blob feltet '%-.64s' kan ikkje ha ein standard verdi", "Ugyldig database namn '%-.64s'", "Ugyldig tabell namn '%-.64s'", -"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt", +"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt", "Ukjend feil", "Ukjend prosedyre %s", "Feil parameter tal til prosedyra %s", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 9ed50b4a00b..817eec3058d 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -107,7 +107,7 @@ "Blob feltet '%-.64s' kan ikke ha en standard verdi", "Ugyldig database navn '%-.64s'", "Ugyldig tabell navn '%-.64s'", -"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt", +"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt", "Ukjent feil", "Ukjent prosedyre %s", "Feil parameter antall til prosedyren %s", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 0badf76c13d..ea4f85f6b03 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -105,7 +105,7 @@ "Coluna BLOB '%-.64s' não pode ter um valor padrão (default)", "Nome de banco de dados '%-.100s' incorreto", "Nome de tabela '%-.100s' incorreto", -"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET OPTION SQL_BIG_SELECTS=1, se o SELECT estiver correto", +"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET SQL_BIG_SELECTS=1, se o SELECT estiver correto", "Erro desconhecido", "'Procedure' '%-.64s' desconhecida", "Número de parâmetros incorreto para a 'procedure' '%-.64s'", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 1b036481538..7fc0c182f6a 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -109,7 +109,7 @@ "Coloana BLOB '%-.64s' nu poate avea o valoare default", "Numele bazei de date este incorect '%-.100s'", "Numele tabelei este incorect '%-.100s'", -"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET OPTION SQL_BIG_SELECTS=1 daca SELECT-ul e ok", +"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET SQL_BIG_SELECTS=1 daca SELECT-ul e ok", "Eroare unknown", "Procedura unknown '%-.64s'", "Procedura '%-.64s' are un numar incorect de parametri", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 8858090e8db..fc090205041 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -107,7 +107,7 @@ "îÅ×ÏÚÍÏÖÎÏ ÕËÁÚÙ×ÁÔØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ ÓÔÏÌÂÃÁ BLOB '%-.64s'", "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ '%-.100s'", "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÔÁÂÌÉÃÙ '%-.100s'", -"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET OPTION SQL_BIG_SELECTS=1", +"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET SQL_BIG_SELECTS=1", "îÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ", "îÅÉÚ×ÅÓÔÎÁÑ ÐÒÏÃÅÄÕÒÁ '%-.64s'", "îÅËÏÒÒÅËÔÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 6424dcec6ee..89a000db554 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -113,7 +113,7 @@ "Pole BLOB '%-.64s' nemô¾e ma» implicitnú hodnotu", "Neprípustné meno databázy '%-.100s'", "Neprípustné meno tabuµky '%-.100s'", -"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET OPTION SQL_BIG_SELECTS=1", +"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET SQL_BIG_SELECTS=1", "Neznámá chyba", "Neznámá procedúra '%-.64s'", "Chybný poèet parametrov procedúry '%-.64s'", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index df95a02a7aa..d566642f1c9 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -106,7 +106,7 @@ "Campo Blob '%-.64s' no puede tener valores patron", "Nombre de base de datos ilegal '%-.64s'", "Nombre de tabla ilegal '%-.64s'", -"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET OPTION SQL_BIG_SELECTS=1 si el SELECT esta correcto", +"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET SQL_BIG_SELECTS=1 si el SELECT esta correcto", "Error desconocido", "Procedimiento desconocido %s", "Equivocado parametro count para procedimiento %s", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index f7da6516600..11ae22d3013 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -105,7 +105,7 @@ "BLOB fält '%-.64s' kan inte ha ett DEFAULT-värde", "Felaktigt databasnamn '%-.64s'", "Felaktigt tabellnamn '%-.64s'", -"Den angivna frågan skulle troligen ta mycket lång tid! Kontrollera din WHERE och använd SET OPTION SQL_BIG_SELECTS=1 ifall du vill hantera stora joins", +"Den angivna frågan skulle troligen ta mycket lång tid! Kontrollera din WHERE och använd SET SQL_BIG_SELECTS=1 ifall du vill hantera stora joins", "Oidentifierat fel", "Okänd procedur: %s", "Felaktigt antal parametrar till procedur %s", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index c1d98e83f7d..a0a4a274d4b 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -110,7 +110,7 @@ "óÔÏ×ÂÅÃØ BLOB '%-.64s' ÎÅ ÍÏÖÅ ÍÁÔÉ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ", "îÅצÒÎÅ ¦Í'Ñ ÂÁÚÉ ÄÁÎÎÉÈ '%-.100s'", "îÅצÒÎÅ ¦Í'Ñ ÔÁÂÌÉæ '%-.100s'", -"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET OPTION SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ", +"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ", "îÅצÄÏÍÁ ÐÏÍÉÌËÁ", "îÅצÄÏÍÁ ÐÒÏÃÅÄÕÒÁ '%-.64s'", "èÉÂÎÁ Ë¦ÌØË¦ÓÔØ ÐÁÒÁÍÅÔÒ¦× ÐÒÏÃÅÄÕÒÉ '%-.64s'", From fd58dc20bbf7b49f806b62dfc700249219d02b28 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Mon, 21 Apr 2003 22:54:02 +0300 Subject: [PATCH 061/188] Fixing few small problems in SET PASSWORD: * comparison with correct cached variable * preventing check_change_password to be called twice, once from set_var::check and the other time from change_password itself --- mysql-test/r/select_safe.result | 2 +- sql/sql_acl.cc | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result index e225a0e3995..8f2b621ac8a 100644 --- a/mysql-test/r/select_safe.result +++ b/mysql-test/r/select_safe.result @@ -30,7 +30,7 @@ You are using safe update mode and you tried to update a table without a WHERE t delete from t1 where a+0=1; You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5; -The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok +The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET SQL_BIG_SELECTS=1 if the SELECT is ok update t1 set b="a" limit 1; update t1 set b="a" where b="b" limit 2; delete from t1 where b="test" limit 1; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8ee210f4e24..53238ef63cb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1029,7 +1029,7 @@ bool check_change_password(THD *thd, const char *host, const char *user) } if (!thd->slave_thread && (strcmp(thd->user,user) || - my_strcasecmp(host,thd->host ? thd->host : thd->ip))) + my_strcasecmp(host,thd->host_or_ip))) { if (check_access(thd, UPDATE_ACL, "mysql",0,1)) return(1); @@ -1067,10 +1067,6 @@ bool change_password(THD *thd, const char *host, const char *user, host,user,new_password)); DBUG_ASSERT(host != 0); // Ensured by parent - if (check_change_password(thd, host, user)) - DBUG_RETURN(1); - - /* password should always be 0 or 16 chars; simple hack to avoid cracking */ length=(uint) strlen(new_password); new_password[length & 16]=0; From ae51f0456475bb55ab1c9b8d04a676c901ad540a Mon Sep 17 00:00:00 2001 From: "serg@sergbook.mysql.com" <> Date: Wed, 23 Apr 2003 00:53:07 +0400 Subject: [PATCH 062/188] do not mark the table as analyzed unless all the key parts are REALLY analyzed. --- myisam/mi_check.c | 10 +-- mysql-test/r/alter_table.result | 116 ++++++++++++++++++++++++++++++++ mysql-test/t/alter_table.test | 16 +++++ 3 files changed, 138 insertions(+), 4 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 5cbe0a7d2f3..b23d4b2277b 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3544,12 +3544,14 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) } if (update & UPDATE_STAT) { - uint key_parts= mi_uint2korr(share->state.header.key_parts); + uint i, key_parts= mi_uint2korr(share->state.header.key_parts); share->state.rec_per_key_rows=info->state->records; - memcpy((char*) share->state.rec_per_key_part, - (char*) param->rec_per_key_part, - sizeof(*param->rec_per_key_part)*key_parts); share->state.changed&= ~STATE_NOT_ANALYZED; + for (i=0; istate.rec_per_key_part[i]=param->rec_per_key_part[i])) + share->state.changed|= STATE_NOT_ANALYZED; + } } if (update & (UPDATE_STAT | UPDATE_SORT | UPDATE_TIME | UPDATE_AUTO_INC)) { diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 096ef2fd79e..a296e0a87ac 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -122,3 +122,119 @@ Field Type Null Key Default Extra i int(10) unsigned PRI NULL auto_increment c char(10) YES NULL drop table t1; +create table t1 (a int, b int); +insert into t1 values(1,100), (2,100), (3, 100); +insert into t1 values(1,99), (2,99), (3, 99); +insert into t1 values(1,98), (2,98), (3, 98); +insert into t1 values(1,97), (2,97), (3, 97); +insert into t1 values(1,96), (2,96), (3, 96); +insert into t1 values(1,95), (2,95), (3, 95); +insert into t1 values(1,94), (2,94), (3, 94); +insert into t1 values(1,93), (2,93), (3, 93); +insert into t1 values(1,92), (2,92), (3, 92); +insert into t1 values(1,91), (2,91), (3, 91); +insert into t1 values(1,90), (2,90), (3, 90); +insert into t1 values(1,89), (2,89), (3, 89); +insert into t1 values(1,88), (2,88), (3, 88); +insert into t1 values(1,87), (2,87), (3, 87); +insert into t1 values(1,86), (2,86), (3, 86); +insert into t1 values(1,85), (2,85), (3, 85); +insert into t1 values(1,84), (2,84), (3, 84); +insert into t1 values(1,83), (2,83), (3, 83); +insert into t1 values(1,82), (2,82), (3, 82); +insert into t1 values(1,81), (2,81), (3, 81); +insert into t1 values(1,80), (2,80), (3, 80); +insert into t1 values(1,79), (2,79), (3, 79); +insert into t1 values(1,78), (2,78), (3, 78); +insert into t1 values(1,77), (2,77), (3, 77); +insert into t1 values(1,76), (2,76), (3, 76); +insert into t1 values(1,75), (2,75), (3, 75); +insert into t1 values(1,74), (2,74), (3, 74); +insert into t1 values(1,73), (2,73), (3, 73); +insert into t1 values(1,72), (2,72), (3, 72); +insert into t1 values(1,71), (2,71), (3, 71); +insert into t1 values(1,70), (2,70), (3, 70); +insert into t1 values(1,69), (2,69), (3, 69); +insert into t1 values(1,68), (2,68), (3, 68); +insert into t1 values(1,67), (2,67), (3, 67); +insert into t1 values(1,66), (2,66), (3, 66); +insert into t1 values(1,65), (2,65), (3, 65); +insert into t1 values(1,64), (2,64), (3, 64); +insert into t1 values(1,63), (2,63), (3, 63); +insert into t1 values(1,62), (2,62), (3, 62); +insert into t1 values(1,61), (2,61), (3, 61); +insert into t1 values(1,60), (2,60), (3, 60); +insert into t1 values(1,59), (2,59), (3, 59); +insert into t1 values(1,58), (2,58), (3, 58); +insert into t1 values(1,57), (2,57), (3, 57); +insert into t1 values(1,56), (2,56), (3, 56); +insert into t1 values(1,55), (2,55), (3, 55); +insert into t1 values(1,54), (2,54), (3, 54); +insert into t1 values(1,53), (2,53), (3, 53); +insert into t1 values(1,52), (2,52), (3, 52); +insert into t1 values(1,51), (2,51), (3, 51); +insert into t1 values(1,50), (2,50), (3, 50); +insert into t1 values(1,49), (2,49), (3, 49); +insert into t1 values(1,48), (2,48), (3, 48); +insert into t1 values(1,47), (2,47), (3, 47); +insert into t1 values(1,46), (2,46), (3, 46); +insert into t1 values(1,45), (2,45), (3, 45); +insert into t1 values(1,44), (2,44), (3, 44); +insert into t1 values(1,43), (2,43), (3, 43); +insert into t1 values(1,42), (2,42), (3, 42); +insert into t1 values(1,41), (2,41), (3, 41); +insert into t1 values(1,40), (2,40), (3, 40); +insert into t1 values(1,39), (2,39), (3, 39); +insert into t1 values(1,38), (2,38), (3, 38); +insert into t1 values(1,37), (2,37), (3, 37); +insert into t1 values(1,36), (2,36), (3, 36); +insert into t1 values(1,35), (2,35), (3, 35); +insert into t1 values(1,34), (2,34), (3, 34); +insert into t1 values(1,33), (2,33), (3, 33); +insert into t1 values(1,32), (2,32), (3, 32); +insert into t1 values(1,31), (2,31), (3, 31); +insert into t1 values(1,30), (2,30), (3, 30); +insert into t1 values(1,29), (2,29), (3, 29); +insert into t1 values(1,28), (2,28), (3, 28); +insert into t1 values(1,27), (2,27), (3, 27); +insert into t1 values(1,26), (2,26), (3, 26); +insert into t1 values(1,25), (2,25), (3, 25); +insert into t1 values(1,24), (2,24), (3, 24); +insert into t1 values(1,23), (2,23), (3, 23); +insert into t1 values(1,22), (2,22), (3, 22); +insert into t1 values(1,21), (2,21), (3, 21); +insert into t1 values(1,20), (2,20), (3, 20); +insert into t1 values(1,19), (2,19), (3, 19); +insert into t1 values(1,18), (2,18), (3, 18); +insert into t1 values(1,17), (2,17), (3, 17); +insert into t1 values(1,16), (2,16), (3, 16); +insert into t1 values(1,15), (2,15), (3, 15); +insert into t1 values(1,14), (2,14), (3, 14); +insert into t1 values(1,13), (2,13), (3, 13); +insert into t1 values(1,12), (2,12), (3, 12); +insert into t1 values(1,11), (2,11), (3, 11); +insert into t1 values(1,10), (2,10), (3, 10); +insert into t1 values(1,9), (2,9), (3, 9); +insert into t1 values(1,8), (2,8), (3, 8); +insert into t1 values(1,7), (2,7), (3, 7); +insert into t1 values(1,6), (2,6), (3, 6); +insert into t1 values(1,5), (2,5), (3, 5); +insert into t1 values(1,4), (2,4), (3, 4); +insert into t1 values(1,3), (2,3), (3, 3); +insert into t1 values(1,2), (2,2), (3, 2); +insert into t1 values(1,1), (2,1), (3, 1); +alter table t1 add unique (a,b), add key (b); +show keys from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 0 a 2 b A NULL NULL NULL YES BTREE +t1 1 b 1 b A 100 NULL NULL YES BTREE +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +show keys from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 0 a 2 b A NULL NULL NULL YES BTREE +t1 1 b 1 b A 100 NULL NULL YES BTREE +drop table t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 1c3987e2a31..301a50bf07d 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -115,3 +115,19 @@ alter table t1 rename t2; alter table t2 rename t1, add c char(10) comment "no comment"; show columns from t1; drop table t1; + +# implicit analyze + +create table t1 (a int, b int); +let $1=100; +while ($1) +{ + eval insert into t1 values(1,$1), (2,$1), (3, $1); + dec $1; +} +alter table t1 add unique (a,b), add key (b); +show keys from t1; +analyze table t1; +show keys from t1; +drop table t1; + From 1621dd9818ae4f281b39403d9ec6ad279a9289e5 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 23 Apr 2003 00:13:37 +0300 Subject: [PATCH 063/188] Fixed problem with timestamps in binary log on 64 bit machines Backported fix from 4.1 for bug 212: SELECT query containing a NATURAL JOIN and parentheses in the WHERE clause --- mysql-test/r/join.result | 3 +++ mysql-test/t/join.test | 14 ++++++++++++++ sql/log_event.cc | 2 +- sql/log_event.h | 8 ++++---- sql/sql_list.h | 2 ++ 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 0c575d7505e..713d7736585 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -41,3 +41,6 @@ rate_code base_rate cust 20 rate_code base_rate cust 20 +ID Value1 ID Value2 +ID Value1 ID Value2 +ID Value1 ID Value2 diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 6a022e690f2..5fe1834873f 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -243,3 +243,17 @@ INSERT INTO t2 VALUES ('rivercats','cust',20); SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND lr.siteid = 'rivercats'; SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith'; drop table t1,t2; + +# +# Problem with internal list handling when reducing WHERE +# + +CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, Value1 VARCHAR(255)); +CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255)); +INSERT INTO t1 VALUES (1, 'A'); +INSERT INTO t2 VALUES (1, 'B'); + +SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B'); +SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B'; +SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1; +drop table t1,t2; diff --git a/sql/log_event.cc b/sql/log_event.cc index 7c4c893a823..da25f842bd0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -304,7 +304,7 @@ void Start_log_event::print(FILE* file, bool short_form, char* last_db) print_header(file); fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version, server_version); - print_timestamp(file, (time_t*)&created); + print_timestamp(file, &created); fputc('\n', file); fflush(file); } diff --git a/sql/log_event.h b/sql/log_event.h index 39ab1f7c6b4..68696442490 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -327,13 +327,13 @@ extern char server_version[SERVER_VERSION_LENGTH]; class Start_log_event: public Log_event { public: - uint32 created; + time_t created; uint16 binlog_version; char server_version[50]; Start_log_event() :Log_event(time(NULL)),binlog_version(BINLOG_VERSION) { - created = (uint32) when; + created = (time_t) when; memcpy(server_version, ::server_version, sizeof(server_version)); } Start_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id_arg) : @@ -345,7 +345,7 @@ public: binlog_version = uint2korr(buf+4); memcpy(server_version, buf + 6, sizeof(server_version)); server_version[sizeof(server_version)-1]=0; - created = uint4korr(buf + 6 + sizeof(server_version)); + created = (time_t) uint4korr(buf + 6 + sizeof(server_version)); } Start_log_event(const char* buf); @@ -354,7 +354,7 @@ public: int write_data(IO_CACHE* file); int get_data_size() { - // sizeof(binlog_version) + sizeof(server_version) sizeof(created) + // size(binlog_version) + sizeof(server_version) + size(created) return 2 + sizeof(server_version) + 4; } void print(FILE* file, bool short_form = 0, char* last_db = 0); diff --git a/sql/sql_list.h b/sql/sql_list.h index d21f2e658dc..f6851385f80 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -160,6 +160,8 @@ public: *new_list.last=current->next; current->info=new_list.first->info; current->next=new_list.first->next; + if (list->last == ¤t->next && new_list.elements > 1) + list->last= new_list.last; list->elements+=new_list.elements-1; } return ret_value; // return old element From 9588dc01e548a8a39af8a71b5da2da20b6c4b2e3 Mon Sep 17 00:00:00 2001 From: "vva@eagle.mysql.r18.ru" <> Date: Tue, 22 Apr 2003 19:38:57 -0400 Subject: [PATCH 064/188] fix error message for for load data infile --- sql/log_event.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index c8eb4026120..f87a3872324 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1922,13 +1922,13 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, close_thread_tables(thd); if (thd->query_error) { - int sql_error = thd->net.last_errno; + int sql_error= thd->net.last_errno; if (!sql_error) - sql_error = ER_UNKNOWN_ERROR; - + sql_error= ER_UNKNOWN_ERROR; slave_print_error(rli,sql_error, - "Slave: Error '%s' running load data infile ", - ER_SAFE(sql_error)); + "Error '%s' running load data infile", + sql_error ? thd->net.last_error : + ER_SAFE(ER_UNKNOWN_ERROR)); free_root(&thd->mem_root,0); return 1; } @@ -1936,7 +1936,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, if (thd->fatal_error) { - sql_print_error("Slave: Fatal error running LOAD DATA INFILE "); + sql_print_error("Fatal error running LOAD DATA INFILE "); return 1; } From 1d5f8cb79f6ce1000271dd610e7d8d3b128a904d Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 23 Apr 2003 01:51:25 +0200 Subject: [PATCH 065/188] - fixed typo in instructions on how to add a PATH to .tcshrc on Mac OS X --- support-files/MacOSX/ReadMe.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/support-files/MacOSX/ReadMe.txt b/support-files/MacOSX/ReadMe.txt index a18c5f3aa41..8b7b7019bd4 100644 --- a/support-files/MacOSX/ReadMe.txt +++ b/support-files/MacOSX/ReadMe.txt @@ -76,5 +76,4 @@ can to add this directory to your PATH environment variable in your login script. For the default shell "tcsh", you can do this by running this command once: -echo 'setenv PATH $PATH:/usr/local/mysql/bin' >> ~/.tcshrc - +echo 'setenv PATH ${PATH}:/usr/local/mysql/bin' >> ~/.tcshrc From 32a987834fbbec88c225231b7227ef9c6dedb901 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 23 Apr 2003 02:51:25 +0300 Subject: [PATCH 066/188] row0mysql.c: Give sensible advice to the user if InnoDB notices index corruption --- innobase/row/row0mysql.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index af4f484b43d..db1119a2abc 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -276,6 +276,17 @@ handle_new_error: "InnoDB: my.cnf and restart the database.\n"); exit(1); + } else if (err == DB_CORRUPTION) { + + fprintf(stderr, + "InnoDB: We detected index corruption in an InnoDB type table.\n" + "InnoDB: You have to dump + drop + reimport the table or, in\n" + "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.html for help.\n"); + } else { fprintf(stderr, "InnoDB: unknown error code %lu\n", err); ut_a(0); From 9d11b35110204123f579890d22990e1de7d50063 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 23 Apr 2003 01:51:26 +0200 Subject: [PATCH 067/188] - Only ignore _regular_ world-writeable files (thanks to Tim Bunce for discovering this) --- mysys/default.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysys/default.c b/mysys/default.c index a3942425b7d..26121cc0e56 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -249,7 +249,8 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(0))) return 0; - if (stat_info.st_mode & S_IWOTH) /* ignore world-writeable files */ + /* ignore world-writeable _regular_ files */ + if (stat_info.st_mode & S_IWOTH && stat_info.st_mode & S_IFREG) { fprintf(stderr, "warning: World-writeable config file %s is ignored\n", name); From 4d6d491a8f19a05017677b49f0696fa99b1d6297 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 23 Apr 2003 01:51:28 +0200 Subject: [PATCH 068/188] - updated sample my.cnf files: removed deprecated set-variable keywords --- support-files/my-huge.cnf.sh | 52 +++++++++++++++++----------------- support-files/my-large.cnf.sh | 52 +++++++++++++++++----------------- support-files/my-medium.cnf.sh | 48 +++++++++++++++---------------- support-files/my-small.cnf.sh | 36 +++++++++++------------ 4 files changed, 94 insertions(+), 94 deletions(-) diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index 3362d5bd131..ca7c63f8e12 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -26,21 +26,21 @@ socket = @MYSQL_UNIX_ADDR@ port = @MYSQL_TCP_PORT@ socket = @MYSQL_UNIX_ADDR@ skip-locking -set-variable = key_buffer=384M -set-variable = max_allowed_packet=1M -set-variable = table_cache=512 -set-variable = sort_buffer_size=2M -set-variable = read_buffer_size=2M -set-variable = myisam_sort_buffer_size=64M -set-variable = thread_cache=8 +key_buffer = 384M +max_allowed_packet = 1M +table_cache = 512 +sort_buffer_size = 2M +read_buffer_size = 2M +myisam_sort_buffer_size = 64M +thread_cache = 8 # Try number of CPU's*2 for thread_concurrency -set-variable = thread_concurrency=8 +thread_concurrency = 8 # Don't listen on a TCP/IP port at all. This can be a security enhancement, # if all processes that need to connect to mysqld run on the same host. # All interaction with mysqld must be made via Unix sockets or named pipes. # Note that using this option without enabling named pipes on Windows -# (via the "pipe" option) will render mysqld useless! +# (via the "enable-named-pipe" option) will render mysqld useless! # #skip-networking @@ -113,8 +113,8 @@ server-id = 1 #log-update = /path-to-dedicated-directory/hostname # Uncomment the following if you are using BDB tables -#set-variable = bdb_cache_size=384M -#set-variable = bdb_max_lock=100000 +#bdb_cache_size = 384M +#bdb_max_lock = 100000 # Uncomment the following if you are using InnoDB tables #innodb_data_home_dir = @localstatedir@/ @@ -123,17 +123,17 @@ server-id = 1 #innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high -#set-variable = innodb_buffer_pool_size=384M -#set-variable = innodb_additional_mem_pool_size=20M +#innodb_buffer_pool_size = 384M +#innodb_additional_mem_pool_size = 20M # Set .._log_file_size to 25 % of buffer pool size -#set-variable = innodb_log_file_size=100M -#set-variable = innodb_log_buffer_size=8M -#innodb_flush_log_at_trx_commit=1 -#set-variable = innodb_lock_wait_timeout=50 +#innodb_log_file_size = 100M +#innodb_log_buffer_size = 8M +#innodb_flush_log_at_trx_commit = 1 +#innodb_lock_wait_timeout = 50 [mysqldump] quick -set-variable = max_allowed_packet=16M +max_allowed_packet = 16M [mysql] no-auto-rehash @@ -141,16 +141,16 @@ no-auto-rehash #safe-updates [isamchk] -set-variable = key_buffer=256M -set-variable = sort_buffer_size=256M -set-variable = read_buffer=2M -set-variable = write_buffer=2M +key_buffer = 256M +sort_buffer_size = 256M +read_buffer = 2M +write_buffer = 2M [myisamchk] -set-variable = key_buffer=256M -set-variable = sort_buffer_size=256M -set-variable = read_buffer=2M -set-variable = write_buffer=2M +key_buffer = 256M +sort_buffer_size = 256M +read_buffer = 2M +write_buffer = 2M [mysqlhotcopy] interactive-timeout diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 5bc3a8eb0c4..91a805724d8 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -26,21 +26,21 @@ socket = @MYSQL_UNIX_ADDR@ port = @MYSQL_TCP_PORT@ socket = @MYSQL_UNIX_ADDR@ skip-locking -set-variable = key_buffer=256M -set-variable = max_allowed_packet=1M -set-variable = table_cache=256 -set-variable = sort_buffer_size=1M -set-variable = read_buffer_size=1M -set-variable = myisam_sort_buffer_size=64M -set-variable = thread_cache=8 +key_buffer = 256M +max_allowed_packet = 1M +table_cache = 256 +sort_buffer_size = 1M +read_buffer_size = 1M +myisam_sort_buffer_size = 64M +thread_cache = 8 # Try number of CPU's*2 for thread_concurrency -set-variable = thread_concurrency=8 +thread_concurrency = 8 # Don't listen on a TCP/IP port at all. This can be a security enhancement, # if all processes that need to connect to mysqld run on the same host. # All interaction with mysqld must be made via Unix sockets or named pipes. # Note that using this option without enabling named pipes on Windows -# (via the "pipe" option) will render mysqld useless! +# (via the "enable-named-pipe" option) will render mysqld useless! # #skip-networking @@ -113,8 +113,8 @@ server-id = 1 #log-update = /path-to-dedicated-directory/hostname # Uncomment the following if you are using BDB tables -#set-variable = bdb_cache_size=64M -#set-variable = bdb_max_lock=100000 +#bdb_cache_size = 64M +#bdb_max_lock = 100000 # Uncomment the following if you are using InnoDB tables #innodb_data_home_dir = @localstatedir@/ @@ -123,17 +123,17 @@ server-id = 1 #innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high -#set-variable = innodb_buffer_pool_size=256M -#set-variable = innodb_additional_mem_pool_size=20M +#innodb_buffer_pool_size = 256M +#innodb_additional_mem_pool_size = 20M # Set .._log_file_size to 25 % of buffer pool size -#set-variable = innodb_log_file_size=64M -#set-variable = innodb_log_buffer_size=8M -#innodb_flush_log_at_trx_commit=1 -#set-variable = innodb_lock_wait_timeout=50 +#innodb_log_file_size = 64M +#innodb_log_buffer_size = 8M +#innodb_flush_log_at_trx_commit = 1 +#innodb_lock_wait_timeout = 50 [mysqldump] quick -set-variable = max_allowed_packet=16M +max_allowed_packet = 16M [mysql] no-auto-rehash @@ -141,16 +141,16 @@ no-auto-rehash #safe-updates [isamchk] -set-variable = key_buffer=128M -set-variable = sort_buffer_size=128M -set-variable = read_buffer=2M -set-variable = write_buffer=2M +key_buffer = 128M +sort_buffer_size = 128M +read_buffer = 2M +write_buffer = 2M [myisamchk] -set-variable = key_buffer=128M -set-variable = sort_buffer_size=128M -set-variable = read_buffer=2M -set-variable = write_buffer=2M +key_buffer = 128M +sort_buffer_size = 128M +read_buffer = 2M +write_buffer = 2M [mysqlhotcopy] interactive-timeout diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh index 084f23cbc94..601ffc503c0 100644 --- a/support-files/my-medium.cnf.sh +++ b/support-files/my-medium.cnf.sh @@ -27,18 +27,18 @@ socket = @MYSQL_UNIX_ADDR@ port = @MYSQL_TCP_PORT@ socket = @MYSQL_UNIX_ADDR@ skip-locking -set-variable = key_buffer=16M -set-variable = max_allowed_packet=1M -set-variable = table_cache=64 -set-variable = sort_buffer_size=512K -set-variable = net_buffer_length=8K -set-variable = myisam_sort_buffer_size=8M +key_buffer = 16M +max_allowed_packet = 1M +table_cache = 64 +sort_buffer_size = 512K +net_buffer_length = 8K +myisam_sort_buffer_size = 8M # Don't listen on a TCP/IP port at all. This can be a security enhancement, # if all processes that need to connect to mysqld run on the same host. # All interaction with mysqld must be made via Unix sockets or named pipes. # Note that using this option without enabling named pipes on Windows -# (via the "pipe" option) will render mysqld useless! +# (via the "enable-named-pipe" option) will render mysqld useless! # #skip-networking @@ -111,8 +111,8 @@ server-id = 1 #log-update = /path-to-dedicated-directory/hostname # Uncomment the following if you are using BDB tables -#set-variable = bdb_cache_size=4M -#set-variable = bdb_max_lock=10000 +#bdb_cache_size = 4M +#bdb_max_lock = 10000 # Uncomment the following if you are using InnoDB tables #innodb_data_home_dir = @localstatedir@/ @@ -121,17 +121,17 @@ server-id = 1 #innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high -#set-variable = innodb_buffer_pool_size=16M -#set-variable = innodb_additional_mem_pool_size=2M +#innodb_buffer_pool_size = 16M +#innodb_additional_mem_pool_size = 2M # Set .._log_file_size to 25 % of buffer pool size -#set-variable = innodb_log_file_size=5M -#set-variable = innodb_log_buffer_size=8M -#innodb_flush_log_at_trx_commit=1 -#set-variable = innodb_lock_wait_timeout=50 +#innodb_log_file_size = 5M +#innodb_log_buffer_size = 8M +#innodb_flush_log_at_trx_commit = 1 +#innodb_lock_wait_timeout = 50 [mysqldump] quick -set-variable = max_allowed_packet=16M +max_allowed_packet = 16M [mysql] no-auto-rehash @@ -139,16 +139,16 @@ no-auto-rehash #safe-updates [isamchk] -set-variable = key_buffer=20M -set-variable = sort_buffer_size=20M -set-variable = read_buffer=2M -set-variable = write_buffer=2M +key_buffer = 20M +sort_buffer_size = 20M +read_buffer = 2M +write_buffer = 2M [myisamchk] -set-variable = key_buffer=20M -set-variable = sort_buffer_size=20M -set-variable = read_buffer=2M -set-variable = write_buffer=2M +key_buffer = 20M +sort_buffer_size = 20M +read_buffer = 2M +write_buffer = 2M [mysqlhotcopy] interactive-timeout diff --git a/support-files/my-small.cnf.sh b/support-files/my-small.cnf.sh index b11277c1b4a..f9e30da78ac 100644 --- a/support-files/my-small.cnf.sh +++ b/support-files/my-small.cnf.sh @@ -27,18 +27,18 @@ socket = @MYSQL_UNIX_ADDR@ port = @MYSQL_TCP_PORT@ socket = @MYSQL_UNIX_ADDR@ skip-locking -set-variable = key_buffer=16K -set-variable = max_allowed_packet=1M -set-variable = table_cache=4 -set-variable = sort_buffer_size=64K -set-variable = net_buffer_length=2K -set-variable = thread_stack=64K +key_buffer = 16K +max_allowed_packet = 1M +table_cache = 4 +sort_buffer_size = 64K +net_buffer_length = 2K +thread_stack = 64K # Don't listen on a TCP/IP port at all. This can be a security enhancement, # if all processes that need to connect to mysqld run on the same host. # All interaction with mysqld must be made via Unix sockets or named pipes. # Note that using this option without enabling named pipes on Windows -# (via the "pipe" option) will render mysqld useless! +# (using the "enable-named-pipe" option) will render mysqld useless! # #skip-networking server-id = 1 @@ -56,17 +56,17 @@ server-id = 1 #innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high -#set-variable = innodb_buffer_pool_size=16M -#set-variable = innodb_additional_mem_pool_size=2M +#innodb_buffer_pool_size = 16M +#innodb_additional_mem_pool_size = 2M # Set .._log_file_size to 25 % of buffer pool size -#set-variable = innodb_log_file_size=5M -#set-variable = innodb_log_buffer_size=8M -#innodb_flush_log_at_trx_commit=1 -#set-variable = innodb_lock_wait_timeout=50 +#innodb_log_file_size = 5M +#innodb_log_buffer_size = 8M +#innodb_flush_log_at_trx_commit = 1 +#innodb_lock_wait_timeout = 50 [mysqldump] quick -set-variable = max_allowed_packet=16M +max_allowed_packet = 16M [mysql] no-auto-rehash @@ -74,12 +74,12 @@ no-auto-rehash #safe-updates [isamchk] -set-variable = key_buffer=8M -set-variable = sort_buffer_size=8M +key_buffer = 8M +sort_buffer_size = 8M [myisamchk] -set-variable = key_buffer=8M -set-variable = sort_buffer_size=8M +key_buffer = 8M +sort_buffer_size = 8M [mysqlhotcopy] interactive-timeout From b6ca95a7f4ca001dd50569eea2a5e3af4d284c76 Mon Sep 17 00:00:00 2001 From: "serg@sergbook.mysql.com" <> Date: Wed, 23 Apr 2003 14:03:21 +0400 Subject: [PATCH 069/188] warning when a 4.1 MYI file is opened in 4.0 --- myisam/mi_open.c | 3 +++ myisam/myisamdef.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 60049325c5c..2f3ef872492 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -182,6 +182,9 @@ 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, "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); + mi_state_info_read(disk_cache, &share->state); len= mi_uint2korr(share->state.header.base_info_length); if (len != MI_BASE_INFO_SIZE) diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 92eead7b96c..7c035bc6097 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -55,7 +55,8 @@ typedef struct st_mi_state_info uchar uniques; /* number of UNIQUE definitions */ uchar language; /* Language for indexes */ uchar max_block_size; /* max keyblock size */ - uchar not_used[2]; /* To align to 8 */ + uchar fulltext_keys; /* reserved for 4.1 */ + uchar not_used; /* To align to 8 */ } header; MI_STATUS_INFO state; From 767f9a52f02d6b15a9ff73f934ce1da342a56b23 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 23 Apr 2003 12:44:00 +0200 Subject: [PATCH 070/188] - added $(SUPERCLEANFILES) to DISTCLEANFILES (bug #201) - thanks to Christian Hammers for providing this patch --- include/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Makefile.am b/include/Makefile.am index 83cf4290d3d..4b881d0e7ed 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -34,7 +34,7 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \ SUPERCLEANFILES = mysql_version.h my_config.h # Some include files that may be moved and patched by configure -DISTCLEANFILES = sched.h +DISTCLEANFILES = sched.h $(SUPERCLEANFILES) all-local: my_config.h From 0bfb2d3d9f056ec0ecc6c973945414e36b6a8750 Mon Sep 17 00:00:00 2001 From: "serg@sergbook.mysql.com" <> Date: Wed, 23 Apr 2003 15:37:11 +0400 Subject: [PATCH 071/188] correct test result --- mysql-test/r/alter_table.result | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index a296e0a87ac..d24f8087bc1 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -231,10 +231,10 @@ t1 0 a 2 b A NULL NULL NULL YES BTREE t1 1 b 1 b A 100 NULL NULL YES BTREE analyze table t1; Table Op Msg_type Msg_text -test.t1 analyze status Table is already up to date +test.t1 analyze status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 a 1 a A NULL NULL NULL YES BTREE -t1 0 a 2 b A NULL NULL NULL YES BTREE +t1 0 a 1 a A 3 NULL NULL YES BTREE +t1 0 a 2 b A 300 NULL NULL YES BTREE t1 1 b 1 b A 100 NULL NULL YES BTREE drop table t1; From fa456991faaf9c03084b55515093b0e696922aad Mon Sep 17 00:00:00 2001 From: "serg@sergbook.mysql.com" <> Date: Wed, 23 Apr 2003 15:44:39 +0400 Subject: [PATCH 072/188] bug 283: FULLTEXT index on a TEXT filed converted to a CHAR field doesn't work anymore --- mysql-test/r/fulltext.result | 11 +++++++++++ mysql-test/t/fulltext.test | 13 +++++++++++++ sql/sql_table.cc | 21 ++++++++++++--------- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index edf109fcc93..eaaaf9c8880 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -215,3 +215,14 @@ test.t1 repair status OK select * from t1 where match (a) against ('aaaa'); a drop table t1; +drop table if exists t1; +create table t1 ( ref_mag text not null, fulltext (ref_mag)); +insert into t1 values ('test'); +select ref_mag from t1 where match ref_mag against ('+test' in boolean mode); +ref_mag +test +alter table t1 change ref_mag ref_mag char (255) not null; +select ref_mag from t1 where match ref_mag against ('+test' in boolean mode); +ref_mag +test +drop table t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 5a64f2614aa..128af680854 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -173,3 +173,16 @@ repair table t1; select * from t1 where match (a) against ('aaaa'); drop table t1; +# +# bug 283 by jocelyn fournier +# FULLTEXT index on a TEXT filed converted to a CHAR field doesn't work anymore +# + +drop table if exists t1; +create table t1 ( ref_mag text not null, fulltext (ref_mag)); +insert into t1 values ('test'); +select ref_mag from t1 where match ref_mag against ('+test' in boolean mode); +alter table t1 change ref_mag ref_mag char (255) not null; +select ref_mag from t1 where match ref_mag against ('+test' in boolean mode); +drop table t1; + diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0cdb0a7ff48..0fbb5807c57 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -569,6 +569,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, column->field_name); DBUG_RETURN(-1); } + /* for fulltext keys keyseg length is 1 for blobs (it's ignored in + ft code anyway, and 0 (set to column width later) for char's. + it has to be correct col width for char's, as char data are not + prefixed with length (unlike blobs, where ft code takes data length + from a data prefix, ignoring column->length). + */ + if (key->type == Key::FULLTEXT) + column->length=test(f_is_blob(sql_field->pack_flag)); if (f_is_blob(sql_field->pack_flag)) { if (!(file->table_flags() & HA_BLOB_KEY)) @@ -579,15 +587,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } if (!column->length) { - if (key->type == Key::FULLTEXT) - column->length=1; /* ft-code ignores it anyway :-) */ - else - { - my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH, - ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0), - column->field_name); - DBUG_RETURN(-1); - } + my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH, + ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0), + column->field_name); + DBUG_RETURN(-1); } } if (!(sql_field->flags & NOT_NULL_FLAG)) From 45080daf4a3e9aab03a61c818b896bd40d339593 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 23 Apr 2003 15:27:11 +0300 Subject: [PATCH 073/188] removing back tick support from the server in change_db() --- sql/sql_db.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sql/sql_db.cc b/sql/sql_db.cc index d33a87f0893..900c87d83a5 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -351,13 +351,6 @@ bool mysql_change_db(THD *thd,const char *name) x_free(dbname); DBUG_RETURN(1); } - if (dbname[0] == '`' && dbname[db_length-1] == '`') - { - int counter=1; - for (; counter < db_length - 1; counter++) - dbname[counter-1]=dbname[counter]; - dbname[(db_length= counter)-1]='\0'; - } DBUG_PRINT("info",("Use database: %s", dbname)); if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; From e6fe7d1bed2bce353863b1c6b8833b1d58d39267 Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Wed, 23 Apr 2003 18:00:07 +0500 Subject: [PATCH 074/188] Task 761:'mysqlbinlog should not die when reading unknown event' --- client/mysqlbinlog.cc | 4 ++++ sql/log_event.cc | 22 +++++++++++++++++++++- sql/log_event.h | 22 ++++++++++++++++++---- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 1fe3dc86b35..75b875b4f4e 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -43,6 +43,7 @@ static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace"; void sql_print_error(const char *format, ...); static bool one_database = 0; +static bool force_opt= 0; static const char* database; static bool short_form = 0; static ulonglong offset = 0; @@ -73,6 +74,9 @@ static struct my_option my_long_options[] = {"database", 'd', "List entries for just this database (local log only)", (gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"force-read", 'f', "Force reading unknown binlog events", + (gptr*) &force_opt, (gptr*) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Get the binlog from server", (gptr*) &host, (gptr*) &host, diff --git a/sql/log_event.cc b/sql/log_event.cc index b627636186b..05d5788f5ae 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -659,9 +659,18 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len, } if (!ev || !ev->is_valid()) { - *error= "Found invalid event in binary log"; delete ev; +#ifdef MYSQL_CLIENT + if (!force_opt) + { + *error= "Found invalid event in binary log"; + return 0; + } + ev= new Unknown_log_event(buf, old_format); +#else + *error= "Found invalid event in binary log"; return 0; +#endif } ev->cached_event_len = event_len; return ev; @@ -1695,6 +1704,17 @@ void Execute_load_log_event::pack_info(String* packet) } #endif +#ifdef MYSQL_CLIENT +void Unknown_log_event::print(FILE* file, bool short_form, char* last_db) +{ + if (short_form) + return; + print_header(file); + fputc('\n', file); + fprintf(file, "# %s", "Unknown event\n"); +} +#endif + #ifndef MYSQL_CLIENT int Query_log_event::exec_event(struct st_relay_log_info* rli) { diff --git a/sql/log_event.h b/sql/log_event.h index 5b9f30b3afd..b46f78d2ce0 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -201,10 +201,10 @@ struct sql_ex_info enum Log_event_type { - START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, ROTATE_EVENT = 4, - INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8, - APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11, - NEW_LOAD_EVENT=12, RAND_EVENT=13 + UNKNOWN_EVENT = 0, START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, + ROTATE_EVENT = 4, INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, + CREATE_FILE_EVENT=8, APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, + DELETE_FILE_EVENT=11, NEW_LOAD_EVENT=12, RAND_EVENT=13 }; enum Int_event_type @@ -714,4 +714,18 @@ public: int write_data(IO_CACHE* file); }; +#ifdef MYSQL_CLIENT +class Unknown_log_event: public Log_event +{ +public: + Unknown_log_event(const char* buf, bool old_format): + Log_event(buf, old_format) + {} + ~Unknown_log_event() {} + void print(FILE* file, bool short_form= 0, char* last_db= 0); + Log_event_type get_type_code() { return UNKNOWN_EVENT;} + bool is_valid() { return 1; } +}; +#endif + #endif /* _log_event_h */ From 9298d590ac54d9055c0da8be34028120cd87179c Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 23 Apr 2003 20:42:07 +0300 Subject: [PATCH 075/188] properly back quoting db.table names in SHOW GRANTS --- sql/sql_acl.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 53238ef63cb..28cb3eed4ef 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3031,11 +3031,11 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } } } - global.append(" ON ",4); + global.append(" ON `",5); global.append(grant_table->db); - global.append(".",1); + global.append("`.`",3); global.append(grant_table->tname); - global.append(" TO '",5); + global.append("` TO '",6); global.append(lex_user->user.str,lex_user->user.length); global.append("'@'",3); global.append(lex_user->host.str,lex_user->host.length); From e918ea54881740e5cc0718004f13afc063eec8d4 Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Wed, 23 Apr 2003 11:43:30 -0700 Subject: [PATCH 076/188] Modify PeterG's internals documentation per Monty. Added more detailed explanation of record header and column storage. --- BitKeeper/etc/logging_ok | 1 + Docs/internals.texi | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index dbd4df6efe4..acc6eebb68a 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -67,6 +67,7 @@ paul@teton.kitebird.com pem@mysql.com peter@linux.local peter@mysql.com +peterg@mysql.com pgulutzan@linux.local ram@mysql.r18.ru ram@ram.(none) diff --git a/Docs/internals.texi b/Docs/internals.texi index 686ecd27fda..b5a7244695f 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -1994,7 +1994,7 @@ When you say: @* MySQL creates files named Table1.MYD ("MySQL Data"), Table1.MYI -("MySQL Index"), and Table1.FRM ("Format"). These files will be in the +("MySQL Index"), and Table1.frm ("Format"). These files will be in the directory: @* /// @* @@ -2030,6 +2030,12 @@ The minimal record header is a set of flags: @end table @* +The length of the record header is thus:@* +(1 + number of NULL columns + 7) / 8 bytes@* +After the header, all columns are stored in +the order that they were created, which is the +same order that you would get from SHOW COLUMNS. + Here's an example. Suppose you say: @* From 44c8a1b012b913060b2d29f7f2df7b34cecef322 Mon Sep 17 00:00:00 2001 From: "mmatthew@markslaptop." <> Date: Wed, 23 Apr 2003 13:43:31 -0500 Subject: [PATCH 077/188] config-win.h: Enable 'LOAD LOCAL INFILE', for parity with unix binaries. --- BitKeeper/etc/logging_ok | 1 + include/config-win.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index acc6eebb68a..2112a7c8dce 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -45,6 +45,7 @@ miguel@hegel.br miguel@hegel.local miguel@light. miguel@light.local +mmatthew@markslaptop. monty@bitch.mysql.fi monty@butch. monty@donna.mysql.fi diff --git a/include/config-win.h b/include/config-win.h index 74b2ae71017..9931d2c4b95 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -145,6 +145,9 @@ typedef uint rf_SetTimer; #define USE_MB_IDENT 1 #define USE_STRCOLL 1 +/* If LOAD DATA LOCAL INFILE should be enabled by default */ +#define ENABLED_LOCAL_INFILE 1 + /* Convert some simple functions to Posix */ #define sigset(A,B) signal((A),(B)) From cde501853af61d365fde16990b780ff22972b04a Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 23 Apr 2003 21:44:24 +0300 Subject: [PATCH 078/188] improved bug fix --- sql/sql_select.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index dfcbc5418cd..a35f5cc2314 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -555,10 +555,18 @@ mysql_select(THD *thd,TABLE_LIST *tables,List &fields,COND *conds, /* Change DISTINCT to GROUP BY */ select_distinct= 0; no_order= !order; - if (order && skip_sort_order) - join.tmp_table_param.quick_group=0; if (all_order_fields_used) + { + if (order && skip_sort_order) + { + /* + Force MySQL to read the table in sorted order to get result in + ORDER BY order. + */ + join.tmp_table_param.quick_group=0; + } order=0; + } join.group=1; // For end_write_group } else From 1d9d1221f0c7f98162240fb50b3c05238b586060 Mon Sep 17 00:00:00 2001 From: "serg@sergbook.mysql.com" <> Date: Wed, 23 Apr 2003 22:46:47 +0400 Subject: [PATCH 079/188] do not execute \* commands inside `identifiers` --- client/mysql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index d7aa0d1404d..a237561d83d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1007,7 +1007,7 @@ static bool add_line(String &buffer,char *line,char *in_string) { // Add found char to buffer if (inchar == *in_string) *in_string=0; - else if (!*in_string && (inchar == '\'' || inchar == '"')) + else if (!*in_string && (inchar == '\'' || inchar == '"' || inchar == '`')) *in_string=(char) inchar; *out++ = (char) inchar; if (inchar == '*' && !*in_string) From f6a43bd567f932995289ed179d18e5923873680b Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 23 Apr 2003 21:52:16 +0300 Subject: [PATCH 080/188] Fixes for valgrind Added optimzation for clustered index Fixed bug in UPDATE ... ORDER BY Fixed handling of UPDATE ... LIMIT --- Images/.cvsignore | 1 - include/my_global.h | 6 + myisam/mi_info.c | 2 +- mysql-test/r/group_by.result | 42 ++--- mysql-test/r/innodb.result | 71 ++++++++ mysql-test/r/join_outer.result | 4 +- mysql-test/r/multi_update.result | 20 +-- mysql-test/r/null_key.result | 2 +- mysql-test/r/update.result | 40 ++++- mysql-test/t/group_by.test | 16 +- mysql-test/t/innodb.test | 55 +++++- mysql-test/t/join_outer.test | 2 +- mysql-test/t/multi_update.test | 2 +- mysql-test/t/update.test | 14 +- repl-tests/README | 12 -- repl-tests/include/master-slave.inc | 2 - repl-tests/run-all-tests | 9 - repl-tests/test-auto-inc/run.test | 10 -- repl-tests/test-auto-inc/x.master | 4 - repl-tests/test-bad-query/run.test | 10 -- repl-tests/test-bad-query/x.master | 4 - repl-tests/test-dump/run.test | 25 --- repl-tests/test-dump/table-dump-check.master | 2 - repl-tests/test-dump/table-dump-select.master | 2 - repl-tests/test-repl-alter/run.test | 12 -- repl-tests/test-repl-alter/test.master | 4 - repl-tests/test-repl-ts/repl-timestamp.master | 2 - .../test-repl-ts/repl-timestamp.master.reject | 2 - repl-tests/test-repl-ts/run.test | 17 -- repl-tests/test-repl/foo-dump-master.master | 3 - repl-tests/test-repl/foo-dump-slave.master | 3 - repl-tests/test-repl/run.test | 24 --- repl-tests/test-repl/sum-wlen-master.master | 2 - repl-tests/test-repl/sum-wlen-slave.master | 2 - sql/field.cc | 2 +- sql/ha_heap.h | 5 +- sql/ha_innodb.cc | 29 +++- sql/ha_innodb.h | 1 + sql/handler.h | 3 +- sql/item_sum.cc | 5 +- sql/mysqld.cc | 2 +- sql/opt_range.cc | 12 +- sql/records.cc | 2 +- sql/sql_list.h | 2 +- sql/sql_select.cc | 24 +-- sql/sql_select.h | 4 +- sql/sql_union.cc | 3 +- sql/sql_update.cc | 163 ++++++++++-------- support-files/my-huge.cnf.sh | 1 + support-files/my-large.cnf.sh | 1 + 50 files changed, 368 insertions(+), 319 deletions(-) delete mode 100644 Images/.cvsignore delete mode 100644 repl-tests/README delete mode 100644 repl-tests/include/master-slave.inc delete mode 100755 repl-tests/run-all-tests delete mode 100755 repl-tests/test-auto-inc/run.test delete mode 100644 repl-tests/test-auto-inc/x.master delete mode 100755 repl-tests/test-bad-query/run.test delete mode 100644 repl-tests/test-bad-query/x.master delete mode 100644 repl-tests/test-dump/run.test delete mode 100644 repl-tests/test-dump/table-dump-check.master delete mode 100644 repl-tests/test-dump/table-dump-select.master delete mode 100644 repl-tests/test-repl-alter/run.test delete mode 100644 repl-tests/test-repl-alter/test.master delete mode 100644 repl-tests/test-repl-ts/repl-timestamp.master delete mode 100644 repl-tests/test-repl-ts/repl-timestamp.master.reject delete mode 100644 repl-tests/test-repl-ts/run.test delete mode 100644 repl-tests/test-repl/foo-dump-master.master delete mode 100644 repl-tests/test-repl/foo-dump-slave.master delete mode 100755 repl-tests/test-repl/run.test delete mode 100644 repl-tests/test-repl/sum-wlen-master.master delete mode 100644 repl-tests/test-repl/sum-wlen-slave.master diff --git a/Images/.cvsignore b/Images/.cvsignore deleted file mode 100644 index 6d0d61a83d5..00000000000 --- a/Images/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -logo_nusphere_b.tif diff --git a/include/my_global.h b/include/my_global.h index b6b2dfcda32..e12a7d7273b 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -850,7 +850,13 @@ typedef char bool; /* Ordinary boolean values 0 1 */ ((uint32) (uchar) (A)[0]))) #define sint4korr(A) (*((long *) (A))) #define uint2korr(A) (*((uint16 *) (A))) +#ifdef HAVE_purify +#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\ + (((uint32) ((uchar) (A)[1])) << 8) +\ + (((uint32) ((uchar) (A)[2])) << 16)) +#else #define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF) +#endif #define uint4korr(A) (*((unsigned long *) (A))) #define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\ (((uint32) ((uchar) (A)[1])) << 8) +\ diff --git a/myisam/mi_info.c b/myisam/mi_info.c index 0be3cc44d80..32767e73bb1 100644 --- a/myisam/mi_info.c +++ b/myisam/mi_info.c @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Ger tillbaka en struct med information om isam-filen */ +/* Return useful base information for an open table */ #include "myisamdef.h" #ifdef __WIN__ diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index f73c4d7f8af..43f1bf8f6d4 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -49,6 +49,10 @@ SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1 userid MIN(t1.score+0.0) 1 1.0 2 2.0 +EXPLAIN SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; +table type possible_keys key key_len ref rows Extra +t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary +t2 index PRIMARY PRIMARY 4 NULL 3 Using where; Using index drop table test.t1,test.t2; CREATE TABLE t1 ( PID int(10) unsigned NOT NULL auto_increment, @@ -242,34 +246,32 @@ score smallint(5) unsigned, key (spid), key (score) ); -INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3); +INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3),(6,3,3),(7,3,3); explain select userid,count(*) from t1 group by userid desc; table type possible_keys key key_len ref rows Extra -t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort +t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort explain select userid,count(*) from t1 group by userid desc order by null; table type possible_keys key key_len ref rows Extra -t1 ALL NULL NULL NULL NULL 6 Using temporary +t1 ALL NULL NULL NULL NULL 8 Using temporary select userid,count(*) from t1 group by userid desc; userid count(*) -3 3 +3 5 2 1 1 2 select userid,count(*) from t1 group by userid desc having (count(*)+1) IN (4,3); userid count(*) -3 3 1 2 select userid,count(*) from t1 group by userid desc having 3 IN (1,COUNT(*)); userid count(*) -3 3 explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc; table type possible_keys key key_len ref rows Extra -t1 range spID spID 5 NULL 2 Using where; Using index +t1 range spID spID 5 NULL 3 Using where; Using index explain select spid,count(*) from t1 where spid between 1 and 2 group by spid; table type possible_keys key key_len ref rows Extra -t1 range spID spID 5 NULL 2 Using where; Using index +t1 range spID spID 5 NULL 3 Using where; Using index explain select spid,count(*) from t1 where spid between 1 and 2 group by spid order by null; table type possible_keys key key_len ref rows Extra -t1 range spID spID 5 NULL 2 Using where; Using index +t1 range spID spID 5 NULL 3 Using where; Using index select spid,count(*) from t1 where spid between 1 and 2 group by spid; spid count(*) 1 1 @@ -280,12 +282,14 @@ spid count(*) 1 1 explain select sql_big_result spid,sum(userid) from t1 group by spid desc; table type possible_keys key key_len ref rows Extra -t1 ALL NULL NULL NULL NULL 6 Using filesort +t1 ALL NULL NULL NULL NULL 8 Using filesort explain select sql_big_result spid,sum(userid) from t1 group by spid desc order by null; table type possible_keys key key_len ref rows Extra -t1 ALL NULL NULL NULL NULL 6 +t1 ALL NULL NULL NULL NULL 8 select sql_big_result spid,sum(userid) from t1 group by spid desc; spid sum(userid) +7 3 +6 3 5 3 4 3 3 3 @@ -293,13 +297,13 @@ spid sum(userid) 1 1 explain select sql_big_result score,count(*) from t1 group by score desc; table type possible_keys key key_len ref rows Extra -t1 index NULL score 3 NULL 6 Using index +t1 index NULL score 3 NULL 8 Using index explain select sql_big_result score,count(*) from t1 group by score desc order by null; table type possible_keys key key_len ref rows Extra -t1 index NULL score 3 NULL 6 Using index +t1 index NULL score 3 NULL 8 Using index select sql_big_result score,count(*) from t1 group by score desc; score count(*) -3 3 +3 5 2 1 1 2 drop table t1; @@ -535,15 +539,7 @@ t1 ALL NULL NULL NULL NULL 6 Using temporary t2 ALL a NULL NULL NULL 4 Using where drop table t1,t2; create table t1 (a int, b int); -insert into t1 values (1, 4); -insert into t1 values (10, 40); -insert into t1 values (1, 4); -insert into t1 values (10, 43); -insert into t1 values (1, 4); -insert into t1 values (10, 41); -insert into t1 values (1, 4); -insert into t1 values (10, 43); -insert into t1 values (1, 4); +insert into t1 values (1, 4),(10, 40),(1, 4),(10, 43),(1, 4),(10, 41),(1, 4),(10, 43),(1, 4); select a, MAX(b), INTERVAL (MAX(b), 1,3,10,30,39,40,50,60,100,1000) from t1 group by a; a MAX(b) INTERVAL (MAX(b), 1,3,10,30,39,40,50,60,100,1000) 1 4 2 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 48db5412da7..293519604dd 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1201,3 +1201,74 @@ a b 8 5 9 5 drop table t1,t2; +create table t1 (a int not null auto_increment primary key, b int, c int, key(c)) type=innodb; +create table t2 (a int not null auto_increment primary key, b int); +insert into t1 (b) values (null),(null),(null),(null),(null),(null),(null); +insert into t2 (a) select b from t1; +insert into t1 (b) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +insert into t2 (a) select b from t1; +insert into t1 (a) select b from t2; +select count(*) from t1; +count(*) +29267 +explain select a from t1 where a between 1 and 10000; +table type possible_keys key key_len ref rows Extra +t1 range PRIMARY PRIMARY 4 NULL 14790 Using where; Using index +explain select * from t1 where a between 1 and 10000; +table type possible_keys key key_len ref rows Extra +t1 range PRIMARY PRIMARY 4 NULL 14790 Using where +explain select * from t1 where c between 1 and 10000; +table type possible_keys key key_len ref rows Extra +t1 range c c 5 NULL 1 Using where +update t1 set c=a; +explain select * from t1 where c between 1 and 10000; +table type possible_keys key key_len ref rows Extra +t1 ALL c NULL NULL NULL 29537 Using where +drop table t1,t2; +create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) type=innodb; +insert into t1 (id) values (null),(null),(null),(null),(null); +update t1 set fk=69 where fk is null order by id limit 1; +SELECT * from t1; +id fk +2 NULL +3 NULL +4 NULL +5 NULL +1 69 +drop table t1; +create table t1 (a int not null, b int not null, key (a)); +insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3); +SET @tmp=0; +update t1 set b=(@tmp:=@tmp+1) order by a; +update t1 set b=99 where a=1 order by b asc limit 1; +update t1 set b=100 where a=1 order by b desc limit 2; +update t1 set a=a+10+b where a=1 order by b; +select * from t1 order by a,b; +a b +2 4 +2 5 +2 6 +3 7 +3 8 +3 9 +3 10 +3 11 +3 12 +13 2 +111 100 +111 100 +drop table t1; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 6e69616b7c6..98f8882aa10 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -373,10 +373,10 @@ Thimble Smith Happy 3 3 3 drop table t1,t2; create table t1 (id int not null, str char(10), index(str)); insert into t1 values (1, null), (2, null), (3, "foo"), (4, "bar"); -select * from t1 where str is not null; +select * from t1 where str is not null order by id; id str -4 bar 3 foo +4 bar select * from t1 where str is null; id str 1 NULL diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 0f3644f15bc..daac5438eaa 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -286,7 +286,7 @@ a b 107 7 108 8 109 9 -update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5; +update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t2.a=t1.a-100; select * from t1; a b 201 1 @@ -300,13 +300,13 @@ a b 109 9 select * from t2; a b -1 3 -2 3 -3 3 -4 3 -5 3 -6 3 -7 3 -8 3 -9 3 +1 1 +2 2 +3 13 +4 14 +5 15 +6 6 +7 7 +8 8 +9 9 drop table t1,t2; diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 236def64b5e..009a3e06eb2 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -84,7 +84,7 @@ table type possible_keys key key_len ref rows Extra t1 range a,b a 5 NULL 5 Using where explain select * from t1 where (a is null or a = 7) and b=7 and c=0; table type possible_keys key key_len ref rows Extra -t1 range a,b a 5 NULL 4 Using where +t1 ALL a,b NULL NULL NULL 12 Using where explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2; table type possible_keys key key_len ref rows Extra t1 ref a,b a 5 const 3 Using where diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index db209c5855c..86647e845a9 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -102,13 +102,39 @@ select status from t1; status 1 drop table t1; -create table t1 (a int not null, b int not null); -insert into t1 values (1,1),(1,2),(1,3); -update t1 set b=4 where a=1 order by b asc limit 1; -update t1 set b=4 where a=1 order by b desc limit 1; -select * from t1; +create table t1 (a int not null, b int not null, key (a)); +insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3); +SET @tmp=0; +update t1 set b=(@tmp:=@tmp+1) order by a; +update t1 set b=99 where a=1 order by b asc limit 1; +select * from t1 order by a,b; a b -1 4 1 2 -1 4 +1 3 +1 99 +2 4 +2 5 +2 6 +3 7 +3 8 +3 9 +3 10 +3 11 +3 12 +update t1 set b=100 where a=1 order by b desc limit 2; +update t1 set a=a+10+b where a=1 order by b; +select * from t1 order by a,b; +a b +2 4 +2 5 +2 6 +3 7 +3 8 +3 9 +3 10 +3 11 +3 12 +13 2 +111 100 +111 100 drop table t1; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 9e5ee4b8b2a..8c111430eea 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -40,6 +40,7 @@ SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; +EXPLAIN SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; drop table test.t1,test.t2; # @@ -236,7 +237,7 @@ CREATE TABLE t1 ( key (score) ); -INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3); +INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3),(6,3,3),(7,3,3); explain select userid,count(*) from t1 group by userid desc; explain select userid,count(*) from t1 group by userid desc order by null; select userid,count(*) from t1 group by userid desc; @@ -255,8 +256,6 @@ explain select sql_big_result score,count(*) from t1 group by score desc order b select sql_big_result score,count(*) from t1 group by score desc; drop table t1; -# - # not purely group_by bug, but group_by is involved... create table t1 (a date default null, b date default null); @@ -265,7 +264,6 @@ select a,min(b) c,count(distinct rand()) from t1 group by a having cday= tmp & 31; ltime->month= (tmp >> 5) & 15; ltime->year= (tmp >> 9); ltime->time_type=TIMESTAMP_DATE; + ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0; return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0; } diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 504f5262bf3..31126111d9d 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -54,8 +54,9 @@ class ha_heap: public handler uint max_keys() const { return MAX_KEY; } uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_length() const { return HA_MAX_REC_LENGTH; } - virtual double scan_time() { return (double) (records+deleted) / 20.0+10; } - virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; } + double scan_time() { return (double) (records+deleted) / 20.0+10; } + double read_time(uint index, uint ranges, ha_rows rows) + { return (double) rows / 20.0+1; } virtual bool fast_key_read() { return 1;} int open(const char *name, int mode, uint test_if_locked); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index ea8eaf6653e..b7b72426053 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3501,10 +3501,8 @@ ha_innobase::records_in_range( /************************************************************************* Gives an UPPER BOUND to the number of rows in a table. This is used in -filesort.cc and the upper bound must hold. TODO: Since the number of -rows in a table may change after this function is called, we still may -get a 'Sort aborted' error in filesort.cc of MySQL. The ultimate fix is to -improve the algorithm of filesort.cc. */ +filesort.cc and its better if the upper bound hold. +*/ ha_rows ha_innobase::estimate_number_of_rows(void) @@ -3570,6 +3568,29 @@ ha_innobase::scan_time() return((double) (prebuilt->table->stat_clustered_index_size)); } +/* + Calculate the time it takes to read a set of ranges through and index + This enables us to optimise reads for clustered indexes. +*/ + +double ha_innobase::read_time(uint index, uint ranges, ha_rows rows) +{ + ha_rows total_rows; + double time_for_scan; + if (index != table->primary_key) + return handler::read_time(index, ranges, rows); // Not clustered + if (rows <= 2) + return (double) rows; + /* + Assume that the read is proportional to scan time for all rows + one + seek per range. + */ + time_for_scan= scan_time(); + if ((total_rows= estimate_number_of_rows()) < rows) + return time_for_scan; + return (ranges + (double) rows / (double) total_rows * time_for_scan); +} + /************************************************************************* Returns statistics information of the table to the MySQL interpreter, in various fields of the handle object. */ diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 8031fa0aa29..f7aa1d3b277 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -118,6 +118,7 @@ class ha_innobase: public handler void initialize(void); int close(void); double scan_time(); + double read_time(uint index, uint ranges, ha_rows rows); int write_row(byte * buf); int update_row(const byte * old_data, byte * new_data); diff --git a/sql/handler.h b/sql/handler.h index 8f1d00f64b5..72a05d7ebee 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -227,7 +227,8 @@ public: void change_table_ptr(TABLE *table_arg) { table=table_arg; } virtual double scan_time() { return ulonglong2double(data_file_length) / IO_SIZE + 1; } - virtual double read_time(ha_rows rows) { return rows2double(rows); } + virtual double read_time(uint index, uint ranges, ha_rows rows) + { return rows2double(ranges+rows); } virtual bool fast_key_read() { return 0;} virtual key_map keys_to_use_for_scanning() { return 0; } virtual bool has_transactions(){ return 0;} diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 3a513505913..d88894d4fb4 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1066,7 +1066,7 @@ bool Item_sum_count_distinct::setup(THD *thd) int Item_sum_count_distinct::tree_to_myisam() { - if (create_myisam_from_heap(table, tmp_table_param, + if (create_myisam_from_heap(current_thd, table, tmp_table_param, HA_ERR_RECORD_FILE_FULL, 1) || tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this, left_root_right)) @@ -1120,7 +1120,8 @@ bool Item_sum_count_distinct::add() if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE) { - if (create_myisam_from_heap(table, tmp_table_param, error,1)) + if (create_myisam_from_heap(current_thd, table, tmp_table_param, error, + 1)) return 1; // Not a table_is_full error } } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 24e343017e2..4c2bda6e1d6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -42,7 +42,7 @@ #define MAIN_THD #define SIGNAL_THD -#ifdef PURIFY +#ifdef HAVE_purify #define IF_PURIFY(A,B) (A) #else #define IF_PURIFY(A,B) (B) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index aeeabb7d29c..cc45e18e54c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -284,7 +284,7 @@ typedef struct st_qsel_param { KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY]; MEM_ROOT *mem_root; table_map prev_tables,read_tables,current_table; - uint baseflag,keys,max_key_part; + uint baseflag, keys, max_key_part, range_count; uint real_keynr[MAX_KEY]; char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH], max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; @@ -710,8 +710,10 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, (double) keys_per_block); } else - found_read_time= head->file->read_time(found_records)+ - (double) found_records / TIME_FOR_COMPARE; + found_read_time= (head->file->read_time(keynr, + param.range_count, + found_records)+ + (double) found_records / TIME_FOR_COMPARE); if (read_time > found_read_time) { read_time=found_read_time; @@ -2113,11 +2115,12 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) if (!tree) DBUG_RETURN(HA_POS_ERROR); // Can't use it + param->max_key_part=0; + param->range_count=0; if (tree->type == SEL_ARG::IMPOSSIBLE) DBUG_RETURN(0L); // Impossible select. return if (tree->type != SEL_ARG::KEY_RANGE || tree->part != 0) DBUG_RETURN(HA_POS_ERROR); // Don't use tree - param->max_key_part=0; records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0); if (records != HA_POS_ERROR) { @@ -2185,6 +2188,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, } keynr=param->real_keynr[idx]; + param->range_count++; if (!tmp_min_flag && ! tmp_max_flag && (uint) key_tree->part+1 == param->table->key_info[keynr].key_parts && (param->table->key_info[keynr].flags & HA_NOSAME) && diff --git a/sql/records.cc b/sql/records.cc index 22c4d54550c..fd46506203f 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -15,7 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Functions to read, write and lock records */ +/* Functions for easy reading of records, possible through a cache */ #include "mysql_priv.h" diff --git a/sql/sql_list.h b/sql/sql_list.h index 542eef623f0..bbda93d32f5 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* 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 diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 96de43ae55c..14b567b86c5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1829,7 +1829,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, { ha_rows rec; double tmp; - THD *thd= current_thd; + THD *thd= join->thd; if (!rest_tables) { @@ -1960,7 +1960,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, if (table->quick_keys & ((key_map) 1 << key)) records= (double) table->quick_rows[key]; else - records= (double) s->records/rec; // quick_range couldn't use key! + { + /* quick_range couldn't use key! */ + records= (double) s->records/rec; + } } else { @@ -4306,12 +4309,11 @@ free_tmp_table(THD *thd, TABLE *entry) * If a HEAP table gets full, create a MyISAM table and copy all rows to this */ -bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error, - bool ignore_last_dupp_key_error) +bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, + int error, bool ignore_last_dupp_key_error) { TABLE new_table; const char *save_proc_info; - THD *thd=current_thd; int write_err; DBUG_ENTER("create_myisam_from_heap"); @@ -5318,7 +5320,8 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE) goto end; - if (create_myisam_from_heap(table, &join->tmp_table_param, error,1)) + if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param, + error,1)) DBUG_RETURN(-1); // Not a table_is_full error table->uniques=0; // To ensure rows are the same } @@ -5395,7 +5398,8 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), copy_funcs(join->tmp_table_param.items_to_copy); if ((error=table->file->write_row(table->record[0]))) { - if (create_myisam_from_heap(table, &join->tmp_table_param, error, 0)) + if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param, + error, 0)) DBUG_RETURN(-1); // Not a table_is_full error /* Change method to update rows */ table->file->index_init(0); @@ -5489,8 +5493,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if ((error=table->file->write_row(table->record[0]))) { - if (create_myisam_from_heap(table, &join->tmp_table_param, - error, 0)) + if (create_myisam_from_heap(join->thd, table, + &join->tmp_table_param, error, 0)) DBUG_RETURN(-1); // Not a table_is_full error } else @@ -6019,7 +6023,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List &fields, Item *having) int error; ulong reclength,offset; uint field_count; - THD *thd= current_thd; + THD *thd= join->thd; DBUG_ENTER("remove_duplicates"); entry->reginfo.lock_type=TL_WRITE; diff --git a/sql/sql_select.h b/sql/sql_select.h index 332778aafe6..5c987e74163 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -195,8 +195,8 @@ void count_field_types(TMP_TABLE_PARAM *param, List &fields, bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List &fields); void copy_fields(TMP_TABLE_PARAM *param); void copy_funcs(Item **func_ptr); -bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error, - bool ignore_last_dupp_error); +bool create_myisam_from_heap(THD *Thd, TABLE *table, TMP_TABLE_PARAM *param, + int error, bool ignore_last_dupp_error); /* functions from opt_sum.cc */ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index faa106d4f42..e7afa7fbd23 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -262,7 +262,8 @@ bool select_union::send_data(List &values) fill_record(table->field,values); if ((write_record(table,&info))) { - if (create_myisam_from_heap(table, tmp_table_param, info.last_errno, 0)) + if (create_myisam_from_heap(thd, table, tmp_table_param, info.last_errno, + 0)) return 1; } return 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 709f88726de..653b16a45e9 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -66,7 +66,10 @@ int mysql_update(THD *thd, TABLE *table; SQL_SELECT *select; READ_RECORD info; + TABLE_LIST tables; + List all_fields; DBUG_ENTER("mysql_update"); + LINT_INIT(used_index); LINT_INIT(timestamp_query_id); @@ -80,8 +83,13 @@ int mysql_update(THD *thd, table->quick_keys=0; want_privilege=table->grant.want_privilege; table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); - if (setup_tables(table_list) || setup_conds(thd,table_list,&conds) - || setup_ftfuncs(thd)) + + bzero((char*) &tables,sizeof(tables)); // For ORDER BY + tables.table = table; + + if (setup_tables(table_list) || setup_conds(thd,table_list,&conds) || + setup_order(thd, &tables, all_fields, all_fields, order) || + setup_ftfuncs(thd)) DBUG_RETURN(-1); /* purecov: inspected */ old_used_keys=table->used_keys; // Keys used in WHERE @@ -159,13 +167,6 @@ int mysql_update(THD *thd, matching rows before updating the table! */ table->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE); - IO_CACHE tempfile; - if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX, - DISK_BUFFER_SIZE, MYF(MY_WME))) - { - delete select; /* purecov: inspected */ - DBUG_RETURN(-1); - } if (old_used_keys & ((key_map) 1 << used_index)) { table->key_read=1; @@ -174,81 +175,97 @@ int mysql_update(THD *thd, if (order) { + /* + Doing an ORDER BY; Let filesort find and sort the rows we are going + to update + */ uint length; SORT_FIELD *sortorder; - TABLE_LIST tables; List fields; - List all_fields; ha_rows examined_rows; - bzero((char*) &tables,sizeof(tables)); - tables.table = table; - table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), MYF(MY_FAE | MY_ZEROFILL)); - if (setup_order(thd, &tables, fields, all_fields, order) || - !(sortorder=make_unireg_sortorder(order, &length)) || + if (!(sortorder=make_unireg_sortorder(order, &length)) || (table->found_records = filesort(table, sortorder, length, - (SQL_SELECT *) 0, 0L, - HA_POS_ERROR, &examined_rows)) - == HA_POS_ERROR) + select, 0L, + limit, &examined_rows)) == + HA_POS_ERROR) + { + delete select; + free_io_cache(table); + DBUG_RETURN(-1); + } + /* + Filesort has already found and selected the rows we want to update, + so we don't need the where clause + */ + delete select; + select= 0; + } + else + { + /* + We are doing a search on a key that is updated. In this case + we go trough the matching rows, save a pointer to them and + update these in a separate loop based on the pointer. + */ + + IO_CACHE tempfile; + if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX, + DISK_BUFFER_SIZE, MYF(MY_WME))) + { + delete select; /* purecov: inspected */ + DBUG_RETURN(-1); + } + + init_read_record(&info,thd,table,select,0,1); + thd->proc_info="Searching rows for update"; + uint tmp_limit= limit; + while (!(error=info.read_record(&info)) && !thd->killed) + { + if (!(select && select->skipp_record())) + { + table->file->position(table->record[0]); + if (my_b_write(&tempfile,table->file->ref, + table->file->ref_length)) + { + error=1; /* purecov: inspected */ + break; /* purecov: inspected */ + } + if (!--limit && using_limit) + break; + } + } + end_read_record(&info); + /* Change select to use tempfile */ + if (select) + { + delete select->quick; + if (select->free_cond) + delete select->cond; + select->quick=0; + select->cond=0; + } + else + { + select= new SQL_SELECT; + select->head=table; + } + if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) + error=1; /* purecov: inspected */ + select->file=tempfile; // Read row ptrs from this file + if (error >= 0) { delete select; DBUG_RETURN(-1); } } - - init_read_record(&info,thd,table,select,0,1); - thd->proc_info="Searching rows for update"; - - while (!(error=info.read_record(&info)) && !thd->killed) - { - if (!(select && select->skipp_record())) - { - table->file->position(table->record[0]); - if (my_b_write(&tempfile,table->file->ref, - table->file->ref_length)) - { - error=1; /* purecov: inspected */ - break; /* purecov: inspected */ - } - } - else - { - if (!(test_flags & 512)) /* For debugging */ - { - DBUG_DUMP("record",(char*) table->record[0],table->reclength); - } - } - } - end_read_record(&info); if (table->key_read) { table->key_read=0; table->file->extra(HA_EXTRA_NO_KEYREAD); } - /* Change select to use tempfile */ - if (select) - { - delete select->quick; - if (select->free_cond) - delete select->cond; - select->quick=0; - select->cond=0; - } - else - { - select= new SQL_SELECT; - select->head=table; - } - if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) - error=1; /* purecov: inspected */ - select->file=tempfile; // Read row ptrs from this file - if (error >= 0) - { - delete select; - DBUG_RETURN(-1); - } } if (handle_duplicates == DUP_IGNORE) @@ -275,11 +292,6 @@ int mysql_update(THD *thd, (byte*) table->record[0]))) { updated++; - if (!--limit && using_limit) - { - error= -1; - break; - } } else if (handle_duplicates != DUP_IGNORE || error != HA_ERR_FOUND_DUPP_KEY) @@ -289,11 +301,17 @@ int mysql_update(THD *thd, break; } } + if (!--limit && using_limit) + { + error= -1; // Simulate end of file + break; + } } else table->file->unlock_row(); } end_read_record(&info); + free_io_cache(table); // If ORDER BY thd->proc_info="end"; VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY)); transactional_table= table->file->has_transactions(); @@ -741,7 +759,8 @@ bool multi_update::send_data(List ¬_used_values) (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE)) { - if (create_myisam_from_heap(table, tmp_table_param + offset, error, 1)) + if (create_myisam_from_heap(thd, table, tmp_table_param + offset, + error, 1)) { do_update=0; DBUG_RETURN(1); // Not a table_is_full error diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index 3362d5bd131..61d0a923058 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -33,6 +33,7 @@ set-variable = sort_buffer_size=2M set-variable = read_buffer_size=2M set-variable = myisam_sort_buffer_size=64M set-variable = thread_cache=8 +set-variable = query_cache_size=32M # Try number of CPU's*2 for thread_concurrency set-variable = thread_concurrency=8 diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 5bc3a8eb0c4..56ac70450e6 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -33,6 +33,7 @@ set-variable = sort_buffer_size=1M set-variable = read_buffer_size=1M set-variable = myisam_sort_buffer_size=64M set-variable = thread_cache=8 +set-variable = query_cache_size=16M # Try number of CPU's*2 for thread_concurrency set-variable = thread_concurrency=8 From 6f28bdee0b5d738ae9c655dc1149ff96d4dcdda1 Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Wed, 23 Apr 2003 13:20:23 -0700 Subject: [PATCH 081/188] Minor changes to PeterG's internals documentation per comments from Monty. --- Docs/internals.texi | 314 ++++++++++++++++++-------------------------- 1 file changed, 131 insertions(+), 183 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index b5a7244695f..07eea90e229 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -2078,8 +2078,8 @@ right is @code{on}, and (b) remember that the first flag bit is the X bit.) There are complications -- the record header is more complex if there are variable-length fields -- but the simple display shown in the -example is exactly what you'd see if you took a debugger and looked -at the MySQL Data file. +example is exactly what you'd see if you looked at the MySQL Data file +with a debugger or a hexadecimal file dumper. @* @section Physical Attributes of Columns @@ -2112,8 +2112,8 @@ Example: a VARCHAR(7) column containing 'A' looks like:@* @item The numeric data types -Important: MySQL stores all multi-byte binary numbers with the -high byte first. This is called "little-endian" numeric storage; +Important: MySQL almost always stores multi-byte binary numbers with +the low byte first. This is called "little-endian" numeric storage; it's normal on Intel x86 machines; MySQL uses it even for non-Intel machines so that databases will be portable. @* @@ -2288,7 +2288,7 @@ Example: a SET('A','B','C') column containing 'A' looks like:@* Storage: one byte if less than 256 alternatives, else two bytes. @item This is an index. The value 1 corresponds to the first listed -alternative. (Note: ENUM always reserves 0 for a blank '' value. This +alternative. (Note: ENUM always reserves 0 for an erroneous value. This explains why 'A' is 1 instead of 0.) @item Example: an ENUM('A','B','C') column containing 'A' looks like:@* @@ -2373,7 +2373,10 @@ Storage: same as LONGBLOB. @strong{References:} @* Most of the formatting work for MyISAM columns is visible -in the program /sql/field.cc in the source code directory. +in the program /sql/field.cc in the source code directory. +And in the MyISAM directory, the files that do formatting +work for different record formats are: /myisam/mi_statrec.c, +/myisam/mi_dynrec.c, and /myisam/mi_packrec.c. @* @node InnoDB Record Structure,InnoDB Page Structure,MyISAM Record Structure,Top @@ -3118,7 +3121,7 @@ page0page.ic, and page0page.h in \page directory. This is a description of the files that you get when you download the source code of MySQL. This description begins with a list -of the 43 directories and a short comment about each one. Then, for +of the main directories and a short comment about each one. Then, for each directory, in alphabetical order, a longer description is supplied. When a directory contains significant program files, a list of each C program is given along with an explanation of its intended function. @@ -3130,43 +3133,37 @@ program is given along with an explanation of its intended function. @item bdb -- The Berkeley Database table handler @item -BitKeeper -- BitKeeper administration +BitKeeper -- BitKeeper administration (not part of the source distribution) @item -BUILD -- Build switches +BUILD -- Some very often used build scripts @item -Build-tools -- Build tools +Build-tools -- Build tools @item client -- Client library @item -cmd-line-utils -- Command-line utilities +cmd-line-utils -- Command-line utilities (libedit and readline) @item -dbug -- Fred Fish's dbug library -@item -div -- Deadlock test +dbug -- Fred Fish's dbug library @item Docs -- Preliminary documents about internals and new modules @item -extra -- Eight minor standalone utility programs +extra -- Some minor standalone utility programs @item -fs -- File System +heap -- The HEAP table handler @item -heap -- The HEAP table handler +include -- Include (*.h) files @item -Images -- Empty directory +innobase -- The Innobase (InnoDB) table handler @item -include -- Include (*.h) files +isam -- The ISAM (MySQL) table handler @item -innobase -- The Innobase (InnoDB) table handler +libmysql -- For producing a thread-safe libmysql library @item -isam -- The ISAM (MySQL) table handler +libmysql_r -- Only one file, a makefile @item -libmysql -- For producing MySQL as a library (e.g. a Windows DLL) +libmysqld -- The MySQL Server as an embeddable library @item -libmysql_r -- Only one file, a makefile -@item -libmysqld -- The MySQL Library -@item -man -- Manual pages +man -- Some user-contributed manual pages @item merge -- The MERGE table handler (see Reference Manual section 7.2) @item @@ -3176,24 +3173,21 @@ myisammrg -- The MyISAM Merge table handler @item mysql-test -- A test suite for mysqld @item -mysys -- MySQL system library (Low level routines for file access -etc.) +mysys -- MySQL system library (Low level routines for file access etc.) @item netware -- Files related to the Novell NetWare version of MySQL @item -NEW-RPMS -- New "RPM Package Manager" files +NEW-RPMS -- Directory to place RPMS while making a distribution @item os2 -- Routines for working with the OS/2 operating system @item -pstack -- Process stack display +pstack -- Process stack display (not currently used) @item -regex -- Regular Expression library for support of REGEXP function +regex -- Henry Spencer's Regular Expression library for support of REGEXP function @item -repl-tests -- Test cases for replication +SCCS -- Source Code Control System (not part of source distribution) @item -SCCS -- Source Code Control System -@item -scripts -- SQL batches, e.g. for converting msql to MySQL +scripts -- SQL batches, e.g. mysqlbug and mysql_install_db @item sql -- Programs for handling SQL commands. The "core" of MySQL @item @@ -3203,18 +3197,17 @@ SSL -- Secure Sockets Layer @item strings -- Library for C string routines, e.g. atof, strchr @item -support-files -- 15 files used for building, containing switches? +support-files -- Files used to build MySQL on different systems @item tests -- Tests in Perl @item -tools -- mysqlmanager.c +tools -- mysqlmanager.c (under development, not yet useful) @item -VC++Files -- Includes this entire directory, repeated for VC++ -(Windows) use +VC++Files -- Includes this entire directory, repeated for VC++ (Windows) use @item vio -- Virtual I/O Library @item -zlib -- data compression library +zlib -- data compression library, used on Windows @end itemize @subsection bdb @@ -3222,7 +3215,9 @@ zlib -- data compression library The Berkeley Database table handler. @*@* -The Berkeley Database (BDB) is maintained by Sleepycat Software. +The Berkeley Database (BDB) is maintained by Sleepycat Software. +MySQL AB maintains only a few small patches to make BDB work +better with MySQL. @*@* The documentation for BDB is available at @@ -3242,6 +3237,10 @@ BitKeeper directory are for maintenance purposes only -- they are not part of the MySQL package. @*@* +The MySQL Reference Manual explains how to use Bitkeeper to get the +MySQL source. +@*@* + @subsection BUILD Build switches. @@ -3268,9 +3267,10 @@ Build tools. @*@* This directory contains batch files for extracting, making -directories, and making programs from source files. There are several -subdirectories -- for building Linux executables, for compiling, for -performing all build steps, etc. +directories, and making programs from source files. There are +several subdirectories with different scripts -- for building +Linux executables, for compiling, for performing all build steps, +and so on. @*@* @subsection client @@ -3288,32 +3288,31 @@ server. The C program files in the directory are: @itemize @bullet @item -connect_test.c -- test that a connect is possible +connect_test.c -- test that a connect is possible @item -get_password.c -- ask for a password from the console +get_password.c -- ask for a password from the console @item -insert_test.c -- test that an insert is possible +insert_test.c -- test that an insert is possible @item -list_test.c -- test that a select is possible +list_test.c -- test that a select is possible @item -mysql.cc -- "The MySQL command tool" +mysql.cc -- "The MySQL command tool" @item -mysqladmin.c -- maintenance of MYSQL databases +mysqladmin.c -- maintenance of MYSQL databases @item -mysqlcheck.c -- check all databases, check connect, etc. +mysqlcheck.c -- check all databases, check connect, etc. @item -mysqldump.c -- dump table's contents in ascii +mysqldump.c -- dump table's contents as SQL statements @item -mysqlimport.c -- import file into a table +mysqlimport.c -- import text files in different formats into tables @item -mysqlmanager-pwgen.c -- pwgen seems to stand for "password -generation" +mysqlmanager-pwgen.c -- pwgen stands for "password generation" (not currently maintained) @item -mysqlmanagerc.c -- entry point for mysql manager +mysqlmanagerc.c -- entry point for mysql manager (not currently maintained) @item mysqlshow.c -- show databases, tables or columns @item -mysqltest.c -- test program +mysqltest.c -- test program used by the mysql-test suite, mysql-test-run @item password.c -- password checking routines @item @@ -3347,7 +3346,10 @@ Software Foundation. @*@* The \libedit (library of edit functions) subdirectory has files -written by Christos Zoulas. They are for editing the line contents. +written by Christos Zoulas. They are distributed and modifed under +the BSD License. These files are for editing the line contents. +@*@* + These are the program files in the \libedit subdirectory: @itemize @bullet @item @@ -3401,7 +3403,9 @@ Fred Fish's dbug library. @*@* This is not really part of the MySQL package. Rather, it's a set of -public-domain routines which are useful for debugging MySQL programs. +public-domain routines which are useful for debugging MySQL programs. +The MySQL Server and all .c and .cc programs support the use of this +package. @*@* How it works: One inserts a function call that begins with DBUG_* in @@ -3411,7 +3415,8 @@ DBUG_ENTER("get_tty_password"); @* at the start of a routine, and this line: @* DBUG_RETURN(my_strdup(to,MYF(MY_FAE))); @* at the end of the routine. These lines don't affect production code. -Features of the dbug library include profiling and state pushing. +Features of the dbug library include extensive reporting and profiling +(the latter has not been used by the MySQL team). @*@* The C programs in this directory are: @@ -3435,14 +3440,6 @@ sanity.c -- Declaration of a variable @end itemize @*@* -@subsection div - -Deadlock test. -@*@* - -This file contains only one program, deadlock_test.c. -@*@* - @subsection Docs Preliminary documents about internals and new modules. @@ -3451,7 +3448,8 @@ Preliminary documents about internals and new modules. This directory doesn't have much at present that's very useful to the student, but the plan is that some documentation related to the source files and the internal workings of MySQL, including perhaps some -documentation from developers themselves, will be placed here. +documentation from developers themselves, will be placed here. Some of +these files will eventually be moved to the MySQL documentation repository. @*@* These sub-directories are part of this directory: @@ -3467,8 +3465,7 @@ mysql-logos -- more MySQL-related logos, some of them moving @item raw-flags -- more country flags, all .gif files @item -support -- various files for generating texinfo/docbook -documentation +support -- various files for generating texinfo/docbook documentation @item to-be-included... -- an empty subdirectory @item @@ -3495,7 +3492,7 @@ make their own JDBC drivers, or just sniff). Eight minor standalone utility programs. @*@* -These eight programs are all standalone utilities, that is, they have +These programs are all standalone utilities, that is, they have a main() function and their main role is to show information that the MySQL server needs or produces. Most are unimportant. They are as follows: @@ -3509,7 +3506,7 @@ mysql_waitpid.c -- wait for a program to terminate @item perror.c -- "print error" -- given error number, display message @item -replace.c -- replace strings in text files +replace.c -- replace strings in text files or pipe @item resolve_stack_dump.c -- show symbolic info from a stack dump @item @@ -3568,7 +3565,7 @@ an "*" in the following list. For example, you will find that @item hp_block.c -- Read/write a block (i.e. a page) @item -hp_clear.c -- Remove all records in the database +hp_clear.c -- Remove all records in the table @item hp_close.c -- * close database @item @@ -3584,7 +3581,7 @@ hp_info.c -- * Information about database status @item hp_open.c -- * open database @item -hp_panic.c -- * the hp_panic routine, probably for sudden shutdowns +hp_panic.c -- * the hp_panic routine, for shutdowns and flushes @item hp_rename.c -- * rename a table @item @@ -3596,8 +3593,7 @@ hp_rlast.c -- * read last row with same key as previously-read row @item hp_rnext.c -- * read next row with same key as previously-read row @item -hp_rprev.c -- * read previous row with same key as previously-read -row +hp_rprev.c -- * read previous row with same key as previously-read row @item hp_rrnd.c -- * read a row based on position @item @@ -3624,14 +3620,6 @@ for a \myisam\mi_cache.c equivalent (to cache reads) or a \myisam\log.c equivalent (to log statements). @*@* -@subsection Images - -Empty directory. -@*@* - -There are no files in this directory. -@*@* - @subsection include Include (*.h) files. @@ -3946,25 +3934,23 @@ mi_dynrec.c -- functions to handle space-packed records and blobs @item mi_extra.c -- setting options and buffer sizes when optimizing @item -mi_info.c -- "Ger tillbaka en struct med information om isam-filen" +mi_info.c -- return useful base information for an open table @item -mi_key.c -- for handling keys +mi_key.c -- for handling keys @item mi_locking.c -- lock database @item -mi_log.c -- save commands in log file which myisamlog program can -read +mi_log.c -- save commands in log file which myisamlog program can read @item mi_open.c -- open database @item -mi_packrec.c -- compress records +mi_packrec.c -- read from a data file compresed with myisampack @item mi_page.c -- read and write pages containing keys @item mi_panic.c -- the mi_panic routine, probably for sudden shutdowns @item -mi_range.c -- approximate count of how many records lie between two -keys +mi_range.c -- approximate count of how many records lie between two keys @item mi_rename.c -- rename a table @item @@ -4113,8 +4099,6 @@ There are other tests in these directories: @item sql-bench @item -repl-tests -@item tests @end itemize @@ -4281,8 +4265,7 @@ free" @item my_open.c -- Open a file @item -my_os2cond.c -- OS2-specific: "A simple implementation of posix -conditions" +my_os2cond.c -- OS2-specific: "A simple implementation of posix conditions" @item my_os2dirsrch.c -- OS2-specific: Emulate a Win32 directory search @item @@ -4296,12 +4279,11 @@ my_os2thread.c -- OS2-specific: For thread handling @item my_os2tls.c -- OS2-specific: For thread-local storage @item -my_port.c -- AIX-specific: my_ulonglong2double() +my_port.c -- OS/machine-dependent porting functions, e.g. AIX-specific my_ulonglong2double() @item my_pread.c -- Read a specified number of bytes from a file @item -my_pthread.c -- A wrapper for thread-handling functions in different -OSs +my_pthread.c -- A wrapper for thread-handling functions in different OSs @item my_quick.c -- Read/write (labelled a "quicker" interface, perhaps obsolete) @@ -4323,15 +4305,13 @@ support them @item my_sleep.c -- Wait n microseconds @item -my_static.c -- Static-variable definitions +my_static.c -- Static variables used by the mysys library @item -my_symlink.c -- Read a symbolic link (symlinks are a UNIX thing, I -guess) +my_symlink.c -- Read a symbolic link (symlinks are a UNIX thing, I guess) @item my_symlink2.c -- Part 2 of my_symlink.c @item -my_tempnam.c -- Obsolete temporary-filename routine used by ISAM -table handler +my_tempnam.c -- Obsolete temporary-filename routine used by ISAM table handler @item my_thr_init.c -- initialize/allocate "all mysys & debug thread variables" @@ -4448,9 +4428,8 @@ NetWare AMP" at: New "RPM Package Manager" files. @*@* -This directory is not part of the Windows distribution. Perhaps in -MYSQL's Linux distribution it has files for use with Red Hat -installations -- a point that needs checking someday. +This directory is not part of the Windows distribution. It is +a temporary directory used during RPM builds with Linux distributions. @*@* @subsection os2 @@ -4523,28 +4502,6 @@ This program calls the 'regcomp' function, which is the entry point in \regex\regexp.c. @*@* -@subsection repl-tests - -Test cases for replication. -@*@* - -There are six short and trivial-looking tests in these subdirectories: -@itemize @bullet -@item -\test-auto-inc -- Do auto-Increment columns work? -@item -\test-bad-query -- Does insert in PK column work? -@item -\test-dump -- Do LOAD statements work? -@item -\test-repl -- Does replication work? -@item -\test-repl-alter -- Does ALTER TABLE work? -@item -\test-repl-ts -- Does TIMESTAMP column work? -@end itemize -@*@* - @subsection SCCS Source Code Control System. @@ -4560,8 +4517,8 @@ administration and are not of interest to application programmers. SQL batches, e.g. for converting msql to MySQL. @*@* -The *.sh filename extension apparently stands for "shell script". -Linux programmers use it where Windows programmers would use a *.bat +The *.sh filename extension stands for "shell script". Linux +programmers use it where Windows programmers would use a *.bat (batch filename extension). @*@* @@ -4570,10 +4527,9 @@ The *.sh files on this directory are: @item fill_help_tables.sh -- Create help-information tables and insert @item -make_binary_distribution.sh -- Get configure information, make, -produce tar +make_binary_distribution.sh -- Get configure information, make, produce tar @item -msql2mysql.sh -- Convert mSQL to MySQL +msql2mysql.sh -- Convert mSQL programs and scripts to MySQL, partly @item mysqlbug.sh -- Create a bug report and mail it @item @@ -4587,33 +4543,29 @@ mysqldumpslow.sh -- Parse and summarize the slow query log @item mysqlhotcopy.sh -- Hot backup @item -mysql_config.sh -- Get configure information that client might need +mysql_config.sh -- Get configuration information that might be needed to compile a client @item -mysql_convert_table_format.sh -- Conversion, e.g. from ISAM to -MyISAM +mysql_convert_table_format.sh -- Conversion, e.g. from ISAM to MyISAM @item -mysql_explain_log.sh -- Put a log (made with --log) into a MySQL -table +mysql_explain_log.sh -- Put a log (made with --log) into a MySQL table @item -mysql_find_rows.sh -- Search for queries containing +mysql_find_rows.sh -- Search for queries containing @item -mysql_fix_extensions.sh -- Renames some file extensions, not -recommended +mysql_fix_extensions.sh -- Renames some file extensions, not recommended @item -mysql_fix_privilege_tables.sh -- Fix mysql.user etc. if upgrading to -MySQL 3.23.14+ +mysql_fix_privilege_tables.sh -- Fix mysql.user etc. if upgrading to MySQL 3.23.14+ @item -mysql_install_db.sh -- Create privilege tables and func table +mysql_install_db.sh -- Create privilege tables and func table @item mysql_secure_installation.sh -- Disallow remote root login, -eliminate test, etc. +eliminate test, etc. @item mysql_setpermission.sh -- Aid to add users or databases, sets -privileges +privileges @item mysql_tableinfo.sh -- Puts info re MySQL tables into a MySQL table @item -mysql_zap.sh -- Kill processes which match pattern +mysql_zap.sh -- Kill processes which match pattern @end itemize @*@* @@ -4635,16 +4587,15 @@ des_key_file.cc -- load DES keys from plaintext file @item field.cc -- "implement classes defined in field.h" (long) @item -field_conv.cc -- functions to copy data to or from fields +field_conv.cc -- functions to copy data between fields @item -filesort.cc -- sort file +filesort.cc -- sort a result set, using memory or temporary files @item frm_crypt.cc -- contains only one short function: get_crypt_for_frm @item -gen_lex_hash.cc -- Knuth's algorithm from Vol 3 Sorting and -Searching, Chapter 6.3 +gen_lex_hash.cc -- Knuth's algorithm from Vol 3 Sorting and Searching, Chapter 6.3 @item -gstream.cc -- GTextReadStream +gstream.cc -- GTextReadStream, used to read GIS objects @item handler.cc -- handler-calling functions @item @@ -4680,7 +4631,7 @@ item_func.cc -- Numerical functions @item item_row.cc -- Row items for comparing rows and for IN on rows @item -item_sum.cc -- Set functions (sum, avg, etc.) +item_sum.cc -- Set functions (SUM, AVG, etc.) @item item_strfunc.cc -- String functions @item @@ -4688,7 +4639,7 @@ item_subselect.cc -- Item subselect @item item_timefunc.cc -- Date/time functions, e.g. week of year @item -item_uniq.cc -- Empty file, here for compatibility reasons +item_uniq.cc -- Empty file, here for compatibility reasons @item key.cc -- Functions to handle keys and fields in forms @item @@ -4700,10 +4651,9 @@ log_event.cc -- Log event @item matherr.c -- Handling overflow, underflow, etc. @item -mf_iocache.cc -- Caching of (sequential) reads +mf_iocache.cc -- Caching of (sequential) reads and writes @item -mini_client.cc -- Client included in server for server-server -messaging +mini_client.cc -- Client included in server for server-server messaging @item mysqld.cc -- Source of mysqld.exe @item @@ -4714,58 +4664,56 @@ net_serv.cc -- Read/write of packets on a network socket nt_servc.cc -- Initialize/register/remove an NT service @item opt_ft.cc -- Create a FT or QUICK RANGE based on a key (very short) -* opt_range.cc -- Range of keys +@item +opt_range.cc -- Range of keys @item opt_sum.cc -- Optimize functions in presence of (implied) GROUP BY @item -password.c -- Password checking +password.c -- Password checking @item -procedure.cc -- Procedure +procedure.cc -- Procedure @item -protocol.cc -- Low level functions for storing data to be sent to -client +protocol.cc -- Low level functions for storing data to be sent to client @item -records.cc -- Functions to read, write, and lock records +records.cc -- Functions for easy reading of records, possible through a cache @item -repl_failsafe.cc -- Replication fail-save +repl_failsafe.cc -- Replication fail-save (not yet implemented) @item -set_var.cc -- MySQL variables +set_var.cc -- Set and retrieve MySQL user variables @item -slave.cc -- Procedures for a slave in a master/slave (replication?) -relation +slave.cc -- Procedures for a slave in a master/slave (replication) relation @item spatial.cc -- Geometry stuff (lines, points, etc.) @item -sql_acl.cc -- Functions related to ACL security +sql_acl.cc -- Functions related to ACL security @item sql_analyse.cc -- Analyse an input string (?) @item -sql_base.cc -- Basic functions needed by many modules +sql_base.cc -- Basic functions needed by many modules @item -sql_cache.cc -- SQL cache, with long comments about how caching -works +sql_cache.cc -- SQL query cache, with long comments about how caching works @item -sql_class.cc -- SQL class +sql_class.cc -- SQL class @item -sql_crypt.cc -- Encode / decode, very short +sql_crypt.cc -- Encode / decode, very short @item -sql_db.cc -- Create / drop database +sql_db.cc -- Create / drop database @item -sql_delete.cc -- The DELETE statement +sql_delete.cc -- The DELETE statement @item -sql_derived.cc -- Derived tables, with long comments +sql_derived.cc -- Derived tables, with long comments @item -sql_do.cc -- The DO statement +sql_do.cc -- The DO statement @item -sql_error.cc -- Errors and warnings +sql_error.cc -- Errors and warnings @item -sql_handler.cc -- Direct access to ISAM +sql_handler.cc -- Direct access to ISAM @item sql_help.cc -- The HELP statement (if there is one?) @item -sql_insert.cc -- The INSERT statement +sql_insert.cc -- The INSERT statement @item -sql_lex.cc -- Related to lex or yacc +sql_lex.cc -- Related to lex or yacc @item sql_list.cc -- Only list_node_end_of_list, short @item From 54100938c411f300030cce6e46f2ce512cd28cd2 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Thu, 24 Apr 2003 00:09:19 +0300 Subject: [PATCH 082/188] Put changeset number in emails --- BitKeeper/triggers/post-commit | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index 8780811a2da..d060c59ab39 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -18,13 +18,15 @@ BK_STATUS=$BK_STATUS$BK_COMMIT if [ "$BK_STATUS" = OK ] then + CHANGESET=`bk -R prs -r+ -h -d':I:' ChangeSet` + echo "Commit successful, notifying developers at $TO" ( cat < From: $FROM To: $TO -Subject: bk commit into 3.23 tree +Subject: bk commit into 3.23 tree ($CHANGESET) EOF bk changes -v -r+ @@ -36,7 +38,7 @@ EOF List-ID: From: $FROM To: $INTERNALS -Subject: bk commit into 3.23 tree +Subject: bk commit into 3.23 tree ($CHANGESET) Below is the list of changes that have just been committed into a local 3.23 repository of $USER. When $USER does a push these changes will @@ -63,7 +65,7 @@ EOF List-ID: From: $FROM To: $DOCS -Subject: bk commit - 3.23 tree (Manual) +Subject: bk commit - 3.23 tree (Manual) ($CHANGESET) EOF bk changes -v -r+ From 279a60d689b74ce11ef43c717566794e7edc6624 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Thu, 24 Apr 2003 02:23:25 +0300 Subject: [PATCH 083/188] Changed test slightly to make it repeatable (There was a problem on some AMD system when the floating point precision wasn't accurate enough) --- mysql-test/r/group_by.result | 6 ++++-- mysql-test/t/group_by.test | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 43f1bf8f6d4..94e1ce59585 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -27,6 +27,8 @@ PRIMARY KEY (userID) INSERT INTO t2 VALUES (1,'name','pass','mail','Y','v','n','adr','1','1','1'); INSERT INTO t2 VALUES (2,'name','pass','mail','Y','v','n','adr','1','1','1'); INSERT INTO t2 VALUES (3,'name','pass','mail','Y','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (4,'name','pass','mail','Y','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (5,'name','pass','mail','Y','v','n','adr','1','1','1'); SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid; userid MIN(t1.score) 1 1 @@ -47,12 +49,12 @@ userid MIN(t1.score+0.0) 2 2.0 SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; userid MIN(t1.score+0.0) -1 1.0 2 2.0 +1 1.0 EXPLAIN SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; table type possible_keys key key_len ref rows Extra t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary -t2 index PRIMARY PRIMARY 4 NULL 3 Using where; Using index +t2 eq_ref PRIMARY PRIMARY 4 t1.userID 1 Using index drop table test.t1,test.t2; CREATE TABLE t1 ( PID int(10) unsigned NOT NULL auto_increment, diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 8c111430eea..67f4eb580a6 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -34,6 +34,8 @@ CREATE TABLE t2 ( INSERT INTO t2 VALUES (1,'name','pass','mail','Y','v','n','adr','1','1','1'); INSERT INTO t2 VALUES (2,'name','pass','mail','Y','v','n','adr','1','1','1'); INSERT INTO t2 VALUES (3,'name','pass','mail','Y','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (4,'name','pass','mail','Y','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (5,'name','pass','mail','Y','v','n','adr','1','1','1'); SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid; SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid ORDER BY NULL; From c6333c5148de47cbde40f5a5ed50424047820032 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Thu, 24 Apr 2003 09:18:53 +0300 Subject: [PATCH 084/188] Fixed bug in SET SQL_BIG_SELECTS --- mysql-test/r/select_safe.result | 28 ++++++++++++++++++++++-- mysql-test/t/select_safe.test | 36 +++++++++++++++++++++++++------ sql/set_var.cc | 2 +- sql/share/czech/errmsg.txt | 2 +- sql/share/danish/errmsg.txt | 2 +- sql/share/dutch/errmsg.txt | 2 +- sql/share/english/errmsg.txt | 2 +- sql/share/estonian/errmsg.txt | 2 +- sql/share/french/errmsg.txt | 2 +- sql/share/german/errmsg.txt | 2 +- sql/share/greek/errmsg.txt | 2 +- sql/share/hungarian/errmsg.txt | 2 +- sql/share/italian/errmsg.txt | 2 +- sql/share/japanese/errmsg.txt | 2 +- sql/share/korean/errmsg.txt | 2 +- sql/share/norwegian-ny/errmsg.txt | 2 +- sql/share/norwegian/errmsg.txt | 2 +- sql/share/portuguese/errmsg.txt | 2 +- sql/share/romanian/errmsg.txt | 2 +- sql/share/russian/errmsg.txt | 2 +- sql/share/slovak/errmsg.txt | 2 +- sql/share/spanish/errmsg.txt | 2 +- sql/share/swedish/errmsg.txt | 2 +- sql/share/ukrainian/errmsg.txt | 2 +- 24 files changed, 77 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result index e225a0e3995..3303f19d9c7 100644 --- a/mysql-test/r/select_safe.result +++ b/mysql-test/r/select_safe.result @@ -1,6 +1,6 @@ drop table if exists t1; SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9; -create table t1 (a int primary key, b char(20)); +create table t1 (a int auto_increment primary key, b char(20)); insert into t1 values(1,"test"); SELECT SQL_BUFFER_RESULT * from t1; a b @@ -30,10 +30,34 @@ You are using safe update mode and you tried to update a table without a WHERE t delete from t1 where a+0=1; You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5; -The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok +The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok update t1 set b="a" limit 1; update t1 set b="a" where b="b" limit 2; delete from t1 where b="test" limit 1; delete from t1 where a+0=1 limit 2; +SET MAX_JOIN_SIZE=2; +SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS; +@@max_join_size @@sql_big_selects +2 0 +insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"); +SELECT * from t1; +The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok +SET SQL_BIG_SELECTS=1; +SELECT * from t1; +a b +3 a +2 test2 +4 a +5 a +SET MAX_JOIN_SIZE=2; +SELECT * from t1; +The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok +SET MAX_JOIN_SIZE=DEFAULT; +SELECT * from t1; +a b +3 a +2 test2 +4 a +5 a drop table t1; SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT; diff --git a/mysql-test/t/select_safe.test b/mysql-test/t/select_safe.test index e76b7558997..a085cfee29d 100644 --- a/mysql-test/t/select_safe.test +++ b/mysql-test/t/select_safe.test @@ -4,7 +4,7 @@ drop table if exists t1; SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9; -create table t1 (a int primary key, b char(20)); +create table t1 (a int auto_increment primary key, b char(20)); insert into t1 values(1,"test"); SELECT SQL_BUFFER_RESULT * from t1; update t1 set b="a" where a=1; @@ -15,18 +15,40 @@ update t1 set b="a" where a=1; select 1 from t1,t1 as t2,t1 as t3,t1 as t4; # The following should give errors: -!$1175 update t1 set b="a"; -!$1175 update t1 set b="a" where b="test"; -!$1175 delete from t1; -!$1175 delete from t1 where b="test"; -!$1175 delete from t1 where a+0=1; -!$1104 select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5; +--error 1175 +update t1 set b="a"; +--error 1175 +update t1 set b="a" where b="test"; +--error 1175 +delete from t1; +--error 1175 +delete from t1 where b="test"; +--error 1175 +delete from t1 where a+0=1; +--error 1104 +select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5; # The following should be ok: update t1 set b="a" limit 1; update t1 set b="a" where b="b" limit 2; delete from t1 where b="test" limit 1; delete from t1 where a+0=1 limit 2; + +# Test SQL_BIG_SELECTS + +SET MAX_JOIN_SIZE=2; +SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS; +insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"); +--error 1104 +SELECT * from t1; +SET SQL_BIG_SELECTS=1; +SELECT * from t1; +SET MAX_JOIN_SIZE=2; +--error 1104 +SELECT * from t1; +SET MAX_JOIN_SIZE=DEFAULT; +SELECT * from t1; + drop table t1; SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT; diff --git a/sql/set_var.cc b/sql/set_var.cc index 9ae813e1c51..172939ce981 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -239,7 +239,7 @@ static sys_var_thd_bit sys_sql_big_tables("sql_big_tables", #endif static sys_var_thd_bit sys_big_selects("sql_big_selects", set_option_bit, - OPTION_BIG_TABLES); + OPTION_BIG_SELECTS); static sys_var_thd_bit sys_log_off("sql_log_off", set_option_bit, OPTION_LOG_OFF); diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index f169d6f85f1..f5e879679cc 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -114,7 +114,7 @@ "Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu", "Nep-Bøípustné jméno databáze '%-.64s'", "Nep-Bøípustné jméno tabulky '%-.64s'", -"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET OPTION SQL_BIG_SELECTS=1", +"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1", "Nezn-Bámá chyba", "Nezn-Bámá procedura %s", "Chybn-Bý poèet parametrù procedury %s", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 06c63e47a73..13c061d50a1 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -108,7 +108,7 @@ "BLOB feltet '%-.64s' kan ikke have en standard værdi", "Ugyldigt database navn '%-.64s'", "Ugyldigt tabel navn '%-.64s'", -"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET OPTION SQL_BIG_SELECTS=1 hvis udtrykket er korrekt", +"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt", "Ukendt fejl", "Ukendt procedure %s", "Forkert antal parametre til proceduren %s", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 452a330b61b..45dbd663fec 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -116,7 +116,7 @@ "Blob veld '%-.64s' can geen standaardwaarde bevatten", "Databasenaam '%-.64s' is niet getoegestaan", "Niet toegestane tabelnaam '%-.64s'", -"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET OPTION SQL_BIG_SELECTS=1 als het stament in orde is.", +"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is.", "Onbekende Fout", "Onbekende procedure %s", "Foutief aantal parameters doorgegeven aan procedure %s", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 023cd7bc73e..b7910bd07b3 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -105,7 +105,7 @@ "BLOB column '%-.64s' can't have a default value", "Incorrect database name '%-.100s'", "Incorrect table name '%-.100s'", -"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok", +"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok", "Unknown error", "Unknown procedure '%-.64s'", "Incorrect parameter count to procedure '%-.64s'", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index d0a30b2f434..c1b98d12b3a 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -110,7 +110,7 @@ "BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust", "Vigane andmebaasi nimi '%-.100s'", "Vigane tabeli nimi '%-.100s'", -"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET OPTION SQL_BIG_SELECTS=1", +"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1", "Tundmatu viga", "Tundmatu protseduur '%-.64s'", "Vale parameetrite hulk protseduurile '%-.64s'", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 08aa5760d6c..242343769e6 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -105,7 +105,7 @@ "BLOB '%-.64s' ne peut avoir de valeur par défaut", "Nom de base de donnée illégal: '%-.64s'", "Nom de table illégal: '%-.64s'", -"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET OPTION SQL_BIG_SELECTS=1 si SELECT se passe bien", +"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien", "Erreur inconnue", "Procédure %s inconnue", "Mauvais nombre de paramètres pour la procedure %s", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 42e8c6f069b..10ec359abe8 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -108,7 +108,7 @@ "BLOB-Feld '%-.64s' kann keinen Vorgabewert (Default-Value) besitzen.", "Unerlaubter Datenbankname '%-.64s'.", "Unerlaubter Tabellenname '%-.64s'.", -"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen und SET OPTION SQL_BIG_SELECTS=1 verwenden, sofern SELECT ok ist.", +"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen und SET SQL_BIG_SELECTS=1 verwenden, sofern SELECT ok ist.", "Unbekannter Fehler.", "Unbekannte Procedure %-.64s.", "Falsche Parameterzahl für Procedure %-.64s.", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index c212c5b5703..11534d9e11b 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -105,7 +105,7 @@ "Ôá Blob ðåäßá '%-.64s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)", "ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'", "ËÜèïò üíïìá ðßíáêá '%-.100s'", -"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET OPTION SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü", +"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü", "ÐñïÝêõøå Üãíùóôï ëÜèïò", "Áãíùóôç äéáäéêáóßá '%-.64s'", "ËÜèïò áñéèìüò ðáñáìÝôñùí óôç äéáäéêáóßá '%-.64s'", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 5e8affe32b7..f8c5dbcc836 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -107,7 +107,7 @@ "A(z) '%-.64s' blob objektumnak nem lehet alapertelmezett erteke", "Hibas adatbazisnev: '%-.100s'", "Hibas tablanev: '%-.100s'", -"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET OPTION SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok", +"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok", "Ismeretlen hiba", "Ismeretlen eljaras: '%-.64s'", "Rossz parameter a(z) '%-.64s'eljaras szamitasanal", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 3fdea588bf3..a82b0cdf18f 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -105,7 +105,7 @@ "Il campo BLOB '%-.64s' non puo` avere un valore di default", "Nome database errato '%-.100s'", "Nome tabella errato '%-.100s'", -"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET OPTION SQL_BIG_SELECTS=1 se e` tutto a posto.", +"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto.", "Errore sconosciuto", "Procedura '%-.64s' sconosciuta", "Numero di parametri errato per la procedura '%-.64s'", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index f9c1645419d..1b04ee5c2e4 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -107,7 +107,7 @@ "BLOB column '%-.64s' can't have a default value", "»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹", "»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹", -"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok", +"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok", "Unknown error", "Unknown procedure '%-.64s'", "Incorrect parameter count to procedure '%-.64s'", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 82d5a5ecfbe..c57723f81e6 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -105,7 +105,7 @@ "BLOB Ä®·³ '%-.64s' ´Â µðÆúÆ® °ªÀ» °¡Áú ¼ö ¾ø½À´Ï´Ù.", "'%-.100s' µ¥ÀÌŸº£À̽ºÀÇ À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.", "'%-.100s' Å×À̺í À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.", -"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET OPTION SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.", +"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.", "¾Ë¼ö ¾ø´Â ¿¡·¯ÀÔ´Ï´Ù.", "¾Ë¼ö ¾ø´Â ¼öÇ๮ : '%-.64s'", "'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆÄ¶ó¸ÞÅÍ", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index a218d5873b0..e331854ff68 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -107,7 +107,7 @@ "Blob feltet '%-.64s' kan ikkje ha ein standard verdi", "Ugyldig database namn '%-.64s'", "Ugyldig tabell namn '%-.64s'", -"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt", +"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt", "Ukjend feil", "Ukjend prosedyre %s", "Feil parameter tal til prosedyra %s", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 9ed50b4a00b..817eec3058d 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -107,7 +107,7 @@ "Blob feltet '%-.64s' kan ikke ha en standard verdi", "Ugyldig database navn '%-.64s'", "Ugyldig tabell navn '%-.64s'", -"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt", +"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt", "Ukjent feil", "Ukjent prosedyre %s", "Feil parameter antall til prosedyren %s", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 0badf76c13d..ea4f85f6b03 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -105,7 +105,7 @@ "Coluna BLOB '%-.64s' não pode ter um valor padrão (default)", "Nome de banco de dados '%-.100s' incorreto", "Nome de tabela '%-.100s' incorreto", -"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET OPTION SQL_BIG_SELECTS=1, se o SELECT estiver correto", +"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET SQL_BIG_SELECTS=1, se o SELECT estiver correto", "Erro desconhecido", "'Procedure' '%-.64s' desconhecida", "Número de parâmetros incorreto para a 'procedure' '%-.64s'", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 1b036481538..7fc0c182f6a 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -109,7 +109,7 @@ "Coloana BLOB '%-.64s' nu poate avea o valoare default", "Numele bazei de date este incorect '%-.100s'", "Numele tabelei este incorect '%-.100s'", -"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET OPTION SQL_BIG_SELECTS=1 daca SELECT-ul e ok", +"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET SQL_BIG_SELECTS=1 daca SELECT-ul e ok", "Eroare unknown", "Procedura unknown '%-.64s'", "Procedura '%-.64s' are un numar incorect de parametri", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 8858090e8db..fc090205041 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -107,7 +107,7 @@ "îÅ×ÏÚÍÏÖÎÏ ÕËÁÚÙ×ÁÔØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ ÓÔÏÌÂÃÁ BLOB '%-.64s'", "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ '%-.100s'", "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÔÁÂÌÉÃÙ '%-.100s'", -"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET OPTION SQL_BIG_SELECTS=1", +"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET SQL_BIG_SELECTS=1", "îÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ", "îÅÉÚ×ÅÓÔÎÁÑ ÐÒÏÃÅÄÕÒÁ '%-.64s'", "îÅËÏÒÒÅËÔÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 6424dcec6ee..89a000db554 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -113,7 +113,7 @@ "Pole BLOB '%-.64s' nemô¾e ma» implicitnú hodnotu", "Neprípustné meno databázy '%-.100s'", "Neprípustné meno tabuµky '%-.100s'", -"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET OPTION SQL_BIG_SELECTS=1", +"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET SQL_BIG_SELECTS=1", "Neznámá chyba", "Neznámá procedúra '%-.64s'", "Chybný poèet parametrov procedúry '%-.64s'", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index df95a02a7aa..d566642f1c9 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -106,7 +106,7 @@ "Campo Blob '%-.64s' no puede tener valores patron", "Nombre de base de datos ilegal '%-.64s'", "Nombre de tabla ilegal '%-.64s'", -"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET OPTION SQL_BIG_SELECTS=1 si el SELECT esta correcto", +"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET SQL_BIG_SELECTS=1 si el SELECT esta correcto", "Error desconocido", "Procedimiento desconocido %s", "Equivocado parametro count para procedimiento %s", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index f7da6516600..7ef663839c9 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -105,7 +105,7 @@ "BLOB fält '%-.64s' kan inte ha ett DEFAULT-värde", "Felaktigt databasnamn '%-.64s'", "Felaktigt tabellnamn '%-.64s'", -"Den angivna frågan skulle troligen ta mycket lång tid! Kontrollera din WHERE och använd SET OPTION SQL_BIG_SELECTS=1 ifall du vill hantera stora joins", +"Den angivna frågan skulle läsa mer än MAX_JOIN_SIZE rader. Kontrollera din WHERE och använd SET SQL_BIG_SELECTS=1 eller SET MAX_JOIN_SIZE=# ifall du vill hantera stora joins", "Oidentifierat fel", "Okänd procedur: %s", "Felaktigt antal parametrar till procedur %s", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index c1d98e83f7d..a0a4a274d4b 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -110,7 +110,7 @@ "óÔÏ×ÂÅÃØ BLOB '%-.64s' ÎÅ ÍÏÖÅ ÍÁÔÉ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ", "îÅצÒÎÅ ¦Í'Ñ ÂÁÚÉ ÄÁÎÎÉÈ '%-.100s'", "îÅצÒÎÅ ¦Í'Ñ ÔÁÂÌÉæ '%-.100s'", -"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET OPTION SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ", +"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ", "îÅצÄÏÍÁ ÐÏÍÉÌËÁ", "îÅצÄÏÍÁ ÐÒÏÃÅÄÕÒÁ '%-.64s'", "èÉÂÎÁ Ë¦ÌØË¦ÓÔØ ÐÁÒÁÍÅÔÒ¦× ÐÒÏÃÅÄÕÒÉ '%-.64s'", From 9a297329681e733e1db20fb52b67fa45c81dcc22 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 24 Apr 2003 15:34:43 +0300 Subject: [PATCH 085/188] ha_innodb.h, ha_innodb.cc: Make ANALYZE TABLE to update index cardinality and other statistics also for an InnoDB table; note that the estimates are based on 10 random dives, not on an exhaustive read of the table --- sql/ha_innodb.cc | 17 +++++++++++++++++ sql/ha_innodb.h | 1 + 2 files changed, 18 insertions(+) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 5cd8a285d0c..8d682deb583 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3756,6 +3756,23 @@ ha_innobase::info( DBUG_VOID_RETURN; } +/************************************************************************** +Updates index cardinalities of the table, based on 10 random dives into +each index tree. This does NOT calculate exact statistics of the table. */ + +int +ha_innobase::analyze( +/*=================*/ + /* out: returns always 0 (success) */ + THD* thd, /* in: connection thread handle */ + HA_CHECK_OPT* check_opt) /* in: currently ignored */ +{ + /* Simply call ::info() with all the flags */ + info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + + return(0); +} + /*********************************************************************** Tries to check that an InnoDB table is not corrupted. If corruption is noticed, prints to stderr information about it. In case of corruption diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index d79f12c7ac2..5677d22a2ca 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -152,6 +152,7 @@ class ha_innobase: public handler void position(const byte *record); void info(uint); + int analyze(THD* thd,HA_CHECK_OPT* check_opt); int extra(enum ha_extra_function operation); int reset(void); int external_lock(THD *thd, int lock_type); From 3866d3805727475df58a43e8b7acf9378f495471 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 24 Apr 2003 21:51:00 +0300 Subject: [PATCH 086/188] srv0srv.c: Make buffer pool flush batches bigger as that may save some time if fsync is very inefficient --- innobase/srv/srv0srv.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index ccb3755b252..f360cf25900 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -2780,9 +2780,6 @@ loop: mutex_exit(&kernel_mutex); - /* We run purge and a batch of ibuf_contract every 10 seconds, even - if the server were active: */ - for (i = 0; i < 10; i++) { n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; @@ -2867,7 +2864,7 @@ loop: if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) { srv_main_thread_op_info = (char*) "flushing buffer pool pages"; - buf_flush_batch(BUF_FLUSH_LIST, 50, ut_dulint_max); + buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); srv_main_thread_op_info = (char*) "flushing log"; log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); @@ -2926,7 +2923,13 @@ background_loop: /* Flush a few oldest pages to make the checkpoint younger */ - n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, ut_dulint_max); + if (srv_fast_shutdown && srv_shutdown_state > 0) { + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, + ut_dulint_max); + } else { + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, + ut_dulint_max); + } srv_main_thread_op_info = (char*)"making checkpoint"; @@ -2993,7 +2996,8 @@ background_loop: } mutex_exit(&kernel_mutex); - srv_main_thread_op_info = (char*) "waiting for buffer pool flush to end"; + srv_main_thread_op_info = + (char*) "waiting for buffer pool flush to end"; buf_flush_wait_batch_end(BUF_FLUSH_LIST); srv_main_thread_op_info = (char*)"making checkpoint"; From 8a1eeca9be5b71a39e324e414e8a47e889528fce Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 24 Apr 2003 23:03:00 +0300 Subject: [PATCH 087/188] srv0srv.c: Make sure we do not do insert buffer merge in fast shutdown even if there is some buglet which increments srv_activity_counter during a shutdown --- innobase/srv/srv0srv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index f360cf25900..d90b818ad4b 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -2802,6 +2802,11 @@ loop: goto suspend_thread; } + if (srv_fast_shutdown && srv_shutdown_state > 0) { + + goto background_loop; + } + /* We flush the log once in a second even if no commit is issued or the we have specified in my.cnf no flush at transaction commit */ @@ -2829,11 +2834,6 @@ loop: log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); log_flush_to_disk(); } - - if (srv_fast_shutdown && srv_shutdown_state > 0) { - - goto background_loop; - } if (srv_activity_count == old_activity_count) { From a4281f59ed78dc9c1c0a725f0d9481e44f681b2f Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 24 Apr 2003 23:24:11 +0300 Subject: [PATCH 088/188] ha_innodb.cc: When FLUSH LOGS is called, flush InnoDB logs to disk also in the case innodb_flush_log_at_trx_commit=0 --- sql/ha_innodb.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 8d682deb583..1363227605e 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -873,6 +873,7 @@ innobase_flush_logs(void) DBUG_ENTER("innobase_flush_logs"); log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + log_flush_to_disk(); DBUG_RETURN(result); } From 80a3c64d9322240cfb39fd39949a5442c354da8c Mon Sep 17 00:00:00 2001 From: "greg@mysql.com" <> Date: Thu, 24 Apr 2003 18:15:52 -0400 Subject: [PATCH 089/188] Minor changes in netware directory (From Rob Lyon - Novell) --- netware/BUILD/compile-AUTOTOOLS | 6 ++++ netware/BUILD/compile-linux-tools | 5 ++- netware/BUILD/compile-netware-END | 6 ++++ netware/BUILD/compile-netware-START | 5 ++- netware/BUILD/compile-netware-all | 6 ++++ netware/BUILD/compile-netware-debug | 6 ++++ netware/BUILD/compile-netware-standard | 7 ++++ netware/BUILD/cron-build | 46 ++++++++++++++++++++++++++ netware/BUILD/crontab | 4 +++ netware/BUILD/mwasmnlm | 3 ++ netware/BUILD/mwccnlm | 3 ++ netware/BUILD/mwldnlm | 3 ++ netware/BUILD/nwbootstrap | 12 +++++-- 13 files changed, 108 insertions(+), 4 deletions(-) create mode 100755 netware/BUILD/cron-build create mode 100755 netware/BUILD/crontab diff --git a/netware/BUILD/compile-AUTOTOOLS b/netware/BUILD/compile-AUTOTOOLS index 0688ea5aaca..57213b1b3d0 100755 --- a/netware/BUILD/compile-AUTOTOOLS +++ b/netware/BUILD/compile-AUTOTOOLS @@ -1,5 +1,11 @@ #! /bin/sh +# debug +#set -x + +# stop on errors +set -e + for package in . ./innobase do (cd $package diff --git a/netware/BUILD/compile-linux-tools b/netware/BUILD/compile-linux-tools index 598be96ab66..3590a900338 100755 --- a/netware/BUILD/compile-linux-tools +++ b/netware/BUILD/compile-linux-tools @@ -1,8 +1,11 @@ #! /bin/sh -#debug +# debug #set -x +# stop on errors +set -e + if test ! -r ./sql/mysqld.cc then echo "you must start from the top source directory" diff --git a/netware/BUILD/compile-netware-END b/netware/BUILD/compile-netware-END index beb15fbeda3..e0097484500 100755 --- a/netware/BUILD/compile-netware-END +++ b/netware/BUILD/compile-netware-END @@ -1,5 +1,11 @@ #! /bin/sh +# debug +#set -x + +# stop on errors +set -e + path=`dirname $0` # clean diff --git a/netware/BUILD/compile-netware-START b/netware/BUILD/compile-netware-START index 2941d8868e4..7eef192a907 100755 --- a/netware/BUILD/compile-netware-START +++ b/netware/BUILD/compile-netware-START @@ -1,8 +1,11 @@ #! /bin/sh -#debug +# debug #set -x +# stop on errors +set -e + if test ! -r ./sql/mysqld.cc then echo "you must start from the top source directory" diff --git a/netware/BUILD/compile-netware-all b/netware/BUILD/compile-netware-all index f8dea0f7583..35d275f3b42 100755 --- a/netware/BUILD/compile-netware-all +++ b/netware/BUILD/compile-netware-all @@ -1,5 +1,11 @@ #! /bin/sh +# debug +#set -x + +# stop on errors +set -e + path=`dirname $0` $path/compile-netware-standard diff --git a/netware/BUILD/compile-netware-debug b/netware/BUILD/compile-netware-debug index 2cd292c82fd..e44d64e3074 100755 --- a/netware/BUILD/compile-netware-debug +++ b/netware/BUILD/compile-netware-debug @@ -1,5 +1,11 @@ #! /bin/sh +# debug +#set -x + +# stop on errors +set -e + path=`dirname $0` . $path/compile-netware-START diff --git a/netware/BUILD/compile-netware-standard b/netware/BUILD/compile-netware-standard index c09337b5fe0..12cae1f024e 100755 --- a/netware/BUILD/compile-netware-standard +++ b/netware/BUILD/compile-netware-standard @@ -1,5 +1,12 @@ #! /bin/sh +# debug +#set -x + +# stop on errors +set -e + + path=`dirname $0` . $path/compile-netware-START diff --git a/netware/BUILD/cron-build b/netware/BUILD/cron-build new file mode 100755 index 00000000000..26ccde28e2a --- /dev/null +++ b/netware/BUILD/cron-build @@ -0,0 +1,46 @@ +#! /bin/sh + +# debug +#set -x + +# stop on errors +set -e + +# repository direcotry +repo_dir=`pwd` + +# show usage +show_usage() +{ + cat << EOF + +usage: cron-patch + +EOF + exit 0; +} + +echo "starting build..." + +# check for bk and repo_dir +bk help > /dev/null +repo_dir=`bk root $repo_dir` +cd $repo_dir + +# pull latest code +echo 'y' | bk pull + +# determine version +version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"` +echo "version: $version" + +# latest revision +rev=`bk changes -e -n -d':REV:' | head -1` +echo "latest revision: $rev" + +# run bootstrap +./netware/BUILD/nwbootstrap --revision=$rev --suffix=$rev --build=all + +echo "done" + + diff --git a/netware/BUILD/crontab b/netware/BUILD/crontab new file mode 100755 index 00000000000..0097f8acaaf --- /dev/null +++ b/netware/BUILD/crontab @@ -0,0 +1,4 @@ +00 23 * * * (export PATH='/usr/local/bin:/usr/bin:/bin'; export DISPLAY=':0'; cd ~/bk/mysqldoc; echo 'y' | bk pull) +00 00 * * * (export PATH='/usr/local/bin:/usr/bin:/bin'; export DISPLAY=':0'; cd ~/bk/mysql-4.0; ./netware/BUILD/cron-build) +00 04 * * * (export PATH='/usr/local/bin:/usr/bin:/bin'; export DISPLAY=':0'; cd ~/bk/mysql-4.1; ./netware/BUILD/cron-build) + diff --git a/netware/BUILD/mwasmnlm b/netware/BUILD/mwasmnlm index c3501112aa5..381f84ec0c8 100755 --- a/netware/BUILD/mwasmnlm +++ b/netware/BUILD/mwasmnlm @@ -1,5 +1,8 @@ #! /bin/sh +# stop on errors +set -e + args=" $*" wine --debugmsg -all -- mwasmnlm $args diff --git a/netware/BUILD/mwccnlm b/netware/BUILD/mwccnlm index 9e989485bd9..cb2d62fe8cf 100755 --- a/netware/BUILD/mwccnlm +++ b/netware/BUILD/mwccnlm @@ -1,5 +1,8 @@ #! /bin/sh +# stop on errors +set -e + # mwccnlm is having a hard time understanding "-I./../include" # convert it to "-I../include" args=" "`echo $* | sed -e 's/-I.\/../-I../g'` diff --git a/netware/BUILD/mwldnlm b/netware/BUILD/mwldnlm index 7ad2872ccbb..28566fc5cb1 100755 --- a/netware/BUILD/mwldnlm +++ b/netware/BUILD/mwldnlm @@ -1,5 +1,8 @@ #! /bin/sh +# stop on errors +set -e + args=" $*" wine --debugmsg -all -- mwldnlm $args diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap index 002e19c8e49..5d068e4e4de 100755 --- a/netware/BUILD/nwbootstrap +++ b/netware/BUILD/nwbootstrap @@ -3,11 +3,11 @@ # debug #set -x -path=`dirname $0` - # stop on errors set -e +path=`dirname $0` + # repository direcotry repo_dir=`pwd` @@ -24,6 +24,7 @@ temp_dir="" revision="" rev="" build="" +suffix="" mwenv="" # show usage @@ -81,6 +82,7 @@ for arg do --wine-build-dir=*) wine_build_dir=`echo "$arg" | sed -e "s;--wine-build-dir=;;"` ;; --revision=*) revision=`echo "$arg" | sed -e "s;--revision=;;"` ;; --build=*) build=`echo "$arg" | sed -e "s;--build=;;"` ;; + --suffix=*) suffix=`echo "$arg" | sed -e "s;--suffix=;;"` ;; --doc-dir=*) doc_dir=`echo "$arg" | sed -e "s;--doc-dir=;;"` ;; *) show_usage ;; esac @@ -111,6 +113,12 @@ echo "version: $version" # build target directory target_dir="$build_dir/mysql-$version" +# add suffix +if test $suffix +then + target_dir="$target_dir-$suffix" +fi + # delete any old target if test -d $target_dir.old; then rm -rf $target_dir.old; fi From 24968f1ee3479abaad6af4141986567d234d0d13 Mon Sep 17 00:00:00 2001 From: "greg@mysql.com" <> Date: Thu, 24 Apr 2003 20:48:54 -0400 Subject: [PATCH 090/188] Changes from Novell for NetWare platform --- include/my_pthread.h | 5 +++++ mysys/mf_path.c | 3 +++ mysys/my_pthread.c | 23 +++++++++++++++++++++++ sql/mini_client.cc | 2 +- sql/mysqld.cc | 8 +++----- sql/slave.cc | 4 ---- sql/sql_load.cc | 2 +- 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 0b41dc18fe1..4247b951d82 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -247,6 +247,11 @@ extern int my_sigwait(const sigset_t *set,int *sig); #error Requires at least rev 2 of EMX pthreads library. #endif +#ifdef __NETWARE__ +void my_pthread_exit(void *status); +#define pthread_exit(A) my_pthread_exit(A) +#endif + extern int my_pthread_getprio(pthread_t thread_id); #define pthread_key(T,V) pthread_key_t V diff --git a/mysys/mf_path.c b/mysys/mf_path.c index 23eadd2acce..1ecd5fbb2b1 100644 --- a/mysys/mf_path.c +++ b/mysys/mf_path.c @@ -77,6 +77,9 @@ my_string my_path(my_string to, const char *progname, #define F_OK 0 #define PATH_SEP ';' #define PROGRAM_EXTENSION ".exe" +#elif defined(__NETWARE__) +#define PATH_SEP ';' +#define PROGRAM_EXTENSION ".nlm" #else #define PATH_SEP ':' #endif diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 1eb15d92bc9..f88a884a1bc 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -90,6 +90,29 @@ void *my_pthread_getspecific_imp(pthread_key_t key) } #endif +#ifdef __NETWARE__ +/* +don't kill the LibC Reaper thread or the main thread +*/ +#include +void my_pthread_exit(void *status) +{ +#undef pthread_exit + NXThreadId_t tid = NXThreadGetId(); + NXContext_t ctx; + char name[PATH_MAX] = ""; + + NXThreadGetContext(tid, &ctx); + NXContextGetName(ctx, name, PATH_MAX); + + // "MYSQLD.NLM's LibC Reaper" or "MYSQLD.NLM's main thread" + // with a debug build of LibC the reaper can have different names + if (!strindex(name, "\'s")) + { + pthread_exit(status); + } +} +#endif /* Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7 (and DEC OSF/1 3.2 too) */ diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 38b3c22b91b..6489685c923 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -243,7 +243,7 @@ static void mc_free_old_query(MYSQL *mysql) static int mc_sock_connect(my_socket s, const struct sockaddr *name, uint namelen, uint to) { -#if defined(__WIN__) || defined(OS2) +#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) return connect(s, (struct sockaddr*) name, namelen); #else int flags, res, s_err; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3910bfc880b..5529408c8d7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -797,9 +797,9 @@ static void __cdecl kill_server(int sig_ptr) #ifdef __NETWARE__ pthread_join(select_thread, NULL); // wait for main thread -#else - pthread_exit(0); /* purecov: deadcode */ #endif /* __NETWARE__ */ + + pthread_exit(0); /* purecov: deadcode */ RETURN_FROM_KILL_SERVER; } @@ -856,13 +856,11 @@ void unireg_end(void) { clean_up(1); my_thread_end(); -#ifndef __NETWARE__ -#ifdef SIGNALS_DONT_BREAK_READ +#if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__) exit(0); #else pthread_exit(0); // Exit is in main thread #endif -#endif /* __NETWARE__ */ } diff --git a/sql/slave.cc b/sql/slave.cc index 771317f9431..e6215356ad1 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2355,9 +2355,7 @@ err: goto slave_begin; #endif my_thread_end(); -#ifndef __NETWARE__ pthread_exit(0); -#endif /* __NETWARE__ */ DBUG_RETURN(0); // Can't return anything here } @@ -2500,9 +2498,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ goto slave_begin; #endif my_thread_end(); // clean-up before broadcasting termination -#ifndef __NETWARE__ pthread_exit(0); -#endif /* __NETWARE__ */ DBUG_RETURN(0); // Can't return anything here } diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 62ed0fc5bed..ee573672c35 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -179,7 +179,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, else { unpack_filename(name,ex->file_name); -#if !defined(__WIN__) && !defined(OS2) +#if !defined(__WIN__) && !defined(OS2) && ! defined(__NETWARE__) MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(MY_WME))) DBUG_RETURN(-1); From 8867a6c4a0902fb0fa822963ee74df39a7a93843 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 25 Apr 2003 13:02:44 +0200 Subject: [PATCH 091/188] - support-files/MacOSX/ReadMe.txt is now autogenerated from the manual instead of being an individual file to avoid redundancy --- Docs/Makefile.am | 5 +- support-files/MacOSX/Makefile.am | 3 +- support-files/MacOSX/ReadMe.txt | 79 -------------------------------- 3 files changed, 6 insertions(+), 81 deletions(-) delete mode 100644 support-files/MacOSX/ReadMe.txt diff --git a/Docs/Makefile.am b/Docs/Makefile.am index af771a5728d..00eb936c408 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -27,7 +27,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \ all: $(targets) txt_files txt_files: ../INSTALL-SOURCE ../COPYING ../COPYING.LIB \ - INSTALL-BINARY + INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt CLEAN_FILES: $(BUILD_SOURCES) touch $(BUILD_SOURCES) @@ -254,5 +254,8 @@ INSTALL-BINARY: mysql.info $(GT) ../COPYING.LIB: mysql.info $(GT) perl -w $(GT) mysql.info "LGPL license" "Function Index" > $@ +../support-files/MacOSX/ReadMe.txt: mysql.info $(GT) + perl -w $(GT) mysql.info "Mac OS X installation" "Netware installation" > $@ + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/support-files/MacOSX/Makefile.am b/support-files/MacOSX/Makefile.am index d030ff39d84..b8047942190 100644 --- a/support-files/MacOSX/Makefile.am +++ b/support-files/MacOSX/Makefile.am @@ -34,7 +34,8 @@ CLEANFILES = Info.plist \ Description.plist \ StartupParameters.plist \ postinstall \ - preinstall + preinstall \ + ReadMe.txt SUFFIXES = .sh diff --git a/support-files/MacOSX/ReadMe.txt b/support-files/MacOSX/ReadMe.txt deleted file mode 100644 index 8b7b7019bd4..00000000000 --- a/support-files/MacOSX/ReadMe.txt +++ /dev/null @@ -1,79 +0,0 @@ -Installation notes for MySQL on Mac OS X - -PLEASE READ! - -For more details about installing and running -MySQL on Mac OS X, also refer to the manual, -which is available online: - -http://www.mysql.com/doc/en/Mac_OS_X_installation.html - -NOTE: Before proceeding with the installation, please -make sure that no other MySQL server is running! - -Please shut down all running MySQL instances before -continuing by either using the MySQL Manager -Application (on Mac OS X Server) or via "mysqladmin -shutdown" on the command line. - -This MySQL package will be installed into -"/usr/local/mysql-" and will also create a -symbolic link "/usr/local/mysql", pointing to the new -location. - -A previously existing /usr/local/mysql directory will -be renamed to /usr/local/mysql.bak before proceeding -with the installation. - -Additionally, it will install the mysql grant tables by -executing "mysql_install_db" after the installation. - -If you are running Mac OS X Server, you already have a -version MySQL installed. Make sure to read Apple's help -about installing MySQL (Run the "Help View" application, -select "Mac OS X Server help", and do a search for MySQL -and read the item entitled "Installing MySQL"). - -If you previously used Marc Liyanage's MySQL packages -for MacOS X from http://www.entropy.ch, you can simply -follow the update instructions given on his pages. - -After the installation (and restoring the old database -files, if necessary), you can start up MySQL by running -the following commands in a terminal window: - - cd /usr/local/mysql - sudo ./bin/mysqld_safe - (Enter your password) - (Press CTRL+Z) - bg - (Press CTRL+D to exit the shell) - -You should now be able to connect to the MySQL server, -e.g. by running /usr/local/mysql/bin/mysql - -If you installed MySQL for the first time, -PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER! -This is done with the following two commands: - -/usr/local/mysql/bin/mysqladmin -u root password 'new-password' - -/usr/local/mysql/bin/mysqladmin -u root -h $hostname password 'new-password' - -Please note, that after upgrading from MySQL 3.23 to -MySQL 4.0 it is recommended to convert the MySQL -privilege tables using the mysql_fix_privilege_tables -script, since some new security privileges have been -added. - -Please see -http://www.mysql.com/doc/en/Upgrading-from-3.23.html -for more information on how to upgrade from MySQL 3.23. - -If you do not want to have to type the full path -"/usr/local/mysql/bin" in front of every command, you -can to add this directory to your PATH environment -variable in your login script. For the default shell -"tcsh", you can do this by running this command once: - -echo 'setenv PATH ${PATH}:/usr/local/mysql/bin' >> ~/.tcshrc From 4c3f1baca99b437c071a2a2a43fd4ee1f36d2afe Mon Sep 17 00:00:00 2001 From: "bar@bar.mysql.r18.ru" <> Date: Fri, 25 Apr 2003 16:27:16 +0500 Subject: [PATCH 092/188] ctype-tis620.c: Don't allow access outside the string --- strings/ctype-tis620.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index d5181dc4db0..7628b425b65 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -492,7 +492,7 @@ static uchar* thai2sortable(const uchar * tstr,uint len) } pLeft4 = pRight4;*/ while(len--) { - if(isldvowel(*p) && isconsnt(p[1])) { + if(isldvowel(*p) && len > 0 && isconsnt(p[1])) { *pRight1++ = t_ctype[p[1]][0]; *pRight2++ = t_ctype[p[1]][1]; *pRight3++ = t_ctype[p[1]][2]; From 3d19d37c46fb6688cc48a448e72a47162d505ca7 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 25 Apr 2003 14:42:01 +0200 Subject: [PATCH 093/188] - Updated innodb test results on Heikki's request (InnoDB now supports ANALYZE TABLE) --- .bzrignore | 1 + mysql-test/r/innodb.result | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.bzrignore b/.bzrignore index f497aa69ffd..5d5909ce4da 100644 --- a/.bzrignore +++ b/.bzrignore @@ -530,3 +530,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +support-files/MacOSX/ReadMe.txt diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 293519604dd..5049dec9ef1 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -208,7 +208,7 @@ create index skr on t1 (a); insert into t1 values (3,""), (4,"testing"); analyze table t1; Table Op Msg_type Msg_text -test.t1 analyze error The handler for the table doesn't support analyze +test.t1 analyze status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 1 skr 1 a A 3 NULL NULL YES BTREE @@ -1227,10 +1227,10 @@ count(*) 29267 explain select a from t1 where a between 1 and 10000; table type possible_keys key key_len ref rows Extra -t1 range PRIMARY PRIMARY 4 NULL 14790 Using where; Using index +t1 range PRIMARY PRIMARY 4 NULL 14745 Using where; Using index explain select * from t1 where a between 1 and 10000; table type possible_keys key key_len ref rows Extra -t1 range PRIMARY PRIMARY 4 NULL 14790 Using where +t1 range PRIMARY PRIMARY 4 NULL 14745 Using where explain select * from t1 where c between 1 and 10000; table type possible_keys key key_len ref rows Extra t1 range c c 5 NULL 1 Using where From aad71de100a673aad7037fe730e7b22e9c829a91 Mon Sep 17 00:00:00 2001 From: "hf@deer.mysql.r18.ru" <> Date: Fri, 25 Apr 2003 21:28:11 +0500 Subject: [PATCH 094/188] Trimming code with Monty's suggestions --- strings/ctype-tis620.c | 172 ++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 90 deletions(-) diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 7628b425b65..885d4406cd6 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -453,82 +453,78 @@ uchar NEAR sort_order_tis620[]= Arg: const source string and length of converted string Ret: Sortable string */ - +/* + NOTE: isn't it faster to alloc buffer in calling function? + */ static uchar* thai2sortable(const uchar * tstr,uint len) { /* We use only 3 levels (neglect capitalization). */ - const uchar* p = tstr; + const uchar* p= tstr; uchar *outBuf; -/* uchar *pRight1, *pRight2, *pRight3, *pRight4; */ -/* uchar *pLeft1, *pLeft2, *pLeft3, *pLeft4; */ uchar *pRight1, *pRight2, *pRight3; uchar *pLeft1, *pLeft2, *pLeft3; uint bufSize; + uint RightSize; - len = (uint) strnlen((char*) tstr,len); - bufSize = (uint) buffsize((char*) tstr); - if(!(pRight1 = (uchar *)malloc(sizeof(uchar) * bufSize))) { - return( (uchar*) tstr); - } - pLeft1 = pRight1; - outBuf = pRight1; - if(!(pRight2 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) { - free(pRight1); - return((uchar*) tstr); - } - pLeft2 = pRight2; - if(!(pRight3 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) { - free(pRight1); - free(pRight2); - return((uchar*) tstr); - } - pLeft3 = pRight3; -/* if(!(pRight4 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) { - free(pRight1); - free(pRight2); - free(pRight3); - return((uchar*) tstr); - } - pLeft4 = pRight4;*/ - while(len--) { - if(isldvowel(*p) && len > 0 && isconsnt(p[1])) { - *pRight1++ = t_ctype[p[1]][0]; - *pRight2++ = t_ctype[p[1]][1]; - *pRight3++ = t_ctype[p[1]][2]; -/* *pRight4++ = t_ctype[p[1]][3]; */ - *pRight1++ = t_ctype[*p][0]; - *pRight2++ = t_ctype[*p][1]; - *pRight3++ = t_ctype[*p][2]; -/* *pRight4++ = t_ctype[*p][3]; */ + len= (uint) strnlen((char*) tstr,len); + bufSize= (uint) buffsize((char*) tstr); + RightSize= sizeof(uchar) * (len + 1); + if (!(outBuf= pLeft1= pRight1= + (uchar *)malloc(sizeof(uchar) * bufSize + RightSize*2))) + return (uchar*) tstr; + pLeft2= pRight2= pRight1 + sizeof(uchar) * bufSize; + pLeft3= pRight3= pRight2 + RightSize; + + while (--len) + { + int *t_ctype0= t_ctype[p[0]]; + if (isldvowel(*p) && isconsnt(p[1])) + { + int *t_ctype1= t_ctype[p[1]]; + *pRight1++= t_ctype1[0]; + *pRight2++= t_ctype1[1]; + *pRight3++= t_ctype1[2]; + *pRight1++= t_ctype0[0]; + *pRight2++= t_ctype0[1]; + *pRight3++= t_ctype0[2]; + p+= 2; len--; - p += 2; - } else { - *pRight1 = t_ctype[*p][0]; - if(*pRight1 != IGNORE) pRight1++; - *pRight2 = t_ctype[*p][1]; - if(*pRight2 != IGNORE) pRight2++; - *pRight3 = t_ctype[*p][2]; - if(*pRight3 != IGNORE) pRight3++; -/* *pRight4 = t_ctype[*p][3]; - if(*pRight4 != IGNORE) pRight4++;*/ + } + else + { + *pRight1= t_ctype0[0]; + if(*pRight1 != IGNORE) + pRight1++; + *pRight2= t_ctype0[1]; + if (*pRight2 != IGNORE) + pRight2++; + *pRight3= t_ctype0[2]; + if(*pRight3 != IGNORE) + pRight3++; p++; } } - *pRight1++ = L2_BLANK; - *pRight2++ = L3_BLANK; -/* *pRight3++ = L4_BLANK; */ - *pRight3++ = '\0'; -/* *pRight4++ = '\0'; */ + if (!len) + { + int *t_ctype0= t_ctype[p[0]]; + *pRight1= t_ctype0[0]; + if (*pRight1 != IGNORE) + pRight1++; + *pRight2= t_ctype0[1]; + if (*pRight2 != IGNORE) + pRight2++; + *pRight3= t_ctype0[2]; + if (*pRight3 != IGNORE) + pRight3++; + } + *pRight1++= L2_BLANK; + *pRight2++= L3_BLANK; + *pRight3++= '\0'; memcpy(pRight1, pLeft2, pRight2 - pLeft2); - pRight1 += pRight2 - pLeft2; + pRight1+= pRight2 - pLeft2; memcpy(pRight1, pLeft3, pRight3 - pLeft3); -/* pRight1 += pRight3 - pLeft3; */ -/* memcpy(pRight1, pLeft4, pRight4 - pLeft4); */ - free(pLeft2); - free(pLeft3); -/* free(pLeft4); */ - return(outBuf); + return outBuf; } /* strncoll() replacement, compare 2 string, both are conveted to sortable string @@ -539,12 +535,12 @@ int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2) { uchar *tc1, *tc2; int i; - tc1 = thai2sortable(s1, len1); - tc2 = thai2sortable(s2, len2); - i = strcmp((char*)tc1, (char*)tc2); + tc1= thai2sortable(s1, len1); + tc2= thai2sortable(s2, len2); + i= strcmp((char*)tc1, (char*)tc2); free(tc1); free(tc2); - return(i); + return i; } /* strnxfrm replacment, convert Thai string to sortable string @@ -555,12 +551,12 @@ int my_strnxfrm_tis620(uchar * dest, const uchar * src, int len, int srclen) { uint bufSize; uchar *tmp; - bufSize = (uint) buffsize((char*)src); - tmp = thai2sortable(src,srclen); + bufSize= (uint) buffsize((char*)src); + tmp= thai2sortable(src,srclen); set_if_smaller(bufSize,(uint) len); memcpy((uchar *)dest, tmp, bufSize); free(tmp); - return (int) bufSize; + return (int)bufSize; } /* strcoll replacment, compare 2 strings @@ -571,12 +567,12 @@ int my_strcoll_tis620(const uchar * s1, const uchar * s2) { uchar *tc1, *tc2; int i; - tc1 = thai2sortable(s1, (uint) strlen((char*)s1)); - tc2 = thai2sortable(s2, (uint) strlen((char*)s2)); - i = strcmp((char*)tc1, (char*)tc2); + tc1= thai2sortable(s1, (uint) strlen((char*)s1)); + tc2= thai2sortable(s2, (uint) strlen((char*)s2)); + i= strcmp((char*)tc1, (char*)tc2); free(tc1); free(tc2); - return(i); + return i; } /* strxfrm replacment, convert Thai string to sortable string @@ -588,9 +584,9 @@ int my_strxfrm_tis620(uchar * dest, const uchar * src, int len) uint bufSize; uchar *tmp; - bufSize = (uint) buffsize((char*) src); - tmp = thai2sortable(src, len); - memcpy((uchar *) dest, tmp, bufSize); + bufSize= (uint)buffsize((char*) src); + tmp= thai2sortable(src, len); + memcpy((uchar *)dest, tmp, bufSize); free(tmp); return bufSize; } @@ -620,7 +616,7 @@ my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape, if (*ptr == escape && ptr+1 != end) { ptr++; /* Skipp escape */ - *min_str++= *max_str++ = *ptr; + *min_str++ = *max_str++ = *ptr; continue; } if (*ptr == wild_one) /* '_' in SQL */ @@ -654,26 +650,22 @@ my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape, */ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length) { - const uchar* fr = from; - uchar* p = ptr; + const uchar* fr= from; + uchar* p= ptr; + + if (length > field_length) + length= field_length; - if(length > field_length) { - length = field_length; - } while (length--) - { - if((istone(*fr) || isdiacrt1(*fr)) && + if ((istone(*fr) || isdiacrt1(*fr)) && (islwrvowel(fr[1]) || isuprvowel(fr[1]))) { - *p = fr[1]; - p[1] = *fr; - fr += 2; - p += 2; + *p= fr[1]; + p[1]= *fr; + fr+= 2; + p+= 2; length--; } else - { *p++ = *fr++; - } - } } From 4393bab73c8a4135c6aeab198f7310d5a67cef9f Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 25 Apr 2003 21:12:44 +0300 Subject: [PATCH 095/188] ut0dbg.h: Print the failing assertion if it fails; helps to analyze bug reports --- innobase/include/ut0dbg.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h index 3407483696c..e99dc8c09d6 100644 --- a/innobase/include/ut0dbg.h +++ b/innobase/include/ut0dbg.h @@ -20,7 +20,6 @@ extern ibool ut_dbg_stop_threads; extern ulint* ut_dbg_null_ptr; - #define ut_a(EXPR)\ {\ ulint dbg_i;\ @@ -31,8 +30,10 @@ extern ulint* ut_dbg_null_ptr; " InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\ os_thread_pf(os_thread_get_curr_id()), IB__FILE__,\ (ulint)__LINE__);\ + fprintf(stderr,\ + "InnoDB: Failing assertion: " #EXPR);\ fprintf(stderr,\ - "InnoDB: We intentionally generate a memory trap.\n");\ + "\nInnoDB: We intentionally generate a memory trap.\n");\ fprintf(stderr,\ "InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n");\ ut_dbg_stop_threads = TRUE;\ From 093f661a8047b186022ad32cae48c6e808893916 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 25 Apr 2003 21:58:25 +0200 Subject: [PATCH 096/188] - Applied patch provided by Martin Mokrejs (General code cleanup, use the GRANT statement instead of updating the privilege tables directly, added option to revoke privileges) --- scripts/mysql_setpermission.sh | 233 ++++++++++++++++----------------- 1 file changed, 112 insertions(+), 121 deletions(-) diff --git a/scripts/mysql_setpermission.sh b/scripts/mysql_setpermission.sh index 43bf8a14c06..9699cd28047 100644 --- a/scripts/mysql_setpermission.sh +++ b/scripts/mysql_setpermission.sh @@ -16,20 +16,25 @@ ## 1.2 begin screen now in a loop + quit is using 0 instead of 9 ## after ideas of Paul DuBois. ## 1.2a Add Grant, References, Index and Alter privilege handling (Monty) +## 1.3 Applied patch provided by Martin Mokrejs +## (General code cleanup, use the GRANT statement instead of updating +## the privilege tables directly, added option to revoke privileges) #### TODO # # empty ... suggestions ... mail them to me ... -$version="1.2"; +$version="1.3"; use DBI; use Getopt::Long; use strict; -use vars qw($dbh $hostname $opt_user $opt_password $opt_help $opt_host +use vars qw($dbh $sth $hostname $opt_user $opt_password $opt_help $opt_host $opt_socket $opt_port $host $version); +my $sqlhost = ""; +my $user = ""; $dbh=$host=$opt_user= $opt_password= $opt_help= $opt_host= $opt_socket= ""; $opt_port=0; @@ -42,11 +47,11 @@ usage() if ($opt_help); # the help function if ($opt_host eq '') { - $hostname = "localhost"; + $sqlhost = "localhost"; } else { - $hostname = $opt_host; + $sqlhost = $opt_host; } # ask for a password if no password is set already @@ -62,7 +67,7 @@ if ($opt_password eq '') # make the connection to MySQL -$dbh= DBI->connect("DBI:mysql:mysql:host=$hostname:port=$opt_port:mysql_socket=$opt_socket",$opt_user,$opt_password, {PrintError => 0}) || +$dbh= DBI->connect("DBI:mysql:mysql:host=$sqlhost:port=$opt_port:mysql_socket=$opt_socket",$opt_user,$opt_password, {PrintError => 0}) || die("Can't make a connection to the mysql server.\n The error: $DBI::errstr"); # the start of the program @@ -86,27 +91,44 @@ sub q1 { # first question ... print "#"x70; print "\n"; print "What would you like to do:\n"; - print " 1. Set password for a user.\n"; - print " 2. Add a database + user privilege for that database.\n"; - print " - user can do all except all admin functions\n"; - print " 3. Add user privilege for an existing database.\n"; - print " - user can do all except all admin functions\n"; - print " 4. Add user privilege for an existing database.\n"; - print " - user can do all except all admin functions + no create/drop\n"; - print " 5. Add user privilege for an existing database.\n"; - print " - user can do only selects (no update/delete/insert etc.)\n"; + print " 1. Set password for an existing user.\n"; + print " 2. Create a database + user privilege for that database\n"; + print " and host combination (user can only do SELECT)\n"; + print " 3. Create/append user privilege for an existing database\n"; + print " and host combination (user can only do SELECT)\n"; + print " 4. Create/append broader user privileges for an existing\n"; + print " database and host combination\n"; + print " (user can do SELECT,INSERT,UPDATE,DELETE)\n"; + print " 5. Create/append quite extended user privileges for an\n"; + print " existing database and host combination (user can do\n"; + print " SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,\n"; + print " LOCK TABLES,CREATE TEMPORARY TABLES)\n"; + print " 6. Create/append database administrative privileges for an\n"; + print " existing database and host combination (user can do\n"; + print " SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,\n"; + print " CREATE TEMPORARY TABLES,SHOW DATABASES,PROCESS)\n"; + print " 7. Create/append full privileges for an existing database\n"; + print " and host combination (user has FULL privilege)\n"; + print " 8. Remove all privileges for for an existing database and\n"; + print " host combination.\n"; + print " (user will have all permission fields set to N)\n"; print " 0. exit this program\n"; - print "\nMake your choice [1,2,3,4,5,0]: "; + print "\nMake your choice [1,2,3,4,5,6,7,0]: "; while () { $answer = $_; chomp($answer); - if ($answer =~ /1|2|3|4|5|0/) { - &setpwd if ($answer == 1); - &addall($answer) if ($answer =~ /^[2345]$/); - if ($answer == 0) { - print "Sorry, hope we can help you next time \n\n"; + if ($answer =~ /^[12345678]$/) { + if ($answer == 1) { + setpwd(); + } elsif ($answer =~ /^[2345678]$/) { + addall($answer); + } else { + print "Sorry, something went wrong. With such option number you should not get here.\n\n"; $end = 1; } + } elsif ($answer == 0) { + print "We hope we can help you next time \n\n"; + $end = 1; } else { print "Your answer was $answer\n"; print "and that's wrong .... Try again\n"; @@ -121,7 +143,7 @@ sub q1 { # first question ... ### sub setpwd { - my ($user,$pass,$host); + my ($user,$pass,$host) = ""; print "\n\nSetting a (new) password for a user.\n"; $user = user(); @@ -168,22 +190,18 @@ sub setpwd ### # all things which will be added are done here ### -sub addall -{ +sub addall { my ($todo) = @_; my ($answer,$good,$db,$user,$pass,$host,$priv); - if ($todo == 2) - { + if ($todo == 2) { $db = newdatabase(); - } - else - { + } else { $db = database(); } $user = newuser(); - $pass = newpass(); + $pass = newpass("$user"); $host = newhosts(); print "#"x70; @@ -198,104 +216,80 @@ sub addall print "Are you pretty sure you would like to implement this [yes/no]: "; my $no = ; chomp($no); - if ($no =~ /n/i) - { + if ($no =~ /n/i) { print "Okay .. that was it then ... See ya\n\n"; return(0); - } - else - { + } else { print "Okay ... let's go then ...\n\n"; } - if ($todo == 2) - { + if ($todo == 2) { # create the database - my $sth = $dbh->do("create database $db") || $dbh->errstr; + if ($db) { + my $sth = $dbh->do("CREATE DATABASE $db") || $dbh->errstr; + } else { + print STDERR "What do you want? You wanted to create new database and add new user, right?\n"; + die "But then specify databasename, please\n"; + } } - # select the privilege .... - if (($todo == 2) || ($todo == 3)) - { - $priv = "'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'"; - } - elsif ($todo == 4) - { - $priv = "'Y','Y','Y','Y','N','N','N','Y','Y','Y'"; - } - elsif ($todo == 5) - { - $priv = "'Y','N','N','N','N','N','N','N','N','N'"; - } - else - { - print "Sorry, choice number $todo isn't known inside the program .. See ya\n"; + if ( ( !$todo ) or not ( $todo =~ m/^[2-8]$/ ) ) { + print STDERR "Sorry, select option $todo isn't known inside the program .. See ya\n"; quit(); } my @hosts = split(/,/,$host); - $user = $dbh->quote($user); - $db = $dbh->quote($db); - if ($pass eq '') - { - $pass = "''"; + if (!$user) { + die "username not specified: $user\n"; } - else - { - $pass = "PASSWORD(". $dbh->quote($pass) . ")"; + if (!$db) { + die "databasename is not specified nor *\n"; } - foreach my $key (@hosts) - { - my $key1 = $dbh->quote($key); - my $sth = $dbh->prepare("select Host,User from user where Host = $key1 and User = $user") || die $dbh->errstr; - $sth->execute || die $dbh->errstr; - my @r = $sth->fetchrow_array; - if ($r[0]) - { - print "WARNING WARNING SKIPPING CREATE FOR USER $user AND HOST $key\n"; - print "Reason: entry already exists in the user table.\n"; + foreach $host (@hosts) { + # user privileges: SELECT + if (($todo == 2) || ($todo == 3)) { + $sth = $dbh->do("GRANT SELECT ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr; + } elsif ($todo == 4) { + # user privileges: SELECT,INSERT,UPDATE,DELETE + $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr; + } elsif ($todo == 5) { + # user privileges: SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES + $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr; + } elsif ($todo == 6) { + # admin privileges: GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES,SHOW DATABASES,PROCESS + $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES,SHOW DATABASES,PROCESS ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr; + } elsif ($todo == 7) { + # all privileges + $sth = $dbh->do("GRANT ALL ON $db.* TO \'$user\'\@\'$host\' IDENTIFIED BY \'$pass\'") || die $dbh->errstr; + } elsif ($todo == 8) { + # all privileges set to N + $sth = $dbh->do("REVOKE ALL ON *.* FROM \'$user\'\@\'$host\'") || die $dbh->errstr; } - else - { - $sth = $dbh->prepare("insert into user (Host,User,Password) values($key1,$user,$pass)") || die $dbh->errstr; - $sth->execute || die $dbh->errstr; - $sth->finish; } - $sth = $dbh->prepare("INSERT INTO db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv) VALUES ($key1,$db,$user,$priv)") || die $dbh->errstr; - $sth->execute || die $dbh->errstr; - $sth->finish; - } - $dbh->do("flush privileges") || print "Can't load privileges\n"; + $dbh->do("FLUSH PRIVILEGES") || print STDERR "Can't flush privileges\n"; print "Everything is inserted and mysql privileges have been reloaded.\n\n"; } ### # ask for a new database name ### -sub newdatabase -{ +sub newdatabase { my ($answer,$good,$db); print "\n\nWhich database would you like to add: "; - while () - { + while () { $answer = $_; $good = 0; chomp($answer); - if ($answer) - { - my $sth = $dbh->prepare("show databases") || die $dbh->errstr; + if ($answer) { + my $sth = $dbh->prepare("SHOW DATABASES") || die $dbh->errstr; $sth->execute || die $dbh->errstr; - while (my @r = $sth->fetchrow_array) - { - if ($r[0] eq $answer) - { + while (my @r = $sth->fetchrow_array) { + if ($r[0] eq $answer) { print "\n\nSorry, this database name is already in use; try something else: "; $good = 1; } } - } - else - { + } else { print "You must type something ...\nTry again: "; next; } @@ -309,48 +303,44 @@ sub newdatabase ### # select a database ### -sub database -{ +sub database { my ($answer,$good,$db); - print "\n\nWhich database would you like to select: \n"; + print "\n\nWhich database from existing databases would you like to select: \n"; print "You can choose from: \n"; my $sth = $dbh->prepare("show databases") || die $dbh->errstr; $sth->execute || die $dbh->errstr; - while (my @r = $sth->fetchrow_array) - { + while (my @r = $sth->fetchrow_array) { print " - $r[0] \n"; } - print "Which database will it be (case sensitive): "; - while () - { + print "Which database will it be (case sensitive). Type * for any: \n"; + while () { $answer = $_; $good = 0; chomp($answer); - if ($answer) - { + if ($answer) { + if ($answer eq "*") { + print "OK, the user entry will NOT be limited to any database"; + return("*"); + } my $sth = $dbh->prepare("show databases") || die $dbh->errstr; $sth->execute || die $dbh->errstr; - while (my @r = $sth->fetchrow_array) - { - if ($r[0] eq $answer) - { + while (my @r = $sth->fetchrow_array) { + if ($r[0] eq $answer) { $good = 1; $db = $r[0]; last; } } - } - else - { - print "You must type something ...\nTry again: "; + } else { + print "Type either database name or * meaning any databasename. That means"; + print " any of those above but also any which will be created in future!"; + print " This option gives a user chance to operate on databse mysql, which"; + print " contains privilege settings. That is really risky!\n"; next; } - if ($good == 1) - { + if ($good == 1) { last; - } - else - { + } else { print "You must select one from the list.\nTry again: "; next; } @@ -364,7 +354,8 @@ sub database ### sub newuser { - my ($answer,$user); + my $user = ""; + my $answer = ""; print "\nWhat username is to be created: "; while() @@ -430,7 +421,7 @@ sub user sub newpass { my ($user) = @_; - my ($answer,$good,$pass,$yes); + my ($pass,$answer,$good,$yes); print "Would you like to set a password for $user [y/n]: "; $yes = ; @@ -487,7 +478,7 @@ sub newpass ### sub newhosts { - my ($answer,$good,$host); + my ($host,$answer,$good); print "We now need to know from what host(s) the user will connect.\n"; print "Keep in mind that % means 'from any host' ...\n"; From b6534b667f4dbf4f93feeadd1f528eab5b79193b Mon Sep 17 00:00:00 2001 From: "igor@hundin.mysql.fi" <> Date: Sat, 26 Apr 2003 14:54:53 +0300 Subject: [PATCH 097/188] filesort.cc, order_by.result: Fixed bug 263 order_by.test: Fixed bug 263 --- mysql-test/r/order_by.result | 25 +++++++++++++++++++++++++ mysql-test/t/order_by.test | 14 ++++++++++++++ sql/filesort.cc | 11 +++++++---- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 79c6c9fa6fb..ff2dd93311c 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -517,3 +517,28 @@ SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,des titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug drop table t1,t2; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1, 2); +INSERT INTO t1 VALUES (3, 4); +INSERT INTO t1 VALUES (5, NULL); +SELECT * FROM t1 ORDER BY b; +a b +5 NULL +1 2 +3 4 +SELECT * FROM t1 ORDER BY b DESC; +a b +3 4 +1 2 +5 NULL +SELECT * FROM t1 ORDER BY (a + b); +a b +5 NULL +1 2 +3 4 +SELECT * FROM t1 ORDER BY (a + b) DESC; +a b +3 4 +1 2 +5 NULL +DROP TABLE t1; diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 06a5d0ceb20..1fb83509ebb 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -331,3 +331,17 @@ INSERT INTO t2 (numeropost,pseudo) VALUES (1,'joce'),(1,'bug'); SELECT titre,t1.numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30; drop table t1,t2; + +# +# Test order by with NULL values +# +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1, 2); +INSERT INTO t1 VALUES (3, 4); +INSERT INTO t1 VALUES (5, NULL); +SELECT * FROM t1 ORDER BY b; +SELECT * FROM t1 ORDER BY b DESC; +SELECT * FROM t1 ORDER BY (a + b); +SELECT * FROM t1 ORDER BY (a + b) DESC; +DROP TABLE t1; + diff --git a/sql/filesort.cc b/sql/filesort.cc index 86574e4dd57..1d30c23a15e 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -456,6 +456,7 @@ static void make_sortkey(register SORTPARAM *param, sort_field != param->end ; sort_field++) { + bool maybe_null=0; if ((field=sort_field->field)) { // Field if (field->maybe_null()) @@ -480,7 +481,7 @@ static void make_sortkey(register SORTPARAM *param, switch (sort_field->result_type) { case STRING_RESULT: { - if (item->maybe_null) + if ((maybe_null=item->maybe_null)) *to++=1; /* All item->str() to use some extra byte for end null.. */ String tmp((char*) to,sort_field->length+4); @@ -546,7 +547,7 @@ static void make_sortkey(register SORTPARAM *param, case INT_RESULT: { longlong value=item->val_int(); - if (item->maybe_null) + if ((maybe_null=item->maybe_null)) *to++=1; /* purecov: inspected */ if (item->null_value) { @@ -580,13 +581,13 @@ static void make_sortkey(register SORTPARAM *param, case REAL_RESULT: { double value=item->val(); - if (item->null_value) + if ((maybe_null=item->null_value)) { bzero((char*) to,sort_field->length+1); to++; break; } - if (item->maybe_null) + if ((maybe_null=item->maybe_null)) *to++=1; change_double_for_sort(value,(byte*) to); break; @@ -595,6 +596,8 @@ static void make_sortkey(register SORTPARAM *param, } if (sort_field->reverse) { /* Revers key */ + if (maybe_null) + to[-1]= ~to[-1]; length=sort_field->length; while (length--) { From ed1b48185a23ce4ffee8b032cfd99fcfa34e3a82 Mon Sep 17 00:00:00 2001 From: "bell@laptop.sanja.is.com.ua" <> Date: Sat, 26 Apr 2003 15:53:27 +0300 Subject: [PATCH 098/188] fixed incorrect number of affected rows in REPLACE...SELECT... (bug 130) --- BitKeeper/etc/logging_ok | 1 + sql/sql_insert.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 2112a7c8dce..aca77159202 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -11,6 +11,7 @@ arjen@fred.bitbike.com arjen@george.bitbike.com bar@bar.mysql.r18.ru bar@bar.udmsearch.izhnet.ru +bell@laptop.sanja.is.com.ua bell@sanja.is.com.ua bk@admin.bk davida@isil.mysql.com diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ace15771449..0e7a487276d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1392,7 +1392,7 @@ bool select_insert::send_eof() thd->cuted_fields); if (last_insert_id) thd->insert_id(last_insert_id); // For update log - ::send_ok(&thd->net,info.copied,last_insert_id,buff); + ::send_ok(&thd->net,info.copied+info.deleted,last_insert_id,buff); mysql_update_log.write(thd,thd->query,thd->query_length); return 0; } From 7499f9a55fdfe11df2e2ab9c1afedad6b5756850 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Sat, 26 Apr 2003 16:03:33 +0300 Subject: [PATCH 099/188] code clean-up --- strings/ctype-tis620.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 6dd3641381a..5fab4f86ff2 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -501,8 +501,6 @@ static uchar* thai2sortable(const uchar * tstr,uint len) *pRight2++ = t_ctype[*p][1]; *pRight3++ = t_ctype[*p][2]; /* *pRight4++ = t_ctype[*p][3]; */ - if (!(len--)) - break; p += 2; } else { *pRight1 = t_ctype[*p][0]; From f88097eee92ac4efbcc38e325f751a60677dab6f Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Sat, 26 Apr 2003 17:57:19 +0300 Subject: [PATCH 100/188] Fix possible memory overrun when reading broken character set files --- mysys/charset.c | 2 +- sql/mysqld.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/charset.c b/mysys/charset.c index 9d9ede2b0c4..4cd32e7e3da 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -85,7 +85,7 @@ static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf) endptr = fb->buf; } - while (!isspace(*endptr)) + while (*endptr && !isspace(*endptr)) *buf++= *endptr++; *buf=0; fb->p = endptr; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a10ad60a3e7..4e88a6fcb32 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -785,7 +785,7 @@ void clean_up(bool print_message) if (!opt_bootstrap) (void) my_delete(pidfile_name,MYF(0)); // This may not always exist #endif - if (print_message) + if (print_message && errmesg) sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname); x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */ my_thread_end(); From bf6cfd2948f4cbab120a76aaf16d7ca0739cf2f4 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Sat, 26 Apr 2003 20:43:28 +0300 Subject: [PATCH 101/188] Fix for -fbranch-probabilites (bug 268) Fix for LEFT/RIGHT/MID with multi-byte-character sets (bug 314) Fix for new bison 1.875 max_insert_delayed_threads and delayed_insert_timeout now works as documented (bug 211) Don't show port in SHOW PROCESSLIST for system threads Fix problem with ORDER BY being discarded for some DISTINCT queries (bug 275) Fixed bug with NATURAL LEFT JOIN, NATURAL RIGHT JOIN and RIGHT JOIN when using many joined tables (Bug 212) --- acinclude.m4 | 2 +- configure.in | 6 +-- myisam/mi_open.c | 7 ++- mysql-test/r/ctype_ujis.result | 8 +++ mysql-test/r/join.result | 87 ++++++++++++++++++++++++++++++ mysql-test/r/join_outer.result | 7 +-- mysql-test/r/select.result | 12 ----- mysql-test/t/ctype_ujis-master.opt | 1 + mysql-test/t/ctype_ujis.test | 13 +++++ mysql-test/t/join.test | 32 +++++++++++ sql/item_strfunc.cc | 4 +- sql/mysqld.cc | 4 +- sql/sql_class.cc | 1 + sql/sql_insert.cc | 5 +- sql/sql_parse.cc | 23 ++++++-- sql/sql_select.cc | 10 ++++ sql/sql_yacc.yy | 26 ++++----- 17 files changed, 204 insertions(+), 44 deletions(-) create mode 100644 mysql-test/r/ctype_ujis.result create mode 100644 mysql-test/t/ctype_ujis-master.opt create mode 100644 mysql-test/t/ctype_ujis.test diff --git a/acinclude.m4 b/acinclude.m4 index cf0233fa38f..4d7900acc3d 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -38,7 +38,7 @@ AC_LANG_SAVE AC_LANG_CPLUSPLUS if test "$ac_cv_prog_gxx" = "yes" then - CXXFLAGS="$CXXFLAGS -Werror" + CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'` fi mysql_cv_btype_last_arg_accept=none [AC_TRY_COMPILE([#if defined(inline) diff --git a/configure.in b/configure.in index aea415a13c4..a1ea566435b 100644 --- a/configure.in +++ b/configure.in @@ -1862,7 +1862,7 @@ AC_LANG_SAVE AC_LANG_CPLUSPLUS if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no" then - CXXFLAGS="$CXXFLAGS -Werror" + CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'` fi AC_TRY_COMPILE( [#undef inline @@ -1894,7 +1894,7 @@ AC_LANG_SAVE AC_LANG_CPLUSPLUS if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no" then - CXXFLAGS="$CXXFLAGS -Werror" + CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'` fi AC_TRY_COMPILE( [#undef inline @@ -2341,7 +2341,7 @@ extern int mbcharlen_${c}(uint);" mbcharlen_${c}" else CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT - 0, /* mbmaxlen */ + 1, /* mbmaxlen */ NULL, /* ismbchar */ NULL, /* ismbhead */ NULL /* mbcharlen */" diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 2f3ef872492..0ccc8a3bf40 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -183,8 +183,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, "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); - + { + /* Not supported in this version */ + my_errno= HA_ERR_UNSUPPORTED; + goto err; + } mi_state_info_read(disk_cache, &share->state); len= mi_uint2korr(share->state.header.base_info_length); if (len != MI_BASE_INFO_SIZE) diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result new file mode 100644 index 00000000000..223a18f19e9 --- /dev/null +++ b/mysql-test/r/ctype_ujis.result @@ -0,0 +1,8 @@ +drop table if exists t1; +create table t1 (c text); +insert into t1 values (0xa4a2),(0xa4a3); +select hex(left(c,1)) from t1 group by c; +hex(left(c,1)) +A4A2 +A4A3 +drop table t1; diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 9f6a8762325..3211dcf76a9 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -274,3 +274,90 @@ SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (site rate_code base_rate cust 20 drop table t1,t2; +create table t1 (i int); +create table t2 (i int); +create table t3 (i int); +insert into t1 values(1),(2); +insert into t2 values(2),(3); +insert into t3 values (2),(4); +select * from t1 natural left join t2; +i i +1 NULL +2 2 +select * from t1 left join t2 on (t1.i=t2.i); +i i +1 NULL +2 2 +select * from t1 natural left join t2 natural left join t3; +i i i +1 NULL NULL +2 2 2 +select * from t1 left join t2 on (t1.i=t2.i) left join t3 on (t2.i=t3.i); +i i i +1 NULL NULL +2 2 2 +select * from t3 natural right join t2; +i i +2 2 +NULL 3 +select * from t3 right join t2 on (t3.i=t2.i); +i i +2 2 +NULL 3 +select * from t3 natural right join t2 natural right join t1; +i i i +NULL NULL 1 +2 2 2 +select * from t3 right join t2 on (t3.i=t2.i) right join t1 on (t2.i=t1.i); +i i i +NULL NULL 1 +2 2 2 +select * from t1,t2 natural left join t3 order by t1.i,t2.i,t3.i; +i i i +1 2 2 +1 3 NULL +2 2 2 +2 3 NULL +select * from t1,t2 left join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i; +i i i +1 2 2 +1 3 NULL +2 2 2 +2 3 NULL +select t1.i,t2.i,t3.i from t2 natural left join t3,t1 order by t1.i,t2.i,t3.i; +i i i +1 2 2 +1 3 NULL +2 2 2 +2 3 NULL +select t1.i,t2.i,t3.i from t2 left join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; +i i i +1 2 2 +1 3 NULL +2 2 2 +2 3 NULL +select * from t1,t2 natural right join t3 order by t1.i,t2.i,t3.i; +i i i +1 NULL 4 +1 2 2 +2 NULL 4 +2 2 2 +select * from t1,t2 right join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i; +i i i +1 NULL 4 +1 2 2 +2 NULL 4 +2 2 2 +select t1.i,t2.i,t3.i from t2 natural right join t3,t1 order by t1.i,t2.i,t3.i; +i i i +1 NULL 4 +1 2 2 +2 NULL 4 +2 2 2 +select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; +i i i +1 NULL 4 +1 2 2 +2 NULL 4 +2 2 2 +drop table t1,t2,t3; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 98f8882aa10..e64cc07e344 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -351,12 +351,7 @@ select t1.name, t2.name, t2.id,t3.id from t1 right join t2 on (t1.id = t2.owner) name name id id Antonio Paz El Gato 1 1 Antonio Paz Perrito 2 1 -NULL Happy 3 1 -NULL El Gato 1 2 -NULL Perrito 2 2 -NULL Happy 3 2 -NULL El Gato 1 3 -NULL Perrito 2 3 +NULL NULL NULL 2 Thimble Smith Happy 3 3 select t1.name, t2.name, t2.id, t2.owner, t3.id from t1 left join t2 on (t1.id = t2.owner) right join t1 as t3 on t3.id=t2.owner; name name id owner id diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1ad3043b4b2..a4c2533ec1a 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3402,13 +3402,7 @@ a a a select * from t1 natural left join (t1 as t2 left join t1 as t3 using (a)); a a a 1 1 1 -2 1 NULL -3 1 NULL -1 2 NULL 2 2 2 -3 2 NULL -1 3 NULL -2 3 NULL 3 3 3 select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1; a a a @@ -3464,13 +3458,7 @@ a a a select * from t1 natural join (t1 as t2 left join t1 as t3 using (a)); a a a 1 1 1 -2 1 NULL -3 1 NULL -1 2 NULL 2 2 2 -3 2 NULL -1 3 NULL -2 3 NULL 3 3 3 select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1; a a a diff --git a/mysql-test/t/ctype_ujis-master.opt b/mysql-test/t/ctype_ujis-master.opt new file mode 100644 index 00000000000..1f4183d5027 --- /dev/null +++ b/mysql-test/t/ctype_ujis-master.opt @@ -0,0 +1 @@ +--default-character-set=ujis diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test new file mode 100644 index 00000000000..cd1dc965000 --- /dev/null +++ b/mysql-test/t/ctype_ujis.test @@ -0,0 +1,13 @@ +# +# Tests with the ujis character set +# +drop table if exists t1; + +# +# Test problem with LEFT() +# + +create table t1 (c text); +insert into t1 values (0xa4a2),(0xa4a3); +select hex(left(c,1)) from t1 group by c; +drop table t1; diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 63ec90f854c..7a9868e60ef 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -271,3 +271,35 @@ INSERT INTO t2 VALUES ('rivercats','cust',20); SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND lr.siteid = 'rivercats'; SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith'; drop table t1,t2; + +# +# Test combination of join methods +# + +create table t1 (i int); +create table t2 (i int); +create table t3 (i int); +insert into t1 values(1),(2); +insert into t2 values(2),(3); +insert into t3 values (2),(4); + +select * from t1 natural left join t2; +select * from t1 left join t2 on (t1.i=t2.i); +select * from t1 natural left join t2 natural left join t3; +select * from t1 left join t2 on (t1.i=t2.i) left join t3 on (t2.i=t3.i); + +select * from t3 natural right join t2; +select * from t3 right join t2 on (t3.i=t2.i); +select * from t3 natural right join t2 natural right join t1; +select * from t3 right join t2 on (t3.i=t2.i) right join t1 on (t2.i=t1.i); + +select * from t1,t2 natural left join t3 order by t1.i,t2.i,t3.i; +select * from t1,t2 left join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i; +select t1.i,t2.i,t3.i from t2 natural left join t3,t1 order by t1.i,t2.i,t3.i; +select t1.i,t2.i,t3.i from t2 left join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; + +select * from t1,t2 natural right join t3 order by t1.i,t2.i,t3.i; +select * from t1,t2 right join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i; +select t1.i,t2.i,t3.i from t2 natural right join t3,t1 order by t1.i,t2.i,t3.i; +select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i; +drop table t1,t2,t3; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0f1ce8adba6..af4e2a01eae 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -899,7 +899,7 @@ void Item_str_func::left_right_max_length() max_length=args[0]->max_length; if (args[1]->const_item()) { - int length=(int) args[1]->val_int(); + int length=(int) args[1]->val_int()*default_charset_info->mbmaxlen; if (length <= 0) max_length=0; else @@ -992,7 +992,7 @@ void Item_func_substr::fix_length_and_dec() } if (arg_count == 3 && args[2]->const_item()) { - int32 length= (int32) args[2]->val_int(); + int32 length= (int32) args[2]->val_int() * default_charset_info->mbmaxlen; if (length <= 0) max_length=0; /* purecov: inspected */ else diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3910bfc880b..211237b8443 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1233,7 +1233,7 @@ void yyerror(const char *s) { NET *net=my_pthread_getspecific_ptr(NET*,THR_NET); char *yytext=(char*) current_lex->tok_start; - if (!strcmp(s,"parse error")) + if (!strcmp(s,"parse error") || !strcmp(s,"syntax error")) s=ER(ER_SYNTAX_ERROR); net_printf(net,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "", current_lex->yylineno); @@ -3787,7 +3787,7 @@ replicating a LOAD DATA INFILE command", (gptr*) &max_connect_errors, (gptr*) &max_connect_errors, 0, GET_ULONG, REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0}, {"max_delayed_threads", OPT_MAX_DELAYED_THREADS, - "Don't start more than this number of threads to handle INSERT DELAYED statements. This option does not yet have effect (on TODO), unless it is set to zero, which means INSERT DELAYED is not used.", + "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.", (gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads, 0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0}, {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index dc687e483e8..2a65291c273 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -110,6 +110,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), net.last_error[0]=0; // If error on boot ull=0; system_thread=cleanup_done=0; + peer_port= 0; // For SHOW PROCESSLIST transaction.changed_tables = 0; #ifdef __WIN__ real_id = 0; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0e7a487276d..0379c1de287 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -643,6 +643,9 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) /* no match; create a new thread to handle the table */ if (!(tmp=find_handler(thd,table_list))) { + /* Don't create more than max_insert_delayed_threads */ + if (delayed_insert_threads >= max_insert_delayed_threads) + DBUG_RETURN(0); thd->proc_info="Creating delayed handler"; pthread_mutex_lock(&LOCK_delayed_create); if (!(tmp=find_handler(thd,table_list))) // Was just created @@ -1021,7 +1024,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) while (!thd->killed) { int error; -#if (defined(HAVE_BROKEN_COND_TIMEDWAIT) || defined(HAVE_LINUXTHREADS)) +#if defined(HAVE_BROKEN_COND_TIMEDWAIT) error=pthread_cond_wait(&di->cond,&di->mutex); #else error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0ffdb68a179..1a8ea7da8f4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -210,9 +210,9 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, !(thd->client_capabilities & CLIENT_LONG_PASSWORD),&ur); DBUG_PRINT("info", - ("Capabilities: %d packet_length: %ld Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'", + ("Capabilities: %d packet_length: %ld Host: '%s' Login user: '%s' Priv_user: '%s' Using password: %s Access: %u db: '%s'", thd->client_capabilities, thd->max_client_packet_length, - thd->host_or_ip, thd->priv_user, + thd->host_or_ip, thd->user, thd->priv_user, passwd[0] ? "yes": "no", thd->master_access, thd->db ? thd->db : "*none*")); if (thd->master_access & NO_ACCESS) @@ -517,7 +517,6 @@ check_connections(THD *thd) DBUG_PRINT("info",("Host: %s",thd->host)); thd->host_or_ip= thd->host; thd->ip= 0; - thd->peer_port= 0; bzero((char*) &thd->remote,sizeof(struct sockaddr)); } /* Ensure that wrong hostnames doesn't cause buffer overflows */ @@ -3419,6 +3418,24 @@ void add_join_on(TABLE_LIST *b,Item *expr) } +/* + Mark that we have a NATURAL JOIN between two tables + + SYNOPSIS + add_join_natural() + a Table to do normal join with + b Do normal join with this table + + IMPLEMENTATION + This function just marks that table b should be joined with a. + The function setup_cond() will create in b->on_expr a list + of equal condition between all fields of the same name. + + SELECT * FROM t1 NATURAL LEFT JOIN t2 + <=> + SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... ) +*/ + void add_join_natural(TABLE_LIST *a,TABLE_LIST *b) { b->natural_join=a; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 14b567b86c5..f870f8f5178 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -556,7 +556,17 @@ mysql_select(THD *thd,TABLE_LIST *tables,List &fields,COND *conds, select_distinct= 0; no_order= !order; if (all_order_fields_used) + { + if (order && skip_sort_order) + { + /* + Force MySQL to read the table in sorted order to get result in + ORDER BY order. + */ + join.tmp_table_param.quick_group=0; + } order=0; + } join.group=1; // For end_write_group } else diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 7cd0b9406ea..d7a0c15e9b9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -492,12 +492,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %right NOT %right BINARY -/* These don't actually affect the way the query is really evaluated, but - they silence a few warnings for shift/reduce conflicts. */ -%left ',' -%left STRAIGHT_JOIN JOIN_SYM -%nonassoc CROSS INNER_SYM NATURAL LEFT RIGHT - %type IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text @@ -2116,7 +2110,7 @@ join_table_list: | join_table_list ',' join_table_list { $$=$3; } | join_table_list normal_join join_table_list { $$=$3; } | join_table_list STRAIGHT_JOIN join_table_list - { $$=$3 ; $$->straight=1; } + { $$=$3 ; $1->next->straight=1; } | join_table_list normal_join join_table_list ON expr { add_join_on($3,$5); $$=$3; } | join_table_list normal_join join_table_list @@ -2140,9 +2134,13 @@ join_table_list: USING '(' using_list ')' { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table_list - { add_join_natural($1,$6); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; } + { + add_join_natural($1,$1->next); + $1->next->outer_join|=JOIN_TYPE_LEFT; + $$=$6; + } | join_table_list RIGHT opt_outer JOIN_SYM join_table_list ON expr - { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } + { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; } | join_table_list RIGHT opt_outer JOIN_SYM join_table_list { SELECT_LEX *sel=Select; @@ -2150,11 +2148,15 @@ join_table_list: sel->db2=$5->db; sel->table2=$5->alias; } USING '(' using_list ')' - { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } + { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; } | join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table_list - { add_join_natural($6,$1); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } + { + add_join_natural($1->next,$1); + $1->outer_join|=JOIN_TYPE_RIGHT; + $$=$6; + } | join_table_list NATURAL JOIN_SYM join_table_list - { add_join_natural($1,$4); $$=$4; }; + { add_join_natural($1,$1->next); $$=$4; }; normal_join: JOIN_SYM {} From 4cca7b5b5027f492aa2de188af7a0ef2d16205c6 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 26 Apr 2003 20:57:13 +0300 Subject: [PATCH 102/188] srv0start.c: fflush stderr after startup --- innobase/srv/srv0start.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 20e7514a4ea..ec0546f8c66 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1439,7 +1439,9 @@ innobase_start_or_create_for_mysql(void) fprintf(stderr, "InnoDB: !!! innodb_force_recovery is set to %lu !!!\n", srv_force_recovery); - } + } + + fflush(stderr); return((int) DB_SUCCESS); } From e63477d6b9c0a0d5479b9e2ddd60d249de33fa2f Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Sat, 26 Apr 2003 16:00:52 -0700 Subject: [PATCH 103/188] Update PeterG's internals documentation per Monty's comments; minor changes only. --- Docs/internals.texi | 884 +++++++++++++++++--------------------------- 1 file changed, 347 insertions(+), 537 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index 07eea90e229..5c2070abb9c 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -273,7 +273,7 @@ and then we read the rows in the sorted order into a row buffer @itemize @bullet @item -We are using @uref{http://www.bitkeeper.com/, BitKeeper} for source management. +We use @uref{http://www.bitkeeper.com/, BitKeeper} for source management. @item You should use the @strong{MySQL} 4.0 source for all developments. @@ -3131,42 +3131,38 @@ program is given along with an explanation of its intended function. @strong{Directory -- Short Comment} @itemize @bullet @item -bdb -- The Berkeley Database table handler +bdb -- The Berkeley Database table handler @item BitKeeper -- BitKeeper administration (not part of the source distribution) @item -BUILD -- Some very often used build scripts +BUILD -- Frequently used build scripts @item -Build-tools -- Build tools +Build-tools -- Build tools (not part of the source distribution) @item -client -- Client library +client -- Client library @item cmd-line-utils -- Command-line utilities (libedit and readline) @item dbug -- Fred Fish's dbug library @item -Docs -- Preliminary documents about internals and new modules +Docs -- Preliminary documents about internals and new modules; will eventually be moved to the mysqldoc repository @item extra -- Some minor standalone utility programs @item heap -- The HEAP table handler @item -include -- Include (*.h) files +include -- Header (*.h) files for most libraries; includes all header files distributed with the MySQL binary distribution @item innobase -- The Innobase (InnoDB) table handler @item -isam -- The ISAM (MySQL) table handler +libmysql -- For producing MySQL as a library (e.g. a Windows .DLL) @item -libmysql -- For producing a thread-safe libmysql library -@item -libmysql_r -- Only one file, a makefile +libmysql_r -- For building a thread-safe libmysql library @item libmysqld -- The MySQL Server as an embeddable library @item man -- Some user-contributed manual pages @item -merge -- The MERGE table handler (see Reference Manual section 7.2) -@item myisam -- The MyISAM table handler @item myisammrg -- The MyISAM Merge table handler @@ -3177,9 +3173,9 @@ mysys -- MySQL system library (Low level routines for file access etc.) @item netware -- Files related to the Novell NetWare version of MySQL @item -NEW-RPMS -- Directory to place RPMS while making a distribution +NEW-RPMS -- Directory to place RPMs while making a distribution @item -os2 -- Routines for working with the OS/2 operating system +os2 -- Routines for working with the OS/2 operating system @item pstack -- Process stack display (not currently used) @item @@ -3189,25 +3185,25 @@ SCCS -- Source Code Control System (not part of source distribution) @item scripts -- SQL batches, e.g. mysqlbug and mysql_install_db @item -sql -- Programs for handling SQL commands. The "core" of MySQL +sql -- Programs for handling SQL commands; the "core" of MySQL @item sql-bench -- The MySQL benchmarks @item -SSL -- Secure Sockets Layer +SSL -- Secure Sockets Layer; includes an example certification one can use to test an SSL (secure) database connection @item strings -- Library for C string routines, e.g. atof, strchr @item support-files -- Files used to build MySQL on different systems @item -tests -- Tests in Perl +tests -- Tests in Perl and in C @item -tools -- mysqlmanager.c (under development, not yet useful) +tools -- mysqlmanager.c (tool under development, not yet useful) @item VC++Files -- Includes this entire directory, repeated for VC++ (Windows) use @item vio -- Virtual I/O Library @item -zlib -- data compression library, used on Windows +zlib -- Data compression library, used on Windows @end itemize @subsection bdb @@ -3215,7 +3211,7 @@ zlib -- data compression library, used on Windows The Berkeley Database table handler. @*@* -The Berkeley Database (BDB) is maintained by Sleepycat Software. +The Berkeley Database (BDB) is maintained by Sleepycat Software. MySQL AB maintains only a few small patches to make BDB work better with MySQL. @*@* @@ -3231,19 +3227,21 @@ in this document. BitKeeper administration. @*@* -This directory may be present if you downloaded the MySQL source using +Bitkeeper administration is not part of the source distribution. This +directory may be present if you downloaded the MySQL source using BitKeeper rather than via the mysql.com site. The files in the BitKeeper directory are for maintenance purposes only -- they are not part of the MySQL package. @*@* -The MySQL Reference Manual explains how to use Bitkeeper to get the -MySQL source. +The MySQL Reference Manual explains how to use Bitkeeper to get the +MySQL source. Please see @url{http://www.mysql.com/doc/en/Installing_source_tree.html} +for more information. @*@* @subsection BUILD -Build switches. +Frequently used build scripts. @*@* This directory contains the build switches for compilation on various @@ -3266,11 +3264,11 @@ solaris Build tools. @*@* -This directory contains batch files for extracting, making -directories, and making programs from source files. There are -several subdirectories with different scripts -- for building -Linux executables, for compiling, for performing all build steps, -and so on. +Build-tools is not part of the source distribution. This directory +contains batch files for extracting, making directories, and making +programs from source files. There are several subdirectories with +different scripts -- for building Linux executables, for compiling, +for performing all build steps, and so on. @*@* @subsection client @@ -3302,7 +3300,7 @@ mysqladmin.c -- maintenance of MYSQL databases @item mysqlcheck.c -- check all databases, check connect, etc. @item -mysqldump.c -- dump table's contents as SQL statements +mysqldump.c -- dump table's contents as SQL statements, suitable to backup a MySQL database @item mysqlimport.c -- import text files in different formats into tables @item @@ -3314,7 +3312,7 @@ mysqlshow.c -- show databases, tables or columns @item mysqltest.c -- test program used by the mysql-test suite, mysql-test-run @item -password.c -- password checking routines +password.c -- password checking routines (version 4.1 and up) @item select_test.c -- test that a select is possible @item @@ -3328,15 +3326,14 @@ thread_test.c -- test that threading is possible @subsection cmd-line-utils -Command-line utilities. +Command-line utilities (libedit and readline). @*@* There are two subdirectories: \readline and \libedit. All the files -here are "non-MYSQL" files, in the sense that MySQL AB didn't produce +here are "non-MySQL" files, in the sense that MySQL AB didn't produce them, it just uses them. It should be unnecessary to study the -programs in these files unless -you are writing or debugging a tty-like client for MySQL, such as -mysql.exe. +programs in these files unless you are writing or debugging a tty-like +client for MySQL, such as mysql.exe. @*@* The \readline subdirectory contains the files of the GNU Readline @@ -3346,54 +3343,54 @@ Software Foundation. @*@* The \libedit (library of edit functions) subdirectory has files -written by Christos Zoulas. They are distributed and modifed under +written by Christos Zoulas. They are distributed and modifed under the BSD License. These files are for editing the line contents. @*@* These are the program files in the \libedit subdirectory: @itemize @bullet @item -chared.c -- character editor +chared.c -- character editor @item -common.c -- common editor functions +common.c -- common editor functions @item -el.c -- editline interface functions +el.c -- editline interface functions @item -emacs.c -- emacs functions +emacs.c -- emacs functions @item -fgetln.c -- get line +fgetln.c -- get line @item -hist.c -- history access functions +hist.c -- history access functions @item -history.c -- more history access functions +history.c -- more history access functions @item -key.c -- procedures for maintaining the extended-key map +key.c -- procedures for maintaining the extended-key map @item -map.c -- editor function definitions +map.c -- editor function definitions @item -parse.c -- parse an editline extended command +parse.c -- parse an editline extended command @item -prompt.c -- prompt printing functions +prompt.c -- prompt printing functions @item -read.c -- terminal read functions +read.c -- terminal read functions @item -readline.c -- read line +readline.c -- read line @item -refresh.c -- "lower level screen refreshing functions" +refresh.c -- "lower level screen refreshing functions" @item -search.c -- "history and character search functions" +search.c -- "history and character search functions" @item -sig.c -- for signal handling +sig.c -- for signal handling @item -strlcpy.c -- string copy +strlcpy.c -- string copy @item -term.c -- "editor/termcap-curses interface" +term.c -- "editor/termcap-curses interface" @item -tokenizer.c -- Bourne shell line tokenizer +tokenizer.c -- Bourne shell line tokenizer @item -tty.c -- for a tty interface +tty.c -- for a tty interface @item -vi.c -- commands used when in the vi (editor) mode +vi.c -- commands used when in the vi (editor) mode @end itemize @*@* @@ -3403,8 +3400,8 @@ Fred Fish's dbug library. @*@* This is not really part of the MySQL package. Rather, it's a set of -public-domain routines which are useful for debugging MySQL programs. -The MySQL Server and all .c and .cc programs support the use of this +public-domain routines which are useful for debugging MySQL programs. +The MySQL Server and all .c and .cc programs support the use of this package. @*@* @@ -3415,61 +3412,62 @@ DBUG_ENTER("get_tty_password"); @* at the start of a routine, and this line: @* DBUG_RETURN(my_strdup(to,MYF(MY_FAE))); @* at the end of the routine. These lines don't affect production code. -Features of the dbug library include extensive reporting and profiling +Features of the dbug library include extensive reporting and profiling (the latter has not been used by the MySQL team). @*@* The C programs in this directory are: @itemize @bullet @item -dbug.c -- The main module +dbug.c -- The main module @item -dbug_analyze.c -- Reads a file produced by trace functions +dbug_analyze.c -- Reads a file produced by trace functions @item -example1.c -- A tiny example +example1.c -- A tiny example @item -example2.c -- A tiny example +example2.c -- A tiny example @item -example3.c -- A tiny example +example3.c -- A tiny example @item -factorial.c -- A tiny example +factorial.c -- A tiny example @item -main.c -- A tiny example +main.c -- A tiny example @item -sanity.c -- Declaration of a variable +sanity.c -- Declaration of a variable @end itemize @*@* @subsection Docs -Preliminary documents about internals and new modules. +Preliminary documents about internals and new modules, which will eventually +be moved to the mysqldoc repository. @*@* This directory doesn't have much at present that's very useful to the student, but the plan is that some documentation related to the source files and the internal workings of MySQL, including perhaps some -documentation from developers themselves, will be placed here. Some of -these files will eventually be moved to the MySQL documentation repository. +documentation from developers themselves, will be placed here. Files in +this directory will eventually be moved to the MySQL documentation repository. @*@* These sub-directories are part of this directory: @itemize @bullet @item -books -- .gif images and empty .txt files; no real information +books -- .gif images and empty .txt files; no real information @item -flags -- images of flags of countries +flags -- images of flags of countries @item -images -- flag backgrounds and the MySQL dolphin logo +images -- flag backgrounds and the MySQL dolphin logo @item -mysql-logos -- more MySQL-related logos, some of them moving +mysql-logos -- more MySQL-related logos, some of them moving @item -raw-flags -- more country flags, all .gif files +raw-flags -- more country flags, all .gif files @item -support -- various files for generating texinfo/docbook documentation +support -- various files for generating texinfo/docbook documentation @item -to-be-included... -- an empty subdirectory +to-be-included... -- an empty subdirectory @item -translations -- some Portuguese myodbc documentation +translations -- some Portuguese myodbc documentation @end itemize @*@* @@ -3480,16 +3478,16 @@ has any importance -- internals.texi -- The "MySQL Internals" document. @*@* -Despite the name, internals.texi is not really much of a description -of MySQL internals. However, there is some useful description of the -functions in the mysys directory (see below), and of the structure of -client/server messages (doubtless very useful for people who want to -make their own JDBC drivers, or just sniff). +Despite the name, internals.texi is not yet much of a description of MySQL +internals although work is in progress to make it so. However, there is +some useful description of the functions in the mysys directory (see below), +and of the structure of client/server messages (doubtless very useful for +eople who want to make their own JDBC drivers, or just sniff). @*@* @subsection extra -Eight minor standalone utility programs. +Some minor standalone utility programs. @*@* These programs are all standalone utilities, that is, they have @@ -3498,56 +3496,20 @@ MySQL server needs or produces. Most are unimportant. They are as follows: @itemize @bullet @item -my_print_defaults.c -- print all parameters in a default file +my_print_defaults.c -- print parameters from my.ini files. Can also be used in scripts to enable processing of my.ini files. @item -mysql_install.c -- startup: install MySQL server +mysql_waitpid.c -- wait for a program to terminate. Useful for shell scripts when one needs to wait until a process terminates. @item -mysql_waitpid.c -- wait for a program to terminate -@item -perror.c -- "print error" -- given error number, display message +perror.c -- "print error" -- given error number, display message @item replace.c -- replace strings in text files or pipe @item -resolve_stack_dump.c -- show symbolic info from a stack dump +resolve_stack_dump.c -- show symbolic information from a MySQL stack dump, normally found in the mysql.err file @item -resolveip.c -- convert an IP address to a hostname, or vice versa +resolveip.c -- convert an IP address to a hostname, or vice versa @end itemize @*@* -@subsection fs - -File System. -@*@* - -Here the word "File System" does not refer to the mere idea of a -directory of files on a disk drive, but to object-based access. The -concept has been compared with Oracle's Internet File System (iFS). -@*@* - -The original developer of the files on this directory is Tonu Samuel, -a former MySQL AB employee. Here is a quote (somewhat edited) from -Tonu Samuel's web page (http://no.spam.ee/~tonu/index.php): -"Question: What is it? -Answer: Actually this is not filesystem in common terms. MySQL FS -makes it possible to make SQL tables and some functions available over -a filesystem. MySQL does not require disk space, it uses an ordinary -MySQL daemon to store data." -The descriptions imply that this is a development project. -@*@* - -There are four program files in the directory: -@itemize @bullet -@item -database.c -- "emulate filesystem behaviour on top of SQL database" -@item -libmysqlfs.c -- Search/replace, show-functions, and parse routines -@item -mysqlcorbafs.c -- Connection with the CORBA "Object Request Broker" -@item -mysqlcorbafs_test.c -- Utility to test the working of mysqlcorbafs.c - -@*@* - @subsection heap The HEAP table handler. @@ -3567,50 +3529,50 @@ hp_block.c -- Read/write a block (i.e. a page) @item hp_clear.c -- Remove all records in the table @item -hp_close.c -- * close database +hp_close.c -- * close database @item -hp_create.c -- * create a table +hp_create.c -- * create a table @item -hp_delete.c -- * delete a row +hp_delete.c -- * delete a row @item hp_extra.c -- * for setting options and buffer sizes when optimizing @item -hp_hash.c -- Hash functions used for saving keys +hp_hash.c -- Hash functions used for saving keys @item -hp_info.c -- * Information about database status +hp_info.c -- * Information about database status @item -hp_open.c -- * open database +hp_open.c -- * open database @item hp_panic.c -- * the hp_panic routine, for shutdowns and flushes @item -hp_rename.c -- * rename a table +hp_rename.c -- * rename a table @item hp_rfirst.c -- * read first row through a specific key (very short) @item -hp_rkey.c -- * read record using a key +hp_rkey.c -- * read record using a key @item hp_rlast.c -- * read last row with same key as previously-read row @item hp_rnext.c -- * read next row with same key as previously-read row @item -hp_rprev.c -- * read previous row with same key as previously-read row +hp_rprev.c -- * read previous row with same key as previously-read row @item -hp_rrnd.c -- * read a row based on position +hp_rrnd.c -- * read a row based on position @item hp_rsame.c -- * find current row using positional read or key-based -read +read @item -hp_scan.c -- * read all rows sequentially +hp_scan.c -- * read all rows sequentially @item hp_static.c -- * static variables (very short) @item -hp_test1.c -- * testing basic functions +hp_test1.c -- * testing basic functions @item -hp_test2.c -- * testing database and storing results +hp_test2.c -- * testing database and storing results @item -hp_update.c -- * update an existing row +hp_update.c -- * update an existing row @item -hp_write.c -- * insert a new row +hp_write.c -- * insert a new row @end itemize @*@* @@ -3622,7 +3584,8 @@ for a \myisam\mi_cache.c equivalent (to cache reads) or a @subsection include -Include (*.h) files. +Header (*.h) files for most libraries; includes all header files distributed +with the MySQL binary distribution. @*@* These files may be included in C program files. Note that each @@ -3637,7 +3600,7 @@ rijndael.h. Looking further, you'll find that rijndael.h is also included in other places: by my_aes.c and my_aes.h. @*@* -The include directory contains 51 *.h (include) files. +The include directory contains 51 *.h (header) files. @*@* @subsection innobase @@ -3649,100 +3612,6 @@ A full description of these files can be found elsewhere in this document. @*@* -@subsection isam - -The ISAM table handler. -@*@* - -The C files in this directory are: -@itemize @bullet -@item -_cache.c -- for reading records from a cache -@item -changed.c -- a single routine for setting a "changed" flag (very -short) -@item -close.c -- close database -@item -create.c -- create a table -@item -_dbug.c -- support routines for use with "dbug" (see the \dbug -description) -@item -delete.c -- delete a row -@item -_dynrec.c -- functions to handle space-packed records and blobs -@item -extra.c -- setting options and buffer sizes when optimizing table -handling -@item -info.c -- Information about database status -@item -_key.c -- for handling keys -@item -_locking.c -- lock database -@item -log.c -- save commands in log file which myisamlog program can read -@item -_packrec.c -- compress records -@item -_page.c -- read and write pages containing keys -@item -panic.c -- the mi_panic routine, probably for sudden shutdowns -@item -range.c -- approximate count of how many records lie between two -keys -@item -rfirst.c -- read first row through a specific key (very short) -@item -rkey.c -- read a record using a key -@item -rlast.c -- read last row with same key as previously-read row -@item -rnext.c -- read next row with same key as previously-read row -@item -rprev.c -- read previous row with same key as previously-read row -@item -rrnd.c -- read a row based on position -@item -rsame.c -- find current row using positional read or key-based read -@item -rsamepos.c -- positional read -@item -_search.c -- key-handling functions -@item -static.c -- static variables (very short) -@item -_statrec.c -- functions to handle fixed-length records -@item -test1.c -- testing basic functions -@item -test2.c -- testing database and storing results -@item -test3.c -- testing locking -@item -update.c -- update an existing row -@item -write.c -- insert a new row -@item -pack_isam.c -- pack isam file (NOTE TO SELF ?? equivalent to -\myisam\myisampack.c) -@end itemize -@*@* - -Except for one minor C file (pack_isam.c) every program in the ISAM -directory has a counterpart in the MyISAM directory. For example -\isam\update.c corresponds to \myisam\mi_update.c. However, the -reverse is not true -- there are many files in the MyISAM directory -which have no counterpart in the ISAM directory. -@*@* - -The reason is simple -- it's because the ISAM files are becoming -obsolete. When MySQL programmers add new features, they add them for -MyISAM only. The student can therefore ignore all files in this -directory and study the MyISAM programs instead. -@*@* - @subsection libmysql The MySQL Library, Part 1. @@ -3772,7 +3641,7 @@ errmsg.c -- English error messages, compare \mysys\errors.c @item get_password.c -- get password @item -libmysql.c -- the main "packet-sending emulation" program +libmysql.c -- the code that implements the MySQL API, i.e. the functions a client that wants to connect to MySQL will call @item manager.c -- initialize/connect/fetch with MySQL manager @end itemize @@ -3784,7 +3653,7 @@ The MySQL Library, Part 2. @*@* This is a continuation of the libmysql directory. There is only one -file here: +file here, used to build a thread-safe libmysql library: @itemize @bullet @item makefile.am @@ -3796,85 +3665,26 @@ makefile.am The MySQL library, Part 3. @*@* -This is a continuation of the libmysql directory. The program files on -this directory are: +This is a continuation of the libmysql directory and contains the MySQL +Server as an embeddable library. The program files on this directory +are: @itemize @bullet @item -libmysqld.c -- The called side, compare the mysqld.exe source +libmysqld.c -- The called side, compare the mysqld.exe source @item -lib_vio.c -- Emulate the vio directory's communication buffer +lib_vio.c -- Emulate the vio directory's communication buffer @end itemize @*@* @subsection man -Manual pages. +Some user-contributed manual pages @*@* These are not the actual "man" (manual) pages, they are switches for the production. @*@* -@subsection merge - -The MERGE table handler. -@*@* - -For a description of the MERGE table handler, see the MySQL Reference -Manual, section 7.2. -@*@* - -You'll notice that there seem to be several directories with -similar-sounding names of C files in them. That's because the MySQL -table handlers are all quite similar. -@*@* - -The related directories are: -@itemize @bullet -@item -\isam -- for ISAM -@item -\myisam -- for MyISAM -@item -\merge -- for ISAM MERGE (mostly call functions in \isam programs) -@item -\myisammrg -- for MyISAM MERGE (mostly call functions in \myisam -programs) -@end itemize -@*@* - -To avoid duplication, only the \myisam program versions are discussed. -@*@* - -The C programs in this (merge) directory are: -@itemize @bullet -@item -mrg_close.c -- compare \isam's close.c -@item -mrg_create.c -- "" create.c -@item -mrg_delete.c -- "" delete.c -@item -mrg_extra.c -- "" extra.c -@item -mrg_info.c -- "" info.c -@item -mrg_locking.c -- "" locking.c -@item -mrg_open.c -- "" open.c -@item -mrg_panic.c -- "" panic.c -@item -mrg_rrnd.c -- "" rrnd.c -@item -mrg_rsame.c -- "" rsame.c -@item -mrg_static.c -- "" static.c -@item -mrg_update.c -- "" update.c -@end itemize -@*@* - @subsection myisam The MyISAM table handler. @@ -3910,10 +3720,9 @@ programs. They are: @item mi_cache.c -- for reading records from a cache @item -mi_changed.c -- a single routine for setting a "changed" flag (very -short) +mi_changed.c -- a single routine for setting a "changed" flag (very short) @item -mi_check.c -- doesn't just do checks, ?? for myisamchk program? +mi_check.c -- for checking and repairing tables. Used by the myisamchk program and by the MySQL server. @item mi_checksum.c -- calculates a checksum for a row @item @@ -3921,8 +3730,7 @@ mi_close.c -- close database @item mi_create.c -- create a table @item -mi_dbug.c -- support routines for use with "dbug" (see \dbug -description) +mi_dbug.c -- support routines for use with "dbug" (see \dbug description) @item mi_delete.c -- delete a row @item @@ -3940,58 +3748,57 @@ mi_key.c -- for handling keys @item mi_locking.c -- lock database @item -mi_log.c -- save commands in log file which myisamlog program can read +mi_log.c -- save commands in a log file which myisamlog program can read. Can be used to exactly replay a set of changes to a table. @item mi_open.c -- open database @item mi_packrec.c -- read from a data file compresed with myisampack @item -mi_page.c -- read and write pages containing keys +mi_page.c -- read and write pages containing keys @item -mi_panic.c -- the mi_panic routine, probably for sudden shutdowns +mi_panic.c -- the mi_panic routine, probably for sudden shutdowns @item mi_range.c -- approximate count of how many records lie between two keys @item -mi_rename.c -- rename a table +mi_rename.c -- rename a table @item mi_rfirst.c -- read first row through a specific key (very short) @item -mi_rkey.c -- read a record using a key +mi_rkey.c -- read a record using a key @item -mi_rlast.c -- read last row with same key as previously-read row +mi_rlast.c -- read last row with same key as previously-read row @item -mi_rnext.c -- read next row with same key as previously-read row +mi_rnext.c -- read next row with same key as previously-read row @item -mi_rnext_same.c -- same as mi_rnext.c, but abort if the key changes +mi_rnext_same.c -- same as mi_rnext.c, but abort if the key changes @item mi_rprev.c -- read previous row with same key as previously-read row @item -mi_rrnd.c -- read a row based on position +mi_rrnd.c -- read a row based on position @item -mi_rsame.c -- find current row using positional read or key-based -read +mi_rsame.c -- find current row using positional read or key-based read @item -mi_rsamepos.c -- positional read +mi_rsamepos.c -- positional read @item -mi_scan.c -- read all rows sequentially +mi_scan.c -- read all rows sequentially @item -mi_search.c -- key-handling functions +mi_search.c -- key-handling functions @item mi_static.c -- static variables (very short) @item -mi_statrec.c -- functions to handle fixed-length records +mi_statrec.c -- functions to handle fixed-length records @item -mi_test1.c -- testing basic functions +mi_test1.c -- testing basic functions @item -mi_test2.c -- testing database and storing results +mi_test2.c -- testing database and storing results @item -mi_test3.c -- testing locking +mi_test3.c -- testing locking @item -mi_unique.c -- functions to check if a row is unique +mi_unique.c -- functions to check if a row is unique @item -mi_update.c -- update an existing row +mi_update.c -- update an existing row @item -mi_write.c -- insert a new row +mi_write.c -- insert a new row @end itemize @*@* @@ -4104,7 +3911,7 @@ tests @subsection mysys -MySQL system library (Low level routines for file access etc.). +MySQL system library. Low level routines for file access and so on. @*@* There are 115 *.c programs in this directory: @@ -4112,13 +3919,11 @@ There are 115 *.c programs in this directory: @item array.c -- Dynamic array handling @item -charset.c -- Using dynamic character sets, set default character -set, ... +charset.c -- Using dynamic character sets, set default character set, ... @item -charset2html.c -- Checking what character set a browser is using +charset2html.c -- Check what character set a browser is using @item -checksum.c -- Calculate checksum for a memory block, used for -pack_isam +checksum.c -- Calculate checksum for a memory block, used for pack_isam @item default.c -- Find defaults from *.cnf or *.ini files @item @@ -4128,54 +3933,51 @@ hash.c -- Hash search/compare/free functions "for saving keys" @item list.c -- Double-linked lists @item -make-conf.c -- "Make a charset .conf file out of a ctype-charset.c -file" +make-conf.c -- "Make a charset .conf file out of a ctype-charset.c file" @item md5.c -- MD5 ("Message Digest 5") algorithm from RSA Data Security @item -mf_brkhant.c -- Prevent user from doing a Break during critical -execution +mf_brkhant.c -- Prevent user from doing a Break during critical execution (not used in MySQL; can be used by standalone MyISAM applications) @item -mf_cache.c -- "Open a temporary file and cache it with io_cache" +mf_cache.c -- "Open a temporary file and cache it with io_cache" @item -mf_dirname.c -- Parse/convert directory names +mf_dirname.c -- Parse/convert directory names @item -mf_fn_ext.c -- Get filename extension +mf_fn_ext.c -- Get filename extension @item -mf_format.c -- Format a filename +mf_format.c -- Format a filename @item -mf_getdate.c -- Get date, return in yyyy-mm-dd hh:mm:ss format +mf_getdate.c -- Get date, return in yyyy-mm-dd hh:mm:ss format @item -mf_iocache.c -- Cached read/write of files in fixed-size units +mf_iocache.c -- Cached read/write of files in fixed-size units @item -mf_iocache2.c -- Continuation of mf_iocache.c +mf_iocache2.c -- Continuation of mf_iocache.c @item -mf_keycache.c -- Key block caching for certain file types +mf_keycache.c -- Key block caching for certain file types @item mf_loadpath.c -- Return full path name (no ..\ stuff) @item mf_pack.c -- Packing/unpacking directory names for create purposes @item -mf_path.c -- Determine where a program can find its files +mf_path.c -- Determine where a program can find its files @item -mf_qsort.c -- Quicksort +mf_qsort.c -- Quicksort @item -mf_qsort2.c -- Quicksort, part 2 +mf_qsort2.c -- Quicksort, part 2 (allows the passing of an extra argument to the sort-compare routine) @item -mf_radix.c -- Radix sort +mf_radix.c -- Radix sort @item -mf_same.c -- Determine whether filenames are the same +mf_same.c -- Determine whether filenames are the same @item -mf_sort.c -- Sort with choice of Quicksort or Radix sort +mf_sort.c -- Sort with choice of Quicksort or Radix sort @item -mf_soundex.c -- Soundex algorithm derived from EDN Nov. 14, 1985 -(pg. 36) +mf_soundex.c -- Soundex algorithm derived from EDN Nov. 14, 1985 (pg. 36) @item -mf_strip.c -- Strip trail spaces from a string +mf_strip.c -- Strip trail spaces from a string @item -mf_tempdir.c -- Initialize/find/free temporary directory +mf_tempdir.c -- Initialize/find/free temporary directory @item -mf_tempfile.c -- Create a temporary file +mf_tempfile.c -- Create a temporary file @item mf_unixpath.c -- Convert filename to UNIX-style filename @item @@ -4300,8 +4102,7 @@ my_rename.c -- Rename without delete @item my_seek.c -- Seek, i.e. point to a spot within a file @item -my_semaphore.c -- Semaphore routines, for use on OS that doesn't -support them +my_semaphore.c -- Semaphore routines, for use on OS that doesn't support them @item my_sleep.c -- Wait n microseconds @item @@ -4309,67 +4110,61 @@ my_static.c -- Static variables used by the mysys library @item my_symlink.c -- Read a symbolic link (symlinks are a UNIX thing, I guess) @item -my_symlink2.c -- Part 2 of my_symlink.c +my_symlink2.c -- Part 2 of my_symlink.c @item -my_tempnam.c -- Obsolete temporary-filename routine used by ISAM table handler +my_tempnam.c -- Obsolete temporary-filename routine used by ISAM table handler @item -my_thr_init.c -- initialize/allocate "all mysys & debug thread -variables" +my_thr_init.c -- initialize/allocate "all mysys & debug thread variables" @item -my_wincond.c -- Windows-specific: emulate Posix conditions +my_wincond.c -- Windows-specific: emulate Posix conditions @item -my_winsem.c -- Windows-specific: emulate Posix threads +my_winsem.c -- Windows-specific: emulate Posix threads @item -my_winthread.c -- Windows-specific: emulate Posix threads +my_winthread.c -- Windows-specific: emulate Posix threads @item -my_write.c -- Write a specified number of bytes to a file +my_write.c -- Write a specified number of bytes to a file @item -ptr_cmp.c -- Point to an optimal byte-comparison function +ptr_cmp.c -- Point to an optimal byte-comparison function @item -queues.c -- Handle priority queues as in Robert Sedgewick's book +queues.c -- Handle priority queues as in Robert Sedgewick's book @item raid2.c -- RAID support (the true implementation is in raid.cc) @item -rijndael.c -- "Optimised ANSI C code for the Rijndael cipher (now -AES") +rijndael.c -- "Optimised ANSI C code for the Rijndael cipher (now AES") @item -safemalloc.c -- A version of the standard malloc() with safety -checking +safemalloc.c -- A version of the standard malloc() with safety checking @item -sha1.c -- Implementation of Secure Hashing Algorithm 1 +sha1.c -- Implementation of Secure Hashing Algorithm 1 @item -string.c -- Initialize/append/free dynamically-sized strings +string.c -- Initialize/append/free dynamically-sized strings; see also sql_string.cc in the /sql directory @item -testhash.c -- Standalone program: test the hash library routines +testhash.c -- Standalone program: test the hash library routines @item -test_charset.c -- Standalone program: display character set -information +test_charset.c -- Standalone program: display character set information @item -test_dir.c -- Standalone program: placeholder for "test all -functions" idea +test_dir.c -- Standalone program: placeholder for "test all functions" idea @item -test_fn.c -- Standalone program: apparently tests a function +test_fn.c -- Standalone program: apparently tests a function @item -test_xml.c -- Standalone program: test XML routines +test_xml.c -- Standalone program: test XML routines @item -thr_alarm.c -- Thread alarms and signal handling +thr_alarm.c -- Thread alarms and signal handling @item -thr_lock.c -- "Read and write locks for Posix threads" +thr_lock.c -- "Read and write locks for Posix threads" @item -thr_mutex.c -- A wrapper for mutex functions +thr_mutex.c -- A wrapper for mutex functions @item -thr_rwlock.c -- Synchronizes the readers' thread locks with the -writer's lock +thr_rwlock.c -- Synchronizes the readers' thread locks with the writer's lock @item -tree.c -- Initialize/search/free binary trees +tree.c -- Initialize/search/free binary trees @item -typelib.c -- Determine what type a field has +typelib.c -- Find a string in a set of strings; returns the offset to the string found @end itemize @*@* You can find documentation for the main functions in these files -elsewhere in this document. -For example, the main functions in my_getwd.c are described thus: +elsewhere in this document. For example, the main functions in my_getwd.c +are described thus: @*@* @example @@ -4399,15 +4194,15 @@ testing. These are the five *.c files, all from Novell Inc.: @itemize @bullet @item -libmysqlmain.c -- Only one function: init_available_charsets() +libmysqlmain.c -- Only one function: init_available_charsets() @item -my_manage.c -- Standalone management utility +my_manage.c -- Standalone management utility @item -mysql_install_db.c -- Compare \scripts\mysql_install_db.sh +mysql_install_db.c -- Compare \scripts\mysql_install_db.sh @item -mysql_test_run.c -- Short test program +mysql_test_run.c -- Short test program @item -mysqld_safe.c -- Compare \scripts\mysqld_safe.sh +mysqld_safe.c -- Compare \scripts\mysqld_safe.sh @end itemize Perhaps the most important file is: @@ -4419,16 +4214,16 @@ netware.patch -- NetWare-specific build instructions and switches @*@* For instructions about basic installation, see "Deployment Guide For -NetWare AMP" at: +NetWare AMP" at: @url{http://developer.novell.com/ndk/whitepapers/namp.htm} @* @subsection NEW-RPMS -New "RPM Package Manager" files. +Directory to place RPMs while making a distribution. @*@* -This directory is not part of the Windows distribution. It is +This directory is not part of the Windows distribution. It is a temporary directory used during RPM builds with Linux distributions. @*@* @@ -4442,10 +4237,10 @@ people from outside MySQL: Yuri Dario, Timo Maier, and John M Alfredsson. There are no .C program files in this directory. @*@* -The contents of \os2 are: +The contents of \os2 are: @itemize @bullet @item -A Readme.Txt file +A Readme.Txt file @item An \include subdirectory containing .h files which are for OS/2 only @item @@ -4460,7 +4255,7 @@ there have been no updates for MySQL 4.0 for this section. @subsection pstack -Process stack display. +Process stack display (not currently used). @*@* This is a set of publicly-available debugging aids which all do pretty @@ -4478,7 +4273,7 @@ and it crashes. @subsection regex -Regular Expression library for support of REGEXP function. +Henry Spencer's Regular Expression library for support of REGEXP function. @*@* This is the copyrighted product of Henry Spencer from the University @@ -4504,7 +4299,7 @@ This program calls the 'regcomp' function, which is the entry point in @subsection SCCS -Source Code Control System. +Source Code Control System (not part of source distribution). @*@* You will see this directory if and only if you used BitKeeper for @@ -4514,10 +4309,10 @@ administration and are not of interest to application programmers. @subsection scripts -SQL batches, e.g. for converting msql to MySQL. +SQL batches, e.g. mysqlbug and mysql_install_db. @*@* -The *.sh filename extension stands for "shell script". Linux +The *.sh filename extension stands for "shell script". Linux programmers use it where Windows programmers would use a *.bat (batch filename extension). @*@* @@ -4525,23 +4320,23 @@ programmers use it where Windows programmers would use a *.bat The *.sh files on this directory are: @itemize @bullet @item -fill_help_tables.sh -- Create help-information tables and insert +fill_help_tables.sh -- Create help-information tables and insert @item make_binary_distribution.sh -- Get configure information, make, produce tar @item -msql2mysql.sh -- Convert mSQL programs and scripts to MySQL, partly +msql2mysql.sh -- Convert (partly) mSQL programs and scripts to MySQL @item -mysqlbug.sh -- Create a bug report and mail it +mysqlbug.sh -- Create a bug report and mail it @item -mysqld_multi.sh -- Start/stop any number of mysqld instances +mysqld_multi.sh -- Start/stop any number of mysqld instances @item -mysqld_safe-watch.sh -- Start/restart in safe mode +mysqld_safe-watch.sh -- Start/restart in safe mode @item -mysqld_safe.sh -- Start/restart in safe mode +mysqld_safe.sh -- Start/restart in safe mode @item -mysqldumpslow.sh -- Parse and summarize the slow query log +mysqldumpslow.sh -- Parse and summarize the slow query log @item -mysqlhotcopy.sh -- Hot backup +mysqlhotcopy.sh -- Hot backup @item mysql_config.sh -- Get configuration information that might be needed to compile a client @item @@ -4553,15 +4348,14 @@ mysql_find_rows.sh -- Search for queries containing @item mysql_fix_extensions.sh -- Renames some file extensions, not recommended @item -mysql_fix_privilege_tables.sh -- Fix mysql.user etc. if upgrading to MySQL 3.23.14+ +mysql_fix_privilege_tables.sh -- Fix mysql.user etc. when upgrading. Can be safely run during any upgrade to get the newest +MySQL privilege tables @item mysql_install_db.sh -- Create privilege tables and func table @item -mysql_secure_installation.sh -- Disallow remote root login, -eliminate test, etc. +mysql_secure_installation.sh -- Disallow remote root login, eliminate test, etc. @item -mysql_setpermission.sh -- Aid to add users or databases, sets -privileges +mysql_setpermission.sh -- Aid to add users or databases, sets privileges @item mysql_tableinfo.sh -- Puts info re MySQL tables into a MySQL table @item @@ -4577,91 +4371,90 @@ Programs for handling SQL commands. The "core" of MySQL. These are the .c and .cc files in the sql directory: @itemize @bullet @item -cache_manager.cc -- manages a number of blocks +convert.cc -- convert tables between different character sets @item -convert.cc -- convert tables between different character sets +derror.cc -- read language-dependent message file @item -derror.cc -- read language-dependent message file +des_key_file.cc -- load DES keys from plaintext file @item -des_key_file.cc -- load DES keys from plaintext file -@item -field.cc -- "implement classes defined in field.h" (long) +field.cc -- "implement classes defined in field.h" (long); defines all storage methods MySQL uses to store field information +into records that are then passed to handlers @item field_conv.cc -- functions to copy data between fields @item filesort.cc -- sort a result set, using memory or temporary files @item -frm_crypt.cc -- contains only one short function: get_crypt_for_frm +frm_crypt.cc -- contains only one short function: get_crypt_for_frm @item -gen_lex_hash.cc -- Knuth's algorithm from Vol 3 Sorting and Searching, Chapter 6.3 +gen_lex_hash.cc -- Knuth's algorithm from Vol 3 Sorting and Searching, Chapter 6.3; used to search for SQL keywords in a query @item gstream.cc -- GTextReadStream, used to read GIS objects @item -handler.cc -- handler-calling functions +handler.cc -- handler-calling functions @item -hash_filo.cc -- static-sized hash tables +hash_filo.cc -- static-sized hash tables, used to store info like hostname -> ip tables in a FIFO manner @item -ha_berkeley.cc -- Handler: BDB +ha_berkeley.cc -- Handler: BDB @item -ha_heap.cc -- Handler: Heap +ha_heap.cc -- Handler: Heap @item -ha_innodb.cc -- Handler: InnoDB +ha_innodb.cc -- Handler: InnoDB @item -ha_isam.cc -- Handler: ISAM +ha_isam.cc -- Handler: ISAM @item ha_isammrg.cc -- Handler: (ISAM MERGE) @item -ha_myisam.cc -- Handler: MyISAM +ha_myisam.cc -- Handler: MyISAM @item ha_myisammrg.cc -- Handler: (MyISAM MERGE) @item -hostname.cc -- Given IP, return hostname +hostname.cc -- Given IP, return hostname @item -init.cc -- Init and dummy functions for interface with unireg +init.cc -- Init and dummy functions for interface with unireg @item -item.cc -- Item functions +item.cc -- Item functions @item -item_buff.cc -- Buffers to save and compare item values +item_buff.cc -- Buffers to save and compare item values @item -item_cmpfunc.cc -- Definition of all compare functions +item_cmpfunc.cc -- Definition of all compare functions @item -item_create.cc -- Create an item. Used by lex.h. +item_create.cc -- Create an item. Used by lex.h. @item -item_func.cc -- Numerical functions +item_func.cc -- Numerical functions @item -item_row.cc -- Row items for comparing rows and for IN on rows +item_row.cc -- Row items for comparing rows and for IN on rows @item item_sum.cc -- Set functions (SUM, AVG, etc.) @item -item_strfunc.cc -- String functions +item_strfunc.cc -- String functions @item -item_subselect.cc -- Item subselect +item_subselect.cc -- Item subselect @item -item_timefunc.cc -- Date/time functions, e.g. week of year +item_timefunc.cc -- Date/time functions, e.g. week of year @item item_uniq.cc -- Empty file, here for compatibility reasons @item -key.cc -- Functions to handle keys and fields in forms +key.cc -- Functions to create keys from records and compare a key to a key in a record @item -lock.cc -- Locks +lock.cc -- Locks @item -log.cc -- Logs +log.cc -- Logs @item -log_event.cc -- Log event +log_event.cc -- Log event @item -matherr.c -- Handling overflow, underflow, etc. +matherr.c -- Handling overflow, underflow, etc. @item mf_iocache.cc -- Caching of (sequential) reads and writes @item -mini_client.cc -- Client included in server for server-server messaging +mini_client.cc -- Client included in server for server-server messaging; used by the replication code @item -mysqld.cc -- Source of mysqld.exe +mysqld.cc -- Source of mysqld.exe; includes the main() program that starts mysqld, handling of signals and connections @item -my_lock.c -- Lock part of a file +my_lock.c -- Lock part of a file (like /mysys/my_lock.c, but with timeout handling for threads) @item -net_serv.cc -- Read/write of packets on a network socket +net_serv.cc -- Read/write of packets on a network socket @item -nt_servc.cc -- Initialize/register/remove an NT service +nt_servc.cc -- Initialize/register/remove an NT service @item opt_ft.cc -- Create a FT or QUICK RANGE based on a key (very short) @item @@ -4671,9 +4464,9 @@ opt_sum.cc -- Optimize functions in presence of (implied) GROUP BY @item password.c -- Password checking @item -procedure.cc -- Procedure +procedure.cc -- Procedure interface, as used in SELECT * FROM Table_name PROCEDURE ANALYSE @item -protocol.cc -- Low level functions for storing data to be sent to client +protocol.cc -- Low level functions for PACKING data that is sent to client; actual sending done with net_serv.cc @item records.cc -- Functions for easy reading of records, possible through a cache @item @@ -4685,15 +4478,15 @@ slave.cc -- Procedures for a slave in a master/slave (replication) relation @item spatial.cc -- Geometry stuff (lines, points, etc.) @item -sql_acl.cc -- Functions related to ACL security +sql_acl.cc -- Functions related to ACL security; checks, stores, retrieves, and deletes MySQL user level privileges @item -sql_analyse.cc -- Analyse an input string (?) +sql_analyse.cc -- Implements the PROCEDURE analyse, which analyses a query result and returns the 'optimal' data type for each result column @item sql_base.cc -- Basic functions needed by many modules @item sql_cache.cc -- SQL query cache, with long comments about how caching works @item -sql_class.cc -- SQL class +sql_class.cc -- SQL class; implements the SQL base classes, of which THD (THREAD object) is the most important @item sql_crypt.cc -- Encode / decode, very short @item @@ -4707,63 +4500,62 @@ sql_do.cc -- The DO statement @item sql_error.cc -- Errors and warnings @item -sql_handler.cc -- Direct access to ISAM +sql_handler.cc -- Implements the HANDLER interface, which gives direct access to rows in MyISAM and InnoDB @item -sql_help.cc -- The HELP statement (if there is one?) +sql_help.cc -- The HELP statement @item sql_insert.cc -- The INSERT statement @item -sql_lex.cc -- Related to lex or yacc +sql_lex.cc -- Does lexical analysis of a query; i.e. breaks a query string into pieces and determines the basic type (number, +string, keyword, etc.) of each piece @item -sql_list.cc -- Only list_node_end_of_list, short +sql_list.cc -- Only list_node_end_of_list, short (the rest of the list class is implemented in sql_list.h) @item -sql_load.cc -- The LOAD DATA statement? +sql_load.cc -- The LOAD DATA statement @item -sql_map.cc -- Memory-mapped files? +sql_map.cc -- Memory-mapped files (not yet in use) @item -sql_manager.cc -- Maintenance tasks, e.g. flushing the buffers -periodically +sql_manager.cc -- Maintenance tasks, e.g. flushing the buffers periodically @item -sql_olap.cc -- ROLLUP +sql_olap.cc -- ROLLUP @item -sql_parse.cc -- Parse an SQL statement +sql_parse.cc -- Parse an SQL statement; do initial checks and then jump to the function that should execute the statement @item -sql_prepare.cc -- Prepare an SQL statement +sql_prepare.cc -- Prepare an SQL statement @item -sql_repl.cc -- Replication +sql_repl.cc -- Replication @item -sql_rename.cc -- Rename table +sql_rename.cc -- Rename table @item -sql_select.cc -- Select and join optimisation +sql_select.cc -- Select and join optimisation @item -sql_show.cc -- The SHOW statement +sql_show.cc -- The SHOW statement @item -sql_string.cc -- String functions: alloc, realloc, copy, convert, -etc. +sql_string.cc -- String functions: alloc, realloc, copy, convert, etc. @item -sql_table.cc -- The DROP TABLE and ALTER TABLE statements +sql_table.cc -- The DROP TABLE and ALTER TABLE statements @item -sql_test.cc -- Some debugging information +sql_test.cc -- Some debugging information @item -sql_udf.cc -- User-defined functions +sql_udf.cc -- User-defined functions @item -sql_union.cc -- The UNION operator +sql_union.cc -- The UNION operator @item -sql_update.cc -- The UPDATE statement +sql_update.cc -- The UPDATE statement @item -stacktrace.c -- Display stack trace (Linux/Intel only?) +stacktrace.c -- Display stack trace (Linux/Intel only) @item -table.cc -- Table metadata retrieval, mostly +table.cc -- Table metadata retrieval; read the table definition from a .frm file and store it in a TABLE object @item -thr_malloc.cc -- Mallocs used in threads +thr_malloc.cc -- Thread-safe interface to /mysys/my_alloc.c @item -time.cc -- Date and time functions +time.cc -- Date and time functions @item -udf_example.cc -- Example file of user-defined functions +udf_example.cc -- Example file of user-defined functions @item -uniques.cc -- Function to handle quick removal of duplicates +uniques.cc -- Function to handle quick removal of duplicates @item -unireg.cc -- Create a unireg form file from a FIELD and field-info struct +unireg.cc -- Create a unireg form file (.frm) from a FIELD and field-info struct @end itemize @*@* @@ -4781,17 +4573,15 @@ available all the material necessary to reproduce all the tests. There are five subdirectories and sub-subdirectories: @itemize @bullet @item -\Comments -- Comments about results from tests of Access, Adabas, -etc. +\Comments -- Comments about results from tests of Access, Adabas, etc. @item -\Data\ATIS -- .txt files containing input data for the "ATIS" tests +\Data\ATIS -- .txt files containing input data for the "ATIS" tests @item -\Data\Wisconsin -- .txt files containing input data for the -"Wisconsin" tests +\Data\Wisconsin -- .txt files containing input data for the "Wisconsin" tests @item -\Results -- old test results +\Results -- old test results @item -\Results-win32 -- old test results from Windows 32-bit tests +\Results-win32 -- old test results from Windows 32-bit tests @end itemize @*@* @@ -4807,7 +4597,8 @@ There is one README file and one TODO file. @subsection SSL -Secure Sockets Layer. +Secure Sockets Layer; includes an example certification one can use +test an SSL (secure) database connection. @*@* This isn't a code directory. It contains a short note from Tonu Samuel @@ -4836,7 +4627,7 @@ recent Pentium class processors, though. The .C files are: @itemize @bullet @item -atof.c -- ascii-to-float, MySQL version +atof.c -- ascii-to-float, MySQL version @item bchange.c -- short replacement routine written by Monty Widenius in 1987 @@ -4885,7 +4676,7 @@ r_strinstr.c -- see if one string is within another @item str2int.c -- convert string to integer @item -strappend.c -- append one string to another +strappend.c -- fill up a string to n characters @item strcat.c -- concatenate strings @item @@ -4905,11 +4696,11 @@ strinstr.c -- find string within string @item strlen.c -- return length of string in bytes @item -strmake.c -- move n characters, or move till end +strmake.c -- create new string from old string with fixed length, append end \0 if needed @item -strmov.c -- move source to dest and return pointer to end +strmov.c -- move source to dest and return pointer to end @item -strnlen.c -- return length of string, or return n +strnlen.c -- return min(length of string, n) @item strnmov.c -- move source to dest for source size, or for n bytes @item @@ -4933,9 +4724,9 @@ strxnmov.c -- like strxmov.c but with a maximum length n @item str_test.c -- test of all the string functions encoded in assembler @item -udiv.c -- unsigned long divide +udiv.c -- unsigned long divide, for operating systems that don't support these @item -xml.c -- read and parse XML strings +xml.c -- read and parse XML strings; used to read character definition information stored in /sql/share/charsets @end itemize @*@* @@ -4947,17 +4738,19 @@ members of the Intel processor family. @subsection support-files -Support files. +Files used to build MySQL on different systems. @*@* The files here are for building ("making") MySQL given a package manager, compiler, linker, and other build tools. The support files -provide instructions and switches for the build processes. +provide instructions and switches for the build processes. They +include example my.cnf files one can use as a default setup for +MySQL. @*@* @subsection tests -Tests in Perl. +Tests in Perl and in C. @*@* These are tests that were run once to check for bugs in various @@ -4972,7 +4765,8 @@ Tools -- well, actually, one tool. The only file is: @itemize @bullet @item -mysqlmanager.c -- A "server management daemon" by Sasha Pachev +mysqlmanager.c -- A "server management daemon" by Sasha Pachev. This +is a tool under development and is not yet useful. @end itemize @*@* @@ -4984,7 +4778,12 @@ Visual C++ Files. Includes this entire directory, repeated for VC++ (Windows) use. @*@* -VC++Files has subdirectories which are copies of the main directories. +VC++Files includes a complete environment to compile MySQL with the VC++ +compiler. To use it, just copy the files on this directory; the make_win_src_distribution.sh +script uses these files to create a Windows source installation. +@*@* + +This directory has subdirectories which are copies of the main directories. For example there is a subdirectory \VC++Files\heap, which has the same files as \heap. So for a description of the files in \VC++Files\heap, see the description of the files in \heap. The same @@ -4999,54 +4798,60 @@ directories", VC++Files contains these subdirectories, which are not duplicates: @itemize @bullet @item -comp_err -- (nearly empty) +comp_err -- (nearly empty) @item -contrib -- (nearly empty) +contrib -- (nearly empty) @item -InstallShield script files +InstallShield -- script files @item -isamchk -- (nearly empty) +isamchk -- (nearly empty) @item -libmysqltest -- one small non-MySQL test program: mytest.c +libmysqltest -- one small non-MySQL test program: mytest.c @item -myisamchk -- (nearly empty) +myisamchk -- (nearly empty) @item -myisamlog -- (nearly empty) +myisamlog -- (nearly empty) @item -myisammrg -- (nearly empty) +myisammrg -- (nearly empty) @item -mysqlbinlog -- (nearly empty) +mysqlbinlog -- (nearly empty) @item -mysqlmanager -- MFC foundation class files created by AppWizard +mysqlmanager -- MFC foundation class files created by AppWizard @item -mysqlserver -- (nearly empty) +mysqlserver -- (nearly empty) @item -mysqlshutdown -- one short program, mysqlshutdown.c +mysqlshutdown -- one short program, mysqlshutdown.c @item -mysqlwatch.c -- Windows service initialization and monitoring +mysqlwatch.c -- Windows service initialization and monitoring @item -my_print_defaults -- (nearly empty) +my_print_defaults -- (nearly empty) @item -pack_isam -- (nearly empty) +pack_isam -- (nearly empty) @item -perror -- (nearly empty) +perror -- (nearly empty) @item -prepare -- (nearly empty) +prepare -- (nearly empty) @item -replace -- (nearly empty) +replace -- (nearly empty) @item -SCCS -- source code control system +SCCS -- source code control system @item -test1 -- tests connecting via X threads +test1 -- tests connecting via X threads @item -thr_insert_test -- (nearly empty) +thr_insert_test -- (nearly empty) @item thr_test -- one short program used to test for memory-allocation bug @item -winmysqladmin -- the winmysqladmin.exe source. machine-generated? +winmysqladmin -- the winmysqladmin.exe source. machine-generated? @end itemize @*@* +The "nearly empty" subdirectories noted above (e.g. comp_err and isamchk) +are needed because VC++ requires one directory per project (i.e. executable). +We are trying to keep to the MySQL standard source layout and compile only +to different directories. +@*@* + @subsection vio Virtual I/O Library. @@ -5094,7 +4899,12 @@ obsolete. @subsection zlib -Data compression library. +Data compression library, used on Windows. +@*@* + +zlib is a data compression library used to support the compressed +protocol and the COMPRESS/UNCOMPRESS functions under Windows. +On Unix, MySQL uses the system libgz.a library for this purpose. @*@* Zlib -- which presumably stands for "Zip Library" -- is not a MySQL From 5e8f76c433f90b0c72b48f0ed587f7c9dd7113a4 Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Sat, 26 Apr 2003 18:58:55 -0700 Subject: [PATCH 104/188] Update PeterG's internals documentation per comments from Monty; minor changes only. --- Docs/internals.texi | 59 ++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index 5c2070abb9c..709dbc4b068 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -3286,17 +3286,11 @@ server. The C program files in the directory are: @itemize @bullet @item -connect_test.c -- test that a connect is possible -@item get_password.c -- ask for a password from the console @item -insert_test.c -- test that an insert is possible -@item -list_test.c -- test that a select is possible -@item mysql.cc -- "The MySQL command tool" @item -mysqladmin.c -- maintenance of MYSQL databases +mysqladmin.c -- maintenance of MySQL databases @item mysqlcheck.c -- check all databases, check connect, etc. @item @@ -3313,14 +3307,6 @@ mysqlshow.c -- show databases, tables or columns mysqltest.c -- test program used by the mysql-test suite, mysql-test-run @item password.c -- password checking routines (version 4.1 and up) -@item -select_test.c -- test that a select is possible -@item -showdb_test.c -- test that a show-databases is possible -@item -ssl_test.c -- test that SSL is possible -@item -thread_test.c -- test that threading is possible @end itemize @*@* @@ -4440,7 +4426,7 @@ lock.cc -- Locks @item log.cc -- Logs @item -log_event.cc -- Log event +log_event.cc -- Log event (a binary log consists of a stream of log events) @item matherr.c -- Handling overflow, underflow, etc. @item @@ -4482,7 +4468,7 @@ sql_acl.cc -- Functions related to ACL security; checks, stores, retrieves, an @item sql_analyse.cc -- Implements the PROCEDURE analyse, which analyses a query result and returns the 'optimal' data type for each result column @item -sql_base.cc -- Basic functions needed by many modules +sql_base.cc -- Basic functions needed by many modules, like opening and closing tables with table cache management @item sql_cache.cc -- SQL query cache, with long comments about how caching works @item @@ -4515,7 +4501,7 @@ sql_load.cc -- The LOAD DATA statement @item sql_map.cc -- Memory-mapped files (not yet in use) @item -sql_manager.cc -- Maintenance tasks, e.g. flushing the buffers periodically +sql_manager.cc -- Maintenance tasks, e.g. flushing the buffers periodically; used with BDB table logs @item sql_olap.cc -- ROLLUP @item @@ -4753,8 +4739,26 @@ MySQL. Tests in Perl and in C. @*@* -These are tests that were run once to check for bugs in various -scenarios: forks, locks, big records, exporting, truncating, etc. +The files in this directory are test programs that can be used +as a base to write a program to simulate problems in MySQL in various +scenarios: forks, locks, big records, exporting, truncating, and so on. +Some examples are: +@itemize @bullet +@item +connect_test.c -- test that a connect is possible +@item +insert_test.c -- test that an insert is possible +@item +list_test.c -- test that a select is possible +@item +select_test.c -- test that a select is possible +@item +showdb_test.c -- test that a show-databases is possible +@item +ssl_test.c -- test that SSL is possible +@item +thread_test.c -- test that threading is possible +@end itemize @*@* @subsection tools @@ -4765,8 +4769,9 @@ Tools -- well, actually, one tool. The only file is: @itemize @bullet @item -mysqlmanager.c -- A "server management daemon" by Sasha Pachev. This -is a tool under development and is not yet useful. +mysqlmanager.c -- A "server management daemon" by Sasha Pachev. This +is a tool under development and is not yet useful. Related to fail-safe +replication. @end itemize @*@* @@ -4784,10 +4789,10 @@ script uses these files to create a Windows source installation. @*@* This directory has subdirectories which are copies of the main directories. -For example there is a subdirectory \VC++Files\heap, which has the -same files as \heap. So for a description of the files in -\VC++Files\heap, see the description of the files in \heap. The same -applies for almost all of VC++Files's subdirectories (bdb, client, +For example, there is a subdirectory \VC++Files\heap, which has the Microsoft +developer studio project file to compile \heap with VC++. So for a description +of the files in \VC++Files\heap, see the description of the files in \heap. The +same applies for almost all of VC++Files's subdirectories (bdb, client, isam, libmysql, etc.). The difference is that the \VC++Files variants are specifically for compilation with Microsoft Visual C++ in 32-bit Windows environments. @@ -4842,7 +4847,7 @@ thr_insert_test -- (nearly empty) @item thr_test -- one short program used to test for memory-allocation bug @item -winmysqladmin -- the winmysqladmin.exe source. machine-generated? +winmysqladmin -- the winmysqladmin.exe source @end itemize @*@* From a1861ddb2215aad22f24b83dc2f7e48a25068051 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 27 Apr 2003 17:25:39 +0300 Subject: [PATCH 105/188] trx0trx.h, trx0trx.c, ha_innodb.cc: Remove code never actually used in IGNORE; InnoDB just rolls back the latest row insert or update on a duplicate key error and leaves it for MySQL to decide whether to ignore the error --- innobase/include/trx0trx.h | 4 ---- innobase/trx/trx0trx.c | 2 -- sql/ha_innodb.cc | 9 --------- 3 files changed, 15 deletions(-) diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 34f820f03e7..be96519c4ea 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -418,10 +418,6 @@ struct trx_struct{ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also in the lock list trx_locks */ - ibool ignore_duplicates_in_insert; - /* in an insert roll back only insert - of the latest row in case - of a duplicate key error */ UT_LIST_NODE_T(trx_t) trx_list; /* list of transactions */ UT_LIST_NODE_T(trx_t) diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 38d15866769..4ce2236f78a 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -102,8 +102,6 @@ trx_create( trx->mysql_master_log_file_name = (char*) ""; trx->mysql_master_log_pos = 0; - trx->ignore_duplicates_in_insert = FALSE; - mutex_create(&(trx->undo_mutex)); mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 1363227605e..1ea8b91a978 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1911,13 +1911,6 @@ ha_innobase::write_row( build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW); } - if (user_thd->lex.sql_command == SQLCOM_INSERT - && user_thd->lex.duplicates == DUP_IGNORE) { - prebuilt->trx->ignore_duplicates_in_insert = TRUE; - } else { - prebuilt->trx->ignore_duplicates_in_insert = FALSE; - } - srv_conc_enter_innodb(prebuilt->trx); error = row_insert_for_mysql((byte*) record, prebuilt); @@ -1958,8 +1951,6 @@ ha_innobase::write_row( } } - prebuilt->trx->ignore_duplicates_in_insert = FALSE; - error = convert_error_code_to_mysql(error, user_thd); /* Tell InnoDB server that there might be work for From dd377bfba62b5f9d8bc43b9d2fdaddbc4107d6e9 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Sun, 27 Apr 2003 22:12:08 +0300 Subject: [PATCH 106/188] Fixed problem when comparing a key for a multi-byte-character set. (bug 152) Use 0x.... as strings if 'new' mode. (bug 152) Don't report -max on windows when InnoDB is enabled. (bug 332) Reset current_linfo; This could cause a hang when doing PURGE LOGS. Fix for row numbers in EXPLAIN (bug 322) Fix that USE_FRM works for all table types (bug 97) --- VC++Files/libmysql/libmysql.dsp | 22 +++++++---- myisam/mi_key.c | 23 +++++++++-- myisam/mi_range.c | 3 +- myisam/mi_rkey.c | 33 +++++++++++----- myisam/mi_search.c | 31 +++++++++++++++ myisam/mi_test2.c | 12 +++--- myisam/myisamdef.h | 4 +- myisam/sort.c | 6 +-- mysql-test/r/ctype_latin1_de.result | 52 +++++++++++++++++++++++++ mysql-test/r/join.result | 8 ++++ mysql-test/r/repair.result | 6 ++- mysql-test/r/rpl_alter.result | 22 +++++------ mysql-test/t/ctype_latin1_de-master.opt | 3 +- mysql-test/t/ctype_latin1_de.test | 23 +++++++++++ mysql-test/t/repair.test | 4 +- sql/field.cc | 25 +++++++++++- sql/item.cc | 8 ++++ sql/item.h | 2 +- sql/mysqld.cc | 4 +- sql/sql_analyse.cc | 1 - sql/sql_insert.cc | 2 +- sql/sql_repl.cc | 3 ++ sql/sql_select.cc | 3 ++ sql/sql_table.cc | 30 +++++++++++--- sql/sql_yacc.yy | 6 +-- 25 files changed, 274 insertions(+), 62 deletions(-) diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp index bddf1988e03..43dee62061f 100644 --- a/VC++Files/libmysql/libmysql.dsp +++ b/VC++Files/libmysql/libmysql.dsp @@ -25,7 +25,7 @@ CFG=libmysql - Win32 Debug # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" -CPP=cl.exe +CPP=xicl6.exe MTL=midl.exe RSC=rc.exe @@ -52,14 +52,14 @@ RSC=rc.exe BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=link.exe +LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 # ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" -PostBuild_Desc=Copy .lib file -PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release\ +PostBuild_Desc=Move DLL export lib +PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release /y # End Special Build Tool !ELSEIF "$(CFG)" == "libmysql - Win32 Debug" @@ -85,14 +85,14 @@ PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release\ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=link.exe +LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" -PostBuild_Desc=Copy .lib file -PostBuild_Cmds=xcopy ..\lib_debug\libmysql.dll C:\winnt\system32\ xcopy debug\libmysql.lib ..\lib_debug\ +PostBuild_Desc=Move DLL export lib +PostBuild_Cmds=xcopy ..\lib_debug\libmysql.dll C:\winnt\system32\ /y xcopy debug\libmysql.lib ..\lib_debug\ /y # End Special Build Tool !ENDIF @@ -239,6 +239,10 @@ SOURCE=..\mysys\mf_pack.c # End Source File # Begin Source File +SOURCE=..\mysys\mf_path.c +# End Source File +# Begin Source File + SOURCE=..\mysys\mf_unixpath.c # End Source File # Begin Source File @@ -395,6 +399,10 @@ SOURCE=..\client\select_test.c # End Source File # Begin Source File +SOURCE=..\mysys\sha1.c +# End Source File +# Begin Source File + SOURCE=..\client\sql_string.cpp # End Source File # Begin Source File diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 9ec1ca99e0e..5b167cc9ab0 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -136,11 +136,26 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, } /* _mi_make_key */ - /* Pack a key to intern format from given format (c_rkey) */ - /* returns length of packed key */ +/* + Pack a key to intern format from given format (c_rkey) + + SYNOPSIS + _mi_pack_key() + info MyISAM handler + uint keynr key number + key Store packed key here + old Not packed key + k_length Length of 'old' to use + last_used_keyseg out parameter. May be NULL + + RETURN + length of packed key + + last_use_keyseg Store pointer to the keyseg after the last used one +*/ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, - uint k_length) + uint k_length, MI_KEYSEG **last_used_keyseg) { uint length; uchar *pos,*end,*start_key=key; @@ -211,6 +226,8 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, key+= length; k_length-=length; } + if (last_used_keyseg) + *last_used_keyseg= keyseg; #ifdef NOT_USED if (keyseg->type) diff --git a/myisam/mi_range.c b/myisam/mi_range.c index 70694bf4620..8e85afc5f80 100644 --- a/myisam/mi_range.c +++ b/myisam/mi_range.c @@ -83,7 +83,8 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len, if (key_len == 0) key_len=USE_WHOLE_KEY; key_buff=info->lastkey+info->s->base.max_key_length; - key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len); + key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len, + (MI_KEYSEG**) 0); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg, (uchar*) key_buff,key_len);); nextflag=myisam_read_vec[search_flag]; diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 86547d3ef04..60dec0449a0 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -23,10 +23,12 @@ /* Ordinary search_flag is 0 ; Give error if no record with key */ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, - enum ha_rkey_function search_flag) + enum ha_rkey_function search_flag) { uchar *key_buff; MYISAM_SHARE *share=info->s; + MI_KEYDEF *keyinfo; + MI_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; DBUG_ENTER("mi_rkey"); DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d", @@ -36,23 +38,27 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, DBUG_RETURN(my_errno); info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); + keyinfo= share->keyinfo + inx; if (!info->use_packed_key) { if (key_len == 0) key_len=USE_WHOLE_KEY; key_buff=info->lastkey+info->s->base.max_key_length; - pack_key_length=_mi_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len); - info->last_rkey_length=pack_key_length; - DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,share->keyinfo[inx].seg, - key_buff,pack_key_length);); + pack_key_length=_mi_pack_key(info, (uint) inx, key_buff, (uchar*) key, + key_len, &last_used_keyseg); + DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg, + key_buff, pack_key_length);); } else { - /* key is already packed! */ + /* + key is already packed!; This happens when we are using a MERGE TABLE + */ key_buff=info->lastkey+info->s->base.max_key_length; - info->last_rkey_length=pack_key_length=key_len; + pack_key_length= key_len; bmove(key_buff,key,key_len); + last_used_keyseg= 0; } if (fast_mi_readinfo(info)) @@ -65,8 +71,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) use_key_length=USE_WHOLE_KEY; - if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length, - myisam_read_vec[search_flag],info->s->state.key_root[inx])) + if (!_mi_search(info,keyinfo, key_buff, use_key_length, + myisam_read_vec[search_flag], info->s->state.key_root[inx])) { while (info->lastpos >= info->state->data_file_length) { @@ -76,7 +82,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, exact key, because the keys are sorted according to position */ - if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey, + if (_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length, myisam_readnext_vec[search_flag], info->s->state.key_root[inx])) @@ -86,6 +92,12 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); + /* Calculate length of the found key; Used by mi_rnext_same */ + if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg) + info->last_rkey_length= _mi_keylength_part(keyinfo, info->lastkey, + last_used_keyseg); + else + info->last_rkey_length= pack_key_length; if (!buf) DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); @@ -99,6 +111,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, /* Store key for read next */ memcpy(info->lastkey,key_buff,pack_key_length); + info->last_rkey_length= pack_key_length; bzero((char*) info->lastkey+pack_key_length,info->s->base.rec_reflength); info->lastkey_length=pack_key_length+info->s->base.rec_reflength; diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 41d53e76241..32db69144d8 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -1441,6 +1441,37 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key) } /* _mi_keylength */ +/* + Calculate length of part key. + + Used in mi_rkey() to find the key found for the key-part that was used. + This is needed in case of multi-byte character sets where we may search + after '0xDF' but find 'ss' +*/ + +uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key, + MI_KEYSEG *end) +{ + reg1 MI_KEYSEG *keyseg; + uchar *start= key; + + for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++) + { + if (keyseg->flag & HA_NULL_PART) + if (!*key++) + continue; + if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH)) + { + uint length; + get_key_length(length,key); + key+=length; + } + else + key+= keyseg->length; + } + return (uint) (key-start); +} + /* Move a key */ uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from) diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c index 93538e3ead7..e3a2ecfbb1f 100644 --- a/myisam/mi_test2.c +++ b/myisam/mi_test2.c @@ -639,14 +639,14 @@ int main(int argc, char *argv[]) if ((long) range_records < (long) records*7/10-2 || (long) range_records > (long) records*14/10+2) { - printf("mi_records_range for key: %d returned %ld; Should be about %ld\n", - i, range_records, records); + printf("mi_records_range for key: %d returned %lu; Should be about %lu\n", + i, (ulong) range_records, (ulong) records); goto end; } if (verbose && records) { - printf("mi_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n", - range_records,records, + printf("mi_records_range returned %lu; Exact is %lu (diff: %4.2g %%)\n", + (ulong) range_records, (ulong) records, labs((long) range_records-(long) records)*100.0/records); } @@ -660,8 +660,8 @@ int main(int argc, char *argv[]) || info.keys != keys) { puts("Wrong info from mi_info"); - printf("Got: records: %ld delete: %ld i_keys: %d\n", - info.records,info.deleted,info.keys); + printf("Got: records: %lu delete: %lu i_keys: %d\n", + (ulong) info.records, (ulong) info.deleted, info.keys); } if (verbose) { diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 7c035bc6097..7631b245b9b 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -505,6 +505,8 @@ extern uchar *_mi_get_last_key(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *keypos, extern uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, uchar *keypos, uint *return_key_length); extern uint _mi_keylength(MI_KEYDEF *keyinfo,uchar *key); +extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key, + MI_KEYSEG *end); extern uchar *_mi_move_key(MI_KEYDEF *keyinfo,uchar *to,uchar *from); extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, uint key_length,uint nextflag,my_off_t pos); @@ -519,7 +521,7 @@ extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo); extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key, const byte *record,my_off_t filepos); extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old, - uint key_length); + uint key_length, MI_KEYSEG **last_used_keyseg); extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf); extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos, uint length,int re_read_if_possibly); diff --git a/myisam/sort.c b/myisam/sort.c index ddf565d5092..224b4ad8420 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -163,8 +163,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (maxbuffer == 0) { if (!no_messages) - printf(" - Dumping %lu keys\n",records); - if (write_index(info,sort_keys,(uint) records)) + printf(" - Dumping %lu keys\n", (ulong) records); + if (write_index(info,sort_keys, (uint) records)) goto err; /* purecov: inspected */ } else @@ -173,7 +173,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (maxbuffer >= MERGEBUFF2) { if (!no_messages) - printf(" - Merging %lu keys\n",records); /* purecov: tested */ + printf(" - Merging %lu keys\n", (ulong) records); /* purecov: tested */ if (merge_many_buff(info,keys,sort_keys, dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile)) goto err; /* purecov: inspected */ diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result index b79bc67138c..630fef9b679 100644 --- a/mysql-test/r/ctype_latin1_de.result +++ b/mysql-test/r/ctype_latin1_de.result @@ -212,3 +212,55 @@ select * from t1 where match a against ("te*" in boolean mode)+0; a test drop table t1; +create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word)); +insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae'); +update t1 set word2=word; +select word, word=0xdf as t from t1 having t > 0; +word t +ß 1 +select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0; +word t +ss 1 +ß 1 +select * from t1 where word=0xDF; +word word2 +ß ß +select * from t1 where word=CAST(0xDF as CHAR); +word word2 +ss ss +ß ß +select * from t1 where word2=0xDF; +word word2 +ß ß +select * from t1 where word2=CAST(0xDF as CHAR); +word word2 +ss ss +ß ß +select * from t1 where word='ae'; +word word2 +ä ä +ae ae +select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR); +word word2 +ä ä +ae ae +select * from t1 where word between 0xDF and 0xDF; +word word2 +ß ß +select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR); +word word2 +ss ss +ß ß +select * from t1 where word like 'ae'; +word word2 +ae ae +select * from t1 where word like 'AE'; +word word2 +ae ae +select * from t1 where word like 0xDF; +word word2 +ß ß +select * from t1 where word like CAST(0xDF as CHAR); +word word2 +ß ß +drop table t1; diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 1b5766e3ab4..e063b5c3e02 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -273,8 +273,16 @@ cust 20 SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith'; rate_code base_rate cust 20 +drop table t1,t2; +CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, Value1 VARCHAR(255)); +CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255)); +INSERT INTO t1 VALUES (1, 'A'); +INSERT INTO t2 VALUES (1, 'B'); +SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B'); ID Value1 ID Value2 +SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B'; ID Value1 ID Value2 +SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1; ID Value1 ID Value2 drop table t1,t2; create table t1 (i int); diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index 8b50f9a92e8..adc09ded0e2 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -4,4 +4,8 @@ repair table t1 use_frm; Table Op Msg_type Msg_text test.t1 repair warning Number of rows changed from 0 to 1 test.t1 repair status OK -drop table if exists t1; +alter table t1 TYPE=HEAP; +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair error The handler for the table doesn't support repair +drop table t1; diff --git a/mysql-test/r/rpl_alter.result b/mysql-test/r/rpl_alter.result index 1dc73c6524a..729c7df6808 100644 --- a/mysql-test/r/rpl_alter.result +++ b/mysql-test/r/rpl_alter.result @@ -4,18 +4,18 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; slave start; -drop database if exists d1; -create database d1; -create table d1.t1 ( n int); -alter table d1.t1 add m int; -insert into d1.t1 values (1,2); -create table d1.t2 (n int); -insert into d1.t2 values (45); -rename table d1.t2 to d1.t3, d1.t1 to d1.t2; -select * from d1.t2; +drop database if exists test_$1; +create database test_$1; +create table test_$1.t1 ( n int); +alter table test_$1.t1 add m int; +insert into test_$1.t1 values (1,2); +create table test_$1.t2 (n int); +insert into test_$1.t2 values (45); +rename table test_$1.t2 to test_$1.t3, test_$1.t1 to test_$1.t2; +select * from test_$1.t2; n m 1 2 -select * from d1.t3; +select * from test_$1.t3; n 45 -drop database d1; +drop database test_$1; diff --git a/mysql-test/t/ctype_latin1_de-master.opt b/mysql-test/t/ctype_latin1_de-master.opt index 98accd58c46..895a62364d6 100644 --- a/mysql-test/t/ctype_latin1_de-master.opt +++ b/mysql-test/t/ctype_latin1_de-master.opt @@ -1 +1,2 @@ ---default-character-set=latin1_de +--default-character-set=latin1_de --new + diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test index 4b96f5f5867..6353650f420 100644 --- a/mysql-test/t/ctype_latin1_de.test +++ b/mysql-test/t/ctype_latin1_de.test @@ -45,3 +45,26 @@ select * from t1 where a like "test%"; select * from t1 where a like "te_t"; select * from t1 where match a against ("te*" in boolean mode)+0; drop table t1; + +# +# Test bug report #152 (problem with index on latin1_de) +# + +create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word)); +insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae'); +update t1 set word2=word; +select word, word=0xdf as t from t1 having t > 0; +select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0; +select * from t1 where word=0xDF; +select * from t1 where word=CAST(0xDF as CHAR); +select * from t1 where word2=0xDF; +select * from t1 where word2=CAST(0xDF as CHAR); +select * from t1 where word='ae'; +select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR); +select * from t1 where word between 0xDF and 0xDF; +select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR); +select * from t1 where word like 'ae'; +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; diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index 6d79014b23d..b901fb3467f 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -5,4 +5,6 @@ drop table if exists t1; create table t1 SELECT 1,"table 1"; repair table t1 use_frm; -drop table if exists t1; +alter table t1 TYPE=HEAP; +repair table t1 use_frm; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index eb7d3dc5686..a2663626723 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -162,6 +162,14 @@ static bool test_if_real(const char *str,int length) } +static inline uint field_length_without_space(const char *ptr, uint length) +{ + const char *end= ptr+length; + while (end > ptr && end[-1] == ' ') + end--; + return (uint) (end-ptr); +} + /**************************************************************************** ** Functions for the base classes ** This is an unpacked number. @@ -3673,8 +3681,21 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr) { if (binary_flag) return memcmp(a_ptr,b_ptr,field_length); - else - return my_sortcmp(a_ptr,b_ptr,field_length); +#ifdef USE_STRCOLL + if (use_strcoll(default_charset_info)) + { + /* + We have to remove end space to be able to compare multi-byte-characters + like in latin_de 'ae' and 0xe4 + */ + uint a_length= field_length_without_space(a_ptr, field_length); + uint b_length= field_length_without_space(b_ptr, field_length); + return my_strnncoll(default_charset_info, + (const uchar*) a_ptr, a_length, + (const uchar*) b_ptr, b_length); + } +#endif + return my_sortcmp(a_ptr,b_ptr,field_length); } void Field_string::sort_string(char *to,uint length) diff --git a/sql/item.cc b/sql/item.cc index 4fefae7358f..79501755cbf 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -576,6 +576,14 @@ inline uint char_val(char X) X-'a'+10); } +/* In MySQL 4.1 this will always return STRING_RESULT */ + +enum Item_result Item_varbinary::result_type () const +{ + return (current_thd->variables.new_mode) ? STRING_RESULT : INT_RESULT; +} + + Item_varbinary::Item_varbinary(const char *str, uint str_length) { name=(char*) str-2; // Lex makes this start with 0x diff --git a/sql/item.h b/sql/item.h index 5e2c2ccc056..09d428509d0 100644 --- a/sql/item.h +++ b/sql/item.h @@ -353,7 +353,7 @@ public: String *val_str(String*) { return &str_value; } bool save_in_field(Field *field, bool no_conversions); void make_field(Send_field *field); - enum Item_result result_type () const { return INT_RESULT; } + enum Item_result result_type () const; unsigned int size_of() { return sizeof(*this);} }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fc2baf5784c..2799bdf9f54 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -204,12 +204,12 @@ static char **opt_argv; #ifdef __WIN__ #undef MYSQL_SERVER_SUFFIX #ifdef __NT__ -#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) +#if defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max-nt" #else #define MYSQL_SERVER_SUFFIX "-nt" #endif /* ...DB */ -#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) +#elif defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max" #else #define MYSQL_SERVER_SUFFIX "" diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 5d3f9a0595c..d6abe6497df 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -284,7 +284,6 @@ void field_str::add() char buff[MAX_FIELD_WIDTH], *ptr; String s(buff, sizeof(buff)), *res; ulong length; - TREE_ELEMENT *element; if (!(res = item->val_str(&s))) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0379c1de287..e02f457fd77 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1029,7 +1029,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) #else error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime); #ifdef EXTRA_DEBUG - if (error && error != EINTR) + if (error && error != EINTR && error != ETIMEDOUT) { fprintf(stderr, "Got error %d from pthread_cond_timedwait\n",error); DBUG_PRINT("error",("Got error %d from pthread_cond_timedwait", diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index d670c673b4a..283dd20a56c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1042,6 +1042,9 @@ err: } send_eof(&thd->net); + pthread_mutex_lock(&LOCK_thread_count); + thd->current_linfo = 0; + pthread_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(0); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f870f8f5178..79ba13a3339 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2631,6 +2631,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) join->thd->select_limit)) < 0) DBUG_RETURN(1); // Impossible range sel->cond=orig_cond; + /* Fix for EXPLAIN */ + if (sel->quick) + join->best_positions[i].records_read= sel->quick->records; } else { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0fbb5807c57..1b1b5112e0b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -23,6 +23,7 @@ #endif #include #include +#include #include #ifdef __WIN__ @@ -1046,12 +1047,31 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table, } else { + /* + User gave us USE_FRM which means that the header in the index file is + trashed. + In this case we will try to fix the table the following way: + - Rename the data file to a temporary name + - Truncate the table + - Replace the new data file with the old one + - Run a normal repair using the new index file and the old data file + */ - char from[FN_REFLEN],tmp[FN_REFLEN]; - char* db = thd->db ? thd->db : table->db; + char from[FN_REFLEN],tmp[FN_REFLEN+32]; + const char **ext= table->table->file->bas_ext(); + MY_STAT stat_info; + + /* + Check if this is a table type that stores index and data separately, + like ISAM or MyISAM + */ + if (!ext[0] || !ext[1]) + DBUG_RETURN(0); // No data file + + strxmov(from, table->table->path, ext[1], NullS); // Name of data file + if (!my_stat(from, &stat_info, MYF(0))) + DBUG_RETURN(0); // Can't use USE_FRM flag - sprintf(from, "%s/%s/%s", mysql_real_data_home, db, table->real_name); - fn_format(from, from, "", MI_NAME_DEXT, 4); sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); pthread_mutex_lock(&LOCK_open); @@ -1067,7 +1087,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table, unlock_table_name(thd, table); pthread_mutex_unlock(&LOCK_open); DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed renaming .MYD file")); + "Failed renaming data file")); } if (mysql_truncate(thd, table, 1)) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d7a0c15e9b9..f895c809366 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2310,16 +2310,12 @@ olap_opt: | WITH CUBE_SYM { LEX *lex=Lex; - lex->olap = true; - lex->select->olap= CUBE_TYPE; net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "CUBE"); YYABORT; /* To be deleted in 4.1 */ } | WITH ROLLUP_SYM { LEX *lex=Lex; - lex->olap = true; - lex->select->olap= ROLLUP_TYPE; net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "ROLLUP"); YYABORT; /* To be deleted in 4.1 */ } @@ -2407,7 +2403,7 @@ delete_limit_clause: ULONG_NUM: NUM { $$= strtoul($1.str,NULL,10); } - | LONG_NUM { $$= (ulonglong) strtoll($1.str,NULL,10); } + | LONG_NUM { $$= (ulong) strtoll($1.str,NULL,10); } | ULONGLONG_NUM { $$= (ulong) strtoull($1.str,NULL,10); } | REAL_NUM { $$= strtoul($1.str,NULL,10); } | FLOAT_NUM { $$= strtoul($1.str,NULL,10); }; From 1d2507e875b73ca9466ce2234965ea4fb1b0fc8d Mon Sep 17 00:00:00 2001 From: "greg@mysql.com" <> Date: Sun, 27 Apr 2003 21:15:52 -0400 Subject: [PATCH 107/188] Change to NetWare platform mods, per Monty --- mysys/my_pthread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index f88a884a1bc..4f472f61593 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -95,9 +95,9 @@ void *my_pthread_getspecific_imp(pthread_key_t key) don't kill the LibC Reaper thread or the main thread */ #include +#undef pthread_exit void my_pthread_exit(void *status) { -#undef pthread_exit NXThreadId_t tid = NXThreadGetId(); NXContext_t ctx; char name[PATH_MAX] = ""; From 51eed4b48cbe41d226bef548fb900306e4edb650 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Mon, 28 Apr 2003 10:32:56 +0300 Subject: [PATCH 108/188] Fix for openssl on Solaris Fix for grant bug with SELECT * --- include/my_global.h | 4 ++++ sql/item_strfunc.cc | 3 --- sql/sql_acl.cc | 17 +++++++------- sql/sql_base.cc | 5 +++-- sql/sql_parse.cc | 20 ++++++++++++----- tests/grant.pl | 20 ++++++++++++++--- tests/grant.res | 55 ++++++++++++++++++++++++++++++--------------- 7 files changed, 84 insertions(+), 40 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index e12a7d7273b..b979cd5955a 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -267,6 +267,10 @@ C_MODE_END #include #endif #include /* Recommended by debian */ +/* We need the following to go around a problem with openssl on solaris */ +#if defined(HAVE_CRYPT) +#include +#endif /* Go around some bugs in different OS and compilers */ #if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index af4e2a01eae..29165d85451 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -27,9 +27,6 @@ #include "mysql_priv.h" #include "sql_acl.h" #include -#ifdef HAVE_CRYPT_H -#include -#endif #ifdef HAVE_OPENSSL #include #endif /* HAVE_OPENSSL */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8ee210f4e24..3f63344baba 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1997,10 +1997,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } -int mysql_table_grant (THD *thd, TABLE_LIST *table_list, - List &user_list, - List &columns, ulong rights, - bool revoke_grant) +int mysql_table_grant(THD *thd, TABLE_LIST *table_list, + List &user_list, + List &columns, ulong rights, + bool revoke_grant) { ulong column_priv = 0; List_iterator str_list (user_list); @@ -2374,7 +2374,7 @@ my_bool grant_init(THD *org_thd) mem_check->ok() && hash_insert(&hash_tables,(byte*) mem_check)) { /* This could only happen if we are out memory */ - grant_option = FALSE; /* purecov: deadcode */ + grant_option= FALSE; /* purecov: deadcode */ goto end_unlock; } } @@ -2404,7 +2404,8 @@ end: void grant_reload(THD *thd) { - HASH old_hash_tables;bool old_grant_option; + HASH old_hash_tables; + bool old_grant_option; MEM_ROOT old_mem; DBUG_ENTER("grant_reload"); @@ -2413,14 +2414,14 @@ void grant_reload(THD *thd) pthread_mutex_lock(&LOCK_grant); grant_version++; old_hash_tables=hash_tables; - old_grant_option = grant_option; + old_grant_option= grant_option; old_mem = memex; if (grant_init(thd)) { // Error. Revert to old hash grant_free(); /* purecov: deadcode */ hash_tables=old_hash_tables; /* purecov: deadcode */ - grant_option = old_grant_option; /* purecov: deadcode */ + grant_option= old_grant_option; /* purecov: deadcode */ memex = old_mem; /* purecov: deadcode */ } else diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e27ccf55543..0f0c3c97ed2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1984,8 +1984,9 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, (!db_name || !strcmp(tables->db,db_name)))) { /* Ensure that we have access right to all columns */ - if (grant_option && !thd->master_access && - check_grant_all_columns(thd,SELECT_ACL,table) ) + if (grant_option && !(table->grant.privilege & + table->grant.want_privilege) && + check_grant_all_columns(thd,SELECT_ACL,table)) DBUG_RETURN(-1); Field **ptr=table->field,*field; thd->used_tables|=table->map; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1a8ea7da8f4..7479ef653a9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2519,12 +2519,20 @@ error: /**************************************************************************** Get the user (global) and database privileges for all used tables - Returns true (error) if we can't get the privileges and we don't use - table/column grants. - The idea of EXTRA_ACL is that one will be granted access to the table if - one has the asked privilege on any column combination of the table; For - example to be able to check a table one needs to have SELECT privilege on - any column of the table. + + NOTES + The idea of EXTRA_ACL is that one will be granted access to the table if + one has the asked privilege on any column combination of the table; For + example to be able to check a table one needs to have SELECT privilege on + any column of the table. + + RETURN + 0 ok + 1 If we can't get the privileges and we don't use table/column grants. + + save_priv In this we store global and db level grants for the table + Note that we don't store db level grants if the global grants + is enough to satisfy the request. ****************************************************************************/ bool diff --git a/tests/grant.pl b/tests/grant.pl index 5a24127d79d..e32431ad63a 100644 --- a/tests/grant.pl +++ b/tests/grant.pl @@ -62,6 +62,12 @@ safe_query("create database $opt_database"); user_connect(1); #goto test; +# +# Enable column grant code +# +safe_query("grant select(user) on mysql.user to $user"); +safe_query("revoke select(user) on mysql.user from $user"); + # # Test grants on user level # @@ -408,21 +414,29 @@ safe_query("grant ALL PRIVILEGES on $opt_database.test to $user identified by 'd user_connect(0,"dummy"); safe_query("grant SELECT on $opt_database.* to $user identified by ''"); user_connect(0); -safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user identified by ''"); +safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user identified by '', ${opt_user}\@127.0.0.1 identified by 'dummy2'"); safe_query("revoke ALL PRIVILEGES on $opt_database.* from $user identified by ''"); + safe_query("show grants for $user"); # # Test bug reported in SELECT INTO OUTFILE # -safe_query("create table $opt_database.test3 (a int)"); +safe_query("create table $opt_database.test3 (a int, b int)"); safe_query("grant SELECT on $opt_database.test3 to $user"); safe_query("grant FILE on *.* to $user"); -safe_query("insert into $opt_database.test3 values (1)"); +safe_query("insert into $opt_database.test3 values (1,1)"); user_connect(0); user_query("select * into outfile '$tmp_table' from $opt_database.test3"); safe_query("revoke SELECT on $opt_database.test3 from $user"); +safe_query("grant SELECT(a) on $opt_database.test3 to $user"); +user_query("select a from $opt_database.test3"); +user_query("select * from $opt_database.test3",1); +user_query("select a,b from $opt_database.test3",1); +user_query("select b from $opt_database.test3",1); + +safe_query("revoke SELECT(a) on $opt_database.test3 from $user"); safe_query("revoke FILE on *.* from $user"); safe_query("drop table $opt_database.test3"); diff --git a/tests/grant.res b/tests/grant.res index 92d271cd864..a50f73740c6 100644 --- a/tests/grant.res +++ b/tests/grant.res @@ -10,6 +10,8 @@ Error in execute: Can't drop database 'grant_test'. Database doesn't exist create database grant_test Connecting grant_user Error on connect: Access denied for user: '@localhost' to database 'grant_test' +grant select(user) on mysql.user to grant_user@localhost +revoke select(user) on mysql.user from grant_user@localhost grant select on *.* to grant_user@localhost set password FOR grant_user2@localhost = password('test') Error in execute: Can't find any matching row in the user table @@ -106,21 +108,21 @@ select count(*) from grant_test.test 2 select * from mysql.user where user = 'grant_user' -Error in execute: select command denied to user: 'grant_user@localhost' for table 'user' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql' insert into grant_test.test values (4,0) -Error in execute: insert command denied to user: 'grant_user@localhost' for table 'test' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' update grant_test.test set a=1 -Error in execute: update command denied to user: 'grant_user@localhost' for table 'test' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' delete from grant_test.test -Error in execute: delete command denied to user: 'grant_user@localhost' for table 'test' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' create table grant_test.test2 (a int) -Error in execute: create command denied to user: 'grant_user@localhost' for table 'test2' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' ALTER TABLE grant_test.test add c int -Error in execute: alter command denied to user: 'grant_user@localhost' for table 'test' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' CREATE INDEX dummy ON grant_test.test (a) -Error in execute: index command denied to user: 'grant_user@localhost' for table 'test' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' drop table grant_test.test -Error in execute: drop command denied to user: 'grant_user@localhost' for table 'test' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' grant ALL PRIVILEGES on grant_test.* to grant_user2@localhost Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' grant ALL PRIVILEGES on grant_test.* to grant_user@localhost WITH GRANT OPTION @@ -133,14 +135,14 @@ REVOKE ALL PRIVILEGES on grant_test.* from grant_user@localhost REVOKE ALL PRIVILEGES on grant_test.* from grant_user@localhost Connecting grant_user insert into grant_test.test values (6,0) -Error in execute: insert command denied to user: 'grant_user@localhost' for table 'test' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' REVOKE GRANT OPTION on grant_test.* from grant_user@localhost Connecting grant_user Error on connect: Access denied for user: 'grant_user@localhost' to database 'grant_test' grant ALL PRIVILEGES on grant_test.* to grant_user@localhost Connecting grant_user select * from mysql.user where user = 'grant_user' -Error in execute: select command denied to user: 'grant_user@localhost' for table 'user' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql' insert into grant_test.test values (7,0) update grant_test.test set a=3 where a=2 delete from grant_test.test where a=3 @@ -152,7 +154,7 @@ show tables from grant_test test insert into mysql.user (host,user) values ('error','grant_user',0) -Error in execute: insert command denied to user: 'grant_user@localhost' for table 'user' +Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql' revoke ALL PRIVILEGES on grant_test.* from grant_user@localhost select * from mysql.user where user = 'grant_user' localhost grant_user N N N N N N N N N N N N N N N N N N N N N 0 0 0 @@ -200,7 +202,7 @@ Connecting grant_user update grant_test.test set b=b+1 revoke SELECT on *.* from grant_user@localhost Connecting grant_user -lect * from test +select * from test Error in execute: select command denied to user: 'grant_user@localhost' for table 'test' grant select on grant_test.test to grant_user@localhost delete from grant_test.test where a=1 @@ -233,7 +235,7 @@ Error in execute: select command denied to user: 'grant_user@localhost' for tabl select count(*) from test,test2 Error in execute: select command denied to user: 'grant_user@localhost' for table 'test2' replace into test2 SELECT a from test -Error in execute: update command denied to user: 'grant_user@localhost' for table 'test2' +Error in execute: delete command denied to user: 'grant_user@localhost' for table 'test2' grant update on grant_test.test2 to grant_user@localhost replace into test2 SELECT a,a from test Error in execute: delete command denied to user: 'grant_user@localhost' for table 'test2' @@ -448,21 +450,34 @@ grant ALL PRIVILEGES on grant_test.test to grant_user@localhost identified by 'd Connecting grant_user grant SELECT on grant_test.* to grant_user@localhost identified by '' Connecting grant_user -revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost identified by '' +revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost identified by '', grant_user@127.0.0.1 identified by 'dummy2' revoke ALL PRIVILEGES on grant_test.* from grant_user@localhost identified by '' show grants for grant_user@localhost -create table grant_test.test3 (a int) +GRANT USAGE ON *.* TO 'grant_user'@'localhost' + +create table grant_test.test3 (a int, b int) grant SELECT on grant_test.test3 to grant_user@localhost grant FILE on *.* to grant_user@localhost -insert into grant_test.test3 values (1) +insert into grant_test.test3 values (1,1) Connecting grant_user select * into outfile '/tmp/mysql-grant.test' from grant_test.test3 revoke SELECT on grant_test.test3 from grant_user@localhost +grant SELECT(a) on grant_test.test3 to grant_user@localhost +select a from grant_test.test3 +1 + +select * from grant_test.test3 +Error in execute: select command denied to user: 'grant_user@localhost' for column 'b' in table 'test3' +select a,b from grant_test.test3 +Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'b' in table 'test3' +select b from grant_test.test3 +Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'b' in table 'test3' +revoke SELECT(a) on grant_test.test3 from grant_user@localhost revoke FILE on *.* from grant_user@localhost drop table grant_test.test3 create table grant_test.test3 (a int) Connecting grant_user -Access denied for user: 'grant_user@localhost' to database 'grant_test' +Error on connect: Access denied for user: 'grant_user@localhost' to database 'grant_test' grant INSERT on grant_test.test3 to grant_user@localhost Connecting grant_user select * into outfile '/tmp/mysql-grant.test' from grant_test.test3 @@ -487,9 +502,11 @@ revoke SELECT,INSERT,UPDATE,DELETE on grant_test.test3 from grant_user@localhost Connecting grant_user revoke LOCK TABLES on *.* from grant_user@localhost Connecting grant_user -Access denied for user: 'grant_user@localhost' to database 'grant_test' +Error on connect: Access denied for user: 'grant_user@localhost' to database 'grant_test' drop table grant_test.test3 show grants for grant_user@localhost +GRANT USAGE ON *.* TO 'grant_user'@'localhost' + grant all on *.* to grant_user@localhost WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 2 MAX_CONNECTIONS_PER_HOUR 3 show grants for grant_user@localhost GRANT ALL PRIVILEGES ON *.* TO 'grant_user'@'localhost' WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 2 MAX_CONNECTIONS_PER_HOUR 3 @@ -501,6 +518,8 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, F revoke ALL PRIVILEGES on *.* from grant_user@localhost show grants for grant_user@localhost +GRANT USAGE ON *.* TO 'grant_user'@'localhost' WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 2 MAX_CONNECTIONS_PER_HOUR 3 + drop database grant_test delete from user where user='grant_user' delete from db where user='grant_user' From 938933afc9f90a5102dba643be1a3c54e6051ba6 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Mon, 28 Apr 2003 12:00:04 +0300 Subject: [PATCH 109/188] Use my.cnf file from datadir even if datadir is different from the default one. --- support-files/mysql.server.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 1e328a4f625..de01142beac 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -118,7 +118,18 @@ else test -z "$print_defaults" && print_defaults="my_print_defaults" fi -parse_arguments `$print_defaults mysqld mysql_server mysql.server` +# +# Test if someone changed datadir; In this case we should also read the +# default arguments from this directory +# + +extra_args="" +if test "$datadir" != "@localstatedir@" +then + extra_args="-e $datadir/my.cnf" +fi + +parse_arguments `$print_defaults $extra_args mysqld mysql_server mysql.server` # Safeguard (relative paths, core dumps..) cd $basedir From 252ba8aa61f14916471f68004967f928f3f63c66 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Mon, 28 Apr 2003 12:31:19 +0300 Subject: [PATCH 110/188] Better test for regular files. --- mysys/default.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index 26121cc0e56..c47d2719ab5 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -249,8 +249,13 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(0))) return 0; - /* ignore world-writeable _regular_ files */ - if (stat_info.st_mode & S_IWOTH && stat_info.st_mode & S_IFREG) + /* + Ignore world-writable regular files. + This is mainly done to protect us to not read a file created by + the mysqld server, but the check is still valid in most context. + */ + if ((stat_info.st_mode & S_IWOTH) && + (stat_info.st_mode & S_IFMT) == S_IFREG) { fprintf(stderr, "warning: World-writeable config file %s is ignored\n", name); From 47a825518403c61919c50004256144d1e14be2af Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 28 Apr 2003 15:59:04 +0200 Subject: [PATCH 111/188] - Fixed some texi errors in internals.texi (still some more left) --- Docs/internals.texi | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index 709dbc4b068..66d04b006ff 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -690,7 +690,7 @@ is the header of the packet. @end menu -@node ok packet, error packet, basic packets, basic packets +@node ok packet, error packet, basic packets, basic packets, basic packets @subsection OK Packet For details, see @file{sql/net_pkg.cc::send_ok()}. @@ -720,7 +720,7 @@ For details, see @file{sql/net_pkg.cc::send_ok()}. @end table -@node error packet, , ok packet, basic packets +@node error packet, , ok packet, basic packets, basic packets @subsection Error Packet @example @@ -745,6 +745,7 @@ For details, see @file{sql/net_pkg.cc::send_ok()}. @node communication, fieldtype codes, basic packets, protocol @section Communication +@example > Packet from server to client < Paket from client tor server @@ -832,9 +833,9 @@ For details, see @file{sql/net_pkg.cc::send_ok()}. 4 byte header 1-8 byte length of data n data - +@end example -@node fieldtype codes, protocol functions, communication, protocol +@node fieldtype codes, protocol functions, communication @section Fieldtype Codes @example @@ -858,10 +859,12 @@ Time 03 08 00 00 |01 0B |03 00 00 00 Date 03 0A 00 00 |01 0A |03 00 00 00 @end example -@node protocol functions, protocol version 2, fieldtype codes, protocol +@node protocol functions, protocol version 2, fieldtype codes @section Functions used to implement the protocol -This should be merged with the above one and changed to texi format +@c This should be merged with the above one and changed to texi format + +@example Raw packets ----------- @@ -966,12 +969,14 @@ The encrypted message is sent to the server which uses the stored random number password to encrypt the random string sent to the client. If this is equal to the new message the client sends to the server then the password is accepted. +@end example -@node protocol version 2, , protocol functions, protocol +@node protocol version 2, 4.1 protocol changes, protocol functions @section Another description of the protocol -This should be merged with the above one and changed to texi format. +@c This should be merged with the above one and changed to texi format. +@example ***************************** * * PROTOCOL OVERVIEW @@ -1646,7 +1651,7 @@ one packet is sent from the server, for simplicity's sake): Followed immediately by one 'LAST DATA' packet: fe 00 . . - +@end example @c The Index was empty, and ugly, so I removed it. (jcole, Sep 7, 2000) @@ -1659,7 +1664,7 @@ fe 00 . . @c @node 4.1 protocol,,, @c @chapter MySQL 4.1 protocol -@node 4.1 protocol changes,,, +@node 4.1 protocol changes, 4.1 field packet, protocol version 2 @section Changes to 4.0 protocol in 4.1 All basic packet handling is identical to 4.0. When communication @@ -1694,7 +1699,7 @@ results will sent as binary (low-byte-first). @end itemize -@node 4.1 field packet,,, +@node 4.1 field packet, 4.1 field desc, 4.1 protocol changes @section 4.1 field description packet The field description packet is sent as a response to a query that @@ -1714,7 +1719,7 @@ uses this to send the number of rows in the table) This packet is always followed by a field description set. @xref{4.1 field desc}. -@node 4.1 field desc,,, +@node 4.1 field desc, 4.1 ok packet, 4.1 field packet @section 4.1 field description result set The field description result set contains the meta info for a result set. @@ -1732,7 +1737,7 @@ The field description result set contains the meta info for a result set. @end multitable -@node 4.1 ok packet,,, +@node 4.1 ok packet, 4.1 end packet, 4.1 field desc @section 4.1 ok packet The ok packet is the first that is sent as an response for a query @@ -1758,7 +1763,7 @@ The message is optional. For example for multi line INSERT it contains a string for how many rows was inserted / deleted. -@node 4.1 end packet,,, +@node 4.1 end packet, 4.1 error packet, 4.1 ok packet @section 4.1 end packet The end packet is sent as the last packet for @@ -1787,7 +1792,7 @@ by checking the packet length < 9 bytes (in which case it's and end packet). -@node 4.1 error packet +@node 4.1 error packet, 4.1 prep init, 4.1 end packet @section 4.1 error packet. The error packet is sent when something goes wrong. @@ -1804,7 +1809,7 @@ The client/server protocol is designed in such a way that a packet can only start with 255 if it's an error packet. -@node 4.1 prep init,,, +@node 4.1 prep init, 4.1 long data, 4.1 error packet @section 4.1 prepared statement init packet This is the return packet when one sends a query with the COM_PREPARE @@ -1838,7 +1843,7 @@ prepared statement will contain a result set. In this case the packet is followed by a field description result set. @xref{4.1 field desc}. -@node 4.1 long data,,, +@node 4.1 long data, 4.1 execute, 4.1 prep init @section 4.1 long data handling This is used by mysql_send_long_data() to set any parameter to a string @@ -1865,7 +1870,7 @@ The server will NOT send an @code{ok} or @code{error} packet in responce for this. If there is any errors (like to big string), one will get the error when calling execute. -@node 4.1 execute,,, +@node 4.1 execute, 4.1 binary result, 4.1 long data @section 4.1 execute On execute we send all parameters to the server in a COM_EXECUTE @@ -1903,7 +1908,7 @@ The parameters are stored the following ways: The result for this will be either an ok packet or a binary result set. -@node 4.1 binary result,,, +@node 4.1 binary result, , 4.1 execute @section 4.1 binary result set A binary result are sent the following way. @@ -3510,6 +3515,7 @@ an "*" in the following list. For example, you will find that (\myisam\mi_extra.c) with the same descriptive comment. @*@* +@itemize @item hp_block.c -- Read/write a block (i.e. a page) @item From ac411193b4c787cb8d9f2a6f9344c3fc60e518e6 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 28 Apr 2003 16:05:27 +0200 Subject: [PATCH 112/188] - Removed two EXPLAIN SELECT statements from the InnoDB test suite (the results are nondeterministic and provide different output on 32bit and 64bit architectures) --- mysql-test/r/innodb.result | 6 ------ mysql-test/t/innodb.test | 2 -- 2 files changed, 8 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 5049dec9ef1..3f28f00f322 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1225,12 +1225,6 @@ insert into t1 (a) select b from t2; select count(*) from t1; count(*) 29267 -explain select a from t1 where a between 1 and 10000; -table type possible_keys key key_len ref rows Extra -t1 range PRIMARY PRIMARY 4 NULL 14745 Using where; Using index -explain select * from t1 where a between 1 and 10000; -table type possible_keys key key_len ref rows Extra -t1 range PRIMARY PRIMARY 4 NULL 14745 Using where explain select * from t1 where c between 1 and 10000; table type possible_keys key key_len ref rows Extra t1 range c c 5 NULL 1 Using where diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 88edaac190a..ab3157a7f86 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -823,8 +823,6 @@ insert into t1 (a) select b from t2; insert into t2 (a) select b from t1; insert into t1 (a) select b from t2; select count(*) from t1; -explain select a from t1 where a between 1 and 10000; -explain select * from t1 where a between 1 and 10000; explain select * from t1 where c between 1 and 10000; update t1 set c=a; explain select * from t1 where c between 1 and 10000; From e741c893eaa7593161e55ded869557199df50fc7 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Mon, 28 Apr 2003 19:05:57 +0300 Subject: [PATCH 113/188] Fix to remove compiler warnings --- include/my_global.h | 2 +- include/violite.h | 4 ++-- libmysqld/libmysqld.c | 6 +++--- myisam/sort.c | 2 ++ myisammrg/myrg_extra.c | 2 +- vio/viossl.c | 12 +++++++++--- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index b979cd5955a..98034fc1cff 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -268,7 +268,7 @@ C_MODE_END #endif #include /* Recommended by debian */ /* We need the following to go around a problem with openssl on solaris */ -#if defined(HAVE_CRYPT) +#if defined(HAVE_CRYPT_H) #include #endif diff --git a/include/violite.h b/include/violite.h index a328e51253a..d20fab23239 100644 --- a/include/violite.h +++ b/include/violite.h @@ -148,7 +148,7 @@ my_bool vio_ssl_should_retry(Vio* vio); int vio_ssl_close(Vio* vio); /* Return last error number */ int vio_ssl_errno(Vio *vio); -my_bool vio_ssl_peer_addr(Vio* vio, char *buf); +my_bool vio_ssl_peer_addr(Vio* vio, char *buf, uint16 *port); void vio_ssl_in_addr(Vio *vio, struct in_addr *in); int vio_ssl_blocking(Vio * vio, my_bool set_blocking_mode, my_bool *old_mode); @@ -224,7 +224,7 @@ struct st_vio my_bool (*is_blocking)(Vio*); int (*viokeepalive)(Vio*, my_bool); int (*fastsend)(Vio*); - my_bool (*peer_addr)(Vio*, gptr, uint16*); + my_bool (*peer_addr)(Vio*, char *, uint16*); void (*in_addr)(Vio*, struct in_addr*); my_bool (*should_retry)(Vio*); int (*vioclose)(Vio*); diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 3fba238a8bf..782731d4765 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -62,7 +62,7 @@ my_string mysql_unix_port=0; #define closesocket(A) close(A) #endif -static void mysql_once_init(void); +static void mysqld_once_init(void); static MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields, uint field_count); static int read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, @@ -729,7 +729,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) MYSQL * STDCALL mysql_init(MYSQL *mysql) { - mysql_once_init(); + mysqld_once_init(); if (!mysql) { if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) @@ -743,7 +743,7 @@ mysql_init(MYSQL *mysql) } -static void mysql_once_init() +static void mysqld_once_init() { if (!mysql_client_init) { diff --git a/myisam/sort.c b/myisam/sort.c index 224b4ad8420..95ede6ddaa1 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -286,6 +286,8 @@ pthread_handler_decl(thr_find_all_keys,arg) uint idx, maxbuffer; uchar **sort_keys=0; + LINT_INIT(keys); + error=1; if (my_thread_init()) diff --git a/myisammrg/myrg_extra.c b/myisammrg/myrg_extra.c index d375b45df99..62cf5f01aba 100644 --- a/myisammrg/myrg_extra.c +++ b/myisammrg/myrg_extra.c @@ -33,7 +33,7 @@ int myrg_extra(MYRG_INFO *info,enum ha_extra_function function, if (function == HA_EXTRA_CACHE) { info->cache_in_use=1; - info->cache_size= (extra_arg ? *(long*) extra_arg : + info->cache_size= (extra_arg ? *(ulong*) extra_arg : my_default_record_cache_size); } else diff --git a/vio/viossl.c b/vio/viossl.c index 0f34a45f9aa..834343a77d9 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -212,13 +212,14 @@ my_socket vio_ssl_fd(Vio* vio) } -my_bool vio_ssl_peer_addr(Vio * vio, char *buf) +my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port) { DBUG_ENTER("vio_ssl_peer_addr"); DBUG_PRINT("enter", ("sd=%d", vio->sd)); if (vio->localhost) { strmov(buf,"127.0.0.1"); + *port=0; } else { @@ -229,8 +230,13 @@ my_bool vio_ssl_peer_addr(Vio * vio, char *buf) DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); DBUG_RETURN(1); } - /* FIXME */ -/* my_inet_ntoa(vio->remote.sin_addr,buf); */ +#ifdef TO_BE_FIXED + my_inet_ntoa(vio->remote.sin_addr,buf); + *port= 0; +#else + strmov(buf, "unknown"); + *port= 0; +#endif } DBUG_PRINT("exit", ("addr=%s", buf)); DBUG_RETURN(0); From fa757919822cd27aae5d983fa4be8df5be3701f5 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 28 Apr 2003 18:35:15 +0200 Subject: [PATCH 114/188] - removed Benchmark results from source distribution (they are not up-to-date anyway) --- sql-bench/Makefile.am | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sql-bench/Makefile.am b/sql-bench/Makefile.am index ab6be7269e3..579a2a9f7fe 100644 --- a/sql-bench/Makefile.am +++ b/sql-bench/Makefile.am @@ -41,12 +41,9 @@ EXTRA_DIST = $(EXTRA_SCRIPTS) dist-hook: mkdir -p $(distdir)/Data/ATIS $(distdir)/Data/Wisconsin \ - $(distdir)/Results $(distdir)/Results-win32 \ $(distdir)/limits $(distdir)/Comments for i in $(srcdir)/Data/ATIS/*.* ; do $(INSTALL_DATA) $$i $(distdir)/Data/ATIS ; done for i in $(srcdir)/Data/Wisconsin/*.* ; do $(INSTALL_DATA) $$i $(distdir)/Data/Wisconsin ; done - for i in $(srcdir)/Results/*-* ; do $(INSTALL_DATA) $$i $(distdir)/Results; done - for i in $(srcdir)/Results-win32/*-* ; do $(INSTALL_DATA) $$i $(distdir)/Results-win32; done for i in $(srcdir)/limits/*.* ; do $(INSTALL_DATA) $$i $(distdir)/limits; done for i in $(srcdir)/Comments/*.* ; do $(INSTALL_DATA) $$i $(distdir)/Comments; done @@ -55,15 +52,11 @@ install-data-local: $(DESTDIR)$(benchdir)/Data \ $(DESTDIR)$(benchdir)/Data/ATIS \ $(DESTDIR)$(benchdir)/Data/Wisconsin \ - $(DESTDIR)$(benchdir)/Results \ - $(DESTDIR)$(benchdir)/Results-win32 \ $(DESTDIR)$(benchdir)/limits \ $(DESTDIR)$(benchdir)/Comments $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(benchdir) for i in $(srcdir)/Data/ATIS/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Data/ATIS ; done for i in $(srcdir)/Data/Wisconsin/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Data/Wisconsin ; done - for i in $(srcdir)/Results/*-* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Results; done - for i in $(srcdir)/Results-win32/*-* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Results-win32; done for i in $(srcdir)/limits/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/limits; done for i in $(srcdir)/Comments/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Comments; done From 10d4684336e486638f2345158ee953270b200a6a Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Tue, 29 Apr 2003 00:14:17 +0300 Subject: [PATCH 115/188] Added missing dependency to VC++ project file --- Docs/internals.texi | 484 +++++++++++++++++++++++--------------------- VC++Files/mysql.dsw | 3 + 2 files changed, 261 insertions(+), 226 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index 66d04b006ff..270fe9e2249 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -43,18 +43,18 @@ END-INFO-DIR-ENTRY @page @end titlepage -@node Top, caching, (dir), (dir) +@node Top, coding guidelines, (dir), (dir) @ifinfo This is a manual about @strong{MySQL} internals. @end ifinfo @menu -* caching:: How MySQL Handles Caching -* join_buffer_size:: -* flush tables:: How MySQL Handles @code{FLUSH TABLES} -* filesort:: How MySQL Does Sorting (@code{filesort}) * coding guidelines:: Coding Guidelines +* caching:: How MySQL Handles Caching +* join_buffer_size:: +* flush tables:: How MySQL Handles @code{FLUSH TABLES} +* Algorithms:: * mysys functions:: Functions In The @code{mysys} Library * DBUG:: DBUG Tags To Use * protocol:: MySQL Client/Server Protocol @@ -67,207 +67,7 @@ This is a manual about @strong{MySQL} internals. @end menu -@node caching, join_buffer_size, Top, Top -@chapter How MySQL Handles Caching - -@strong{MySQL} has the following caches: -(Note that the some of the filename have a wrong spelling of cache. :) - -@table @strong - -@item Key Cache -A shared cache for all B-tree index blocks in the different NISAM -files. Uses hashing and reverse linked lists for quick caching of the -last used blocks and quick flushing of changed entries for a specific -table. (@file{mysys/mf_keycash.c}) - -@item Record Cache -This is used for quick scanning of all records in a table. -(@file{mysys/mf_iocash.c} and @file{isam/_cash.c}) - -@item Table Cache -This holds the last used tables. (@file{sql/sql_base.cc}) - -@item Hostname Cache -For quick lookup (with reverse name resolving). Is a must when one has a -slow DNS. -(@file{sql/hostname.cc}) - -@item Privilege Cache -To allow quick change between databases the last used privileges are -cached for each user/database combination. -(@file{sql/sql_acl.cc}) - -@item Heap Table Cache -Many use of @code{GROUP BY} or @code{DISTINCT} caches all found rows in -a @code{HEAP} table. (This is a very quick in-memory table with hash index.) - -@item Join buffer Cache -For every full join in a @code{SELECT} statement (a full join here means -there were no keys that one could use to find the next table in a list), -the found rows are cached in a join cache. One @code{SELECT} query can -use many join caches in the worst case. -@end table - -@node join_buffer_size, flush tables, caching, Top -@chapter How MySQL uses the join_buffer cache - -Basic information about @code{join_buffer_size}: - -@itemize @bullet -@item -It's only used in the case when join type is of type @code{ALL} or -@code{index}; In other words: no possible keys can be used. -@item -A join buffer is never allocated for the first not-const table, -even it it would be of type @code{ALL}/@code{index}. -@item -The buffer is allocated when we need to do a each full join between two -tables and freed after the query is done. -@item -Accepted row combinations of tables before the @code{ALL}/@code{index} -able is stored in the cache and is used to compare against each read -row in the @code{ALL} table. -@item -We only store the used fields in the join_buffer cache, not the -whole rows. -@end itemize - -Assume you have the following join: - -@example -Table name Type -t1 range -t2 ref -t3 @code{ALL} -@end example - -The join is then done as follows: - -@example -- While rows in t1 matching range - - Read through all rows in t2 according to reference key - - Store used fields form t1,t2 in cache - - If cache is full - - Read through all rows in t3 - - Compare t3 row against all t1,t2 combination in cache - - If rows satisfying join condition, send it to client - - Empty cache - -- Read through all rows in t3 - - Compare t3 row against all stored t1,t2 combinations in cache - - If rows satisfying join condition, send it to client -@end example - -The above means that table t3 is scanned - -@example -(size-of-stored-row(t1,t2) * accepted-row-cominations(t1,t2))/ -join_buffer_size+1 -@end example -times. - -Some conclusions: - -@itemize @bullet -@item -The larger the join_buff_size, the fewer scans of t3. -If @code{join_buff_size} is already large enough to hold all previous row -combinations then there is no speed to gain by making it bigger. -@item -If there is several tables of @code{ALL}/@code{index} then the we -allocate one @code{join_buffer_size buffer} for each of them and use the -same algorithm described above to handle it. (In other words, we store -the same row combination several times into different buffers) -@end itemize - -@node flush tables, filesort, join_buffer_size, Top -@chapter How MySQL Handles @code{FLUSH TABLES} - -@itemize @bullet - -@item -Flush tables is handled in @file{sql/sql_base.cc::close_cached_tables()}. - -@item -The idea of flush tables is to force all tables to be closed. This -is mainly to ensure that if someone adds a new table outside of -@strong{MySQL} (for example with @code{cp}) all threads will start using -the new table. This will also ensure that all table changes are flushed -to disk (but of course not as optimally as simple calling a sync on -all tables)! - -@item -When one does a @code{FLUSH TABLES}, the variable @code{refresh_version} -will be incremented. Every time a thread releases a table it checks if -the refresh version of the table (updated at open) is the same as -the current @code{refresh_version}. If not it will close it and broadcast -a signal on @code{COND_refresh} (to wait any thread that is waiting for -all instanses of a table to be closed). - -@item -The current @code{refresh_version} is also compared to the open -@code{refresh_version} after a thread gets a lock on a table. If the -refresh version is different the thread will free all locks, reopen the -table and try to get the locks again; This is just to quickly get all -tables to use the newest version. This is handled by -@file{sql/lock.cc::mysql_lock_tables()} and -@file{sql/sql_base.cc::wait_for_tables()}. - -@item -When all tables has been closed @code{FLUSH TABLES} will return an ok -to client. - -@item -If the thread that is doing @code{FLUSH TABLES} has a lock on some tables, -it will first close the locked tables, then wait until all other threads -have also closed them, and then reopen them and get the locks. -After this it will give other threads a chance to open the same tables. - -@end itemize - -@node filesort, coding guidelines, flush tables, Top -@chapter How MySQL Does Sorting (@code{filesort}) - -@itemize @bullet - -@item -Read all rows according to key or by table scanning. - -@item -Store the sort-key in a buffer (@code{sort_buffer}). - -@item -When the buffer gets full, run a @code{qsort} on it and store the result -in a temporary file. Save a pointer to the sorted block. - -@item -Repeat the above until all rows have been read. - -@item -Repeat the following until there is less than @code{MERGEBUFF2} (15) -blocks left. - -@item -Do a multi-merge of up to @code{MERGEBUFF} (7) regions to one block in -another temporary file. Repeat until all blocks from the first file -are in the second file. - -@item -On the last multi-merge, only the pointer to the row (last part of -the sort-key) is written to a result file. - -@item -Now the code in @file{sql/records.cc} will be used to read through them -in sorted order by using the row pointers in the result file. -To optimize this, we read in a big block of row pointers, sort these -and then we read the rows in the sorted order into a row buffer -(@code{record_buffer}). - -@end itemize - - -@node coding guidelines, mysys functions, filesort, Top +@node coding guidelines, caching, Top, Top @chapter Coding Guidelines @itemize @bullet @@ -427,8 +227,230 @@ Suggested mode in emacs: (setq c-default-style "MY") @end example +@node caching, join_buffer_size, coding guidelines, Top +@chapter How MySQL Handles Caching -@node mysys functions, DBUG, coding guidelines, Top +@strong{MySQL} has the following caches: +(Note that the some of the filename have a wrong spelling of cache. :) + +@table @strong + +@item Key Cache +A shared cache for all B-tree index blocks in the different NISAM +files. Uses hashing and reverse linked lists for quick caching of the +last used blocks and quick flushing of changed entries for a specific +table. (@file{mysys/mf_keycash.c}) + +@item Record Cache +This is used for quick scanning of all records in a table. +(@file{mysys/mf_iocash.c} and @file{isam/_cash.c}) + +@item Table Cache +This holds the last used tables. (@file{sql/sql_base.cc}) + +@item Hostname Cache +For quick lookup (with reverse name resolving). Is a must when one has a +slow DNS. +(@file{sql/hostname.cc}) + +@item Privilege Cache +To allow quick change between databases the last used privileges are +cached for each user/database combination. +(@file{sql/sql_acl.cc}) + +@item Heap Table Cache +Many use of @code{GROUP BY} or @code{DISTINCT} caches all found rows in +a @code{HEAP} table. (This is a very quick in-memory table with hash index.) + +@item Join buffer Cache +For every full join in a @code{SELECT} statement (a full join here means +there were no keys that one could use to find the next table in a list), +the found rows are cached in a join cache. One @code{SELECT} query can +use many join caches in the worst case. +@end table + +@node join_buffer_size, flush tables, caching, Top +@chapter How MySQL uses the join_buffer cache + +Basic information about @code{join_buffer_size}: + +@itemize @bullet +@item +It's only used in the case when join type is of type @code{ALL} or +@code{index}; In other words: no possible keys can be used. +@item +A join buffer is never allocated for the first not-const table, +even it it would be of type @code{ALL}/@code{index}. +@item +The buffer is allocated when we need to do a each full join between two +tables and freed after the query is done. +@item +Accepted row combinations of tables before the @code{ALL}/@code{index} +able is stored in the cache and is used to compare against each read +row in the @code{ALL} table. +@item +We only store the used fields in the join_buffer cache, not the +whole rows. +@end itemize + +Assume you have the following join: + +@example +Table name Type +t1 range +t2 ref +t3 @code{ALL} +@end example + +The join is then done as follows: + +@example +- While rows in t1 matching range + - Read through all rows in t2 according to reference key + - Store used fields form t1,t2 in cache + - If cache is full + - Read through all rows in t3 + - Compare t3 row against all t1,t2 combination in cache + - If rows satisfying join condition, send it to client + - Empty cache + +- Read through all rows in t3 + - Compare t3 row against all stored t1,t2 combinations in cache + - If rows satisfying join condition, send it to client +@end example + +The above means that table t3 is scanned + +@example +(size-of-stored-row(t1,t2) * accepted-row-cominations(t1,t2))/ +join_buffer_size+1 +@end example +times. + +Some conclusions: + +@itemize @bullet +@item +The larger the join_buff_size, the fewer scans of t3. +If @code{join_buff_size} is already large enough to hold all previous row +combinations then there is no speed to gain by making it bigger. +@item +If there is several tables of @code{ALL}/@code{index} then the we +allocate one @code{join_buffer_size buffer} for each of them and use the +same algorithm described above to handle it. (In other words, we store +the same row combination several times into different buffers) +@end itemize + +@node flush tables, Algorithms, join_buffer_size, Top +@chapter How MySQL Handles @code{FLUSH TABLES} + +@itemize @bullet + +@item +Flush tables is handled in @file{sql/sql_base.cc::close_cached_tables()}. + +@item +The idea of flush tables is to force all tables to be closed. This +is mainly to ensure that if someone adds a new table outside of +@strong{MySQL} (for example with @code{cp}) all threads will start using +the new table. This will also ensure that all table changes are flushed +to disk (but of course not as optimally as simple calling a sync on +all tables)! + +@item +When one does a @code{FLUSH TABLES}, the variable @code{refresh_version} +will be incremented. Every time a thread releases a table it checks if +the refresh version of the table (updated at open) is the same as +the current @code{refresh_version}. If not it will close it and broadcast +a signal on @code{COND_refresh} (to wait any thread that is waiting for +all instanses of a table to be closed). + +@item +The current @code{refresh_version} is also compared to the open +@code{refresh_version} after a thread gets a lock on a table. If the +refresh version is different the thread will free all locks, reopen the +table and try to get the locks again; This is just to quickly get all +tables to use the newest version. This is handled by +@file{sql/lock.cc::mysql_lock_tables()} and +@file{sql/sql_base.cc::wait_for_tables()}. + +@item +When all tables has been closed @code{FLUSH TABLES} will return an ok +to client. + +@item +If the thread that is doing @code{FLUSH TABLES} has a lock on some tables, +it will first close the locked tables, then wait until all other threads +have also closed them, and then reopen them and get the locks. +After this it will give other threads a chance to open the same tables. + +@end itemize + +@node Algorithms, mysys functions, flush tables, Top +@chapter Different algoritms used in MySQL + +MySQL uses a lot of different algorithms. This chapter tries to describe +some of these: + +@menu +* filesort:: +* bulk-insert:: +@end menu + +@node filesort, bulk-insert, Algorithms, Algorithms +@section How MySQL Does Sorting (@code{filesort}) + +@itemize @bullet + +@item +Read all rows according to key or by table scanning. + +@item +Store the sort-key in a buffer (@code{sort_buffer}). + +@item +When the buffer gets full, run a @code{qsort} on it and store the result +in a temporary file. Save a pointer to the sorted block. + +@item +Repeat the above until all rows have been read. + +@item +Repeat the following until there is less than @code{MERGEBUFF2} (15) +blocks left. + +@item +Do a multi-merge of up to @code{MERGEBUFF} (7) regions to one block in +another temporary file. Repeat until all blocks from the first file +are in the second file. + +@item +On the last multi-merge, only the pointer to the row (last part of +the sort-key) is written to a result file. + +@item +Now the code in @file{sql/records.cc} will be used to read through them +in sorted order by using the row pointers in the result file. +To optimize this, we read in a big block of row pointers, sort these +and then we read the rows in the sorted order into a row buffer +(@code{record_buffer}). + +@end itemize + +@node bulk-insert, , filesort, Algorithms +@section Bulk insert + +Logic behind bulk insert optimisation is simple. + +Instead of writing each key value to b-tree (that is to keycache, but +bulk insert code doesn't know about keycache) keys are stored in +balanced binary (red-black) tree, in memory. When this tree reaches its +memory limit it's writes all keys to disk (to keycache, that is). But +as key stream coming from the binary tree is already sorted inserting +goes much faster, all the necessary pages are already in cache, disk +access is minimized, etc. + +@node mysys functions, DBUG, Algorithms, Top @chapter Functions In The @code{mysys} Library Functions in @code{mysys}: (For flags see @file{my_sys.h}) @@ -624,6 +646,16 @@ Print query. * fieldtype codes:: * protocol functions:: * protocol version 2:: +* 4.1 protocol changes:: +* 4.1 field packet:: +* 4.1 field desc:: +* 4.1 ok packet:: +* 4.1 end packet:: +* 4.1 error packet:: +* 4.1 prep init:: +* 4.1 long data:: +* 4.1 execute:: +* 4.1 binary result:: @end menu @node raw packet without compression, raw packet with compression, protocol, protocol @@ -690,7 +722,7 @@ is the header of the packet. @end menu -@node ok packet, error packet, basic packets, basic packets, basic packets +@node ok packet, error packet, basic packets, basic packets @subsection OK Packet For details, see @file{sql/net_pkg.cc::send_ok()}. @@ -720,7 +752,7 @@ For details, see @file{sql/net_pkg.cc::send_ok()}. @end table -@node error packet, , ok packet, basic packets, basic packets +@node error packet, , ok packet, basic packets @subsection Error Packet @example @@ -835,7 +867,7 @@ For details, see @file{sql/net_pkg.cc::send_ok()}. n data @end example -@node fieldtype codes, protocol functions, communication +@node fieldtype codes, protocol functions, communication, protocol @section Fieldtype Codes @example @@ -859,7 +891,7 @@ Time 03 08 00 00 |01 0B |03 00 00 00 Date 03 0A 00 00 |01 0A |03 00 00 00 @end example -@node protocol functions, protocol version 2, fieldtype codes +@node protocol functions, protocol version 2, fieldtype codes, protocol @section Functions used to implement the protocol @c This should be merged with the above one and changed to texi format @@ -971,7 +1003,7 @@ client. If this is equal to the new message the client sends to the server then the password is accepted. @end example -@node protocol version 2, 4.1 protocol changes, protocol functions +@node protocol version 2, 4.1 protocol changes, protocol functions, protocol @section Another description of the protocol @c This should be merged with the above one and changed to texi format. @@ -1664,7 +1696,7 @@ fe 00 . . @c @node 4.1 protocol,,, @c @chapter MySQL 4.1 protocol -@node 4.1 protocol changes, 4.1 field packet, protocol version 2 +@node 4.1 protocol changes, 4.1 field packet, protocol version 2, protocol @section Changes to 4.0 protocol in 4.1 All basic packet handling is identical to 4.0. When communication @@ -1699,7 +1731,7 @@ results will sent as binary (low-byte-first). @end itemize -@node 4.1 field packet, 4.1 field desc, 4.1 protocol changes +@node 4.1 field packet, 4.1 field desc, 4.1 protocol changes, protocol @section 4.1 field description packet The field description packet is sent as a response to a query that @@ -1719,7 +1751,7 @@ uses this to send the number of rows in the table) This packet is always followed by a field description set. @xref{4.1 field desc}. -@node 4.1 field desc, 4.1 ok packet, 4.1 field packet +@node 4.1 field desc, 4.1 ok packet, 4.1 field packet, protocol @section 4.1 field description result set The field description result set contains the meta info for a result set. @@ -1737,7 +1769,7 @@ The field description result set contains the meta info for a result set. @end multitable -@node 4.1 ok packet, 4.1 end packet, 4.1 field desc +@node 4.1 ok packet, 4.1 end packet, 4.1 field desc, protocol @section 4.1 ok packet The ok packet is the first that is sent as an response for a query @@ -1763,7 +1795,7 @@ The message is optional. For example for multi line INSERT it contains a string for how many rows was inserted / deleted. -@node 4.1 end packet, 4.1 error packet, 4.1 ok packet +@node 4.1 end packet, 4.1 error packet, 4.1 ok packet, protocol @section 4.1 end packet The end packet is sent as the last packet for @@ -1792,7 +1824,7 @@ by checking the packet length < 9 bytes (in which case it's and end packet). -@node 4.1 error packet, 4.1 prep init, 4.1 end packet +@node 4.1 error packet, 4.1 prep init, 4.1 end packet, protocol @section 4.1 error packet. The error packet is sent when something goes wrong. @@ -1809,7 +1841,7 @@ The client/server protocol is designed in such a way that a packet can only start with 255 if it's an error packet. -@node 4.1 prep init, 4.1 long data, 4.1 error packet +@node 4.1 prep init, 4.1 long data, 4.1 error packet, protocol @section 4.1 prepared statement init packet This is the return packet when one sends a query with the COM_PREPARE @@ -1843,7 +1875,7 @@ prepared statement will contain a result set. In this case the packet is followed by a field description result set. @xref{4.1 field desc}. -@node 4.1 long data, 4.1 execute, 4.1 prep init +@node 4.1 long data, 4.1 execute, 4.1 prep init, protocol @section 4.1 long data handling This is used by mysql_send_long_data() to set any parameter to a string @@ -1870,7 +1902,7 @@ The server will NOT send an @code{ok} or @code{error} packet in responce for this. If there is any errors (like to big string), one will get the error when calling execute. -@node 4.1 execute, 4.1 binary result, 4.1 long data +@node 4.1 execute, 4.1 binary result, 4.1 long data, protocol @section 4.1 execute On execute we send all parameters to the server in a COM_EXECUTE @@ -1908,7 +1940,7 @@ The parameters are stored the following ways: The result for this will be either an ok packet or a binary result set. -@node 4.1 binary result, , 4.1 execute +@node 4.1 binary result, , 4.1 execute, protocol @section 4.1 binary result set A binary result are sent the following way. @@ -2384,7 +2416,7 @@ work for different record formats are: /myisam/mi_statrec.c, /myisam/mi_dynrec.c, and /myisam/mi_packrec.c. @* -@node InnoDB Record Structure,InnoDB Page Structure,MyISAM Record Structure,Top +@node InnoDB Record Structure, InnoDB Page Structure, MyISAM Record Structure, Top @chapter InnoDB Record Structure This page contains: @@ -2690,7 +2722,7 @@ shorter because the NULLs take no space. The most relevant InnoDB source-code files are rem0rec.c, rem0rec.ic, and rem0rec.h in the rem ("Record Manager") directory. -@node InnoDB Page Structure,Files in MySQL Sources,InnoDB Record Structure,Top +@node InnoDB Page Structure, Files in MySQL Sources, InnoDB Record Structure, Top @chapter InnoDB Page Structure InnoDB stores all records inside a fixed-size unit which is commonly called a @@ -3121,7 +3153,7 @@ header. The most relevant InnoDB source-code files are page0page.c, page0page.ic, and page0page.h in \page directory. -@node Files in MySQL Sources,Files in InnoDB Sources,InnoDB Page Structure,Top +@node Files in MySQL Sources, Files in InnoDB Sources, InnoDB Page Structure, Top @chapter Annotated List Of Files in the MySQL Source Code Distribution This is a description of the files that you get when you download the @@ -4942,7 +4974,7 @@ The MySQL program that uses zlib is \mysys\my_compress.c. The use is for packet compression. The client sends messages to the server which are compressed by zlib. See also: \sql\net_serv.cc. -@node Files in InnoDB Sources,,Files in MySQL Sources,Top +@node Files in InnoDB Sources, , Files in MySQL Sources, Top @chapter Annotated List Of Files in the InnoDB Source Code Distribution ERRATUM BY HEIKKI TUURI (START) diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw index eef82588fa8..9903c91ba1b 100644 --- a/VC++Files/mysql.dsw +++ b/VC++Files/mysql.dsw @@ -605,6 +605,9 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name strings + End Project Dependency }}} ############################################################################### From d13e4fc5323d39740f4e7084ee7de5550283fef3 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 29 Apr 2003 00:15:18 +0200 Subject: [PATCH 116/188] CURRENT_USER() and "access denied" error messages now report hostname exactly as it was specified in the GRANT command (with wildcards, that is) --- BitKeeper/etc/logging_ok | 1 + sql/item_create.cc | 2 +- sql/sql_acl.cc | 18 ++++++++++-------- sql/sql_acl.h | 3 ++- sql/sql_class.h | 5 ++--- sql/sql_db.cc | 4 ++-- sql/sql_parse.cc | 9 +++++---- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index aca77159202..8074f38541a 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -79,6 +79,7 @@ salle@geopard.(none) salle@geopard.online.bg sasha@mysql.sashanet.com serg@build.mysql2.com +serg@serg.mylan serg@serg.mysql.com serg@sergbook.mysql.com sinisa@rhols221.adsl.netsonic.fi diff --git a/sql/item_create.cc b/sql/item_create.cc index 7e082bc174c..6809d6892b0 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -297,7 +297,7 @@ Item *create_func_current_user() char buff[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; uint length; - length= (uint) (strxmov(buff, thd->priv_user, "@", thd->host_or_ip, NullS) - + length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) - buff); return new Item_string(NullS, thd->memdup(buff, length), length); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 3f63344baba..e14fa891977 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -114,7 +114,7 @@ static ACL_USER *find_acl_user(const char *host, const char *user); static bool update_user_table(THD *thd, const char *host, const char *user, const char *new_password); static void update_hostname(acl_host_and_ip *host, const char *hostname); -static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, +static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, const char *ip); /* @@ -492,7 +492,8 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) */ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, - const char *password,const char *message,char **priv_user, + const char *password,const char *message, + char **priv_user, char **priv_host, bool old_ver, USER_RESOURCES *mqh) { ulong user_access=NO_ACCESS; @@ -526,10 +527,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, #ifdef HAVE_OPENSSL Vio *vio=thd->net.vio; /* - In this point we know that user is allowed to connect - from given host by given username/password pair. Now - we check if SSL is required, if user is using SSL and - if X509 certificate attributes are OK + In this point we know that user is allowed to connect + from given host by given username/password pair. Now + we check if SSL is required, if user is using SSL and + if X509 certificate attributes are OK */ switch (acl_user->ssl_type) { case SSL_TYPE_NOT_SPECIFIED: // Impossible @@ -577,7 +578,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, X509* cert=SSL_get_peer_certificate(vio->ssl_); DBUG_PRINT("info",("checkpoint 2")); /* If X509 issuer is speified, we check it... */ - if (acl_user->x509_issuer) + if (acl_user->x509_issuer) { DBUG_PRINT("info",("checkpoint 3")); char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); @@ -605,7 +606,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, if (strcmp(acl_user->x509_subject,ptr)) { if (global_system_variables.log_warnings) - sql_print_error("X509 subject mismatch: '%s' vs '%s'", + sql_print_error("X509 subject mismatch: '%s' vs '%s'", acl_user->x509_subject, ptr); user_access=NO_ACCESS; } @@ -622,6 +623,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, *mqh=acl_user->user_resource; if (!acl_user->user) *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */ + *priv_host=acl_user->host.hostname; break; } #ifndef ALLOW_DOWNGRADE_OF_USERS diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 6925b6b406c..26e445fb7ea 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -87,7 +87,8 @@ void acl_free(bool end=0); ulong acl_get(const char *host, const char *ip, const char *bin_ip, const char *user, const char *db); ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, - const char *password,const char *scramble,char **priv_user, + const char *password,const char *scramble, + char **priv_user, char **priv_host, bool old_ver, USER_RESOURCES *max); bool acl_check_host(const char *host, const char *ip); bool check_change_password(THD *thd, const char *host, const char *user); diff --git a/sql/sql_class.h b/sql/sql_class.h index ad0540de18c..26551b01da1 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -351,14 +351,14 @@ public: db - currently selected database ip - client IP */ - char *host,*user,*priv_user,*db,*ip; + char *host,*user,*priv_user,*priv_host,*db,*ip; /* remote (peer) port */ uint16 peer_port; /* Points to info-string that will show in SHOW PROCESSLIST */ const char *proc_info; /* points to host if host is available, otherwise points to ip */ const char *host_or_ip; - + uint client_capabilities; /* What the client supports */ /* Determines if which non-standard SQL behaviour should be enabled */ uint sql_mode; @@ -366,7 +366,6 @@ public: ulong master_access; /* Global privileges from mysql.user */ ulong db_access; /* Privileges for current db */ - /* open_tables - list of regular tables in use by this thread temporary_tables - list of temp tables in use by this thread diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 900c87d83a5..7e58b5d4582 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -362,11 +362,11 @@ bool mysql_change_db(THD *thd,const char *name) { net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, thd->priv_user, - thd->host_or_ip, + thd->priv_host, dbname); mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), thd->priv_user, - thd->host_or_ip, + thd->priv_host, dbname); my_free(dbname,MYF(0)); DBUG_RETURN(1); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7479ef653a9..33b6c3f45c0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -186,7 +186,7 @@ end: /* Check if user is ok Updates: - thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access + thd->{user,master_access,priv_user,priv_host,db,db_access} */ static bool check_user(THD *thd,enum_server_command command, const char *user, @@ -205,7 +205,8 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, return 1; } thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, - passwd, thd->scramble, &thd->priv_user, + passwd, thd->scramble, + &thd->priv_user, &thd->priv_host, protocol_version == 9 || !(thd->client_capabilities & CLIENT_LONG_PASSWORD),&ur); @@ -2566,7 +2567,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if (!no_errors) net_printf(&thd->net,ER_ACCESS_DENIED_ERROR, thd->priv_user, - thd->host_or_ip, + thd->priv_host, thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ } @@ -2591,7 +2592,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if (!no_errors) net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, thd->priv_user, - thd->host_or_ip, + thd->priv_host, db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ } From b86dc228874df509e1d138e0d5bf8b70943ffd24 Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Mon, 28 Apr 2003 16:40:33 -0700 Subject: [PATCH 117/188] Updated PeterG's internals documentation per comments from Monty; added additional description of MySQL's three types of record formats. --- Docs/internals.texi | 73 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index 270fe9e2249..bc417e250ca 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -2046,12 +2046,15 @@ And if you use Windows, you might find the files in this directory: @* @*@* Let's look at the .MYD Data file (MyISAM SQL Data file) more closely. +There are three possible formats -- fixed, dynamic, and packed. First, +let's discuss the fixed format. + @table @strong @item Page Size Unlike most DBMSs, MySQL doesn't store on disk using pages. Therefore you will not see filler space between rows. (Reminder: This does not -refer to BDB and INNODB tables, which do use pages). +refer to BDB and InnoDB tables, which do use pages). @* @item Record Header @@ -2069,8 +2072,8 @@ The minimal record header is a set of flags: The length of the record header is thus:@* (1 + number of NULL columns + 7) / 8 bytes@* -After the header, all columns are stored in -the order that they were created, which is the +After the header, all columns are stored in +the order that they were created, which is the same order that you would get from SHOW COLUMNS. Here's an example. Suppose you say: @@ -2115,10 +2118,72 @@ right is @code{on}, and (b) remember that the first flag bit is the X bit.) There are complications -- the record header is more complex if there are variable-length fields -- but the simple display shown in the -example is exactly what you'd see if you looked at the MySQL Data file +example is exactly what you'd see if you looked at the MySQL Data file with a debugger or a hexadecimal file dumper. @* +So much for the fixed format. Now, let's discuss the dynamic format. +@* + +The dynamic file format is necessary if rows can vary in size. That will +be the case if there are BLOB columns, or "true" VARCHAR columns. (Remember +that MySQL may treat VARCHAR columns as if they're CHAR columns, in which +case the fixed format is used.) A dynamic row has more fields in the header. +The important ones are "the actual length", "the unused length", and "the +overflow pointer". The actual length is the total number of bytes in all the +columns. The unused length is the total number of bytes between one physical +record and the next one. The overflow pointer is the location of the rest of +the record if there are multiple parts. +@* + +For example, here is a dynamic row:@* +@example( +03, 00 start of header +04 actual length +0c unused length +01, fc flags + overflow pointer +**** data in the row +************ unused bytes + <-- next row starts here) +@end example + +In the example, the actual length and the unused length +are short (one byte each) because the table definition +says that the columns are short -- if the columns were +potentially large, then the actual length and the unused +length could be two bytes each, three bytes each, and so +on. In this case, actual length plus unused length is 10 +hexadecimal (sixteen decimal), which is a minimum. + +As for the third format -- packed -- we will only say +briefly that: +@itemize @bullet +@item +Numeric values are stored in a form that depends on the +range (start/end values) for the data type. +@item +All columns are packed using either Huffman or enum coding. +@end itemize + +For details, see the source files /myisam/mi_statrec.c +(for fixed format), /myisam/mi_dynrec.c (for dynamic +format), and /myisam/mi_packrec.c (for packed format). + +Note: Internally, MySQL uses a format much like the fixed format +which it uses for disk storage. The main differences are: +@enumerate @bullet +@item +BLOBs have a length and a memory pointer rather than being stored inline. +@item +"True VARCHAR" (a column storage which will be fully implemented in +version 5.0) will have a 16-bit length plus the data. +@item +All integer or floating-point numbers are stored with the low byte first. +Point (3) does not apply for ISAM storage or internals. +@end enumerate +@* + + @section Physical Attributes of Columns Next I'll describe the physical attributes of each column in a row. From 04bf79ce6ae867cab26ffcb3235c56a46f88b205 Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Mon, 28 Apr 2003 17:01:19 -0700 Subject: [PATCH 118/188] Updated PeterG's internals documentation per comments from Monty; one minor change, plus addition of how HEAP works. --- Docs/internals.texi | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index bc417e250ca..df17da14bef 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -3553,7 +3553,7 @@ raw-flags -- more country flags, all .gif files @item support -- various files for generating texinfo/docbook documentation @item -to-be-included... -- an empty subdirectory +to-be-included... -- contains a MySQL-for-dummies file @item translations -- some Portuguese myodbc documentation @end itemize @@ -3609,7 +3609,11 @@ produces) have files with similar names and functions. Thus, this (for the MyISAM table handler). Such duplicates have been marked with an "*" in the following list. For example, you will find that \heap\hp_extra.c has a close equivalent in the myisam directory -(\myisam\mi_extra.c) with the same descriptive comment. +(\myisam\mi_extra.c) with the same descriptive comment. (Some of the +differences arise because HEAP has different structures. HEAP does not +need to use the sort of B-tree indexing that ISAM and MyISAM use; instead +there is a hash index. Most importantly, HEAP is entirely in memory. +File-I/O routines lose some of their vitality in such a context.) @*@* @itemize From f0d57daf44f2b9acada5df30a64e816eeb422d1e Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Mon, 28 Apr 2003 17:13:48 -0700 Subject: [PATCH 119/188] Updated PeterG's internals documentation per comments from Monty; new description of /man subdirectory --- Docs/internals.texi | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index df17da14bef..9557481cc0a 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -3774,8 +3774,10 @@ lib_vio.c -- Emulate the vio directory's communication buffer Some user-contributed manual pages @*@* -These are not the actual "man" (manual) pages, they are switches for -the production. +These are user-contributed "man" (manual) pages in a special markup +format. The format is described in a document with a heading like +"man page for man" or "macros to format man pages" which you can find +in a Linux directory or on the Internet. @*@* @subsection myisam @@ -3787,13 +3789,13 @@ The C files in this subdirectory come in six main groups: @itemize @bullet @item ft*.c files -- ft stands for "Full Text", code contributed by Sergei -Golubchik +Golubchik @item mi*.c files -- mi stands for "My Isam", these are the main programs -for Myisam +for Myisam @item myisam*.c files -- for example, "myisamchk" utility routine -functions source +functions source @item rt*.c files -- rt stands for "rtree", some code was written by Alexander Barkov From e600aa8c45007b3c54a32ce50a8e5d2f0f61118f Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Mon, 28 Apr 2003 17:20:26 -0700 Subject: [PATCH 120/188] Updated PeterG's internals documentation per comments from Monty; minor changes only. --- Docs/internals.texi | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index 9557481cc0a..b6dc3ccc10c 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -2406,9 +2406,6 @@ of correspondence between the BLOB and the INT types. There isn't -- a BLOB's preceding length is not four bytes long (the size of an INT). @* -(NOTE TO SELF: BLOB storage has not been fully addressed here.) -@* - @strong{TINYBLOB} @itemize @bullet @item @@ -4744,8 +4741,7 @@ bmove_upp.c -- bmove.c variant, starting with last byte @item bzero.c -- something like bfill with an argument of 0 @item -conf_to_src.c -- reading a configuration file (NOTE TO SELF ? what's -this doing here?) +conf_to_src.c -- reading a configuration file @item ctype*.c -- string handling programs for each char type MySQL handles From 31b61445505ee54837529039771cc782012e0b76 Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Mon, 28 Apr 2003 18:21:06 -0700 Subject: [PATCH 121/188] Updated PeterG's internals documentation per comments from Monty; clarified differences between the MySQL library directories. --- Docs/internals.texi | 54 +++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index b6dc3ccc10c..7cdac236aa6 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -3715,25 +3715,33 @@ sending messages, the client part merely calls the server part. The libmysql files are split into three directories: libmysql (this one), libmysql_r (the next one), and libmysqld (the next one after -that). It may be that the original intention was that the libmysql -directory would hold the "client part" files, and the libmysqld -directory would hold the "server part" files. +that). +@*@* + +The "library of mysql" has some client-connection +modules. For example, as described in an earlier +section of this manual, there is a discussion of +libmysql/libmysql.c which sends packets from the +client to the server. Many of the entries in the +libmysql directory (and in the following libmysqld +directory) are 'symlinks' on Linux, that is, they +are in fact pointers to files in other directories. @*@* The program files on this directory are: @itemize @bullet @item -conf_to_src.c -- has to do with charsets +conf_to_src.c -- has to do with charsets @item -dll.c -- initialization of the dll library +dll.c -- initialization of the dll library @item -errmsg.c -- English error messages, compare \mysys\errors.c +errmsg.c -- English error messages, compare \mysys\errors.c @item -get_password.c -- get password +get_password.c -- get password @item libmysql.c -- the code that implements the MySQL API, i.e. the functions a client that wants to connect to MySQL will call @item -manager.c -- initialize/connect/fetch with MySQL manager +manager.c -- initialize/connect/fetch with MySQL manager @end itemize @*@* @@ -3742,8 +3750,7 @@ manager.c -- initialize/connect/fetch with MySQL manager The MySQL Library, Part 2. @*@* -This is a continuation of the libmysql directory. There is only one -file here, used to build a thread-safe libmysql library: +There is only one file here, used to build a thread-safe libmysql library: @itemize @bullet @item makefile.am @@ -3755,8 +3762,9 @@ makefile.am The MySQL library, Part 3. @*@* -This is a continuation of the libmysql directory and contains the MySQL -Server as an embeddable library. The program files on this directory +The Embedded MySQL Server Library. The product of libmysqld +is not a client/server affair, but a library. There is a wrapper +to emulate the client calls. The program files on this directory are: @itemize @bullet @item @@ -3771,9 +3779,9 @@ lib_vio.c -- Emulate the vio directory's communication buffer Some user-contributed manual pages @*@* -These are user-contributed "man" (manual) pages in a special markup +These are user-contributed "man" (manual) pages in a special markup format. The format is described in a document with a heading like -"man page for man" or "macros to format man pages" which you can find +"man page for man" or "macros to format man pages" which you can find in a Linux directory or on the Internet. @*@* @@ -3785,23 +3793,17 @@ The MyISAM table handler. The C files in this subdirectory come in six main groups: @itemize @bullet @item -ft*.c files -- ft stands for "Full Text", code contributed by Sergei -Golubchik +ft*.c files -- ft stands for "Full Text", code contributed by Sergei Golubchik @item -mi*.c files -- mi stands for "My Isam", these are the main programs -for Myisam +mi*.c files -- mi stands for "My Isam", these are the main programs for Myisam @item -myisam*.c files -- for example, "myisamchk" utility routine -functions source +myisam*.c files -- for example, "myisamchk" utility routine functions source @item -rt*.c files -- rt stands for "rtree", some code was written by -Alexander Barkov +rt*.c files -- rt stands for "rtree", some code was written by Alexander Barkov @item -sp*.c files -- sp stands for "spatial", some code was written by -Ramil Kalimullin +sp*.c files -- sp stands for "spatial", some code was written by Ramil Kalimullin @item -sort.c -- this is a single file that sorts keys for index-create -purposes +sort.c -- this is a single file that sorts keys for index-create purposes @end itemize @*@* From 208fec78b22fe6e0d9e2258c07b567aab3f90603 Mon Sep 17 00:00:00 2001 From: "peterg@mysql.com" <> Date: Mon, 28 Apr 2003 18:52:04 -0700 Subject: [PATCH 122/188] Update PeterG's internals documentation per comments from Monty; minor changes only. --- Docs/internals.texi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index 7cdac236aa6..0fa6122865b 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -4615,7 +4615,7 @@ sql_olap.cc -- ROLLUP @item sql_parse.cc -- Parse an SQL statement; do initial checks and then jump to the function that should execute the statement @item -sql_prepare.cc -- Prepare an SQL statement +sql_prepare.cc -- Prepare an SQL statement, or use a prepared statement @item sql_repl.cc -- Replication @item @@ -5026,11 +5026,11 @@ variation of the famous "Lempel-Ziv" method, which is also used by bytes is as follows: @itemize @bullet @item -Find a substring which occurs twice in the string. +Find a substring which occurs twice in the string. @item Replace the second occurrence of the substring with (a) a pointer to the first occurrence, plus (b) an indication of the length of the -first occurrence. +first occurrence. @end itemize There is a full description of the library's functions in the gzip @@ -5039,9 +5039,9 @@ manual at: @* There is therefore no need to list the modules in this document. @*@* -The MySQL program that uses zlib is \mysys\my_compress.c. The use is -for packet compression. The client sends messages to the server which -are compressed by zlib. See also: \sql\net_serv.cc. +The MySQL program \mysys\my_compress.c uses zlib for packet compression. +The client sends messages to the server which are compressed by zlib. +See also: \sql\net_serv.cc. @node Files in InnoDB Sources, , Files in MySQL Sources, Top @chapter Annotated List Of Files in the InnoDB Source Code Distribution From 75c5ebe6591b49f7530d30963ce6198a26bb1c68 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 29 Apr 2003 09:52:14 +0200 Subject: [PATCH 123/188] - minor fixups (no more warnings) - the preferred mailing list is internals@ not dev-public@ (this is a public document) - Rather use the 4.1 tree for new development (4.0 is frozen) --- .bzrignore | 4 ++++ Docs/internals.texi | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.bzrignore b/.bzrignore index 5d5909ce4da..a18a5008cb0 100644 --- a/.bzrignore +++ b/.bzrignore @@ -531,3 +531,7 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl support-files/MacOSX/ReadMe.txt +Docs/internals.html +Docs/internals.pdf +Docs/internals.txt +Docs/internals_toc.html diff --git a/Docs/internals.texi b/Docs/internals.texi index 0fa6122865b..a54f5098e5d 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -76,12 +76,11 @@ This is a manual about @strong{MySQL} internals. We use @uref{http://www.bitkeeper.com/, BitKeeper} for source management. @item -You should use the @strong{MySQL} 4.0 source for all developments. +You should use the @strong{MySQL} 4.1 source for all developments. @item If you have any questions about the @strong{MySQL} source, you can post these -to @email{dev-public@@mysql.com} and we will answer them. Please -remember to not use this internal email list in public! +to @email{internals@@mysql.com} and we will answer them. @item Try to write code in a lot of black boxes that can be reused or use at @@ -2136,8 +2135,9 @@ record and the next one. The overflow pointer is the location of the rest of the record if there are multiple parts. @* -For example, here is a dynamic row:@* -@example( +For example, here is a dynamic row: +@* +@example 03, 00 start of header 04 actual length 0c unused length @@ -2171,7 +2171,7 @@ format), and /myisam/mi_packrec.c (for packed format). Note: Internally, MySQL uses a format much like the fixed format which it uses for disk storage. The main differences are: -@enumerate @bullet +@enumerate @item BLOBs have a length and a memory pointer rather than being stored inline. @item From 89d9766fd2ee813e2f64fa8c617475ebf0651669 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Tue, 29 Apr 2003 14:13:22 +0300 Subject: [PATCH 124/188] code cleanup --- mysql-test/r/innodb.result | 1 + mysql-test/t/innodb.test | 2 +- sql/sql_base.cc | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index aefcd135dd8..39214348244 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1219,6 +1219,7 @@ parent child 1 2 1 3 2 1 +drop table t1; create table t1 (a int not null auto_increment primary key, b int, c int, key(c)) type=innodb; create table t2 (a int not null auto_increment primary key, b int); insert into t1 (b) values (null),(null),(null),(null),(null),(null),(null); diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 393112beb27..4fb9351020e 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -809,7 +809,7 @@ drop table t1,t2; create table t1 ( pk int primary key, parent int not null, child int not null, index (parent) ) type = innodb; insert into t1 values (1,0,4), (2,1,3), (3,2,1), (4,1,2); select distinct parent,child from t1 order by parent; -drop table t1,t2; +drop table t1; # # Test that MySQL priorities clustered indexes diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e27ccf55543..d01dc50cf9d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1984,7 +1984,8 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, (!db_name || !strcmp(tables->db,db_name)))) { /* Ensure that we have access right to all columns */ - if (grant_option && !thd->master_access && + if (grant_option && !((thd->master_access | table->grant.privilege) & + table->grant.want_privilege) && check_grant_all_columns(thd,SELECT_ACL,table) ) DBUG_RETURN(-1); Field **ptr=table->field,*field; From 2f45dd04a051be2bb58323df15e2881d834b91de Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 29 Apr 2003 15:11:45 +0200 Subject: [PATCH 125/188] followup to CURRENT_USER() fix --- libmysqld/lib_sql.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 641fd2bb2c1..4e85c29c2f2 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -225,7 +225,8 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, return 1; } thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, - passwd, thd->scramble, &thd->priv_user, + passwd, thd->scramble, + &thd->priv_user, &thd->priv_host, protocol_version == 9 || !(thd->client_capabilities & CLIENT_LONG_PASSWORD),&ur); From 0ed1cbbd48944fb844adcf8482e39781606eecd1 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Tue, 29 Apr 2003 18:24:33 +0300 Subject: [PATCH 126/188] Porting back security fix from 4.0. All tests plus grant.pl test passed. --- sql/sql_base.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f0b370c23d7..46370949650 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1878,8 +1878,9 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, for (; tables ; tables=tables->next) { TABLE *table=tables->table; - if (grant_option && !thd->master_access && - check_grant_all_columns(thd,SELECT_ACL,table) ) + if (grant_option && !(table->grant.privilege & + table->grant.want_privilege) && + check_grant_all_columns(thd,SELECT_ACL,table)) DBUG_RETURN(-1); if (!table_name || (!strcmp(table_name,tables->alias) && (!db_name || !tables->db || From 9e4f394e59e6047609032344b46b7432b43840ac Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 30 Apr 2003 10:15:09 +0300 Subject: [PATCH 127/188] Fix reference to not initialized memory Changed handing of priv_host to fix bug in FLUSH PRIVILEGES --- libmysqld/lib_sql.cc | 2 +- myisam/mi_rkey.c | 9 ++++++--- sql/sql_acl.cc | 7 +++++-- sql/sql_acl.h | 2 +- sql/sql_class.h | 3 ++- sql/sql_parse.cc | 2 +- sql/unireg.h | 1 + 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 4e85c29c2f2..83f398ca50b 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -226,7 +226,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, } thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, passwd, thd->scramble, - &thd->priv_user, &thd->priv_host, + &thd->priv_user, thd->priv_host, protocol_version == 9 || !(thd->client_capabilities & CLIENT_LONG_PASSWORD),&ur); diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 60dec0449a0..1bb478efd3d 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -93,13 +93,16 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, rw_unlock(&share->key_root_lock[inx]); /* Calculate length of the found key; Used by mi_rnext_same */ - if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg) + if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg && + info->lastpos != HA_OFFSET_ERROR) info->last_rkey_length= _mi_keylength_part(keyinfo, info->lastkey, last_used_keyseg); else info->last_rkey_length= pack_key_length; + + /* Check if we don't want to have record back, only error message */ if (!buf) - DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); + DBUG_RETURN(info->lastpos == HA_OFFSET_ERROR ? my_errno : 0); if (!(*info->read_record)(info,info->lastpos,buf)) { @@ -109,7 +112,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, info->lastpos = HA_OFFSET_ERROR; /* Didn't find key */ - /* Store key for read next */ + /* Store last used key as a base for read next */ memcpy(info->lastkey,key_buff,pack_key_length); info->last_rkey_length= pack_key_length; bzero((char*) info->lastkey+pack_key_length,info->s->base.rec_reflength); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e14fa891977..bdf1a2ac716 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -493,7 +493,7 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, const char *password,const char *message, - char **priv_user, char **priv_host, + char **priv_user, char *priv_host, bool old_ver, USER_RESOURCES *mqh) { ulong user_access=NO_ACCESS; @@ -623,7 +623,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, *mqh=acl_user->user_resource; if (!acl_user->user) *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */ - *priv_host=acl_user->host.hostname; + if (acl_user->host.hostname) + strmake(priv_host, acl_user->host.hostname, MAX_HOSTNAME); + else + *priv_host= 0; break; } #ifndef ALLOW_DOWNGRADE_OF_USERS diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 26e445fb7ea..1d074fe6001 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -88,7 +88,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip, const char *user, const char *db); ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, const char *password,const char *scramble, - char **priv_user, char **priv_host, + char **priv_user, char *priv_host, bool old_ver, USER_RESOURCES *max); bool acl_check_host(const char *host, const char *ip); bool check_change_password(THD *thd, const char *host, const char *user); diff --git a/sql/sql_class.h b/sql/sql_class.h index 26551b01da1..160c06ca3c6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -351,7 +351,8 @@ public: db - currently selected database ip - client IP */ - char *host,*user,*priv_user,*priv_host,*db,*ip; + char *host,*user,*priv_user,*db,*ip; + char priv_host[MAX_HOSTNAME]; /* remote (peer) port */ uint16 peer_port; /* Points to info-string that will show in SHOW PROCESSLIST */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 33b6c3f45c0..8d4ae065aa6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -206,7 +206,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, } thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, passwd, thd->scramble, - &thd->priv_user, &thd->priv_host, + &thd->priv_user, thd->priv_host, protocol_version == 9 || !(thd->client_capabilities & CLIENT_LONG_PASSWORD),&ur); diff --git a/sql/unireg.h b/sql/unireg.h index 7e98d0d3cbe..f69d67455dd 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -55,6 +55,7 @@ #else #define MAX_REFLENGTH 4 /* Max length for record ref */ #endif +#define MAX_HOSTNAME 61 /* len+1 in mysql.user */ #define MAX_FIELD_WIDTH 256 /* Max column width +1 */ #define MAX_TABLES (sizeof(table_map)*8-1) /* Max tables in join */ From 5f830363f2efff0b40b52c0a32d14cd3054773cb Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 30 Apr 2003 11:27:13 +0200 Subject: [PATCH 128/188] - disabled MyISAM RAID (--with-raid) for the 4.0 Max binaries for now (several users reported crashes, even when not using RAID) (see bug #346) --- support-files/mysql.spec.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 500b308e686..64a1a73bad5 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -16,7 +16,7 @@ Copyright: GPL Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz Icon: mysql.gif URL: http://www.mysql.com/ -Packager: Lenz Grimmer +Packager: Lenz Grimmer Vendor: MySQL AB Requires: fileutils sh-utils Provides: msqlormysql MySQL-server mysql @@ -257,7 +257,6 @@ export PATH BuildMySQL "--enable-shared \ --with-berkeley-db \ --with-innodb \ - --with-raid \ --with-server-suffix='-Max'" # Save everything for debug @@ -536,6 +535,11 @@ fi %changelog +* Wed Apr 30 2003 Lenz Grimmer + +- disabled MyISAM RAID (--with-raid) - it throws an assertion which + needs to be investigated first. + * Mon Mar 10 2003 Lenz Grimmer - added missing file mysql_secure_installation to server subpackage From 66997c0fb3b200158956d93dc70347408e16c37c Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Wed, 30 Apr 2003 11:30:45 +0200 Subject: [PATCH 129/188] - fixed Max RPM package description (removed RAID) --- support-files/mysql.spec.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 64a1a73bad5..9f8b29ab697 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -146,7 +146,7 @@ languages and applications need to dynamically load and use MySQL. %package Max Release: %{release} -Summary: MySQL - server with Berkeley DB, RAID and UDF support +Summary: MySQL - server with Berkeley BD and UDF support Group: Applications/Databases Provides: mysql-Max Obsoletes: mysql-Max @@ -154,7 +154,7 @@ Requires: MySQL >= 4.0 %description Max Optional MySQL server binary that supports additional features like -Berkeley DB, RAID and User Defined Functions (UDF). +Berkeley DB and User Defined Functions (UDFs). To activate this binary, just install this package in addition to the standard MySQL package. From f69b6e041c54a850e13881f9a85a8745dc7f9e20 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Wed, 30 Apr 2003 12:32:43 +0200 Subject: [PATCH 130/188] more #ifdef THREAD added --- include/my_semaphore.h | 5 +++++ mysys/my_semaphore.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/my_semaphore.h b/include/my_semaphore.h index 3431212ec82..7f182bea6bf 100644 --- a/include/my_semaphore.h +++ b/include/my_semaphore.h @@ -31,6 +31,8 @@ #ifndef _my_semaphore_h_ #define _my_semaphore_h_ +#ifdef THREAD + C_MODE_START #ifdef HAVE_SEMAPHORE_H #include @@ -56,4 +58,7 @@ int sem_getvalue(sem_t * sem, unsigned int * sval); #endif /* !__bsdi__ */ C_MODE_END + +#endif /* THREAD */ + #endif /* !_my_semaphore_h_ */ diff --git a/mysys/my_semaphore.c b/mysys/my_semaphore.c index 2dd224cd99e..aa216cbc289 100644 --- a/mysys/my_semaphore.c +++ b/mysys/my_semaphore.c @@ -23,7 +23,7 @@ #include #include -#if !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) +#if !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) && defined(THREAD) int sem_init(sem_t * sem, int pshared, uint value) { @@ -101,4 +101,4 @@ int sem_getvalue(sem_t * sem, uint *sval) return 0; } -#endif /* !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) */ +#endif /* !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) && defined(THREAD) */ From 64b0bfcf00c402d9ec1bcc687023432993a17f39 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 30 Apr 2003 17:39:23 +0300 Subject: [PATCH 131/188] removing architecture dependent test --- mysql-test/r/func_misc.result | 3 --- mysql-test/t/func_misc.test | 1 - 2 files changed, 4 deletions(-) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 67f43ca5ba4..4eed80c4cc9 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -10,6 +10,3 @@ inet_aton("255.255.255.255.255") inet_aton("255.255.1.255") inet_aton("0.1.255") select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511); inet_ntoa(1099511627775) inet_ntoa(4294902271) inet_ntoa(511) NULL 255.255.1.255 0.0.1.255 -select format("nan",2); -format("nan",2) -nan diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index d9ae288cc59..d48b17e87af 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -7,4 +7,3 @@ select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.5555 select inet_ntoa(inet_aton("255.255.255.255.255.255.255.255")); select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255"); select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511); -select format("nan",2); From fe560da59f655ce10077dead04aac967e94f845d Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Fri, 2 May 2003 22:12:15 +0200 Subject: [PATCH 132/188] avoid sigsegv when open_ltable() fails in REPAIR ... USE_FRM --- sql/sql_table.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 94b37e164e7..745d9ea1084 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1049,6 +1049,11 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table, { DBUG_ENTER("prepare_for_repair"); + if (!table->table) + { + DBUG_RETURN(send_check_errmsg(thd, table, "repair", "table is read-only or does not exists")); + } + if (!(check_opt->sql_flags & TT_USEFRM)) { DBUG_RETURN(0); From 35fd869e5176f9f9a16171a3715bfb4190c62172 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 3 May 2003 02:29:40 +0300 Subject: [PATCH 133/188] Many files: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released --- innobase/buf/buf0flu.c | 2 +- innobase/include/log0log.h | 65 ++++++++------- innobase/include/trx0trx.h | 14 ++++ innobase/log/log0log.c | 158 +++++++++++++++++-------------------- innobase/os/os0file.c | 7 +- innobase/row/row0mysql.c | 2 +- innobase/srv/srv0srv.c | 17 ++-- innobase/trx/trx0trx.c | 48 ++++++++++- sql/ha_innodb.cc | 64 ++++++++++----- sql/ha_innodb.h | 2 + sql/handler.cc | 30 ++++++- sql/handler.h | 1 + sql/log.cc | 20 ++++- 13 files changed, 276 insertions(+), 154 deletions(-) diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 516056b5174..4d998f8306f 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -398,7 +398,7 @@ buf_flush_write_block_low( "Warning: cannot force log to disk in the log debug version!\n"); #else /* Force the log to the disk before writing the modified block */ - log_flush_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS); + log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE); #endif buf_flush_init_for_writing(block->frame, block->newest_modification, block->space, block->offset); diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h index f200371de9d..4e1404b15fe 100644 --- a/innobase/include/log0log.h +++ b/innobase/include/log0log.h @@ -20,7 +20,7 @@ typedef struct log_group_struct log_group_t; extern ibool log_do_write; extern ibool log_debug_writes; -/* Wait modes for log_flush_up_to */ +/* Wait modes for log_write_up_to */ #define LOG_NO_WAIT 91 #define LOG_WAIT_ONE_GROUP 92 #define LOG_WAIT_ALL_GROUPS 93 @@ -157,26 +157,21 @@ log_io_complete( /*============*/ log_group_t* group); /* in: log group */ /********************************************************** -Flushes the log files to the disk, using, for example, the Unix fsync. -This function does the flush even if the user has set -srv_flush_log_at_trx_commit = FALSE. */ - -void -log_flush_to_disk(void); -/*===================*/ -/********************************************************** This function is called, e.g., when a transaction wants to commit. It checks -that the log has been flushed to disk up to the last log entry written by the -transaction. If there is a flush running, it waits and checks if the flush -flushed enough. If not, starts a new flush. */ +that the log has been written to the log file up to the last log entry written +by the transaction. If there is a flush running, it waits and checks if the +flush flushed enough. If not, starts a new flush. */ void -log_flush_up_to( +log_write_up_to( /*============*/ dulint lsn, /* in: log sequence number up to which the log should - be flushed, ut_dulint_max if not specified */ - ulint wait); /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP, + be written, ut_dulint_max if not specified */ + ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP, or LOG_WAIT_ALL_GROUPS */ + ibool flush_to_disk); + /* in: TRUE if we want the written log also to be + flushed to disk */ /******************************************************************** Advances the smallest lsn for which there are unflushed dirty blocks in the buffer pool and also may make a new checkpoint. NOTE: this function may only @@ -741,27 +736,37 @@ struct log_struct{ be advanced, it is enough that the write i/o has been completed for all log groups */ - dulint flush_lsn; /* end lsn for the current flush */ - ulint flush_end_offset;/* the data in buffer has been flushed + dulint write_lsn; /* end lsn for the current running + write */ + ulint write_end_offset;/* the data in buffer has been written up to this offset when the current - flush ends: this field will then + write ends: this field will then be copied to buf_next_to_write */ - ulint n_pending_writes;/* number of currently pending flush - writes */ + dulint current_flush_lsn;/* end lsn for the current running + write + flush operation */ + dulint flushed_to_disk_lsn; + /* how far we have written the log + AND flushed to disk */ + ulint n_pending_writes;/* number of currently pending flushes + or writes */ + /* NOTE on the 'flush' in names of the fields below: starting from + 4.0.14, we separate the write of the log file and the actual fsync() + or other method to flush it to disk. The names below shhould really + be 'flush_or_write'! */ os_event_t no_flush_event; /* this event is in the reset state - when a flush is running; a thread - should wait for this without owning - the log mutex, but NOTE that to set or - reset this event, the thread MUST own - the log mutex! */ + when a flush or a write is running; + a thread should wait for this without + owning the log mutex, but NOTE that + to set or reset this event, the + thread MUST own the log mutex! */ ibool one_flushed; /* during a flush, this is first FALSE and becomes TRUE when one log group - has been flushed */ + has been written or flushed */ os_event_t one_flushed_event;/* this event is reset when the - flush has not yet completed for any - log group; e.g., this means that a - transaction has been committed when - this is set; a thread should wait + flush or write has not yet completed + for any log group; e.g., this means + that a transaction has been committed + when this is set; a thread should wait for this without owning the log mutex, but NOTE that to set or reset this event, the thread MUST own the log diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index be96519c4ea..39229923375 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -157,6 +157,15 @@ trx_commit_for_mysql( /* out: 0 or error number */ trx_t* trx); /* in: trx handle */ /************************************************************************** +If required, flushes the log to disk if we called trx_commit_for_mysql() +with trx->flush_log_later == TRUE. */ + +ulint +trx_commit_complete_for_mysql( +/*==========================*/ + /* out: 0 or error number */ + trx_t* trx); /* in: trx handle */ +/************************************************************************** Marks the latest SQL statement ended. */ void @@ -343,6 +352,11 @@ struct trx_struct{ dulint no; /* transaction serialization number == max trx id when the transaction is moved to COMMITTED_IN_MEMORY state */ + ibool flush_log_later;/* when we commit the transaction + in MySQL's binlog write, we will + flush the log to disk later in + a separate call */ + dulint commit_lsn; /* lsn at the time of the commit */ ibool dict_operation; /* TRUE if the trx is used to create a table, create an index, or drop a table */ diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index 539cde337bd..25cc666e802 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -178,7 +178,7 @@ loop: /* Not enough free space, do a syncronous flush of the log buffer */ - log_flush_up_to(ut_dulint_max, LOG_WAIT_ALL_GROUPS); + log_write_up_to(ut_dulint_max, LOG_WAIT_ALL_GROUPS, TRUE); count++; @@ -675,7 +675,9 @@ log_init(void) log_sys->buf_next_to_write = 0; - log_sys->flush_lsn = ut_dulint_zero; + log_sys->write_lsn = ut_dulint_zero; + log_sys->current_flush_lsn = ut_dulint_zero; + log_sys->flushed_to_disk_lsn = ut_dulint_zero; log_sys->written_to_some_lsn = log_sys->lsn; log_sys->written_to_all_lsn = log_sys->lsn; @@ -867,7 +869,7 @@ log_group_check_flush_completion( printf("Log flushed first to group %lu\n", group->id); } - log_sys->written_to_some_lsn = log_sys->flush_lsn; + log_sys->written_to_some_lsn = log_sys->write_lsn; log_sys->one_flushed = TRUE; return(LOG_UNLOCK_NONE_FLUSHED_LOCK); @@ -896,15 +898,15 @@ log_sys_check_flush_completion(void) if (log_sys->n_pending_writes == 0) { - log_sys->written_to_all_lsn = log_sys->flush_lsn; - log_sys->buf_next_to_write = log_sys->flush_end_offset; + log_sys->written_to_all_lsn = log_sys->write_lsn; + log_sys->buf_next_to_write = log_sys->write_end_offset; - if (log_sys->flush_end_offset > log_sys->max_buf_free / 2) { + if (log_sys->write_end_offset > log_sys->max_buf_free / 2) { /* Move the log buffer content to the start of the buffer */ move_start = ut_calc_align_down( - log_sys->flush_end_offset, + log_sys->write_end_offset, OS_FILE_LOG_BLOCK_SIZE); move_end = ut_calc_align(log_sys->buf_free, OS_FILE_LOG_BLOCK_SIZE); @@ -981,57 +983,6 @@ log_io_complete( mutex_exit(&(log_sys->mutex)); } -/********************************************************** -Flushes the log files to the disk, using, for example, the Unix fsync. -This function does the flush even if the user has set -srv_flush_log_at_trx_commit = FALSE. */ - -void -log_flush_to_disk(void) -/*===================*/ -{ - log_group_t* group; -loop: - mutex_enter(&(log_sys->mutex)); - - if (log_sys->n_pending_writes > 0) { - /* A log file write is running */ - - mutex_exit(&(log_sys->mutex)); - - /* Wait for the log file write to complete and try again */ - - os_event_wait(log_sys->no_flush_event); - - goto loop; - } - - group = UT_LIST_GET_FIRST(log_sys->log_groups); - - log_sys->n_pending_writes++; - group->n_pending_writes++; - - os_event_reset(log_sys->no_flush_event); - os_event_reset(log_sys->one_flushed_event); - - mutex_exit(&(log_sys->mutex)); - - fil_flush(group->space_id); - - mutex_enter(&(log_sys->mutex)); - - ut_a(group->n_pending_writes == 1); - ut_a(log_sys->n_pending_writes == 1); - - group->n_pending_writes--; - log_sys->n_pending_writes--; - - os_event_set(log_sys->no_flush_event); - os_event_set(log_sys->one_flushed_event); - - mutex_exit(&(log_sys->mutex)); -} - /********************************************************** Writes a log file header to a log file space. */ static @@ -1205,12 +1156,15 @@ by the transaction. If there is a flush running, it waits and checks if the flush flushed enough. If not, starts a new flush. */ void -log_flush_up_to( +log_write_up_to( /*============*/ dulint lsn, /* in: log sequence number up to which the log should be written, ut_dulint_max if not specified */ - ulint wait) /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP, + ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP, or LOG_WAIT_ALL_GROUPS */ + ibool flush_to_disk) + /* in: TRUE if we want the written log also to be + flushed to disk */ { log_group_t* group; ulint start_offset; @@ -1239,9 +1193,18 @@ loop: mutex_enter(&(log_sys->mutex)); - if ((ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0) - || ((ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0) - && (wait != LOG_WAIT_ALL_GROUPS))) { + if (flush_to_disk + && ut_dulint_cmp(log_sys->flushed_to_disk_lsn, lsn) >= 0) { + + mutex_exit(&(log_sys->mutex)); + + return; + } + + if (!flush_to_disk + && (ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0 + || (ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0 + && wait != LOG_WAIT_ALL_GROUPS))) { mutex_exit(&(log_sys->mutex)); @@ -1249,10 +1212,19 @@ loop: } if (log_sys->n_pending_writes > 0) { - /* A flush is running */ + /* A write (+ possibly flush to disk) is running */ - if (ut_dulint_cmp(log_sys->flush_lsn, lsn) >= 0) { - /* The flush will flush enough: wait for it to + if (flush_to_disk + && ut_dulint_cmp(log_sys->current_flush_lsn, lsn) >= 0) { + /* The write + flush will write enough: wait for it to + complete */ + + goto do_waits; + } + + if (!flush_to_disk + && ut_dulint_cmp(log_sys->write_lsn, lsn) >= 0) { + /* The write will write enough: wait for it to complete */ goto do_waits; @@ -1260,16 +1232,17 @@ loop: mutex_exit(&(log_sys->mutex)); - /* Wait for the flush to complete and try to start a new - flush */ + /* Wait for the write to complete and try to start a new + write */ os_event_wait(log_sys->no_flush_event); goto loop; } - if (log_sys->buf_free == log_sys->buf_next_to_write) { - /* Nothing to flush */ + if (!flush_to_disk + && log_sys->buf_free == log_sys->buf_next_to_write) { + /* Nothing to write and no flush to disk requested */ mutex_exit(&(log_sys->mutex)); @@ -1277,7 +1250,7 @@ loop: } if (log_debug_writes) { - printf("Flushing log from %lu %lu up to lsn %lu %lu\n", + printf("Writing log from %lu %lu up to lsn %lu %lu\n", ut_dulint_get_high(log_sys->written_to_all_lsn), ut_dulint_get_low(log_sys->written_to_all_lsn), ut_dulint_get_high(log_sys->lsn), @@ -1301,7 +1274,12 @@ loop: ut_ad(area_end - area_start > 0); - log_sys->flush_lsn = log_sys->lsn; + log_sys->write_lsn = log_sys->lsn; + + if (flush_to_disk) { + log_sys->current_flush_lsn = log_sys->lsn; + } + log_sys->one_flushed = FALSE; log_block_set_flush_bit(log_sys->buf + area_start, TRUE); @@ -1318,10 +1296,12 @@ loop: OS_FILE_LOG_BLOCK_SIZE); log_sys->buf_free += OS_FILE_LOG_BLOCK_SIZE; - log_sys->flush_end_offset = log_sys->buf_free; + log_sys->write_end_offset = log_sys->buf_free; group = UT_LIST_GET_FIRST(log_sys->log_groups); + /* Do the write to the log files */ + while (group) { log_group_write_buf(LOG_FLUSH, group, log_sys->buf + area_start, @@ -1330,20 +1310,25 @@ loop: OS_FILE_LOG_BLOCK_SIZE), start_offset - area_start); - log_group_set_fields(group, log_sys->flush_lsn); + log_group_set_fields(group, log_sys->write_lsn); group = UT_LIST_GET_NEXT(log_groups, group); } mutex_exit(&(log_sys->mutex)); - if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC - && srv_unix_file_flush_method != SRV_UNIX_NOSYNC - && srv_flush_log_at_trx_commit != 2) { + if (srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) { + /* O_DSYNC means the OS did not buffer the log file at all: + so we have also flushed to disk what we have written */ + + log_sys->flushed_to_disk_lsn = log_sys->write_lsn; + + } else if (flush_to_disk) { group = UT_LIST_GET_FIRST(log_sys->log_groups); fil_flush(group->space_id); + log_sys->flushed_to_disk_lsn = log_sys->write_lsn; } mutex_enter(&(log_sys->mutex)); @@ -1403,7 +1388,7 @@ log_flush_margin(void) mutex_exit(&(log->mutex)); if (do_flush) { - log_flush_up_to(ut_dulint_max, LOG_NO_WAIT); + log_write_up_to(ut_dulint_max, LOG_NO_WAIT, FALSE); } } @@ -1555,7 +1540,8 @@ log_group_checkpoint( buf = group->checkpoint_buf; mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no); - mach_write_to_8(buf + LOG_CHECKPOINT_LSN, log_sys->next_checkpoint_lsn); + mach_write_to_8(buf + LOG_CHECKPOINT_LSN, + log_sys->next_checkpoint_lsn); mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET, log_group_calc_lsn_offset( @@ -1664,8 +1650,10 @@ log_reset_first_header_and_checkpoint( lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE); /* Write the label of ibbackup --restore */ - sprintf((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup "); - ut_sprintf_timestamp((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP + sprintf((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, + "ibbackup "); + ut_sprintf_timestamp( + (char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP + strlen("ibbackup ")); buf = hdr_buf + LOG_CHECKPOINT_1; @@ -1773,7 +1761,7 @@ log_checkpoint( write-ahead-logging algorithm ensures that the log has been flushed up to oldest_lsn. */ - log_flush_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS); + log_write_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS, TRUE); mutex_enter(&(log_sys->mutex)); @@ -2466,7 +2454,7 @@ loop: mutex_exit(&(log_sys->mutex)); - log_flush_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS); + log_write_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS, TRUE); calc_new_limit = FALSE; @@ -3104,8 +3092,8 @@ log_print( "Last checkpoint at %lu %lu\n", ut_dulint_get_high(log_sys->lsn), ut_dulint_get_low(log_sys->lsn), - ut_dulint_get_high(log_sys->written_to_some_lsn), - ut_dulint_get_low(log_sys->written_to_some_lsn), + ut_dulint_get_high(log_sys->flushed_to_disk_lsn), + ut_dulint_get_low(log_sys->flushed_to_disk_lsn), ut_dulint_get_high(log_sys->last_checkpoint_lsn), ut_dulint_get_low(log_sys->last_checkpoint_lsn)); diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 1d1d84adda7..46129e3de79 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -521,10 +521,11 @@ try_again: } #endif #ifdef UNIV_NON_BUFFERED_IO - if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) { + if (type == OS_LOG_FILE) { /* Do not use unbuffered i/o to log files because - value 2 denotes that we do not flush the log at every - commit, but only once per second */ + to allow group commit to work when MySQL binlogging + is used we must separate log file write and log + file flush to disk. */ } else { if (srv_win_file_flush_method == SRV_WIN_IO_UNBUFFERED) { diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index db1119a2abc..428e4d568f3 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1664,7 +1664,7 @@ row_drop_table_for_mysql_in_background( the InnoDB data dictionary get out-of-sync if the user runs with innodb_flush_log_at_trx_commit = 0 */ - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); trx_commit_for_mysql(trx); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index d90b818ad4b..07df708e5fb 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -2812,8 +2812,7 @@ loop: at transaction commit */ srv_main_thread_op_info = (char*)"flushing log"; - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); - log_flush_to_disk(); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); /* If there were less than 10 i/os during the one second sleep, we assume that there is free @@ -2831,8 +2830,8 @@ loop: srv_main_thread_op_info = (char*)"flushing log"; - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); - log_flush_to_disk(); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, + TRUE); } if (srv_activity_count == old_activity_count) { @@ -2867,8 +2866,7 @@ loop: buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); srv_main_thread_op_info = (char*) "flushing log"; - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); - log_flush_to_disk(); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); } /* We run a batch of insert buffer merge every 10 seconds, @@ -2878,8 +2876,7 @@ loop: ibuf_contract_for_n_pages(TRUE, 5); srv_main_thread_op_info = (char*)"flushing log"; - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); - log_flush_to_disk(); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); /* We run a full purge every 10 seconds, even if the server were active */ @@ -2903,8 +2900,8 @@ loop: if (difftime(current_time, last_flush_time) > 1) { srv_main_thread_op_info = (char*) "flushing log"; - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); - log_flush_to_disk(); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, + TRUE); last_flush_time = current_time; } } diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 4ce2236f78a..e6ef400bb40 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -89,6 +89,8 @@ trx_create( trx->check_foreigns = TRUE; trx->check_unique_secondary = TRUE; + trx->flush_log_later = FALSE; + trx->dict_operation = FALSE; trx->mysql_thd = NULL; @@ -780,13 +782,26 @@ trx_commit_off_kernel( /*-------------------------------------*/ - /* Most MySQL users run with srv_flush_.. set to FALSE: */ + /* Most MySQL users run with srv_flush_.. set to 0: */ - if (srv_flush_log_at_trx_commit) { - - log_flush_up_to(lsn, LOG_WAIT_ONE_GROUP); + if (srv_flush_log_at_trx_commit != 0) { + if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC + && srv_flush_log_at_trx_commit != 2 + && !trx->flush_log_later) { + + /* Write the log to the log files AND flush + them to disk */ + + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE); + } else { + /* Write the log but do not flush it to disk */ + + log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE); + } } + trx->commit_lsn = lsn; + /*-------------------------------------*/ mutex_enter(&kernel_mutex); @@ -1467,6 +1482,31 @@ trx_commit_for_mysql( return(0); } +/************************************************************************** +If required, flushes the log to disk if we called trx_commit_for_mysql() +with trx->flush_log_later == TRUE. */ + +ulint +trx_commit_complete_for_mysql( +/*==========================*/ + /* out: 0 or error number */ + trx_t* trx) /* in: trx handle */ +{ + ut_a(trx); + + if (srv_flush_log_at_trx_commit == 1 + && srv_unix_file_flush_method != SRV_UNIX_NOSYNC) { + + trx->op_info = (char *) "flushing log"; + + /* Flush the log files to disk */ + + log_write_up_to(trx->commit_lsn, LOG_WAIT_ONE_GROUP, TRUE); + + trx->op_info = (char *) ""; + } +} + /************************************************************************** Marks the latest SQL statement ended. */ diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 73654536083..50bb4275eaa 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -872,8 +872,7 @@ innobase_flush_logs(void) DBUG_ENTER("innobase_flush_logs"); - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); - log_flush_to_disk(); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); DBUG_RETURN(result); } @@ -920,7 +919,7 @@ Commits a transaction in an InnoDB database. */ int innobase_commit( /*============*/ - /* out: 0 or error number */ + /* out: 0 */ THD* thd, /* in: MySQL thread handle of the user for whom the transaction should be committed */ void* trx_handle)/* in: InnoDB trx handle or @@ -928,7 +927,6 @@ innobase_commit( that the current SQL statement ended, and we should mark the start of a new statement with a savepoint */ { - int error = 0; trx_t* trx; DBUG_ENTER("innobase_commit"); @@ -955,29 +953,27 @@ innobase_commit( innobase_release_stat_resources(trx); trx_mark_sql_stat_end(trx); -#ifndef DBUG_OFF - if (error) { - DBUG_PRINT("error", ("error: %d", error)); - } -#endif /* Tell InnoDB server that there might be work for utility threads: */ srv_active_wake_master_thread(); - DBUG_RETURN(error); + DBUG_RETURN(0); } /********************************************************************* This is called when MySQL writes the binlog entry for the current transaction. Writes to the InnoDB tablespace info which tells where the MySQL binlog entry for the current transaction ended. Also commits the -transaction inside InnoDB. */ +transaction inside InnoDB but does NOT flush InnoDB log files to disk. +To flush you have to call innobase_flush_log_to_disk. We have separated +flushing to eliminate the bottleneck of LOCK_log in log.cc which disabled +InnoDB's group commit capability. */ int innobase_report_binlog_offset_and_commit( /*=====================================*/ - /* out: 0 or error code */ + /* out: 0 */ THD* thd, /* in: user thread */ void* trx_handle, /* in: InnoDB trx handle */ char* log_file_name, /* in: latest binlog file name */ @@ -993,7 +989,39 @@ innobase_report_binlog_offset_and_commit( trx->mysql_log_file_name = log_file_name; trx->mysql_log_offset = (ib_longlong)end_offset; - return(innobase_commit(thd, trx_handle)); + trx->flush_log_later = TRUE; + + innobase_commit(thd, trx_handle); + + trx->flush_log_later = FALSE; + + return(0); +} + +/********************************************************************* +This is called after MySQL has written the binlog entry for the current +transaction. Flushes the InnoDB log files to disk if required. */ + +int +innobase_commit_complete( +/*=====================*/ + /* out: 0 */ + void* trx_handle) /* in: InnoDB trx handle */ +{ + trx_t* trx; + + if (srv_flush_log_at_trx_commit == 0) { + + return(0); + } + + trx = (trx_t*)trx_handle; + + ut_a(trx != NULL); + + trx_commit_complete_for_mysql(trx); + + return(0); } /********************************************************************* @@ -3202,7 +3230,7 @@ ha_innobase::create( the InnoDB data dictionary get out-of-sync if the user runs with innodb_flush_log_at_trx_commit = 0 */ - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); innobase_table = dict_table_get(norm_name, NULL); @@ -3277,7 +3305,7 @@ ha_innobase::delete_table( the InnoDB data dictionary get out-of-sync if the user runs with innodb_flush_log_at_trx_commit = 0 */ - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); /* Tell the InnoDB server that there might be work for utility threads: */ @@ -3347,7 +3375,7 @@ innobase_drop_database( the InnoDB data dictionary get out-of-sync if the user runs with innodb_flush_log_at_trx_commit = 0 */ - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); /* Tell the InnoDB server that there might be work for utility threads: */ @@ -3419,7 +3447,7 @@ ha_innobase::rename_table( the InnoDB data dictionary get out-of-sync if the user runs with innodb_flush_log_at_trx_commit = 0 */ - log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); /* Tell the InnoDB server that there might be work for utility threads: */ @@ -3936,7 +3964,7 @@ ha_innobase::extra( case HA_EXTRA_RESET: case HA_EXTRA_RESET_STATE: prebuilt->read_just_key = 0; - break; + break; case HA_EXTRA_NO_KEYREAD: prebuilt->read_just_key = 0; break; diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 5677d22a2ca..8309c5eb440 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -211,6 +211,8 @@ int innobase_report_binlog_offset_and_commit( void* trx_handle, char* log_file_name, my_off_t end_offset); +int innobase_commit_complete( + void* trx_handle); int innobase_rollback(THD *thd, void* trx_handle); int innobase_close_connection(THD *thd); int innobase_drop_database(char *path); diff --git a/sql/handler.cc b/sql/handler.cc index 6e3f8486b45..ba7799fef4a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -243,6 +243,9 @@ int ha_autocommit_or_rollback(THD *thd, int error) replication. This function also calls the commit of the table handler, because the order of transactions in the log of the table handler must be the same as in the binlog. + NOTE that to eliminate the bottleneck of the group commit, we do not + flush the handler log files here, but only later in a call of + ha_commit_complete(). arguments: thd: the thread handle of the current connection @@ -269,12 +272,37 @@ int ha_report_binlog_offset_and_commit(THD *thd, my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); error=1; } - trans->innodb_active_trans=0; } #endif return error; } +/* + Flushes the handler log files (if my.cnf settings do not free us from it) + after we have called ha_report_binlog_offset_and_commit(). To eliminate + the bottleneck from the group commit, this should be called when + LOCK_log has been released in log.cc. + + arguments: + thd: the thread handle of the current connection + return value: always 0 +*/ + +int ha_commit_complete(THD *thd) +{ +#ifdef HAVE_INNOBASE_DB + THD_TRANS *trans; + trans = &thd->transaction.all; + if (trans->innobase_tid) + { + innobase_commit_complete(trans->innobase_tid); + + trans->innodb_active_trans=0; + } +#endif + return 0; +} + /* This function should be called when MySQL sends rows of a SELECT result set or the EOF mark to the client. It releases a possible adaptive hash index diff --git a/sql/handler.h b/sql/handler.h index 72a05d7ebee..fbad36bffdd 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -372,6 +372,7 @@ void ha_resize_key_cache(void); int ha_start_stmt(THD *thd); int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name, my_off_t end_offset); +int ha_commit_complete(THD *thd); int ha_release_temporary_latches(THD *thd); int ha_commit_trans(THD *thd, THD_TRANS *trans); int ha_rollback_trans(THD *thd, THD_TRANS *trans); diff --git a/sql/log.cc b/sql/log.cc index 8a5aba5cd34..f4c78b9c50d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1033,6 +1033,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, bool MYSQL_LOG::write(Log_event* event_info) { + THD *thd=event_info->thd; + bool called_handler_commit=0; bool error=0; DBUG_ENTER("MYSQL_LOG::write(event)"); @@ -1047,7 +1049,6 @@ bool MYSQL_LOG::write(Log_event* event_info) if (is_open()) { bool should_rotate = 0; - THD *thd=event_info->thd; const char *local_db = event_info->get_db(); #ifdef USING_TRANSACTIONS IO_CACHE *file = ((event_info->get_cache_stmt()) ? @@ -1147,6 +1148,7 @@ bool MYSQL_LOG::write(Log_event* event_info) { error = ha_report_binlog_offset_and_commit(thd, log_file_name, file->pos_in_file); + called_handler_commit=1; } should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size); @@ -1172,6 +1174,15 @@ err: } pthread_mutex_unlock(&LOCK_log); + + /* Flush the transactional handler log file now that we have released + LOCK_log; the flush is placed here to eliminate the bottleneck on the + group commit */ + + if (called_handler_commit) { + ha_commit_complete(thd); + } + DBUG_RETURN(error); } @@ -1277,6 +1288,13 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache) } VOID(pthread_mutex_unlock(&LOCK_log)); + + /* Flush the transactional handler log file now that we have released + LOCK_log; the flush is placed here to eliminate the bottleneck on the + group commit */ + + ha_commit_complete(thd); + DBUG_RETURN(0); err: From 40435e8554b786d3dfb053c45e40fcb3acb21e26 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Sat, 3 May 2003 14:48:51 +0200 Subject: [PATCH 134/188] mising reset_tree() in ft_reinit_search() added --- myisam/ft_boolean_search.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 97c55c1d937..ed6bf1808a9 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -242,10 +242,10 @@ static void _ftb_init_index_search(FT_INFO *ftb) else /* 3 */ { 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); - } + else + reset_tree(& ftb->no_dupes); } } r=_mi_search(info, keyinfo, (uchar*) ftbw->word, ftbw->len, From c7885b55716afe09532939e36fde321432830e82 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Sat, 3 May 2003 15:21:39 +0200 Subject: [PATCH 135/188] test case added --- mysql-test/r/repair.result | 3 +++ mysql-test/t/repair.test | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index adc09ded0e2..ad869787b8a 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -9,3 +9,6 @@ repair table t1 use_frm; Table Op Msg_type Msg_text test.t1 repair error The handler for the table doesn't support repair drop table t1; +repair table t1 use_frm; +Table Op Msg_type Msg_text +t1 repair error table is read-only or does not exists diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index b901fb3467f..e7da79d8c9e 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -8,3 +8,8 @@ repair table t1 use_frm; alter table t1 TYPE=HEAP; repair table t1 use_frm; drop table t1; + +# non-existent table +repair table t1 use_frm; + + From 7410b6cbdf21412f8cf4f6fc55713a2592f16f0e Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Sat, 3 May 2003 16:21:43 +0300 Subject: [PATCH 136/188] Fix problem where key_read was not cleaned up properly, which caused assert in innodb test. --- mysql-test/r/innodb.result | 34 +++++++++++++++++++++++----------- mysql-test/t/innodb.test | 4 ++-- sql/opt_sum.cc | 14 ++++++++++---- sql/sql_base.cc | 5 +++-- sql/sql_update.cc | 25 ++++++++++++++----------- 5 files changed, 52 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 3f28f00f322..f954928befc 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1139,7 +1139,7 @@ a b drop table t1; CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) type=innodb; CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) type=innodb; -INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); +INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12); INSERT INTO t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); update t1,t2 set t1.a=t1.a+100; select * from t1; @@ -1153,6 +1153,9 @@ a b 107 7 108 8 109 9 +110 10 +111 11 +112 12 update t1,t2 set t1.a=t1.a+100 where t1.a=101; select * from t1; a b @@ -1165,6 +1168,9 @@ a b 107 7 108 8 109 9 +110 10 +111 11 +112 12 update t1,t2 set t1.b=t1.b+10 where t1.b=2; select * from t1; a b @@ -1176,8 +1182,11 @@ a b 107 7 108 8 109 9 +110 10 +111 11 102 12 -update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5; +112 12 +update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100; select * from t1; a b 201 1 @@ -1188,18 +1197,21 @@ a b 107 7 108 8 109 9 +110 10 +111 11 102 12 +112 12 select * from t2; a b -1 5 -2 5 -3 5 -4 5 -5 5 -6 5 -7 5 -8 5 -9 5 +1 1 +2 2 +6 6 +7 7 +8 8 +9 9 +3 13 +4 14 +5 15 drop table t1,t2; create table t1 (a int not null auto_increment primary key, b int, c int, key(c)) type=innodb; create table t2 (a int not null auto_increment primary key, b int); diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index ab3157a7f86..8aa26b567a6 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -776,7 +776,7 @@ drop table t1; CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) type=innodb; CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) type=innodb; -INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); +INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12); INSERT INTO t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); # Full join, without key @@ -792,7 +792,7 @@ update t1,t2 set t1.b=t1.b+10 where t1.b=2; select * from t1; # Range key (in t1) -update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5; +update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100; select * from t1; select * from t2; drop table t1,t2; diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index aeaf8beef07..21296845c21 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -191,13 +191,13 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) ref.key_buff=key_buff; TABLE *table=((Item_field*) expr)->field->table; - if ((outer_tables & table->map) || - !find_range_key(&ref, ((Item_field*) expr)->field,conds)) + if ((table->file->table_flags() & HA_NOT_READ_AFTER_KEY)) { const_result=0; break; } - if ((table->file->table_flags() & HA_NOT_READ_AFTER_KEY)) + if ((outer_tables & table->map) || + !find_range_key(&ref, ((Item_field*) expr)->field,conds)) { const_result=0; break; @@ -348,7 +348,13 @@ bool part_of_cond(COND *cond,Field *field) } -/* Check if we can get value for field by using a key */ +/* + Check if we can get value for field by using a key + + NOTES + This function may set table->key_read to 1, which must be reset after + index is used! (This can only happen when function returns 1) +*/ static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0f0c3c97ed2..f0aa8e9c351 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -482,8 +482,9 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) { DBUG_ENTER("close_thread_table"); - bool found_old_table=0; - TABLE *table=*table_ptr; + bool found_old_table= 0; + TABLE *table= *table_ptr; + DBUG_ASSERT(table->key_read == 0); *table_ptr=table->next; if (table->version != refresh_version || diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 653b16a45e9..e73b0e6025d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -62,6 +62,7 @@ int mysql_update(THD *thd, int error=0; uint used_index, want_privilege; ulong query_id=thd->query_id, timestamp_query_id; + ha_rows updated, found; key_map old_used_keys; TABLE *table; SQL_SELECT *select; @@ -192,9 +193,8 @@ int mysql_update(THD *thd, limit, &examined_rows)) == HA_POS_ERROR) { - delete select; free_io_cache(table); - DBUG_RETURN(-1); + goto err; } /* Filesort has already found and selected the rows we want to update, @@ -214,10 +214,7 @@ int mysql_update(THD *thd, IO_CACHE tempfile; if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME))) - { - delete select; /* purecov: inspected */ - DBUG_RETURN(-1); - } + goto err; init_read_record(&info,thd,table,select,0,1); thd->proc_info="Searching rows for update"; @@ -256,10 +253,7 @@ int mysql_update(THD *thd, error=1; /* purecov: inspected */ select->file=tempfile; // Read row ptrs from this file if (error >= 0) - { - delete select; - DBUG_RETURN(-1); - } + goto err; } if (table->key_read) { @@ -272,7 +266,7 @@ int mysql_update(THD *thd, table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); init_read_record(&info,thd,table,select,0,1); - ha_rows updated=0L,found=0L; + updated= found= 0; thd->count_cuted_fields=1; /* calc cuted fields */ thd->cuted_fields=0L; thd->proc_info="Updating"; @@ -365,6 +359,15 @@ int mysql_update(THD *thd, thd->count_cuted_fields=0; /* calc cuted fields */ free_io_cache(table); DBUG_RETURN(0); + +err: + delete select; + if (table->key_read) + { + table->key_read=0; + table->file->extra(HA_EXTRA_NO_KEYREAD); + } + DBUG_RETURN(-1); } From 7179284df92516572a19fa9b0dfa46349042e11e Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Sat, 3 May 2003 16:16:52 +0200 Subject: [PATCH 137/188] - applied patch from Tim Bunce (new --addtodest option that adds copied files into an already existing directory) --- scripts/mysqlhotcopy.sh | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index ec76aa479f3..a89a8919752 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -55,7 +55,8 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory] -P, --port=# port to use when connecting to local server with TCP/IP -S, --socket=# socket to use when connecting to local server - --allowold don\'t abort if target already exists (rename it _old) + --allowold don\'t abort if target dir already exists (rename it _old) + --addtodest don\'t rename target dir if it exists, just add files to it --keepold don\'t delete previous (now renamed) target when done --noindices don\'t include full index files in copy --method=# method for copy (only "cp" currently supported) @@ -98,6 +99,7 @@ GetOptions( \%opt, "socket|S=s", "allowold!", "keepold!", + "addtodest!", "noindices!", "method=s", "debug", @@ -380,14 +382,14 @@ if ($opt{method} =~ /^cp\b/) push @existing, $rdb->{target} if ( -d $rdb->{target} ); } - if ( @existing && !$opt{allowold} ) + if ( @existing && !($opt{allowold} || $opt{addtodest}) ) { $dbh->disconnect(); - die "Can't hotcopy to '", join( "','", @existing ), "' because directory\nalready exist and the --allowold option was not given.\n" + die "Can't hotcopy to '", join( "','", @existing ), "' because directory\nalready exist and the --allowold or --addtodest options were not given.\n" } } -retire_directory( @existing ) if ( @existing ); +retire_directory( @existing ) if @existing && !$opt{addtodest}; foreach my $rdb ( @db_desc ) { foreach my $td ( '', @{$rdb->{raid_dirs}} ) { @@ -403,8 +405,8 @@ foreach my $rdb ( @db_desc ) { ## ... } else { - mkdir($tgt_dirpath, 0750) - or die "Can't create '$tgt_dirpath': $!\n"; + mkdir($tgt_dirpath, 0750) or die "Can't create '$tgt_dirpath': $!\n" + unless -d $tgt_dirpath; } } } @@ -861,6 +863,22 @@ Any existing versions of the backup directory are deleted. Behaves as for the --allowold, with the additional feature of keeping the backup directory after the copy successfully completes. +=item --addtodest + +Don't rename target directory if it already exists, just add the +copied files into it. + +This is most useful when backing up a database with many large +tables and you don't want to have all the tables locked for the +whole duration. + +In this situation, I you are happy for groups of tables to be +backed up separately (and thus possibly not be logically consistant +with one another) then you can run mysqlhotcopy several times on +the same database each with different db_name./table_regex/. +All but the first should use the --addtodest option so the tables +all end up in the same directory. + =item --flushlog Rotate the log files by executing "FLUSH LOGS" after all tables are @@ -869,13 +887,13 @@ locked, and before they are copied. =item --resetmaster Reset the bin-log by executing "RESET MASTER" after all tables are -locked, and before they are copied. Usefull if you are recovering a +locked, and before they are copied. Useful if you are recovering a slave in a replication setup. =item --resetslave Reset the master.info by executing "RESET SLAVE" after all tables are -locked, and before they are copied. Usefull if you are recovering a +locked, and before they are copied. Useful if you are recovering a server in a mutual replication setup. =item --regexp pattern @@ -941,7 +959,7 @@ will vary with your ability to understand how scp works. 'man scp' and 'man ssh' are your friends. The destination directory _must exist_ on the target machine using the -scp method. --keepold and --allowold are meeningless with scp. +scp method. --keepold and --allowold are meaningless with scp. Liberal use of the --debug option will help you figure out what\'s really going on when you do an scp. From 6db5e7f42884d16716226efb46daaf3606c06aec Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Sat, 3 May 2003 18:08:11 +0200 Subject: [PATCH 138/188] "delete from table where const" bug fixed --- mysql-test/t/delete.test | 6 ++++++ sql/sql_delete.cc | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 13fa617b3cf..904d959d148 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -53,5 +53,11 @@ select * from t1 where misc > 5 and bool is null; delete from t1 where misc > 5 and bool is null; select * from t1 where misc > 5 and bool is null; +select count(*) from t1; +delete from t1 where 1 > 2; +select count(*) from t1; +delete from t1 where 3 > 2; +select count(*) from t1; + drop table t1; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 1507d49ebd6..caa1e0e0312 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -54,7 +54,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, DBUG_RETURN(-1); /* Test if the user wants to delete all rows */ - if (!using_limit && (!conds || conds->const_item()) && + if (!using_limit && (!conds || (conds->const_item() && conds->val_int())) && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && !safe_update) { deleted= table->file->records; From 971f770946419091a7a8a474679c79a180ab8cc3 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 3 May 2003 19:44:46 +0300 Subject: [PATCH 139/188] buf0buf.c, srv0srv.h, buf0buf.h, srv0srv.c: Clean up the working of the main thread; add a tunable parameter srv_max_buf_pool_modified_pct which can be used to make the flush phase in shutdown quicker --- innobase/buf/buf0buf.c | 22 +++++++ innobase/include/buf0buf.h | 7 +++ innobase/include/srv0srv.h | 3 + innobase/srv/srv0srv.c | 114 ++++++++++++++++++++++++++++--------- 4 files changed, 118 insertions(+), 28 deletions(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 42799da9d7c..944a5ef60d0 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1832,6 +1832,28 @@ buf_get_n_pending_ios(void) + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); } +/************************************************************************* +Returns the ratio in percents of modified pages in the buffer pool / +database pages in the buffer pool. */ + +ulint +buf_get_modified_ratio_pct(void) +/*============================*/ +{ + ulint ratio; + + mutex_enter(&(buf_pool->mutex)); + + ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list)) + / (1 + UT_LIST_GET_LEN(buf_pool->LRU)); + + /* 1 + is there to avoid division by zero */ + + mutex_exit(&(buf_pool->mutex)); + + return(ratio); +} + /************************************************************************* Prints info of the buffer i/o. */ diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 395f88a2c7c..e4d3671586d 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -472,6 +472,13 @@ buf_print_io( /*=========*/ char* buf, /* in/out: buffer where to print */ char* buf_end);/* in: buffer end */ +/************************************************************************* +Returns the ratio in percents of modified pages in the buffer pool / +database pages in the buffer pool. */ + +ulint +buf_get_modified_ratio_pct(void); +/*============================*/ /************************************************************************** Refreshes the statistics used to print per-second averages. */ diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index ad6f71f7a3a..8355496762c 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -74,6 +74,9 @@ extern ulint srv_lock_wait_timeout; extern char* srv_file_flush_method_str; extern ulint srv_unix_file_flush_method; extern ulint srv_win_file_flush_method; + +extern ulint srv_max_dirty_pages_pct; + extern ulint srv_force_recovery; extern ulint srv_thread_concurrency; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 07df708e5fb..97841056b1e 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -157,6 +157,13 @@ char* srv_file_flush_method_str = NULL; ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; +/* The InnoDB main thread tries to keep the ratio of modified pages +in the buffer pool to all database pages in the buffer pool smaller than +the following number. But it is not guaranteed that the value stays below +that during a time of heavy update/insert activity. */ + +ulint srv_max_buf_pool_modified_pct = 30; + /* If the following is != 0 we do not allow inserts etc. This protects the user from forgetting the innodb_force_recovery keyword to my.cnf */ @@ -2770,16 +2777,29 @@ srv_master_thread( os_event_set(srv_sys->operational); loop: + /*****************************************************************/ + /* ---- When there is database activity by users, we cycle in this + loop */ + srv_main_thread_op_info = (char*) "reserving kernel mutex"; n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; mutex_enter(&kernel_mutex); + /* Store the user activity counter at the start of this loop */ old_activity_count = srv_activity_count; mutex_exit(&kernel_mutex); + if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) { + + goto suspend_thread; + } + + /* ---- We run the following loop approximately once per second + when there is database activity */ + for (i = 0; i < 10; i++) { n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; @@ -2797,11 +2817,6 @@ loop: srv_main_thread_op_info = (char*)""; - if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) { - - goto suspend_thread; - } - if (srv_fast_shutdown && srv_shutdown_state > 0) { goto background_loop; @@ -2814,7 +2829,7 @@ loop: srv_main_thread_op_info = (char*)"flushing log"; log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); - /* If there were less than 10 i/os during the + /* If there were less than 5 i/os during the one second sleep, we assume that there is free disk i/o capacity available, and it makes sense to do an insert buffer merge. */ @@ -2823,7 +2838,7 @@ loop: + log_sys->n_pending_writes; n_ios = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; - if (n_pend_ios < 3 && (n_ios - n_ios_old < 10)) { + if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) { srv_main_thread_op_info = (char*)"doing insert buffer merge"; ibuf_contract_for_n_pages(TRUE, 5); @@ -2834,19 +2849,27 @@ loop: TRUE); } + if (buf_get_modified_ratio_pct() > + srv_max_buf_pool_modified_pct) { + + /* Try to keep the number of modified pages in the + buffer pool under the limit wished by the user */ + + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, + ut_dulint_max); + } + if (srv_activity_count == old_activity_count) { - if (srv_print_thread_releases) { - printf("Master thread wakes up!\n"); - } + /* There is no user activity at the moment, go to + the background loop */ goto background_loop; } } - if (srv_print_thread_releases) { - printf("Master thread wakes up!\n"); - } + /* ---- We perform the following code approximately once per + 10 seconds when there is database activity */ #ifdef MEM_PERIODIC_CHECK /* Check magic numbers of every allocated mem block once in 10 @@ -2855,7 +2878,7 @@ loop: #endif /* If there were less than 200 i/os during the 10 second period, we assume that there is free disk i/o capacity available, and it - makes sense to do a buffer pool flush. */ + makes sense to flush 100 pages. */ n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes; n_ios = log_sys->n_log_ios + buf_pool->n_pages_read @@ -2905,25 +2928,24 @@ loop: last_flush_time = current_time; } } - -background_loop: - /* In this loop we run background operations when the server - is quiet and we also come here about once in 10 seconds */ - - srv_main_thread_op_info = (char*)"doing background drop tables"; - - n_tables_to_drop = row_drop_tables_for_mysql_in_background(); - - srv_main_thread_op_info = (char*)""; srv_main_thread_op_info = (char*)"flushing buffer pool pages"; - /* Flush a few oldest pages to make the checkpoint younger */ + /* Flush a few oldest pages to make a new checkpoint younger */ + + if (buf_get_modified_ratio_pct() > 70) { + + /* If there are lots of modified pages in the buffer pool + (> 70 %), we assume we can afford reserving the disk(s) for + the time it requires to flush 100 pages */ - if (srv_fast_shutdown && srv_shutdown_state > 0) { n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); } else { + /* Otherwise, we only flush a small number of pages so that + we do not unnecessarily use much disk i/o capacity from + other work */ + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, ut_dulint_max); } @@ -2937,16 +2959,31 @@ background_loop: srv_main_thread_op_info = (char*)"reserving kernel mutex"; mutex_enter(&kernel_mutex); + + /* ---- When there is database activity, we jump from here back to + the start of loop */ + if (srv_activity_count != old_activity_count) { mutex_exit(&kernel_mutex); goto loop; } - old_activity_count = srv_activity_count; + mutex_exit(&kernel_mutex); + /* If the database is quiet, we enter the background loop */ + + /*****************************************************************/ +background_loop: + /* ---- In this loop we run background operations when the server + is quiet from user activity */ + /* The server has been quiet for a while: start running background operations */ + srv_main_thread_op_info = (char*)"doing background drop tables"; + + n_tables_to_drop = row_drop_tables_for_mysql_in_background(); + srv_main_thread_op_info = (char*)"purging"; if (srv_fast_shutdown && srv_shutdown_state > 0) { @@ -2981,6 +3018,7 @@ background_loop: } mutex_exit(&kernel_mutex); +flush_loop: srv_main_thread_op_info = (char*)"flushing buffer pool pages"; n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); @@ -3001,6 +3039,14 @@ background_loop: log_checkpoint(TRUE, FALSE); + if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) { + + /* Try to keep the number of modified pages in the + buffer pool under the limit wished by the user */ + + goto flush_loop; + } + srv_main_thread_op_info = (char*)"reserving kernel mutex"; mutex_enter(&kernel_mutex); @@ -3015,15 +3061,24 @@ background_loop: log_archive_do(FALSE, &n_bytes_archived); + /* Keep looping in the background loop if still work to do */ + if (srv_fast_shutdown && srv_shutdown_state > 0) { if (n_tables_to_drop + n_pages_flushed + n_bytes_archived != 0) { + /* If we are doing a fast shutdown (= the default) + we do not do purge or insert buffer merge. But we + flush the buffer pool completely to disk. */ + goto background_loop; } } else if (n_tables_to_drop + - n_pages_purged + n_bytes_merged + n_pages_flushed + n_pages_purged + n_bytes_merged + n_pages_flushed + n_bytes_archived != 0) { + /* In a 'slow' shutdown we run purge and the insert buffer + merge to completion */ + goto background_loop; } @@ -3055,6 +3110,9 @@ suspend_thread: os_event_wait(event); + /* When there is user activity, InnoDB will set the event and the main + thread goes back to loop: */ + goto loop; #ifndef __WIN__ From 33e1b9398a2d4c1b7b95c985d570ad6132768065 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 3 May 2003 19:46:03 +0300 Subject: [PATCH 140/188] srv0srv.c: Clean up the working of the main thread; add a tunable parameter srv_max_buf_pool_modified_pct which can be used to make the flush phase in shutdown quicker --- innobase/srv/srv0srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 97841056b1e..75742d8f670 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -162,7 +162,7 @@ in the buffer pool to all database pages in the buffer pool smaller than the following number. But it is not guaranteed that the value stays below that during a time of heavy update/insert activity. */ -ulint srv_max_buf_pool_modified_pct = 30; +ulint srv_max_buf_pool_modified_pct = 100; /* If the following is != 0 we do not allow inserts etc. This protects the user from forgetting the innodb_force_recovery keyword to my.cnf */ From 86da817cec6c708dc1d6e0d2d0d22df0b4660266 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Sun, 4 May 2003 11:00:45 +0200 Subject: [PATCH 141/188] result updated --- mysql-test/r/delete.result | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 582ab894233..abc8245e69f 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -38,4 +38,15 @@ NULL d 7 delete from t1 where misc > 5 and bool is null; select * from t1 where misc > 5 and bool is null; bool not_null misc +select count(*) from t1; +count(*) +2 +delete from t1 where 1 > 2; +select count(*) from t1; +count(*) +2 +delete from t1 where 3 > 2; +select count(*) from t1; +count(*) +0 drop table t1; From afafe36b3e8c56e62315972ffbd3093a3d99dd27 Mon Sep 17 00:00:00 2001 From: "peter@mysql.com" <> Date: Sun, 4 May 2003 14:41:21 +0400 Subject: [PATCH 142/188] Added innodb_max_dirty_pages_pct parameter to limit amount of dirty pages in the buffer pool (can be changed online) --- sql/mysql_priv.h | 1 + sql/mysqld.cc | 5 +++++ sql/set_var.cc | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9617d19caae..c184b09974d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -657,6 +657,7 @@ extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit; extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size; extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log; extern ulong specialflag, current_pid; +extern ulong srv_max_buf_pool_modified_pct; extern uint test_flags,select_errors,ha_open_options; extern uint protocol_version,dropping_tables; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 33724c7100e..e2f9fff36c5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3156,6 +3156,7 @@ enum options { OPT_INNODB_LOCK_WAIT_TIMEOUT, OPT_INNODB_THREAD_CONCURRENCY, OPT_INNODB_FORCE_RECOVERY, + OPT_INNODB_MAX_DIRTY_PAGES_PCT, OPT_BDB_CACHE_SIZE, OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_MAX_LOCK, @@ -3304,6 +3305,10 @@ struct my_option my_long_options[] = {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN, "Speeds up server shutdown process", (gptr*) &innobase_fast_shutdown, (gptr*) &innobase_fast_shutdown, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"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}, + #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 172939ce981..697ebbe6edb 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -219,6 +219,11 @@ sys_var_thd_ulong sys_tmp_table_size("tmp_table_size", &SV::tmp_table_size); sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", &SV::net_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); +#endif /* @@ -378,6 +383,9 @@ sys_var *sys_variables[]= &sys_timestamp, &sys_tmp_table_size, &sys_tx_isolation, +#ifdef HAVE_INNOBASE_DB + &sys_innodb_max_dirty_pages_pct, +#endif &sys_unique_checks }; @@ -446,6 +454,7 @@ struct show_var_st init_vars[]= { {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG}, {"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}, #endif {sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS}, {sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS}, From eab9a5e005300611e982230e0d314e9b30b25219 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 4 May 2003 15:14:33 +0300 Subject: [PATCH 143/188] srv0srv.c: Do not let the main thread sleep the 1 second if we had to do a bug pool flush batch trying to establish srv_max_buf_pool_modified_pct --- innobase/srv/srv0srv.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 75742d8f670..147606ec17c 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -2760,6 +2760,7 @@ srv_master_thread( ulint n_ios_old; ulint n_ios_very_old; ulint n_pend_ios; + ibool skip_sleep = FALSE; ulint i; UT_NOT_USED(arg); @@ -2800,11 +2801,19 @@ loop: /* ---- We run the following loop approximately once per second when there is database activity */ + skip_sleep = FALSE; + for (i = 0; i < 10; i++) { n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; srv_main_thread_op_info = (char*)"sleeping"; - os_thread_sleep(1000000); + + if (!skip_sleep) { + + os_thread_sleep(1000000); + } + + skip_sleep = FALSE; /* ALTER TABLE in MySQL requires on Unix that the table handler can drop tables lazily after there no longer are SELECT @@ -2857,6 +2866,13 @@ loop: n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); + + /* If we had to do the flush, it may have taken + even more than 1 second, and also, there may be more + to flush. Do not sleep 1 second during the next + iteration of this loop. */ + + skip_sleep = TRUE; } if (srv_activity_count == old_activity_count) { From 9dd21162bb63367519f3930aa53b75240af6ab8b Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 4 May 2003 15:42:47 +0300 Subject: [PATCH 144/188] os0file.c: Print progress information if at startup InnoDB creates and writes bigger than 100 MB data file or log file --- innobase/os/os0file.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 46129e3de79..c7f95d79104 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -752,7 +752,12 @@ os_file_set_size( offset = 0; low = (ib_longlong)size + (((ib_longlong)size_high) << 32); + + if (low >= (ib_longlong)(100 * 1024 * 1024)) { + fprintf(stderr, "InnoDB: Progress in MB:"); + } + while (offset < low) { if (low - offset < UNIV_PAGE_SIZE * 512) { n_bytes = (ulint)(low - offset); @@ -768,9 +773,24 @@ os_file_set_size( ut_free(buf2); goto error_handling; } + + /* Print about progress for each 100 MB written */ + if ((offset + n_bytes) / (ib_longlong)(100 * 1024 * 1024) + != offset / (ib_longlong)(100 * 1024 * 1024)) { + + fprintf(stderr, " %lu00", + (ulint)((offset + n_bytes) + / (ib_longlong)(100 * 1024 * 1024))); + } + offset += n_bytes; } + if (low >= (ib_longlong)(100 * 1024 * 1024)) { + + fprintf(stderr, "\n"); + } + ut_free(buf2); ret = os_file_flush(file); From 356b7f62fb1c0dd64ad1b35cae4a551d0d2eb855 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Sun, 4 May 2003 18:43:07 +0200 Subject: [PATCH 145/188] count_bits() moved to mysys/ --- include/my_sys.h | 1 + mysys/my_bit.c | 42 ++++++++++++++++++++++++++++++++++++++++++ sql/item_func.cc | 45 ++------------------------------------------- 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index c67a150f24f..603b3bad6bd 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -749,6 +749,7 @@ extern my_bool my_uncompress(byte *, ulong *, ulong *); extern byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen); extern ulong checksum(const byte *mem, uint count); extern uint my_bit_log2(ulong value); +uint my_count_bits(ulonglong v); extern void my_sleep(ulong m_seconds); #ifdef __WIN__ diff --git a/mysys/my_bit.c b/mysys/my_bit.c index 0ff487afe03..55dd72f5f76 100644 --- a/mysys/my_bit.c +++ b/mysys/my_bit.c @@ -29,3 +29,45 @@ uint my_bit_log2(ulong value) for (bit=0 ; value > 1 ; value>>=1, bit++) ; return bit; } + +static char nbits[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, +}; + +uint my_count_bits(ulonglong v) +{ +#if SIZEOF_LONG_LONG > 4 + /* The following code is a bit faster on 16 bit machines than if we would + only shift v */ + ulong v2=(ulong) (v >> 32); + return (uint) (uchar) (nbits[(uchar) v] + + nbits[(uchar) (v >> 8)] + + nbits[(uchar) (v >> 16)] + + nbits[(uchar) (v >> 24)] + + nbits[(uchar) (v2)] + + nbits[(uchar) (v2 >> 8)] + + nbits[(uchar) (v2 >> 16)] + + nbits[(uchar) (v2 >> 24)]); +#else + return (uint) (uchar) (nbits[(uchar) v] + + nbits[(uchar) (v >> 8)] + + nbits[(uchar) (v >> 16)] + + nbits[(uchar) (v >> 24)]); +#endif +} + diff --git a/sql/item_func.cc b/sql/item_func.cc index 6c23b0aa424..532a7cedec0 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1110,47 +1110,6 @@ longlong Item_func_find_in_set::val_int() return 0; } -static char nbits[256] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, -}; - -uint count_bits(ulonglong v) -{ -#if SIZEOF_LONG_LONG > 4 - /* The following code is a bit faster on 16 bit machines than if we would - only shift v */ - ulong v2=(ulong) (v >> 32); - return (uint) (uchar) (nbits[(uchar) v] + - nbits[(uchar) (v >> 8)] + - nbits[(uchar) (v >> 16)] + - nbits[(uchar) (v >> 24)] + - nbits[(uchar) (v2)] + - nbits[(uchar) (v2 >> 8)] + - nbits[(uchar) (v2 >> 16)] + - nbits[(uchar) (v2 >> 24)]); -#else - return (uint) (uchar) (nbits[(uchar) v] + - nbits[(uchar) (v >> 8)] + - nbits[(uchar) (v >> 16)] + - nbits[(uchar) (v >> 24)]); -#endif -} - longlong Item_func_bit_count::val_int() { ulonglong value= (ulonglong) args[0]->val_int(); @@ -1159,7 +1118,7 @@ longlong Item_func_bit_count::val_int() null_value=1; /* purecov: inspected */ return 0; /* purecov: inspected */ } - return (longlong) count_bits(value); + return (longlong) my_count_bits(value); } @@ -2221,7 +2180,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) used_tables_cache|=item->used_tables(); } /* check that all columns come from the same table */ - if (count_bits(used_tables_cache) != 1) + if (my_count_bits(used_tables_cache) != 1) key=NO_SUCH_KEY; const_item_cache=0; table=((Item_field *)fields.head())->field->table; From 12e53eb9e1cd81dd8e046babfb466162f4d7609c Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Sun, 4 May 2003 18:43:37 +0200 Subject: [PATCH 146/188] parallel-repair available in mysqld --- myisam/mi_check.c | 12 +++++++++++- sql/ha_myisam.cc | 20 +++++++++++++++++--- sql/mysqld.cc | 9 +++++++-- sql/set_var.cc | 9 ++++++--- sql/sql_class.h | 1 + 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index b23d4b2277b..a64130cf6e0 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -2246,7 +2246,17 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, else rec_length=share->base.pack_reclength; sort_info.max_records= - ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records : + /* +1 below is required hack for parallel repair mode. + The info->state->records value, that is compared later + to sort_info.max_records and cannot exceed it, is + increased in sort_key_write. In mi_repair_by_sort, sort_key_write + is called after sort_key_read, where the comparison is performed, + but in parallel mode master thread can call sort_key_write + before some other repair thread calls sort_key_read. + Furthermore I'm not even sure +1 would be enough. + May be sort_info.max_records shold be always set to max value in + parallel mode. */ + ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records + 1: (ha_rows) (sort_info.filelength/rec_length+1)); del=info->state->del; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index aef9c09833a..202cd90fd88 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -579,10 +579,24 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize) { local_testflag|= T_STATISTICS; param.testflag|= T_STATISTICS; // We get this for free - thd->proc_info="Repair by sorting"; statistics_done=1; - error = mi_repair_by_sort(¶m, file, fixed_name, - param.testflag & T_QUICK); + if (current_thd->variables.myisam_repair_threads>1) + { + char buf[40]; + /* TODO: respect myisam_repair_threads variable */ + my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map)); + thd->proc_info=buf; + error = mi_repair_parallel(¶m, file, fixed_name, + param.testflag & T_QUICK); + thd->proc_info="Repair done"; // to reset proc_info, as + // it was pointing to local buffer + } + else + { + thd->proc_info="Repair by sorting"; + error = mi_repair_by_sort(¶m, file, fixed_name, + param.testflag & T_QUICK); + } } else { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 33724c7100e..4199e7c4825 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3145,7 +3145,7 @@ enum options { OPT_SORT_BUFFER, OPT_TABLE_CACHE, OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE, OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK, - OPT_WAIT_TIMEOUT, + OPT_WAIT_TIMEOUT, OPT_MYISAM_REPAIR_THREADS, OPT_INNODB_MIRRORED_LOG_GROUPS, OPT_INNODB_LOG_FILES_IN_GROUP, OPT_INNODB_LOG_FILE_SIZE, @@ -3839,13 +3839,18 @@ replicating a LOAD DATA INFILE command", (gptr*) &global_system_variables.myisam_max_sort_file_size, (gptr*) &max_system_variables.myisam_max_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, ~0L, 0, 1024*1024, 0}, + {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS, + "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", + (gptr*) &global_system_variables.myisam_repair_threads, + (gptr*) &max_system_variables.myisam_repair_threads, 0, + GET_ULONG, REQUIRED_ARG, 1, 1, ~0L, 0, 1, 0}, {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE, "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", (gptr*) &global_system_variables.myisam_sort_buff_size, (gptr*) &max_system_variables.myisam_sort_buff_size, 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, - "Buffer length for TCP/IP and socket communication.", + "Buffer length for TCP/IP and socket communication.", (gptr*) &global_system_variables.net_buffer_length, (gptr*) &max_system_variables.net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0}, diff --git a/sql/set_var.cc b/sql/set_var.cc index 172939ce981..43d02828719 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -167,6 +167,7 @@ sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count", &max_write_lock_count); sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size); sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size); +sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads); sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size); sys_var_thd_ulong sys_net_buffer_length("net_buffer_length", &SV::net_buffer_length); @@ -342,6 +343,7 @@ sys_var *sys_variables[]= &sys_max_write_lock_count, &sys_myisam_max_extra_sort_file_size, &sys_myisam_max_sort_file_size, + &sys_myisam_repair_threads, &sys_myisam_sort_buffer_size, &sys_net_buffer_length, &sys_net_read_timeout, @@ -475,13 +477,14 @@ struct show_var_st init_vars[]= { {sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS}, {sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS}, {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, - {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, + {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS}, {sys_myisam_max_extra_sort_file_size.name, (char*) &sys_myisam_max_extra_sort_file_size, SHOW_SYS}, - {sys_myisam_max_sort_file_size.name, - (char*) &sys_myisam_max_sort_file_size, + {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size, + SHOW_SYS}, + {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, SHOW_SYS}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS}, diff --git a/sql/sql_class.h b/sql/sql_class.h index 160c06ca3c6..9857774fb84 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -294,6 +294,7 @@ struct system_variables ulong max_heap_table_size; ulong max_sort_length; ulong max_tmp_tables; + ulong myisam_repair_threads; ulong myisam_sort_buff_size; ulong net_buffer_length; ulong net_interactive_timeout; From ac377a684ea89d62f395d5d804d9557ae255cf31 Mon Sep 17 00:00:00 2001 From: "peter@mysql.com" <> Date: Sun, 4 May 2003 21:35:20 +0400 Subject: [PATCH 147/188] Minor fix to previous code --- sql/mysql_priv.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c184b09974d..956fdf8cd45 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -657,7 +657,10 @@ extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit; extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size; extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log; extern ulong specialflag, current_pid; + +#ifdef HAVE_INNOBASE_DB extern ulong srv_max_buf_pool_modified_pct; +#endif extern uint test_flags,select_errors,ha_open_options; extern uint protocol_version,dropping_tables; From aa92b8ecd10d42b70ee93e90822c35f25d00cf84 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 4 May 2003 23:24:23 +0300 Subject: [PATCH 148/188] row0ins.c, dict0dict.c, dict0dict.h, srv0srv.c: Let SHOW INNODB STATUS print detailed info of the latest unique key violation, note that REPLACE and INSERT IGNORE mask the error from the user --- innobase/dict/dict0dict.c | 10 +++++-- innobase/include/dict0dict.h | 7 +++-- innobase/row/row0ins.c | 53 ++++++++++++++++++++++++++++++++---- innobase/srv/srv0srv.c | 15 +++++++++- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 74fe5cd5b70..c11a5f76d94 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -185,10 +185,12 @@ dict_foreign_free( /*==============*/ dict_foreign_t* foreign); /* in, own: foreign key struct */ -/* Buffer for storing detailed information about the latest foreig key -error */ +/* Buffers for storing detailed information about the latest foreign key +and unique key errors */ char* dict_foreign_err_buf = NULL; -mutex_t dict_foreign_err_mutex; /* mutex protecting the buffer */ +char* dict_unique_err_buf = NULL; +mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign + and unique error buffers */ /************************************************************************ @@ -582,6 +584,8 @@ dict_init(void) dict_foreign_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN); dict_foreign_err_buf[0] = '\0'; + dict_unique_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN); + dict_unique_err_buf[0] = '\0'; mutex_create(&dict_foreign_err_mutex); mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH); } diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index 600965700ed..97486a7c2f6 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -839,10 +839,11 @@ dict_mutex_exit_for_mysql(void); /* The following len must be at least 10000 bytes! */ #define DICT_FOREIGN_ERR_BUF_LEN 10000 -/* Buffer for storing detailed information about the latest foreig key -error */ +/* Buffers for storing detailed information about the latest foreign key +and unique key errors */ extern char* dict_foreign_err_buf; -extern mutex_t dict_foreign_err_mutex; /* mutex protecting the buffer */ +extern char* dict_unique_err_buf; +extern mutex_t dict_foreign_err_mutex; /* mutex protecting the buffers */ extern dict_sys_t* dict_sys; /* the dictionary system */ extern rw_lock_t dict_operation_lock; diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 596273477aa..3af9e1b752b 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -1263,6 +1263,48 @@ row_ins_check_foreign_constraints( return(DB_SUCCESS); } +/************************************************************************* +Reports a UNIQUE key error to dict_unique_err_buf so that SHOW INNODB +STATUS can print it. */ +static +void +row_ins_unique_report_err( +/*======================*/ + que_thr_t* thr, /* in: query thread */ + rec_t* rec, /* in: a record in the index */ + dtuple_t* entry, /* in: index entry to insert in the index */ + dict_index_t* index) /* in: index */ +{ + char* buf = dict_unique_err_buf; + + /* The foreign err mutex protects also dict_unique_err_buf */ + + mutex_enter(&dict_foreign_err_mutex); + + ut_sprintf_timestamp(buf); + sprintf(buf + strlen(buf), " Transaction:\n"); + trx_print(buf + strlen(buf), thr_get_trx(thr)); + + sprintf(buf + strlen(buf), +"Unique key constraint fails for table %.500s.\n", index->table_name); + sprintf(buf + strlen(buf), +"Trying to add in index %.500s (%lu fields unique) tuple:\n", index->name, + dict_index_get_n_unique(index)); + + dtuple_sprintf(buf + strlen(buf), 1000, entry); + + sprintf(buf + strlen(buf), +"\nBut there is already a record:\n"); + + rec_sprintf(buf + strlen(buf), 1000, rec); + + sprintf(buf + strlen(buf), "\n"); + + ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + + mutex_exit(&dict_foreign_err_mutex); +} + /******************************************************************* Checks if a unique key violation to rec would occur at the index entry insert. */ @@ -1393,10 +1435,8 @@ row_ins_scan_sec_index_for_duplicate( if (cmp == 0) { if (row_ins_dupl_error_with_rec(rec, entry, index)) { - /* printf("Duplicate key in index %s\n", - index->name); - dtuple_print(entry); */ - + row_ins_unique_report_err(thr, rec, entry, + index); err = DB_DUPLICATE_KEY; thr_get_trx(thr)->error_info = index; @@ -1491,7 +1531,8 @@ row_ins_duplicate_error_in_clust( if (row_ins_dupl_error_with_rec(rec, entry, cursor->index)) { trx->error_info = cursor->index; - + row_ins_unique_report_err(thr, rec, entry, + cursor->index); return(DB_DUPLICATE_KEY); } } @@ -1515,6 +1556,8 @@ row_ins_duplicate_error_in_clust( cursor->index)) { trx->error_info = cursor->index; + row_ins_unique_report_err(thr, rec, entry, + cursor->index); return(DB_DUPLICATE_KEY); } } diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 147606ec17c..ef50a4ca261 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -162,7 +162,7 @@ in the buffer pool to all database pages in the buffer pool smaller than the following number. But it is not guaranteed that the value stays below that during a time of heavy update/insert activity. */ -ulint srv_max_buf_pool_modified_pct = 100; +ulint srv_max_buf_pool_modified_pct = 90; /* If the following is != 0 we do not allow inserts etc. This protects the user from forgetting the innodb_force_recovery keyword to my.cnf */ @@ -2366,6 +2366,19 @@ srv_sprintf_innodb_monitor( ut_a(buf < buf_end + 1500); + if (*dict_unique_err_buf != '\0') { + buf += sprintf(buf, +"---------------------------------------------------------------\n" +"LATEST UNIQUE KEY ERROR (is masked in REPLACE or INSERT IGNORE)\n" +"---------------------------------------------------------------\n"); + + if (buf_end - buf > 6000) { + buf+= sprintf(buf, "%.4000s", dict_unique_err_buf); + } + } + + ut_a(buf < buf_end + 1500); + lock_print_info(buf, buf_end); buf = buf + strlen(buf); From fa08fdfaef03aca2be4f84cfe8ba3657a4f40577 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 5 May 2003 10:54:56 +0300 Subject: [PATCH 149/188] buf0lru.c, buf0flu.c: Better warning message if more than 4 / 5 of the buffer pool is consumed by locks of adaptive hash index --- innobase/buf/buf0flu.c | 3 ++- innobase/buf/buf0lru.c | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 4d998f8306f..d732bf40b57 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -531,7 +531,8 @@ buf_flush_try_page( rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); if (buf_debug_prints) { - printf("Flushing single page space %lu, page no %lu \n", + printf( + "Flushing single page space %lu, page no %lu \n", block->space, block->offset); } diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 2ec1506c522..735a32cf067 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -228,9 +228,12 @@ loop: fprintf(stderr, " InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n" "InnoDB: lock heaps or the adaptive hash index! Check that your\n" -"InnoDB: transactions do not set too many row locks. Starting InnoDB\n" -"InnoDB: Monitor to print diagnostics, including lock heap and hash index\n" -"InnoDB: sizes.\n"); +"InnoDB: transactions do not set too many row locks.\n" +"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n" +"InnoDB: the buffer pool bigger?\n" +"InnoDB: Starting the InnoDB Monitor to print diagnostics, including\n" +"InnoDB: lock heap and hash index sizes.\n", + buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE)); srv_print_innodb_monitor = TRUE; From 3e1afec6719e9891983bfea19ff18e0d39cdb275 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Mon, 5 May 2003 14:52:39 +0300 Subject: [PATCH 150/188] Fixed that reading a DATE string of 000000 is interpreted as 0000-00-00 instead of 2000-00-00 --- mysql-test/r/loaddata.result | 11 +++ mysql-test/std_data/loaddata1.dat | 3 + mysql-test/t/loaddata.test | 11 +++ sql/time.cc | 142 +----------------------------- 4 files changed, 27 insertions(+), 140 deletions(-) create mode 100644 mysql-test/r/loaddata.result create mode 100644 mysql-test/std_data/loaddata1.dat create mode 100644 mysql-test/t/loaddata.test diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result new file mode 100644 index 00000000000..d121a4e6c40 --- /dev/null +++ b/mysql-test/r/loaddata.result @@ -0,0 +1,11 @@ +drop table if exists t1; +create table t1 (a date, b date, c date not null, d date); +load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ','; +load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES; +SELECT * from t1; +a b c d +0000-00-00 NULL 0000-00-00 0000-00-00 +0000-00-00 0000-00-00 0000-00-00 0000-00-00 +2003-03-03 2003-03-03 2003-03-03 NULL +2003-03-03 2003-03-03 2003-03-03 NULL +drop table t1; diff --git a/mysql-test/std_data/loaddata1.dat b/mysql-test/std_data/loaddata1.dat new file mode 100644 index 00000000000..c9e8549b211 --- /dev/null +++ b/mysql-test/std_data/loaddata1.dat @@ -0,0 +1,3 @@ +,\N,NULL,, +00,0,000000,, +2003-03-03, 20030303,030303,\N diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test new file mode 100644 index 00000000000..ceb5c47af11 --- /dev/null +++ b/mysql-test/t/loaddata.test @@ -0,0 +1,11 @@ +# +# Some simple test of load data +# + +drop table if exists t1; + +create table t1 (a date, b date, c date not null, d date); +load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ','; +load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES; +SELECT * from t1; +drop table t1; diff --git a/sql/time.cc b/sql/time.cc index 4fe79966404..cc8cd4fbcf9 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -251,144 +251,6 @@ void get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month, DBUG_VOID_RETURN; } -/* find date from string and put it in vektor - Input: pos = "YYMMDD" OR "YYYYMMDD" in any order or - "xxxxx YYxxxMMxxxDD xxxx" where xxx is anything exept - a number. Month or day mustn't exeed 2 digits, year may be 4 digits. -*/ - - -#ifdef NOT_NEEDED - -void find_date(string pos,uint *vek,uint flag) -{ - uint length,value; - string start; - DBUG_ENTER("find_date"); - DBUG_PRINT("enter",("pos: '%s' flag: %d",pos,flag)); - - bzero((char*) vek,sizeof(int)*4); - while (*pos && !isdigit(*pos)) - pos++; - length=(uint) strlen(pos); - for (uint i=0 ; i< 3; i++) - { - start=pos; value=0; - while (isdigit(pos[0]) && - ((pos-start) < 2 || ((pos-start) < 4 && length >= 8 && - !(flag & 3)))) - { - value=value*10 + (uint) (uchar) (*pos - '0'); - pos++; - } - vek[flag & 3]=value; flag>>=2; - while (*pos && (ispunct(*pos) || isspace(*pos))) - pos++; - } - DBUG_PRINT("exit",("year: %d month: %d day: %d",vek[0],vek[1],vek[2])); - DBUG_VOID_RETURN; -} /* find_date */ - - - /* Outputs YYMMDD if input year < 100 or YYYYMMDD else */ - -static long calc_daynr_from_week(uint year,uint week,uint day) -{ - long daynr; - int weekday; - - daynr=calc_daynr(year,1,1); - if ((weekday= calc_weekday(daynr,0)) >= 3) - daynr+= (7-weekday); - else - daynr-=weekday; - - return (daynr+week*7+day-8); -} - -void convert_week_to_date(string date,uint flag,uint *res_length) -{ - string format; - uint year,vek[4]; - - find_date(date,vek,(uint) (1*4+2*16)); /* YY-WW-DD */ - year=vek[0]; - - get_date_from_daynr(calc_daynr_from_week(vek[0],vek[1],vek[2]), - &vek[0],&vek[1],&vek[2]); - *res_length=8; - format="%04d%02d%02d"; - if (year < 100) - { - vek[0]= vek[0]%100; - *res_length=6; - format="%02d%02d%02d"; - } - sprintf(date,format,vek[flag & 3],vek[(flag >> 2) & 3], - vek[(flag >> 4) & 3]); - return; -} - - /* returns YYWWDD or YYYYWWDD according to input year */ - /* flag only reflects format of input date */ - -void convert_date_to_week(string date,uint flag,uint *res_length) -{ - uint vek[4],weekday,days,year,week,day; - long daynr,first_daynr; - char buff[256],*format; - - if (! date[0]) - { - get_date(buff,0,0L); /* Use current date */ - find_date(buff+2,vek,(uint) (1*4+2*16)); /* YY-MM-DD */ - } - else - find_date(date,vek,flag); - - year= vek[0]; - daynr= calc_daynr(year,vek[1],vek[2]); - first_daynr=calc_daynr(year,1,1); - - /* Caculate year and first daynr of year */ - if (vek[1] == 1 && (weekday=calc_weekday(first_daynr,0)) >= 3 && - vek[2] <= 7-weekday) - { - if (!year--) - year=99; - first_daynr=first_daynr-calc_days_in_year(year); - } - else if (vek[1] == 12 && - (weekday=calc_weekday(first_daynr+calc_days_in_year(year)),0) < 3 && - vek[2] > 31-weekday) - { - first_daynr=first_daynr+calc_days_in_year(year); - if (year++ == 99) - year=0; - } - - /* Calulate daynr of first day of week 1 */ - if ((weekday= calc_weekday(first_daynr,0)) >= 3) - first_daynr+= (7-weekday); - else - first_daynr-=weekday; - - days=(int) (daynr-first_daynr); - week=days/7+1 ; day=calc_weekday(daynr,0)+1; - - *res_length=8; - format="%04d%02d%02d"; - if (year < 100) - { - *res_length=6; - format="%02d%02d%02d"; - } - sprintf(date,format,year,week,day); - return; -} - -#endif - /* Functions to handle periods */ ulong convert_period_to_month(ulong period) @@ -486,14 +348,14 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) else date[6]=0; - if (year_length == 2) + if (year_length == 2 && i >=2 && (date[1] || date[2])) date[0]+= (date[0] < YY_PART_YEAR ? 2000 : 1900); number_of_fields=i; while (i < 6) date[i++]=0; if (number_of_fields < 3 || date[1] > 12 || date[2] > 31 || date[3] > 23 || date[4] > 59 || date[5] > 59 || - !fuzzy_date && (date[1] == 0 || date[2] == 0)) + (!fuzzy_date && (date[1] == 0 || date[2] == 0))) { /* Only give warning for a zero date if there is some garbage after */ if (!not_zero_date) // If zero date From 23cb2a95f94413f74725750dc9cc7d8f8f73dee1 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 6 May 2003 22:33:08 +0200 Subject: [PATCH 151/188] - added MySQL-shared-compat.spec(.sh) to the distribution. This spec file can be used to build a compatibility package that includes the shared libraries of MySQL 3.23.xx and MySQL 4.0.xx for backwards compatibility with dynamically linked applications. It simply repackages the two MySQL-shared RPMs, so these need to be created or downloaded separately. --- support-files/Makefile.am | 9 ++- support-files/MySQL-shared-compat.spec.sh | 72 +++++++++++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 support-files/MySQL-shared-compat.spec.sh diff --git a/support-files/Makefile.am b/support-files/Makefile.am index 4aadd98bd1b..79ba6eec763 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -25,7 +25,8 @@ EXTRA_DIST = mysql.spec.sh \ mysql-log-rotate.sh \ mysql.server.sh \ binary-configure.sh \ - magic + magic \ + MySQL-shared-compat.spec.sh SUBDIRS = MacOSX @@ -35,7 +36,8 @@ pkgdata_DATA = my-small.cnf \ my-huge.cnf \ mysql-log-rotate \ mysql-@VERSION@.spec \ - binary-configure + binary-configure \ + MySQL-shared-compat.spec pkgdata_SCRIPTS = mysql.server @@ -47,7 +49,8 @@ CLEANFILES = my-small.cnf \ mysql-@VERSION@.spec \ mysql-log-rotate \ mysql.server \ - binary-configure + binary-configure \ + MySQL-shared-compat.spec mysql-@VERSION@.spec: mysql.spec diff --git a/support-files/MySQL-shared-compat.spec.sh b/support-files/MySQL-shared-compat.spec.sh new file mode 100644 index 00000000000..f569dc20f42 --- /dev/null +++ b/support-files/MySQL-shared-compat.spec.sh @@ -0,0 +1,72 @@ +# +# MySQL-shared-compat.spec +# +# RPM build instructions to create a "meta" package that includes two +# versions of the MySQL shared libraries (for compatibility with +# distributions that ship older versions of MySQL and do not provide a +# separate "MySQL-shared" package. This spec file simply repackages two +# already existing MySQL-shared RPMs into a single package. +# +# 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 + +# +# Change this to match the version of the shared libs you want to include +# +%define version4 @VERSION@ +%define version3 3.23.56 + +Name: MySQL-shared-compat +Packager: Lenz Grimmer +Vendor: MySQL AB +License: GPL +Group: Applications/Databases +URL: http://www.mysql.com/ +Autoreqprov: on +Version: %{version4} +Release: 0 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Obsoletes: MySQL-shared, mysql-shared +Provides: MySQL-shared +Summary: MySQL shared libraries for MySQL %{version4} and %{version3} +Source0: MySQL-shared-%{version4}-0.i386.rpm +Source1: MySQL-shared-%{version3}-1.i386.rpm +# No need to include the RPMs once more - they can be downloaded seperately +# if you want to rebuild this package +NoSource: 0 +NoSource: 1 +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%description +This package includes the shared libraries for both MySQL %{version3} and +MySQL %{version4}. Install this package instead of "MySQL-shared", if you +have applications installed that are dynamically linked against MySQL +3.23.xx but you want to upgrade to MySQL 4.0.xx without breaking the library +dependencies. + +%install +[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT; +mkdir -p $RPM_BUILD_ROOT +cd $RPM_BUILD_ROOT +rpm2cpio %{SOURCE0} | cpio -iv --make-directories +rpm2cpio %{SOURCE1} | cpio -iv --make-directories + +%clean +[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT; + +%files +%defattr(-, root, root) +/usr/lib/libmysqlclient* From ef6f91458debf81e765d8fd5342558721366aa27 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 7 May 2003 19:01:45 +0300 Subject: [PATCH 152/188] sql_select.cc, opt_sum.cc: Fix bug: if MIN() or MAX() resulted in a deadlock or a lock wait timeout, MySQL did not return an error, but NULL as the function value --- sql/opt_sum.cc | 50 +++++++++++++++++++++++++++++++++++------------ sql/sql_select.cc | 9 +++++++++ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 21296845c21..855813f1140 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -37,8 +37,10 @@ static bool find_range_key(TABLE_REF *ref, Field* field,COND *cond); RETURN VALUES 0 No errors - 1 if all items was resolved - -1 on impossible conditions + 1 if all items were resolved + -1 on impossible conditions + OR an error number from my_base.h HA_ERR_... if a deadlock or a lock + wait timeout happens, for example */ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) @@ -50,6 +52,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) table_map where_tables= 0; Item *item; COND *org_conds= conds; + int error; if (conds) where_tables= conds->used_tables(); @@ -136,7 +139,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) const_result=0; break; } - bool error= table->file->index_init((uint) ref.key); + error= table->file->index_init((uint) ref.key); enum ha_rkey_function find_flag= HA_READ_KEY_OR_NEXT; uint prefix_len= ref.key_length; /* @@ -150,12 +153,17 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) } if (!ref.key_length) - error=table->file->index_first(table->record[0]) !=0; + { + error=table->file->index_first(table->record[0]); + } else + { error=table->file->index_read(table->record[0],key_buff, ref.key_length, - find_flag) || - key_cmp(table, key_buff, ref.key, prefix_len); + find_flag); + if (!error && key_cmp(table, key_buff, ref.key, prefix_len)) + error = HA_ERR_KEY_NOT_FOUND; + } if (table->key_read) { table->key_read=0; @@ -163,7 +171,14 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) } table->file->index_end(); if (error) - return -1; // No rows matching where + { + if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) + return -1; // No rows matching WHERE + + table->file->print_error(error, MYF(0)); + return(error); // HA_ERR_LOCK_DEADLOCK or + // some other error + } removed_tables|= table->map; } else if (!expr->const_item()) // This is VERY seldom false @@ -202,16 +217,19 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) const_result=0; break; } - bool error=table->file->index_init((uint) ref.key); + error=table->file->index_init((uint) ref.key); if (!ref.key_length) - error=table->file->index_last(table->record[0]) !=0; + { + error=table->file->index_last(table->record[0]); + } else { - error = table->file->index_read(table->record[0], key_buff, + error=table->file->index_read(table->record[0], key_buff, ref.key_length, - HA_READ_PREFIX_LAST) || - key_cmp(table,key_buff,ref.key,ref.key_length); + HA_READ_PREFIX_LAST); + if (!error && key_cmp(table,key_buff,ref.key,ref.key_length)) + error = HA_ERR_KEY_NOT_FOUND; } if (table->key_read) { @@ -220,7 +238,13 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) } table->file->index_end(); if (error) - return -1; // Impossible query + { + if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) + return -1; // Impossible query + + table->file->print_error(error, MYF(0)); + return error; // Deadlock or some other error + } removed_tables|= table->map; } else if (!expr->const_item()) // This is VERY seldom false diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 79ba13a3339..daf388c9ff3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -391,8 +391,17 @@ mysql_select(THD *thd,TABLE_LIST *tables,List &fields,COND *conds, if (tables && join.tmp_table_param.sum_func_count && ! group) { int res; + /* + opt_sum_query returns -1 if no rows match to the WHERE conditions, + or 1 if all items were resolved, or 0, or an error number HA_ERR_... + */ if ((res=opt_sum_query(tables, all_fields, conds))) { + if (res > 1) + { + delete procedure; + DBUG_RETURN(-1); + } if (res < 0) { error=return_zero_rows(&join, result, tables, fields, !group, From 611836e488a995b76b22f7e999514e6c0c9d1308 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 7 May 2003 19:13:56 +0300 Subject: [PATCH 153/188] my_base.h: Fix bug: if MIN() or MAX() resulted in a deadlock or a lock wait timeout, MySQL did not return an error, but NULL as the function value --- include/my_base.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/my_base.h b/include/my_base.h index f91b45ee469..cd04ab971db 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -224,6 +224,7 @@ enum ha_base_keytype { /* Errorcodes given by functions */ +/* opt_sum_query() assumes these codes are > 1 */ #define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */ #define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */ #define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */ From 38bb63e16bec82af522d50d1100fb777da7856e2 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Wed, 7 May 2003 23:15:46 +0300 Subject: [PATCH 154/188] Updated comment --- sql/sql_parse.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 60942e47337..2b1c05bfaeb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2533,7 +2533,8 @@ error: save_priv In this we store global and db level grants for the table Note that we don't store db level grants if the global grants - is enough to satisfy the request. + is enough to satisfy the request and the global grants contains + a SELECT grant. ****************************************************************************/ bool From 71ce598fa21e2e8ee3abf156af2cd95821f3d282 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Wed, 7 May 2003 23:59:24 +0300 Subject: [PATCH 155/188] Security patch to remove wrong error when one had a global update/delete privilige and a database specific SELECT privilege. --- sql/sql_acl.cc | 9 ++++++--- sql/sql_base.cc | 9 ++++----- sql/sql_parse.cc | 12 +++++++++++- tests/grant.pl | 13 +++++++++++++ tests/grant.res | 15 +++++++++++++++ 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 05ec57b134a..f36e39b0645 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2118,8 +2118,8 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables, } -bool check_grant_column (THD *thd,TABLE *table, const char *name, - uint length, uint show_tables) +bool check_grant_column(THD *thd,TABLE *table, const char *name, + uint length, uint show_tables) { GRANT_TABLE *grant_table; GRANT_COLUMN *grant_column; @@ -2127,6 +2127,8 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name, uint want_access=table->grant.want_privilege; if (!want_access) return 0; // Already checked + if (!grant_option) + goto err2; pthread_mutex_lock(&LOCK_grant); @@ -2158,8 +2160,9 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name, #endif /* We must use my_printf_error() here! */ - err: +err: pthread_mutex_unlock(&LOCK_grant); +err2: if (!show_tables) { const char *command=""; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 46370949650..d28fedba25b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1616,7 +1616,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, else thd->dupp_field=field; } - if (check_grants && check_grant_column(thd,table,name,length)) + if (check_grants && check_grant_column(thd,table,name,length)) return WRONG_GRANT; return field; } @@ -1643,8 +1643,8 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) { found_table=1; Field *find=find_field_in_table(thd,tables->table,name,length, - grant_option && - tables->table->grant.want_privilege, + test(tables->table->grant. + want_privilege), 1); if (find) { @@ -1684,8 +1684,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) for (; tables ; tables=tables->next) { Field *field=find_field_in_table(thd,tables->table,name,length, - grant_option && - tables->table->grant.want_privilege, + test(tables->table->grant.want_privilege), allow_rowid); if (field) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 152d9c585ca..805063cb6dc 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2155,7 +2155,17 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, if ((thd->master_access & want_access) == want_access) { - *save_priv=thd->master_access | thd->db_access; + /* + If we don't have a global SELECT privilege, we have to get the database + specific access rights to be able to handle queries of type + UPDATE t1 SET a=1 WHERE b > 0 + */ + db_access= thd->db_access; + if (!(thd->master_access & SELECT_ACL) && + (db && (!thd->db || strcmp(db,thd->db)))) + db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, + thd->priv_user, db); /* purecov: inspected */ + *save_priv=thd->master_access | db_access; return FALSE; } if ((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL) || diff --git a/tests/grant.pl b/tests/grant.pl index bf67ce5e790..8ec83c85349 100644 --- a/tests/grant.pl +++ b/tests/grant.pl @@ -214,8 +214,21 @@ user_query("update $opt_database.test set b=b+1",1); safe_query("grant SELECT on *.* to $user"); user_connect(0); user_query("update $opt_database.test set b=b+1"); +user_query("update $opt_database.test set b=b+1 where a > 0"); safe_query("revoke SELECT on *.* from $user"); +safe_query("grant SELECT on $opt_database.* to $user"); user_connect(0); +user_query("update $opt_database.test set b=b+1"); +user_query("update $opt_database.test set b=b+1 where a > 0"); +safe_query("grant UPDATE on *.* to $user"); +user_connect(0); +user_query("update $opt_database.test set b=b+1"); +user_query("update $opt_database.test set b=b+1 where a > 0"); +safe_query("revoke UPDATE on *.* from $user"); +safe_query("revoke SELECT on $opt_database.* from $user"); +user_connect(0); +user_query("update $opt_database.test set b=b+1 where a > 0",1); +user_query("update $opt_database.test set b=b+1",1); # Add one privilege at a time until the user has all privileges user_query("select * from test",1); diff --git a/tests/grant.res b/tests/grant.res index 44e20db555f..086111ce567 100644 --- a/tests/grant.res +++ b/tests/grant.res @@ -195,8 +195,23 @@ Error in execute: select command denied to user: 'grant_user@localhost' for colu grant SELECT on *.* to grant_user@localhost Connecting grant_user update grant_test.test set b=b+1 +update grant_test.test set b=b+1 where a > 0 revoke SELECT on *.* from grant_user@localhost +grant SELECT on grant_test.* to grant_user@localhost Connecting grant_user +update grant_test.test set b=b+1 +update grant_test.test set b=b+1 where a > 0 +grant UPDATE on *.* to grant_user@localhost +Connecting grant_user +update grant_test.test set b=b+1 +update grant_test.test set b=b+1 where a > 0 +revoke UPDATE on *.* from grant_user@localhost +revoke SELECT on grant_test.* from grant_user@localhost +Connecting grant_user +update grant_test.test set b=b+1 where a > 0 +Error in execute: select command denied to user: 'grant_user@localhost' for column 'a' in table 'test' +update grant_test.test set b=b+1 +Error in execute: select command denied to user: 'grant_user@localhost' for column 'b' in table 'test' select * from test Error in execute: select command denied to user: 'grant_user@localhost' for table 'test' grant select on grant_test.test to grant_user@localhost From 8a28428c0a4976214d97b61b7207560c19e2cf6d Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Thu, 8 May 2003 00:34:23 +0300 Subject: [PATCH 156/188] Better grant test for SELECT * --- sql/sql_base.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d28fedba25b..3f8a59613b4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1877,14 +1877,14 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, for (; tables ; tables=tables->next) { TABLE *table=tables->table; - if (grant_option && !(table->grant.privilege & - table->grant.want_privilege) && - check_grant_all_columns(thd,SELECT_ACL,table)) - DBUG_RETURN(-1); if (!table_name || (!strcmp(table_name,tables->alias) && (!db_name || !tables->db || !strcmp(tables->db,db_name)))) { + if (!(table->grant.privilege & SELECT_ACL) && + check_grant_all_columns(thd,SELECT_ACL,table)) + DBUG_RETURN(-1); + Field **ptr=table->field,*field; thd->used_tables|=table->map; while ((field = *ptr++)) From 5b7a86faec185e5d787586a35ee6866e12997836 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Thu, 8 May 2003 01:47:20 +0300 Subject: [PATCH 157/188] More tests --- tests/grant.pl | 10 ++++++++-- tests/grant.res | 18 ++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/tests/grant.pl b/tests/grant.pl index fb73be786b6..3146b7b6c25 100644 --- a/tests/grant.pl +++ b/tests/grant.pl @@ -82,6 +82,7 @@ user_query("select * from mysql.user where user = '$opt_user'"); user_query("select * from mysql.db where user = '$opt_user'"); safe_query("grant select on *.* to $user,$user"); safe_query("show grants for $user"); +user_connect(0); # The following should fail user_query("insert into mysql.user (host,user) values ('error','$opt_user')",1); @@ -95,16 +96,21 @@ safe_query("grant select on $opt_database.not_exists to $opt_user",1); safe_query("grant FILE on $opt_database.test to $opt_user",1); safe_query("grant select on *.* to wrong___________user_name",1); safe_query("grant select on $opt_database.* to wrong___________user_name",1); +user_connect(0); user_query("grant select on $opt_database.test to $opt_user with grant option",1); safe_query("set password FOR ''\@''=''",1); user_query("set password FOR root\@$opt_host = password('test')",1); # Change privileges for user safe_query("revoke select on *.* from $user"); -safe_query("grant create on *.* to $user"); +safe_query("grant create,update on *.* to $user"); user_connect(0); +safe_query("flush privileges"); user_query("create table $opt_database.test (a int,b int)"); - +user_query("update $opt_database.test set b=b+1 where a > 0",1); +safe_query("show grants for $user"); +safe_query("revoke update on *.* from $user"); +user_connect(0); safe_query("grant select(c) on $opt_database.test to $user",1); safe_query("revoke select(c) on $opt_database.test from $user",1); safe_query("grant select on $opt_database.test to wrong___________user_name",1); diff --git a/tests/grant.res b/tests/grant.res index 7947ca692b6..f208241d989 100644 --- a/tests/grant.res +++ b/tests/grant.res @@ -28,6 +28,7 @@ grant select on *.* to grant_user@localhost,grant_user@localhost show grants for grant_user@localhost GRANT SELECT ON *.* TO 'grant_user'@'localhost' +Connecting grant_user insert into mysql.user (host,user) values ('error','grant_user') Error in execute: insert command denied to user: 'grant_user@localhost' for table 'user' update mysql.user set host='error' WHERE user='grant_user' @@ -50,6 +51,7 @@ grant select on *.* to wrong___________user_name Error in execute: The host or user argument to GRANT is too long grant select on grant_test.* to wrong___________user_name Error in execute: The host or user argument to GRANT is too long +Connecting grant_user grant select on grant_test.test to grant_user with grant option Error in execute: grant command denied to user: 'grant_user@localhost' for table 'test' set password FOR ''@''='' @@ -57,9 +59,17 @@ Error in execute: Can't find any matching row in the user table set password FOR root@localhost = password('test') Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql' revoke select on *.* from grant_user@localhost -grant create on *.* to grant_user@localhost +grant create,update on *.* to grant_user@localhost Connecting grant_user +flush privileges create table grant_test.test (a int,b int) +update grant_test.test set b=b+1 where a > 0 +Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'a' in table 'test' +show grants for grant_user@localhost +GRANT UPDATE, CREATE ON *.* TO 'grant_user'@'localhost' + +revoke update on *.* from grant_user@localhost +Connecting grant_user grant select(c) on grant_test.test to grant_user@localhost Error in execute: Unknown column 'c' in 'test' revoke select(c) on grant_test.test from grant_user@localhost @@ -214,9 +224,9 @@ revoke UPDATE on *.* from grant_user@localhost revoke SELECT on grant_test.* from grant_user@localhost Connecting grant_user update grant_test.test set b=b+1 where a > 0 -Error in execute: select command denied to user: 'grant_user@localhost' for column 'a' in table 'test' +Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'a' in table 'test' update grant_test.test set b=b+1 -Error in execute: select command denied to user: 'grant_user@localhost' for column 'b' in table 'test' +Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'b' in table 'test' select * from test Error in execute: select command denied to user: 'grant_user@localhost' for table 'test' grant select on grant_test.test to grant_user@localhost @@ -504,7 +514,7 @@ Error in execute: Access denied for user: 'grant_user@localhost' to database 'gr grant LOCK TABLES on *.* to grant_user@localhost show grants for grant_user@localhost GRANT LOCK TABLES ON *.* TO 'grant_user'@'localhost' -GRANT SELECT, INSERT ON grant_test.test3 TO 'grant_user'@'localhost' +GRANT SELECT, INSERT ON `grant_test`.`test3` TO 'grant_user'@'localhost' select * from mysql.user where user='grant_user' 127.0.0.1 grant_user 7f70e8b858ee6782 N N N N N N N N N N N N N N N N N N N N N 0 0 0 From 7e85affd1e5869f114d392a990a4964c8f3c2144 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Sat, 10 May 2003 14:52:22 -0400 Subject: [PATCH 158/188] MySQL-classic did not pass the test suite rpl_rotate_logs.test anymore because a recent 1.1424.2.17 cset introduced an opt_using_transactions which prevented binlogs to be rotated if transactions were not enabled. Fix for this. This bug did not affect releases. --- sql/log.cc | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index f4c78b9c50d..79ee59eedf8 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1133,24 +1133,26 @@ bool MYSQL_LOG::write(Log_event* event_info) was a MyISAM event! */ - if (file == &log_file && opt_using_transactions - && !my_b_tell(&thd->transaction.trans_log)) + if (file == &log_file) // we are writing to the real log (disk) { - /* - LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog - chunks also before it is successfully completed. We only report - the binlog write and do the commit inside the transactional table - handler if the log event type is appropriate. - */ - - if (event_info->get_type_code() == QUERY_EVENT - || event_info->get_type_code() == EXEC_LOAD_EVENT) + if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log)) { - error = ha_report_binlog_offset_and_commit(thd, log_file_name, - file->pos_in_file); - called_handler_commit=1; + /* + LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog + chunks also before it is successfully completed. We only report + the binlog write and do the commit inside the transactional table + handler if the log event type is appropriate. + */ + + if (event_info->get_type_code() == QUERY_EVENT + || event_info->get_type_code() == EXEC_LOAD_EVENT) + { + error = ha_report_binlog_offset_and_commit(thd, log_file_name, + file->pos_in_file); + called_handler_commit=1; + } } - + /* we wrote to the real log, check automatic rotation */ should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size); } From 9ec42178e9755a021ba5ea6509c60e551f409b85 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 12 May 2003 17:33:42 +0300 Subject: [PATCH 159/188] srv0start.c, trx0sys.c: Let InnoDB to skip writing of pages from the doublewrite buffer if innodb_force_recovery=6; normally, if the page is corrupt AND the corresponding page in the doublewrite buffer is also corrupt, InnoDB calls exit(1) --- innobase/srv/srv0start.c | 5 ++++- innobase/trx/trx0sys.c | 13 +++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index ec0546f8c66..552355e5d45 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1168,7 +1168,10 @@ innobase_start_or_create_for_mysql(void) and restore them from the doublewrite buffer if possible */ - trx_sys_doublewrite_restore_corrupt_pages(); + if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { + + trx_sys_doublewrite_restore_corrupt_pages(); + } } srv_normalize_path_for_win(srv_arch_dir); diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c index c403cd447e3..51aad60d3e2 100644 --- a/innobase/trx/trx0sys.c +++ b/innobase/trx/trx0sys.c @@ -340,7 +340,6 @@ trx_sys_doublewrite_restore_corrupt_pages(void) /* It is an unwritten doublewrite buffer page: do nothing */ - } else { /* Read in the actual page from the data files */ @@ -357,9 +356,19 @@ trx_sys_doublewrite_restore_corrupt_pages(void) "InnoDB: Trying to recover it from the doublewrite buffer.\n"); if (buf_page_is_corrupted(page)) { + fprintf(stderr, + "InnoDB: Dump of the page:\n"); + buf_page_print(read_buf); + fprintf(stderr, + "InnoDB: Dump of corresponding page in doublewrite buffer:\n"); + buf_page_print(page); + fprintf(stderr, "InnoDB: Also the page in the doublewrite buffer is corrupt.\n" - "InnoDB: Cannot continue operation.\n"); + "InnoDB: Cannot continue operation.\n" + "InnoDB: You can try to recover the database with the my.cnf\n" + "InnoDB: option:\n" + "InnoDB: set-variable=innodb_force_recovery=6\n"); exit(1); } From 07238bab28f4fc739186259ce3590944fd153f3f Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 12 May 2003 17:09:31 +0200 Subject: [PATCH 160/188] - On Mac OS X, better call mysql_install_db with "-IN-RPM" during the installation to make sure the privilege tables are being installed even if the DNS configuration is broken, which seems to be quite common (reverse lookups to "hostname" fail). This should resolve the problem many Mac OS users experience ("Fatal error: Can't open privilege tables: Table 'mysql.host' doesn't exist") when they try to start MySQL after installing the PKG. --- support-files/MacOSX/postinstall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/MacOSX/postinstall.sh b/support-files/MacOSX/postinstall.sh index daaf10bda8f..f46f4480e3e 100644 --- a/support-files/MacOSX/postinstall.sh +++ b/support-files/MacOSX/postinstall.sh @@ -10,7 +10,7 @@ if cd @prefix@ ; then if [ ! -f data/mysql/db.frm ] ; then - ./scripts/mysql_install_db + ./scripts/mysql_install_db -IN-RPM fi if [ -d data ] ; then From 4bde719df7b67e8c42c16724af0e3eacb64c3757 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Tue, 13 May 2003 10:54:07 +0300 Subject: [PATCH 161/188] Safety fix to enable RAID in max binaries Better fix for format('nan') Fix for HAVING COUNT(DISTINCT...) --- myisam/mi_check.c | 12 ++++++---- myisam/mi_dynrec.c | 21 +++++++----------- myisam/myisamchk.c | 16 ++++++++------ mysql-test/r/func_misc.result | 3 +++ mysql-test/r/having.result | 8 +++++++ mysql-test/t/func_misc.test | 5 +++++ mysql-test/t/having.test | 2 ++ mysys/raid.cc | 4 ++-- scripts/mysql_install_db.sh | 6 ++--- sql/item_strfunc.cc | 14 +++++++----- sql/mysqld.cc | 1 + sql/sql_yacc.yy | 8 +++++-- tests/big_record.pl | 41 +++++++++++++++++++++++++++++------ tests/table_types.pl | 35 ++++++++++++------------------ 14 files changed, 110 insertions(+), 66 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index a64130cf6e0..92641cce13a 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -873,15 +873,19 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) { if (b_type & BLOCK_LAST) { - mi_check_print_error(param,"Record link to short for record at %s", - llstr(start_recpos,llbuff)); + mi_check_print_error(param, + "Wrong record length %s of %s at %s", + llstr(block_info.rec_len-left_length,llbuff), + llstr(block_info.rec_len, llbuff2), + llstr(start_recpos,llbuff3)); got_error=1; break; } if (info->state->data_file_length < block_info.next_filepos) { - mi_check_print_error(param,"Found next-recordlink that points outside datafile at %s", - llstr(block_info.filepos,llbuff)); + mi_check_print_error(param, + "Found next-recordlink that points outside datafile at %s", + llstr(block_info.filepos,llbuff)); got_error=1; break; } diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index dc51269ac35..faf86c3ffbd 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -485,7 +485,7 @@ int _mi_write_part_record(MI_INFO *info, { info->update&= ~HA_STATE_EXTEND_BLOCK; if (my_block_write(&info->rec_cache,(byte*) *record-head_length, - length+extra_length+del_length,filepos)) + length+extra_length+del_length,filepos)) goto err; } else if (my_b_write(&info->rec_cache,(byte*) *record-head_length, @@ -1412,10 +1412,7 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos) VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); if (my_read(file,(char*) header,sizeof(info->header),MYF(0)) != sizeof(info->header)) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - return BLOCK_FATAL_ERROR; - } + goto err; } DBUG_DUMP("header",(byte*) header,MI_BLOCK_INFO_HEADER_LENGTH); if (info->second_read) @@ -1435,10 +1432,7 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos) if ((info->block_len=(uint) mi_uint3korr(header+1)) < MI_MIN_BLOCK_LENGTH || (info->block_len & (MI_DYN_ALIGN_SIZE -1))) - { - my_errno=HA_ERR_WRONG_IN_RECORD; - return BLOCK_ERROR; - } + goto err; info->filepos=filepos; info->next_filepos=mi_sizekorr(header+4); info->prev_filepos=mi_sizekorr(header+12); @@ -1449,7 +1443,7 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos) (mi_uint4korr(header+12) != 0 && (mi_uint4korr(header+12) != (ulong) ~0 || info->prev_filepos != (ulong) ~0))) - return BLOCK_FATAL_ERROR; + goto err; #endif return return_val | BLOCK_DELETED; /* Deleted block */ @@ -1529,8 +1523,9 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos) info->second_read=1; info->filepos=filepos+12; return return_val; - default: - my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */ - return BLOCK_ERROR; } + +err: + my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */ + return BLOCK_ERROR; } diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index ac1d0fbfc4a..a3970d65fdf 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -44,6 +44,7 @@ static const char *load_default_groups[]= { "myisamchk", 0 }; static const char *set_charset_name; static CHARSET_INFO *set_charset; static long opt_myisam_block_size; +static const char *my_progname_short; static const char *type_names[]= { "?","char","binary", "short", "long", "float", @@ -85,6 +86,7 @@ int main(int argc, char **argv) { int error; MY_INIT(argv[0]); + my_progname_short= my_progname+dirname_length(my_progname); #ifdef __EMX__ _wildcard (&argc, &argv); @@ -330,7 +332,7 @@ static void usage(void) puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n"); puts("Description, check and repair of MyISAM tables."); puts("Used without options all tables on the command will be checked for errors"); - printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname); + printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname_short); puts("\nGlobal options:\n\ -#, --debug=... Output debug log. Often this is 'd:t:o,filename'\n\ -?, --help Display this help and exit.\n\ @@ -679,7 +681,7 @@ static void get_options(register int *argc,register char ***argv) { VOID(fprintf(stderr, "%s: --unpack can't be used with --quick or --sort-records\n", - my_progname)); + my_progname_short)); exit(1); } if ((check_param.testflag & T_READONLY) && @@ -689,7 +691,7 @@ static void get_options(register int *argc,register char ***argv) { VOID(fprintf(stderr, "%s: Can't use --readonly when repairing or sorting\n", - my_progname)); + my_progname_short)); exit(1); } @@ -1655,13 +1657,13 @@ void mi_check_print_warning(MI_CHECK *param, const char *fmt,...) if (!param->warning_printed && !param->error_printed) { if (param->testflag & T_SILENT) - fprintf(stderr,"%s: MyISAM file %s\n",my_progname, + fprintf(stderr,"%s: MyISAM file %s\n",my_progname_short, param->isam_file_name); param->out_flag|= O_DATA_LOST; } param->warning_printed=1; va_start(args,fmt); - fprintf(stderr,"%s: warning: ",my_progname); + fprintf(stderr,"%s: warning: ",my_progname_short); VOID(vfprintf(stderr, fmt, args)); VOID(fputc('\n',stderr)); fflush(stderr); @@ -1681,12 +1683,12 @@ void mi_check_print_error(MI_CHECK *param, const char *fmt,...) if (!param->warning_printed && !param->error_printed) { if (param->testflag & T_SILENT) - fprintf(stderr,"%s: MyISAM file %s\n",my_progname,param->isam_file_name); + fprintf(stderr,"%s: MyISAM file %s\n",my_progname_short,param->isam_file_name); param->out_flag|= O_DATA_LOST; } param->error_printed|=1; va_start(args,fmt); - fprintf(stderr,"%s: error: ",my_progname); + fprintf(stderr,"%s: error: ",my_progname_short); VOID(vfprintf(stderr, fmt, args)); VOID(fputc('\n',stderr)); fflush(stderr); diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 4eed80c4cc9..8d05adcc1ba 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -10,3 +10,6 @@ inet_aton("255.255.255.255.255") inet_aton("255.255.1.255") inet_aton("0.1.255") select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511); inet_ntoa(1099511627775) inet_ntoa(4294902271) inet_ntoa(511) NULL 255.255.1.255 0.0.1.255 +select length(format('nan', 2)) > 0; +length(format('nan', 2)) > 0 +1 diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index f113eb6ed49..d643070f7f9 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -69,4 +69,12 @@ select id, sum(qty) as sqty from t1 group by id having sqty>2; id sqty 1 5 2 9 +select sum(qty) as sqty from t1 group by id having count(id) > 0; +sqty +5 +9 +select sum(qty) as sqty from t1 group by id having count(distinct id) > 0; +sqty +5 +9 drop table t1; diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index d48b17e87af..be64c170fa1 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -7,3 +7,8 @@ select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.5555 select inet_ntoa(inet_aton("255.255.255.255.255.255.255.255")); select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255"); select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511); + +# +# Test for core dump with nan +# +select length(format('nan', 2)) > 0; diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test index fd972fea1ad..cb6fa85ffde 100644 --- a/mysql-test/t/having.test +++ b/mysql-test/t/having.test @@ -63,4 +63,6 @@ drop table t1; create table t1 (id int not null, qty int not null); insert into t1 values (1,2),(1,3),(2,4),(2,5); select id, sum(qty) as sqty from t1 group by id having sqty>2; +select sum(qty) as sqty from t1 group by id having count(id) > 0; +select sum(qty) as sqty from t1 group by id having count(distinct id) > 0; drop table t1; diff --git a/mysys/raid.cc b/mysys/raid.cc index d6359dc0f93..0b688464fb3 100644 --- a/mysys/raid.cc +++ b/mysys/raid.cc @@ -157,10 +157,10 @@ extern "C" { DBUG_PRINT("enter",("Fd: %d pos: %lu whence: %d MyFlags: %d", fd, (ulong) pos, whence, MyFlags)); - assert(pos != MY_FILEPOS_ERROR); - if (is_raid(fd)) { + assert(pos != MY_FILEPOS_ERROR); + RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); DBUG_RETURN(raid->Seek(pos,whence,MyFlags)); } diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 2f27f5d7c1a..64fdd0dfebb 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -118,7 +118,8 @@ then resolved=`$bindir/resolveip localhost 2>&1` if [ $? -eq 0 ] then - echo "Sorry, the host '$hostname' could not be looked up." + echo "Neither host '$hostname' and 'localhost' could not be looked up with" + echo "$bindir/resolveip" echo "Please configure the 'hostname' command to return a correct hostname." echo "If you want to solve this at a later stage, restart this script with" echo "the --force option" @@ -134,15 +135,12 @@ then fi # Create database directories mysql & test -if test "$IN_RPM" -eq 0 -then if test ! -d $ldata; then mkdir $ldata; chmod 700 $ldata ; fi if test ! -d $ldata/mysql; then mkdir $ldata/mysql; chmod 700 $ldata/mysql ; fi if test ! -d $ldata/test; then mkdir $ldata/test; chmod 700 $ldata/test ; fi if test -w / -a ! -z "$user"; then chown $user $ldata $ldata/mysql $ldata/test; fi -fi # Initialize variables c_d="" i_d="" diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9876b77e8cb..ae8bf1dfecb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1473,15 +1473,17 @@ String *Item_func_format::val_str(String *str) str_length=str->length(); if (nr < 0) str_length--; // Don't count sign - length=str->length()+(diff=(str_length- dec-1)/3); - if (diff && diff < 330) // size of buff ... + + /* We need this test to handle 'nan' values */ + if (str_length >= dec+4) { char *tmp,*pos; - str=copy_if_not_alloced(&tmp_str,str,length); + length= str->length()+(diff=(str_length- dec-1)/3); + str= copy_if_not_alloced(&tmp_str,str,length); str->length(length); - tmp=(char*) str->ptr()+length - dec-1; - for (pos=(char*) str->ptr()+length ; pos != tmp; pos--) - pos[0]=pos[- (int) diff]; + tmp= (char*) str->ptr()+length - dec-1; + for (pos= (char*) str->ptr()+length ; pos != tmp; pos--) + pos[0]= pos[-(int) diff]; while (diff) { pos[0]=pos[-(int) diff]; pos--; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9e9fcd4ecbd..c6a67e2582c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1607,6 +1607,7 @@ static void init_signals(void) sa.sa_handler=handle_segfault; #endif sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); #ifdef SIGBUS sigaction(SIGBUS, &sa, NULL); #endif diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f895c809366..340fbc1b3dc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2017,8 +2017,12 @@ sum_expr: { $$=new Item_sum_count(new Item_int((int32) 0L,1)); } | COUNT_SYM '(' in_sum_expr ')' { $$=new Item_sum_count($3); } - | COUNT_SYM '(' DISTINCT expr_list ')' - { $$=new Item_sum_count_distinct(* $4); } + | COUNT_SYM '(' DISTINCT + { Select->in_sum_expr++; } + expr_list + { Select->in_sum_expr--; } + ')' + { $$=new Item_sum_count_distinct(* $5); } | GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')' { $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); } | MIN_SYM '(' in_sum_expr ')' diff --git a/tests/big_record.pl b/tests/big_record.pl index 08547b50823..fbe94e3540f 100755 --- a/tests/big_record.pl +++ b/tests/big_record.pl @@ -11,12 +11,13 @@ use Getopt::Long; $opt_host=""; $opt_user=$opt_password=""; $opt_db="test"; -$opt_rows=200; # Test of blobs up to ($rows-1)*100000+1 bytes +$opt_rows=20; # Test of blobs up to ($rows-1)*100000+1 bytes $opt_compress=0; $opt_table="test_big_record"; +$opt_loop_count=100000; # Change this to make test harder/easier GetOptions("host=s","db=s","user=s", "password=s", "table=s", "rows=i", - "compress") || die "Aborted"; + "compress", "loop-count=i") || die "Aborted"; print "Connection to database $test_db\n"; @@ -42,12 +43,12 @@ $|=1; # Flush output to stdout to be able to monitor process for ($i=0 ; $i < $opt_rows ; $i++) { $tmp= chr(65+($i % 16)) x ($i*100000+1); - print $i," ",length($tmp),"\n"; $tmp= $dbh->quote($tmp); $dbh->do("insert into $opt_table (test) values ($tmp)") or die $DBI::errstr; + print "."; } -print "Reading records\n"; +print "\nReading records\n"; $sth=$dbh->prepare("select * from $opt_table", { "mysql_use_result" => 1}) or die $dbh->errstr; @@ -56,14 +57,40 @@ $sth->execute() or die $sth->errstr; $i=0; while (($row = $sth->fetchrow_arrayref)) { - print $row->[0]," ",length($row->[1]),"\n"; die "Record $i had wrong data in blob" if ($row->[1] ne (chr(65+($i % 16)) x ($i*100000+1))); $i++; } die "Didn't get all rows from server" if ($i != $opt_rows); -$dbh->do("drop table $opt_table") or die $DBI::errstr; +# +# Test by insert/updating/deleting random rows for a while +# -print "Test ok\n"; +print "Testing insert/update/delete\n"; + +$max_row_id= $rows; +for ($i= 0 ; $i < $opt_loop_count ; $i++) +{ + $length= int(rand 65535); + $tmp= chr(65+($i % 16)) x $length; + $tmp= $dbh->quote($tmp); + $dbh->do("insert into $opt_table (test) values ($tmp)") or die $DBI::errstr; + $max_row_id++; + $length=int(rand 65535); + $tmp= chr(65+($i % 16)) x $length; + $tmp= $dbh->quote($tmp); + $id= int(rand $max_row_id); + $dbh->do("update $opt_table set test= $tmp where auto= $id") or die $DBI::errstr; + if (($i % 2) == 1) + { + $id= int(rand $max_row_id); + $dbh->do("delete from $opt_table where auto= $id") or die $DBI::errstr; + } + print "." if ($i % ($opt_loop_count/100) == 1); +} + +# $dbh->do("drop table $opt_table") or die $DBI::errstr; + +print "\nTest ok\n"; exit 0; diff --git a/tests/table_types.pl b/tests/table_types.pl index 8198cd9ba86..4dbcdcb975c 100755 --- a/tests/table_types.pl +++ b/tests/table_types.pl @@ -66,13 +66,6 @@ $dbh = $server->connect(); #### $table_name="bench1"; -<<<<<<< table_types.pl -||||||| 1.2 -test("n","type=isam","char"); test("m","type=myisam pack_keys=1","char"); exit(1); - -======= - ->>>>>>> /tmp/T4a17019 test($table_name,"type=isam","char"); test($table_name,"type=myisam pack_keys=0","char"); test($table_name,"type=myisam pack_keys=0","char"); @@ -91,7 +84,7 @@ exit (0); sub test { my ($name,$options,$chartype)=@_; - + print "\nTesting with options: '$options'\n"; $dbh->do("drop table $name"); do_many($dbh,$server->create("$name", @@ -102,23 +95,23 @@ sub test { ["primary key (id,id2)", "index index_id3 (id3)"], $options)); - + if ($opt_lock_tables) { $sth = $dbh->do("LOCK TABLES $name WRITE") || die $DBI::errstr; } - + if ($opt_fast && defined($server->{vacuum})) { $server->vacuum(\$dbh,1); } - + #### #### Insert $total_rows records in order, in reverse order and random. #### - + $loop_time=new Benchmark; - + if ($opt_fast_insert) { $query="insert into $name values "; @@ -127,11 +120,11 @@ sub test { { $query="insert into $name (id,id2,id3,dummy1) values "; } - + if (($opt_fast || $opt_fast_insert) && $limits->{'multi_value_insert'}) { $query_size=$server->{'limits'}->{'query_size'}; - + print "Inserting $opt_loop_count multiple-value rows in order\n"; $res=$query; for ($i=0 ; $i < $opt_loop_count ; $i++) @@ -186,7 +179,7 @@ sub test { { $sth = $dbh->do($query . "($i,$i,$i,'ABCDEFGHIJ')") or die $DBI::errstr; } - + print "Inserting $opt_loop_count rows in reverse order\n"; for ($i=0 ; $i < $opt_loop_count ; $i++) { @@ -195,25 +188,25 @@ sub test { ($total_rows-1-$i) . ",'BCDEFGHIJK')") or die $DBI::errstr; } - + print "Inserting $opt_loop_count rows in random order\n"; - + for ($i=0 ; $i < $opt_loop_count ; $i++) { $sth = $dbh->do($query . "(". $random[$i] . "," . $random[$i] . "," . $random[$i] . ",'CDEFGHIJKL')") or die $DBI::errstr; } } - + $end_time=new Benchmark; print "Time for insert (" . ($total_rows) . "): " . timestr(timediff($end_time, $loop_time),"all") . "\n\n"; - + if ($opt_fast && defined($server->{vacuum})) { $server->vacuum(\$dbh,1); } - + $sth=$dbh->prepare("show table status like '$name'"); $sth->execute || die "Show table status returned error: $DBI::errstr\n"; while (@row = $sth->fetchrow_array) From 95aa8cfbcf0b9b74be1e4812fe5140b8945b7480 Mon Sep 17 00:00:00 2001 From: "jani@rhols221.adsl.netsonic.fi" <> Date: Tue, 13 May 2003 11:39:07 +0300 Subject: [PATCH 162/188] Removed timing of tests from mysql-test-run. Needed by QNX, and there was no real use for timing. --- mysql-test/mysql-test-run.sh | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 65c960d13fa..40726b776e8 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -110,7 +110,6 @@ GREP=grep if test $? != 0; then exit 1; fi PRINTF=printf RM=rm -TIME=`which time` if test $? != 0; then exit 1; fi TR=tr XARGS=`which xargs` @@ -409,7 +408,7 @@ fi if test ${COLUMNS:-0} -lt 80 ; then COLUMNS=80 ; fi E=`$EXPR $COLUMNS - 8` -DASH72=`$ECHO '------------------------------------------------------------------------'|$CUT -c 1-$E` +DASH72=`$ECHO '------------------------------------------'|$CUT -c 1-$E` # on source dist, we pick up freshly build executables # on binary, use what is installed @@ -588,9 +587,8 @@ skip_test() { USERT=" ...." SYST=" ...." REALT=" ...." - timestr="$USERT $SYST $REALT" pname=`$ECHO "$1 "|$CUT -c 1-24` - RES="$pname $timestr" + RES="$pname" skip_inc $ECHO "$RES$RES_SPACE [ skipped ]" } @@ -1217,31 +1215,15 @@ run_testcase () $RM -f r/$tname.*reject mysql_test_args="-R r/$tname.result $EXTRA_MYSQL_TEST_OPT" if [ -z "$DO_CLIENT_GDB" ] ; then - mytime=`$TIME -p $MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE` + `$MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`; else do_gdb_test "$mysql_test_args" "$tf" fi res=$? - if [ $res = 0 ]; then - mytime=`$CAT $TIMEFILE | $TAIL -3 | $TR '\n' ':'` - - USERT=`$ECHO $mytime | $CUT -d : -f 2 | $CUT -d ' ' -f 2` - USERT=`prefix_to_8 $USERT` - SYST=`$ECHO $mytime | $CUT -d : -f 3 | $CUT -d ' ' -f 2` - SYST=`prefix_to_8 $SYST` - REALT=`$ECHO $mytime | $CUT -d : -f 1 | $CUT -d ' ' -f 2` - REALT=`prefix_to_8 $REALT` - else - USERT=" ...." - SYST=" ...." - REALT=" ...." - fi - - timestr="$USERT $SYST $REALT" pname=`$ECHO "$tname "|$CUT -c 1-24` - RES="$pname $timestr" + RES="$pname" if [ x$many_slaves = x1 ] ; then stop_slave 1 @@ -1373,7 +1355,7 @@ then fi $ECHO -$ECHO " TEST USER SYSTEM ELAPSED RESULT" +$ECHO " TEST RESULT" $ECHO $DASH72 if [ -z "$1" ] ; From 13530887cb09194adbe89d65277c59ffb71fdd15 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Tue, 13 May 2003 18:58:26 +0300 Subject: [PATCH 163/188] Fix for UNION and LEFT JOIN (Bug #386) Fixed wrong logging of Access denied error (Bug #398) --- include/my_global.h | 2 +- mysql-test/r/union.result | 59 ++++++++++++++++++++++++++++++++++++- mysql-test/t/union.test | 61 ++++++++++++++++++++++++++++++++++++++- mysys/my_seek.c | 3 ++ sql/field.h | 2 ++ sql/mysql_priv.h | 4 +-- sql/sql_base.cc | 8 ++--- sql/sql_insert.cc | 10 +++---- sql/sql_parse.cc | 11 +++++-- sql/sql_union.cc | 5 ++-- sql/sql_update.cc | 6 ++-- 11 files changed, 150 insertions(+), 21 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 98034fc1cff..0cd1352a290 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -361,7 +361,7 @@ typedef unsigned short ushort; #define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1)) #define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) #ifndef HAVE_RINT -#define rint(A) floor((A)+0.5) +#define rint(A) floor((A)+((A) < 0) -0.5 : 0.5) #endif /* Define some general constants */ diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 2af9d5a3584..970e83c6752 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,t5,t6; CREATE TABLE t1 (a int not null, b char (10) not null); insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c'); CREATE TABLE t2 (a int not null, b char (10) not null); @@ -202,3 +202,60 @@ a 11 set SQL_SELECT_LIMIT=DEFAULT; drop table t1,t2; +CREATE TABLE t1 ( +cid smallint(5) unsigned NOT NULL default '0', +cv varchar(250) NOT NULL default '', +PRIMARY KEY (cid), +UNIQUE KEY cv (cv) +) ; +INSERT INTO t1 VALUES (8,'dummy'); +CREATE TABLE t2 ( +cid bigint(20) unsigned NOT NULL auto_increment, +cap varchar(255) NOT NULL default '', +PRIMARY KEY (cid), +KEY cap (cap) +) ; +CREATE TABLE t3 ( +gid bigint(20) unsigned NOT NULL auto_increment, +gn varchar(255) NOT NULL default '', +must tinyint(4) default NULL, +PRIMARY KEY (gid), +KEY gn (gn) +) ; +INSERT INTO t3 VALUES (1,'V1',NULL); +CREATE TABLE t4 ( +uid bigint(20) unsigned NOT NULL default '0', +gid bigint(20) unsigned default NULL, +rid bigint(20) unsigned default NULL, +cid bigint(20) unsigned default NULL, +UNIQUE KEY m (uid,gid,rid,cid), +KEY uid (uid), +KEY rid (rid), +KEY cid (cid), +KEY container (gid,rid,cid) +) ; +INSERT INTO t4 VALUES (1,1,NULL,NULL); +CREATE TABLE t5 ( +rid bigint(20) unsigned NOT NULL auto_increment, +rl varchar(255) NOT NULL default '', +PRIMARY KEY (rid), +KEY rl (rl) +) ; +CREATE TABLE t6 ( +uid bigint(20) unsigned NOT NULL auto_increment, +un varchar(250) NOT NULL default '', +uc smallint(5) unsigned NOT NULL default '0', +PRIMARY KEY (uid), +UNIQUE KEY nc (un,uc), +KEY un (un) +) ; +INSERT INTO t6 VALUES (1,'test',8); +SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test"; +uid rl g1 cid gg +1 NULL V1 NULL 1 +SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test"; +uid rl g1 cid gg +(SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test") UNION (SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test"); +uid rl g1 cid gg +1 NULL V1 NULL 1 +drop table t1,t2,t3,t4,t5,t6; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 6e6b43ebe3b..7262b8f78d7 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -2,7 +2,7 @@ # Test of unions # -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,t5,t6; CREATE TABLE t1 (a int not null, b char (10) not null); insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c'); CREATE TABLE t2 (a int not null, b char (10) not null); @@ -98,3 +98,62 @@ set SQL_SELECT_LIMIT=2; (select * from t1 limit 1) union (select * from t2 limit 3); set SQL_SELECT_LIMIT=DEFAULT; drop table t1,t2; + +# +# Test error with left join +# + +CREATE TABLE t1 ( + cid smallint(5) unsigned NOT NULL default '0', + cv varchar(250) NOT NULL default '', + PRIMARY KEY (cid), + UNIQUE KEY cv (cv) +) ; +INSERT INTO t1 VALUES (8,'dummy'); +CREATE TABLE t2 ( + cid bigint(20) unsigned NOT NULL auto_increment, + cap varchar(255) NOT NULL default '', + PRIMARY KEY (cid), + KEY cap (cap) +) ; +CREATE TABLE t3 ( + gid bigint(20) unsigned NOT NULL auto_increment, + gn varchar(255) NOT NULL default '', + must tinyint(4) default NULL, + PRIMARY KEY (gid), + KEY gn (gn) +) ; +INSERT INTO t3 VALUES (1,'V1',NULL); +CREATE TABLE t4 ( + uid bigint(20) unsigned NOT NULL default '0', + gid bigint(20) unsigned default NULL, + rid bigint(20) unsigned default NULL, + cid bigint(20) unsigned default NULL, + UNIQUE KEY m (uid,gid,rid,cid), + KEY uid (uid), + KEY rid (rid), + KEY cid (cid), + KEY container (gid,rid,cid) +) ; +INSERT INTO t4 VALUES (1,1,NULL,NULL); +CREATE TABLE t5 ( + rid bigint(20) unsigned NOT NULL auto_increment, + rl varchar(255) NOT NULL default '', + PRIMARY KEY (rid), + KEY rl (rl) +) ; +CREATE TABLE t6 ( + uid bigint(20) unsigned NOT NULL auto_increment, + un varchar(250) NOT NULL default '', + uc smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (uid), + UNIQUE KEY nc (un,uc), + KEY un (un) +) ; +INSERT INTO t6 VALUES (1,'test',8); + +SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test"; +SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test"; +(SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test") UNION (SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test"); + +drop table t1,t2,t3,t4,t5,t6; diff --git a/mysys/my_seek.c b/mysys/my_seek.c index 177a5cee953..ec24a26b3d9 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mysys_priv.h" +#include /* Seek to position in file */ /*ARGSUSED*/ @@ -27,6 +28,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d", fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos, whence, MyFlags)); + DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */ + newpos=lseek(fd, pos, whence); if (newpos == (os_off_t) -1) { diff --git a/sql/field.h b/sql/field.h index 842bbb89988..e63802d8c00 100644 --- a/sql/field.h +++ b/sql/field.h @@ -122,6 +122,8 @@ public: Field *tmp= (Field*) memdup_root(root,(char*) this,size_of()); if (tmp) { + if (tmp->table->maybe_null) + tmp->flags&= ~NOT_NULL_FLAG; tmp->table=new_table; tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0; tmp->unireg_check=Field::NONE; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 956fdf8cd45..d02202cd7c6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -560,8 +560,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table, bool return_if_owned_by_thd=0); bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables); void copy_field_from_tmp_record(Field *field,int offset); -int fill_record(List &fields,List &values); -int fill_record(Field **field,List &values); +int fill_record(List &fields,List &values, bool ignore_errors); +int fill_record(Field **field,List &values, bool ignore_errors); OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild); /* sql_calc.cc */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4c607bd5698..3bfd5e14d43 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2112,7 +2112,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ******************************************************************************/ int -fill_record(List &fields,List &values) +fill_record(List &fields,List &values, bool ignore_errors) { List_iterator_fast f(fields),v(values); Item *value; @@ -2122,7 +2122,7 @@ fill_record(List &fields,List &values) while ((field=(Item_field*) f++)) { value=v++; - if (value->save_in_field(field->field, 0)) + if (value->save_in_field(field->field, 0) && !ignore_errors) DBUG_RETURN(1); } DBUG_RETURN(0); @@ -2130,7 +2130,7 @@ fill_record(List &fields,List &values) int -fill_record(Field **ptr,List &values) +fill_record(Field **ptr,List &values, bool ignore_errors) { List_iterator_fast v(values); Item *value; @@ -2140,7 +2140,7 @@ fill_record(Field **ptr,List &values) while ((field = *ptr++)) { value=v++; - if (value->save_in_field(field, 0)) + if (value->save_in_field(field, 0) && !ignore_errors) DBUG_RETURN(1); } DBUG_RETURN(0); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e02f457fd77..33a13fabdc6 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -219,7 +219,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, if (fields.elements || !value_count) { restore_record(table,2); // Get empty record - if (fill_record(fields,*values) || check_null_fields(thd,table)) + if (fill_record(fields, *values, 0) || check_null_fields(thd,table)) { if (values_list.elements != 1) { @@ -236,7 +236,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, restore_record(table,2); // Get empty record else table->record[0][0]=table->record[2][0]; // Fix delete marker - if (fill_record(table->field,*values)) + if (fill_record(table->field, *values, 0)) { if (values_list.elements != 1) { @@ -1330,9 +1330,9 @@ bool select_insert::send_data(List &values) return 0; } if (fields->elements) - fill_record(*fields,values); + fill_record(*fields, values, 1); else - fill_record(table->field,values); + fill_record(table->field, values, 1); if (write_record(table,&info)) return 1; if (table->next_number_field) // Clear for next record @@ -1444,7 +1444,7 @@ bool select_create::send_data(List &values) thd->offset_limit--; return 0; } - fill_record(field,values); + fill_record(field, values, 1); if (write_record(table,&info)) return 1; if (table->next_number_field) // Clear for next record diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 73983bc03b1..7496d05be50 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -196,9 +196,17 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, thd->db=0; thd->db_length=0; USER_RESOURCES ur; + char tmp_passwd[SCRAMBLE_LENGTH]; if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH) return 1; + /* + Move password to temporary buffer as it may be stored in communication + buffer + */ + strmov(tmp_passwd, passwd); + passwd= tmp_passwd; // Use local copy + if (!(thd->user = my_strdup(user, MYF(0)))) { send_error(net,ER_OUT_OF_RESOURCES); @@ -264,6 +272,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, } else send_ok(net); // Ready to handle questions + thd->password= test(passwd[0]); // Remember for error messages return 0; // ok } @@ -617,7 +626,6 @@ check_connections(THD *thd) net->read_timeout=(uint) thd->variables.net_read_timeout; if (check_user(thd,COM_CONNECT, user, passwd, db, 1)) return (-1); - thd->password=test(passwd[0]); return 0; } @@ -1007,7 +1015,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, decrease_user_connections(save_uc); x_free((gptr) save_db); x_free((gptr) save_user); - thd->password=test(passwd[0]); break; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index e7afa7fbd23..55b5d57d07d 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -110,7 +110,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) while ((item= it++)) if (item_list.push_back(item)) DBUG_RETURN(-1); - if (setup_fields(thd,first_table,item_list,0,0,1)) + if (setup_tables(first_table) || + setup_fields(thd,first_table,item_list,0,0,1)) DBUG_RETURN(-1); } @@ -259,7 +260,7 @@ bool select_union::send_data(List &values) return 0; } - fill_record(table->field,values); + fill_record(table->field, values, 1); if ((write_record(table,&info))) { if (create_myisam_from_heap(thd, table, tmp_table_param, info.last_errno, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 0dc6073278f..de953aa603b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -277,7 +277,7 @@ int mysql_update(THD *thd, if (!(select && select->skipp_record())) { store_record(table,1); - if (fill_record(fields,values)) + if (fill_record(fields, values, 0)) break; /* purecov: inspected */ found++; if (compare_record(table, query_id)) @@ -726,7 +726,7 @@ bool multi_update::send_data(List ¬_used_values) { table->status|= STATUS_UPDATED; store_record(table,1); - if (fill_record(*fields_for_table[offset], *values_for_table[offset])) + if (fill_record(*fields_for_table[offset], *values_for_table[offset],0 )) DBUG_RETURN(1); found++; if (compare_record(table, thd->query_id)) @@ -754,7 +754,7 @@ bool multi_update::send_data(List ¬_used_values) { int error; TABLE *tmp_table= tmp_tables[offset]; - fill_record(tmp_table->field+1, *values_for_table[offset]); + fill_record(tmp_table->field+1, *values_for_table[offset], 1); found++; /* Store pointer to row */ memcpy((char*) tmp_table->field[0]->ptr, From 2693203a08c72dcf87d0f8be49846530eba56666 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Tue, 13 May 2003 19:26:07 +0300 Subject: [PATCH 164/188] Fixed problem with ansi mode and GROUP BY with constants. (Bug #387) --- mysql-test/r/ansi.result | 10 ++++++++++ mysql-test/t/ansi-master.opt | 1 + mysql-test/t/ansi.test | 17 +++++++++++++++++ sql/sql_select.cc | 3 ++- 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/ansi.result create mode 100644 mysql-test/t/ansi-master.opt create mode 100644 mysql-test/t/ansi.test diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result new file mode 100644 index 00000000000..f9f96310b73 --- /dev/null +++ b/mysql-test/r/ansi.result @@ -0,0 +1,10 @@ +drop table if exists t1; +SELECT 'A' || 'B'; +'A' || 'B' +AB +CREATE TABLE t1 (id INT, id2 int); +SELECT id,NULL,1,1.1,'a' FROM t1 GROUP BY id; +id NULL 1 1.1 a +SELECT id FROM t1 GROUP BY id2; +'t1.id' isn't in GROUP BY +drop table t1; diff --git a/mysql-test/t/ansi-master.opt b/mysql-test/t/ansi-master.opt new file mode 100644 index 00000000000..6bf7a4f30e2 --- /dev/null +++ b/mysql-test/t/ansi-master.opt @@ -0,0 +1 @@ +--ansi diff --git a/mysql-test/t/ansi.test b/mysql-test/t/ansi.test new file mode 100644 index 00000000000..e1ac8ffd4f9 --- /dev/null +++ b/mysql-test/t/ansi.test @@ -0,0 +1,17 @@ +# +# Test of ansi mode +# + +drop table if exists t1; + +# Test some functions that works different in ansi mode + +SELECT 'A' || 'B'; + +# Test GROUP BY behaviour + +CREATE TABLE t1 (id INT, id2 int); +SELECT id,NULL,1,1.1,'a' FROM t1 GROUP BY id; +--error 1055 +SELECT id FROM t1 GROUP BY id2; +drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index daf388c9ff3..ff6fde1ca0c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6668,7 +6668,8 @@ setup_group(THD *thd,TABLE_LIST *tables,List &fields, while ((item=li++)) { - if (item->type() != Item::SUM_FUNC_ITEM && !item->marker) + if (item->type() != Item::SUM_FUNC_ITEM && !item->marker && + !item->const_item()) { my_printf_error(ER_WRONG_FIELD_WITH_GROUP, ER(ER_WRONG_FIELD_WITH_GROUP), From c9c5841760ef0c180f2dd04079c3ad2e1d4f3322 Mon Sep 17 00:00:00 2001 From: "jani@hynda.(none)" <> Date: Tue, 13 May 2003 19:34:51 +0300 Subject: [PATCH 165/188] - Fixed a bug in myisam_max_[extra]_sort_file_size, bug ID 339 and 342 - Fix for QNX: UNIX sockets available since 6.2.1 --- include/my_global.h | 1 - mysql-test/r/variables.result | 19 ++++++++++--------- mysql-test/t/variables.test | 13 ++++++++----- sql/mysqld.cc | 5 +++-- sql/set_var.cc | 32 ++++++++++++++++++++++++++++---- sql/set_var.h | 14 ++++++++++++++ 6 files changed, 63 insertions(+), 21 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 98034fc1cff..d412d9064f5 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -290,7 +290,6 @@ C_MODE_END /* This has to be after include limits.h */ #define HAVE_ERRNO_AS_DEFINE #define HAVE_FCNTL_LOCK -#undef HAVE_SYS_UN_H #undef HAVE_FINITE #undef HAVE_RINT #undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */ diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 1cc48d2aeac..8a6791004ee 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -108,17 +108,14 @@ show global variables like 'table_type'; Variable_name Value table_type INNODB set GLOBAL query_cache_size=100000; -set myisam_max_sort_file_size=10000, GLOBAL myisam_max_sort_file_size=20000; -show variables like 'myisam_max_sort_file_size'; -Variable_name Value -myisam_max_sort_file_size 10000 +set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; Variable_name Value -myisam_max_sort_file_size 20000 -set myisam_max_sort_file_size=default; +myisam_max_sort_file_size 1048576 +set GLOBAL myisam_max_sort_file_size=default; show variables like 'myisam_max_sort_file_size'; Variable_name Value -myisam_max_sort_file_size 20000 +myisam_max_sort_file_size 2147483647 set global net_retry_count=10, session net_retry_count=10; set global net_buffer_length=1024, net_write_timeout=200, net_read_timeout=300; set session net_buffer_length=2048, net_write_timeout=500, net_read_timeout=600; @@ -211,6 +208,10 @@ set @@global.sql_auto_is_null=1; Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL select @@global.sql_auto_is_null; Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL +set myisam_max_sort_file_size=100; +Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL +set myisam_max_extra_sort_file_size=100; +Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL set autocommit=1; set big_tables=1; select @@autocommit, @@big_tables; @@ -264,11 +265,11 @@ select @@max_user_connections; @@max_user_connections 100 set global max_write_lock_count=100; -set myisam_max_extra_sort_file_size=100; +set global myisam_max_extra_sort_file_size=100; select @@myisam_max_extra_sort_file_size; @@myisam_max_extra_sort_file_size 100 -set myisam_max_sort_file_size=100; +set global myisam_max_sort_file_size=100; set myisam_sort_buffer_size=100; set net_buffer_length=100; set net_read_timeout=100; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 639a28edd38..c730f317fcb 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -69,10 +69,9 @@ show local variables like 'table_type'; show global variables like 'table_type'; set GLOBAL query_cache_size=100000; -set myisam_max_sort_file_size=10000, GLOBAL myisam_max_sort_file_size=20000; -show variables like 'myisam_max_sort_file_size'; +set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; -set myisam_max_sort_file_size=default; +set GLOBAL myisam_max_sort_file_size=default; show variables like 'myisam_max_sort_file_size'; set global net_retry_count=10, session net_retry_count=10; @@ -137,6 +136,10 @@ set @@concurrent_insert=1; set @@global.sql_auto_is_null=1; --error 1228 select @@global.sql_auto_is_null; +--error 1229 +set myisam_max_sort_file_size=100; +--error 1229 +set myisam_max_extra_sort_file_size=100; # Test setting all variables @@ -181,9 +184,9 @@ set max_tmp_tables=100; set global max_user_connections=100; select @@max_user_connections; set global max_write_lock_count=100; -set myisam_max_extra_sort_file_size=100; +set global myisam_max_extra_sort_file_size=100; select @@myisam_max_extra_sort_file_size; -set myisam_max_sort_file_size=100; +set global myisam_max_sort_file_size=100; set myisam_sort_buffer_size=100; set net_buffer_length=100; set net_read_timeout=100; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c6a67e2582c..731298266dc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3839,12 +3839,13 @@ replicating a LOAD DATA INFILE command", (gptr*) &global_system_variables.myisam_max_extra_sort_file_size, (gptr*) &max_system_variables.myisam_max_extra_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, - 0, ~0L, 0, 1, 0}, + 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0}, {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE, "Don't use the fast sort index method to created index if the temporary file would get bigger than this!", (gptr*) &global_system_variables.myisam_max_sort_file_size, (gptr*) &max_system_variables.myisam_max_sort_file_size, 0, - GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, ~0L, 0, 1024*1024, 0}, + GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE, + 0, 1024*1024, 0}, {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS, "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", (gptr*) &global_system_variables.myisam_repair_threads, diff --git a/sql/set_var.cc b/sql/set_var.cc index 6fe82328580..12ce37c5bc8 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -82,6 +82,8 @@ static void fix_net_retry_count(THD *thd, enum_var_type type); static void fix_max_join_size(THD *thd, enum_var_type type); static void fix_query_cache_size(THD *thd, enum_var_type type); static void fix_key_buffer_size(THD *thd, enum_var_type type); +static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type); +static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); /* Variable definition list @@ -165,8 +167,8 @@ sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables", &SV::max_tmp_tables); sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count", &max_write_lock_count); -sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size); -sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size); +sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size, fix_myisam_max_extra_sort_file_size, 1); +sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1); sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads); sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size); sys_var_thd_ulong sys_net_buffer_length("net_buffer_length", @@ -586,6 +588,21 @@ static void fix_low_priority_updates(THD *thd, enum_var_type type) } +static void +fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type) +{ + myisam_max_extra_temp_length= + (my_off_t) global_system_variables.myisam_max_sort_file_size; +} + + +static void +fix_myisam_max_sort_file_size(THD *thd, enum_var_type type) +{ + myisam_max_temp_length= + (my_off_t) global_system_variables.myisam_max_sort_file_size; +} + /* Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR */ @@ -815,15 +832,22 @@ byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type) bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) { + ulonglong tmp= var->value->val_int(); + + if ((ulonglong) tmp > max_system_variables.*offset) + tmp= max_system_variables.*offset; + + if (option_limits) + tmp= (ulong) getopt_ull_limit_value(tmp, option_limits); if (var->type == OPT_GLOBAL) { /* Lock is needed to make things safe on 32 bit systems */ pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= var->value->val_int(); + global_system_variables.*offset= (ulonglong) tmp; pthread_mutex_unlock(&LOCK_global_system_variables); } else - thd->variables.*offset= var->value->val_int(); + thd->variables.*offset= (ulonglong) tmp; return 0; } diff --git a/sql/set_var.h b/sql/set_var.h index c74f1e827bd..f33f53c5acc 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -233,13 +233,27 @@ class sys_var_thd_ulonglong :public sys_var_thd { public: ulonglong SV::*offset; + bool only_global; sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg) :sys_var_thd(name_arg), offset(offset_arg) {} + sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg, + sys_after_update_func func, bool only_global_arg) + :sys_var_thd(name_arg, func), offset(offset_arg), + only_global(only_global_arg) + {} bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_LONGLONG; } byte *value_ptr(THD *thd, enum_var_type type); + bool check_default(enum_var_type type) + { + return type == OPT_GLOBAL && !option_limits; + } + bool check_type(enum_var_type type) + { + return (only_global && type != OPT_GLOBAL); + } }; From a2928182ad2b9e65e605375e266277cdb7cc0d20 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 13 May 2003 18:54:20 +0200 Subject: [PATCH 166/188] - added mysql_fix_privilege_tables(1) man page to distribution (thanks to Christian Hammers from the Debian project for providing it) - Updated version number in man pages (3.23 -> 4.0) --- man/Makefile.am | 2 +- man/isamchk.1 | 2 +- man/isamlog.1 | 2 +- man/mysql.1 | 2 +- man/mysql_fix_privilege_tables.1 | 23 +++++++++++++++++++++++ man/mysql_zap.1 | 2 +- man/mysqlaccess.1 | 2 +- man/mysqladmin.1 | 2 +- man/mysqld.1 | 2 +- man/mysqld_multi.1 | 2 +- man/mysqld_safe.1 | 2 +- man/mysqldump.1 | 2 +- man/mysqlshow.1 | 2 +- man/perror.1 | 2 +- man/replace.1 | 2 +- 15 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 man/mysql_fix_privilege_tables.1 diff --git a/man/Makefile.am b/man/Makefile.am index 7019d2aa865..9f919e77b8f 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -19,7 +19,7 @@ man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \ mysqladmin.1 mysqld.1 mysqld_multi.1 mysqldump.1 mysqlshow.1 \ - perror.1 replace.1 mysqld_safe.1 + perror.1 replace.1 mysqld_safe.1 mysql_fix_privilege_tables.1 EXTRA_DIST = $(man_MANS) diff --git a/man/isamchk.1 b/man/isamchk.1 index bfc4ccd9c08..341e968a131 100644 --- a/man/isamchk.1 +++ b/man/isamchk.1 @@ -1,4 +1,4 @@ -.TH isamchk 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH isamchk 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME .BR isamchk \- Description, check and repair of ISAM tables. diff --git a/man/isamlog.1 b/man/isamlog.1 index a386f11c010..402c3052ad8 100644 --- a/man/isamlog.1 +++ b/man/isamlog.1 @@ -1,4 +1,4 @@ -.TH isamlog 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH isamlog 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME isamlog - Write info about whats in a nisam log file. .SH USAGE diff --git a/man/mysql.1 b/man/mysql.1 index 6664581072f..c0c37716b14 100644 --- a/man/mysql.1 +++ b/man/mysql.1 @@ -1,4 +1,4 @@ -.TH mysql 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH mysql 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME mysql \- text-based client for mysqld, a SQL-based relational database daemon .SH SYNOPSIS diff --git a/man/mysql_fix_privilege_tables.1 b/man/mysql_fix_privilege_tables.1 new file mode 100644 index 00000000000..bf4e0e15dfa --- /dev/null +++ b/man/mysql_fix_privilege_tables.1 @@ -0,0 +1,23 @@ +.TH mysql 1 "17 March 2003" "MySQL 4.0" "MySQL database" +.SH NAME +mysql_fix_privilege_tables \- Fixes MySQL privilege tables. +.SH SYNOPSIS +mysql_fix_privilege_tables [options] +.SH DESCRIPTION +This scripts updates the mysql.user, mysql.db, mysql.host and the +mysql.func tables to MySQL 3.22.14 and above. + +This is needed if you want to use the new GRANT functions, +CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23 + +If you get 'Access denied' errors, you should run this script again +and give the MySQL root user password as an argument! + +For more information start the program with '--help'. +.SH "SEE ALSO" +mysql (1), mysqld (1) +.SH AUTHOR +This manpage was written by Christian Hammers . + +MySQL is available at http://www.mysql.com/. +.\" end of man page diff --git a/man/mysql_zap.1 b/man/mysql_zap.1 index 144fc212372..71931c03db6 100644 --- a/man/mysql_zap.1 +++ b/man/mysql_zap.1 @@ -1,4 +1,4 @@ -.TH zap 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH zap 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME zap - a perl script used to kill processes .SH USAGE diff --git a/man/mysqlaccess.1 b/man/mysqlaccess.1 index c1c61d4a8a7..fc7c185e050 100644 --- a/man/mysqlaccess.1 +++ b/man/mysqlaccess.1 @@ -1,4 +1,4 @@ -.TH mysqlaccess 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH mysqlaccess 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME .BR mysqlaccess \- Create new users to mysql. diff --git a/man/mysqladmin.1 b/man/mysqladmin.1 index 9d7d73aad21..693e8aa5a72 100644 --- a/man/mysqladmin.1 +++ b/man/mysqladmin.1 @@ -1,4 +1,4 @@ -.TH mysqladmin 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH mysqladmin 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME mysqladmin [OPTIONS] command command.... \- A utility for performing administrative operations .SH OPTION SYNOPSIS diff --git a/man/mysqld.1 b/man/mysqld.1 index 0a6fcccbef2..98247cd9445 100644 --- a/man/mysqld.1 +++ b/man/mysqld.1 @@ -1,4 +1,4 @@ -.TH mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH mysqld 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME .BR mysqld \- Starts the MySQL server demon diff --git a/man/mysqld_multi.1 b/man/mysqld_multi.1 index 68b9d1e876f..47418835939 100644 --- a/man/mysqld_multi.1 +++ b/man/mysqld_multi.1 @@ -1,4 +1,4 @@ -.TH mysqld_multi 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH mysqld_multi 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME mysqld_multi - is meant for managing several mysqld processes running in different UNIX sockets and TCP/IP ports. .SH USAGE diff --git a/man/mysqld_safe.1 b/man/mysqld_safe.1 index b8271c848cc..3679346d7db 100644 --- a/man/mysqld_safe.1 +++ b/man/mysqld_safe.1 @@ -1,4 +1,4 @@ -.TH safe_mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH safe_mysqld 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME mysqld_safe \- start the mysqld daemon on Unix. .SH SYNOPSIS diff --git a/man/mysqldump.1 b/man/mysqldump.1 index b4aba2ade13..af50366f24c 100644 --- a/man/mysqldump.1 +++ b/man/mysqldump.1 @@ -1,4 +1,4 @@ -.TH mysqldump 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH mysqldump 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME mysqldump \- text-based client for dumping or backing up mysql databases , tables and or data. diff --git a/man/mysqlshow.1 b/man/mysqlshow.1 index b6aceec82e3..39590b54375 100644 --- a/man/mysqlshow.1 +++ b/man/mysqlshow.1 @@ -1,4 +1,4 @@ -.TH mysqlshow 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH mysqlshow 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME .BR mysqlshow \- Shows the structure of a mysql database (databases,tables and columns) diff --git a/man/perror.1 b/man/perror.1 index 2c5dd9a295f..b8eec8af318 100644 --- a/man/perror.1 +++ b/man/perror.1 @@ -1,4 +1,4 @@ -.TH perror 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH perror 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME perror \- describes a system or MySQL error code. .SH SYNOPSIS diff --git a/man/replace.1 b/man/replace.1 index 7c3b79f605b..46d542d57f4 100644 --- a/man/replace.1 +++ b/man/replace.1 @@ -1,4 +1,4 @@ -.TH replace 1 "19 December 2000" "MySQL 3.23" "MySQL database" +.TH replace 1 "19 December 2000" "MySQL 4.0" "MySQL database" .SH NAME .TP replace - A utility program that is used by msql2mysql, but that has more general applicability as well. replace changes strings in place in files or on the standard input. Uses a finite state machine to match longer strings first. Can be used to swap strings. From 41d2103e260b751f398c7f254b08ce86ecbcd338 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Tue, 13 May 2003 20:07:43 +0300 Subject: [PATCH 167/188] Fixed 'Unknown error' when using 'UPDATE ... LIMIT'. Bug 373 --- mysql-test/r/update.result | 12 ++++++++++++ mysql-test/t/update.test | 17 +++++++++++++++++ sql/sql_update.cc | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 86647e845a9..5357e8367e3 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -138,3 +138,15 @@ a b 111 100 111 100 drop table t1; +CREATE TABLE t1 ( +`id_param` smallint(3) unsigned NOT NULL default '0', +`nom_option` char(40) NOT NULL default '', +`valid` tinyint(1) NOT NULL default '0', +KEY `id_param` (`id_param`,`nom_option`) +) TYPE=MyISAM; +INSERT INTO t1 (id_param,nom_option,valid) VALUES (185,'600x1200',1); +UPDATE t1 SET nom_option='test' WHERE id_param=185 AND nom_option='600x1200' AND valid=1 LIMIT 1; +select * from t1; +id_param nom_option valid +185 test 1 +drop table t1; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 359ae815197..6ac8543ec93 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -91,3 +91,20 @@ update t1 set b=100 where a=1 order by b desc limit 2; update t1 set a=a+10+b where a=1 order by b; select * from t1 order by a,b; drop table t1; + +# +# Test with limit (Bug #393) +# + +CREATE TABLE t1 ( + `id_param` smallint(3) unsigned NOT NULL default '0', + `nom_option` char(40) NOT NULL default '', + `valid` tinyint(1) NOT NULL default '0', + KEY `id_param` (`id_param`,`nom_option`) + ) TYPE=MyISAM; + +INSERT INTO t1 (id_param,nom_option,valid) VALUES (185,'600x1200',1); + +UPDATE t1 SET nom_option='test' WHERE id_param=185 AND nom_option='600x1200' AND valid=1 LIMIT 1; +select * from t1; +drop table t1; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index de953aa603b..ed4d6fd9b81 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -231,9 +231,13 @@ int mysql_update(THD *thd, break; /* purecov: inspected */ } if (!--limit && using_limit) + { + error= -1; break; + } } } + limit= tmp_limit; end_read_record(&info); /* Change select to use tempfile */ if (select) From 44026b18b4f64a15f15f612cab866154a2189fe2 Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Tue, 13 May 2003 19:16:30 +0200 Subject: [PATCH 168/188] Fix of bug 390: primary key now implies (silently) NOT NULL for key fields. --- mysql-test/r/create.result | 13 +++++++++---- mysql-test/r/key.result | 1 - mysql-test/t/create.test | 12 ++++++++++-- mysql-test/t/key.test | 4 ++-- sql/sql_table.cc | 5 +++-- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index a2ab0e97905..2e2aa41c671 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -25,13 +25,9 @@ create table t1 (a int not null auto_increment,primary key (a)) type=heap; The used table type doesn't support AUTO_INCREMENT columns create table t1 (a int not null,b text) type=heap; The used table type doesn't support BLOB/TEXT columns -create table t1 (a int ,primary key(a)) type=heap; -All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead drop table if exists t1; create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; The used table type doesn't support AUTO_INCREMENT columns -create table t1 (ordid int(8), primary key (ordid)); -All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead create table not_existing_database.test (a int); Got one of the listed errors create table `a/a` (a int); @@ -171,3 +167,12 @@ t1 CREATE TABLE `t1` ( ) TYPE=MyISAM SET SESSION table_type=default; drop table t1; +create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2)); +insert into t1 values ("a", 1), ("b", 2); +insert into t1 values ("c", NULL); +Column 'k2' cannot be null +insert into t1 values (NULL, 3); +Column 'k1' cannot be null +insert into t1 values (NULL, NULL); +Column 'k1' cannot be null +drop table t1; diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 1cd9c9dfe79..31d35a681aa 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -42,7 +42,6 @@ price area type transityes shopsyes schoolsyes petsyes drop table t1; CREATE TABLE t1 (program enum('signup','unique','sliding') not null, type enum('basic','sliding','signup'), sites set('mt'), PRIMARY KEY (program)); ALTER TABLE t1 modify program enum('signup','unique','sliding'); -All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead drop table t1; CREATE TABLE t1 ( name varchar(50) DEFAULT '' NOT NULL, diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 68d68929f07..86c3f6be0f5 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -24,11 +24,9 @@ drop table if exists t1,t2; !$1167 create table t1 (b char(0) not null, index(b)); !$1164 create table t1 (a int not null auto_increment,primary key (a)) type=heap; !$1163 create table t1 (a int not null,b text) type=heap; -!$1171 create table t1 (a int ,primary key(a)) type=heap; drop table if exists t1; !$1164 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; -!$1171 create table t1 (ordid int(8), primary key (ordid)); -- error 1044,1 create table not_existing_database.test (a int); @@ -119,3 +117,13 @@ show create table t1; SET SESSION table_type=default; drop table t1; + +# +# ISO requires that primary keys are implicitly NOT NULL +# +create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2)); +insert into t1 values ("a", 1), ("b", 2); +!$1048 insert into t1 values ("c", NULL); +!$1048 insert into t1 values (NULL, 3); +!$1048 insert into t1 values (NULL, NULL); +drop table t1; diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index 1996c793880..4c9b6479ac2 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -54,12 +54,12 @@ INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','Y','Y','Y','Y'); drop table t1; # -# problem med primary key +# No longer a problem with primary key # CREATE TABLE t1 (program enum('signup','unique','sliding') not null, type enum('basic','sliding','signup'), sites set('mt'), PRIMARY KEY (program)); # The following should give an error for wrong primary key -!$1171 ALTER TABLE t1 modify program enum('signup','unique','sliding'); +ALTER TABLE t1 modify program enum('signup','unique','sliding'); drop table t1; # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 745d9ea1084..90239c1c7ea 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -598,8 +598,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { if (key->type == Key::PRIMARY) { - my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0)); - DBUG_RETURN(-1); + /* Implicitly set primary key fields to NOT NULL for ISO conf. */ + sql_field->flags|= NOT_NULL_FLAG; + sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL; } if (!(file->table_flags() & HA_NULL_KEY)) { From 7229217f33396fc778320a58d14760c321336460 Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Tue, 13 May 2003 19:19:57 +0200 Subject: [PATCH 169/188] Forgot to correct comment in key.test (after fixing bug 390). --- mysql-test/t/key.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index 4c9b6479ac2..cb80d88aee8 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -58,7 +58,7 @@ drop table t1; # CREATE TABLE t1 (program enum('signup','unique','sliding') not null, type enum('basic','sliding','signup'), sites set('mt'), PRIMARY KEY (program)); -# The following should give an error for wrong primary key +# This no longer give an error for wrong primary key ALTER TABLE t1 modify program enum('signup','unique','sliding'); drop table t1; From a909b1b75d07ef1bb33d6fdfa6343630782f5c37 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 13 May 2003 19:30:07 +0200 Subject: [PATCH 170/188] - disabled all "EXPLAIN SELECT" tests from the InnoDB test because of nodeterministic results on some platforms --- mysql-test/r/innodb.result | 12 ------------ mysql-test/t/innodb.test | 8 ++++---- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index b3c7c137a6f..e2dea324ff2 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -138,15 +138,6 @@ id parent_id level 1008 102 2 1010 102 2 1015 102 2 -explain select level from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 12 Using where; Using index -explain select level,id from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 12 Using where; Using index -explain select level,id,parent_id from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 12 Using where select level,id from t1 where level=1; level id 1 1002 @@ -595,9 +586,6 @@ id parent_id level 1009 102 2 1025 102 2 1016 102 2 -explain select level from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 6 Using where; Using index select level,id from t1 where level=1; level id 1 1004 diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index ae1f7dae922..dc3c76f1a91 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -40,9 +40,9 @@ update ignore t1 set id=id+1; # This will change all rows select * from t1; update ignore t1 set id=1023 where id=1010; select * from t1 where parent_id=102; -explain select level from t1 where level=1; -explain select level,id from t1 where level=1; -explain select level,id,parent_id from t1 where level=1; +# explain select level from t1 where level=1; +# explain select level,id from t1 where level=1; +# explain select level,id,parent_id from t1 where level=1; select level,id from t1 where level=1; select level,id,parent_id from t1 where level=1; optimize table t1; @@ -339,7 +339,7 @@ update ignore t1 set id=id+1; # This will change all rows select * from t1; update ignore t1 set id=1023 where id=1010; select * from t1 where parent_id=102; -explain select level from t1 where level=1; +# explain select level from t1 where level=1; select level,id from t1 where level=1; select level,id,parent_id from t1 where level=1; select level,id from t1 where level=1 order by id; From 447bebfd770377e6a592ee4f837e482d43922661 Mon Sep 17 00:00:00 2001 From: "jani@hynda.(none)" <> Date: Tue, 13 May 2003 22:28:34 +0300 Subject: [PATCH 171/188] Fixed a bug in DROP DATABASE when database had a RAID type table. Bug ID 381. --- mysql-test/r/raid.result | 3 +++ mysql-test/t/raid.test | 3 +++ sql/mysqld.cc | 6 ++---- sql/set_var.cc | 2 +- sql/sql_db.cc | 21 ++++++++++++++++++--- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/raid.result b/mysql-test/r/raid.result index 41af50851e9..fd47a9451f6 100644 --- a/mysql-test/r/raid.result +++ b/mysql-test/r/raid.result @@ -1,3 +1,6 @@ +create database test_raid; +create table test_raid.r1 (i int) raid_type=1; +drop database test_raid; DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 ( id int unsigned not null auto_increment primary key, diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test index 8b608c1069f..4dbaf84a836 100644 --- a/mysql-test/t/raid.test +++ b/mysql-test/t/raid.test @@ -5,6 +5,9 @@ show variables like "have_raid"; # Test of raided tables # +create database test_raid; +create table test_raid.r1 (i int) raid_type=1; +drop database test_raid; DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 ( id int unsigned not null auto_increment primary key, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 731298266dc..0211c471ed7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4722,11 +4722,9 @@ static void get_options(int argc,char **argv) my_disable_locking= myisam_single_user= test(opt_external_locking == 0); my_default_record_cache_size=global_system_variables.read_buff_size; myisam_max_temp_length= - (my_off_t) min(global_system_variables.myisam_max_sort_file_size, - (ulonglong) MAX_FILE_SIZE); + (my_off_t) global_system_variables.myisam_max_sort_file_size; myisam_max_extra_temp_length= - (my_off_t) min(global_system_variables.myisam_max_extra_sort_file_size, - (ulonglong) MAX_FILE_SIZE); + (my_off_t) global_system_variables.myisam_max_extra_sort_file_size; /* Set global variables based on startup options */ myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size); diff --git a/sql/set_var.cc b/sql/set_var.cc index 12ce37c5bc8..a45a923ef90 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -592,7 +592,7 @@ static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type) { myisam_max_extra_temp_length= - (my_off_t) global_system_variables.myisam_max_sort_file_size; + (my_off_t) global_system_variables.myisam_max_extra_sort_file_size; } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 7e58b5d4582..6251b1ec624 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -211,6 +211,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, ulong found_other_files=0; char filePath[FN_REFLEN]; TABLE_LIST *tot_list=0, **tot_list_next; + List raid_dirs; + DBUG_ENTER("mysql_rm_known_files"); DBUG_PRINT("enter",("path: %s", org_path)); @@ -229,6 +231,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, { char newpath[FN_REFLEN]; MY_DIR *new_dirp; + String *dir; + strxmov(newpath,org_path,"/",file->name,NullS); unpack_filename(newpath,newpath); if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT)))) @@ -239,7 +243,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, my_dirend(dirp); DBUG_RETURN(-1); } + raid_dirs.push_back(dir=new String(newpath)); + dir->copy(); + continue; } + found_other_files++; continue; } if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0) @@ -278,12 +286,19 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, deleted++; } } - my_dirend(dirp); - if (thd->killed || (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 1))) + { + my_dirend(dirp); DBUG_RETURN(-1); - + } + List_iterator it(raid_dirs); + String *dir; + while ((dir= it++)) + if (rmdir(dir->c_ptr()) < 0) + found_other_files++; + my_dirend(dirp); + /* If the directory is a symbolic link, remove the link first, then remove the directory the symbolic link pointed at From 05c8973671b6d90acf62a29deda12ad2d87c20ba Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 13 May 2003 23:03:00 +0200 Subject: [PATCH 172/188] Fix for bug 343 : we require only REPLICATION CLIENT for SHOW SLAVE STATUS and SHOW MASTER STATUS, because this is what the manual states. We still accept SUPER. --- 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 73983bc03b1..fc30bb45ea6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1475,7 +1475,9 @@ mysql_execute_command(void) } case SQLCOM_SHOW_SLAVE_STAT: { - if (check_global_access(thd, SUPER_ACL)) + /* Accept two privileges */ + if (check_global_access(thd, SUPER_ACL) && + check_global_access(thd, REPL_CLIENT_ACL)) goto error; LOCK_ACTIVE_MI; res = show_master_info(thd,active_mi); @@ -1484,7 +1486,9 @@ mysql_execute_command(void) } case SQLCOM_SHOW_MASTER_STAT: { - if (check_global_access(thd, SUPER_ACL)) + /* Accept two privileges */ + if (check_global_access(thd, SUPER_ACL) && + check_global_access(thd, REPL_CLIENT_ACL)) goto error; res = show_binlog_info(thd); break; From 3e72b423e39702fddca1f345d61069fe9b1343e3 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 14 May 2003 01:27:26 +0300 Subject: [PATCH 173/188] Fix for MacOSX and symlinks Fix for USE_FRM and crashed index file --- configure.in | 10 +- myisam/mi_open.c | 7 +- mysql-test/r/repair.result | 3 +- mysql-test/r/repair_part2.result | 8 ++ mysql-test/r/update.result | 16 ++++ mysql-test/t/repair.test | 4 + mysql-test/t/repair_part2-master.sh | 1 + mysql-test/t/repair_part2.test | 7 ++ mysql-test/t/update.test | 15 +++ sql/handler.cc | 10 +- sql/sql_table.cc | 142 +++++++++++++++------------- 11 files changed, 149 insertions(+), 74 deletions(-) create mode 100644 mysql-test/r/repair_part2.result create mode 100644 mysql-test/t/repair_part2-master.sh create mode 100644 mysql-test/t/repair_part2.test diff --git a/configure.in b/configure.in index a1ea566435b..3b00f5343ce 100644 --- a/configure.in +++ b/configure.in @@ -1007,8 +1007,9 @@ case $SYSTEM_TYPE in *darwin5*) if test "$ac_cv_prog_gcc" = "yes" then - CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" - CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE" + FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" + CFLAGS="$CFLAGS $FLAGS" + CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" with_named_curses="" fi @@ -1016,8 +1017,9 @@ case $SYSTEM_TYPE in *darwin6*) if test "$ac_cv_prog_gcc" = "yes" then - CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" - CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE" + FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" + CFLAGS="$CFLAGS $FLAGS" + CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" fi ;; diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 0ccc8a3bf40..99b97db3fbd 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -114,8 +114,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) errpos=1; if (my_read(kfile,(char*) share->state.header.file_version,head_length, MYF(MY_NABP))) + { + my_errno= HA_ERR_NOT_A_TABLE; goto err; - + } if (memcmp((byte*) share->state.header.file_version, (byte*) myisam_file_magic, 4)) { @@ -165,7 +167,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) } errpos=3; if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP))) + { + my_errno=HA_ERR_CRASHED; goto err; + } len=mi_uint2korr(share->state.header.state_info_length); keys= (uint) share->state.header.keys; uniques= (uint) share->state.header.uniques; diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index ad869787b8a..6c2107b2cf3 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -11,4 +11,5 @@ test.t1 repair error The handler for the table doesn't support repair drop table t1; repair table t1 use_frm; Table Op Msg_type Msg_text -t1 repair error table is read-only or does not exists +test.t1 repair error Table 'test.t1' doesn't exist +create table t1 type=myisam SELECT 1,"table 1"; diff --git a/mysql-test/r/repair_part2.result b/mysql-test/r/repair_part2.result new file mode 100644 index 00000000000..77aa98c3da9 --- /dev/null +++ b/mysql-test/r/repair_part2.result @@ -0,0 +1,8 @@ +repair table t1; +Table Op Msg_type Msg_text +test.t1 repair error Can't open file: 't1.MYI'. (errno: 130) +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 1 +test.t1 repair status OK +drop table t1; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 5357e8367e3..11aff8fe50a 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -150,3 +150,19 @@ select * from t1; id_param nom_option valid 185 test 1 drop table t1; +create table t1 (F1 VARCHAR(30), F2 VARCHAR(30), F3 VARCHAR(30), cnt int, groupid int, KEY groupid_index (groupid)); +insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6), +('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2), +('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4), +('2','2','0',1,7); +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; +F1 F2 F3 cnt groupid +0 0 0 1 6 +0 1 2 1 5 +0 2 0 1 3 +1 0 1 1 2 +1 2 1 1 1 +2 0 1 2 4 +2 2 0 1 7 +drop table t1; diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index e7da79d8c9e..159fc090653 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -12,4 +12,8 @@ drop table t1; # non-existent table repair table t1 use_frm; +# +# Create test table for repair2 +# The following must be last in this file +create table t1 type=myisam SELECT 1,"table 1"; diff --git a/mysql-test/t/repair_part2-master.sh b/mysql-test/t/repair_part2-master.sh new file mode 100644 index 00000000000..964bde06c18 --- /dev/null +++ b/mysql-test/t/repair_part2-master.sh @@ -0,0 +1 @@ +echo "1" > $MYSQL_TEST_DIR/var/master-data/test/t1.MYI diff --git a/mysql-test/t/repair_part2.test b/mysql-test/t/repair_part2.test new file mode 100644 index 00000000000..8c27e382dff --- /dev/null +++ b/mysql-test/t/repair_part2.test @@ -0,0 +1,7 @@ +# +# This test starts with a crashed t1.MYI file left over from repair.test +# + +repair table t1; +repair table t1 use_frm; +drop table t1; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 6ac8543ec93..a455b308158 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -108,3 +108,18 @@ INSERT INTO t1 (id_param,nom_option,valid) VALUES (185,'600x1200',1); UPDATE t1 SET nom_option='test' WHERE id_param=185 AND nom_option='600x1200' AND valid=1 LIMIT 1; select * from t1; drop table t1; + +# +# Multi table update test from bugs +# + +create table t1 (F1 VARCHAR(30), F2 VARCHAR(30), F3 VARCHAR(30), cnt int, groupid int, KEY groupid_index (groupid)); + +insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6), +('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2), +('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4), +('2','2','0',1,7); + +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; diff --git a/sql/handler.cc b/sql/handler.cc index ba7799fef4a..45c83355c94 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -830,7 +830,8 @@ void handler::print_error(int error, myf errflag) DBUG_VOID_RETURN; } - /* Return key if error because of duplicated keys */ + +/* Return key if error because of duplicated keys */ uint handler::get_dup_key(int error) { @@ -841,6 +842,7 @@ uint handler::get_dup_key(int error) DBUG_RETURN(table->file->errkey); } + int handler::delete_table(const char *name) { int error=0; @@ -867,9 +869,10 @@ int handler::rename_table(const char * from, const char * to) DBUG_RETURN(0); } -/* Tell the handler to turn on or off logging to the handler's - recovery log +/* + Tell the handler to turn on or off logging to the handler's recovery log */ + int ha_recovery_logging(THD *thd, bool on) { int error=0; @@ -914,7 +917,6 @@ int handler::delete_all_rows() int ha_create_table(const char *name, HA_CREATE_INFO *create_info, bool update_create_info) - { int error; TABLE table; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 90239c1c7ea..07ec1d67538 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -946,6 +946,7 @@ static void safe_remove_from_cache(THD *thd,TABLE *table) DBUG_VOID_RETURN; } + bool close_cached_table(THD *thd,TABLE *table) { DBUG_ENTER("close_cached_table"); @@ -957,7 +958,8 @@ bool close_cached_table(THD *thd,TABLE *table) /* Close lock if this is not got with LOCK TABLES */ if (thd->lock) { - mysql_unlock_tables(thd, thd->lock); thd->lock=0; // Start locked threads + mysql_unlock_tables(thd, thd->lock); + thd->lock=0; // Start locked threads } /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ thd->open_tables=unlink_open_table(thd,thd->open_tables,table); @@ -1045,93 +1047,105 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, } -static int prepare_for_repair(THD* thd, TABLE_LIST* table, +static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, HA_CHECK_OPT *check_opt) { + int error= 0; + TABLE tmp_table, *table; DBUG_ENTER("prepare_for_repair"); - if (!table->table) - { - DBUG_RETURN(send_check_errmsg(thd, table, "repair", "table is read-only or does not exists")); - } - if (!(check_opt->sql_flags & TT_USEFRM)) - { DBUG_RETURN(0); - } - else + + if (!(table= table_list->table)) /* if open_ltable failed */ { - /* - User gave us USE_FRM which means that the header in the index file is - trashed. - In this case we will try to fix the table the following way: - - Rename the data file to a temporary name - - Truncate the table - - Replace the new data file with the old one - - Run a normal repair using the new index file and the old data file - */ + char name[FN_REFLEN]; + strxmov(name, mysql_data_home, "/", table_list->db, "/", + table_list->real_name, NullS); + if (openfrm(name, "", 0, 0, 0, &tmp_table)) + DBUG_RETURN(0); // Can't open frm file + table= &tmp_table; + } - char from[FN_REFLEN],tmp[FN_REFLEN+32]; - const char **ext= table->table->file->bas_ext(); - MY_STAT stat_info; + /* + User gave us USE_FRM which means that the header in the index file is + trashed. + In this case we will try to fix the table the following way: + - Rename the data file to a temporary name + - Truncate the table + - Replace the new data file with the old one + - Run a normal repair using the new index file and the old data file + */ - /* - Check if this is a table type that stores index and data separately, - like ISAM or MyISAM - */ - if (!ext[0] || !ext[1]) - DBUG_RETURN(0); // No data file + char from[FN_REFLEN],tmp[FN_REFLEN+32]; + const char **ext= table->file->bas_ext(); + MY_STAT stat_info; - strxmov(from, table->table->path, ext[1], NullS); // Name of data file - if (!my_stat(from, &stat_info, MYF(0))) - DBUG_RETURN(0); // Can't use USE_FRM flag + /* + Check if this is a table type that stores index and data separately, + like ISAM or MyISAM + */ + if (!ext[0] || !ext[1]) + goto end; // No data file - sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); + strxmov(from, table->path, ext[1], NullS); // Name of data file + if (!my_stat(from, &stat_info, MYF(0))) + goto end; // Can't use USE_FRM flag + sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); + + pthread_mutex_lock(&LOCK_open); + close_cached_table(thd,table_list->table); + pthread_mutex_unlock(&LOCK_open); + + if (lock_and_wait_for_table_name(thd,table_list)) + { + error= -1; + goto end; + } + if (my_rename(from, tmp, MYF(MY_WME))) + { pthread_mutex_lock(&LOCK_open); - close_cached_table(thd,table->table); + unlock_table_name(thd, table_list); pthread_mutex_unlock(&LOCK_open); - - if (lock_and_wait_for_table_name(thd,table)) - DBUG_RETURN(-1); - - if (my_rename(from, tmp, MYF(MY_WME))) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed renaming data file")); - } - if (mysql_truncate(thd, table, 1)) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed generating table from .frm file")); - } - if (my_rename(tmp, from, MYF(MY_WME))) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed restoring .MYD file")); - } + error= send_check_errmsg(thd, table_list, "repair", + "Failed renaming data file"); + goto end; + } + if (mysql_truncate(thd, table_list, 1)) + { + pthread_mutex_lock(&LOCK_open); + unlock_table_name(thd, table_list); + pthread_mutex_unlock(&LOCK_open); + error= send_check_errmsg(thd, table_list, "repair", + "Failed generating table from .frm file"); + goto end; + } + if (my_rename(tmp, from, MYF(MY_WME))) + { + pthread_mutex_lock(&LOCK_open); + unlock_table_name(thd, table_list); + pthread_mutex_unlock(&LOCK_open); + error= send_check_errmsg(thd, table_list, "repair", + "Failed restoring .MYD file"); + goto end; } /* Now we should be able to open the partially repaired table to finish the repair in the handler later on. */ - if (!(table->table = reopen_name_locked_table(thd, table))) + if (!(table_list->table = reopen_name_locked_table(thd, table_list))) { pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); + unlock_table_name(thd, table_list); pthread_mutex_unlock(&LOCK_open); } - DBUG_RETURN(0); + +end: + if (table == &tmp_table) + closefrm(table); // Free allocated memory + DBUG_RETURN(error); } From d8a6c1ca227780be09300b12c9e9b24def26fafb Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 14 May 2003 01:55:23 +0300 Subject: [PATCH 174/188] Fix for checking global_access rights --- sql/sql_parse.cc | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 002af61fae6..ad2f7f9a8bd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1482,9 +1482,8 @@ mysql_execute_command(void) } case SQLCOM_SHOW_SLAVE_STAT: { - /* Accept two privileges */ - if (check_global_access(thd, SUPER_ACL) && - check_global_access(thd, REPL_CLIENT_ACL)) + /* Accept one of two privileges */ + if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) goto error; LOCK_ACTIVE_MI; res = show_master_info(thd,active_mi); @@ -1493,9 +1492,8 @@ mysql_execute_command(void) } case SQLCOM_SHOW_MASTER_STAT: { - /* Accept two privileges */ - if (check_global_access(thd, SUPER_ACL) && - check_global_access(thd, REPL_CLIENT_ACL)) + /* Accept one of two privileges */ + if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) goto error; res = show_binlog_info(thd); break; @@ -2620,12 +2618,29 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, } -/* check for global access and give descriptive error message if it fails */ +/* + check for global access and give descriptive error message if it fails + + SYNOPSIS + check_global_access() + thd Thread handler + want_access Use should have any of these global rights + + WARNING + One gets access rigth if one has ANY of the rights in want_access + This is useful as one in most cases only need one global right, + but in some case we want to check if the user has SUPER or + REPL_CLIENT_ACL rights. + + RETURN + 0 ok + 1 Access denied. In this case an error is sent to the client +*/ bool check_global_access(THD *thd, ulong want_access) { char command[128]; - if ((thd->master_access & want_access) == want_access) + if ((thd->master_access & want_access)) return 0; get_privilege_desc(command, sizeof(command), want_access); net_printf(&thd->net,ER_SPECIFIC_ACCESS_DENIED_ERROR, From 413bb98b5c9c999b064c67f983f58e9697b76ba5 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 14 May 2003 09:37:04 +0300 Subject: [PATCH 175/188] SHOW TABLE STATUS displayed wrong Row_format for myisampack'ed tables. (Bug #427) --- sql/sql_show.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 585c30110b3..dc81510051b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -324,10 +324,11 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK); net_store_data(packet, file->table_type()); net_store_data(packet, - (table->db_options_in_use & HA_OPTION_PACK_RECORD) ? - "Dynamic" : (table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) - ? "Compressed" : "Fixed"); + ? "Compressed" : + (table->db_options_in_use & HA_OPTION_PACK_RECORD) ? + "Dynamic" : "Fixed"); + net_store_data(packet, (longlong) file->records); net_store_data(packet, (uint32) file->mean_rec_length); net_store_data(packet, (longlong) file->data_file_length); From 75e49549a57d35a2b9c5a39fc81dc92442f64613 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 14 May 2003 19:00:17 +0300 Subject: [PATCH 176/188] os0sync.c: We had forgotten to call pthread_mutex_destroy when we free an OS mutex in Unix --- innobase/os/os0sync.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index a9127e6310a..83b2961c3ca 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -495,10 +495,7 @@ os_fast_mutex_free( ut_a(fast_mutex); DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); -#elif defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) - pthread_mutex_destroy(fast_mutex); #else - UT_NOT_USED(fast_mutex); - + pthread_mutex_destroy(fast_mutex); #endif } From 8c9a12d472b505cc11de986bbda1839b759b596f Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 14 May 2003 19:09:05 +0300 Subject: [PATCH 177/188] os0sync.c: Backport from 4.0: We had forgotten to call pthread_mutex_destroy when we free an OS mutex in Unix --- innobase/os/os0sync.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 14677ede20f..e212b115806 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -488,7 +488,6 @@ os_fast_mutex_free( DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else - UT_NOT_USED(fast_mutex); - + pthread_mutex_destroy(fast_mutex); #endif } From cef5df827a80e8fc7d38608e20f96780fb699698 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 14 May 2003 20:17:01 +0300 Subject: [PATCH 178/188] os0sync.c: Check that pthread_mutex_init and pthread_mutex_destroy return 0 --- innobase/os/os0sync.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 83b2961c3ca..c460416fa64 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -446,9 +446,9 @@ os_fast_mutex_init( InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) - pthread_mutex_init(fast_mutex, pthread_mutexattr_default); + ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default)); #else - pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST); + ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); #endif #endif } @@ -496,6 +496,6 @@ os_fast_mutex_free( DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else - pthread_mutex_destroy(fast_mutex); + ut_a(0 == pthread_mutex_destroy(fast_mutex)); #endif } From 53b7eaf9ca56240af74c4be8e763a57f0e74d47f Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 14 May 2003 20:22:55 +0300 Subject: [PATCH 179/188] os0sync.c: Check return value of pthread_cond_... --- innobase/os/os0sync.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index c460416fa64..407b280f805 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -68,9 +68,10 @@ os_event_create( os_fast_mutex_init(&(event->os_mutex)); #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) - pthread_cond_init(&(event->cond_var), pthread_condattr_default); + ut_a(0 == pthread_cond_init(&(event->cond_var), + pthread_condattr_default)); #else - pthread_cond_init(&(event->cond_var), NULL); + ut_a(0 == pthread_cond_init(&(event->cond_var), NULL)); #endif event->is_set = FALSE; @@ -130,7 +131,7 @@ os_event_set( /* Do nothing */ } else { event->is_set = TRUE; - pthread_cond_broadcast(&(event->cond_var)); + ut_a(0 == pthread_cond_broadcast(&(event->cond_var))); } os_fast_mutex_unlock(&(event->os_mutex)); @@ -182,7 +183,7 @@ os_event_free( ut_a(event); os_fast_mutex_free(&(event->os_mutex)); - pthread_cond_destroy(&(event->cond_var)); + ut_a(0 == pthread_cond_destroy(&(event->cond_var))); ut_free(event); #endif From cf99d899084c47d248d42cb38be522321a9806e1 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 14 May 2003 22:08:30 +0300 Subject: [PATCH 180/188] Portability fixes OpenUnix 8 & UnixWare 7.1.x --- acinclude.m4 | 3 ++- configure.in | 8 ++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 83cc01cc127..e0b28874892 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1165,7 +1165,8 @@ m4_define([_AC_PROG_CXX_EXIT_DECLARATION], 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ - 'void exit (int);' + 'void exit (int);' \ + '#include ' do _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include $ac_declaration], diff --git a/configure.in b/configure.in index cc6f3a79b69..5b690c3af78 100644 --- a/configure.in +++ b/configure.in @@ -1170,10 +1170,8 @@ then with_named_thread="-Kthread -lsocket -lnsl" if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null then -# AC_DEFINE(HAVE_OpenUNIX8_THREADS) AC_DEFINE(HAVE_UNIXWARE7_THREADS) else -# AC_DEFINE(HAVE_OpenUNIX8_POSIX) AC_DEFINE(HAVE_UNIXWARE7_POSIX) fi # We must have cc @@ -1182,10 +1180,8 @@ then then { echo "configure: error: On OpenUNIX8 and UnixWare7 MySQL must be compiled with cc. See the Installation chapter in the Reference Manual." 1>&2; exit 1; }; else -# CC="$CC -Kthread -DOpenUNIX8"; -# CXX="$CXX -Kthread -DOpenUNIX8"; - CC="$CC -Kthread -DUNIXWARE_7"; - CXX="$CXX -Kthread -DUNIXWARE_7"; + CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; fi AC_MSG_RESULT("yes") else From dcb7b452bd3b00300f3f53f1a59b65f1f0418a17 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 14 May 2003 22:12:55 +0300 Subject: [PATCH 181/188] Fixed bug in CREATE ... DECIMAL(-1,1). Bug #432 --- mysql-test/mysql-test-run.sh | 3 ++- mysql-test/r/type_decimal.result | 6 ++++++ mysql-test/t/type_decimal.test | 10 ++++++++++ sql/sql_parse.cc | 16 +++++++++------- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 40726b776e8..7ce6ffe14af 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -114,6 +114,7 @@ if test $? != 0; then exit 1; fi TR=tr XARGS=`which xargs` if test $? != 0; then exit 1; fi +SORT=sort # Are we using a source or a binary distribution? @@ -1363,7 +1364,7 @@ then if [ x$RECORD = x1 ]; then $ECHO "Will not run in record mode without a specific test case." else - for tf in $TESTDIR/*.$TESTSUFFIX + for tf in `ls -1 $TESTDIR/*.$TESTSUFFIX | $SORT` do run_testcase $tf done diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index 4c326957c03..b74765696a2 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -357,3 +357,9 @@ select * from t1; a 99999999999 drop table t1; +CREATE TABLE t1 (a_dec DECIMAL(-1,0)); +Too big column length for column 'a_dec' (max = 255). Use BLOB instead +CREATE TABLE t1 (a_dec DECIMAL(-2,1)); +Too big column length for column 'a_dec' (max = 255). Use BLOB instead +CREATE TABLE t1 (a_dec DECIMAL(-1,1)); +Too big column length for column 'a_dec' (max = 255). Use BLOB instead diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index 7d5d719592c..7aedc051905 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -230,3 +230,13 @@ insert into t1 values("1e4294967297"); select * from t1; drop table t1; +# +# Test of wrong decimal type +# + +--error 1074 +CREATE TABLE t1 (a_dec DECIMAL(-1,0)); +--error 1074 +CREATE TABLE t1 (a_dec DECIMAL(-2,1)); +--error 1074 +CREATE TABLE t1 (a_dec DECIMAL(-1,1)); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ad2f7f9a8bd..e69d260bf11 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2977,9 +2977,8 @@ bool add_field_to_list(char *field_name, enum_field_types type, new_field->change=change; new_field->interval=0; new_field->pack_length=0; - if (length) - if (!(new_field->length= (uint) atoi(length))) - length=0; /* purecov: inspected */ + if (length && !(new_field->length= (uint) atoi(length))) + length=0; /* purecov: inspected */ uint sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1; if (new_field->length && new_field->decimals && @@ -3015,10 +3014,13 @@ bool add_field_to_list(char *field_name, enum_field_types type, break; case FIELD_TYPE_DECIMAL: if (!length) - new_field->length = 10; // Default length for DECIMAL - new_field->length+=sign_len; - if (new_field->decimals) - new_field->length++; + new_field->length= 10; // Default length for DECIMAL + if (new_field->length < MAX_FIELD_WIDTH) // Skip wrong argument + { + new_field->length+=sign_len; + if (new_field->decimals) + new_field->length++; + } break; case FIELD_TYPE_BLOB: case FIELD_TYPE_TINY_BLOB: From a46c0a7cace4075c8f77a54bdf8d7f02373a1ea2 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Wed, 14 May 2003 23:06:06 +0300 Subject: [PATCH 182/188] Portability fix for 64 bit machines --- mysql-test/r/variables.result | 2 +- mysql-test/t/variables.test | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 8a6791004ee..7c054f55acd 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -115,7 +115,7 @@ myisam_max_sort_file_size 1048576 set GLOBAL myisam_max_sort_file_size=default; show variables like 'myisam_max_sort_file_size'; Variable_name Value -myisam_max_sort_file_size 2147483647 +myisam_max_sort_file_size FILE_SIZE set global net_retry_count=10, session net_retry_count=10; set global net_buffer_length=1024, net_write_timeout=200, net_read_timeout=300; set session net_buffer_length=2048, net_write_timeout=500, net_read_timeout=600; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index c730f317fcb..fa39906fd6a 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -72,6 +72,7 @@ set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; set GLOBAL myisam_max_sort_file_size=default; +--replace_result 2147483647 FILE_SIZE 9223372036854775807 FILE_SIZE show variables like 'myisam_max_sort_file_size'; set global net_retry_count=10, session net_retry_count=10; From eb3ba82ec64fb46c2acf9c66200638b5c4900588 Mon Sep 17 00:00:00 2001 From: "mysqldev@build.mysql2.com" <> Date: Fri, 16 May 2003 13:03:47 +0200 Subject: [PATCH 183/188] my_global.h: - QNX 6.2.1 actually defines HAVE_RINT - fixed rint(A) #define as it was causing compile errors on QNX --- BitKeeper/etc/logging_ok | 1 + include/my_global.h | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 8074f38541a..c0e329b1c8d 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -62,6 +62,7 @@ monty@work.mysql.com mwagner@cash.mwagner.org mwagner@evoq.mwagner.org mwagner@work.mysql.com +mysqldev@build.mysql2.com nick@mysql.com nick@nick.leippe.com paul@central.snake.net diff --git a/include/my_global.h b/include/my_global.h index 31375de30da..15495c60dd7 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -291,7 +291,6 @@ C_MODE_END #define HAVE_ERRNO_AS_DEFINE #define HAVE_FCNTL_LOCK #undef HAVE_FINITE -#undef HAVE_RINT #undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */ #undef LONGLONG_MAX /* standard system library 'limits.h' */ #endif @@ -360,7 +359,7 @@ typedef unsigned short ushort; #define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1)) #define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) #ifndef HAVE_RINT -#define rint(A) floor((A)+((A) < 0) -0.5 : 0.5) +#define rint(A) floor((A)+(((A) < 0)? -0.5 : 0.5)) #endif /* Define some general constants */ From cf79c47597956f98781dffe0a2137ce6778c86f3 Mon Sep 17 00:00:00 2001 From: "mysqldev@build.mysql2.com" <> Date: Fri, 16 May 2003 13:36:13 +0200 Subject: [PATCH 184/188] - re-enabled RAID support for the Max subpackage again --- support-files/mysql.spec.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 9f8b29ab697..aab3e298e14 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -146,7 +146,7 @@ languages and applications need to dynamically load and use MySQL. %package Max Release: %{release} -Summary: MySQL - server with Berkeley BD and UDF support +Summary: MySQL - server with Berkeley BD, RAID and UDF support Group: Applications/Databases Provides: mysql-Max Obsoletes: mysql-Max @@ -154,7 +154,7 @@ Requires: MySQL >= 4.0 %description Max Optional MySQL server binary that supports additional features like -Berkeley DB and User Defined Functions (UDFs). +Berkeley DB, RAID and User Defined Functions (UDFs). To activate this binary, just install this package in addition to the standard MySQL package. @@ -257,6 +257,7 @@ export PATH BuildMySQL "--enable-shared \ --with-berkeley-db \ --with-innodb \ + --with-raid \ --with-server-suffix='-Max'" # Save everything for debug @@ -534,6 +535,9 @@ fi %attr(644, root, root) /usr/lib/mysql/libmysqld.a %changelog +* Fri May 16 2003 Lenz Grimmer + +- re-enabled RAID again * Wed Apr 30 2003 Lenz Grimmer From 5359d046083ddf0318c725780b61baa1a1aaed62 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 16 May 2003 16:27:50 +0300 Subject: [PATCH 185/188] buf0lru.c, buf0flu.c, buf0buf.c, buf0lru.h: Search first only 10 % of the LRU list for a replaceable block before doing an LRU flush; enable again flushing of close pages also in a flush list (checkpointing) flush trx0trx.c: Add forgotten return value (it was not used anywhere, fortunately) ha_innodb.h, mysql_priv.h: Move declaration of srv_buf_pool_max_modified_pct to ha_innodb.h and enclose it to denote it is a C variable, not C++ --- innobase/buf/buf0buf.c | 8 ++++--- innobase/buf/buf0flu.c | 36 ++++++++++++++++------------ innobase/buf/buf0lru.c | 49 +++++++++++++++++++++++++++----------- innobase/include/buf0lru.h | 25 ++++++++++--------- innobase/trx/trx0trx.c | 2 ++ sql/ha_innodb.h | 3 +++ sql/mysql_priv.h | 4 ---- 7 files changed, 80 insertions(+), 47 deletions(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 944a5ef60d0..c793c11f29e 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1613,7 +1613,7 @@ buf_pool_invalidate(void) freed = TRUE; while (freed) { - freed = buf_LRU_search_and_free_block(0); + freed = buf_LRU_search_and_free_block(100); } mutex_enter(&(buf_pool->mutex)); @@ -1898,8 +1898,10 @@ buf_print_io( buf += sprintf(buf, "Pending writes: LRU %lu, flush list %lu, single page %lu\n", - buf_pool->n_flush[BUF_FLUSH_LRU], - buf_pool->n_flush[BUF_FLUSH_LIST], + buf_pool->n_flush[BUF_FLUSH_LRU] + + buf_pool->init_flush[BUF_FLUSH_LRU], + buf_pool->n_flush[BUF_FLUSH_LIST] + + buf_pool->init_flush[BUF_FLUSH_LIST], buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); current_time = time(NULL); diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index d732bf40b57..735966c28c5 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -573,15 +573,7 @@ buf_flush_try_neighbors( low = offset; high = offset + 1; - } else if (flush_type == BUF_FLUSH_LIST) { - /* Since semaphore waits require us to flush the - doublewrite buffer to disk, it is best that the - search area is just the page itself, to minimize - chances for semaphore waits */ - - low = offset; - high = offset + 1; - } + } /* printf("Flush area: low %lu high %lu\n", low, high); */ @@ -598,13 +590,20 @@ buf_flush_try_neighbors( if (block && flush_type == BUF_FLUSH_LRU && i != offset && !block->old) { - /* We avoid flushing 'non-old' blocks in an LRU flush, - because the flushed blocks are soon freed */ + /* We avoid flushing 'non-old' blocks in an LRU flush, + because the flushed blocks are soon freed */ - continue; + continue; } - if (block && buf_flush_ready_for_flush(block, flush_type)) { + if (block && buf_flush_ready_for_flush(block, flush_type) + && (i == offset || block->buf_fix_count == 0)) { + /* We only try to flush those neighbors != offset + where the buf fix count is zero, as we then know that + we probably can latch the page without a semaphore + wait. Semaphore waits are expensive because we must + flush the doublewrite buffer before we start + waiting. */ mutex_exit(&(buf_pool->mutex)); @@ -723,7 +722,6 @@ buf_flush_batch( page_count += buf_flush_try_neighbors(space, offset, flush_type); - /* printf( "Flush type %lu, page no %lu, neighb %lu\n", flush_type, offset, @@ -849,11 +847,19 @@ buf_flush_free_margin(void) /*=======================*/ { ulint n_to_flush; + ulint n_flushed; n_to_flush = buf_flush_LRU_recommendation(); if (n_to_flush > 0) { - buf_flush_batch(BUF_FLUSH_LRU, n_to_flush, ut_dulint_zero); + n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush, + ut_dulint_zero); + if (n_flushed == ULINT_UNDEFINED) { + /* There was an LRU type flush batch already running; + let us wait for it to end */ + + buf_flush_wait_batch_end(BUF_FLUSH_LRU); + } } } diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 735a32cf067..eeccbf7728a 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -104,12 +104,15 @@ ibool buf_LRU_search_and_free_block( /*==========================*/ /* out: TRUE if freed */ - ulint n_iterations __attribute__((unused))) /* in: how many times - this has been called repeatedly without - result: a high value means that we should - search farther */ + ulint n_iterations) /* in: how many times this has been called + repeatedly without result: a high value means + that we should search farther; if value is + k < 10, then we only search k/10 * [number + of pages in the buffer pool] from the end + of the LRU list */ { buf_block_t* block; + ulint distance = 0; ibool freed; mutex_enter(&(buf_pool->mutex)); @@ -146,6 +149,18 @@ buf_LRU_search_and_free_block( } block = UT_LIST_GET_PREV(LRU, block); + distance++; + + if (!freed && n_iterations <= 10 + && distance > 100 + (n_iterations * buf_pool->curr_size) + / 10) { + + buf_pool->LRU_flush_ended = 0; + + mutex_exit(&(buf_pool->mutex)); + + return(FALSE); + } } if (buf_pool->LRU_flush_ended > 0) { @@ -180,7 +195,7 @@ buf_LRU_try_free_flushed_blocks(void) mutex_exit(&(buf_pool->mutex)); - buf_LRU_search_and_free_block(0); + buf_LRU_search_and_free_block(1); mutex_enter(&(buf_pool->mutex)); } @@ -200,7 +215,7 @@ buf_LRU_get_free_block(void) { buf_block_t* block = NULL; ibool freed; - ulint n_iterations = 0; + ulint n_iterations = 1; ibool mon_value_was = 0; /* remove bug */ ibool started_monitor = FALSE; loop: @@ -246,14 +261,6 @@ loop: srv_print_innodb_monitor = FALSE; } - - if (buf_pool->LRU_flush_ended > 0) { - mutex_exit(&(buf_pool->mutex)); - - buf_LRU_try_free_flushed_blocks(); - - mutex_enter(&(buf_pool->mutex)); - } /* If there is a block in the free list, take it */ if (UT_LIST_GET_LEN(buf_pool->free) > 0) { @@ -319,6 +326,20 @@ loop: os_aio_simulated_wake_handler_threads(); + mutex_enter(&(buf_pool->mutex)); + + if (buf_pool->LRU_flush_ended > 0) { + /* We have written pages in an LRU flush. To make the insert + buffer more efficient, we try to move these pages to the free + list. */ + + mutex_exit(&(buf_pool->mutex)); + + buf_LRU_try_free_flushed_blocks(); + } else { + mutex_exit(&(buf_pool->mutex)); + } + if (n_iterations > 10) { os_thread_sleep(500000); diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h index 946b6c4e31d..eb9d43d3b93 100644 --- a/innobase/include/buf0lru.h +++ b/innobase/include/buf0lru.h @@ -46,6 +46,20 @@ buf_LRU_get_recent_limit(void); /*==========================*/ /* out: the limit; zero if could not determine it */ /********************************************************************** +Look for a replaceable block from the end of the LRU list and put it to +the free list if found. */ + +ibool +buf_LRU_search_and_free_block( +/*==========================*/ + /* out: TRUE if freed */ + ulint n_iterations); /* in: how many times this has been called + repeatedly without result: a high value means + that we should search farther; if value is + k < 10, then we only search k/10 * number + of pages in the buffer pool from the end + of the LRU list */ +/********************************************************************** Returns a free block from the buf_pool. The block is taken off the free list. If it is empty, blocks are moved from the end of the LRU list to the free list. */ @@ -86,17 +100,6 @@ void buf_LRU_make_block_old( /*===================*/ buf_block_t* block); /* in: control block */ -/********************************************************************** -Look for a replaceable block from the end of the LRU list and put it to -the free list if found. */ - -ibool -buf_LRU_search_and_free_block( -/*==========================*/ - /* out: TRUE if freed */ - ulint n_iterations); /* in: how many times this has been called - repeatedly without result: a high value - means that we should search farther */ /************************************************************************** Validates the LRU list. */ diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index e6ef400bb40..d73d6327d76 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -1505,6 +1505,8 @@ trx_commit_complete_for_mysql( trx->op_info = (char *) ""; } + + return(0); } /************************************************************************** diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 8309c5eb440..1a9b1b16c64 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -197,6 +197,9 @@ extern char *innobase_unix_file_flush_method; /* The following variables have to be my_bool for SHOW VARIABLES to work */ extern my_bool innobase_log_archive, innobase_use_native_aio, innobase_fast_shutdown; +extern "C" { +extern ulong srv_max_buf_pool_modified_pct; +} extern TYPELIB innobase_lock_typelib; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index d02202cd7c6..82bb6659c7e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -658,10 +658,6 @@ extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size; extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log; extern ulong specialflag, current_pid; -#ifdef HAVE_INNOBASE_DB -extern ulong srv_max_buf_pool_modified_pct; -#endif - extern uint test_flags,select_errors,ha_open_options; extern uint protocol_version,dropping_tables; extern uint delay_key_write_options; From 526bb7dc7b750ad9dd4273d48eab223770efe73b Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 17 May 2003 16:23:46 +0300 Subject: [PATCH 186/188] buf0buf.c: When calculating the buf pool dirty pages ratio, add also free pages to the LRU list length: no need to active flushing if there are lots of free pages in the buffer pool --- innobase/buf/buf0buf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index c793c11f29e..e000d862403 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1845,7 +1845,8 @@ buf_get_modified_ratio_pct(void) mutex_enter(&(buf_pool->mutex)); ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list)) - / (1 + UT_LIST_GET_LEN(buf_pool->LRU)); + / (1 + UT_LIST_GET_LEN(buf_pool->LRU) + + UT_LIST_GET_LEN(buf_pool->free)); /* 1 + is there to avoid division by zero */ From 6ba4c68728024b65220ceb6165e83ddc2e2d293c Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 18 May 2003 21:46:19 +0300 Subject: [PATCH 187/188] srv0start.c: Better instructions for the user if adding of new ibdata files fails --- innobase/srv/srv0start.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 552355e5d45..d47af68d663 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -161,13 +161,13 @@ srv_parse_data_file_paths_and_sizes( } if (strlen(str) >= ut_strlen(":autoextend") - && 0 == ut_memcmp(str, ":autoextend", + && 0 == ut_memcmp(str, (char*)":autoextend", ut_strlen(":autoextend"))) { str += ut_strlen(":autoextend"); if (strlen(str) >= ut_strlen(":max:") - && 0 == ut_memcmp(str, ":max:", + && 0 == ut_memcmp(str, (char*)":max:", ut_strlen(":max:"))) { str += ut_strlen(":max:"); @@ -265,7 +265,7 @@ srv_parse_data_file_paths_and_sizes( (*data_file_sizes)[i] = size; if (strlen(str) >= ut_strlen(":autoextend") - && 0 == ut_memcmp(str, ":autoextend", + && 0 == ut_memcmp(str, (char*)":autoextend", ut_strlen(":autoextend"))) { *is_auto_extending = TRUE; @@ -273,7 +273,7 @@ srv_parse_data_file_paths_and_sizes( str += ut_strlen(":autoextend"); if (strlen(str) >= ut_strlen(":max:") - && 0 == ut_memcmp(str, ":max:", + && 0 == ut_memcmp(str, (char*)":max:", ut_strlen(":max:"))) { str += ut_strlen(":max:"); @@ -864,6 +864,7 @@ open_or_create_data_files( return(DB_SUCCESS); } +#ifdef notdefined /********************************************************************* This thread is used to measure contention of latches. */ static @@ -935,6 +936,7 @@ test_measure_cont( return(0); } +#endif /******************************************************************** Starts InnoDB and creates a new database if database files @@ -1036,20 +1038,24 @@ innobase_start_or_create_for_mysql(void) srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; #ifndef __WIN__ - } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) { + } else if (0 == ut_strcmp(srv_file_flush_method_str, + (char*)"fdatasync")) { srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; - } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) { + } else if (0 == ut_strcmp(srv_file_flush_method_str, + (char*)"O_DSYNC")) { srv_unix_file_flush_method = SRV_UNIX_O_DSYNC; } else if (0 == ut_strcmp(srv_file_flush_method_str, - "littlesync")) { + (char*)"littlesync")) { srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC; - } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) { + } else if (0 == ut_strcmp(srv_file_flush_method_str, + (char*)"nosync")) { srv_unix_file_flush_method = SRV_UNIX_NOSYNC; #else - } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) { + } else if (0 == ut_strcmp(srv_file_flush_method_str, + (char*)"normal")) { srv_win_file_flush_method = SRV_WIN_IO_NORMAL; os_aio_use_native_aio = FALSE; @@ -1157,7 +1163,14 @@ innobase_start_or_create_for_mysql(void) &max_flushed_lsn, &max_arch_log_no, &sum_of_new_sizes); if (err != DB_SUCCESS) { - fprintf(stderr, "InnoDB: Could not open data files\n"); + fprintf(stderr, +"InnoDB: Could not open or create data files.\n" +"InnoDB: If you tried to add new data files, and it failed here,\n" +"InnoDB: you should now edit innodb_data_file_path in my.cnf back\n" +"InnoDB: to what it was, and remove the new ibdata files InnoDB created\n" +"InnoDB: in this failed attempt. InnoDB only wrote those files full of\n" +"InnoDB: zeros, but did not yet use them in any way. But be careful: do not\n" +"InnoDB: remove old data files which contain your precious data!\n"); return((int) err); } From c01678bc3d926915c0ca02966212306db148ef34 Mon Sep 17 00:00:00 2001 From: "monty@narttu.mysql.fi" <> Date: Mon, 19 May 2003 12:01:38 +0300 Subject: [PATCH 188/188] Added option --read-only (Thanks to Markus Benning) --- myisam/myisamchk.c | 3 ++- sql/init.cc | 2 -- sql/mysql_priv.h | 3 +-- sql/mysqld.cc | 14 ++++++++++---- sql/set_var.cc | 4 ++++ sql/sql_parse.cc | 12 ++++++++++++ 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index a3970d65fdf..a7df01e0169 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -45,6 +45,7 @@ static const char *set_charset_name; static CHARSET_INFO *set_charset; static long opt_myisam_block_size; static const char *my_progname_short; +static int stopwords_inited= 0; static const char *type_names[]= { "?","char","binary", "short", "long", "float", @@ -861,7 +862,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) } else { - if (share->fulltext_index) + if (share->fulltext_index && !stopwords_inited++) ft_init_stopwords(); if (!(param->testflag & T_READONLY)) diff --git a/sql/init.cc b/sql/init.cc index df06ddd41ef..7d90cc564a1 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -38,13 +38,11 @@ void unireg_init(ulong options) init_my_atof(); /* use our atof */ #endif my_abort_hook=unireg_abort; /* Abort with close of databases */ - f_fyllchar=' '; /* Input fill char */ VOID(strmov(reg_ext,".frm")); for (i=0 ; i < 6 ; i++) // YYMMDDHHMMSS dayord.pos[i]=i; specialflag=SPECIAL_SAME_DB_NAME; - blob_newline='^'; /* Convert newline in blobs to this */ /* Make a tab of powers of 10 */ for (i=0,nr=1.0; i < array_elements(log_10) ; i++) { /* It's used by filesort... */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index d02202cd7c6..c4b1121a321 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -627,7 +627,6 @@ extern char language[LIBLEN],reg_ext[FN_EXTLEN]; extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file; extern char log_error_file[FN_REFLEN]; -extern char blob_newline; extern double log_10[32]; extern ulonglong keybuff_size; extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables; @@ -675,8 +674,8 @@ extern uint volatile thread_count, thread_running, global_read_lock; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names; extern my_bool opt_slave_compressed_protocol, use_temp_pool; +extern my_bool opt_readonly; extern my_bool opt_enable_named_pipe; -extern char f_fyllchar; extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; extern FILE *bootstrap_file; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0211c471ed7..67fb7798ebd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -289,7 +289,7 @@ my_bool opt_enable_named_pipe= 0; my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol; uint delay_key_write_options= (uint) DELAY_KEY_WRITE_ON; -static bool opt_do_pstack = 0; +static my_bool opt_do_pstack = 0; static ulong opt_specialflag=SPECIAL_ENGLISH; static ulong opt_myisam_block_size; @@ -306,6 +306,7 @@ my_bool opt_safe_user_create = 0, opt_no_mix_types = 0; my_bool lower_case_table_names, opt_old_rpl_compat; my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_log_slave_updates= 0, opt_console= 0; +my_bool opt_readonly = 0; volatile bool mqh_used = 0; FILE *bootstrap_file=0; @@ -376,7 +377,7 @@ const char *localhost=LOCAL_HOST; const char *delayed_user="DELAYED"; uint master_port = MYSQL_PORT, master_connect_retry = 60; uint report_port = MYSQL_PORT; -bool master_ssl = 0; +my_bool master_ssl = 0; ulong master_retry_count=0; ulong bytes_sent = 0L, bytes_received = 0L; @@ -404,8 +405,7 @@ ulong slow_launch_threads = 0; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *charsets_list, - blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot, - *opt_init_file; + 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; #ifndef EMBEDDED_LIBRARY @@ -3143,6 +3143,7 @@ enum options { OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER, OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME, + OPT_READONLY, OPT_SORT_BUFFER, OPT_TABLE_CACHE, OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE, OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK, @@ -3927,6 +3928,11 @@ replicating a LOAD DATA INFILE command", "Number of seconds to wait for more data from a master/slave connection before aborting the read.", (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0, GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, + {"read-only", OPT_READONLY, + "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege", + (gptr*) &opt_readonly, + (gptr*) &opt_readonly, + 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"slow_launch_time", OPT_SLOW_LAUNCH_TIME, "If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.", (gptr*) &slow_launch_time, (gptr*) &slow_launch_time, 0, GET_ULONG, diff --git a/sql/set_var.cc b/sql/set_var.cc index a45a923ef90..2ca12cdb802 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -204,6 +204,8 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", &opt_slave_compressed_protocol); sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout", &slave_net_timeout); +sys_var_bool_ptr sys_readonly("read_only", + &opt_readonly); sys_var_long_ptr sys_slow_launch_time("slow_launch_time", &slow_launch_time); sys_var_thd_ulong sys_sort_buffer("sort_buffer_size", @@ -375,6 +377,7 @@ sys_var *sys_variables[]= &sys_slave_compressed_protocol, &sys_slave_net_timeout, &sys_slave_skip_counter, + &sys_readonly, &sys_slow_launch_time, &sys_sort_buffer, &sys_sql_big_tables, @@ -522,6 +525,7 @@ struct show_var_st init_vars[]= { #endif /* HAVE_QUERY_CACHE */ {sys_server_id.name, (char*) &sys_server_id, SHOW_SYS}, {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, + {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, {"skip_external_locking", (char*) &my_disable_locking, SHOW_MY_BOOL}, {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL}, {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e69d260bf11..d9060b4b26e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1329,6 +1329,18 @@ mysql_execute_command(void) (table_rules_on && tables && thd->slave_thread && !tables_ok(thd,tables))) DBUG_VOID_RETURN; + + /* + When option readonly is set deny operations which change tables. + Except for the replication thread and the 'super' users. + */ + if (opt_readonly && + !(thd->slave_thread || (thd->master_access & SUPER_ACL)) && + (uc_update_queries[lex->sql_command] > 0)) + { + send_error(&thd->net,ER_CANT_UPDATE_WITH_READLOCK); + DBUG_VOID_RETURN; + } statistic_increment(com_stat[lex->sql_command],&LOCK_status); switch (lex->sql_command) {