From 5b2a810e5d857856971dcd0e9f88ec1a397486d2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Feb 2003 22:26:09 +0200 Subject: [PATCH 001/399] fixed SQL_SELECT option with UNIONs mysql-test/r/query_cache.result: test of SQL_CACHE with UNIONs mysql-test/t/query_cache.test: test of SQL_CACHE 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 33131c9e58a101327e6d867146e79f67a574fa11 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Mar 2003 23:32:59 +0200 Subject: [PATCH 002/399] calloc replaced with alloc in st_select_lex_node 'new' operator (SCRUM?) sql/sql_lex.cc: initialization of all need field sql/sql_lex.h: calloc replaced with alloc sql/sql_parse.cc: no need full initialization here sql/sql_yacc.yy: removed initialization which will be done in init_qiery method --- sql/sql_lex.cc | 21 +++++++++++++-------- sql/sql_lex.h | 3 +-- sql/sql_parse.cc | 2 +- sql/sql_yacc.yy | 1 - 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 94c06d41634..c6514a93053 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -999,6 +999,8 @@ int yylex(void *arg, void *yythd) void st_select_lex_node::init_query() { + options= 0; + linkage= UNSPECIFIED_TYPE; no_table_names_allowed= uncacheable= dependent= 0; ref_pointer_array= 0; } @@ -1016,8 +1018,8 @@ void st_select_lex_node::init_select() void st_select_lex_unit::init_query() { - linkage= GLOBAL_OPTIONS_TYPE; st_select_lex_node::init_query(); + linkage= GLOBAL_OPTIONS_TYPE; global_parameters= this; select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; @@ -1031,11 +1033,10 @@ void st_select_lex_unit::init_query() void st_select_lex::init_query() { st_select_lex_node::init_query(); - table_list.elements= 0; - table_list.first= 0; - table_list.next= (byte**) &table_list.first; + table_list.empty(); item_list.empty(); join= 0; + where= 0; olap= UNSPECIFIED_OLAP_TYPE; having_fix_field= 0; with_wild= 0; @@ -1044,11 +1045,15 @@ void st_select_lex::init_query() void st_select_lex::init_select() { st_select_lex_node::init_select(); - group_list.elements= 0; - group_list.first= 0; - group_list.next= (byte**) &group_list.first; + group_list.empty(); + type= db= db1= table1= db2= table2= 0; + having= 0; + group_list.empty(); + use_index_ptr= ignore_index_ptr= 0; + table_join_options= 0; + in_sum_expr= with_wild= 0; options= 0; - where= having= 0; + braces= 0; when_list.empty(); expr_list.empty(); interval_list.empty(); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index aff3485dbe4..6e03e0441c0 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -221,8 +221,7 @@ public: static void *operator new(size_t size) { - // TODO: Change to alloc() and explicitely clear elements in constructors - return (void*) sql_calloc((uint) size); + return (void*) sql_alloc((uint) size); } static void operator delete(void *ptr,size_t size) {} st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {} diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b336f41aa7e..055d144be05 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3316,7 +3316,7 @@ void mysql_init_multi_delete(LEX *lex) lex->select_lex.select_limit= lex->unit.select_limit_cnt= HA_POS_ERROR; lex->auxilliary_table_list= lex->select_lex.table_list; - lex->select_lex.init_query(); + lex->select_lex.table_list.empty(); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e5d94c30521..af964ddbb07 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3361,7 +3361,6 @@ delete: { LEX *lex= Lex; lex->sql_command= SQLCOM_DELETE; - lex->select_lex.options= 0; lex->lock_option= lex->thd->update_lock_default; lex->select_lex.init_order(); } From 7a440f777914eb22f2393d4761d5ac9b498480c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Mar 2003 19:39:01 +0100 Subject: [PATCH 003/399] 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 856d50f9d1ebf2c8a99be88c23f724c15e0d1d93 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 19 Mar 2003 16:10:16 +0200 Subject: [PATCH 004/399] 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 2e98d56c7bd39f29a18714bdf5d9fd1c38426424 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 19 Mar 2003 17:25:59 +0200 Subject: [PATCH 005/399] 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 404878b8730700ffcf55331b4b8e8ba5421d7f9c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 19 Mar 2003 17:46:36 +0200 Subject: [PATCH 006/399] 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 2d87079675b28f2b29a30b82c9243169987b226e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Mar 2003 19:04:30 +0200 Subject: [PATCH 007/399] 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 fc7ab8d1b176740ca167f17fec9dd12998723d36 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Mar 2003 19:13:45 +0200 Subject: [PATCH 008/399] 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 d99370dd1b2d5e85c36ed45a9f7758c3d2ebb35c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Mar 2003 22:52:46 +0200 Subject: [PATCH 009/399] A fix for bug #176 code cleanup mysql-test/r/having.result: A test for the bug fix for bug #176 mysql-test/t/having.test: A test for the bug fix for bug #176 sql/item.cc: A for the bug #176 sql/item_func.cc: 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 a424d01173d0b6d446f752a220c827d28358831a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Mar 2003 09:49:09 +0300 Subject: [PATCH 010/399] fixed bug 209 (SQL_SELECT_LIMIT and query cache incompatibility) mysql-test/r/query_cache.result: test of SET OPTION SQL_SELECT_LIMIT mysql-test/t/query_cache.test: test of SET OPTION SQL_SELECT_LIMIT sql/sql_cache.cc: layout fixed SQL_SELECT_LIMIT stored in query cache now sql/sql_parse.cc: room for SQL_SELECT_LAYOUT storing added --- 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 bd4d87297d03706b49eab04d030b2e63a4bc9997 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Apr 2003 17:05:34 +0300 Subject: [PATCH 011/399] 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 aa588247c6fdeea329e72fc8b62563bab8707f76 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 21:51:14 +0600 Subject: [PATCH 012/399] test-transactions.sh: correct misprint in the test_update sql-bench/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 6376b0a8b8c6e2806ed5c63232b9379744eb8601 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 19:55:37 +0300 Subject: [PATCH 013/399] 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 89bb3165501b09b2922d361905a4efb7b490d8b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 20:24:15 +0300 Subject: [PATCH 014/399] One test case, one bug fix and one new feature mysql-test/r/innodb.result: A test case for non-functional rollback after inserting a row into MyISAM table with binary log enabled. mysql-test/t/innodb.test: A test case for non-functional rollback after inserting a row into MyISAM table with binary log enabled. sql/sql_show.cc: Displaying disabled keys in SHOW KEYS sql/sql_table.cc: Fix for a serious bug with ALTER TABLE ENABLE / DISABLE KEYS --- 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 00d9b06a7a6a659762e5fd4a6b8e32bbf3b639d0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 21:17:53 +0300 Subject: [PATCH 015/399] 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 ecd9e7129186ca1b8617c183a7cb2950ecaa0a78 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 21:19:13 +0300 Subject: [PATCH 016/399] 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: 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 e8c9045eebb2aed64e795936bc4cb915b20b8d37 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 20:19:13 +0200 Subject: [PATCH 017/399] 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 e7b3accb4882022e38df175007b27d53a820e8bc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 20:19:14 +0200 Subject: [PATCH 018/399] 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 a31ff43462782e391e6073fd58984d08c11deced Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Apr 2003 02:54:07 +0600 Subject: [PATCH 019/399] crash-me.sh: add sorted_group_by parameter sql-bench/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 654d1026e4517c760372b828fe3c9457aa86972b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Apr 2003 20:26:13 -0400 Subject: [PATCH 020/399] fux bug #183 BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- 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 a65aa6bce3115e7ba5b96c82c39430a9ef765a57 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Apr 2003 10:14:06 +0300 Subject: [PATCH 021/399] log.cc: Fix crash in previous bug fix log.cc reported by Rob Lyon if --skip-innodb is specified sql/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 02270252fe018c8247d501f3bb1ee6a7f1016f07 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Apr 2003 17:43:54 +0200 Subject: [PATCH 022/399] 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 909596e030134e96a4cb403c92ed57570b6b7157 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Apr 2003 19:05:00 +0200 Subject: [PATCH 023/399] - 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 da68e3d69ff23aa89322bc4460a214aa57798c5b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Apr 2003 21:36:45 +0300 Subject: [PATCH 024/399] 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: Changed name of created test database sql/ha_innobase.cc: Changed innobase_flush_log_at_trx_commit to be 1 as default sql/mini_client.cc: Fixed problem with not freed thr_alarm() sql/mysqld.cc: Allocate some extra thr_alarm slots just to be safe sql/slave.cc: Simple code cleanup --- 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 da0844b15fec2629c207dc13f33495f9c40eeb96 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Apr 2003 10:35:13 +0500 Subject: [PATCH 025/399] #244 bugfix (thread stack error message in embedded library) sql/mysql_priv.h: stack checking suppressed in EMBEDDED case sql/sql_parse.cc: code of check_stack_overrun ifdefed --- 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 27282ed325563b4a3570f449ba30cce265152319 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Apr 2003 14:53:20 +0200 Subject: [PATCH 026/399] - 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 8cad4f7090f50c19a1e0a247c57d9d965b7b7a6e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Apr 2003 15:16:12 +0200 Subject: [PATCH 027/399] 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: 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 0606f5bb1b4c98b77e10b934d3c1b71b5eaa9b36 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Apr 2003 21:19:53 +0200 Subject: [PATCH 028/399] - 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: - applied Patch provided by Christian Hammers from Debian to be able to run this script on every upgrade without having to worry that the server is really running. Therefore "mysqld --bootstrap" is used to make the changes. For this to work all SQL statements are sent to stderr when "--sqlonly" is given and the echo's are piped to /dev/null. The echo_stderr that is used is just a "#!/bin/sh\necho "$*" >&2" script. --- 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 029/399] - 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: - work around bug #235 (comments at the end of configuration options lead to errors) by reformatting the comments to be above the options instead - enhanced comments on the replication options a bit - added option "skip-networking" (commented out by default) with an appropriate comment (bug #234) support-files/my-large.cnf.sh: - work around bug #235 (comments at the end of configuration options lead to errors) by reformatting the comments to be above the options instead - enhanced comments on the replication options a bit - added option "skip-networking" (commented out by default) with an appropriate comment (bug #234) support-files/my-medium.cnf.sh: - work around bug #235 (comments at the end of configuration options lead to errors) by reformatting the comments to be above the options instead - enhanced comments on the replication options a bit - added option "skip-networking" (commented out by default) with an appropriate comment (bug #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 8b8d3135042b68c6ccb7dff74f91bdde10f7e786 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Apr 2003 20:03:52 +0200 Subject: [PATCH 030/399] - 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: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/buf/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/com/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/data/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/dict/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/dyn/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/eval/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/fil/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/fsp/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/fut/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/ha/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/ibuf/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/include/Makefile.i: - removed libsdir = ../libs to fix a bug in "make DESTDIR= install" (the libs always got installed in "dir../") innobase/lock/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/log/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/mach/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/mem/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/mtr/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/odbc/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/os/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/page/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/pars/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/que/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/read/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/rem/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/row/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/srv/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/sync/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/thr/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/trx/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/usr/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) innobase/ut/Makefile.am: - replaced libs_LIBRARIES with noinst_LIBRARIES (they are not supposed to be installed anyway) --- 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 a96a8137c646bed06df482d02c9ecdc39c1523dc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Apr 2003 13:02:16 +0200 Subject: [PATCH 031/399] - 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 ffb7fb400ef62a824047df479bc4c1f77aac76a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Apr 2003 17:07:58 +0200 Subject: [PATCH 032/399] 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 Makefile.am: - added dist-hook to remove superfluous SCCS directories from the source distribution bdb/dist/s_symlink: - don't try to create symlinks to nonexisting doc files --- 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 3e335144be1af3f7c70a0c385b4e88da2c1e5e94 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Apr 2003 20:09:24 +0300 Subject: [PATCH 033/399] Two bug fixes mysql-test/r/innodb.result: Fix for a bug that caused queries with ORDER BY field_in_select_list to be returned entirely unsorted. mysql-test/t/innodb.test: Fix for a bug that caused queries with ORDER BY field_in_select_list to be returned entirely unsorted. sql/sql_select.cc: Fix for a bug that caused queries with ORDER BY field_in_select_list to be returned entirely unsorted. sql/sql_update.cc: Fix for a glitch that caused too many tables to be locked. --- 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 e357610ba303f303d0a9b8652a437a4cb0a3f22e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Apr 2003 19:45:09 +0300 Subject: [PATCH 034/399] 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 930ded12ca1c0df3e8c86ae65a1e7461132a95be Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Apr 2003 20:58:41 +0300 Subject: [PATCH 035/399] 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 24aba046bf287388622e2fdc34bb66a6cca40876 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Apr 2003 21:46:24 +0300 Subject: [PATCH 036/399] 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 bf09c10a6e72b5993b579ea023e3d91e6db22e46 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Apr 2003 16:11:37 +0200 Subject: [PATCH 037/399] - 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 592c30bdef7fe7c0a3d6dbd11a835221b38e941c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Apr 2003 17:34:56 +0200 Subject: [PATCH 038/399] - 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: - updated variable names that have been renamed in 4.0 (bug #223) - added more detailed info about how to set up replication (suggestion made by Guilhem) support-files/my-large.cnf.sh: - updated variable names that have been renamed in 4.0 (bug #223) - added more detailed info about how to set up replication (suggestion made by Guilhem) support-files/my-medium.cnf.sh: - updated variable names that have been renamed in 4.0 (bug #223) - added more detailed info about how to set up replication (suggestion made by Guilhem) support-files/my-small.cnf.sh: - updated variable names that have been renamed in 4.0 (bug #223) - added hint and commented out sample about skip-networking option (security enhancement) --- 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 3ac05ea4812531bd213de6b35508d7da0a679378 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Apr 2003 22:04:16 +0300 Subject: [PATCH 039/399] 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: Added replication flags from 4.1 mysql-test/r/func_group.result: Added test for SUM(NULL) mysql-test/t/func_group.test: Added test for SUM(NULL) sql/item_sum.cc: Fixed bug in SUM() with NULL:s sql/item_sum.h: Fixed bug in SUM() with NULL:s sql/mysqld.cc: Added option --symbolic-links Fixed bug in symbolic link handling on Windows sql/net_serv.cc: Code cleanup sql/sql_acl.cc: Added logging of warnings for failed connections with ssl. sql/sql_show.cc: Changed to use HAVE_REPLICATION instead of EMBEDDED_LIBRARY --- 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 3cb207ec4b460f983eb0bb063fd171040ab4e9ec Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 15:05:47 +0500 Subject: [PATCH 040/399] 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 a3274c2222bc09a055cdcac8d5606d11da37ed8e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 13:39:39 +0300 Subject: [PATCH 041/399] 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 797d9de9cd4c3ce933c604c72a3a96ceac975e17 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 17:25:05 +0500 Subject: [PATCH 042/399] 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 07c29cc91aaba8a7982db9b7ba9c95ffc9ab7445 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 17:47:36 +0500 Subject: [PATCH 043/399] 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 33ac47279b7367c816c90642f1b4e530c05f248e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 16:45:01 +0300 Subject: [PATCH 044/399] Many files: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/buf/buf0flu.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/dict/dict0crea.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/dict/dict0dict.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/dict/dict0load.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/ibuf/ibuf0ibuf.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/include/db0err.h: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/include/dict0dict.h: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/include/row0ins.h: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/lock/lock0lock.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/os/os0file.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/row/row0ins.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/row/row0mysql.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/row/row0sel.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/row/row0upd.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/srv/srv0srv.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works innobase/ut/ut0ut.c: Merge InnoDB-4.0.13; DROP FOREIGN KEY now works sql/ha_innodb.cc: 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 0d898379a71fc1dc999dcf2503b6c7d4f885ce47 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 19:48:58 +0500 Subject: [PATCH 045/399] fix for bug #212 sql/sql_list.h: We should reset list::last here --- 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 2eaaae7abbde373520737a195b6d6edb48777d8a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 11:43:04 -0400 Subject: [PATCH 046/399] Exported functions required by MySQLCC BitKeeper/deleted/.del-libmysql.def~29fc6d70335f1c4c: Delete: VC++Files/libmysql/libmysql.def --- 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 fecbc44eb65ab17eece38e68ae9f9d4899b31acc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 21:37:22 +0500 Subject: [PATCH 047/399] Fix for #126 sql/ha_myisam.cc: Flag added to turn on check sum recounting --- 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 dad32c931086985a007932bdabf48af91478b7cb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 21:10:45 +0300 Subject: [PATCH 048/399] 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 6e13c4e255824970c12a5772a5ee38310d98b229 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 21:36:42 +0300 Subject: [PATCH 049/399] 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: 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 923c638e895e30da305c7d2e517d5f90d6b78b07 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 22:24:58 +0300 Subject: [PATCH 050/399] 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 31d0d6e5bddcc4394a2bfd0320d3f01203146530 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 22:50:12 +0300 Subject: [PATCH 051/399] 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: 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 7214d07baf67817974a87da9faa61eaa8e2bb4ae Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Apr 2003 23:05:22 +0300 Subject: [PATCH 052/399] row0ins.c: Better fix for the ON DELETE SET NULL problem innobase/row/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 01545bd472169f8637ba0dab1630a069db6d2195 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Apr 2003 02:28:40 +0300 Subject: [PATCH 053/399] 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: Allow HANDLER PREV and NEXT also after positioning the cursor with a unique search on the primary key innobase/row/row0mysql.c: Allow HANDLER PREV and NEXT also after positioning the cursor with a unique search on the primary key innobase/row/row0sel.c: Allow HANDLER PREV and NEXT also after positioning the cursor with a unique search on the primary key sql/ha_innodb.cc: 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 88ebdaaa0cdae07128dc8d71b7e7efc44072df55 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Apr 2003 02:51:50 +0300 Subject: [PATCH 054/399] 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: 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 4643820397ae1ac92e8112b17e258e41d8ff7009 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 18 Apr 2003 18:42:43 +0300 Subject: [PATCH 055/399] 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: Use fflush to make sure report of a corrupt log record is printed to .err log before mysqld crashes sql/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 sql/ha_innodb.h: 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 --- 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 b09b7a1f198fa60702aeb6ce836562a9f0511c39 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 18 Apr 2003 22:06:10 +0300 Subject: [PATCH 056/399] 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: 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 --- 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 480dbf0f30b9d6f8673902173f414b51eff99a61 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 19 Apr 2003 20:09:01 +0300 Subject: [PATCH 057/399] 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: 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 1b23ce2d358c1db696744a9ca0a6a611e20e5242 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 19 Apr 2003 23:18:35 +0300 Subject: [PATCH 058/399] Three bug fixes and one fix being undone. mysql-test/r/innodb_handler.result: change of test case after Heikki's fix sql/sql_db.cc: Adding suport for backquotes in change_db() sql/sql_update.cc: Undoing a fix strings/ctype-tis620.c: Fixing a crashing bug --- 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 61e368438ab5afe1d88ee718915437c038c5490e Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 20 Apr 2003 19:36:09 +0300 Subject: [PATCH 059/399] univ.i: If HAVE_purify is defined, define UNIV_SET_MEM_TO_ZERO to eliminate Purify warnings innobase/include/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 c798445608f7a27d3bce7aea440bb842bac65bb4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Apr 2003 12:56:54 +0300 Subject: [PATCH 060/399] buf0buf.c: No buffer pool activity in SHOW INNODB STATUS actually meant no page gets innobase/buf/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 325e11a3e011e2d72128b5aa3091239bed4e9eb4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Apr 2003 14:11:17 +0300 Subject: [PATCH 061/399] 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 ae89db4904de34cdfb9cdb3ecdc3217f6a32834f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Apr 2003 22:54:02 +0300 Subject: [PATCH 062/399] 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: Fixing result for fixed error message --- 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 b534154b12c6b592594588efb3dacc5dbf2e33e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 00:53:07 +0400 Subject: [PATCH 063/399] 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 963d57a39446490ce2fb91c773ac2466c3723aa1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 00:13:37 +0300 Subject: [PATCH 064/399] 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: New test results mysql-test/t/join.test: Test for bug 212 sql/log_event.cc: Removed wrong cast sql/log_event.h: Fixed problem with timestamps in binary log on 64 bit machines sql/sql_list.h: Fix for bug 212 (back ported from 4.1) --- 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 60d620aee0f586cae0424cac2ae79e70aa59281d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Apr 2003 19:38:57 -0400 Subject: [PATCH 065/399] 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 ce0dbf79151787a5117317c7c41cdd3cbb10f61a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 01:51:25 +0200 Subject: [PATCH 066/399] - 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 39734017215569684390e47ce39ffdc55c163b94 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 02:51:25 +0300 Subject: [PATCH 067/399] row0mysql.c: Give sensible advice to the user if InnoDB notices index corruption innobase/row/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 e103eeb2bb21e0f822c3f7c83f6acced84278a4d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 01:51:26 +0200 Subject: [PATCH 068/399] - 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 2c2bc003e2451d35d8b80689f0aff66ef248cf21 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 01:51:28 +0200 Subject: [PATCH 069/399] - updated sample my.cnf files: removed deprecated set-variable keywords support-files/my-huge.cnf.sh: - removed deprecated "set-variable" keywords from options support-files/my-large.cnf.sh: - removed deprecated "set-variable" keywords from options support-files/my-medium.cnf.sh: - removed deprecated "set-variable" keywords from options support-files/my-small.cnf.sh: - removed deprecated "set-variable" keywords from options --- 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 d19ba33f98a2de54d5356d75fe1a92d88f407ca6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 14:03:21 +0400 Subject: [PATCH 070/399] 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 a792b31b90ec4414da4a1cc787818523875fde89 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 12:44:00 +0200 Subject: [PATCH 071/399] - 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 29b593987d81b987a0feb1750afec23bd8cac9c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 15:37:11 +0400 Subject: [PATCH 072/399] 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 b21a0be804fbff458ffbfff4e01f28f8730d3820 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 15:44:39 +0400 Subject: [PATCH 073/399] 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 9127fb60d603df30d74b9e810275d76cdb1cdc8b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 15:27:11 +0300 Subject: [PATCH 074/399] 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 c14f989ff83e27d0c28964cf1a97e5e58a53c4ff Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 18:00:07 +0500 Subject: [PATCH 075/399] Task 761:'mysqlbinlog should not die when reading unknown event' client/mysqlbinlog.cc: Task 761:'mysqlbinlog should not die when reading unknown event' The 'force-read' option has been added. sql/log_event.cc: Task 761:'mysqlbinlog should not die when reading unknown event' The'Unknown_log_event' class has been added sql/log_event.h: Task 761:'mysqlbinlog should not die when reading unknown event' The 'Unknown_log_event' class has been added. --- 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 95d4978ff60b6dd170e1490de380ee6db36a4a4f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 20:42:07 +0300 Subject: [PATCH 076/399] 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 562fe48731960b0bfb30f43687a5196c7b0bb208 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 11:43:30 -0700 Subject: [PATCH 077/399] Modify PeterG's internals documentation per Monty. Added more detailed explanation of record header and column storage. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- 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 d7fee29e2fce2b3ad823339ffe53d39ce1443289 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 13:43:31 -0500 Subject: [PATCH 078/399] config-win.h: Enable 'LOAD LOCAL INFILE', for parity with unix binaries. include/config-win.h: Enable 'LOAD LOCAL INFILE', for parity with unix binaries. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- 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 61950d517d54944deb0b0c2d4e2edabcfa32023f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 21:44:24 +0300 Subject: [PATCH 079/399] improved bug fix sql/sql_select.cc: somewhat 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 18c1a9bd07b7fd22c8d29e571d127a8bd31f6d02 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 22:46:47 +0400 Subject: [PATCH 080/399] 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 7032486889f42b3f18b4a0a5be6cb97b74790ea8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 21:52:16 +0300 Subject: [PATCH 081/399] Fixes for valgrind Added optimzation for clustered index Fixed bug in UPDATE ... ORDER BY Fixed handling of UPDATE ... LIMIT BitKeeper/deleted/.del-.cvsignore~7e29af89a3559f4c: Delete: Images/.cvsignore BitKeeper/deleted/.del-README~d5a4e7ca3a2e87a9: Delete: repl-tests/README BitKeeper/deleted/.del-run-all-tests~4deb6479a13e4568: Delete: repl-tests/run-all-tests BitKeeper/deleted/.del-run.test~3dc5b9bd1e9feea5: Delete: repl-tests/test-repl-alter/run.test BitKeeper/deleted/.del-run.test~4020771cff278f14: Delete: repl-tests/test-bad-query/run.test BitKeeper/deleted/.del-run.test~452f2b66537404a8: Delete: repl-tests/test-dump/run.test BitKeeper/deleted/.del-run.test~b1f0c1f96554df8: Delete: repl-tests/test-auto-inc/run.test BitKeeper/deleted/.del-table-dump-check.master~e13afeb8c79264b5: Delete: repl-tests/test-dump/table-dump-check.master BitKeeper/deleted/.del-table-dump-select.master~744acb955e33f3db: Delete: repl-tests/test-dump/table-dump-select.master BitKeeper/deleted/.del-x.master~29a93ed7956c8693: Delete: repl-tests/test-auto-inc/x.master BitKeeper/deleted/.del-x.master~3b248cbac9abda2b: Delete: repl-tests/test-bad-query/x.master BitKeeper/deleted/.del-foo-dump-master.master~b49ae6bec1e918ee: Delete: repl-tests/test-repl/foo-dump-master.master BitKeeper/deleted/.del-foo-dump-slave.master~f16ed20457d59be9: Delete: repl-tests/test-repl/foo-dump-slave.master BitKeeper/deleted/.del-repl-timestamp.master.reject~3492d2b74b413771: Delete: repl-tests/test-repl-ts/repl-timestamp.master.reject BitKeeper/deleted/.del-repl-timestamp.master~4b7782da5cc13161: Delete: repl-tests/test-repl-ts/repl-timestamp.master BitKeeper/deleted/.del-run.test~a1e32ea1e4253af4: Delete: repl-tests/test-repl/run.test BitKeeper/deleted/.del-run.test~ce5e626c91b760ec: Delete: repl-tests/test-repl-ts/run.test BitKeeper/deleted/.del-sum-wlen-master.master~1a5ea625c79e978: Delete: repl-tests/test-repl/sum-wlen-master.master BitKeeper/deleted/.del-sum-wlen-slave.master~f016d98833433084: Delete: repl-tests/test-repl/sum-wlen-slave.master BitKeeper/deleted/.del-test.master~5829e7b3770179db: Delete: repl-tests/test-repl-alter/test.master BitKeeper/deleted/.del-master-slave.inc~6775f6ae10137c39: Delete: repl-tests/include/master-slave.inc include/my_global.h: Fix for purify/valgrind myisam/mi_info.c: Updated comment mysql-test/r/group_by.result: New test results mysql-test/r/innodb.result: New test results mysql-test/r/join_outer.result: New test results mysql-test/r/multi_update.result: New test results mysql-test/r/null_key.result: New test results mysql-test/r/update.result: New test results mysql-test/t/group_by.test: Added extra explain to 'suspicious' test. mysql-test/t/innodb.test: Added test for UPDATE ... ORDER BY mysql-test/t/join_outer.test: Changed test to be repeatable mysql-test/t/multi_update.test: Slight change of test to catch more bugs mysql-test/t/update.test: Better test for UPDATE ... ORDER BY sql/field.cc: Simple optimization sql/ha_heap.h: Added optimzation for clustered index sql/ha_innodb.cc: Added optimzation for clustered index sql/ha_innodb.h: Added optimzation for clustered index sql/handler.h: Added optimzation for clustered index sql/item_sum.cc: Removed some usage of current_thd sql/mysqld.cc: Fix bug when compiling for purify/valgrind sql/opt_range.cc: Added optimzation for clustered index sql/records.cc: Fixed comment sql/sql_list.h: Fixed comment sql/sql_select.cc: Removed some usage of current_thd sql/sql_select.h: Removed some usage of current_thd sql/sql_union.cc: Removed some usage of current_thd sql/sql_update.cc: Fixed bug in UPDATE ... ORDER BY Fixed handling of UPDATE ... LIMIT support-files/my-huge.cnf.sh: Added default size for query cache support-files/my-large.cnf.sh: Added default size for query cache --- 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 148472b4712ffec00f53e7c61534226786e7e570 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2003 13:20:23 -0700 Subject: [PATCH 082/399] 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 975598a38308ccc6c1cf142fb0d326413a4901f1 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 00:09:19 +0300 Subject: [PATCH 083/399] 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 81a83ca8b667f16c7fd40e666ac26c251b2b87de Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 02:23:25 +0300 Subject: [PATCH 084/399] 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: new test result mysql-test/t/group_by.test: Changed test slightly to make it repeatable --- 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 cdf3e090e5d1cd9a0aaf17dba52acf39abdfe1a1 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 09:18:53 +0300 Subject: [PATCH 085/399] Fixed bug in SET SQL_BIG_SELECTS mysql-test/r/select_safe.result: Updated results mysql-test/t/select_safe.test: Added test for SQL_BIG_SELECTS sql/set_var.cc: Fixed bug in SQL_BIG_SELECTS sql/share/czech/errmsg.txt: Updated error messages sql/share/danish/errmsg.txt: Updated error messages sql/share/dutch/errmsg.txt: Updated error messages sql/share/english/errmsg.txt: Updated error messages sql/share/estonian/errmsg.txt: Updated error messages sql/share/french/errmsg.txt: Updated error messages sql/share/german/errmsg.txt: Updated error messages sql/share/greek/errmsg.txt: Updated error messages sql/share/hungarian/errmsg.txt: Updated error messages sql/share/italian/errmsg.txt: Updated error messages sql/share/japanese/errmsg.txt: Updated error messages sql/share/korean/errmsg.txt: Updated error messages sql/share/norwegian-ny/errmsg.txt: Updated error messages sql/share/norwegian/errmsg.txt: Updated error messages sql/share/portuguese/errmsg.txt: Updated error messages sql/share/romanian/errmsg.txt: Updated error messages sql/share/russian/errmsg.txt: Updated error messages sql/share/slovak/errmsg.txt: Updated error messages sql/share/spanish/errmsg.txt: Updated error messages sql/share/swedish/errmsg.txt: Updated error messages sql/share/ukrainian/errmsg.txt: Updated error messages --- 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 1e8414803c0e3583ec729954236c3498d739d26a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 15:34:43 +0300 Subject: [PATCH 086/399] 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: 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.h: 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 73b49b70ca0d8d7700bee66183b96ab4fda8ef26 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 21:51:00 +0300 Subject: [PATCH 087/399] srv0srv.c: Make buffer pool flush batches bigger as that may save some time if fsync is very inefficient innobase/srv/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 616ca7f6058746f47d6b2b74e5c8b82ccadf019f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 23:03:00 +0300 Subject: [PATCH 088/399] 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: 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 aaa3e8271321437eff98cfab2861516f25acc80a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 23:24:11 +0300 Subject: [PATCH 089/399] 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: 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 1a01f0ff08b2e22602605d59e009d19500f9fb75 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 18:15:52 -0400 Subject: [PATCH 090/399] Minor changes in netware directory (From Rob Lyon - Novell) netware/mysql.xdc: Change mode to -rw-rw-r-- netware/BUILD/compile-AUTOTOOLS: Turned on error checking in all NetWare build scripts. netware/BUILD/compile-linux-tools: Turned on error checking in all NetWare build scripts. netware/BUILD/compile-netware-END: Turned on error checking in all NetWare build scripts. netware/BUILD/compile-netware-START: Turned on error checking in all NetWare build scripts. netware/BUILD/compile-netware-all: Turned on error checking in all NetWare build scripts. netware/BUILD/compile-netware-debug: Turned on error checking in all NetWare build scripts. netware/BUILD/compile-netware-standard: Turned on error checking in all NetWare build scripts. netware/BUILD/mwasmnlm: Turned on error checking in all NetWare build scripts. netware/BUILD/mwccnlm: Turned on error checking in all NetWare build scripts. netware/BUILD/mwldnlm: Turned on error checking in all NetWare build scripts. netware/BUILD/nwbootstrap: Add target path suffix --- 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 ae5e364c19dba6c87e2fed60df1ee4c417e1f893 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Apr 2003 20:48:54 -0400 Subject: [PATCH 091/399] Changes from Novell for NetWare platform include/my_pthread.h: Consolidated NetWare pthread_exit() changes. mysys/mf_path.c: NetWare needs a semicolon path delimiter. mysys/my_pthread.c: Consolidated NetWare pthread_exit() changes. sql/mini_client.cc: Modified to match my_connect(). sql/mysqld.cc: Consolidated NetWare pthread_exit() changes. sql/slave.cc: Consolidated NetWare pthread_exit() changes. sql/sql_load.cc: Stat properites should not be checked here on NetWare. --- 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 616b717db5431924d92d57bd523c6beb330ccac5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2003 13:02:44 +0200 Subject: [PATCH 092/399] - support-files/MacOSX/ReadMe.txt is now autogenerated from the manual instead of being an individual file to avoid redundancy BitKeeper/deleted/.del-ReadMe.txt~bd880aa05a0baccd: Delete: support-files/MacOSX/ReadMe.txt Docs/Makefile.am: - Generate the MacOS ReadMe.txt from the manual support-files/MacOSX/Makefile.am: - Added MacOS X ReadMe.txt to CLEANFILES now that it's being autogenerated --- 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 c1ae7593b822aef6d2a267e520d2d0d469287294 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2003 16:27:16 +0500 Subject: [PATCH 093/399] ctype-tis620.c: Don't allow access outside the string strings/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 a8d6374fef97a4fb8617880386e706b4856e807d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2003 14:42:01 +0200 Subject: [PATCH 094/399] - Updated innodb test results on Heikki's request (InnoDB now supports ANALYZE TABLE) BitKeeper/etc/ignore: Added support-files/MacOSX/ReadMe.txt to the ignore list --- .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 3e81b9d22bd83992f1dabe9b8d5597d405184558 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2003 21:28:11 +0500 Subject: [PATCH 095/399] Trimming code with Monty's suggestions strings/ctype-tis620.c: thai2sortable code optimized all the file formatted with company standards --- 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 5d80c04f5b65ceac09ae263c892293655a9889fc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2003 21:12:44 +0300 Subject: [PATCH 096/399] ut0dbg.h: Print the failing assertion if it fails; helps to analyze bug reports innobase/include/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 30a9ca4f72f84de38f96fd4d94e2ed9c9b5e783c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2003 21:58:25 +0200 Subject: [PATCH 097/399] - 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 046c66819fafd0f83dc16fda56c5b249c8b195c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 14:54:53 +0300 Subject: [PATCH 098/399] filesort.cc, order_by.result: Fixed bug 263 order_by.test: Fixed bug 263 mysql-test/t/order_by.test: Fixed bug 263 mysql-test/r/order_by.result: Fixed bug 263 sql/filesort.cc: 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 4832d06f9251b3b0f26655efec90b3f2b745082e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 15:53:27 +0300 Subject: [PATCH 099/399] fixed incorrect number of affected rows in REPLACE...SELECT... (bug 130) sql/sql_insert.cc: fixed incorrect number of affected rows in REPLACE...SELECT... BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- 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 75ef233342e7bd61640e699b754efbbcb970b827 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 16:03:33 +0300 Subject: [PATCH 100/399] code clean-up strings/ctype-tis620.c: making final 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 418467e32ad8617c1546870f1b24493601ca4d47 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 17:57:19 +0300 Subject: [PATCH 101/399] Fix possible memory overrun when reading broken character set files sql/mysqld.cc: Safety fix. --- 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 62af18cb8729894625d005e260838f68b7c57175 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 20:43:28 +0300 Subject: [PATCH 102/399] 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: Fix for -fbranch-probabilites configure.in: Fix for -fbranch-probabilites myisam/mi_open.c: Give error instead of writing to stderr (Which user can't see) mysql-test/r/join.result: Update results after change to NATURAL/LEFT/RIGHT JOIN mysql-test/r/join_outer.result: Update results after change to NATURAL/LEFT/RIGHT JOIN mysql-test/r/select.result: Update results after change to NATURAL/LEFT/RIGHT JOIN mysql-test/t/join.test: Update results after change to NATURAL/LEFT/RIGHT JOIN sql/item_strfunc.cc: Fix for LEFT/RIGHT/MID with multi-byte-character sets sql/mysqld.cc: Fix for new bison 1.875 (Wrong error text message when one got syntax error) sql/sql_class.cc: Don't show port in SHOW PROCESSLIST for system threads sql/sql_insert.cc: max_insert_delayed_threads now works as documented. delayed_insert_timeout now works on Linux sql/sql_parse.cc: Added comment sql/sql_select.cc: Fix problem with ORDER BY being discarded and results returned un-sorted sql/sql_yacc.yy: Fixed bug with NATURAL LEFT JOIN, NATURAL RIGHT JOIN and RIGHT JOIN when using many joined tables. --- 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 c492e6be2d7058797b63a3400f95afcac8e795f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 20:57:13 +0300 Subject: [PATCH 103/399] srv0start.c: fflush stderr after startup innobase/srv/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 4de0399566a8772490e0bacd60d6c0a2172183e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 16:00:52 -0700 Subject: [PATCH 104/399] 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 5c965deec7efdfcc8fb72e6e76aa92e9b75902bf Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Apr 2003 18:58:55 -0700 Subject: [PATCH 105/399] 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 0f78cb180743b150e0afe673e9bdc709adb72da3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Apr 2003 17:25:39 +0300 Subject: [PATCH 106/399] 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 sql/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/trx/trx0trx.c: 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: 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 f22be777341f53b4deb58851828c0733ab5380bf Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Apr 2003 22:12:08 +0300 Subject: [PATCH 107/399] 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: Added new source files myisam/mi_key.c: Fixed problem when comparing a key for a multi-byte-character set. myisam/mi_range.c: Fixed problem when comparing a key for a multi-byte-character set. myisam/mi_rkey.c: Fixed problem when comparing a key for a multi-byte-character set. myisam/mi_search.c: Fixed problem when comparing a key for a multi-byte-character set. myisam/mi_test2.c: Fixed printf statements myisam/myisamdef.h: Fixed problem when comparing a key for a multi-byte-character set. myisam/sort.c: Fixed printf statements mysql-test/r/ctype_latin1_de.result: New test results mysql-test/r/join.result: New test results mysql-test/r/repair.result: New test results mysql-test/r/rpl_alter.result: New test results mysql-test/t/ctype_latin1_de-master.opt: --new is needed to get 0x... strings to work properly mysql-test/t/ctype_latin1_de.test: New test for latin1_de mysql-test/t/repair.test: Test of USE_FRM and HEAP tables sql/field.cc: Fixed problem when comparing a key for a multi-byte-character set. sql/item.cc: Use 0x.... as strings if 'new' mode sql/item.h: Use 0x.... as strings if 'new' mode sql/mysqld.cc: Don't report -max on windows when InnoDB is enabled. sql/sql_analyse.cc: Removed unused variable sql/sql_insert.cc: Removed debug message sql/sql_repl.cc: Reset current_linfo; This could cause a hang when doing PURGE LOGS. sql/sql_select.cc: Fix for row numbers in EXPLAIN sql/sql_table.cc: Fix that USE_FRM works for all table types (without strange errors) sql/sql_yacc.yy: Removed compiler warnings. --- 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 1ab78e0320ba13d675f4bd1ed6d02bda1b7eadcd Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Apr 2003 21:15:52 -0400 Subject: [PATCH 108/399] Change to NetWare platform mods, per Monty mysys/my_pthread.c: Move #undef directive out of function --- 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 a34fc634658ce1b2ba63a45ee6bad4355a390439 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 10:32:56 +0300 Subject: [PATCH 109/399] Fix for openssl on Solaris Fix for grant bug with SELECT * include/my_global.h: Fix for openssl on Solaris sql/item_strfunc.cc: Fix for openssl on Solaris sql/sql_acl.cc: Indentation cleanup sql/sql_base.cc: Fix for grant bug with SELECT * sql/sql_parse.cc: Added comment tests/grant.pl: New grant test for SELECT * tests/grant.res: new grant results --- 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 546097b95f94e88bb8f0c8fd33223c9ee75705db Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 12:00:04 +0300 Subject: [PATCH 110/399] 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 8a05f5c7f497ff483f711dee55d3a1e7f5fe7e6a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 12:31:19 +0300 Subject: [PATCH 111/399] 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 7318eff7df63b9fff04728669cdbf55058da5c54 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 15:59:04 +0200 Subject: [PATCH 112/399] - Fixed some texi errors in internals.texi (still some more left) Docs/internals.texi: - fixed some structural errors --- 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 671e77a1f7bfbb51fdd2d9af361e226e89506048 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 16:05:27 +0200 Subject: [PATCH 113/399] - 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: - removed two EXPLAIN SELECT results because the output is nondeterministic (the result was different on 64bit platforms) mysql-test/t/innodb.test: - removed two EXPLAIN SELECT tests because the results are nondeterministic (the result was different on 64bit platforms) --- 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 68faea2eaa718bf3fe46e1c3f328346f7fd92f7e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 19:05:57 +0300 Subject: [PATCH 114/399] Fix to remove compiler warnings include/my_global.h: Fixed wrong #ifdef include/violite.h: Fix to remove compiler warning libmysqld/libmysqld.c: Fix to remove compiler warning myisam/sort.c: Fix to remove compiler warning myisammrg/myrg_extra.c: Fix to remove compiler warning vio/viossl.c: Fix to remove compiler warning --- 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 288e32a3cb73724459975592b6fd8bc9d58377ae Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 18:35:15 +0200 Subject: [PATCH 115/399] - 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 3d12a41d67481a04a218c38c1ac90a2abbe3828a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Apr 2003 00:14:17 +0300 Subject: [PATCH 116/399] Added missing dependency to VC++ project file Docs/internals.texi: Moved code guidelines first Fixed texinfo nodes & menus VC++Files/mysql.dsw: Added missing dependency --- 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 d098137155f184aaa25b9710d40854928276fcaf Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Apr 2003 00:15:18 +0200 Subject: [PATCH 117/399] 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: Logging to logging@openlogging.org accepted --- 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 66dc5cccea327b8a496bf5f6fb504cb7a78b53da Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 16:40:33 -0700 Subject: [PATCH 118/399] Updated PeterG's internals documentation per comments from Monty; added additional description of MySQL's three types of record formats. Docs/internals.texi: 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 df280ba4ca44d8ca8736a8ed2dfca5f63d401d6e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 17:01:19 -0700 Subject: [PATCH 119/399] 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 d4e65cc37142cf0daf74ace00fd505e010c88964 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 17:13:48 -0700 Subject: [PATCH 120/399] 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 1604f14e345753ec5a4ed4c00a965fe18ce596e5 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 17:20:26 -0700 Subject: [PATCH 121/399] 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 349029c1e9ec0fb714f67ec9f8b6900ae6a213e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 18:21:06 -0700 Subject: [PATCH 122/399] 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 8fd46234892fa44b8705b77498c6ecd607aae713 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2003 18:52:04 -0700 Subject: [PATCH 123/399] 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 3c9524233bf4cac12ebd2ac432f8ce4cfe1b5dbc Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Apr 2003 09:52:14 +0200 Subject: [PATCH 124/399] - 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) BitKeeper/etc/ignore: Added Docs/internals.html Docs/internals.pdf Docs/internals.txt Docs/internals_toc.html to the ignore list --- .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 38b70f0608fbd8f5c3f25fba16c2887611311803 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Apr 2003 14:13:22 +0300 Subject: [PATCH 125/399] code cleanup mysql-test/r/innodb.result: fixing result mysql-test/t/innodb.test: fixing test sql/sql_base.cc: committing a fix in order to pull new stuff --- 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 7e1b828a387c33bb36d10661a05d6c83d66d0c54 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Apr 2003 15:11:45 +0200 Subject: [PATCH 126/399] 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 4845193d431f7fb9588e2f17155e09561045defb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Apr 2003 18:24:33 +0300 Subject: [PATCH 127/399] 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 6db41f7793d81c08f042e0b1ff23e5d387b2976f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Apr 2003 10:15:09 +0300 Subject: [PATCH 128/399] Fix reference to not initialized memory Changed handing of priv_host to fix bug in FLUSH PRIVILEGES libmysqld/lib_sql.cc: Changed handing of priv_host to fix bug in FLUSH PRIVILEGES myisam/mi_rkey.c: Fix reference to not initialized memory sql/sql_acl.cc: Changed handing of priv_host to fix bug in FLUSH PRIVILEGES sql/sql_acl.h: Changed handing of priv_host to fix bug in FLUSH PRIVILEGES sql/sql_class.h: Changed handing of priv_host to fix bug in FLUSH PRIVILEGES sql/sql_parse.cc: Changed handing of priv_host to fix bug in FLUSH PRIVILEGES sql/unireg.h: 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 f84febcde61c3a7b3ba043d6545c8f71cadf4dce Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Apr 2003 11:27:13 +0200 Subject: [PATCH 129/399] - 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 fff9e2722bff6792ea2527249c1122dcc6bb629a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Apr 2003 11:30:45 +0200 Subject: [PATCH 130/399] - 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 7a5b5d51b289497e3c1b3b807d9019026d65b02f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Apr 2003 12:32:43 +0200 Subject: [PATCH 131/399] 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 edde138b30dc970931e16eca78255f18e7101c10 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Apr 2003 17:39:23 +0300 Subject: [PATCH 132/399] 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 a1e47ce8ee3746a6ecf05d8c4707bea914fa14be Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 May 2003 21:07:41 +0500 Subject: [PATCH 133/399] SCRUM common parts of libmysql.c and sql/mini_client.cc moved to sql-common/client.c names of functions now are same in both cases libmysql/libmysql.c: many parts moved to sql-common/client.c libmysqld/Makefile.am: superfluous files removed sql/mini_client.cc: most of the file moved to sql-common/client.c sql/mini_client.h: mc_ prefixes were deleted sql/repl_failsafe.cc: mc_ prefixes removed sql/slave.cc: _mc prefixes removed --- libmysql/libmysql.c | 2146 +------------------------------------- libmysqld/Makefile.am | 8 +- sql-common/client.c | 2299 +++++++++++++++++++++++++++++++++++++++++ sql/mini_client.cc | 1337 +----------------------- sql/mini_client.h | 50 +- sql/repl_failsafe.cc | 67 +- sql/slave.cc | 56 +- 7 files changed, 2401 insertions(+), 3562 deletions(-) create mode 100644 sql-common/client.c diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 2f64bb3bd44..72a3294347e 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -165,197 +165,14 @@ void STDCALL mysql_thread_end() #define reset_sigpipe(mysql) #endif +#define _libmysql_c +#include "../sql-common/client.c" + static MYSQL* spawn_init(MYSQL* parent, const char* host, unsigned int port, const char* user, const char* passwd); - -/**************************************************************************** - A modified version of connect(). my_connect() allows you to specify - a timeout value, in seconds, that we should wait until we - derermine we can't connect to a particular host. If timeout is 0, - my_connect() will behave exactly like connect(). - - Base version coded by Steve Bernacki, Jr. -*****************************************************************************/ - -my_bool my_connect(my_socket s, const struct sockaddr *name, - uint namelen, uint timeout) -{ -#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) - return connect(s, (struct sockaddr*) name, namelen) != 0; -#else - int flags, res, s_err; - SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); - fd_set sfds; - struct timeval tv; - time_t start_time, now_time; - - /* - If they passed us a timeout of zero, we should behave - exactly like the normal connect() call does. - */ - - if (timeout == 0) - return connect(s, (struct sockaddr*) name, namelen) != 0; - - flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ -#ifdef O_NONBLOCK - fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ -#endif - - res = connect(s, (struct sockaddr*) name, namelen); - s_err = errno; /* Save the error... */ - fcntl(s, F_SETFL, flags); - if ((res != 0) && (s_err != EINPROGRESS)) - { - errno = s_err; /* Restore it */ - return(1); - } - if (res == 0) /* Connected quickly! */ - return(0); - - /* - Otherwise, our connection is "in progress." We can use - the select() call to wait up to a specified period of time - for the connection to succeed. If select() returns 0 - (after waiting howevermany seconds), our socket never became - writable (host is probably unreachable.) Otherwise, if - select() returns 1, then one of two conditions exist: - - 1. An error occured. We use getsockopt() to check for this. - 2. The connection was set up sucessfully: getsockopt() will - return 0 as an error. - - Thanks goes to Andrew Gierth - who posted this method of timing out a connect() in - comp.unix.programmer on August 15th, 1997. - */ - - FD_ZERO(&sfds); - FD_SET(s, &sfds); - /* - select could be interrupted by a signal, and if it is, - the timeout should be adjusted and the select restarted - to work around OSes that don't restart select and - implementations of select that don't adjust tv upon - failure to reflect the time remaining - */ - start_time = time(NULL); - for (;;) - { - tv.tv_sec = (long) timeout; - tv.tv_usec = 0; -#if defined(HPUX10) && defined(THREAD) - if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) > 0) - break; -#else - if ((res = select(s+1, NULL, &sfds, NULL, &tv)) > 0) - break; -#endif - if (res == 0) /* timeout */ - return -1; - now_time=time(NULL); - timeout-= (uint) (now_time - start_time); - if (errno != EINTR || (int) timeout <= 0) - return 1; - } - - /* - select() returned something more interesting than zero, let's - see if we have any errors. If the next two statements pass, - we've got an open socket! - */ - - s_err=0; - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) - return(1); - - if (s_err) - { /* getsockopt could succeed */ - errno = s_err; - return(1); /* but return an error... */ - } - return (0); /* ok */ - -#endif -} - - -/* - Create a named pipe connection -*/ - -#ifdef __WIN__ - -HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, - char **arg_unix_socket) -{ - HANDLE hPipe=INVALID_HANDLE_VALUE; - char szPipeName [ 257 ]; - DWORD dwMode; - int i; - my_bool testing_named_pipes=0; - char *host= *arg_host, *unix_socket= *arg_unix_socket; - - if ( ! unix_socket || (unix_socket)[0] == 0x00) - unix_socket = mysql_unix_port; - if (!host || !strcmp(host,LOCAL_HOST)) - host=LOCAL_HOST_NAMEDPIPE; - - sprintf( szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); - DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", - host, unix_socket)); - - for (i=0 ; i < 100 ; i++) /* Don't retry forever */ - { - if ((hPipe = CreateFile(szPipeName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL )) != INVALID_HANDLE_VALUE) - break; - if (GetLastError() != ERROR_PIPE_BUSY) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - /* wait for for an other instance */ - if (! WaitNamedPipe(szPipeName, connect_timeout*1000) ) - { - net->last_errno=CR_NAMEDPIPEWAIT_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - } - if (hPipe == INVALID_HANDLE_VALUE) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; - if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) ) - { - CloseHandle( hPipe ); - net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */ - return (hPipe); -} -#endif - - /* Create new shared memory connection, return handler of connection @@ -559,212 +376,6 @@ err: } #endif - -/***************************************************************************** - Read a packet from server. Give error message if socket was down - or packet is an error message -*****************************************************************************/ - -ulong -net_safe_read(MYSQL *mysql) -{ - NET *net= &mysql->net; - ulong len=0; - init_sigpipe_variables - - /* Don't give sigpipe errors if the client doesn't want them */ - set_sigpipe(mysql); - if (net->vio != 0) - len=my_net_read(net); - reset_sigpipe(mysql); - - if (len == packet_error || len == 0) - { - DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", - vio_description(net->vio),len)); - end_server(mysql); - net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ? - CR_NET_PACKET_TOO_LARGE: - CR_SERVER_LOST); - strmov(net->last_error,ER(net->last_errno)); - return (packet_error); - } - if (net->read_pos[0] == 255) - { - if (len > 3) - { - char *pos=(char*) net->read_pos+1; - net->last_errno=uint2korr(pos); - pos+=2; - len-=2; - (void) strmake(net->last_error,(char*) pos, - min((uint) len,(uint) sizeof(net->last_error)-1)); - } - else - { - net->last_errno=CR_UNKNOWN_ERROR; - (void) strmov(net->last_error,ER(net->last_errno)); - } - DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno, - net->last_error)); - return(packet_error); - } - return len; -} - -static void free_rows(MYSQL_DATA *cur) -{ - if (cur) - { - free_root(&cur->alloc,MYF(0)); - my_free((gptr) cur,MYF(0)); - } -} - - -static my_bool -advanced_command(MYSQL *mysql, enum enum_server_command command, - const char *header, ulong header_length, - const char *arg, ulong arg_length, my_bool skip_check) -{ - NET *net= &mysql->net; - my_bool result= 1; - init_sigpipe_variables - - /* Don't give sigpipe errors if the client doesn't want them */ - set_sigpipe(mysql); - - if (mysql->net.vio == 0) - { /* Do reconnect if possible */ - if (mysql_reconnect(mysql)) - return 1; - } - if (mysql->status != MYSQL_STATUS_READY) - { - strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - return 1; - } - - mysql->net.last_error[0]=0; - mysql->net.last_errno=0; - mysql->info=0; - mysql->affected_rows= ~(my_ulonglong) 0; - net_clear(&mysql->net); /* Clear receive buffer */ - - if (net_write_command(net,(uchar) command, header, header_length, - arg, arg_length)) - { - DBUG_PRINT("error",("Can't send command to server. Error: %d", - socket_errno)); - if (net->last_errno == ER_NET_PACKET_TOO_LARGE) - { - net->last_errno=CR_NET_PACKET_TOO_LARGE; - strmov(net->last_error,ER(net->last_errno)); - goto end; - } - end_server(mysql); - if (mysql_reconnect(mysql)) - goto end; - if (net_write_command(net,(uchar) command, header, header_length, - arg, arg_length)) - { - net->last_errno=CR_SERVER_GONE_ERROR; - strmov(net->last_error,ER(net->last_errno)); - goto end; - } - } - result=0; - if (!skip_check) - result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ? - 1 : 0); - end: - reset_sigpipe(mysql); - return result; -} - - -my_bool -simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, - ulong length, my_bool skip_check) -{ - return advanced_command(mysql, command, NullS, 0, arg, length, skip_check); -} - - -static void free_old_query(MYSQL *mysql) -{ - DBUG_ENTER("free_old_query"); - if (mysql->fields) - free_root(&mysql->field_alloc,MYF(0)); - init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ - mysql->fields=0; - mysql->field_count=0; /* For API */ - DBUG_VOID_RETURN; -} - - -#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL) -struct passwd *getpwuid(uid_t); -char* getlogin(void); -#endif - - -#if defined(__NETWARE__) -/* default to "root" on NetWare */ -static void read_user_name(char *name) -{ - char *str=getenv("USER"); - strmake(name, str ? str : "UNKNOWN_USER", USERNAME_LENGTH); -} - -#elif !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__) && !defined(OS2) - -static void read_user_name(char *name) -{ - DBUG_ENTER("read_user_name"); - if (geteuid() == 0) - (void) strmov(name,"root"); /* allow use of surun */ - else - { -#ifdef HAVE_GETPWUID - struct passwd *skr; - const char *str; - if ((str=getlogin()) == NULL) - { - if ((skr=getpwuid(geteuid())) != NULL) - str=skr->pw_name; - else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) && - !(str=getenv("LOGIN"))) - str="UNKNOWN_USER"; - } - (void) strmake(name,str,USERNAME_LENGTH); -#elif HAVE_CUSERID - (void) cuserid(name); -#else - strmov(name,"UNKNOWN_USER"); -#endif - } - DBUG_VOID_RETURN; -} - -#else /* If MSDOS || VMS */ - -static void read_user_name(char *name) -{ - char *str=getenv("USER"); /* ODBC will send user variable */ - strmake(name,str ? str : "ODBC", USERNAME_LENGTH); -} - -#endif - -#ifdef __WIN__ -static my_bool is_NT(void) -{ - char *os=getenv("OS"); - return (os && !strcmp(os, "Windows_NT")) ? 1 : 0; -} -#endif - /* Expand wildcard to a sql string */ @@ -841,530 +452,6 @@ pipe_sig_handler(int sig __attribute__((unused))) #endif } - -/************************************************************************** - Shut down connection -**************************************************************************/ - -static void -end_server(MYSQL *mysql) -{ - DBUG_ENTER("end_server"); - if (mysql->net.vio != 0) - { - init_sigpipe_variables - DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); - set_sigpipe(mysql); - vio_delete(mysql->net.vio); - reset_sigpipe(mysql); - mysql->net.vio= 0; /* Marker */ - } - net_end(&mysql->net); - free_old_query(mysql); - DBUG_VOID_RETURN; -} - - -void STDCALL -mysql_free_result(MYSQL_RES *result) -{ - DBUG_ENTER("mysql_free_result"); - DBUG_PRINT("enter",("mysql_res: %lx",result)); - if (result) - { - if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT) - { - DBUG_PRINT("warning",("Not all rows in set where read; Ignoring rows")); - for (;;) - { - ulong pkt_len; - if ((pkt_len=net_safe_read(result->handle)) == packet_error) - break; - if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254) - break; /* End of data */ - } - result->handle->status=MYSQL_STATUS_READY; - } - free_rows(result->data); - if (result->fields) - free_root(&result->field_alloc,MYF(0)); - if (result->row) - my_free((gptr) result->row,MYF(0)); - my_free((gptr) result,MYF(0)); - } - DBUG_VOID_RETURN; -} - - -/**************************************************************************** - Get options from my.cnf -****************************************************************************/ - -static const char *default_options[]= -{ - "port","socket","compress","password","pipe", "timeout", "user", - "init-command", "host", "database", "debug", "return-found-rows", - "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", - "character-sets-dir", "default-character-set", "interactive-timeout", - "connect-timeout", "local-infile", "disable-local-infile", - "replication-probe", "enable-reads-from-master", "repl-parse-query", - "ssl-cipher", "max-allowed-packet", - "protocol", "shared-memory-base-name", - NullS -}; - -static TYPELIB option_types={array_elements(default_options)-1, - "options",default_options}; - -static int add_init_command(struct st_mysql_options *options, const char *cmd) -{ - char *tmp; - - if (!options->init_commands) - { - options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY), - MYF(MY_WME)); - init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO); - } - - if (!(tmp= my_strdup(cmd,MYF(MY_WME))) || - insert_dynamic(options->init_commands, (gptr)&tmp)) - { - my_free(tmp, MYF(MY_ALLOW_ZERO_PTR)); - return 1; - } - - return 0; -} - -static void mysql_read_default_options(struct st_mysql_options *options, - const char *filename,const char *group) -{ - int argc; - char *argv_buff[1],**argv; - const char *groups[3]; - DBUG_ENTER("mysql_read_default_options"); - DBUG_PRINT("enter",("file: %s group: %s",filename,group ? group :"NULL")); - - argc=1; argv=argv_buff; argv_buff[0]= (char*) "client"; - groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0; - - load_defaults(filename, groups, &argc, &argv); - if (argc != 1) /* If some default option */ - { - char **option=argv; - while (*++option) - { - /* DBUG_PRINT("info",("option: %s",option[0])); */ - if (option[0][0] == '-' && option[0][1] == '-') - { - char *end=strcend(*option,'='); - char *opt_arg=0; - if (*end) - { - opt_arg=end+1; - *end=0; /* Remove '=' */ - } - /* Change all '_' in variable name to '-' */ - for (end= *option ; *(end= strcend(end,'_')) ; ) - *end= '-'; - switch (find_type(*option+2,&option_types,2)) { - case 1: /* port */ - if (opt_arg) - options->port=atoi(opt_arg); - break; - case 2: /* socket */ - if (opt_arg) - { - my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR)); - options->unix_socket=my_strdup(opt_arg,MYF(MY_WME)); - } - break; - case 3: /* compress */ - options->compress=1; - options->client_flag|= CLIENT_COMPRESS; - break; - case 4: /* password */ - if (opt_arg) - { - my_free(options->password,MYF(MY_ALLOW_ZERO_PTR)); - options->password=my_strdup(opt_arg,MYF(MY_WME)); - } - break; - case 5: - options->protocol = MYSQL_PROTOCOL_PIPE; - case 20: /* connect_timeout */ - case 6: /* timeout */ - if (opt_arg) - options->connect_timeout=atoi(opt_arg); - break; - case 7: /* user */ - if (opt_arg) - { - my_free(options->user,MYF(MY_ALLOW_ZERO_PTR)); - options->user=my_strdup(opt_arg,MYF(MY_WME)); - } - break; - case 8: /* init-command */ - add_init_command(options,opt_arg); - break; - case 9: /* host */ - if (opt_arg) - { - my_free(options->host,MYF(MY_ALLOW_ZERO_PTR)); - options->host=my_strdup(opt_arg,MYF(MY_WME)); - } - break; - case 10: /* database */ - if (opt_arg) - { - my_free(options->db,MYF(MY_ALLOW_ZERO_PTR)); - options->db=my_strdup(opt_arg,MYF(MY_WME)); - } - break; - case 11: /* debug */ - mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace"); - break; - case 12: /* return-found-rows */ - options->client_flag|=CLIENT_FOUND_ROWS; - break; -#ifdef HAVE_OPENSSL - case 13: /* ssl_key */ - my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR)); - options->ssl_key = my_strdup(opt_arg, MYF(MY_WME)); - break; - case 14: /* ssl_cert */ - my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); - options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME)); - break; - case 15: /* ssl_ca */ - my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); - options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME)); - break; - case 16: /* ssl_capath */ - my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME)); - break; -#else - case 13: /* Ignore SSL options */ - case 14: - case 15: - case 16: - break; -#endif /* HAVE_OPENSSL */ - case 17: /* charset-lib */ - my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR)); - options->charset_dir = my_strdup(opt_arg, MYF(MY_WME)); - break; - case 18: - my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR)); - options->charset_name = my_strdup(opt_arg, MYF(MY_WME)); - break; - case 19: /* Interactive-timeout */ - options->client_flag|= CLIENT_INTERACTIVE; - break; - case 21: - if (!opt_arg || atoi(opt_arg) != 0) - options->client_flag|= CLIENT_LOCAL_FILES; - else - options->client_flag&= ~CLIENT_LOCAL_FILES; - break; - case 22: - options->client_flag&= CLIENT_LOCAL_FILES; - break; - case 23: /* replication probe */ - options->rpl_probe= 1; - break; - case 24: /* enable-reads-from-master */ - options->no_master_reads= 0; - break; - case 25: /* repl-parse-query */ - options->rpl_parse= 1; - break; - case 27: - options->max_allowed_packet= atoi(opt_arg); - break; - case 28: /* protocol */ - if ((options->protocol = find_type(opt_arg, &sql_protocol_typelib,0)) == ~(ulong) 0) - { - fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg); - exit(1); - } - break; - case 29: /* shared_memory_base_name */ -#ifdef HAVE_SMEM - if (options->shared_memory_base_name != def_shared_memory_base_name) - my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); - options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); -#endif - break; - default: - DBUG_PRINT("warning",("unknown option: %s",option[0])); - } - } - } - } - free_defaults(argv); - DBUG_VOID_RETURN; -} - - -/*************************************************************************** - Change field rows to field structs -***************************************************************************/ - -static MYSQL_FIELD * -unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, - my_bool default_value, uint server_capabilities) -{ - MYSQL_ROWS *row; - MYSQL_FIELD *field,*result; - ulong lengths[8]; /* Max of fields */ - DBUG_ENTER("unpack_fields"); - - field=result=(MYSQL_FIELD*) alloc_root(alloc, - (uint) sizeof(MYSQL_FIELD)*fields); - if (!result) - { - free_rows(data); /* Free old data */ - DBUG_RETURN(0); - } - bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields); - if (server_capabilities & CLIENT_PROTOCOL_41) - { - /* server is 4.1, and returns the new field result format */ - for (row=data->data; row ; row = row->next,field++) - { - uchar *pos; - fetch_lengths(&lengths[0], row->data, default_value ? 7 : 6); - field->db = strdup_root(alloc,(char*) row->data[0]); - field->table = strdup_root(alloc,(char*) row->data[1]); - field->org_table= strdup_root(alloc,(char*) row->data[2]); - field->name = strdup_root(alloc,(char*) row->data[3]); - field->org_name = strdup_root(alloc,(char*) row->data[4]); - - field->db_length= lengths[0]; - field->table_length= lengths[1]; - field->org_table_length= lengths[2]; - field->name_length= lengths[3]; - field->org_name_length= lengths[4]; - - /* Unpack fixed length parts */ - pos= (uchar*) row->data[5]; - field->charsetnr= uint2korr(pos); - field->length= (uint) uint3korr(pos+2); - field->type= (enum enum_field_types) pos[5]; - field->flags= uint2korr(pos+6); - field->decimals= (uint) pos[8]; - - if (INTERNAL_NUM_FIELD(field)) - field->flags|= NUM_FLAG; - if (default_value && row->data[6]) - { - field->def=strdup_root(alloc,(char*) row->data[6]); - field->def_length= lengths[6]; - } - else - field->def=0; - field->max_length= 0; - } - } -#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL - else - { - /* old protocol, for backward compatibility */ - for (row=data->data; row ; row = row->next,field++) - { - fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5); - field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]); - field->name= strdup_root(alloc,(char*) row->data[1]); - field->length= (uint) uint3korr(row->data[2]); - field->type= (enum enum_field_types) (uchar) row->data[3][0]; - - field->org_table_length= field->table_length= lengths[0]; - field->name_length= lengths[1]; - - if (server_capabilities & CLIENT_LONG_FLAG) - { - field->flags= uint2korr(row->data[4]); - field->decimals=(uint) (uchar) row->data[4][2]; - } - else - { - field->flags= (uint) (uchar) row->data[4][0]; - field->decimals=(uint) (uchar) row->data[4][1]; - } - if (INTERNAL_NUM_FIELD(field)) - field->flags|= NUM_FLAG; - if (default_value && row->data[5]) - { - field->def=strdup_root(alloc,(char*) row->data[5]); - field->def_length= lengths[5]; - } - else - field->def=0; - field->max_length= 0; - } - } -#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */ - free_rows(data); /* Free old data */ - DBUG_RETURN(result); -} - - -/* Read all rows (fields or data) from server */ - -static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - uint fields) -{ - uint field; - ulong pkt_len; - ulong len; - uchar *cp; - char *to, *end_to; - MYSQL_DATA *result; - MYSQL_ROWS **prev_ptr,*cur; - NET *net = &mysql->net; - DBUG_ENTER("read_rows"); - - if ((pkt_len= net_safe_read(mysql)) == packet_error) - DBUG_RETURN(0); - if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), - MYF(MY_WME | MY_ZEROFILL)))) - { - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - DBUG_RETURN(0); - } - init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ - result->alloc.min_malloc=sizeof(MYSQL_ROWS); - prev_ptr= &result->data; - result->rows=0; - result->fields=fields; - - /* - The last EOF packet is either a single 254 character or (in MySQL 4.1) - 254 followed by 1-7 status bytes. - - This doesn't conflict with normal usage of 254 which stands for a - string where the length of the string is 8 bytes. (see net_field_length()) - */ - - while (*(cp=net->read_pos) != 254 || pkt_len >= 8) - { - result->rows++; - if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc, - sizeof(MYSQL_ROWS))) || - !(cur->data= ((MYSQL_ROW) - alloc_root(&result->alloc, - (fields+1)*sizeof(char *)+pkt_len)))) - { - free_rows(result); - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - DBUG_RETURN(0); - } - *prev_ptr=cur; - prev_ptr= &cur->next; - to= (char*) (cur->data+fields+1); - end_to=to+pkt_len-1; - for (field=0 ; field < fields ; field++) - { - if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) - { /* null field */ - cur->data[field] = 0; - } - else - { - cur->data[field] = to; - if (len > (ulong) (end_to - to)) - { - free_rows(result); - net->last_errno=CR_MALFORMED_PACKET; - strmov(net->last_error,ER(net->last_errno)); - DBUG_RETURN(0); - } - memcpy(to,(char*) cp,len); to[len]=0; - to+=len+1; - cp+=len; - if (mysql_fields) - { - if (mysql_fields[field].max_length < len) - mysql_fields[field].max_length=len; - } - } - } - cur->data[field]=to; /* End of last field */ - if ((pkt_len=net_safe_read(mysql)) == packet_error) - { - free_rows(result); - DBUG_RETURN(0); - } - } - *prev_ptr=0; /* last pointer is null */ - if (pkt_len > 1) /* MySQL 4.1 protocol */ - { - mysql->warning_count= uint2korr(cp+1); - DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count)); - } - DBUG_PRINT("exit",("Got %d rows",result->rows)); - DBUG_RETURN(result); -} - - -/* - Read one row. Uses packet buffer as storage for fields. - When next packet is read, the previous field values are destroyed -*/ - - -static int -read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) -{ - uint field; - ulong pkt_len,len; - uchar *pos, *end_pos; - uchar *prev_pos; - - if ((pkt_len=net_safe_read(mysql)) == packet_error) - return -1; - if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) - { - if (pkt_len > 1) /* MySQL 4.1 protocol */ - mysql->warning_count= uint2korr(mysql->net.read_pos+1); - return 1; /* End of data */ - } - prev_pos= 0; /* allowed to write at packet[-1] */ - pos=mysql->net.read_pos; - end_pos=pos+pkt_len; - for (field=0 ; field < fields ; field++) - { - if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) - { /* null field */ - row[field] = 0; - *lengths++=0; - } - else - { - if (len > (ulong) (end_pos - pos)) - { - mysql->net.last_errno=CR_UNKNOWN_ERROR; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - return -1; - } - row[field] = (char*) pos; - pos+=len; - *lengths++=len; - } - if (prev_pos) - *prev_pos=0; /* Terminate prev field */ - prev_pos= pos; - } - row[field]=(char*) prev_pos+1; /* End of last field */ - *prev_pos=0; /* Terminate last field */ - return 0; -} - /* perform query on master */ my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q, unsigned long length) @@ -1660,108 +747,6 @@ STDCALL mysql_rpl_query_type(const char* q, int len) return MYSQL_RPL_MASTER; /* By default, send to master */ } - -/**************************************************************************** - Init MySQL structure or allocate one -****************************************************************************/ - -MYSQL * STDCALL -mysql_init(MYSQL *mysql) -{ - mysql_once_init(); - if (!mysql) - { - if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) - return 0; - mysql->free_me=1; - } - else - bzero((char*) (mysql),sizeof(*(mysql))); - mysql->options.connect_timeout=CONNECT_TIMEOUT; - mysql->last_used_con = mysql->next_slave = mysql->master = mysql; - - /* - By default, we are a replication pivot. The caller must reset it - after we return if this is not the case. - */ - mysql->rpl_pivot = 1; -#if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__) - if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) - (void) signal(SIGPIPE,pipe_sig_handler); -#endif - -/* - Only enable LOAD DATA INFILE by default if configured with - --enable-local-infile -*/ -#ifdef ENABLED_LOCAL_INFILE - mysql->options.client_flag|= CLIENT_LOCAL_FILES; -#endif -#ifdef HAVE_SMEM - mysql->options.shared_memory_base_name=(char*)def_shared_memory_base_name; -#endif - return mysql; -} - - -/* - Initialize the MySQL library - - SYNOPSIS - mysql_once_init() - - NOTES - Can't be static on NetWare - This function is called by mysql_init() and indirectly called - by mysql_query(), so one should never have to call this from an - outside program. -*/ - -void mysql_once_init(void) -{ - if (!mysql_client_init) - { - mysql_client_init=1; - org_my_init_done=my_init_done; - my_init(); /* Will init threads */ - init_client_errs(); - if (!mysql_port) - { - mysql_port = MYSQL_PORT; -#ifndef MSDOS - { - struct servent *serv_ptr; - char *env; - if ((serv_ptr = getservbyname("mysql", "tcp"))) - mysql_port = (uint) ntohs((ushort) serv_ptr->s_port); - if ((env = getenv("MYSQL_TCP_PORT"))) - mysql_port =(uint) atoi(env); - } -#endif - } - if (!mysql_unix_port) - { - char *env; -#ifdef __WIN__ - mysql_unix_port = (char*) MYSQL_NAMEDPIPE; -#else - mysql_unix_port = (char*) MYSQL_UNIX_ADDR; -#endif - if ((env = getenv("MYSQL_UNIX_PORT"))) - mysql_unix_port = env; - } - mysql_debug(NullS); -#if defined(SIGPIPE) && !defined(THREAD) && !defined(__WIN__) - (void) signal(SIGPIPE,SIG_IGN); -#endif - } -#ifdef THREAD - else - my_thread_init(); /* Init if new thread */ -#endif -} - - /* Fill in SSL part of MYSQL structure and set 'use_ssl' flag. NB! Errors are not reported until you do mysql_real_connect. @@ -1787,101 +772,6 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , return 0; } - -/* - Free strings in the SSL structure and clear 'use_ssl' flag. - NB! Errors are not reported until you do mysql_real_connect. -*/ - -#ifdef HAVE_OPENSSL -static void -mysql_ssl_free(MYSQL *mysql __attribute__((unused))) -{ - my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.ssl_key = 0; - mysql->options.ssl_cert = 0; - mysql->options.ssl_ca = 0; - mysql->options.ssl_capath = 0; - mysql->options.ssl_cipher= 0; - mysql->options.use_ssl = FALSE; - mysql->connector_fd = 0; -} -#endif /* HAVE_OPENSSL */ - - -/* - Handle password authentication -*/ - -static my_bool mysql_autenticate(MYSQL *mysql, const char *passwd) -{ - ulong pkt_length; - NET *net= &mysql->net; - char buff[SCRAMBLE41_LENGTH]; - char password_hash[SCRAMBLE41_LENGTH]; /* Used for storage of stage1 hash */ - - /* We shall only query server if it expect us to do so */ - if ((pkt_length=net_safe_read(mysql)) == packet_error) - goto error; - - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - /* - This should always happen with new server unless empty password - OK/Error packets have zero as the first char - */ - if (pkt_length == 24 && net->read_pos[0]) - { - /* Old passwords will have '*' at the first byte of hash */ - if (net->read_pos[0] != '*') - { - /* Build full password hash as it is required to decode scramble */ - password_hash_stage1(buff, passwd); - /* Store copy as we'll need it later */ - memcpy(password_hash,buff,SCRAMBLE41_LENGTH); - /* Finally hash complete password using hash we got from server */ - password_hash_stage2(password_hash,(const char*) net->read_pos); - /* Decypt and store scramble 4 = hash for stage2 */ - password_crypt((const char*) net->read_pos+4,mysql->scramble_buff, - password_hash, SCRAMBLE41_LENGTH); - mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; - /* Encode scramble with password. Recycle buffer */ - password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH); - } - else - { - /* Create password to decode scramble */ - create_key_from_old_password(passwd,password_hash); - /* Decypt and store scramble 4 = hash for stage2 */ - password_crypt((const char*) net->read_pos+4,mysql->scramble_buff, - password_hash, SCRAMBLE41_LENGTH); - mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; - /* Finally scramble decoded scramble with password */ - scramble(buff, mysql->scramble_buff, passwd,0); - } - /* Write second package of authentication */ - if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - /* Read what server thinks about out new auth message report */ - if (net_safe_read(mysql) == packet_error) - goto error; - } - } - return 0; - -error: - return 1; -} - /************************************************************************** Connect to sql server If host == 0 then use localhost @@ -1906,601 +796,6 @@ mysql_connect(MYSQL *mysql,const char *host, } #endif - -/* - Note that the mysql argument must be initialized with mysql_init() - before calling mysql_real_connect ! -*/ - -MYSQL * STDCALL -mysql_real_connect(MYSQL *mysql,const char *host, const char *user, - const char *passwd, const char *db, - uint port, const char *unix_socket,ulong client_flag) -{ - char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; - char *end,*host_info,*charset_name; - my_socket sock; - uint32 ip_addr; - struct sockaddr_in sock_addr; - ulong pkt_length; - NET *net= &mysql->net; -#ifdef __WIN__ - HANDLE hPipe=INVALID_HANDLE_VALUE; -#endif -#ifdef HAVE_SYS_UN_H - struct sockaddr_un UNIXaddr; -#endif - init_sigpipe_variables - DBUG_ENTER("mysql_real_connect"); - LINT_INIT(host_info); - - DBUG_PRINT("enter",("host: %s db: %s user: %s", - host ? host : "(Null)", - db ? db : "(Null)", - user ? user : "(Null)")); - - /* Don't give sigpipe errors if the client doesn't want them */ - set_sigpipe(mysql); - net->vio = 0; /* If something goes wrong */ - /* use default options */ - if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) - { - mysql_read_default_options(&mysql->options, - (mysql->options.my_cnf_file ? - mysql->options.my_cnf_file : "my"), - mysql->options.my_cnf_group); - my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.my_cnf_file=mysql->options.my_cnf_group=0; - } - - /* Some empty-string-tests are done because of ODBC */ - if (!host || !host[0]) - host=mysql->options.host; - if (!user || !user[0]) - user=mysql->options.user; - if (!passwd) - { - passwd=mysql->options.password; -#ifndef DONT_USE_MYSQL_PWD - if (!passwd) - passwd=getenv("MYSQL_PWD"); /* get it from environment */ -#endif - } - if (!db || !db[0]) - db=mysql->options.db; - if (!port) - port=mysql->options.port; - if (!unix_socket) - unix_socket=mysql->options.unix_socket; - - mysql->reconnect=1; /* Reconnect as default */ - mysql->server_status=SERVER_STATUS_AUTOCOMMIT; - - /* - Grab a socket and connect it to the server - */ -#if defined(HAVE_SMEM) - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && - (!host || !strcmp(host,LOCAL_HOST))) - { - if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) == - INVALID_HANDLE_VALUE) - { - DBUG_PRINT("error", - ("host: '%s' socket: '%s' shared memory: %s have_tcpip: %d", - host ? host : "", - unix_socket ? unix_socket : "", - (int) mysql->options.shared_memory_base_name, - (int) have_tcpip)); - if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) - goto error; - /* Try also with PIPE or TCP/IP */ - } - else - { - mysql->options.protocol=MYSQL_PROTOCOL_MEMORY; - sock=0; - unix_socket = 0; - host=mysql->options.shared_memory_base_name; - host_info=(char*) ER(CR_SHARED_MEMORY_CONNECTION); - } - } else -#endif /* HAVE_SMEM */ -#if defined(HAVE_SYS_UN_H) - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&& - (!host || !strcmp(host,LOCAL_HOST)) && - (unix_socket || mysql_unix_port)) - { - host=LOCAL_HOST; - if (!unix_socket) - unix_socket=mysql_unix_port; - host_info=(char*) ER(CR_LOCALHOST_CONNECTION); - DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); - if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) - { - net->last_errno=CR_SOCKET_CREATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),socket_errno); - goto error; - } - net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); - bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); - UNIXaddr.sun_family = AF_UNIX; - strmov(UNIXaddr.sun_path, unix_socket); - if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), - mysql->options.connect_timeout)) - { - DBUG_PRINT("error",("Got error %d on connect to local server", - socket_errno)); - net->last_errno=CR_CONNECTION_ERROR; - sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); - goto error; - } - else - mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; - } - else -#elif defined(__WIN__) - { - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&& - ((unix_socket || !host && is_NT() || - host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||! have_tcpip))&& - (!net->vio)) - { - sock=0; - if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, - (char**) &host, (char**) &unix_socket)) == - INVALID_HANDLE_VALUE) - { - DBUG_PRINT("error", - ("host: '%s' socket: '%s' have_tcpip: %d", - host ? host : "", - unix_socket ? unix_socket : "", - (int) have_tcpip)); - if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || - (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || - (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) - goto error; - /* Try also with TCP/IP */ - } - else - { - net->vio=vio_new_win32pipe(hPipe); - sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host, - unix_socket); - } - } - } -#endif - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_TCP)&&(!net->vio)) - { - unix_socket=0; /* This is not used */ - if (!port) - port=mysql_port; - if (!host) - host=LOCAL_HOST; - sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); - DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); - /* _WIN64 ; Assume that the (int) range is enough for socket() */ - if ((sock = (my_socket) socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR) - { - net->last_errno=CR_IPSOCK_ERROR; - sprintf(net->last_error,ER(net->last_errno),socket_errno); - goto error; - } - net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE); - bzero((char*) &sock_addr,sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - - /* - The server name may be a host name or IP address - */ - - if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) - { - memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); - } - else - { - int tmp_errno; - struct hostent tmp_hostent,*hp; - char buff2[GETHOSTBYNAME_BUFF_SIZE]; - hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), - &tmp_errno); - if (!hp) - { - my_gethostbyname_r_free(); - net->last_errno=CR_UNKNOWN_HOST; - sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); - goto error; - } - memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); - my_gethostbyname_r_free(); - } - sock_addr.sin_port = (ushort) htons((ushort) port); - if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), - mysql->options.connect_timeout)) - { - DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, - host)); - net->last_errno= CR_CONN_HOST_ERROR; - sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); - goto error; - } - } - else if (!net->vio) - { - DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); - net->last_errno= CR_CONN_UNKNOW_PROTOCOL; - sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL)); - goto error; - } - - if (!net->vio || my_net_init(net, net->vio)) - { - vio_delete(net->vio); - net->vio = 0; - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - vio_keepalive(net->vio,TRUE); - - /* Get version info */ - mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ - if (mysql->options.connect_timeout && - vio_poll_read(net->vio, mysql->options.connect_timeout)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - if ((pkt_length=net_safe_read(mysql)) == packet_error) - goto error; - - /* Check if version of protocol matches current one */ - - mysql->protocol_version= net->read_pos[0]; - DBUG_DUMP("packet",(char*) net->read_pos,10); - DBUG_PRINT("info",("mysql protocol version %d, server=%d", - PROTOCOL_VERSION, mysql->protocol_version)); - if (mysql->protocol_version != PROTOCOL_VERSION) - { - net->last_errno= CR_VERSION_ERROR; - sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, - PROTOCOL_VERSION); - goto error; - } - end=strend((char*) net->read_pos+1); - mysql->thread_id=uint4korr(end+1); - end+=5; - strmake(mysql->scramble_buff,end,8); - end+=9; - if (pkt_length >= (uint) (end+1 - (char*) net->read_pos)) - mysql->server_capabilities=uint2korr(end); - if (pkt_length >= (uint) (end+18 - (char*) net->read_pos)) - { - /* New protocol with 16 bytes to describe server characteristics */ - mysql->server_language=end[2]; - mysql->server_status=uint2korr(end+3); - } - - /* Set character set */ - if ((charset_name=mysql->options.charset_name)) - { - const char *save=charsets_dir; - if (mysql->options.charset_dir) - charsets_dir=mysql->options.charset_dir; - mysql->charset=get_charset_by_name(mysql->options.charset_name, - MYF(MY_WME)); - charsets_dir=save; - } - else if (mysql->server_language) - { - charset_name=charset_name_buff; - sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */ - if (!(mysql->charset = - get_charset((uint8) mysql->server_language, MYF(0)))) - mysql->charset = default_charset_info; /* shouldn't be fatal */ - } - else - mysql->charset=default_charset_info; - - if (!mysql->charset) - { - net->last_errno=CR_CANT_READ_CHARSET; - if (mysql->options.charset_dir) - sprintf(net->last_error,ER(net->last_errno), - charset_name ? charset_name : "unknown", - mysql->options.charset_dir); - else - { - char cs_dir_name[FN_REFLEN]; - get_charsets_dir(cs_dir_name); - sprintf(net->last_error,ER(net->last_errno), - charset_name ? charset_name : "unknown", - cs_dir_name); - } - goto error; - } - - /* Save connection information */ - if (!user) user=""; - if (!passwd) passwd=""; - if (!my_multi_malloc(MYF(0), - &mysql->host_info, (uint) strlen(host_info)+1, - &mysql->host, (uint) strlen(host)+1, - &mysql->unix_socket,unix_socket ? - (uint) strlen(unix_socket)+1 : (uint) 1, - &mysql->server_version, - (uint) (end - (char*) net->read_pos), - NullS) || - !(mysql->user=my_strdup(user,MYF(0))) || - !(mysql->passwd=my_strdup(passwd,MYF(0)))) - { - strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); - goto error; - } - strmov(mysql->host_info,host_info); - strmov(mysql->host,host); - if (unix_socket) - strmov(mysql->unix_socket,unix_socket); - else - mysql->unix_socket=0; - strmov(mysql->server_version,(char*) net->read_pos+1); - mysql->port=port; - client_flag|=mysql->options.client_flag; - - /* Send client information for access check */ - client_flag|=CLIENT_CAPABILITIES; - -#ifdef HAVE_OPENSSL - if (mysql->options.ssl_key || mysql->options.ssl_cert || - mysql->options.ssl_ca || mysql->options.ssl_capath || - mysql->options.ssl_cipher) - mysql->options.use_ssl= 1; - if (mysql->options.use_ssl) - client_flag|=CLIENT_SSL; -#endif /* HAVE_OPENSSL */ - if (db) - client_flag|=CLIENT_CONNECT_WITH_DB; - /* Remove options that server doesn't support */ - client_flag= ((client_flag & - ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) | - (client_flag & mysql->server_capabilities)); - -#ifndef HAVE_COMPRESS - client_flag&= ~CLIENT_COMPRESS; -#endif - - if (client_flag & CLIENT_PROTOCOL_41) - { - /* 4.1 server and 4.1 client has a 4 byte option flag */ - int4store(buff,client_flag); - int4store(buff+4,max_allowed_packet); - end= buff+8; - } - else - { - int2store(buff,client_flag); - int3store(buff+2,max_allowed_packet); - end= buff+5; - } - mysql->client_flag=client_flag; - -#ifdef HAVE_OPENSSL - /* - Oops.. are we careful enough to not send ANY information without - encryption? - */ - if (client_flag & CLIENT_SSL) - { - struct st_mysql_options *options= &mysql->options; - if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - /* Do the SSL layering. */ - if (!(mysql->connector_fd= - (gptr) new_VioSSLConnectorFd(options->ssl_key, - options->ssl_cert, - options->ssl_ca, - options->ssl_capath, - options->ssl_cipher))) - { - net->last_errno= CR_SSL_CONNECTION_ERROR; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - DBUG_PRINT("info", ("IO layer change in progress...")); - if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), - mysql->net.vio, (long) (mysql->options.connect_timeout))) - { - net->last_errno= CR_SSL_CONNECTION_ERROR; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - DBUG_PRINT("info", ("IO layer change done!")); - } -#endif /* HAVE_OPENSSL */ - - DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu", - mysql->server_version,mysql->server_capabilities, - mysql->server_status, client_flag)); - /* This needs to be changed as it's not useful with big packets */ - if (user && user[0]) - strmake(end,user,32); /* Max user name */ - else - read_user_name((char*) end); - /* We have to handle different version of handshake here */ -#ifdef _CUSTOMCONFIG_ -#include "_cust_libmysql.h"; -#endif - DBUG_PRINT("info",("user: %s",end)); - /* - We always start with old type handshake the only difference is message sent - If server handles secure connection type we'll not send the real scramble - */ - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - if (passwd[0]) - { - /* Prepare false scramble */ - end=strend(end)+1; - bfill(end, SCRAMBLE_LENGTH, 'x'); - end+=SCRAMBLE_LENGTH; - *end=0; - } - else /* For empty password*/ - { - end=strend(end)+1; - *end=0; /* Store zero length scramble */ - } - } - else - { - /* - Real scramble is only sent to old servers. This can be blocked - by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); - */ - end=scramble(strend(end)+1, mysql->scramble_buff, passwd, - (my_bool) (mysql->protocol_version == 9)); - } - /* Add database if needed */ - if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) - { - end=strmake(end+1,db,NAME_LEN); - mysql->db=my_strdup(db,MYF(MY_WME)); - db=0; - } - /* Write authentication package */ - if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - - if (mysql_autenticate(mysql, passwd)) - goto error; - - if (client_flag & CLIENT_COMPRESS) /* We will use compression */ - net->compress=1; - if (mysql->options.max_allowed_packet) - net->max_packet_size= mysql->options.max_allowed_packet; - if (db && mysql_select_db(mysql,db)) - goto error; - - if (mysql->options.init_commands) - { - DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; - char **ptr= (char**)init_commands->buffer; - char **end= ptr + init_commands->elements; - - my_bool reconnect=mysql->reconnect; - mysql->reconnect=0; - - for (; ptrfields) - { - if (!(res= mysql_use_result(mysql))) - goto error; - mysql_free_result(res); - } - } - - mysql->reconnect=reconnect; - } - - if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) - goto error; - - DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); - reset_sigpipe(mysql); - DBUG_RETURN(mysql); - -error: - reset_sigpipe(mysql); - DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); - { - /* Free alloced memory */ - my_bool free_me=mysql->free_me; - end_server(mysql); - mysql->free_me=0; - mysql_close(mysql); - mysql->free_me=free_me; - } - DBUG_RETURN(0); -} - - -/* needed when we move MYSQL structure to a different address */ - -static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) -{ - MYSQL *tmp, *tmp_prev; - if (mysql->master == old_mysql) - mysql->master = mysql; - if (mysql->last_used_con == old_mysql) - mysql->last_used_con = mysql; - if (mysql->last_used_slave == old_mysql) - mysql->last_used_slave = mysql; - for (tmp_prev = mysql, tmp = mysql->next_slave; - tmp != old_mysql;tmp = tmp->next_slave) - { - tmp_prev = tmp; - } - tmp_prev->next_slave = mysql; -} - - -static my_bool mysql_reconnect(MYSQL *mysql) -{ - MYSQL tmp_mysql; - DBUG_ENTER("mysql_reconnect"); - - if (!mysql->reconnect || - (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) - { - /* Allow reconnect next time */ - mysql->server_status&= ~SERVER_STATUS_IN_TRANS; - mysql->net.last_errno=CR_SERVER_GONE_ERROR; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - DBUG_RETURN(1); - } - mysql_init(&tmp_mysql); - tmp_mysql.options=mysql->options; - bzero((char*) &mysql->options,sizeof(mysql->options)); - tmp_mysql.rpl_pivot = mysql->rpl_pivot; - if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, - mysql->db, mysql->port, mysql->unix_socket, - mysql->client_flag)) - { - mysql->net.last_errno= tmp_mysql.net.last_errno; - strmov(mysql->net.last_error, tmp_mysql.net.last_error); - DBUG_RETURN(1); - } - tmp_mysql.free_me=mysql->free_me; - mysql->free_me=0; - mysql_close(mysql); - *mysql=tmp_mysql; - mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ - net_clear(&mysql->net); - mysql->affected_rows= ~(my_ulonglong) 0; - DBUG_RETURN(0); -} - - /************************************************************************** Change user and database **************************************************************************/ @@ -2569,111 +864,6 @@ error: DBUG_RETURN(1); } - -/************************************************************************** - Set current database -**************************************************************************/ - -int STDCALL -mysql_select_db(MYSQL *mysql, const char *db) -{ - int error; - DBUG_ENTER("mysql_select_db"); - DBUG_PRINT("enter",("db: '%s'",db)); - - if ((error=simple_command(mysql,COM_INIT_DB,db,(ulong) strlen(db),0))) - DBUG_RETURN(error); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); - mysql->db=my_strdup(db,MYF(MY_WME)); - DBUG_RETURN(0); -} - - -/************************************************************************* - Send a QUIT to the server and close the connection - If handle is alloced by mysql connect free it. -*************************************************************************/ - -void STDCALL -mysql_close(MYSQL *mysql) -{ - DBUG_ENTER("mysql_close"); - if (mysql) /* Some simple safety */ - { - if (mysql->net.vio != 0) - { - free_old_query(mysql); - mysql->status=MYSQL_STATUS_READY; /* Force command */ - mysql->reconnect=0; - simple_command(mysql,COM_QUIT,NullS,0,1); - end_server(mysql); /* Sets mysql->net.vio= 0 */ - } - my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); - if (mysql->options.init_commands) - { - DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; - char **ptr= (char**)init_commands->buffer; - char **end= ptr + init_commands->elements; - for (; ptroptions.shared_memory_base_name != def_shared_memory_base_name) - my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); -#endif /* HAVE_SMEM */ - /* Clear pointers for better safety */ - mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; - bzero((char*) &mysql->options,sizeof(mysql->options)); - - /* free/close slave list */ - if (mysql->rpl_pivot) - { - MYSQL* tmp; - for (tmp = mysql->next_slave; tmp != mysql; ) - { - /* trick to avoid following freed pointer */ - MYSQL* tmp1 = tmp->next_slave; - mysql_close(tmp); - tmp = tmp1; - } - mysql->rpl_pivot=0; - } - if (mysql->stmts) - { - /* Free any open prepared statements */ - LIST *element, *next_element; - for (element= mysql->stmts; element; element= next_element) - { - next_element= element->next; - stmt_close((MYSQL_STMT *)element->data, 0); - } - } - if (mysql != mysql->master) - mysql_close(mysql->master); - if (mysql->free_me) - my_free((gptr) mysql,MYF(0)); - } - DBUG_VOID_RETURN; -} - - /************************************************************************** Do a query. If query returned rows, free old rows. Read data by mysql_store_result or by repeat call of mysql_fetch_row @@ -2746,225 +936,6 @@ STDCALL mysql_add_slave(MYSQL* mysql, const char* host, return 0; } - -/* - Send the query and return so we can do something else. - Needs to be followed by mysql_read_query_result() when we want to - finish processing it. -*/ - -int STDCALL -mysql_send_query(MYSQL* mysql, const char* query, ulong length) -{ - DBUG_ENTER("mysql_send_query"); - DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d", - mysql->options.rpl_parse, mysql->rpl_pivot)); - - if (mysql->options.rpl_parse && mysql->rpl_pivot) - { - switch (mysql_rpl_query_type(query, length)) { - case MYSQL_RPL_MASTER: - DBUG_RETURN(mysql_master_send_query(mysql, query, length)); - case MYSQL_RPL_SLAVE: - DBUG_RETURN(mysql_slave_send_query(mysql, query, length)); - case MYSQL_RPL_ADMIN: - break; /* fall through */ - } - } - - mysql->last_used_con = mysql; - DBUG_RETURN(simple_command(mysql, COM_QUERY, query, length, 1)); -} - - -my_bool STDCALL mysql_read_query_result(MYSQL *mysql) -{ - uchar *pos; - ulong field_count; - MYSQL_DATA *fields; - ulong length; - DBUG_ENTER("mysql_read_query_result"); - - /* - Read from the connection which we actually used, which - could differ from the original connection if we have slaves - */ - mysql = mysql->last_used_con; - - if ((length = net_safe_read(mysql)) == packet_error) - DBUG_RETURN(1); - free_old_query(mysql); /* Free old result */ -get_info: - pos=(uchar*) mysql->net.read_pos; - if ((field_count= net_field_length(&pos)) == 0) - { - mysql->affected_rows= net_field_length_ll(&pos); - mysql->insert_id= net_field_length_ll(&pos); - if (protocol_41(mysql)) - { - mysql->server_status=uint2korr(pos); pos+=2; - mysql->warning_count=uint2korr(pos); pos+=2; - } - else if (mysql->server_capabilities & CLIENT_TRANSACTIONS) - { - mysql->server_status=uint2korr(pos); pos+=2; - mysql->warning_count= 0; - } - DBUG_PRINT("info",("status: %ld warning_count: %ld", - mysql->server_status, mysql->warning_count)); - if (pos < mysql->net.read_pos+length && net_field_length(&pos)) - mysql->info=(char*) pos; - DBUG_RETURN(0); - } - if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ - { - int error=send_file_to_server(mysql,(char*) pos); - if ((length=net_safe_read(mysql)) == packet_error || error) - DBUG_RETURN(1); - goto get_info; /* Get info packet */ - } - if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) - mysql->server_status|= SERVER_STATUS_IN_TRANS; - - mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ - - if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 6 : 5))) - DBUG_RETURN(1); - if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, - (uint) field_count,0, - mysql->server_capabilities))) - DBUG_RETURN(1); - mysql->status= MYSQL_STATUS_GET_RESULT; - mysql->field_count= (uint) field_count; - mysql->warning_count= 0; - DBUG_RETURN(0); -} - - -int STDCALL -mysql_real_query(MYSQL *mysql, const char *query, ulong length) -{ - DBUG_ENTER("mysql_real_query"); - DBUG_PRINT("enter",("handle: %lx",mysql)); - DBUG_PRINT("query",("Query = '%-.4096s'",query)); - - if (mysql_send_query(mysql,query,length)) - DBUG_RETURN(1); - DBUG_RETURN((int) mysql_read_query_result(mysql)); -} - - -static my_bool -send_file_to_server(MYSQL *mysql, const char *filename) -{ - int fd, readcount; - my_bool result= 1; - uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); - char *buf, tmp_name[FN_REFLEN]; - DBUG_ENTER("send_file_to_server"); - - if (!(buf=my_malloc(packet_length,MYF(0)))) - { - strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY)); - DBUG_RETURN(1); - } - - fn_format(tmp_name,filename,"","",4); /* Convert to client format */ - if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) - { - my_net_write(&mysql->net,"",0); /* Server needs one packet */ - net_flush(&mysql->net); - mysql->net.last_errno=EE_FILENOTFOUND; - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - EE(mysql->net.last_errno),tmp_name, errno); - goto err; - } - - while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) - { - if (my_net_write(&mysql->net,buf,readcount)) - { - DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); - mysql->net.last_errno=CR_SERVER_LOST; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - goto err; - } - } - /* Send empty packet to mark end of file */ - if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net)) - { - mysql->net.last_errno=CR_SERVER_LOST; - sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno); - goto err; - } - if (readcount < 0) - { - mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */ - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - tmp_name,errno); - goto err; - } - result=0; /* Ok */ - -err: - if (fd >= 0) - (void) my_close(fd,MYF(0)); - my_free(buf,MYF(0)); - DBUG_RETURN(result); -} - - -/************************************************************************** - Alloc result struct for buffered results. All rows are read to buffer. - mysql_data_seek may be used. -**************************************************************************/ - -MYSQL_RES * STDCALL -mysql_store_result(MYSQL *mysql) -{ - MYSQL_RES *result; - DBUG_ENTER("mysql_store_result"); - - /* read from the actually used connection */ - mysql = mysql->last_used_con; - - if (!mysql->fields) - DBUG_RETURN(0); - if (mysql->status != MYSQL_STATUS_GET_RESULT) - { - strmov(mysql->net.last_error, - ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - DBUG_RETURN(0); - } - mysql->status=MYSQL_STATUS_READY; /* server is ready */ - if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+ - sizeof(ulong) * - mysql->field_count), - MYF(MY_WME | MY_ZEROFILL)))) - { - mysql->net.last_errno=CR_OUT_OF_MEMORY; - strmov(mysql->net.last_error, ER(mysql->net.last_errno)); - DBUG_RETURN(0); - } - result->eof=1; /* Marker for buffered */ - result->lengths=(ulong*) (result+1); - if (!(result->data=read_rows(mysql,mysql->fields,mysql->field_count))) - { - my_free((gptr) result,MYF(0)); - DBUG_RETURN(0); - } - mysql->affected_rows= result->row_count= result->data->rows; - result->data_cursor= result->data->data; - result->fields= mysql->fields; - result->field_alloc= mysql->field_alloc; - result->field_count= mysql->field_count; - result->current_field=0; - result->current_row=0; /* Must do a fetch first */ - mysql->fields=0; /* fields is now in result */ - DBUG_RETURN(result); /* Data fetched */ -} - - /************************************************************************** Alloc struct for use with unbuffered reads. Data is fetched by domand when calling to mysql_fetch_row. @@ -3027,76 +998,6 @@ mysql_fetch_field(MYSQL_RES *result) return &result->fields[result->current_field++]; } - -/************************************************************************** - Return next row of the query results -**************************************************************************/ - -MYSQL_ROW STDCALL -mysql_fetch_row(MYSQL_RES *res) -{ - DBUG_ENTER("mysql_fetch_row"); - if (!res->data) - { /* Unbufferred fetch */ - if (!res->eof) - { - if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths))) - { - res->row_count++; - DBUG_RETURN(res->current_row=res->row); - } - else - { - DBUG_PRINT("info",("end of data")); - res->eof=1; - res->handle->status=MYSQL_STATUS_READY; - /* Don't clear handle in mysql_free_results */ - res->handle=0; - } - } - DBUG_RETURN((MYSQL_ROW) NULL); - } - { - MYSQL_ROW tmp; - if (!res->data_cursor) - { - DBUG_PRINT("info",("end of data")); - DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL); - } - tmp = res->data_cursor->data; - res->data_cursor = res->data_cursor->next; - DBUG_RETURN(res->current_row=tmp); - } -} - -/************************************************************************** - Get column lengths of the current row - If one uses mysql_use_result, res->lengths contains the length information, - else the lengths are calculated from the offset between pointers. -**************************************************************************/ - -static void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count) -{ - ulong *prev_length; - byte *start=0; - MYSQL_ROW end; - - prev_length=0; /* Keep gcc happy */ - for (end=column + field_count + 1 ; column != end ; column++, to++) - { - if (!*column) - { - *to= 0; /* Null */ - continue; - } - if (start) /* Found end of prev string */ - *prev_length= (ulong) (*column-start-1); - start= *column; - prev_length= to; - } -} - - ulong * STDCALL mysql_fetch_lengths(MYSQL_RES *res) { @@ -3109,21 +1010,6 @@ mysql_fetch_lengths(MYSQL_RES *res) return res->lengths; } -/************************************************************************** - Move to a specific row and column -**************************************************************************/ - -void STDCALL -mysql_data_seek(MYSQL_RES *result, my_ulonglong row) -{ - MYSQL_ROWS *tmp=0; - DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); - if (result->data) - for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; - result->current_row=0; - result->data_cursor = tmp; -} - /************************************************************************* put the row or field cursor one a position one got from mysql_row_tell() This doesn't restore any data. The next mysql_fetch_row or @@ -3445,22 +1331,6 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) DBUG_RETURN(0); } -/**************************************************************************** - Functions to get information from the MySQL structure - These are functions to make shared libraries more usable. -****************************************************************************/ - -/* MYSQL_RES */ -my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res) -{ - return res->row_count; -} - -unsigned int STDCALL mysql_num_fields(MYSQL_RES *res) -{ - return res->field_count; -} - my_bool STDCALL mysql_eof(MYSQL_RES *res) { return res->eof; @@ -3503,16 +1373,6 @@ my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) return mysql->last_used_con->insert_id; } -uint STDCALL mysql_errno(MYSQL *mysql) -{ - return mysql->net.last_errno; -} - -const char * STDCALL mysql_error(MYSQL *mysql) -{ - return mysql->net.last_error; -} - uint STDCALL mysql_warning_count(MYSQL *mysql) { return mysql->warning_count; diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index b36f8d92490..303be2459a9 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -43,14 +43,14 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \ item.cc item_buff.cc item_cmpfunc.cc item_create.cc \ item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \ item_uniq.cc item_subselect.cc item_row.cc\ - key.cc lock.cc log.cc log_event.cc mf_iocache.cc\ - mini_client.cc protocol.cc net_serv.cc opt_ft.cc opt_range.cc \ + key.cc lock.cc log.cc log_event.cc \ + protocol.cc net_serv.cc opt_ft.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ - repl_failsafe.cc slave.cc sql_load.cc sql_olap.cc \ + sql_load.cc sql_olap.cc \ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \ sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \ sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \ - sql_prepare.cc sql_derived.cc sql_rename.cc sql_repl.cc \ + sql_prepare.cc sql_derived.cc sql_rename.cc \ sql_select.cc sql_do.cc sql_show.cc set_var.cc \ sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \ sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \ diff --git a/sql-common/client.c b/sql-common/client.c new file mode 100644 index 00000000000..3e08c55737b --- /dev/null +++ b/sql-common/client.c @@ -0,0 +1,2299 @@ +my_bool mysql_reconnect(MYSQL *mysql); +static my_bool send_file_to_server(MYSQL *mysql, const char *filename); +void end_server(MYSQL *mysql); + +/**************************************************************************** + A modified version of connect(). my_connect() allows you to specify + a timeout value, in seconds, that we should wait until we + derermine we can't connect to a particular host. If timeout is 0, + my_connect() will behave exactly like connect(). + + Base version coded by Steve Bernacki, Jr. +*****************************************************************************/ + +my_bool my_connect(my_socket s, const struct sockaddr *name, + uint namelen, uint timeout) +{ +#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) + return connect(s, (struct sockaddr*) name, namelen) != 0; +#else + int flags, res, s_err; + SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); + fd_set sfds; + struct timeval tv; + time_t start_time, now_time; + + /* + If they passed us a timeout of zero, we should behave + exactly like the normal connect() call does. + */ + + if (timeout == 0) + return connect(s, (struct sockaddr*) name, namelen) != 0; + + flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ +#ifdef O_NONBLOCK + fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ +#endif + + res = connect(s, (struct sockaddr*) name, namelen); + s_err = errno; /* Save the error... */ + fcntl(s, F_SETFL, flags); + if ((res != 0) && (s_err != EINPROGRESS)) + { + errno = s_err; /* Restore it */ + return(1); + } + if (res == 0) /* Connected quickly! */ + return(0); + + /* + Otherwise, our connection is "in progress." We can use + the select() call to wait up to a specified period of time + for the connection to succeed. If select() returns 0 + (after waiting howevermany seconds), our socket never became + writable (host is probably unreachable.) Otherwise, if + select() returns 1, then one of two conditions exist: + + 1. An error occured. We use getsockopt() to check for this. + 2. The connection was set up sucessfully: getsockopt() will + return 0 as an error. + + Thanks goes to Andrew Gierth + who posted this method of timing out a connect() in + comp.unix.programmer on August 15th, 1997. + */ + + FD_ZERO(&sfds); + FD_SET(s, &sfds); + /* + select could be interrupted by a signal, and if it is, + the timeout should be adjusted and the select restarted + to work around OSes that don't restart select and + implementations of select that don't adjust tv upon + failure to reflect the time remaining + */ + start_time = time(NULL); + for (;;) + { + tv.tv_sec = (long) timeout; + tv.tv_usec = 0; +#if defined(HPUX10) && defined(THREAD) + if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) > 0) + break; +#else + if ((res = select(s+1, NULL, &sfds, NULL, &tv)) > 0) + break; +#endif + if (res == 0) /* timeout */ + return -1; + now_time=time(NULL); + timeout-= (uint) (now_time - start_time); + if (errno != EINTR || (int) timeout <= 0) + return 1; + } + + /* + select() returned something more interesting than zero, let's + see if we have any errors. If the next two statements pass, + we've got an open socket! + */ + + s_err=0; + if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) + return(1); + + if (s_err) + { /* getsockopt could succeed */ + errno = s_err; + return(1); /* but return an error... */ + } + return (0); /* ok */ + +#endif +} + +/* + Create a named pipe connection +*/ + +#ifdef __WIN__ + +HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, + char **arg_unix_socket) +{ + HANDLE hPipe=INVALID_HANDLE_VALUE; + char szPipeName [ 257 ]; + DWORD dwMode; + int i; + my_bool testing_named_pipes=0; + char *host= *arg_host, *unix_socket= *arg_unix_socket; + +#ifdef _libmysql_c + if ( ! unix_socket || (unix_socket)[0] == 0x00) + unix_socket = mysql_unix_port; +#endif + if (!host || !strcmp(host,LOCAL_HOST)) + host=LOCAL_HOST_NAMEDPIPE; + + sprintf( szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); + DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", + host, unix_socket)); + + for (i=0 ; i < 100 ; i++) /* Don't retry forever */ + { + if ((hPipe = CreateFile(szPipeName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL )) != INVALID_HANDLE_VALUE) + break; + if (GetLastError() != ERROR_PIPE_BUSY) + { + net->last_errno=CR_NAMEDPIPEOPEN_ERROR; + sprintf(net->last_error,ER(net->last_errno),host, unix_socket, + (ulong) GetLastError()); + return INVALID_HANDLE_VALUE; + } + /* wait for for an other instance */ + if (! WaitNamedPipe(szPipeName, connect_timeout*1000) ) + { + net->last_errno=CR_NAMEDPIPEWAIT_ERROR; + sprintf(net->last_error,ER(net->last_errno),host, unix_socket, + (ulong) GetLastError()); + return INVALID_HANDLE_VALUE; + } + } + if (hPipe == INVALID_HANDLE_VALUE) + { + net->last_errno=CR_NAMEDPIPEOPEN_ERROR; + sprintf(net->last_error,ER(net->last_errno),host, unix_socket, + (ulong) GetLastError()); + return INVALID_HANDLE_VALUE; + } + dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; + if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) ) + { + CloseHandle( hPipe ); + net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; + sprintf(net->last_error,ER(net->last_errno),host, unix_socket, + (ulong) GetLastError()); + return INVALID_HANDLE_VALUE; + } + *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */ + return (hPipe); +} +#endif + +/***************************************************************************** + Read a packet from server. Give error message if socket was down + or packet is an error message +*****************************************************************************/ + +ulong +net_safe_read(MYSQL *mysql) +{ + NET *net= &mysql->net; + ulong len=0; + init_sigpipe_variables + + /* Don't give sigpipe errors if the client doesn't want them */ + set_sigpipe(mysql); + if (net->vio != 0) + len=my_net_read(net); + reset_sigpipe(mysql); + + if (len == packet_error || len == 0) + { + DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", + vio_description(net->vio),len)); + end_server(mysql); + net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ? + CR_NET_PACKET_TOO_LARGE: + CR_SERVER_LOST); + strmov(net->last_error,ER(net->last_errno)); + return (packet_error); + } + if (net->read_pos[0] == 255) + { + if (len > 3) + { + char *pos=(char*) net->read_pos+1; + net->last_errno=uint2korr(pos); + pos+=2; + len-=2; + (void) strmake(net->last_error,(char*) pos, + min((uint) len,(uint) sizeof(net->last_error)-1)); + } + else + { + net->last_errno=CR_UNKNOWN_ERROR; + (void) strmov(net->last_error,ER(net->last_errno)); + } + DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno, + net->last_error)); + return(packet_error); + } + return len; +} + +static void free_rows(MYSQL_DATA *cur) +{ + if (cur) + { + free_root(&cur->alloc,MYF(0)); + my_free((gptr) cur,MYF(0)); + } +} + +static my_bool +advanced_command(MYSQL *mysql, enum enum_server_command command, + const char *header, ulong header_length, + const char *arg, ulong arg_length, my_bool skip_check) +{ + NET *net= &mysql->net; + my_bool result= 1; + init_sigpipe_variables + + /* Don't give sigpipe errors if the client doesn't want them */ + set_sigpipe(mysql); + + if (mysql->net.vio == 0) + { /* Do reconnect if possible */ + if (mysql_reconnect(mysql)) + return 1; + } + if (mysql->status != MYSQL_STATUS_READY) + { + strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + return 1; + } + + mysql->net.last_error[0]=0; + mysql->net.last_errno=0; + mysql->net.report_error=0; + mysql->info=0; + mysql->affected_rows= ~(my_ulonglong) 0; + net_clear(&mysql->net); /* Clear receive buffer */ + if (!arg) + arg=""; + + if (net_write_command(net,(uchar) command, header, header_length, + arg, arg_length)) + { + DBUG_PRINT("error",("Can't send command to server. Error: %d", + socket_errno)); + if (net->last_errno == ER_NET_PACKET_TOO_LARGE) + { + net->last_errno=CR_NET_PACKET_TOO_LARGE; + strmov(net->last_error,ER(net->last_errno)); + goto end; + } + end_server(mysql); + if (mysql_reconnect(mysql)) + goto end; + if (net_write_command(net,(uchar) command, header, header_length, + arg, arg_length)) + { + net->last_errno=CR_SERVER_GONE_ERROR; + strmov(net->last_error,ER(net->last_errno)); + goto end; + } + } + result=0; + if (!skip_check) + result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ? + 1 : 0); + end: + reset_sigpipe(mysql); + return result; +} + +my_bool +simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, + ulong length, my_bool skip_check) +{ + return advanced_command(mysql, command, NullS, 0, arg, length, skip_check); +} + +static void free_old_query(MYSQL *mysql) +{ + DBUG_ENTER("free_old_query"); + if (mysql->fields) + free_root(&mysql->field_alloc,MYF(0)); + else + init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ + mysql->fields=0; + mysql->field_count=0; /* For API */ + DBUG_VOID_RETURN; +} + +#ifdef __WIN__ +static my_bool is_NT(void) +{ + char *os=getenv("OS"); + return (os && !strcmp(os, "Windows_NT")) ? 1 : 0; +} +#endif + +/************************************************************************** + Shut down connection +**************************************************************************/ + +void end_server(MYSQL *mysql) +{ + DBUG_ENTER("end_server"); + if (mysql->net.vio != 0) + { + init_sigpipe_variables + DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); + set_sigpipe(mysql); + vio_delete(mysql->net.vio); + reset_sigpipe(mysql); + mysql->net.vio= 0; /* Marker */ + } + net_end(&mysql->net); + free_old_query(mysql); + DBUG_VOID_RETURN; +} + +void STDCALL +mysql_free_result(MYSQL_RES *result) +{ + DBUG_ENTER("mysql_free_result"); + DBUG_PRINT("enter",("mysql_res: %lx",result)); + if (result) + { + if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT) + { + DBUG_PRINT("warning",("Not all rows in set where read; Ignoring rows")); + for (;;) + { + ulong pkt_len; + if ((pkt_len=net_safe_read(result->handle)) == packet_error) + break; + if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254) + break; /* End of data */ + } + result->handle->status=MYSQL_STATUS_READY; + } + free_rows(result->data); + if (result->fields) + free_root(&result->field_alloc,MYF(0)); + if (result->row) + my_free((gptr) result->row,MYF(0)); + my_free((gptr) result,MYF(0)); + } + DBUG_VOID_RETURN; +} + +#ifdef _libmysql_c + +/**************************************************************************** + Get options from my.cnf +****************************************************************************/ + +static const char *default_options[]= +{ + "port","socket","compress","password","pipe", "timeout", "user", + "init-command", "host", "database", "debug", "return-found-rows", + "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", + "character-sets-dir", "default-character-set", "interactive-timeout", + "connect-timeout", "local-infile", "disable-local-infile", + "replication-probe", "enable-reads-from-master", "repl-parse-query", + "ssl-cipher", "max-allowed-packet", + "protocol", "shared-memory-base-name", + NullS +}; + +static TYPELIB option_types={array_elements(default_options)-1, + "options",default_options}; + +static int add_init_command(struct st_mysql_options *options, const char *cmd) +{ + char *tmp; + + if (!options->init_commands) + { + options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY), + MYF(MY_WME)); + init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO); + } + + if (!(tmp= my_strdup(cmd,MYF(MY_WME))) || + insert_dynamic(options->init_commands, (gptr)&tmp)) + { + my_free(tmp, MYF(MY_ALLOW_ZERO_PTR)); + return 1; + } + + return 0; +} + +static void mysql_read_default_options(struct st_mysql_options *options, + const char *filename,const char *group) +{ + int argc; + char *argv_buff[1],**argv; + const char *groups[3]; + DBUG_ENTER("mysql_read_default_options"); + DBUG_PRINT("enter",("file: %s group: %s",filename,group ? group :"NULL")); + + argc=1; argv=argv_buff; argv_buff[0]= (char*) "client"; + groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0; + + load_defaults(filename, groups, &argc, &argv); + if (argc != 1) /* If some default option */ + { + char **option=argv; + while (*++option) + { + /* DBUG_PRINT("info",("option: %s",option[0])); */ + if (option[0][0] == '-' && option[0][1] == '-') + { + char *end=strcend(*option,'='); + char *opt_arg=0; + if (*end) + { + opt_arg=end+1; + *end=0; /* Remove '=' */ + } + /* Change all '_' in variable name to '-' */ + for (end= *option ; *(end= strcend(end,'_')) ; ) + *end= '-'; + switch (find_type(*option+2,&option_types,2)) { + case 1: /* port */ + if (opt_arg) + options->port=atoi(opt_arg); + break; + case 2: /* socket */ + if (opt_arg) + { + my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR)); + options->unix_socket=my_strdup(opt_arg,MYF(MY_WME)); + } + break; + case 3: /* compress */ + options->compress=1; + options->client_flag|= CLIENT_COMPRESS; + break; + case 4: /* password */ + if (opt_arg) + { + my_free(options->password,MYF(MY_ALLOW_ZERO_PTR)); + options->password=my_strdup(opt_arg,MYF(MY_WME)); + } + break; + case 5: + options->protocol = MYSQL_PROTOCOL_PIPE; + case 20: /* connect_timeout */ + case 6: /* timeout */ + if (opt_arg) + options->connect_timeout=atoi(opt_arg); + break; + case 7: /* user */ + if (opt_arg) + { + my_free(options->user,MYF(MY_ALLOW_ZERO_PTR)); + options->user=my_strdup(opt_arg,MYF(MY_WME)); + } + break; + case 8: /* init-command */ + add_init_command(options,opt_arg); + break; + case 9: /* host */ + if (opt_arg) + { + my_free(options->host,MYF(MY_ALLOW_ZERO_PTR)); + options->host=my_strdup(opt_arg,MYF(MY_WME)); + } + break; + case 10: /* database */ + if (opt_arg) + { + my_free(options->db,MYF(MY_ALLOW_ZERO_PTR)); + options->db=my_strdup(opt_arg,MYF(MY_WME)); + } + break; + case 11: /* debug */ + mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace"); + break; + case 12: /* return-found-rows */ + options->client_flag|=CLIENT_FOUND_ROWS; + break; +#ifdef HAVE_OPENSSL + case 13: /* ssl_key */ + my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR)); + options->ssl_key = my_strdup(opt_arg, MYF(MY_WME)); + break; + case 14: /* ssl_cert */ + my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); + options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME)); + break; + case 15: /* ssl_ca */ + my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); + options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME)); + break; + case 16: /* ssl_capath */ + my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); + options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME)); + break; +#else + case 13: /* Ignore SSL options */ + case 14: + case 15: + case 16: + break; +#endif /* HAVE_OPENSSL */ + case 17: /* charset-lib */ + my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR)); + options->charset_dir = my_strdup(opt_arg, MYF(MY_WME)); + break; + case 18: + my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR)); + options->charset_name = my_strdup(opt_arg, MYF(MY_WME)); + break; + case 19: /* Interactive-timeout */ + options->client_flag|= CLIENT_INTERACTIVE; + break; + case 21: + if (!opt_arg || atoi(opt_arg) != 0) + options->client_flag|= CLIENT_LOCAL_FILES; + else + options->client_flag&= ~CLIENT_LOCAL_FILES; + break; + case 22: + options->client_flag&= CLIENT_LOCAL_FILES; + break; + case 23: /* replication probe */ + options->rpl_probe= 1; + break; + case 24: /* enable-reads-from-master */ + options->no_master_reads= 0; + break; + case 25: /* repl-parse-query */ + options->rpl_parse= 1; + break; + case 27: + options->max_allowed_packet= atoi(opt_arg); + break; + case 28: /* protocol */ + if ((options->protocol = find_type(opt_arg, &sql_protocol_typelib,0)) == ~(ulong) 0) + { + fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg); + exit(1); + } + break; + case 29: /* shared_memory_base_name */ +#ifdef HAVE_SMEM + if (options->shared_memory_base_name != def_shared_memory_base_name) + my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); + options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); +#endif + break; + default: + DBUG_PRINT("warning",("unknown option: %s",option[0])); + } + } + } + } + free_defaults(argv); + DBUG_VOID_RETURN; +} + +#endif /*_libmysql_c*/ + +/************************************************************************** + Get column lengths of the current row + If one uses mysql_use_result, res->lengths contains the length information, + else the lengths are calculated from the offset between pointers. +**************************************************************************/ + +static void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count) +{ + ulong *prev_length; + byte *start=0; + MYSQL_ROW end; + + prev_length=0; /* Keep gcc happy */ + for (end=column + field_count + 1 ; column != end ; column++, to++) + { + if (!*column) + { + *to= 0; /* Null */ + continue; + } + if (start) /* Found end of prev string */ + *prev_length= (ulong) (*column-start-1); + start= *column; + prev_length= to; + } +} + + +static inline void +unpack_fields_40(MYSQL_ROWS *row, MYSQL_FIELD *field, MEM_ROOT *alloc, + ulong *lengths, uint n_lengths, + my_bool default_value, my_bool long_flag_protocol) +{ + DBUG_ENTER("unpack_fields_40"); + + for (; row ; row = row->next,field++) + { + fetch_lengths(lengths, row->data, n_lengths); + field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]); + field->name= strdup_root(alloc,(char*) row->data[1]); + field->length= (uint) uint3korr(row->data[2]); + field->type= (enum enum_field_types) (uchar) row->data[3][0]; + + field->org_table_length= field->table_length= lengths[0]; + field->name_length= lengths[1]; + + if (long_flag_protocol) + { + field->flags= uint2korr(row->data[4]); + field->decimals=(uint) (uchar) row->data[4][2]; + } + else + { + field->flags= (uint) (uchar) row->data[4][0]; + field->decimals=(uint) (uchar) row->data[4][1]; + } + if (INTERNAL_NUM_FIELD(field)) + field->flags|= NUM_FLAG; + if (default_value && row->data[5]) + { + field->def=strdup_root(alloc,(char*) row->data[5]); + field->def_length= lengths[5]; + } + else + field->def=0; + field->max_length= 0; + } +} + +/*************************************************************************** + Change field rows to field structs +***************************************************************************/ + +static MYSQL_FIELD * +unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, + my_bool default_value, uint server_capabilities) +{ + MYSQL_ROWS *row; + MYSQL_FIELD *field,*result; + ulong lengths[8]; /* Max of fields */ + DBUG_ENTER("unpack_fields"); + + field=result=(MYSQL_FIELD*) alloc_root(alloc, + (uint) sizeof(MYSQL_FIELD)*fields); + if (!result) + { + free_rows(data); /* Free old data */ + DBUG_RETURN(0); + } + bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields); +#ifdef _mini_client_c + unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, + default_value, server_capabilities & CLIENT_LONG_FLAG); +#else + if (server_capabilities & CLIENT_PROTOCOL_41) + { + /* server is 4.1, and returns the new field result format */ + for (row=data->data; row ; row = row->next,field++) + { + uchar *pos; + fetch_lengths(&lengths[0], row->data, default_value ? 7 : 6); + field->db = strdup_root(alloc,(char*) row->data[0]); + field->table = strdup_root(alloc,(char*) row->data[1]); + field->org_table= strdup_root(alloc,(char*) row->data[2]); + field->name = strdup_root(alloc,(char*) row->data[3]); + field->org_name = strdup_root(alloc,(char*) row->data[4]); + + field->db_length= lengths[0]; + field->table_length= lengths[1]; + field->org_table_length= lengths[2]; + field->name_length= lengths[3]; + field->org_name_length= lengths[4]; + + /* Unpack fixed length parts */ + pos= (uchar*) row->data[5]; + field->charsetnr= uint2korr(pos); + field->length= (uint) uint3korr(pos+2); + field->type= (enum enum_field_types) pos[5]; + field->flags= uint2korr(pos+6); + field->decimals= (uint) pos[8]; + + if (INTERNAL_NUM_FIELD(field)) + field->flags|= NUM_FLAG; + if (default_value && row->data[6]) + { + field->def=strdup_root(alloc,(char*) row->data[6]); + field->def_length= lengths[6]; + } + else + field->def=0; + field->max_length= 0; + } + } +#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL + else + unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, + default_value, server_capabilities & CLIENT_LONG_FLAG); +#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */ +#endif /*_mini_client_c*/ + free_rows(data); /* Free old data */ + DBUG_RETURN(result); +} + +/* Read all rows (fields or data) from server */ + +static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, + uint fields) +{ + uint field; + ulong pkt_len; + ulong len; + uchar *cp; + char *to, *end_to; + MYSQL_DATA *result; + MYSQL_ROWS **prev_ptr,*cur; + NET *net = &mysql->net; + DBUG_ENTER("read_rows"); + + if ((pkt_len= net_safe_read(mysql)) == packet_error) + DBUG_RETURN(0); + if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), + MYF(MY_WME | MY_ZEROFILL)))) + { + net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->last_error,ER(net->last_errno)); + DBUG_RETURN(0); + } + init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ + result->alloc.min_malloc=sizeof(MYSQL_ROWS); + prev_ptr= &result->data; + result->rows=0; + result->fields=fields; + + /* + The last EOF packet is either a single 254 character or (in MySQL 4.1) + 254 followed by 1-7 status bytes. + + This doesn't conflict with normal usage of 254 which stands for a + string where the length of the string is 8 bytes. (see net_field_length()) + */ + + while (*(cp=net->read_pos) != 254 || pkt_len >= 8) + { + result->rows++; + if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc, + sizeof(MYSQL_ROWS))) || + !(cur->data= ((MYSQL_ROW) + alloc_root(&result->alloc, + (fields+1)*sizeof(char *)+pkt_len)))) + { + free_rows(result); + net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->last_error,ER(net->last_errno)); + DBUG_RETURN(0); + } + *prev_ptr=cur; + prev_ptr= &cur->next; + to= (char*) (cur->data+fields+1); + end_to=to+pkt_len-1; + for (field=0 ; field < fields ; field++) + { + if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) + { /* null field */ + cur->data[field] = 0; + } + else + { + cur->data[field] = to; + if (len > (ulong) (end_to - to)) + { + free_rows(result); + net->last_errno=CR_MALFORMED_PACKET; + strmov(net->last_error,ER(net->last_errno)); + DBUG_RETURN(0); + } + memcpy(to,(char*) cp,len); to[len]=0; + to+=len+1; + cp+=len; + if (mysql_fields) + { + if (mysql_fields[field].max_length < len) + mysql_fields[field].max_length=len; + } + } + } + cur->data[field]=to; /* End of last field */ + if ((pkt_len=net_safe_read(mysql)) == packet_error) + { + free_rows(result); + DBUG_RETURN(0); + } + } + *prev_ptr=0; /* last pointer is null */ +#ifndef _mini_client_c + if (pkt_len > 1) /* MySQL 4.1 protocol */ + { + mysql->warning_count= uint2korr(cp+1); + DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count)); + } +#endif + DBUG_PRINT("exit",("Got %d rows",result->rows)); + DBUG_RETURN(result); +} + +/* + Read one row. Uses packet buffer as storage for fields. + When next packet is read, the previous field values are destroyed +*/ + + +static int +read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) +{ + uint field; + ulong pkt_len,len; + uchar *pos,*prev_pos, *end_pos; + + if ((pkt_len=net_safe_read(mysql)) == packet_error) + return -1; + if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) + { +#ifndef _mini_client_c + if (pkt_len > 1) /* MySQL 4.1 protocol */ + mysql->warning_count= uint2korr(mysql->net.read_pos+1); +#endif + return 1; /* End of data */ + } + prev_pos= 0; /* allowed to write at packet[-1] */ + pos=mysql->net.read_pos; + end_pos=pos+pkt_len; + for (field=0 ; field < fields ; field++) + { + if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) + { /* null field */ + row[field] = 0; + *lengths++=0; + } + else + { + if (len > (ulong) (end_pos - pos)) + { + mysql->net.last_errno=CR_UNKNOWN_ERROR; + strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + return -1; + } + row[field] = (char*) pos; + pos+=len; + *lengths++=len; + } + if (prev_pos) + *prev_pos=0; /* Terminate prev field */ + prev_pos=pos; + } + row[field]=(char*) prev_pos+1; /* End of last field */ + *prev_pos=0; /* Terminate last field */ + return 0; +} + + +/**************************************************************************** + Init MySQL structure or allocate one +****************************************************************************/ + +MYSQL * STDCALL +mysql_init(MYSQL *mysql) +{ + mysql_once_init(); + if (!mysql) + { + if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) + return 0; + mysql->free_me=1; + } + else + bzero((char*) (mysql),sizeof(*(mysql))); +#ifndef _mini_client_c + mysql->options.connect_timeout=CONNECT_TIMEOUT; + mysql->last_used_con = mysql->next_slave = mysql->master = mysql; + /* + By default, we are a replication pivot. The caller must reset it + after we return if this is not the case. + */ + mysql->rpl_pivot = 1; +#if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__) + if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) + (void) signal(SIGPIPE,pipe_sig_handler); +#endif + +/* + Only enable LOAD DATA INFILE by default if configured with + --enable-local-infile +*/ +#ifdef ENABLED_LOCAL_INFILE + mysql->options.client_flag|= CLIENT_LOCAL_FILES; +#endif +#ifdef HAVE_SMEM + mysql->options.shared_memory_base_name=(char*)def_shared_memory_base_name; +#endif + +#else /*_mini_client_c*/ + +#ifdef __WIN__ + mysql->options.connect_timeout=20; +#endif + mysql->net.read_timeout = slave_net_timeout; + +#endif /*_mini_client_c*/ + return mysql; +} + + +/* + Initialize the MySQL library + + SYNOPSIS + mysql_once_init() + + NOTES + Can't be static on NetWare + This function is called by mysql_init() and indirectly called + by mysql_query(), so one should never have to call this from an + outside program. +*/ + +void mysql_once_init(void) +{ +#ifndef _mini_client_c + + if (!mysql_client_init) + { + mysql_client_init=1; + org_my_init_done=my_init_done; + my_init(); /* Will init threads */ + init_client_errs(); + if (!mysql_port) + { + mysql_port = MYSQL_PORT; +#ifndef MSDOS + { + struct servent *serv_ptr; + char *env; + if ((serv_ptr = getservbyname("mysql", "tcp"))) + mysql_port = (uint) ntohs((ushort) serv_ptr->s_port); + if ((env = getenv("MYSQL_TCP_PORT"))) + mysql_port =(uint) atoi(env); + } +#endif + } + if (!mysql_unix_port) + { + char *env; +#ifdef __WIN__ + mysql_unix_port = (char*) MYSQL_NAMEDPIPE; +#else + mysql_unix_port = (char*) MYSQL_UNIX_ADDR; +#endif + if ((env = getenv("MYSQL_UNIX_PORT"))) + mysql_unix_port = env; + } + mysql_debug(NullS); +#if defined(SIGPIPE) && !defined(THREAD) && !defined(__WIN__) + (void) signal(SIGPIPE,SIG_IGN); +#endif + } +#ifdef THREAD + else + my_thread_init(); /* Init if new thread */ +#endif + +#else /*_mini_client_c*/ + init_client_errs(); +#endif /*_mini_client_c*/ +} + + +/* + Handle password authentication +*/ + +static my_bool mysql_autenticate(MYSQL *mysql, const char *passwd) +{ + ulong pkt_length; + NET *net= &mysql->net; + char buff[SCRAMBLE41_LENGTH]; + char password_hash[SCRAMBLE41_LENGTH]; /* Used for storage of stage1 hash */ + + /* We shall only query server if it expect us to do so */ + if ((pkt_length=net_safe_read(mysql)) == packet_error) + goto error; + + if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) + { + /* + This should always happen with new server unless empty password + OK/Error packets have zero as the first char + */ + if (pkt_length == 24 && net->read_pos[0]) + { + /* Old passwords will have '*' at the first byte of hash */ + if (net->read_pos[0] != '*') + { + /* Build full password hash as it is required to decode scramble */ + password_hash_stage1(buff, passwd); + /* Store copy as we'll need it later */ + memcpy(password_hash,buff,SCRAMBLE41_LENGTH); + /* Finally hash complete password using hash we got from server */ + password_hash_stage2(password_hash,(const char*) net->read_pos); + /* Decypt and store scramble 4 = hash for stage2 */ + password_crypt((const char*) net->read_pos+4,mysql->scramble_buff, + password_hash, SCRAMBLE41_LENGTH); + mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; + /* Encode scramble with password. Recycle buffer */ + password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH); + } + else + { + /* Create password to decode scramble */ + create_key_from_old_password(passwd,password_hash); + /* Decypt and store scramble 4 = hash for stage2 */ + password_crypt((const char*) net->read_pos+4,mysql->scramble_buff, + password_hash, SCRAMBLE41_LENGTH); + mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; + /* Finally scramble decoded scramble with password */ + scramble(buff, mysql->scramble_buff, passwd,0); + } + /* Write second package of authentication */ + if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net)) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + /* Read what server thinks about out new auth message report */ + if (net_safe_read(mysql) == packet_error) + goto error; + } + } + return 0; + +error: + return 1; +} + +#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL) +struct passwd *getpwuid(uid_t); +char* getlogin(void); +#endif + + +#if defined(__NETWARE__) +/* default to "root" on NetWare */ +static void read_user_name(char *name) +{ + char *str=getenv("USER"); + strmake(name, str ? str : "UNKNOWN_USER", USERNAME_LENGTH); +} + +#elif !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__) && !defined(OS2) + +static void read_user_name(char *name) +{ + DBUG_ENTER("read_user_name"); + if (geteuid() == 0) + (void) strmov(name,"root"); /* allow use of surun */ + else + { +#ifdef HAVE_GETPWUID + struct passwd *skr; + const char *str; + if ((str=getlogin()) == NULL) + { + if ((skr=getpwuid(geteuid())) != NULL) + str=skr->pw_name; + else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) && + !(str=getenv("LOGIN"))) + str="UNKNOWN_USER"; + } + (void) strmake(name,str,USERNAME_LENGTH); +#elif HAVE_CUSERID + (void) cuserid(name); +#else + strmov(name,"UNKNOWN_USER"); +#endif + } + DBUG_VOID_RETURN; +} + +#else /* If MSDOS || VMS */ + +static void read_user_name(char *name) +{ + char *str=getenv("USER"); /* ODBC will send user variable */ + strmake(name,str ? str : "ODBC", USERNAME_LENGTH); +} + +#endif + +/* + Note that the mysql argument must be initialized with mysql_init() + before calling mysql_real_connect ! +*/ + +MYSQL * STDCALL +mysql_real_connect(MYSQL *mysql,const char *host, const char *user, + const char *passwd, const char *db, + uint port, const char *unix_socket,ulong client_flag +#ifdef _mini_client_c + , uint net_read_timeout +#endif +) +{ + char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; + char *end,*host_info,*charset_name; + my_socket sock; + uint32 ip_addr; + struct sockaddr_in sock_addr; + ulong pkt_length; + NET *net= &mysql->net; +#ifdef _mini_client_c + thr_alarm_t alarmed; + ALARM alarm_buff; + ulong max_allowed_packet; +#endif + +#ifdef __WIN__ + HANDLE hPipe=INVALID_HANDLE_VALUE; +#endif +#ifdef HAVE_SYS_UN_H + struct sockaddr_un UNIXaddr; +#endif + init_sigpipe_variables + DBUG_ENTER("mysql_real_connect"); + LINT_INIT(host_info); + + DBUG_PRINT("enter",("host: %s db: %s user: %s", + host ? host : "(Null)", + db ? db : "(Null)", + user ? user : "(Null)")); + + /* Don't give sigpipe errors if the client doesn't want them */ + set_sigpipe(mysql); + net->vio = 0; /* If something goes wrong */ +#ifdef _mini_client_c + mysql->charset=default_charset_info; /* Set character set */ +#endif + +#ifdef _libmysql_c + /* use default options */ + if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) + { + mysql_read_default_options(&mysql->options, + (mysql->options.my_cnf_file ? + mysql->options.my_cnf_file : "my"), + mysql->options.my_cnf_group); + my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.my_cnf_file=mysql->options.my_cnf_group=0; + } + + /* Some empty-string-tests are done because of ODBC */ + if (!host || !host[0]) + host=mysql->options.host; + if (!user || !user[0]) + user=mysql->options.user; + if (!passwd) + { + passwd=mysql->options.password; +#ifndef DONT_USE_MYSQL_PWD + if (!passwd) + passwd=getenv("MYSQL_PWD"); /* get it from environment */ +#endif + } + if (!db || !db[0]) + db=mysql->options.db; + if (!port) + port=mysql->options.port; + if (!unix_socket) + unix_socket=mysql->options.unix_socket; +#endif /*_libmysql_c*/ +#ifdef _mini_client_c + if (!port) + port = MYSQL_PORT; /* Should always be set by mysqld */ + if (!unix_socket) + unix_socket=MYSQL_UNIX_ADDR; + if (!mysql->options.connect_timeout) + mysql->options.connect_timeout= net_read_timeout; +#endif /*mini_client_c*/ + + mysql->reconnect=1; /* Reconnect as default */ + mysql->server_status=SERVER_STATUS_AUTOCOMMIT; + + /* + Grab a socket and connect it to the server + */ +#if defined(_libmysql_c) && defined(HAVE_SMEM) + if ((!mysql->options.protocol || + mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && + (!host || !strcmp(host,LOCAL_HOST))) + { + if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) == + INVALID_HANDLE_VALUE) + { + DBUG_PRINT("error", + ("host: '%s' socket: '%s' shared memory: %s have_tcpip: %d", + host ? host : "", + unix_socket ? unix_socket : "", + (int) mysql->options.shared_memory_base_name, + (int) have_tcpip)); + if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) + goto error; + /* Try also with PIPE or TCP/IP */ + } + else + { + mysql->options.protocol=MYSQL_PROTOCOL_MEMORY; + sock=0; + unix_socket = 0; + host=mysql->options.shared_memory_base_name; + host_info=(char*) ER(CR_SHARED_MEMORY_CONNECTION); + } + } else +#endif /* HAVE_SMEM */ +#if defined(HAVE_SYS_UN_H) + if ( +#ifdef _libmysql_c + (!mysql->options.protocol || + mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&& + (unix_socket || mysql_unix_port) && +#endif +#ifdef _mini_client_c + unix_socket && +#endif + (!host || !strcmp(host,LOCAL_HOST))) + { + host=LOCAL_HOST; +#ifdef _libmysql_c + if (!unix_socket) + unix_socket=mysql_unix_port; +#endif + host_info=(char*) ER(CR_LOCALHOST_CONNECTION); + DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); + if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) + { + net->last_errno=CR_SOCKET_CREATE_ERROR; + sprintf(net->last_error,ER(net->last_errno),socket_errno); + goto error; + } + net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); + bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); + UNIXaddr.sun_family = AF_UNIX; + strmov(UNIXaddr.sun_path, unix_socket); + if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), + mysql->options.connect_timeout)) + { + DBUG_PRINT("error",("Got error %d on connect to local server", + socket_errno)); + net->last_errno=CR_CONNECTION_ERROR; + sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); + goto error; + } +#ifdef _libmysql_c + else + mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; +#endif + } + else +#elif defined(__WIN__) + { +#ifdef _libmysql_c + if ((!mysql->options.protocol || + mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&& + ((unix_socket || !host && is_NT() || + host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||! have_tcpip))&& + (!net->vio)) +#elif _mini_client_c + if ((unix_socket || + !host && is_NT() || + host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) || + mysql->options.named_pipe || !have_tcpip)) +#endif + { + sock=0; + if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, + (char**) &host, (char**) &unix_socket)) == + INVALID_HANDLE_VALUE) + { + DBUG_PRINT("error", + ("host: '%s' socket: '%s' have_tcpip: %d", + host ? host : "", + unix_socket ? unix_socket : "", + (int) have_tcpip)); + if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || + (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || + (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) + goto error; + /* Try also with TCP/IP */ + } + else + { + net->vio=vio_new_win32pipe(hPipe); + sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host, + unix_socket); + } + } + } +#ifdef _mini_client_c + if (hPipe == INVALID_HANDLE_VALUE) +#endif +#endif +#ifdef _libmysql_c + if ((!mysql->options.protocol || + mysql->options.protocol == MYSQL_PROTOCOL_TCP)&&(!net->vio)) +#endif + { + unix_socket=0; /* This is not used */ +#ifdef _libmysql_c + if (!port) + port=mysql_port; +#endif + if (!host) + host=LOCAL_HOST; + sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); + DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); +#ifdef _mini_client_c + thr_alarm_init(&alarmed); + thr_alarm(&alarmed, net_read_timeout, &alarm_buff); +#endif + sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); +#ifdef _mini_client_c + thr_end_alarm(&alarmed); +#endif + /* _WIN64 ; Assume that the (int) range is enough for socket() */ + if (sock == SOCKET_ERROR) + { + net->last_errno=CR_IPSOCK_ERROR; + sprintf(net->last_error,ER(net->last_errno),socket_errno); + goto error; + } + net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE); + bzero((char*) &sock_addr,sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + + /* + The server name may be a host name or IP address + */ + + if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) + { + memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); + } + else + { + int tmp_errno; + struct hostent tmp_hostent,*hp; + char buff2[GETHOSTBYNAME_BUFF_SIZE]; + hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), + &tmp_errno); + if (!hp) + { + my_gethostbyname_r_free(); + net->last_errno=CR_UNKNOWN_HOST; + sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); + goto error; + } + memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); + my_gethostbyname_r_free(); + } + sock_addr.sin_port = (ushort) htons((ushort) port); + if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), + mysql->options.connect_timeout)) + { + DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, + host)); + net->last_errno= CR_CONN_HOST_ERROR; + sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); + goto error; + } + } +#ifdef _libmysql_c + else if (!net->vio) + { + DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); + net->last_errno= CR_CONN_UNKNOW_PROTOCOL; + sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL)); + goto error; + } +#endif /*_libmysql_c*/ + if (!net->vio || my_net_init(net, net->vio)) + { + vio_delete(net->vio); + net->vio = 0; + net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + vio_keepalive(net->vio,TRUE); +#ifdef _mini_client_c + net->read_timeout=slave_net_timeout; +#endif + /* Get version info */ + mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ + if (mysql->options.connect_timeout && + vio_poll_read(net->vio, mysql->options.connect_timeout)) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + if ((pkt_length=net_safe_read(mysql)) == packet_error) + goto error; + + /* Check if version of protocol matches current one */ + + mysql->protocol_version= net->read_pos[0]; + DBUG_DUMP("packet",(char*) net->read_pos,10); + DBUG_PRINT("info",("mysql protocol version %d, server=%d", + PROTOCOL_VERSION, mysql->protocol_version)); + if (mysql->protocol_version != PROTOCOL_VERSION +#ifdef _mini_client_c + && mysql->protocol_version != PROTOCOL_VERSION-1 +#endif + ) + { + net->last_errno= CR_VERSION_ERROR; + sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, + PROTOCOL_VERSION); + goto error; + } + end=strend((char*) net->read_pos+1); + mysql->thread_id=uint4korr(end+1); + end+=5; + strmake(mysql->scramble_buff,end,8); + end+=9; + if (pkt_length >= (uint) (end+1 - (char*) net->read_pos)) + mysql->server_capabilities=uint2korr(end); + if (pkt_length >= (uint) (end+18 - (char*) net->read_pos)) + { + /* New protocol with 16 bytes to describe server characteristics */ + mysql->server_language=end[2]; + mysql->server_status=uint2korr(end+3); + } + +#ifdef _libmysql_c + /* Set character set */ + if ((charset_name=mysql->options.charset_name)) + { + const char *save=charsets_dir; + if (mysql->options.charset_dir) + charsets_dir=mysql->options.charset_dir; + mysql->charset=get_charset_by_name(mysql->options.charset_name, + MYF(MY_WME)); + charsets_dir=save; + } + else if (mysql->server_language) + { + charset_name=charset_name_buff; + sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */ + if (!(mysql->charset = + get_charset((uint8) mysql->server_language, MYF(0)))) + mysql->charset = default_charset_info; /* shouldn't be fatal */ + } + else + mysql->charset=default_charset_info; + + if (!mysql->charset) + { + net->last_errno=CR_CANT_READ_CHARSET; + if (mysql->options.charset_dir) + sprintf(net->last_error,ER(net->last_errno), + charset_name ? charset_name : "unknown", + mysql->options.charset_dir); + else + { + char cs_dir_name[FN_REFLEN]; + get_charsets_dir(cs_dir_name); + sprintf(net->last_error,ER(net->last_errno), + charset_name ? charset_name : "unknown", + cs_dir_name); + } + goto error; + } +#endif /*_libmysql_c*/ + + /* Save connection information */ + if (!user) user=""; + if (!passwd) passwd=""; + if (!my_multi_malloc(MYF(0), + &mysql->host_info, (uint) strlen(host_info)+1, + &mysql->host, (uint) strlen(host)+1, + &mysql->unix_socket,unix_socket ? + (uint) strlen(unix_socket)+1 : (uint) 1, + &mysql->server_version, + (uint) (end - (char*) net->read_pos), + NullS) || + !(mysql->user=my_strdup(user,MYF(0))) || + !(mysql->passwd=my_strdup(passwd,MYF(0)))) + { + strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); + goto error; + } + strmov(mysql->host_info,host_info); + strmov(mysql->host,host); + if (unix_socket) + strmov(mysql->unix_socket,unix_socket); + else + mysql->unix_socket=0; + strmov(mysql->server_version,(char*) net->read_pos+1); + mysql->port=port; + client_flag|=mysql->options.client_flag; + + /* Send client information for access check */ + client_flag|=CLIENT_CAPABILITIES; + +#ifdef HAVE_OPENSSL + if (mysql->options.ssl_key || mysql->options.ssl_cert || + mysql->options.ssl_ca || mysql->options.ssl_capath || + mysql->options.ssl_cipher) + mysql->options.use_ssl= 1; + if (mysql->options.use_ssl) + client_flag|=CLIENT_SSL; +#endif /* HAVE_OPENSSL */ + if (db) + client_flag|=CLIENT_CONNECT_WITH_DB; + +#ifdef _libmysql_c + /* Remove options that server doesn't support */ + client_flag= ((client_flag & + ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) | + (client_flag & mysql->server_capabilities)); +#ifndef HAVE_COMPRESS + client_flag&= ~CLIENT_COMPRESS; +#endif + if (client_flag & CLIENT_PROTOCOL_41) + { + /* 4.1 server and 4.1 client has a 4 byte option flag */ + int4store(buff,client_flag); + int4store(buff+4,max_allowed_packet); + end= buff+8; + } + else + { + int2store(buff,client_flag); + int3store(buff+2,max_allowed_packet); + end= buff+5; + } + mysql->client_flag=client_flag; +#endif /*_libmysql_c*/ + +#ifdef _mini_client_c +#ifdef HAVE_COMPRESS + if ((mysql->server_capabilities & CLIENT_COMPRESS) && + (mysql->options.compress || (client_flag & CLIENT_COMPRESS))) + client_flag|=CLIENT_COMPRESS; /* We will use compression */ + else +#endif + client_flag&= ~CLIENT_COMPRESS; +#endif /*mini_client_c*/ + +#ifdef _mini_client_c +#ifdef HAVE_OPENSSL + if ((mysql->server_capabilities & CLIENT_SSL) && + (mysql->options.use_ssl || (client_flag & CLIENT_SSL))) + { + DBUG_PRINT("info", ("Changing IO layer to SSL")); + client_flag |= CLIENT_SSL; + } + else + { + if (client_flag & CLIENT_SSL) + { + DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL")); + } + client_flag &= ~CLIENT_SSL; + } +#endif /* HAVE_OPENSSL */ + + max_allowed_packet=mysql->net.max_packet_size; + int2store(buff,client_flag); + int3store(buff+2,max_allowed_packet); + end= buff+5; + mysql->client_flag=client_flag; +#endif /*_mini_client_c*/ + +#ifdef HAVE_OPENSSL + /* + Oops.. are we careful enough to not send ANY information without + encryption? + */ + if (client_flag & CLIENT_SSL) + { + struct st_mysql_options *options= &mysql->options; + if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + /* Do the SSL layering. */ +#ifdef _libmysql_c + if (!(mysql->connector_fd= + (gptr) new_VioSSLConnectorFd(options->ssl_key, + options->ssl_cert, + options->ssl_ca, + options->ssl_capath, + options->ssl_cipher))) + { + net->last_errno= CR_SSL_CONNECTION_ERROR; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } +#endif /*libmysql_c*/ + DBUG_PRINT("info", ("IO layer change in progress...")); + if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), + mysql->net.vio, (long) (mysql->options.connect_timeout))) + { + net->last_errno= CR_SSL_CONNECTION_ERROR; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + DBUG_PRINT("info", ("IO layer change done!")); + } +#endif /* HAVE_OPENSSL */ + + DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu", + mysql->server_version,mysql->server_capabilities, + mysql->server_status, client_flag)); + /* This needs to be changed as it's not useful with big packets */ + if (user && user[0]) + strmake(end,user,32); /* Max user name */ + else +#ifdef _mini_client_c + { + user = getenv("USER"); + if (!user) user = "mysql"; + strmov((char*) end, user ); + } +#else + read_user_name((char*) end); +#endif /*_mini_client_c*/ + /* We have to handle different version of handshake here */ +#if defined(_CUSTOMCONFIG_) && defined(_libmysql_c) +#include "_cust_libmysql.h"; +#endif + DBUG_PRINT("info",("user: %s",end)); + /* + We always start with old type handshake the only difference is message sent + If server handles secure connection type we'll not send the real scramble + */ + if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) + { + if (passwd[0]) + { + /* Prepare false scramble */ + end=strend(end)+1; + bfill(end, SCRAMBLE_LENGTH, 'x'); + end+=SCRAMBLE_LENGTH; + *end=0; + } + else /* For empty password*/ + { + end=strend(end)+1; + *end=0; /* Store zero length scramble */ + } + } + else + { + /* + Real scramble is only sent to old servers. This can be blocked + by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); + */ + end=scramble(strend(end)+1, mysql->scramble_buff, passwd, + (my_bool) (mysql->protocol_version == 9)); + } + /* Add database if needed */ + if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) + { + end=strmake(end+1,db,NAME_LEN); + mysql->db=my_strdup(db,MYF(MY_WME)); + db=0; + } + /* Write authentication package */ + if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } + + if (mysql_autenticate(mysql, passwd)) + goto error; + + if (client_flag & CLIENT_COMPRESS) /* We will use compression */ + net->compress=1; + +#ifdef _libmysql_c + if (mysql->options.max_allowed_packet) + net->max_packet_size= mysql->options.max_allowed_packet; + if (db && mysql_select_db(mysql,db)) + goto error; + + if (mysql->options.init_commands) + { + DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; + char **ptr= (char**)init_commands->buffer; + char **end= ptr + init_commands->elements; + + my_bool reconnect=mysql->reconnect; + mysql->reconnect=0; + + for (; ptrfields) + { + if (!(res= mysql_use_result(mysql))) + goto error; + mysql_free_result(res); + } + } + + mysql->reconnect=reconnect; + } + + if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) + goto error; +#endif /*_libmysql_c*/ + + DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); + reset_sigpipe(mysql); + DBUG_RETURN(mysql); + +error: + reset_sigpipe(mysql); + DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); + { + /* Free alloced memory */ + my_bool free_me=mysql->free_me; + end_server(mysql); + mysql->free_me=0; + mysql_close(mysql); + mysql->free_me=free_me; + } + DBUG_RETURN(0); +} + +/* needed when we move MYSQL structure to a different address */ + +static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) +{ + MYSQL *tmp, *tmp_prev; + if (mysql->master == old_mysql) + mysql->master = mysql; + if (mysql->last_used_con == old_mysql) + mysql->last_used_con = mysql; + if (mysql->last_used_slave == old_mysql) + mysql->last_used_slave = mysql; + for (tmp_prev = mysql, tmp = mysql->next_slave; + tmp != old_mysql;tmp = tmp->next_slave) + { + tmp_prev = tmp; + } + tmp_prev->next_slave = mysql; +} + +my_bool mysql_reconnect(MYSQL *mysql) +{ + MYSQL tmp_mysql; + DBUG_ENTER("mysql_reconnect"); + + if (!mysql->reconnect +#ifdef _libmysql_c + || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info +#endif +) + { + /* Allow reconnect next time */ +#ifdef _libmysql_c + mysql->server_status&= ~SERVER_STATUS_IN_TRANS; +#endif + mysql->net.last_errno=CR_SERVER_GONE_ERROR; + strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + DBUG_RETURN(1); + } + mysql_init(&tmp_mysql); + tmp_mysql.options=mysql->options; + bzero((char*) &mysql->options,sizeof(mysql->options)); + tmp_mysql.rpl_pivot = mysql->rpl_pivot; + if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, + mysql->db, mysql->port, mysql->unix_socket, + mysql->client_flag +#ifdef _mini_client_c + , mysql->net.read_timeout +#endif +)) + { + mysql->net.last_errno= tmp_mysql.net.last_errno; + strmov(mysql->net.last_error, tmp_mysql.net.last_error); + DBUG_RETURN(1); + } + tmp_mysql.free_me=mysql->free_me; + mysql->free_me=0; + mysql_close(mysql); + *mysql=tmp_mysql; +#ifdef _libmysql_c + mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ +#endif + net_clear(&mysql->net); + mysql->affected_rows= ~(my_ulonglong) 0; + DBUG_RETURN(0); +} + +/************************************************************************** + Set current database +**************************************************************************/ + +int STDCALL +mysql_select_db(MYSQL *mysql, const char *db) +{ + int error; + DBUG_ENTER("mysql_select_db"); + DBUG_PRINT("enter",("db: '%s'",db)); + + if ((error=simple_command(mysql,COM_INIT_DB,db,(ulong) strlen(db),0))) + DBUG_RETURN(error); + my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); + mysql->db=my_strdup(db,MYF(MY_WME)); + DBUG_RETURN(0); +} + +/* + Free strings in the SSL structure and clear 'use_ssl' flag. + NB! Errors are not reported until you do mysql_real_connect. +*/ + +#ifdef HAVE_OPENSSL +static void +mysql_ssl_free(MYSQL *mysql __attribute__((unused))) +{ + my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.ssl_key = 0; + mysql->options.ssl_cert = 0; + mysql->options.ssl_ca = 0; + mysql->options.ssl_capath = 0; + mysql->options.ssl_cipher= 0; + mysql->options.use_ssl = FALSE; + mysql->connector_fd = 0; +} +#endif /* HAVE_OPENSSL */ + +/************************************************************************* + Send a QUIT to the server and close the connection + If handle is alloced by mysql connect free it. +*************************************************************************/ + +void STDCALL +mysql_close(MYSQL *mysql) +{ + DBUG_ENTER("mysql_close"); + if (mysql) /* Some simple safety */ + { + if (mysql->net.vio != 0) + { + free_old_query(mysql); + mysql->status=MYSQL_STATUS_READY; /* Force command */ + mysql->reconnect=0; + simple_command(mysql,COM_QUIT,NullS,0,1); + end_server(mysql); /* Sets mysql->net.vio= 0 */ + } + my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); +#ifdef _libmysql_c + my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); + if (mysql->options.init_commands) + { + DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; + char **ptr= (char**)init_commands->buffer; + char **end= ptr + init_commands->elements; + for (; ptroptions.shared_memory_base_name != def_shared_memory_base_name) + my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); +#endif /* HAVE_SMEM */ + + /* free/close slave list */ + if (mysql->rpl_pivot) + { + MYSQL* tmp; + for (tmp = mysql->next_slave; tmp != mysql; ) + { + /* trick to avoid following freed pointer */ + MYSQL* tmp1 = tmp->next_slave; + mysql_close(tmp); + tmp = tmp1; + } + mysql->rpl_pivot=0; + } + if (mysql->stmts) + { + /* Free any open prepared statements */ + LIST *element, *next_element; + for (element= mysql->stmts; element; element= next_element) + { + next_element= element->next; + stmt_close((MYSQL_STMT *)element->data, 0); + } + } + if (mysql != mysql->master) + mysql_close(mysql->master); +#endif /*_libmysql_c*/ + +#ifdef HAVE_OPENSSL + mysql_ssl_free(mysql); +#endif /* HAVE_OPENSSL */ + /* Clear pointers for better safety */ + + mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; + bzero((char*) &mysql->options,sizeof(mysql->options)); + if (mysql->free_me) + my_free((gptr) mysql,MYF(0)); + } + DBUG_VOID_RETURN; +} + +my_bool STDCALL mysql_read_query_result(MYSQL *mysql) +{ + uchar *pos; + ulong field_count; + MYSQL_DATA *fields; + ulong length; + DBUG_ENTER("mysql_read_query_result"); + +#ifdef _libmysql_c + /* + Read from the connection which we actually used, which + could differ from the original connection if we have slaves + */ + mysql = mysql->last_used_con; +#endif + + if ((length = net_safe_read(mysql)) == packet_error) + DBUG_RETURN(1); + free_old_query(mysql); /* Free old result */ +get_info: + pos=(uchar*) mysql->net.read_pos; + if ((field_count= net_field_length(&pos)) == 0) + { + mysql->affected_rows= net_field_length_ll(&pos); + mysql->insert_id= net_field_length_ll(&pos); +#ifdef _libmysql_c + if (protocol_41(mysql)) + { + mysql->server_status=uint2korr(pos); pos+=2; + mysql->warning_count=uint2korr(pos); pos+=2; + } + else +#endif /*libmysql_c*/ + if (mysql->server_capabilities & CLIENT_TRANSACTIONS) + { + mysql->server_status=uint2korr(pos); pos+=2; + mysql->warning_count= 0; + } + DBUG_PRINT("info",("status: %ld warning_count: %ld", + mysql->server_status, mysql->warning_count)); + if (pos < mysql->net.read_pos+length && net_field_length(&pos)) + mysql->info=(char*) pos; + DBUG_RETURN(0); + } + if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ + { + int error=send_file_to_server(mysql,(char*) pos); + if ((length=net_safe_read(mysql)) == packet_error || error) + DBUG_RETURN(1); + goto get_info; /* Get info packet */ + } + if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) + mysql->server_status|= SERVER_STATUS_IN_TRANS; + + mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ + + if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, +#ifdef _libmysql_c + protocol_41(mysql) ? 6 : +#endif + 5))) + DBUG_RETURN(1); + if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, + (uint) field_count,0, + mysql->server_capabilities))) + DBUG_RETURN(1); + mysql->status= MYSQL_STATUS_GET_RESULT; + mysql->field_count= (uint) field_count; + mysql->warning_count= 0; + DBUG_RETURN(0); +} + + +/* + Send the query and return so we can do something else. + Needs to be followed by mysql_read_query_result() when we want to + finish processing it. +*/ + +int STDCALL +mysql_send_query(MYSQL* mysql, const char* query, ulong length) +{ + DBUG_ENTER("mysql_send_query"); + DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d", + mysql->options.rpl_parse, mysql->rpl_pivot)); +#ifdef _libmysql_c + if (mysql->options.rpl_parse && mysql->rpl_pivot) + { + switch (mysql_rpl_query_type(query, length)) { + case MYSQL_RPL_MASTER: + DBUG_RETURN(mysql_master_send_query(mysql, query, length)); + case MYSQL_RPL_SLAVE: + DBUG_RETURN(mysql_slave_send_query(mysql, query, length)); + case MYSQL_RPL_ADMIN: + break; /* fall through */ + } + } + + mysql->last_used_con = mysql; +#endif /*libmysql_c*/ + + DBUG_RETURN(simple_command(mysql, COM_QUERY, query, length, 1)); +} + + +int STDCALL +mysql_real_query(MYSQL *mysql, const char *query, ulong length) +{ + DBUG_ENTER("mysql_real_query"); + DBUG_PRINT("enter",("handle: %lx",mysql)); + DBUG_PRINT("query",("Query = '%-.4096s'",query)); + + if (mysql_send_query(mysql,query,length)) + DBUG_RETURN(1); + DBUG_RETURN((int) mysql_read_query_result(mysql)); +} + +static my_bool +send_file_to_server(MYSQL *mysql, const char *filename) +{ + int fd, readcount; + my_bool result= 1; + uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); + char *buf, tmp_name[FN_REFLEN]; + DBUG_ENTER("send_file_to_server"); + + if (!(buf=my_malloc(packet_length,MYF(0)))) + { + strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY)); + DBUG_RETURN(1); + } + + fn_format(tmp_name,filename,"","",4); /* Convert to client format */ + if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) + { + my_net_write(&mysql->net,"",0); /* Server needs one packet */ + net_flush(&mysql->net); + mysql->net.last_errno=EE_FILENOTFOUND; + my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, + EE(mysql->net.last_errno),tmp_name, errno); + goto err; + } + + while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) + { + if (my_net_write(&mysql->net,buf,readcount)) + { + DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); + mysql->net.last_errno=CR_SERVER_LOST; + strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + goto err; + } + } + /* Send empty packet to mark end of file */ + if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net)) + { + mysql->net.last_errno=CR_SERVER_LOST; + sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno); + goto err; + } + if (readcount < 0) + { + mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */ + my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, + tmp_name,errno); + goto err; + } + result=0; /* Ok */ + +err: + if (fd >= 0) + (void) my_close(fd,MYF(0)); + my_free(buf,MYF(0)); + DBUG_RETURN(result); +} + +/************************************************************************** + Alloc result struct for buffered results. All rows are read to buffer. + mysql_data_seek may be used. +**************************************************************************/ + +MYSQL_RES * STDCALL +mysql_store_result(MYSQL *mysql) +{ + MYSQL_RES *result; + DBUG_ENTER("mysql_store_result"); + +#ifdef _libmysql_c + /* read from the actually used connection */ + mysql = mysql->last_used_con; +#endif + if (!mysql->fields) + DBUG_RETURN(0); + if (mysql->status != MYSQL_STATUS_GET_RESULT) + { + strmov(mysql->net.last_error, + ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + DBUG_RETURN(0); + } + mysql->status=MYSQL_STATUS_READY; /* server is ready */ + if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+ + sizeof(ulong) * + mysql->field_count), + MYF(MY_WME | MY_ZEROFILL)))) + { + mysql->net.last_errno=CR_OUT_OF_MEMORY; + strmov(mysql->net.last_error, ER(mysql->net.last_errno)); + DBUG_RETURN(0); + } + result->eof=1; /* Marker for buffered */ + result->lengths=(ulong*) (result+1); + if (!(result->data=read_rows(mysql,mysql->fields,mysql->field_count))) + { + my_free((gptr) result,MYF(0)); + DBUG_RETURN(0); + } + mysql->affected_rows= result->row_count= result->data->rows; + result->data_cursor= result->data->data; + result->fields= mysql->fields; + result->field_alloc= mysql->field_alloc; + result->field_count= mysql->field_count; + result->current_field=0; + result->current_row=0; /* Must do a fetch first */ + mysql->fields=0; /* fields is now in result */ + DBUG_RETURN(result); /* Data fetched */ +} + +/************************************************************************** + Return next row of the query results +**************************************************************************/ + +MYSQL_ROW STDCALL +mysql_fetch_row(MYSQL_RES *res) +{ + DBUG_ENTER("mysql_fetch_row"); + if (!res->data) + { /* Unbufferred fetch */ + if (!res->eof) + { + if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths))) + { + res->row_count++; + DBUG_RETURN(res->current_row=res->row); + } + else + { + DBUG_PRINT("info",("end of data")); + res->eof=1; + res->handle->status=MYSQL_STATUS_READY; + /* Don't clear handle in mysql_free_results */ + res->handle=0; + } + } + DBUG_RETURN((MYSQL_ROW) NULL); + } + { + MYSQL_ROW tmp; + if (!res->data_cursor) + { + DBUG_PRINT("info",("end of data")); + DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL); + } + tmp = res->data_cursor->data; + res->data_cursor = res->data_cursor->next; + DBUG_RETURN(res->current_row=tmp); + } +} + +/************************************************************************** + Move to a specific row and column +**************************************************************************/ + +void STDCALL +mysql_data_seek(MYSQL_RES *result, my_ulonglong row) +{ + MYSQL_ROWS *tmp=0; + DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); + if (result->data) + for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; + result->current_row=0; + result->data_cursor = tmp; +} + +/**************************************************************************** + Functions to get information from the MySQL structure + These are functions to make shared libraries more usable. +****************************************************************************/ + +/* MYSQL_RES */ +my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res) +{ + return res->row_count; +} + +unsigned int STDCALL mysql_num_fields(MYSQL_RES *res) +{ + return res->field_count; +} + +uint STDCALL mysql_errno(MYSQL *mysql) +{ + return mysql->net.last_errno; +} + +const char * STDCALL mysql_error(MYSQL *mysql) +{ + return mysql->net.last_error; +} diff --git a/sql/mini_client.cc b/sql/mini_client.cc index afcee5fbb02..8c431c0d1be 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -76,18 +76,6 @@ extern "C" { // Because of SCO 3.2V4.2 #endif } -static void mc_free_rows(MYSQL_DATA *cur); -void mc_end_server(MYSQL *mysql); -static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to); -static void mc_free_old_query(MYSQL *mysql); -static int mc_send_file_to_server(MYSQL *mysql, const char *filename); -static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, - ulong *lengths); -static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - uint fields); - - - #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) @@ -99,1324 +87,13 @@ static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, #define SOCKET_ERROR -1 #endif -#ifdef __WIN__ -static my_bool is_NT(void) -{ - char *os=getenv("OS"); - return (os && !strcmp(os, "Windows_NT")) ? 1 : 0; -} -#endif - extern ulong slave_net_timeout; - -/* -** Create a named pipe connection -*/ - -#ifdef __WIN__ - -HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, - char **arg_unix_socket) -{ - HANDLE hPipe=INVALID_HANDLE_VALUE; - char szPipeName [ 257 ]; - DWORD dwMode; - int i; - my_bool testing_named_pipes=0; - char *host= *arg_host, *unix_socket= *arg_unix_socket; - - if (!host || !strcmp(host,LOCAL_HOST)) - host=LOCAL_HOST_NAMEDPIPE; - - sprintf(szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); - DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", - host, unix_socket)); - - for (i=0 ; i < 100 ; i++) /* Don't retry forever */ - { - if ((hPipe = CreateFile(szPipeName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL )) != INVALID_HANDLE_VALUE) - break; - if (GetLastError() != ERROR_PIPE_BUSY) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - /* wait for for an other instance */ - if (! WaitNamedPipe(szPipeName, connect_timeout*1000) ) - { - net->last_errno=CR_NAMEDPIPEWAIT_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - } - if (hPipe == INVALID_HANDLE_VALUE) - { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; - if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) ) - { - CloseHandle( hPipe ); - net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); - return INVALID_HANDLE_VALUE; - } - *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */ - return (hPipe); -} -#endif - - -/**************************************************************************** -** Init MySQL structure or allocate one -****************************************************************************/ - -MYSQL *mc_mysql_init(MYSQL *mysql) -{ - init_client_errs(); - if (!mysql) - { - if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) - return 0; - mysql->free_me=1; - mysql->net.vio = 0; - } - else - bzero((char*) (mysql),sizeof(*(mysql))); -#ifdef __WIN__ - mysql->options.connect_timeout=20; -#endif - mysql->net.read_timeout = slave_net_timeout; - return mysql; -} - -/************************************************************************** -** Shut down connection -**************************************************************************/ - -void -mc_end_server(MYSQL *mysql) -{ - DBUG_ENTER("mc_end_server"); - if (mysql->net.vio != 0) - { - DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); - vio_delete(mysql->net.vio); - mysql->net.vio= 0; /* Marker */ - } - net_end(&mysql->net); - mc_free_old_query(mysql); - DBUG_VOID_RETURN; -} - -static void mc_free_old_query(MYSQL *mysql) -{ - DBUG_ENTER("mc_free_old_query"); - if (mysql->fields) - free_root(&mysql->field_alloc,MYF(0)); - else - init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ - mysql->fields=0; - mysql->field_count=0; /* For API */ - DBUG_VOID_RETURN; -} - - -/**************************************************************************** -* A modified version of connect(). mc_sock_connect() allows you to specify -* a timeout value, in seconds, that we should wait until we -* derermine we can't connect to a particular host. If timeout is 0, -* mc_sock_connect() will behave exactly like connect(). -* -* Base version coded by Steve Bernacki, Jr. -*****************************************************************************/ - -static int mc_sock_connect(my_socket s, const struct sockaddr *name, - uint namelen, uint to) -{ -#if defined(__WIN__) || defined(OS2) - return connect(s, (struct sockaddr*) name, namelen); -#else - int flags, res, s_err; - SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); - fd_set sfds; - struct timeval tv; - - /* If they passed us a timeout of zero, we should behave - * exactly like the normal connect() call does. - */ - - if (to == 0) - return connect(s, (struct sockaddr*) name, namelen); - - flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ -#ifdef O_NONBLOCK - fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ -#endif - - res = connect(s, (struct sockaddr*) name, namelen); - s_err = errno; /* Save the error... */ - fcntl(s, F_SETFL, flags); - if ((res != 0) && (s_err != EINPROGRESS)) - { - errno = s_err; /* Restore it */ - return(-1); - } - if (res == 0) /* Connected quickly! */ - return(0); - - /* Otherwise, our connection is "in progress." We can use - * the select() call to wait up to a specified period of time - * for the connection to suceed. If select() returns 0 - * (after waiting howevermany seconds), our socket never became - * writable (host is probably unreachable.) Otherwise, if - * select() returns 1, then one of two conditions exist: - * - * 1. An error occured. We use getsockopt() to check for this. - * 2. The connection was set up sucessfully: getsockopt() will - * return 0 as an error. - * - * Thanks goes to Andrew Gierth - * who posted this method of timing out a connect() in - * comp.unix.programmer on August 15th, 1997. - */ - - FD_ZERO(&sfds); - FD_SET(s, &sfds); - tv.tv_sec = (long) to; - tv.tv_usec = 0; -#ifdef HPUX10 - res = select(s+1, NULL, (int*) &sfds, NULL, &tv); -#else - res = select(s+1, NULL, &sfds, NULL, &tv); -#endif /* HPUX10 */ - if (res <= 0) /* Never became writable */ - return(-1); - - /* select() returned something more interesting than zero, let's - * see if we have any errors. If the next two statements pass, - * we've got an open socket! - */ - - s_err=0; - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) - return(-1); - - if (s_err) - { // getsockopt() could succeed - errno = s_err; - return(-1); // but return an error... - } - return(0); /* It's all good! */ -#endif -} - -/***************************************************************************** -** read a packet from server. Give error message if socket was down -** or packet is an error message -*****************************************************************************/ - -ulong -mc_net_safe_read(MYSQL *mysql) -{ - NET *net= &mysql->net; - ulong len=0; - - if (net->vio != 0) - len=my_net_read(net); - - if (len == packet_error || len == 0) - { - DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", - vio_description(net->vio),len)); - if (socket_errno != SOCKET_EINTR) - { - mc_end_server(mysql); - if (net->last_errno != ER_NET_PACKET_TOO_LARGE) - { - net->last_errno=CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - } - else - strmov(net->last_error, "Packet too large - increase \ -max_allowed_packet on this server"); - } - return(packet_error); - } - if (net->read_pos[0] == 255) - { - if (len > 3) - { - char *pos=(char*) net->read_pos+1; - if (mysql->protocol_version > 9) - { /* New client protocol */ - net->last_errno=uint2korr(pos); - pos+=2; - len-=2; - if (!net->last_errno) - net->last_errno = CR_UNKNOWN_ERROR; - } - else - { - net->last_errno=CR_UNKNOWN_ERROR; - len--; - } - (void) strmake(net->last_error,(char*) pos, - min(len,sizeof(net->last_error)-1)); - } - else - { - net->last_errno=CR_UNKNOWN_ERROR; - (void) strmov(net->last_error,ER(net->last_errno)); - } - DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno, - net->last_error)); - return(packet_error); - } - return len; -} - - -char *mc_mysql_error(MYSQL *mysql) -{ - return (mysql)->net.last_error; -} - -int mc_mysql_errno(MYSQL *mysql) -{ - return (mysql)->net.last_errno; -} - - -my_bool mc_mysql_reconnect(MYSQL *mysql) -{ - MYSQL tmp_mysql; - DBUG_ENTER("mc_mysql_reconnect"); - - if (!mysql->reconnect) - { - mysql->net.last_errno=CR_SERVER_GONE_ERROR; - strmov(mysql->net.last_error, ER(mysql->net.last_errno)); - DBUG_RETURN(1); - } - mc_mysql_init(&tmp_mysql); - tmp_mysql.options=mysql->options; - if (!mc_mysql_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, - mysql->db, mysql->port, mysql->unix_socket, - mysql->client_flag, mysql->net.read_timeout)) - { - mysql->net.last_errno= tmp_mysql.net.last_errno; - strmov(mysql->net.last_error, tmp_mysql.net.last_error); - DBUG_RETURN(1); - } - tmp_mysql.free_me=mysql->free_me; - mysql->free_me=0; - bzero((char*) &mysql->options,sizeof(&mysql->options)); - mc_mysql_close(mysql); - *mysql=tmp_mysql; - net_clear(&mysql->net); - mysql->affected_rows= ~(my_ulonglong) 0; - DBUG_RETURN(0); -} - - - -int -mc_simple_command(MYSQL *mysql,enum enum_server_command command, - const char *arg, uint length, my_bool skipp_check) -{ - NET *net= &mysql->net; - int result= -1; - - if (mysql->net.vio == 0) - { /* Do reconnect if possible */ - if (mc_mysql_reconnect(mysql)) - goto end; - } - if (mysql->status != MYSQL_STATUS_READY) - { - strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - goto end; - } - - mysql->net.last_error[0]=0; - mysql->net.last_errno=0; - mysql->net.report_error=0; - mysql->info=0; - mysql->affected_rows= ~(my_ulonglong) 0; - net_clear(net); /* Clear receive buffer */ - if (!arg) - arg=""; - - if (net_write_command(net, (uchar) command, NullS, 0, arg, length)) - { - DBUG_PRINT("error",("Can't send command to server. Error: %d", - socket_errno)); - mc_end_server(mysql); - if (mc_mysql_reconnect(mysql)) - goto end; - if (net_write_command(net,(uchar) command, NullS, 0, arg, length)) - { - net->last_errno=CR_SERVER_GONE_ERROR; - strmov(net->last_error,ER(net->last_errno)); - goto end; - } - } - result=0; - if (!skipp_check) - result= ((mysql->packet_length=mc_net_safe_read(mysql)) == packet_error ? - -1 : 0); - end: - return result; -} - - -MYSQL * -mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, - const char *passwd, const char *db, - uint port, const char *unix_socket,uint client_flag, - uint net_read_timeout) -{ - char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info; - char password_hash[SCRAMBLE41_LENGTH]; - my_socket sock; - ulong ip_addr; - struct sockaddr_in sock_addr; - ulong pkt_length; - NET *net= &mysql->net; - thr_alarm_t alarmed; - ALARM alarm_buff; - ulong max_allowed_packet; - -#ifdef __WIN__ - HANDLE hPipe=INVALID_HANDLE_VALUE; -#endif -#ifdef HAVE_SYS_UN_H - struct sockaddr_un UNIXaddr; -#endif - DBUG_ENTER("mc_mysql_connect"); - DBUG_PRINT("enter",("host: %s db: %s user: %s connect_time_out: %u read_timeout: %u", - host ? host : "(Null)", - db ? db : "(Null)", - user ? user : "(Null)", - net_read_timeout, - (uint) slave_net_timeout)); - net->vio = 0; /* If something goes wrong */ - mysql->charset=default_charset_info; /* Set character set */ - if (!port) - port = MYSQL_PORT; /* Should always be set by mysqld */ - if (!unix_socket) - unix_socket=MYSQL_UNIX_ADDR; - - mysql->reconnect=1; /* Reconnect as default */ - mysql->server_status=SERVER_STATUS_AUTOCOMMIT; - if (!mysql->options.connect_timeout) - mysql->options.connect_timeout= net_read_timeout; - - /* - ** Grab a socket and connect it to the server - */ - -#if defined(HAVE_SYS_UN_H) - if ((!host || !strcmp(host,LOCAL_HOST)) && unix_socket) - { - host=LOCAL_HOST; - host_info=(char*) ER(CR_LOCALHOST_CONNECTION); - DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); - if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) - { - net->last_errno=CR_SOCKET_CREATE_ERROR; - sprintf(net->last_error,ER(net->last_errno),socket_errno); - goto error; - } - net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); - bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); - UNIXaddr.sun_family = AF_UNIX; - strmov(UNIXaddr.sun_path, unix_socket); - if (mc_sock_connect(sock, - my_reinterpret_cast(struct sockaddr *) (&UNIXaddr), - sizeof(UNIXaddr), - mysql->options.connect_timeout) <0) - { - DBUG_PRINT("error",("Got error %d on connect to local server", - socket_errno)); - net->last_errno=CR_CONNECTION_ERROR; - sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); - goto error; - } - } - else -#elif defined(__WIN__) - { - if ((unix_socket || - !host && is_NT() || - host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) || - mysql->options.named_pipe || !have_tcpip)) - { - sock=0; - if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, - (char**) &host, (char**) &unix_socket)) == - INVALID_HANDLE_VALUE) - { - DBUG_PRINT("error", - ("host: '%s' socket: '%s' named_pipe: %d have_tcpip: %d", - host ? host : "", - unix_socket ? unix_socket : "", - (int) mysql->options.named_pipe, - (int) have_tcpip)); - if (mysql->options.named_pipe || - (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || - (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) - goto error; /* User only requested named pipes */ - /* Try also with TCP/IP */ - } - else - { - net->vio=vio_new_win32pipe(hPipe); - sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host, - unix_socket); - } - } - } - if (hPipe == INVALID_HANDLE_VALUE) -#endif - { - unix_socket=0; /* This is not used */ - if (!host) - host=LOCAL_HOST; - sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); - DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); - 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); - goto error; - } - net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE); - bzero((char*) &sock_addr,sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - - /* - ** The server name may be a host name or IP address - */ - - if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) - { - memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); - } - else - { - int tmp_errno; - struct hostent tmp_hostent,*hp; - char buff2[GETHOSTBYNAME_BUFF_SIZE]; - hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), - &tmp_errno); - if (!hp) - { - net->last_errno=CR_UNKNOWN_HOST; - sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); - my_gethostbyname_r_free(); - goto error; - } - memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); - my_gethostbyname_r_free(); - } - sock_addr.sin_port = (ushort) htons((ushort) port); - if (mc_sock_connect(sock, - my_reinterpret_cast(struct sockaddr *) (&sock_addr), - sizeof(sock_addr), - mysql->options.connect_timeout) <0) - { - DBUG_PRINT("error",("Got error %d on connect to '%s'", - socket_errno,host)); - net->last_errno= CR_CONN_HOST_ERROR; - sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); - goto error; - } - } - - if (!net->vio || my_net_init(net, net->vio)) - { - vio_delete(net->vio); - net->vio = 0; - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - vio_keepalive(net->vio,TRUE); - net->read_timeout=slave_net_timeout; - /* Get version info */ - mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ - if (mysql->options.connect_timeout && - vio_poll_read(net->vio, mysql->options.connect_timeout)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - if ((pkt_length=mc_net_safe_read(mysql)) == packet_error) - goto error; - - /* Check if version of protocol matches current one */ - - mysql->protocol_version= net->read_pos[0]; - DBUG_DUMP("packet",(char*) net->read_pos,10); - DBUG_PRINT("info",("mysql protocol version %d, server=%d", - PROTOCOL_VERSION, mysql->protocol_version)); - if (mysql->protocol_version != PROTOCOL_VERSION && - mysql->protocol_version != PROTOCOL_VERSION-1) - { - net->last_errno= CR_VERSION_ERROR; - sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, - PROTOCOL_VERSION); - goto error; - } - end=strend((char*) net->read_pos+1); - mysql->thread_id=uint4korr(end+1); - end+=5; - strmake(mysql->scramble_buff,end,8); - end+=9; - if (pkt_length >= (uint) (end+1 - (char*) net->read_pos)) - mysql->server_capabilities=uint2korr(end); - if (pkt_length >= (uint) (end+18 - (char*) net->read_pos)) - { - /* New protocol with 16 bytes to describe server characteristics */ - mysql->server_language=end[2]; - mysql->server_status=uint2korr(end+3); - } - - /* Save connection information */ - if (!user) user=""; - if (!passwd) passwd=""; - if (!my_multi_malloc(MYF(0), - &mysql->host_info, (uint) strlen(host_info)+1, - &mysql->host, (uint) strlen(host)+1, - &mysql->unix_socket, - unix_socket ? (uint) strlen(unix_socket)+1 : (uint) 1, - &mysql->server_version, - (uint) (end - (char*) net->read_pos), - NullS) || - !(mysql->user=my_strdup(user,MYF(0))) || - !(mysql->passwd=my_strdup(passwd,MYF(0)))) - { - strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); - goto error; - } - strmov(mysql->host_info,host_info); - strmov(mysql->host,host); - if (unix_socket) - strmov(mysql->unix_socket,unix_socket); - else - mysql->unix_socket=0; - strmov(mysql->server_version,(char*) net->read_pos+1); - mysql->port=port; - client_flag|=mysql->options.client_flag; - DBUG_PRINT("info",("Server version = '%s' capabilites: %ld", - mysql->server_version,mysql->server_capabilities)); - - /* Send client information for access check */ - client_flag|=CLIENT_CAPABILITIES; - -#ifdef HAVE_OPENSSL - if (mysql->options.ssl_key || mysql->options.ssl_cert || - mysql->options.ssl_ca || mysql->options.ssl_capath || - mysql->options.ssl_cipher) - mysql->options.use_ssl= 1; - if (mysql->options.use_ssl) - client_flag|=CLIENT_SSL; -#endif /* HAVE_OPENSSL */ - - if (db) - client_flag|=CLIENT_CONNECT_WITH_DB; -#ifdef HAVE_COMPRESS - if ((mysql->server_capabilities & CLIENT_COMPRESS) && - (mysql->options.compress || (client_flag & CLIENT_COMPRESS))) - client_flag|=CLIENT_COMPRESS; /* We will use compression */ - else -#endif - client_flag&= ~CLIENT_COMPRESS; - -#ifdef HAVE_OPENSSL - if ((mysql->server_capabilities & CLIENT_SSL) && - (mysql->options.use_ssl || (client_flag & CLIENT_SSL))) - { - DBUG_PRINT("info", ("Changing IO layer to SSL")); - client_flag |= CLIENT_SSL; - } - else - { - if (client_flag & CLIENT_SSL) - { - DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL")); - } - client_flag &= ~CLIENT_SSL; - } -#endif /* HAVE_OPENSSL */ - - int2store(buff,client_flag); - mysql->client_flag=client_flag; - -#ifdef HAVE_OPENSSL - /* - Oops.. are we careful enough to not send ANY information without - encryption? - */ - if (client_flag & CLIENT_SSL) - { - if (my_net_write(net,buff,(uint) (2)) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - /* Do the SSL layering. */ - DBUG_PRINT("info", ("IO layer change in progress...")); - DBUG_PRINT("info", ("IO context %p",((struct st_VioSSLConnectorFd*)mysql->connector_fd)->ssl_context_)); - sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio, (long)(mysql->options.connect_timeout)); - DBUG_PRINT("info", ("IO layer change done!")); - } -#endif /* HAVE_OPENSSL */ - max_allowed_packet=mysql->net.max_packet_size; - int3store(buff+2,max_allowed_packet); - - - if (user && user[0]) - strmake(buff+5,user,32); - else - { - user = getenv("USER"); - if (!user) user = "mysql"; - strmov((char*) buff+5, user ); - } - - DBUG_PRINT("info",("user: %s",buff+5)); - - /* - We always start with old type handshake the only difference is message sent - If server handles secure connection type we'll not send the real scramble - */ - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - if (passwd[0]) - { - /* Prepare false scramble */ - end=strend(buff+5)+1; - bfill(end, SCRAMBLE_LENGTH, 'x'); - end+=SCRAMBLE_LENGTH; - *end=0; - } - else /* For empty password*/ - { - end=strend(buff+5)+1; - *end=0; /* Store zero length scramble */ - } - } - else - { - /* - Real scramble is only sent to old servers. This can be blocked - by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); - */ - end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, - (my_bool) (mysql->protocol_version == 9)); - - } - /* Add database if needed */ - if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) - { - end=strmake(end+1,db,NAME_LEN); - mysql->db=my_strdup(db,MYF(MY_WME)); - db=0; - } - /* Write authentication package */ - if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - - /* We shall only query sever if it expect us to do so */ - - if ( (pkt_length=mc_net_safe_read(mysql)) == packet_error) - goto error; - - if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) - { - /* This should always happen with new server unless empty password */ - if (pkt_length==24 && net->read_pos[0]) - /* OK/Error message has zero as the first character */ - { - /* Old passwords will have zero at the first byte of hash */ - if (net->read_pos[0] != '*') - { - /* Build full password hash as it is required to decode scramble */ - password_hash_stage1(buff, passwd); - /* Store copy as we'll need it later */ - memcpy(password_hash,buff,SCRAMBLE41_LENGTH); - /* Finally hash complete password using hash we got from server */ - password_hash_stage2(password_hash,(char*)net->read_pos); - /* Decypt and store scramble 4 = hash for stage2 */ - password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash, - SCRAMBLE41_LENGTH); - mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; - /* Encode scramble with password. Recycle buffer */ - password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH); - } - else - { - /* Create password to decode scramble */ - create_key_from_old_password(passwd,password_hash); - /* Decypt and store scramble 4 = hash for stage2 */ - password_crypt((char*)net->read_pos+4,mysql->scramble_buff,password_hash, - SCRAMBLE41_LENGTH); - mysql->scramble_buff[SCRAMBLE41_LENGTH]=0; - /* Finally scramble decoded scramble with password */ - scramble(buff, mysql->scramble_buff, passwd,0); - } - /* Write second package of authentication */ - if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net)) - { - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); - goto error; - } - /* Read What server thinks about out new auth message report */ - if (mc_net_safe_read(mysql) == packet_error) - goto error; - } - } - - /* End of authentication part of handshake */ - - if (client_flag & CLIENT_COMPRESS) /* We will use compression */ - net->compress=1; - DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); - DBUG_RETURN(mysql); - -error: - DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); - { - /* Free alloced memory */ - my_bool free_me=mysql->free_me; - mc_end_server(mysql); - mysql->free_me=0; - mc_mysql_close(mysql); - mysql->free_me=free_me; - } - DBUG_RETURN(0); -} - - -#ifdef HAVE_OPENSSL -/* -************************************************************************** -** Free strings in the SSL structure and clear 'use_ssl' flag. -** NB! Errors are not reported until you do mysql_real_connect. -************************************************************************** -*/ -int -mysql_ssl_clear(MYSQL *mysql) -{ - my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.ssl_key = 0; - mysql->options.ssl_cert = 0; - mysql->options.ssl_ca = 0; - mysql->options.ssl_capath = 0; - mysql->options.ssl_cipher= 0; - mysql->options.use_ssl = FALSE; - my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); - mysql->connector_fd = 0; - return 0; -} -#endif /* HAVE_OPENSSL */ - -/************************************************************************* -** Send a QUIT to the server and close the connection -** If handle is alloced by mysql connect free it. -*************************************************************************/ - -void -mc_mysql_close(MYSQL *mysql) -{ - DBUG_ENTER("mysql_close"); - if (mysql) /* Some simple safety */ - { - if (mysql->net.vio != 0) - { - mc_free_old_query(mysql); - mysql->status=MYSQL_STATUS_READY; /* Force command */ - mysql->reconnect=0; - mc_simple_command(mysql,COM_QUIT,NullS,0,1); - mc_end_server(mysql); - } - my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); - /* Clear pointers for better safety */ - mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; - bzero((char*) &mysql->options,sizeof(mysql->options)); -#ifdef HAVE_OPENSSL - mysql_ssl_clear(mysql); -#endif /* HAVE_OPENSSL */ - if (mysql->free_me) - my_free((gptr) mysql,MYF(0)); - } - DBUG_VOID_RETURN; -} - -void mc_mysql_free_result(MYSQL_RES *result) -{ - DBUG_ENTER("mc_mysql_free_result"); - DBUG_PRINT("enter",("mysql_res: %lx",result)); - if (result) - { - if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT) - { - DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows")); - for (;;) - { - ulong pkt_len; - if ((pkt_len=mc_net_safe_read(result->handle)) == packet_error) - break; - if (pkt_len == 1 && result->handle->net.read_pos[0] == 254) - break; /* End of data */ - } - result->handle->status=MYSQL_STATUS_READY; - } - mc_free_rows(result->data); - if (result->fields) - free_root(&result->field_alloc,MYF(0)); - if (result->row) - my_free((gptr) result->row,MYF(0)); - my_free((gptr) result,MYF(0)); - } - DBUG_VOID_RETURN; -} - -static void mc_free_rows(MYSQL_DATA *cur) -{ - if (cur) - { - free_root(&cur->alloc,MYF(0)); - my_free((gptr) cur,MYF(0)); - } -} - -static MYSQL_FIELD * -mc_unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, - my_bool default_value, my_bool long_flag_protocol) -{ - MYSQL_ROWS *row; - MYSQL_FIELD *field,*result; - DBUG_ENTER("unpack_fields"); - - field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields); - if (!result) - DBUG_RETURN(0); - - for (row=data->data; row ; row = row->next,field++) - { - field->table= strdup_root(alloc,(char*) row->data[0]); - field->name= strdup_root(alloc,(char*) row->data[1]); - field->length= (uint) uint3korr(row->data[2]); - field->type= (enum enum_field_types) (uchar) row->data[3][0]; - if (long_flag_protocol) - { - field->flags= uint2korr(row->data[4]); - field->decimals=(uint) (uchar) row->data[4][2]; - } - else - { - field->flags= (uint) (uchar) row->data[4][0]; - field->decimals=(uint) (uchar) row->data[4][1]; - } - if (INTERNAL_NUM_FIELD(field)) - field->flags|= NUM_FLAG; - if (default_value && row->data[5]) - field->def=strdup_root(alloc,(char*) row->data[5]); - else - field->def=0; - field->max_length= 0; - } - mc_free_rows(data); /* Free old data */ - DBUG_RETURN(result); -} - -int mc_mysql_send_query(MYSQL* mysql, const char* query, uint length) -{ - return mc_simple_command(mysql, COM_QUERY, query, length, 1); -} - - -int mc_mysql_read_query_result(MYSQL *mysql) -{ - uchar *pos; - ulong field_count; - MYSQL_DATA *fields; - ulong length; - DBUG_ENTER("mc_mysql_read_query_result"); - - if ((length = mc_net_safe_read(mysql)) == packet_error) - DBUG_RETURN(-1); - mc_free_old_query(mysql); /* Free old result */ -get_info: - pos=(uchar*) mysql->net.read_pos; - if ((field_count= net_field_length(&pos)) == 0) - { - mysql->affected_rows= net_field_length_ll(&pos); - mysql->insert_id= net_field_length_ll(&pos); - if (mysql->server_capabilities & CLIENT_TRANSACTIONS) - { - mysql->server_status=uint2korr(pos); pos+=2; - } - if (pos < mysql->net.read_pos+length && net_field_length(&pos)) - mysql->info=(char*) pos; - DBUG_RETURN(0); - } - if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ - { - int error=mc_send_file_to_server(mysql,(char*) pos); - if ((length=mc_net_safe_read(mysql)) == packet_error || error) - DBUG_RETURN(-1); - goto get_info; /* Get info packet */ - } - if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) - mysql->server_status|= SERVER_STATUS_IN_TRANS; - - mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ - if (!(fields=mc_read_rows(mysql,(MYSQL_FIELD*) 0,5))) - DBUG_RETURN(-1); - if (!(mysql->fields=mc_unpack_fields(fields,&mysql->field_alloc, - (uint) field_count,0, - (my_bool) test(mysql->server_capabilities & - CLIENT_LONG_FLAG)))) - DBUG_RETURN(-1); - mysql->status=MYSQL_STATUS_GET_RESULT; - mysql->field_count=field_count; - DBUG_RETURN(0); -} - - -int mc_mysql_query(MYSQL *mysql, const char *query, uint length) -{ - DBUG_ENTER("mc_mysql_query"); - DBUG_PRINT("enter",("handle: %lx",mysql)); - DBUG_PRINT("query",("Query = \"%s\"",query)); - DBUG_ASSERT(length == strlen(query)); - if (mc_simple_command(mysql,COM_QUERY,query,length,1)) - DBUG_RETURN(-1); - DBUG_RETURN(mc_mysql_read_query_result(mysql)); -} - - -static int mc_send_file_to_server(MYSQL *mysql, const char *filename) -{ - int fd, readcount, result= -1; - uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); - char *buf, tmp_name[FN_REFLEN]; - DBUG_ENTER("send_file_to_server"); - - if (!(buf=my_malloc(packet_length,MYF(0)))) - { - strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY)); - DBUG_RETURN(-1); - } - - fn_format(tmp_name,filename,"","",4); /* Convert to client format */ - if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) - { - my_net_write(&mysql->net,"",0); // Server needs one packet - net_flush(&mysql->net); - mysql->net.last_errno=EE_FILENOTFOUND; - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - EE(mysql->net.last_errno),tmp_name, errno); - goto err; - } - - while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) - { - if (my_net_write(&mysql->net,buf,readcount)) - { - DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); - mysql->net.last_errno=CR_SERVER_LOST; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - goto err; - } - } - /* Send empty packet to mark end of file */ - if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net)) - { - mysql->net.last_errno=CR_SERVER_LOST; - sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno); - goto err; - } - if (readcount < 0) - { - mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */ - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - tmp_name,errno); - goto err; - } - result=0; // Ok - -err: - if (fd >= 0) - (void) my_close(fd,MYF(0)); - my_free(buf,MYF(0)); - DBUG_RETURN(result); -} - -/* Read all rows (fields or data) from server */ - -static MYSQL_DATA *mc_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, - uint fields) -{ - uint field; - ulong pkt_len; - ulong len; - uchar *cp; - char *to; - MYSQL_DATA *result; - MYSQL_ROWS **prev_ptr,*cur; - NET *net = &mysql->net; - DBUG_ENTER("mc_read_rows"); - - if ((pkt_len=mc_net_safe_read(mysql)) == packet_error) - DBUG_RETURN(0); - if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), - MYF(MY_ZEROFILL)))) - { - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - DBUG_RETURN(0); - } - init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ - result->alloc.min_malloc=sizeof(MYSQL_ROWS); - prev_ptr= &result->data; - result->rows=0; - result->fields=fields; - - while (*(cp=net->read_pos) != 254 || pkt_len != 1) - { - result->rows++; - if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc, - sizeof(MYSQL_ROWS))) || - !(cur->data= ((MYSQL_ROW) - alloc_root(&result->alloc, - (fields+1)*sizeof(char *)+pkt_len)))) - { - mc_free_rows(result); - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); - DBUG_RETURN(0); - } - *prev_ptr=cur; - prev_ptr= &cur->next; - to= (char*) (cur->data+fields+1); - for (field=0 ; field < fields ; field++) - { - if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) - { /* null field */ - cur->data[field] = 0; - } - else - { - cur->data[field] = to; - memcpy(to,(char*) cp,len); to[len]=0; - to+=len+1; - cp+=len; - if (mysql_fields) - { - if (mysql_fields[field].max_length < len) - mysql_fields[field].max_length=len; - } - } - } - cur->data[field]=to; /* End of last field */ - if ((pkt_len=mc_net_safe_read(mysql)) == packet_error) - { - mc_free_rows(result); - DBUG_RETURN(0); - } - } - *prev_ptr=0; /* last pointer is null */ - DBUG_PRINT("exit",("Got %d rows",result->rows)); - DBUG_RETURN(result); -} - - -/* -** Read one row. Uses packet buffer as storage for fields. -** When next packet is read, the previous field values are destroyed -*/ - - -static int mc_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, - ulong *lengths) -{ - uint field; - ulong pkt_len,len; - uchar *pos; - uchar *prev_pos; - - if ((pkt_len=mc_net_safe_read(mysql)) == packet_error) - return -1; - if (pkt_len == 1 && mysql->net.read_pos[0] == 254) - return 1; /* End of data */ - prev_pos= 0; /* allowed to write at packet[-1] */ - pos=mysql->net.read_pos; - for (field=0 ; field < fields ; field++) - { - if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) - { /* null field */ - row[field] = 0; - *lengths++=0; - } - else - { - row[field] = (char*) pos; - pos+=len; - *lengths++=len; - } - if (prev_pos) - *prev_pos=0; /* Terminate prev field */ - prev_pos= pos; - } - row[field]=(char*) prev_pos+1; /* End of last field */ - *prev_pos=0; /* Terminate last field */ - return 0; -} - -my_ulonglong mc_mysql_num_rows(MYSQL_RES *res) -{ - return res->row_count; -} - -unsigned int mc_mysql_num_fields(MYSQL_RES *res) -{ - return res->field_count; -} - -void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row) -{ - MYSQL_ROWS *tmp=0; - DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); - if (result->data) - for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; - result->current_row=0; - result->data_cursor = tmp; -} - -MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res) -{ - DBUG_ENTER("mc_mysql_fetch_row"); - if (!res->data) - { /* Unbufferred fetch */ - if (!res->eof) - { - if (!(mc_read_one_row(res->handle,res->field_count,res->row, - res->lengths))) - { - res->row_count++; - DBUG_RETURN(res->current_row=res->row); - } - else - { - DBUG_PRINT("info",("end of data")); - res->eof=1; - res->handle->status=MYSQL_STATUS_READY; - } - } - DBUG_RETURN((MYSQL_ROW) NULL); - } - { - MYSQL_ROW tmp; - if (!res->data_cursor) - { - DBUG_PRINT("info",("end of data")); - DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL); - } - tmp = res->data_cursor->data; - res->data_cursor = res->data_cursor->next; - DBUG_RETURN(res->current_row=tmp); - } -} - -int mc_mysql_select_db(MYSQL *mysql, const char *db) -{ - int error; - DBUG_ENTER("mysql_select_db"); - DBUG_PRINT("enter",("db: '%s'",db)); - - if ((error=mc_simple_command(mysql,COM_INIT_DB,db,(uint) strlen(db),0))) - DBUG_RETURN(error); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); - mysql->db=my_strdup(db,MYF(MY_WME)); - DBUG_RETURN(0); -} - - -MYSQL_RES *mc_mysql_store_result(MYSQL *mysql) -{ - MYSQL_RES *result; - DBUG_ENTER("mysql_store_result"); - - if (!mysql->fields) - DBUG_RETURN(0); - if (mysql->status != MYSQL_STATUS_GET_RESULT) - { - strmov(mysql->net.last_error, - ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - DBUG_RETURN(0); - } - mysql->status=MYSQL_STATUS_READY; /* server is ready */ - if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+ - sizeof(ulong)*mysql->field_count, - MYF(MY_ZEROFILL)))) - { - mysql->net.last_errno=CR_OUT_OF_MEMORY; - strmov(mysql->net.last_error, ER(mysql->net.last_errno)); - DBUG_RETURN(0); - } - result->eof=1; /* Marker for buffered */ - result->lengths=(ulong*) (result+1); - if (!(result->data=mc_read_rows(mysql,mysql->fields,mysql->field_count))) - { - my_free((gptr) result,MYF(0)); - DBUG_RETURN(0); - } - mysql->affected_rows= result->row_count= result->data->rows; - result->data_cursor= result->data->data; - result->fields= mysql->fields; - result->field_alloc= mysql->field_alloc; - result->field_count= mysql->field_count; - result->current_field=0; - result->current_row=0; /* Must do a fetch first */ - mysql->fields=0; /* fields is now in result */ - DBUG_RETURN(result); /* Data fetched */ -} +#define _mini_client_c +#define init_sigpipe_variables +#define set_sigpipe(mysql) +#define reset_sigpipe(mysql) +#include "../sql-common/client.c" #endif /* HAVE_EXTERNAL_CLIENT */ + + diff --git a/sql/mini_client.h b/sql/mini_client.h index 24c13646170..3388c342312 100644 --- a/sql/mini_client.h +++ b/sql/mini_client.h @@ -17,30 +17,32 @@ #ifndef _MINI_CLIENT_H #define _MINI_CLIENT_H +MYSQL * +mysql_real_connect(MYSQL *mysql,const char *host, const char *user, + const char *passwd, const char *db, + uint port, const char *unix_socket,ulong client_flag, + uint net_read_timeout); -MYSQL* mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, - const char *passwd, const char *db, - uint port, const char *unix_socket,uint client_flag, - uint net_read_timeout); -int mc_simple_command(MYSQL *mysql,enum enum_server_command command, - const char *arg, uint length, my_bool skipp_check); -void mc_mysql_close(MYSQL *mysql); -MYSQL *mc_mysql_init(MYSQL *mysql); -void mc_mysql_debug(const char *debug); -ulong mc_net_safe_read(MYSQL *mysql); -char *mc_mysql_error(MYSQL *mysql); -int mc_mysql_errno(MYSQL *mysql); -my_bool mc_mysql_reconnect(MYSQL* mysql); -int mc_mysql_send_query(MYSQL* mysql, const char* query, uint length); -int mc_mysql_read_query_result(MYSQL *mysql); -int mc_mysql_query(MYSQL *mysql, const char *query, uint length); -MYSQL_RES * mc_mysql_store_result(MYSQL *mysql); -void mc_mysql_free_result(MYSQL_RES *result); -void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row); -my_ulonglong mc_mysql_num_rows(MYSQL_RES *res); -unsigned int mc_mysql_num_fields(MYSQL_RES *res); -MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res); -int mc_mysql_select_db(MYSQL *mysql, const char *db); -void mc_end_server(MYSQL *mysql); +my_bool simple_command(MYSQL *mysql,enum enum_server_command command, + const char *arg, unsigned long length, + my_bool skip_check); +void mysql_close(MYSQL *mysql); +MYSQL *mysql_init(MYSQL *mysql); +void mysql_debug(const char *debug); +ulong net_safe_read(MYSQL *mysql); +const char *mysql_error(MYSQL *mysql); +unsigned int mysql_errno(MYSQL *mysql); +my_bool mysql_reconnect(MYSQL* mysql); +int mysql_send_query(MYSQL* mysql, const char* query, uint length); +my_bool mysql_read_query_result(MYSQL *mysql); +int mysql_real_query(MYSQL *mysql, const char *q, unsigned long length); +MYSQL_RES * mysql_store_result(MYSQL *mysql); +void mysql_free_result(MYSQL_RES *result); +void mysql_data_seek(MYSQL_RES *result, my_ulonglong row); +my_ulonglong mysql_num_rows(MYSQL_RES *res); +unsigned int mysql_num_fields(MYSQL_RES *res); +MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *res); +int mysql_select_db(MYSQL *mysql, const char *db); +void end_server(MYSQL *mysql); #endif diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 58769827bed..843539f92a2 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -484,14 +484,15 @@ int update_slave_list(MYSQL* mysql, MASTER_INFO* mi) int port_ind; DBUG_ENTER("update_slave_list"); - if (mc_mysql_query(mysql,"SHOW SLAVE HOSTS",16) || - !(res = mc_mysql_store_result(mysql))) + + if (mysql_real_query(mysql,"SHOW SLAVE HOSTS",16) || + !(res = mysql_store_result(mysql))) { - error= mc_mysql_error(mysql); + error= mysql_error(mysql); goto err; } - switch (mc_mysql_num_fields(res)) { + switch (mysql_num_fields(res)) { case 5: have_auth_info = 0; port_ind=2; @@ -508,7 +509,7 @@ HOSTS"; pthread_mutex_lock(&LOCK_slave_list); - while ((row= mc_mysql_fetch_row(res))) + while ((row= mysql_fetch_row(res))) { uint32 server_id; SLAVE_INFO* si, *old_si; @@ -541,7 +542,7 @@ HOSTS"; err: if (res) - mc_mysql_free_result(res); + mysql_free_result(res); if (error) { sql_print_error("While trying to obtain the list of slaves from the master \ @@ -566,7 +567,7 @@ pthread_handler_decl(handle_failsafe_rpl,arg) thd->thread_stack = (char*)&thd; MYSQL* recovery_captain = 0; pthread_detach_this_thread(); - if (init_failsafe_rpl_thread(thd) || !(recovery_captain=mc_mysql_init(0))) + if (init_failsafe_rpl_thread(thd) || !(recovery_captain=mysql_init(0))) { sql_print_error("Could not initialize failsafe replication thread"); goto err; @@ -599,7 +600,7 @@ pthread_handler_decl(handle_failsafe_rpl,arg) pthread_mutex_unlock(&LOCK_rpl_status); err: if (recovery_captain) - mc_mysql_close(recovery_captain); + mysql_close(recovery_captain); delete thd; my_thread_end(); pthread_exit(0); @@ -668,7 +669,7 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi) strmov(mysql->net.last_error, "Master is not configured"); DBUG_RETURN(1); } - if (!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0, + if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, mi->port, 0, 0, slave_net_timeout)) DBUG_RETURN(1); @@ -682,9 +683,9 @@ static inline void cleanup_mysql_results(MYSQL_RES* db_res, for (; cur >= start; --cur) { if (*cur) - mc_mysql_free_result(*cur); + mysql_free_result(*cur); } - mc_mysql_free_result(db_res); + mysql_free_result(db_res); } @@ -692,8 +693,8 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db, MYSQL_RES *table_res, MASTER_INFO *mi) { MYSQL_ROW row; - for (row = mc_mysql_fetch_row(table_res); row; - row = mc_mysql_fetch_row(table_res)) + for (row = mysql_fetch_row(table_res); row; + row = mysql_fetch_row(table_res)) { TABLE_LIST table; const char* table_name= row[0]; @@ -727,7 +728,7 @@ int load_master_data(THD* thd) int error = 0; const char* errmsg=0; int restart_thread_mask; - mc_mysql_init(&mysql); + mysql_init(&mysql); /* We do not want anyone messing with the slave at all for the entire @@ -749,7 +750,7 @@ int load_master_data(THD* thd) if (connect_to_master(thd, &mysql, active_mi)) { net_printf(thd, error= ER_CONNECT_TO_MASTER, - mc_mysql_error(&mysql)); + mysql_error(&mysql)); goto err; } @@ -758,15 +759,15 @@ int load_master_data(THD* thd) MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res; uint num_dbs; - if (mc_mysql_query(&mysql, "SHOW DATABASES", 14) || - !(db_res = mc_mysql_store_result(&mysql))) + if (mysql_real_query(&mysql, "SHOW DATABASES", 14) || + !(db_res = mysql_store_result(&mysql))) { net_printf(thd, error = ER_QUERY_ON_MASTER, - mc_mysql_error(&mysql)); + mysql_error(&mysql)); goto err; } - if (!(num_dbs = (uint) mc_mysql_num_rows(db_res))) + if (!(num_dbs = (uint) mysql_num_rows(db_res))) goto err; /* In theory, the master could have no databases at all @@ -785,12 +786,12 @@ int load_master_data(THD* thd) we wait to issue FLUSH TABLES WITH READ LOCK for as long as we can to minimize the lock time. */ - if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 27) || - mc_mysql_query(&mysql, "SHOW MASTER STATUS",18) || - !(master_status_res = mc_mysql_store_result(&mysql))) + if (mysql_real_query(&mysql, "FLUSH TABLES WITH READ LOCK", 27) || + mysql_real_query(&mysql, "SHOW MASTER STATUS",18) || + !(master_status_res = mysql_store_result(&mysql))) { net_printf(thd, error = ER_QUERY_ON_MASTER, - mc_mysql_error(&mysql)); + mysql_error(&mysql)); goto err; } @@ -805,7 +806,7 @@ int load_master_data(THD* thd) cur_table_res++) { // since we know how many rows we have, this can never be NULL - MYSQL_ROW row = mc_mysql_fetch_row(db_res); + MYSQL_ROW row = mysql_fetch_row(db_res); char* db = row[0]; /* @@ -834,12 +835,12 @@ int load_master_data(THD* thd) goto err; } - if (mc_mysql_select_db(&mysql, db) || - mc_mysql_query(&mysql, "SHOW TABLES", 11) || - !(*cur_table_res = mc_mysql_store_result(&mysql))) + if (mysql_select_db(&mysql, db) || + mysql_real_query(&mysql, "SHOW TABLES", 11) || + !(*cur_table_res = mysql_store_result(&mysql))) { net_printf(thd, error = ER_QUERY_ON_MASTER, - mc_mysql_error(&mysql)); + mysql_error(&mysql)); cleanup_mysql_results(db_res, cur_table_res - 1, table_res); goto err; } @@ -857,7 +858,7 @@ int load_master_data(THD* thd) // adjust position in the master if (master_status_res) { - MYSQL_ROW row = mc_mysql_fetch_row(master_status_res); + MYSQL_ROW row = mysql_fetch_row(master_status_res); /* We need this check because the master may not be running with @@ -875,13 +876,13 @@ int load_master_data(THD* thd) active_mi->master_log_pos = BIN_LOG_HEADER_SIZE; flush_master_info(active_mi); } - mc_mysql_free_result(master_status_res); + mysql_free_result(master_status_res); } - if (mc_mysql_query(&mysql, "UNLOCK TABLES", 13)) + if (mysql_real_query(&mysql, "UNLOCK TABLES", 13)) { net_printf(thd, error = ER_QUERY_ON_MASTER, - mc_mysql_error(&mysql)); + mysql_error(&mysql)); goto err; } } @@ -920,7 +921,7 @@ err: UNLOCK_ACTIVE_MI; thd->proc_info = 0; - mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init() + mysql_close(&mysql); // safe to call since we always do mysql_init() if (!error) send_ok(thd); diff --git a/sql/slave.cc b/sql/slave.cc index eae795ae760..8ab067cc355 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1164,15 +1164,15 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, if (!called_connected) { - if (!(mysql = mc_mysql_init(NULL))) + if (!(mysql = mysql_init(NULL))) { send_error(thd); // EOM DBUG_RETURN(1); } if (connect_to_master(thd, mysql, mi)) { - net_printf(thd, ER_CONNECT_TO_MASTER, mc_mysql_error(mysql)); - mc_mysql_close(mysql); + net_printf(thd, ER_CONNECT_TO_MASTER, mysql_error(mysql)); + mysql_close(mysql); DBUG_RETURN(1); } if (thd->killed) @@ -1193,7 +1193,7 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, err: thd->net.no_send_ok = 0; // Clear up garbage after create_table_from_dump if (!called_connected) - mc_mysql_close(mysql); + mysql_close(mysql); if (errmsg && thd->net.vio) send_error(thd, error, errmsg); DBUG_RETURN(test(error)); // Return 1 on error @@ -1560,12 +1560,12 @@ int register_slave_on_master(MYSQL* mysql) /* The master will fill in master_id */ int4store(pos, 0); pos+= 4; - if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf, + if (simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf, (uint) (pos- buf), 0)) { sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'", - mc_mysql_errno(mysql), - mc_mysql_error(mysql)); + mysql_errno(mysql), + mysql_error(mysql)); return 1; } return 0; @@ -1959,18 +1959,18 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi, int4store(buf + 6, server_id); len = (uint) strlen(logname); memcpy(buf + 10, logname,len); - if (mc_simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1)) + if (simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1)) { /* Something went wrong, so we will just reconnect and retry later in the future, we should do a better error analysis, but for now we just fill up the error log :-) */ - if (mc_mysql_errno(mysql) == ER_NET_READ_INTERRUPTED) + if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED) *suppress_warnings= 1; // Suppress reconnect warning else sql_print_error("Error on COM_BINLOG_DUMP: %d %s, will retry in %d secs", - mc_mysql_errno(mysql), mc_mysql_error(mysql), + mysql_errno(mysql), mysql_error(mysql), master_connect_retry); DBUG_RETURN(1); } @@ -1997,7 +1997,7 @@ static int request_table_dump(MYSQL* mysql, const char* db, const char* table) *p++ = table_len; memcpy(p, table, table_len); - if (mc_simple_command(mysql, COM_TABLE_DUMP, buf, p - buf + table_len, 1)) + if (simple_command(mysql, COM_TABLE_DUMP, buf, p - buf + table_len, 1)) { sql_print_error("request_table_dump: Error sending the table dump \ command"); @@ -2041,10 +2041,10 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) return packet_error; #endif - len = mc_net_safe_read(mysql); + len = net_safe_read(mysql); if (len == packet_error || (long) len < 1) { - if (mc_mysql_errno(mysql) == ER_NET_READ_INTERRUPTED) + if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED) { /* We are trying a normal reconnect after a read timeout; @@ -2056,7 +2056,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) else sql_print_error("Error reading packet from server: %s (\ server_errno=%d)", - mc_mysql_error(mysql), mc_mysql_errno(mysql)); + mysql_error(mysql), mysql_errno(mysql)); return packet_error; } @@ -2064,7 +2064,7 @@ server_errno=%d)", { sql_print_error("Slave: received 0 length packet from server, apparent\ master shutdown: %s", - mc_mysql_error(mysql)); + mysql_error(mysql)); return packet_error; } @@ -2214,7 +2214,7 @@ slave_begin: mi->master_log_name, llstr(mi->master_log_pos,llbuff))); - if (!(mi->mysql = mysql = mc_mysql_init(NULL))) + if (!(mi->mysql = mysql = mysql_init(NULL))) { sql_print_error("Slave I/O thread: error in mc_mysql_init()"); goto err; @@ -2269,7 +2269,7 @@ dump"); } thd->proc_info = "Waiiting to reconnect after a failed dump request"; - mc_end_server(mysql); + end_server(mysql); /* First time retry immediately, assuming that we can recover right away - if first time fails, sleep between re-tries @@ -2319,7 +2319,7 @@ after reconnect"); if (event_len == packet_error) { - uint mysql_error_number= mc_mysql_errno(mysql); + uint mysql_error_number= mysql_errno(mysql); if (mysql_error_number == ER_NET_PACKET_TOO_LARGE) { sql_print_error("\ @@ -2332,11 +2332,11 @@ max_allowed_packet", if (mysql_error_number == ER_MASTER_FATAL_ERROR_READING_BINLOG) { sql_print_error(ER(mysql_error_number), mysql_error_number, - mc_mysql_error(mysql)); + mysql_error(mysql)); goto err; } thd->proc_info = "Waiting to reconnect after a failed read"; - mc_end_server(mysql); + end_server(mysql); if (retry_count++) { if (retry_count > master_retry_count) @@ -2406,7 +2406,7 @@ err: VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { - mc_mysql_close(mysql); + mysql_close(mysql); mi->mysql=0; } thd->proc_info = "Waiting for slave mutex on exit"; @@ -2951,22 +2951,22 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, client_flag=CLIENT_COMPRESS; /* We will use compression */ while (!(slave_was_killed = io_slave_killed(thd,mi)) && - (reconnect ? mc_mysql_reconnect(mysql) != 0: - !mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0, - mi->port, 0, client_flag, - thd->variables.net_read_timeout))) + (reconnect ? mysql_reconnect(mysql) != 0: + !mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, + mi->port, 0, client_flag, + thd->variables.net_read_timeout))) { /* Don't repeat last error */ - if (mc_mysql_errno(mysql) != last_errno) + if ((int)mysql_errno(mysql) != last_errno) { - last_errno=mc_mysql_errno(mysql); + last_errno=mysql_errno(mysql); suppress_warnings= 0; sql_print_error("Slave I/O thread: error %s to master \ '%s@%s:%d': \ Error: '%s' errno: %d retry-time: %d retries: %d", (reconnect ? "reconnecting" : "connecting"), mi->user,mi->host,mi->port, - mc_mysql_error(mysql), last_errno, + mysql_error(mysql), last_errno, mi->connect_retry, master_retry_count); } From 870397892be8a35afdb343c209be91cba117cee6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 May 2003 22:12:15 +0200 Subject: [PATCH 134/399] 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 8d8f52e902699c260f455075650906025f59f010 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 02:29:40 +0300 Subject: [PATCH 135/399] Many files: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released sql/log.cc: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released sql/handler.cc: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released sql/handler.h: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released sql/ha_innodb.cc: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released sql/ha_innodb.h: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/include/log0log.h: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/include/trx0trx.h: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/os/os0file.c: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/buf/buf0flu.c: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/trx/trx0trx.c: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/log/log0log.c: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/srv/srv0srv.c: Eliminate the LOCK_log bottleneck in group commit in binlogging: flush InnoDB log files only after it has been released innobase/row/row0mysql.c: 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 6d454dc6e4ab0e10f06d6d20a7449ce8fc684db8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 14:48:51 +0200 Subject: [PATCH 136/399] 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 e2a839ff470f99f629dba2ddd31c0f2dce314941 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 15:21:39 +0200 Subject: [PATCH 137/399] 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 34c3c0279441554e8d42ff0ec18a2890c1a6e148 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 16:21:43 +0300 Subject: [PATCH 138/399] Fix problem where key_read was not cleaned up properly, which caused assert in innodb test. mysql-test/r/innodb.result: Changed tests to make them repeatable. mysql-test/t/innodb.test: Changed tests to make them repeatable. sql/opt_sum.cc: Safety fix sql/sql_base.cc: Safety assert --- 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 f58147225b90e68d1cd00f5dc6ded6aa45188706 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 16:16:52 +0200 Subject: [PATCH 139/399] - 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 155b8e001307bced530900fe92644c1daa929fb1 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 18:08:11 +0200 Subject: [PATCH 140/399] "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 1d64ab5e4705207196d6ff34f866a1070d49f108 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 19:44:46 +0300 Subject: [PATCH 141/399] 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/srv/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/include/buf0buf.h: 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/include/srv0srv.h: 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: 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 ef19f0db5d223e844cc0c95611917dc21f8a598c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 May 2003 19:46:03 +0300 Subject: [PATCH 142/399] 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: 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 6b1d89b1c9cae92d31c73ba3818fb3ec9b2de13d Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 11:00:45 +0200 Subject: [PATCH 143/399] 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 09b03ed23ca3c269e8fdc6e1792fa8e67cd69419 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 14:41:21 +0400 Subject: [PATCH 144/399] 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: Added innodb_max_dirty_pages_pct parameter to limit amount of dirty pages in the buffer pool (can be changed online) sql/mysqld.cc: Added new option sql/set_var.cc: Added new variable handling --- 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 87dc6aa669a3053255462d2534c5e740a70ced63 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 15:14:33 +0300 Subject: [PATCH 145/399] 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: 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 a8841f011412b29a44b8587dac23277a3e7b109b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 15:42:47 +0300 Subject: [PATCH 146/399] 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: 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 97946e16b3a667772586f244d36e1ff4de353ba4 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 18:43:07 +0200 Subject: [PATCH 147/399] 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 f3a1967bc976661ce717d5bee37cf92b03583c19 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 18:43:37 +0200 Subject: [PATCH 148/399] 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 81a752eb726063396d8e6819937b7a2ca5b3de28 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 21:35:20 +0400 Subject: [PATCH 149/399] Minor fix to previous code sql/mysql_priv.h: Add ifdef to allow compilation without Innodb --- 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 de4bf8b93cc5fe05bfce216c94a68aaa0a537288 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 May 2003 23:24:23 +0300 Subject: [PATCH 150/399] 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/srv/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/include/dict0dict.h: 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: 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/row/row0ins.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 00fd88c9451008237395d93a73d2d78152ea369c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 5 May 2003 10:54:56 +0300 Subject: [PATCH 151/399] 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: Better warning message if more than 4 / 5 of the buffer pool is consumed by locks of adaptive hash index innobase/buf/buf0lru.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 afe9738efb8d9704b66f6b7cea57ccb011d79a1a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 5 May 2003 14:52:39 +0300 Subject: [PATCH 152/399] Fixed that reading a DATE string of 000000 is interpreted as 0000-00-00 instead of 2000-00-00 sql/time.cc: Removed not used code 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 03706ea4b6f79eb581d402e48e4c53d4b546f847 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 May 2003 22:33:08 +0200 Subject: [PATCH 153/399] - 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: - added MySQL-shared-compat.spec(.sh) to the distribution --- 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 0299df4b4f7d62197b0e490d65b94a47661cdeef Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 May 2003 19:01:45 +0300 Subject: [PATCH 154/399] 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: 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/sql_select.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 fb17658eb218a1b0a0965fd1acd0a8ec6a58a709 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 May 2003 19:13:56 +0300 Subject: [PATCH 155/399] 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: 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 4d91444b15a9d156875b4ba7df2efc301e10845b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 May 2003 23:15:46 +0300 Subject: [PATCH 156/399] 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 a57e7732897ee7973d82dccea0425c436845066a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 May 2003 23:59:24 +0300 Subject: [PATCH 157/399] Security patch to remove wrong error when one had a global update/delete privilige and a database specific SELECT privilege. sql/sql_acl.cc: Security patch sql/sql_base.cc: Security patch sql/sql_parse.cc: Security patch tests/grant.pl: Test of security patch tests/grant.res: Test of security patch --- 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 a1b470729b1b9868d8d1eb741dbeda15097ad310 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 May 2003 00:34:23 +0300 Subject: [PATCH 158/399] 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 504fd4d43990e507b685eb336ee672c637ecf4cb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 May 2003 01:47:20 +0300 Subject: [PATCH 159/399] 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 6b14b0de14283d7566651c04340299f6508a4a6a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 May 2003 14:52:22 -0400 Subject: [PATCH 160/399] 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: 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 ce50dd42d8e5375942e0f9b23fff002ba3a054e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 May 2003 17:33:42 +0300 Subject: [PATCH 161/399] 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/trx/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: 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 9cbcdfa26a67a2fed3fe3018c66ac15be978ccca Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 May 2003 17:09:31 +0200 Subject: [PATCH 162/399] - 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 10c790eff016ff0fc779baeb7ebf94940d3544e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 10:54:07 +0300 Subject: [PATCH 163/399] Safety fix to enable RAID in max binaries Better fix for format('nan') Fix for HAVING COUNT(DISTINCT...) myisam/mi_check.c: Better error message myisam/mi_dynrec.c: Simple code cleanup myisam/myisamchk.c: Better error messages mysql-test/r/func_misc.result: Added back test for format('nan') mysql-test/r/having.result: New test mysql-test/t/func_misc.test: Added back test for format('nan') mysql-test/t/having.test: Added test for count(distinct) in having mysys/raid.cc: Safety fix to enable RAID in max binaries scripts/mysql_install_db.sh: Create data directories even if --in-rpm is used (for MaxOSX) sql/item_strfunc.cc: Better fix for format('nan') sql/mysqld.cc: Give stacktrace on assert() sql/sql_yacc.yy: Fix for HAVING COUNT(DISTINCT...) tests/big_record.pl: Extend test to abuse packed MyISAM tables tests/table_types.pl: Fixed wrong merge --- 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 179b1b68422ca100e9ffc6ef6f47cb1d287b1a17 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 11:39:07 +0300 Subject: [PATCH 164/399] 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 dc1e55f8194db83e7a40dea5bf49e9fef970826c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 18:58:26 +0300 Subject: [PATCH 165/399] Fix for UNION and LEFT JOIN (Bug #386) Fixed wrong logging of Access denied error (Bug #398) include/my_global.h: Fix for QNX mysql-test/r/union.result: new test case mysql-test/t/union.test: Test of bug in union and left join mysys/my_seek.c: Safety fix to find out when pos gets a wrong value sql/field.h: Fix for UNION and LEFT JOIN sql/mysql_priv.h: Fix for UNION and LEFT JOIN sql/sql_base.cc: Fix for UNION and LEFT JOIN sql/sql_insert.cc: Fix for UNION and LEFT JOIN sql/sql_parse.cc: Fixed wrong logging of Access denied error sql/sql_union.cc: Fix for UNION and LEFT JOIN sql/sql_update.cc: Fix for UNION and LEFT JOIN --- 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 d05cd28c10bdc94783074ebaba40a3ed1fabe6a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 19:26:07 +0300 Subject: [PATCH 166/399] Fixed problem with ansi mode and GROUP BY with constants. (Bug #387) sql/sql_select.cc: Fixed problem with ansi mode and GROUP BY with constants --- 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 496357a18069730b97b303d40d91a9ac3ec3783f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 19:34:51 +0300 Subject: [PATCH 167/399] - 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: Fix for QNX: UNIX sockets available since 6.2.1 mysql-test/r/variables.result: Fixed a bug in myisam_max_[extra]_sort_file_size, bug ID 339 mysql-test/t/variables.test: Fixed a bug in myisam_max_[extra]_sort_file_size, bug ID 339 sql/mysqld.cc: Fixed a bug in myisam_max_[extra]_sort_file_size, bug ID 339 sql/set_var.cc: Fixed a bug in myisam_max_[extra]_sort_file_size, bug ID 339 sql/set_var.h: Fixed a bug in myisam_max_[extra]_sort_file_size, bug ID 339 --- 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 46d868829e9760f42952377b97f74b2a12a81e3e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 18:54:20 +0200 Subject: [PATCH 168/399] - 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: - added mysql_fix_privilege_tables(1) man page to man_MANS man/isamchk.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/isamlog.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysql.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysql_zap.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysqlaccess.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysqladmin.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysqld.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysqld_multi.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysqld_safe.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysqldump.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/mysqlshow.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/perror.1: - Updated version number ("MySQL-3.23" -> "MySQL 4.0") man/replace.1: - Updated version number ("MySQL-3.23" -> "MySQL 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 d4ae4f0ec0e43f395722dbd1153938c66658b037 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 20:07:43 +0300 Subject: [PATCH 169/399] Fixed 'Unknown error' when using 'UPDATE ... LIMIT'. Bug 373 mysql-test/r/update.result: new test mysql-test/t/update.test: Test of UPDATE ... LIMIT sql/sql_update.cc: Fixed 'Unknown error' when using 'UPDATE ... LIMIT' --- 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 563c32ccd1f5a212dfb270097c1dbd1cdc1be907 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 19:16:30 +0200 Subject: [PATCH 170/399] 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 a147307f426ef6c93b94e4b62fe14bf004585fa9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 19:19:57 +0200 Subject: [PATCH 171/399] Forgot to correct comment in key.test (after fixing bug 390). mysql-test/t/key.test: Forgot to correct comment (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 7a96b137ef140d2e6d372927c33ca0aecb058ffa Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 19:30:07 +0200 Subject: [PATCH 172/399] - 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 f0fc67294ce1e9fa20c332a418dbd9ae20b85051 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 12:06:34 -0700 Subject: [PATCH 173/399] logging_ok: Logging to logging@openlogging.org accepted mf_keycache.c: Fixed a deadlock when reading from an index file fails. mysys/mf_keycache.c: Fixed a deadlock when reading from an index file fails. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysys/mf_keycache.c | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index b6f9647ea49..0a5caaa8858 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -31,6 +31,7 @@ hf@bisonxp.(none) hf@deer.mysql.r18.ru hf@genie.(none) igor@hundin.mysql.fi +igor@rurik.mysql.com jani@dsl-jkl1657.dial.inet.fi jani@dsl-kpogw4gb5.dial.inet.fi jani@hynda.(none) diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 45cbcdb3ab7..264037e9a70 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -826,7 +826,7 @@ restart: (uint) hash_link->file,(ulong) hash_link->diskpos)); } } - KEYCACHE_DBUG_ASSERT(n <= my_hash_links_used); + KEYCACHE_DBUG_ASSERT(cnt <= my_hash_links_used); #endif } if (! hash_link) @@ -1063,6 +1063,9 @@ restart: KEYCACHE_DBUG_ASSERT(page_status != -1); *page_st=page_status; + KEYCACHE_DBUG_PRINT("find_key_block", + ("file %u, filepos %lu, page_status %lu", + (uint) file,(ulong) filepos,(uint) page_status)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("check_keycache2",test_key_cache("end of find_key_block",0);); @@ -1181,7 +1184,7 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length, keycache_pthread_mutex_lock(&THR_LOCK_keycache); my_cache_r_requests++; block=find_key_block(file,filepos,0,&page_st); - if (page_st != PAGE_READ) + if (block->status != BLOCK_ERROR && page_st != PAGE_READ) { /* The requested page is to be read into the block buffer */ read_block(block,key_cache_block_size,read_length+offset, @@ -1303,7 +1306,7 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length, keycache_pthread_mutex_lock(&THR_LOCK_keycache); my_cache_w_requests++; block=find_key_block(file, filepos, 1, &page_st); - if (page_st != PAGE_READ && + if (block->status != BLOCK_ERROR && page_st != PAGE_READ && (offset || read_length < key_cache_block_size)) read_block(block, offset + read_length >= key_cache_block_size? From 32450d159b685660add0d2f68bc9d3a24b6bfb52 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 22:28:34 +0300 Subject: [PATCH 174/399] 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 d079990894e41dc3220156729f95557233dd88d8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 May 2003 23:03:00 +0200 Subject: [PATCH 175/399] 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 13a23a879f3f2e9b3d09578e08802e6fe19f88f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 01:27:26 +0300 Subject: [PATCH 176/399] Fix for MacOSX and symlinks Fix for USE_FRM and crashed index file configure.in: Fix for MacOSX and symlinks myisam/mi_open.c: Give better error message in case of of crashed index file mysql-test/r/repair.result: new test case mysql-test/r/update.result: new test case mysql-test/t/repair.test: Added test with crashed MyISAM index header mysql-test/t/update.test: Added test case from bugs system sql/handler.cc: Indentation changes sql/sql_table.cc: 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 7297502a7bc6ab09d8e7c6cbd822bba4d58d4977 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 01:55:23 +0300 Subject: [PATCH 177/399] 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 f527bc7fee872a34246f127e56cca8c8967e3dd5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 09:37:04 +0300 Subject: [PATCH 178/399] SHOW TABLE STATUS displayed wrong Row_format for myisampack'ed tables. (Bug #427) sql/sql_show.cc: SHOW TABLE STATUS displayed wrong Row_format for myisampack'ed tables. --- 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 209e44c1a2921423acc51eae888aa16293153619 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 13:49:43 +0300 Subject: [PATCH 179/399] Fixed documentation for mysql_fix_privilege_tables man page. Bug ID: 384 --- man/mysql_fix_privilege_tables.1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/man/mysql_fix_privilege_tables.1 b/man/mysql_fix_privilege_tables.1 index bf4e0e15dfa..4ed81368098 100644 --- a/man/mysql_fix_privilege_tables.1 +++ b/man/mysql_fix_privilege_tables.1 @@ -2,7 +2,7 @@ .SH NAME mysql_fix_privilege_tables \- Fixes MySQL privilege tables. .SH SYNOPSIS -mysql_fix_privilege_tables [options] +mysql_fix_privilege_tables [mysql_root_password] .SH DESCRIPTION This scripts updates the mysql.user, mysql.db, mysql.host and the mysql.func tables to MySQL 3.22.14 and above. @@ -10,10 +10,9 @@ 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! +If you get 'Access denied' errors, run the 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 From 8b87a1aa0e6328a67c2c72f11612134ed5eb7597 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 16:47:55 +0300 Subject: [PATCH 180/399] Fixed a bug with having comments after options in config files. Bug ID: 235 --- mysys/default.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index c47d2719ab5..3ff240da3a1 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -72,6 +72,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc, const char *dir, const char *config_file, const char *ext, TYPELIB *group); +static char *remove_end_comment(char *ptr); void load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv) @@ -297,9 +298,11 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, } if (!read_values) continue; - if (!(end=value=strchr(ptr,'='))) - end=strend(ptr); /* Option without argument */ + end= remove_end_comment(ptr); + if ((value= strchr(ptr, '='))) + end= value; /* Option without argument */ for ( ; isspace(end[-1]) ; end--) ; + if (!value) { if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3))) @@ -368,6 +371,29 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, } +static char *remove_end_comment(char *ptr) +{ + char quote= 0; + + for (; *ptr; ptr++) + { + if (*ptr == '\'' || *ptr == '\"') + { + if (!quote) + quote= *ptr; + else if (quote == *ptr) + quote= 0; + } + if (!quote && *ptr == '#') /* We are not inside a comment */ + { + *ptr= 0; + return ptr; + } + } + return ptr; +} + + void print_defaults(const char *conf_file, const char **groups) { #ifdef __WIN__ From 23d7a317eea687133028801e2aafda31d3ddafa3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 19:00:17 +0300 Subject: [PATCH 181/399] os0sync.c: We had forgotten to call pthread_mutex_destroy when we free an OS mutex in Unix innobase/os/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 58d4f5692814b2e393163f1083b6da525a6f0a15 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 19:09:05 +0300 Subject: [PATCH 182/399] 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: 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 fb0d4064a79f5bee250f8fbac0f2d552e16503e8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 20:17:01 +0300 Subject: [PATCH 183/399] os0sync.c: Check that pthread_mutex_init and pthread_mutex_destroy return 0 innobase/os/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 dbc5d0e1096b33ae2bad34e2dc6821fea09806c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 20:22:55 +0300 Subject: [PATCH 184/399] os0sync.c: Check return value of pthread_cond_... innobase/os/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 3e52a3f1fc2b1c65e9f08b66f10056312ce363e1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 22:08:30 +0300 Subject: [PATCH 185/399] 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 ac316cfdb33bd4974a90c240c7a14ecb6a29da34 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 22:12:55 +0300 Subject: [PATCH 186/399] Fixed bug in CREATE ... DECIMAL(-1,1). Bug #432 mysql-test/mysql-test-run.sh: Ensure that tests are sorted mysql-test/r/type_decimal.result: Test for bug with decimal() mysql-test/t/type_decimal.test: Test for bug with decimal() sql/sql_parse.cc: Fixed bug in CREATE ... DECIMAL(-1,1) --- 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 43d371409589e835779a6236050ce92bb7344dae Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2003 23:06:06 +0300 Subject: [PATCH 187/399] 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 71df0f640a8b03468a59193ae3de5ed54483f34c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 May 2003 13:03:47 +0200 Subject: [PATCH 188/399] my_global.h: - QNX 6.2.1 actually defines HAVE_RINT - fixed rint(A) #define as it was causing compile errors on QNX include/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: Logging to logging@openlogging.org accepted --- 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 d57d45bb10b04a3fdea3f2c4aa3772893f5393bf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 May 2003 13:36:13 +0200 Subject: [PATCH 189/399] - 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 e4a95f291454943f14b680fb8f0d0c43ea50ead7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 May 2003 16:27:50 +0300 Subject: [PATCH 190/399] 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++ sql/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++ sql/ha_innodb.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/trx/trx0trx.c: Add forgotten return value (it was not used anywhere, fortunately) innobase/include/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 innobase/buf/buf0buf.c: 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 innobase/buf/buf0flu.c: 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 innobase/buf/buf0lru.c: 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 --- 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 acda3d79b6f16441375171dfc58a78b85d313eff Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 17 May 2003 10:05:07 +0300 Subject: [PATCH 191/399] fixed memory overrun (bug 380) mysql-test/r/func_group.result: new tests mysql-test/t/func_group.test: new tests sql/item.cc: count items in select list sql/item_subselect.cc: use number of item in select list for array creation sql/item_sum.cc: with_sum_func now is boolean sql/sql_derived.cc: use number of item in select list for array creation sql/sql_lex.cc: create_refs changed with parsing_place enum variable sql/sql_lex.h: added items in select list counter create_refs changed with parsing_place enum variable with_sum_func now is boolean sql/sql_select.cc: use number of item in select list for array creation sql/sql_union.cc: use number of item in select list for array creation sql/sql_yacc.yy: create_refs changed with parsing_place enum variable --- mysql-test/r/func_group.result | 11 ++++++- mysql-test/t/func_group.test | 9 ++++-- sql/item.cc | 2 ++ sql/item_subselect.cc | 2 +- sql/item_sum.cc | 3 +- sql/sql_derived.cc | 2 +- sql/sql_lex.cc | 6 ++-- sql/sql_lex.h | 13 ++++++-- sql/sql_select.cc | 2 +- sql/sql_union.cc | 2 +- sql/sql_yacc.yy | 54 ++++++++++++++++++++++++++++------ 11 files changed, 83 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index b7bf3a5cd80..9e1fa4ff67c 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -561,4 +561,13 @@ select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using index 1 SIMPLE t2 index NULL k2 4 NULL 6 Using where; Using index -drop table if exists t1, t2; +drop table t1, t2; +create table t1 (USR_ID integer not null, MAX_REQ integer not null, constraint PK_SEA_USER primary key (USR_ID)) type=InnoDB; +insert into t1 values (1, 3); +select count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ from t1 group by MAX_REQ; +count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ +1 +select Case When Count(*) < MAX_REQ Then 1 Else 0 End from t1 where t1.USR_ID = 1 group by MAX_REQ; +Case When Count(*) < MAX_REQ Then 1 Else 0 End +1 +drop table t1; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index c78509d3869..659032c431b 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -326,6 +326,11 @@ explain select min(a4) from t1 where (a4 + 0.01) between 0.07 and 0.08; explain select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME'; +drop table t1, t2; + +create table t1 (USR_ID integer not null, MAX_REQ integer not null, constraint PK_SEA_USER primary key (USR_ID)) type=InnoDB; +insert into t1 values (1, 3); +select count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ from t1 group by MAX_REQ; +select Case When Count(*) < MAX_REQ Then 1 Else 0 End from t1 where t1.USR_ID = 1 group by MAX_REQ; +drop table t1; -# Clean up -drop table if exists t1, t2; \ No newline at end of file diff --git a/sql/item.cc b/sql/item.cc index 053a94cb695..0a885edec2a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -46,6 +46,8 @@ Item::Item(): next= thd->free_list; // Put in free list thd->free_list= this; loop_id= 0; + if (thd->lex.current_select->parsing_place == SELECT_LEX_NODE::SELECT_LIST) + thd->lex.current_select->select_items++; } /* diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c749fba616f..e7a2c6e7f24 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -492,7 +492,7 @@ void Item_in_subselect::single_value_transformer(THD *thd, { sl->item_list.push_back(item); setup_ref_array(thd, &sl->ref_pointer_array, - 1 + sl->with_sum_func + + 1 + sl->select_items + sl->order_list.elements + sl->group_list.elements); // To prevent crash on Item_ref_null_helper destruction in case of error sl->ref_pointer_array[0]= 0; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 11c850f9d5f..631c5cf9a0e 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -57,8 +57,7 @@ Item_sum::Item_sum(THD *thd, Item_sum &item): void Item_sum::mark_as_sum_func() { - current_thd->lex.current_select->with_sum_func++; - with_sum_func= 1; + current_thd->lex.current_select->with_sum_func= with_sum_func= 1; } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 7f555f37d40..4ede6462058 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -125,7 +125,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, item_list= select_cursor->item_list; select_cursor->with_wild= 0; if (setup_ref_array(thd, &select_cursor->ref_pointer_array, - (item_list.elements + select_cursor->with_sum_func + + (item_list.elements + select_cursor->select_items + select_cursor->order_list.elements + select_cursor->group_list.elements)) || setup_fields(thd, select_cursor->ref_pointer_array, first_table, item_list, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9bc4dfc74e7..c61149b8313 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -111,7 +111,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->next_state=MY_LEX_START; lex->end_of_query=(lex->ptr=buf)+length; lex->yylineno = 1; - lex->select_lex.create_refs=lex->in_comment=0; + lex->select_lex.parsing_place= SELECT_LEX_NODE::NO_MATTER; + lex->in_comment=0; lex->length=0; lex->select_lex.in_sum_expr=0; lex->select_lex.expr_list.empty(); @@ -973,8 +974,9 @@ void st_select_lex_node::init_select() order_list.next= (byte**) &order_list.first; select_limit= HA_POS_ERROR; offset_limit= 0; + select_items= 0; with_sum_func= 0; - create_refs= 0; + parsing_place= SELECT_LEX_NODE::NO_MATTER; } void st_select_lex_unit::init_query() diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f31b3305e07..b4444c03280 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -77,7 +77,6 @@ enum enum_sql_command { SQLCOM_END }; - typedef List List_item; typedef struct st_lex_master_info @@ -191,6 +190,13 @@ protected: *master, *slave, /* vertical links */ *link_next, **link_prev; /* list of whole SELECT_LEX */ public: + enum enum_parsing_place + { + NO_MATTER, + IN_HAVING, + SELECT_LIST + }; + ulong options; enum sub_select_type linkage; SQL_LIST order_list; /* ORDER clause */ @@ -200,8 +206,9 @@ public: // Arrays of pointers to top elements of all_fields list Item **ref_pointer_array; - uint with_sum_func; /* sum function indicator and number of it */ - bool create_refs; + uint select_items; /* number of items in select_list */ + enum_parsing_place parsing_place; /* where we are parsing expression */ + bool with_sum_func; /* sum function indicator */ bool dependent; /* dependent from outer select subselect */ bool uncacheable; /* result of this query can't be cached */ bool no_table_names_allowed; /* used for global order by */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 85ebb9f207f..bee41cee346 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -289,7 +289,7 @@ JOIN::prepare(Item ***rref_pointer_array, fields_list, &all_fields, wild_num))) || setup_ref_array(thd, rref_pointer_array, (fields_list.elements + - select_lex->with_sum_func + + select_lex->select_items + og_num)) || setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, &all_fields, 1) || diff --git a/sql/sql_union.cc b/sql/sql_union.cc index fe4ca49da14..df50e98c2c4 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -159,7 +159,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, item_list= select_cursor->item_list; select_cursor->with_wild= 0; if (setup_ref_array(thd, &select_cursor->ref_pointer_array, - (item_list.elements + select_cursor->with_sum_func + + (item_list.elements + select_cursor->select_items + select_cursor->order_list.elements + select_cursor->group_list.elements)) || setup_fields(thd, select_cursor->ref_pointer_array, first_table, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ad60270ccb3..12482d98220 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -925,8 +925,13 @@ create3: LEX *lex=Lex; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; mysql_init_select(lex); + lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; } - select_options select_item_list opt_select_from union_clause {} + select_options select_item_list + { + Select->parsing_place= SELECT_LEX_NODE::NO_MATTER; + } + opt_select_from union_clause {} ; opt_as: @@ -1883,8 +1888,13 @@ select_part2: lex->lock_option= TL_READ; /* Only for global SELECT */ if (sel->linkage != UNION_TYPE) mysql_init_select(lex); + lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; } - select_options select_item_list select_into select_lock_type; + select_options select_item_list + { + Select->parsing_place= SELECT_LEX_NODE::NO_MATTER; + } + select_into select_lock_type; select_into: opt_limit_clause {} @@ -2917,10 +2927,15 @@ where_clause: having_clause: /* empty */ - | HAVING { Select->select_lex()->create_refs= 1; } expr + | HAVING + { + Select->select_lex()->parsing_place= SELECT_LEX_NODE::IN_HAVING; + } + expr { SELECT_LEX *sel= Select->select_lex(); - sel->having= $3; sel->create_refs=0; + sel->having= $3; + sel->parsing_place= SELECT_LEX_NODE::NO_MATTER; if ($3) $3->top_level_item(); } @@ -3348,8 +3363,13 @@ insert_values: SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT); lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; mysql_init_select(lex); + lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; } - select_options select_item_list opt_select_from select_lock_type + select_options select_item_list + { + Select->parsing_place= SELECT_LEX_NODE::NO_MATTER; + } + opt_select_from select_lock_type union_clause {} ; @@ -4030,7 +4050,10 @@ simple_ident: ident { SELECT_LEX_NODE *sel=Select; - $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); + $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + sel->get_in_sum_expr() > 0) ? + (Item*) new Item_field(NullS,NullS,$1.str) : + (Item*) new Item_ref(NullS,NullS,$1.str); } | ident '.' ident { @@ -4043,7 +4066,10 @@ simple_ident: ER(ER_TABLENAME_NOT_ALLOWED_HERE), MYF(0), $1.str, thd->where); } - $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str); + $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + sel->get_in_sum_expr() > 0) ? + (Item*) new Item_field(NullS,$1.str,$3.str) : + (Item*) new Item_ref(NullS,$1.str,$3.str); } | '.' ident '.' ident { @@ -4056,7 +4082,10 @@ simple_ident: ER(ER_TABLENAME_NOT_ALLOWED_HERE), MYF(0), $2.str, thd->where); } - $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str); + $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + sel->get_in_sum_expr() > 0) ? + (Item*) new Item_field(NullS,$2.str,$4.str) : + (Item*) new Item_ref(NullS,$2.str,$4.str); } | ident '.' ident '.' ident { @@ -4069,7 +4098,14 @@ simple_ident: ER(ER_TABLENAME_NOT_ALLOWED_HERE), MYF(0), $3.str, thd->where); } - $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str); + $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + sel->get_in_sum_expr() > 0) ? + (Item*) new Item_field((YYTHD->client_capabilities & + CLIENT_NO_SCHEMA ? NullS : $1.str), + $3.str, $5.str) : + (Item*) new Item_ref((YYTHD->client_capabilities & + CLIENT_NO_SCHEMA ? NullS : $1.str), + $3.str, $5.str); }; From bdf002d9635e9be3fc853dd4ce1f3905dfa10569 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 17 May 2003 16:23:46 +0300 Subject: [PATCH 192/399] 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: 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 c2c0e70ffe28660f3d15ad7dcea74fce7f6ceae2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 18 May 2003 21:46:19 +0300 Subject: [PATCH 193/399] srv0start.c: Better instructions for the user if adding of new ibdata files fails innobase/srv/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 18dd37b8a101dab654a896eabd9e73bc71aed8ca Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 May 2003 12:01:38 +0300 Subject: [PATCH 194/399] Added option --read-only (Thanks to Markus Benning) myisam/myisamchk.c: Removed warning from fulltext when repairing many tables with fulltext index sql/init.cc: Remove not used variables sql/mysql_priv.h: Remove not used variables sql/mysqld.cc: Removed not used variables Added option --read-only Change opt_do_pstack and master_ssl to get them to work with my_getopt sql/set_var.cc: Option --read-only sql/sql_parse.cc: Option --read-only --- 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) { From a33adc45bcac91120659eaab4a8dab09f57c04aa Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 May 2003 15:32:38 +0300 Subject: [PATCH 195/399] fixed bugs 442/443 (reduced subselect in ORDER/GROUP clauses) mysql-test/r/subselect.result: test of reduced subselects in ORDER/GROUP mysql-test/t/subselect.test: test of reduced subselects in ORDER/GROUP sql/sql_select.cc: added reassigning temporary variable --- mysql-test/r/subselect.result | 17 +++++++++++++++++ mysql-test/t/subselect.test | 17 +++++++++++++++++ sql/sql_select.cc | 6 ++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 5c57ea87f21..d905024672b 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1126,3 +1126,20 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ref salary salary 5 const 1 Using where 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away drop table t1; +(SELECT 1 as a) UNION (SELECT 1) ORDER BY (SELECT a+0); +a +1 +CREATE TABLE `t1` ( +`id` mediumint(8) unsigned NOT NULL auto_increment, +`pseudo` varchar(35) NOT NULL default '', +`email` varchar(60) NOT NULL default '', +PRIMARY KEY (`id`), +UNIQUE KEY `email` (`email`), +UNIQUE KEY `pseudo` (`pseudo`), +) TYPE=MyISAM CHARSET=latin1 PACK_KEYS=1 ROW_FORMAT=DYNAMIC; +INSERT INTO t1 (id,pseudo,email) VALUES (1,'test','test'),(2,'test1','test1'); +SELECT pseudo as a, pseudo as b FROM t1 GROUP BY (SELECT a) ORDER BY (SELECT id*1); +a b +test test +test1 test1 +drop table if exists t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 8e8a3dfe1d4..7ba75e3dbb0 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -714,3 +714,20 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000); explain SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1); drop table t1; + +# +# reduced subselect in ORDER BY & GROUP BY clauses +# +(SELECT 1 as a) UNION (SELECT 1) ORDER BY (SELECT a+0); + +CREATE TABLE `t1` ( + `id` mediumint(8) unsigned NOT NULL auto_increment, + `pseudo` varchar(35) NOT NULL default '', + `email` varchar(60) NOT NULL default '', + PRIMARY KEY (`id`), + UNIQUE KEY `email` (`email`), + UNIQUE KEY `pseudo` (`pseudo`), +) TYPE=MyISAM CHARSET=latin1 PACK_KEYS=1 ROW_FORMAT=DYNAMIC; +INSERT INTO t1 (id,pseudo,email) VALUES (1,'test','test'),(2,'test1','test1'); +SELECT pseudo as a, pseudo as b FROM t1 GROUP BY (SELECT a) ORDER BY (SELECT id*1); +drop table if exists t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 85ebb9f207f..71dfec8cac2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7167,9 +7167,11 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, } order->in_field_list=0; Item *it= *order->item; - if (it->fix_fields(thd, tables, order->item) || it->check_cols(1) || + if (it->fix_fields(thd, tables, order->item) || + //'it' ressigned because fix_field can change it + (it= *order->item), it->check_cols(1) || thd->is_fatal_error) - return 1; // Wrong field + return 1; // Wrong field uint el= all_fields.elements; all_fields.push_front(it); // Add new field to field list ref_pointer_array[el]= it; From 32592ab8c1a331f3bbd52dbd62f738ba82d29ea6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 May 2003 16:36:50 +0200 Subject: [PATCH 196/399] - Tagged ChangeSet 1.1497 as "mysql-4.0.13" - Updated version number in configure.in to 4.0.14 now that 4.0.13 has been tagged configure.in: - Updated version number to 4.0.14 now that 4.0.13 has been tagged --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index c7cf4f66b70..df83f7e715e 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.13) +AM_INIT_AUTOMAKE(mysql, 4.0.14) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From 3431b9dd0c9109d830a66160a0518480ab721f21 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 May 2003 04:57:59 +0600 Subject: [PATCH 197/399] add check of __NT__ definition for shared_memory for tree 4.1 --- sql/mysqld.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f73bd6721f0..e11729e0876 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2327,7 +2327,9 @@ static void handle_connections_methods() #endif /* __NT__ */ if (have_tcpip && !opt_disable_networking) { +#ifdef __NT__ handler_count++; +#endif if (pthread_create(&hThread,&connection_attrib, handle_connections_sockets, 0)) { @@ -2338,7 +2340,9 @@ static void handle_connections_methods() #ifdef HAVE_SMEM if (opt_enable_shared_memory) { +#ifdef __NT__ handler_count++; +#endif if (pthread_create(&hThread,&connection_attrib, handle_connections_shared_memory, 0)) { @@ -3364,10 +3368,12 @@ error: if (!handle_connect_file_map) CloseHandle(handle_connect_file_map); if (!event_connect_answer) CloseHandle(event_connect_answer); if (!event_connect_request) CloseHandle(event_connect_request); +#ifdef __NT__ pthread_mutex_lock(&LOCK_thread_count); handler_count--; pthread_mutex_unlock(&LOCK_thread_count); pthread_cond_signal(&COND_handler_count); +#endif DBUG_RETURN(0); } #endif /* HAVE_SMEM */ From f72611b4fa7eb45259b26d75a733f7a29d20dc04 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 May 2003 21:39:58 +0300 Subject: [PATCH 198/399] After merge fixes Added initialization of all important global variables BUILD/SETUP.sh: build with readline client/mysqltest.c: Added variable SERVER_VERSION myisam/mi_key.c: Indentation change myisam/mi_open.c: After merge fix myisam/mi_range.c: After merge fix myisam/mi_rkey.c: After merge fix myisam/mi_search.c: After merge fix myisam/myisamdef.h: After merge fix mysql-test/include/not_embedded.inc: Fix test (because of wrong utf8 test) mysql-test/r/alter_table.result: Updated results after merge mysql-test/r/create.result: Updated results after merge mysql-test/r/ctype_recoding.result: Updated results after merge mysql-test/r/fulltext.result: Updated results after merge mysql-test/r/func_group.result: Updated results after merge mysql-test/r/group_by.result: Updated results after merge mysql-test/r/innodb.result: Updated results after merge mysql-test/r/join_outer.result: Updated results after merge mysql-test/r/null_key.result: Updated results after merge mysql-test/r/order_by.result: Updated results after merge mysql-test/r/query_cache.result: Updated results after merge mysql-test/r/repair.result: Updated results after merge mysql-test/r/rpl_flush_tables.result: Updated results after merge mysql-test/r/union.result: Updated results after merge mysql-test/r/update.result: Updated results after merge mysql-test/t/ansi.test: After merge fixes mysql-test/t/create.test: After merge fixes mysql-test/t/ctype_recoding.test: After merge fixes mysql-test/t/ctype_ujis.test: After merge fixes mysql-test/t/fulltext.test: After merge fixes mysql-test/t/innodb.test: After merge fixes mysql-test/t/join_outer.test: After merge fixes mysql-test/t/loaddata.test: After merge fixes mysql-test/t/order_by.test: After merge fixes mysql-test/t/rpl_flush_tables.test: After merge fixes mysql-test/t/status.test: After merge fixes mysql-test/t/subselect.test: After merge fixes sql/convert.cc: Code cleanup sql/field.cc: After merge fixes sql/filesort.cc: Remove compiler warning sql/item.cc: More efficient set_name() (no mallocs) sql/item_cmpfunc.cc: Code Code cleanup Item_bool_func2::fix_fields() added to get error handling right for cmp_charset sql/item_cmpfunc.h: New prototypes sql/item_func.cc: After merge fix sql/item_strfunc.cc: Faster check for BINARY sql/log_event.cc: Comment cleanup sql/mysql_priv.h: New prototypes and variables sql/mysqld.cc: Added initialization of all important global variables. Cleanup of variable declarations This is needed ot make the embedded version restartable sql/opt_sum.cc: After merge fix sql/set_var.cc: Code cleanup sql/sql_acl.cc: After merge fix Better error message sql/sql_db.cc: After merge fix sql/sql_derived.cc: After merge fix sql/sql_insert.cc: Indentation cleanups sql/sql_list.h: Added empty() to base_ilist sql/sql_parse.cc: After merge fix sql/sql_select.cc: After merge fix Fixed derived name handling in EXPLAIN sql/sql_show.cc: After merge fix sql/sql_string.cc: Made copy_and_convert global sql/sql_string.h: Made copy_and_convert global sql/sql_update.cc: After merge fix sql/sql_yacc.yy: After merge fix sql/thr_malloc.cc: Added sql_strmake_with_convert() sql/unireg.h: Added MAX_ALIAS_NAME strings/ctype-ujis.c: Fixed bug in converting to ujis --- BUILD/SETUP.sh | 2 +- client/mysqltest.c | 60 +-- myisam/mi_key.c | 2 +- myisam/mi_open.c | 6 - myisam/mi_range.c | 5 +- myisam/mi_rkey.c | 2 +- myisam/mi_search.c | 4 +- myisam/myisamdef.h | 4 +- mysql-test/include/not_embedded.inc | 2 +- mysql-test/r/alter_table.result | 4 +- mysql-test/r/create.result | 6 +- mysql-test/r/ctype_recoding.result | 1 + mysql-test/r/fulltext.result | 1 - mysql-test/r/func_group.result | 94 ++--- mysql-test/r/group_by.result | 16 +- mysql-test/r/innodb.result | 12 +- mysql-test/r/join_outer.result | 1 - mysql-test/r/null_key.result | 2 +- mysql-test/r/order_by.result | 4 +- mysql-test/r/query_cache.result | 20 +- mysql-test/r/repair.result | 2 +- mysql-test/r/rpl_flush_tables.result | 4 +- mysql-test/r/union.result | 37 +- mysql-test/r/update.result | 5 +- mysql-test/t/ansi.test | 2 + mysql-test/t/create.test | 10 +- mysql-test/t/ctype_recoding.test | 1 + mysql-test/t/ctype_ujis.test | 2 + mysql-test/t/fulltext.test | 2 - mysql-test/t/innodb.test | 1 - mysql-test/t/join_outer.test | 2 +- mysql-test/t/loaddata.test | 2 + mysql-test/t/order_by.test | 2 +- mysql-test/t/rpl_flush_tables.test | 2 + mysql-test/t/status.test | 2 +- mysql-test/t/subselect.test | 2 + sql/convert.cc | 4 +- sql/field.cc | 18 +- sql/filesort.cc | 2 +- sql/item.cc | 43 +- sql/item_cmpfunc.cc | 75 ++-- sql/item_cmpfunc.h | 3 +- sql/item_func.cc | 12 +- sql/item_strfunc.cc | 2 +- sql/log_event.cc | 60 +-- sql/mysql_priv.h | 6 +- sql/mysqld.cc | 561 ++++++++++++++++----------- sql/opt_sum.cc | 1 + sql/set_var.cc | 3 +- sql/sql_acl.cc | 7 +- sql/sql_db.cc | 4 +- sql/sql_derived.cc | 16 +- sql/sql_insert.cc | 10 +- sql/sql_list.h | 1 + sql/sql_parse.cc | 6 +- sql/sql_select.cc | 16 +- sql/sql_show.cc | 3 +- sql/sql_string.cc | 5 +- sql/sql_string.h | 3 + sql/sql_update.cc | 8 +- sql/sql_yacc.yy | 14 +- sql/thr_malloc.cc | 30 ++ sql/unireg.h | 1 + strings/ctype-ujis.c | 2 +- 64 files changed, 694 insertions(+), 548 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 55b82e38d63..4a19c490e5d 100644 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -52,7 +52,7 @@ debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMA base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti" -base_configs="--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client" +base_configs="--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-readline" static_link="--with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static" alpha_configs="" # Not used yet pentium_configs="" diff --git a/client/mysqltest.c b/client/mysqltest.c index fb2104f43f4..9889d365335 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -939,16 +939,16 @@ int do_system(struct st_query* q) var_init(&v, 0, 0, 0, 0); eval_expr(&v, p, 0); /* NULL terminated */ if (v.str_val_len) - { - char expr_buf[512]; - if ((uint)v.str_val_len > sizeof(expr_buf) - 1) - v.str_val_len = sizeof(expr_buf) - 1; - memcpy(expr_buf, v.str_val, v.str_val_len); - expr_buf[v.str_val_len] = 0; - DBUG_PRINT("info", ("running system command '%s'", expr_buf)); - if (system(expr_buf) && q->abort_on_error) - die("system command '%s' failed", expr_buf); - } + { + char expr_buf[512]; + if ((uint)v.str_val_len > sizeof(expr_buf) - 1) + v.str_val_len = sizeof(expr_buf) - 1; + memcpy(expr_buf, v.str_val, v.str_val_len); + expr_buf[v.str_val_len] = 0; + DBUG_PRINT("info", ("running system command '%s'", expr_buf)); + if (system(expr_buf) && q->abort_on_error) + die("system command '%s' failed", expr_buf); + } var_free(&v); return 0; } @@ -2284,7 +2284,7 @@ void get_query_type(struct st_query* q) q->type=(enum enum_commands) type; /* Found command */ } -static byte* get_var_key(const byte* var, uint* len, +static byte *get_var_key(const byte* var, uint* len, my_bool __attribute__((unused)) t) { register char* key; @@ -2293,11 +2293,11 @@ static byte* get_var_key(const byte* var, uint* len, return (byte*)key; } -static VAR* var_init(VAR* v, const char* name, int name_len, const char* val, +static VAR *var_init(VAR *v, const char *name, int name_len, const char *val, int val_len) { int val_alloc_len; - VAR* tmp_var; + VAR *tmp_var; if (!name_len && name) name_len = strlen(name); if (!val_len && val) @@ -2327,7 +2327,7 @@ static VAR* var_init(VAR* v, const char* name, int name_len, const char* val, return tmp_var; } -static void var_free(void* v) +static void var_free(void *v) { my_free(((VAR*) v)->str_val, MYF(MY_WME)); if (((VAR*)v)->alloced) @@ -2335,10 +2335,10 @@ static void var_free(void* v) } -static void var_from_env(const char* name, const char* def_val) +static void var_from_env(const char *name, const char *def_val) { - const char* tmp; - VAR* v; + const char *tmp; + VAR *v; if (!(tmp = getenv(name))) tmp = def_val; @@ -2347,9 +2347,9 @@ static void var_from_env(const char* name, const char* def_val) } -static void init_var_hash() +static void init_var_hash(MYSQL *mysql) { - VAR* v; + VAR *v; DBUG_ENTER("init_var_hash"); if (hash_init(&var_hash, charset_info, 1024, 0, 0, get_var_key, var_free, MYF(0))) @@ -2358,16 +2358,19 @@ static void init_var_hash() var_from_env("SLAVE_MYPORT", "9307"); var_from_env("MYSQL_TEST_DIR", "/tmp"); var_from_env("BIG_TEST", opt_big_test ? "1" : "0"); - v=var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "63",0); - hash_insert(&var_hash, (byte*)v); + v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0); + hash_insert(&var_hash, (byte*) v); + v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0); + hash_insert(&var_hash, (byte*) v); + DBUG_VOID_RETURN; } -int main(int argc, char** argv) +int main(int argc, char **argv) { int error = 0; - struct st_query* q; + struct st_query *q; my_bool require_file=0, q_send_flag=0; char save_file[FN_REFLEN]; MY_INIT(argv[0]); @@ -2402,7 +2405,6 @@ int main(int argc, char** argv) embedded_server_args, (char**) embedded_server_groups)) die("Can't initialize MySQL server"); - init_var_hash(); if (cur_file == file_stack) *++cur_file = stdin; *lineno=1; @@ -2421,14 +2423,14 @@ int main(int argc, char** argv) opt_ssl_capath, opt_ssl_cipher); #endif - cur_con->name = my_strdup("default", MYF(MY_WME)); - if (!cur_con->name) + if (!(cur_con->name = my_strdup("default", MYF(MY_WME)))) die("Out of memory"); - if (safe_connect(&cur_con->mysql, host, - user, pass, db, port, unix_sock)) + if (safe_connect(&cur_con->mysql, host, user, pass, db, port, unix_sock)) die("Failed in mysql_real_connect(): %s", mysql_error(&cur_con->mysql)); + init_var_hash(&cur_con->mysql); + while (!read_query(&q)) { int current_line_inc = 1, processed = 0; @@ -2596,7 +2598,7 @@ int main(int argc, char** argv) */ -static int read_server_arguments(const char* name) +static int read_server_arguments(const char *name) { char argument[1024],buff[FN_REFLEN], *str=0; FILE *file; diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 37708a399b0..a375a415103 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -164,7 +164,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, */ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, - uint k_length, MI_KEYSEG **last_used_keyseg) + uint k_length, HA_KEYSEG **last_used_keyseg) { uint length; uchar *pos,*end,*start_key=key; diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 6da1a0395c0..178365577aa 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -186,12 +186,6 @@ 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) - { - /* 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/myisam/mi_range.c b/myisam/mi_range.c index d5a786438cd..379ffba135a 100644 --- a/myisam/mi_range.c +++ b/myisam/mi_range.c @@ -59,7 +59,8 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key, if (start_key_len == 0) start_key_len=USE_WHOLE_KEY; key_buff=info->lastkey+info->s->base.max_key_length; - start_key_len=_mi_pack_key(info,inx,key_buff,(uchar*) start_key,start_key_len); + start_key_len= _mi_pack_key(info,inx,key_buff,(uchar*) start_key, + start_key_len, (HA_KEYSEG**) 0); res=rtree_estimate(info, inx, key_buff, start_key_len, myisam_read_vec[start_search_flag]); res=res?res:1; break; @@ -104,7 +105,7 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len, 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, - (MI_KEYSEG**) 0); + (HA_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 a702f78b926..ddfac0a39a2 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -28,7 +28,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, uchar *key_buff; MYISAM_SHARE *share=info->s; MI_KEYDEF *keyinfo; - MI_KEYSEG *last_used_keyseg; + HA_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", diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 340d8ec2db6..7e8577c0656 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -1042,9 +1042,9 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key) */ uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key, - MI_KEYSEG *end) + HA_KEYSEG *end) { - reg1 MI_KEYSEG *keyseg; + reg1 HA_KEYSEG *keyseg; uchar *start= key; for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++) diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 0d9d7d43438..c986c483902 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -538,7 +538,7 @@ 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); + HA_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); @@ -553,7 +553,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, MI_KEYSEG **last_used_keyseg); + uint key_length, HA_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/mysql-test/include/not_embedded.inc b/mysql-test/include/not_embedded.inc index 52ae026ece3..fcc1756caab 100644 --- a/mysql-test/include/not_embedded.inc +++ b/mysql-test/include/not_embedded.inc @@ -1,5 +1,5 @@ -- require r/not_embedded.require disable_query_log; -select version() like "%embedded%" as "have_embedded"; +select version() like N'%embedded%' as 'have_embedded'; enable_query_log; diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 1fe874a211c..ec2f7220a3d 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -158,8 +158,8 @@ alter table t2 rename t1, add c char(10) comment "no comment"; show columns from t1; Field Type Collation Null Key Default Extra i int(10) unsigned binary PRI NULL auto_increment -c char(10) latin1_swedish_ci YES NULL -drop table t1; +c char(10) latin1_swedish_ci 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); diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 520227c0fba..4e06c724142 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -183,18 +183,20 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0' -) TYPE=HEAP +) TYPE=HEAP CHARSET=latin1 drop table t1; SET SESSION table_type="gemini"; SELECT @@table_type; @@table_type GEMINI CREATE TABLE t1 (a int not null); +Warnings: +Warning 1259 Using storage engine MYISAM for table 't1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0' -) TYPE=MyISAM +) TYPE=MyISAM CHARSET=latin1 SET SESSION table_type=default; drop table t1; create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2)); diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index fb813e394f4..815445150cd 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -41,3 +41,4 @@ Field Type Collation Null Key Default Extra поле char(32) character set koi8r koi8r_general_ci SET CHARACTER SET koi8r; DROP TABLE ÔÁÂÌÉÃÁ; +SET CHARACTER SET default; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index d87b00dd4d7..5b410396390 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -216,7 +216,6 @@ 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); diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index e9fb56a77d6..99d7bd2d087 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -42,22 +42,12 @@ insert into t1 values (null,null,''); select count(distinct a),count(distinct grp) from t1; count(distinct a) count(distinct grp) 6 3 -select sum(all a),count(all a),avg(all a),std(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1; -sum(all a) count(all a) avg(all a) std(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c) -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 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 -select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp; select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1; sum(all a) count(all a) avg(all a) std(all a) variance(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c) 21 6 3.5000 1.7078 2.9167 7 0 1 6 E select grp, sum(a),count(a),avg(a),std(a),variance(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) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c) -NULL 0 0 NULL NULL NULL 0 0 NULL NULL +NULL NULL 0 NULL NULL NULL 0 0 NULL NULL 1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a 2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c 3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E @@ -231,47 +221,6 @@ select max(t1.a2),max(t2.a1) from t1 left outer join t2 on t1.a1=10; max(t1.a2) max(t2.a1) zzz BBB 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; create table t1( a1 char(3) primary key, a2 smallint, @@ -613,3 +562,44 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using index 1 SIMPLE t2 index NULL k2 4 NULL 6 Using where; Using index 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 18446744073709551615 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 18446744073709551615 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 18446744073709551615 0 +2 0 NULL NULL NULL NULL NULL 18446744073709551615 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 18446744073709551615 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 18446744073709551615 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/r/group_by.result b/mysql-test/r/group_by.result index 5a5689f0185..2f9a55e0c42 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -54,9 +54,9 @@ userid MIN(t1.score+0.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 eq_ref PRIMARY PRIMARY 4 t1.userID 1 Using index +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 t1.userID 1 Using index drop table t1,t2; CREATE TABLE t1 ( PID int(10) unsigned NOT NULL auto_increment, @@ -253,10 +253,10 @@ key (score) 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; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort explain select userid,count(*) from t1 group by userid desc order by null; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using temporary select userid,count(*) from t1 group by userid desc; userid count(*) 3 5 @@ -269,13 +269,13 @@ select userid,count(*) from t1 group by userid desc having 3 IN (1,COUNT(*)); userid count(*) explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index +1 SIMPLE 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; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index +1 SIMPLE 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; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index +1 SIMPLE 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 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 922f4816e90..98613dad628 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1209,7 +1209,8 @@ 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 +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back SELECT * FROM t1; B_ID drop table t1,t2; @@ -1247,12 +1248,12 @@ select count(*) from t1; count(*) 29267 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 +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE 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 +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE 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); @@ -1286,6 +1287,7 @@ a b 13 2 111 100 111 100 +drop table t1; CREATE TABLE t1 (col1 int(1))TYPE=InnoDB; CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP(+0),INDEX stamp_idx (stamp))TYPE=InnoDB; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 1412c5e7d10..123de82fe09 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -646,7 +646,6 @@ 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); diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 3248d359546..c55f29a4e78 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -84,7 +84,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE 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; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range a,b a 5 NULL 12 Using where +1 SIMPLE 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; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref a,b a 5 const 3 Using where diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index a8a6dd6312d..0cfe1534252 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -549,10 +549,10 @@ KEY FieldKey (FieldKey), KEY LongField (FieldKey,LongVal), KEY StringField (FieldKey,StringVal(32)) ); -INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3'); +INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3'); EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 36 const 2 Using where +1 SIMPLE t1 ref FieldKey,LongField,StringField StringField 36 const 3 Using where; Using filesort SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; FieldKey LongVal StringVal 1 0 2 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 48a2a8a5a21..1d46d1dcf25 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -382,14 +382,14 @@ a set CHARACTER SET cp1251_koi8; select * from t1; a -? +á set CHARACTER SET DEFAULT; show status like "Qcache_queries_in_cache"; Variable_name Value -Qcache_queries_in_cache 2 +Qcache_queries_in_cache 1 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 4 +Qcache_hits 5 drop table t1; create database if not exists mysqltest; create table mysqltest.t1 (i int not null); @@ -415,7 +415,7 @@ Variable_name Value Qcache_queries_in_cache 2 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 6 +Qcache_hits 7 drop database mysqltest; drop table t1; create table t1 (i int not null); @@ -429,7 +429,7 @@ FOUND_ROWS() 4 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 6 +Qcache_hits 7 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 1 @@ -441,7 +441,7 @@ FOUND_ROWS() 1 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 6 +Qcache_hits 7 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 2 @@ -454,7 +454,7 @@ FOUND_ROWS() 4 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 7 +Qcache_hits 8 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 2 @@ -466,7 +466,7 @@ FOUND_ROWS() 1 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 8 +Qcache_hits 9 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 2 @@ -535,7 +535,7 @@ a 3 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 11 +Qcache_hits 12 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 2 @@ -552,7 +552,7 @@ a 3 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 12 +Qcache_hits 13 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 2 diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index 6c2107b2cf3..eb46622dcc1 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -7,7 +7,7 @@ test.t1 repair status OK 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 +test.t1 repair error The storage enginge for the table doesn't support repair drop table t1; repair table t1 use_frm; Table Op Msg_type Msg_text diff --git a/mysql-test/r/rpl_flush_tables.result b/mysql-test/r/rpl_flush_tables.result index 7eb3b77758e..6353a6101d6 100644 --- a/mysql-test/r/rpl_flush_tables.result +++ b/mysql-test/r/rpl_flush_tables.result @@ -14,7 +14,7 @@ rename table t1 to t5, t2 to t1; flush no_write_to_binlog tables; show binlog events; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.000001 4 Start 1 4 Server ver: 4.1.1-alpha-debug-log, Binlog ver: 3 +master-bin.000001 4 Start 1 4 Server ver: SERVER_VERSION, Binlog ver: 3 master-bin.000001 79 Query 1 79 use `test`; create table t1 (a int) master-bin.000001 137 Query 1 137 use `test`; insert into t1 values (10) master-bin.000001 198 Query 1 198 use `test`; create table t2 (a int) @@ -27,7 +27,7 @@ a flush tables; show binlog events; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.000001 4 Start 1 4 Server ver: 4.1.1-alpha-debug-log, Binlog ver: 3 +master-bin.000001 4 Start 1 4 Server ver: SERVER_VERSION, Binlog ver: 3 master-bin.000001 79 Query 1 79 use `test`; create table t1 (a int) master-bin.000001 137 Query 1 137 use `test`; insert into t1 values (10) master-bin.000001 198 Query 1 198 use `test`; create table t2 (a int) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index d506891b0fb..272ffdd330e 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -90,9 +90,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 2 UNION t2 ALL NULL NULL NULL NULL 4 Using filesort -select found_rows(); -found_rows() -0 explain select a,b from t1 union all select a,b from t2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 @@ -132,6 +129,23 @@ create table t3 select a,b from t1 union all select a,b from t2; insert into t3 select a,b from t1 union all select a,b from t2; replace into t3 select a,b as c from t1 union all select a,b from t2; drop table t1,t2,t3; +select * union select 1; +No tables used +select 1 as a,(select a union select a); +a (select a union select a) +1 1 +(select 1) union (select 2) order by 0; +Unknown column '0' in 'order clause' +SELECT @a:=1 UNION SELECT @a:=@a+1; +@a:=1 +1 +2 +(SELECT 1) UNION (SELECT 2) ORDER BY (SELECT a); +Unknown column 'a' in 'field list' +(SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2); +1 3 +1 3 +2 1 CREATE TABLE t1 ( `pseudo` char(35) NOT NULL default '', `pseudo1` char(35) NOT NULL default '', @@ -255,11 +269,6 @@ uid rl g1 cid gg uid rl g1 cid gg 1 NULL V1 NULL 1 drop table t1,t2,t3,t4,t5,t6; -select * union select 1; -No tables used -select 1 as a,(select a union select a); -a (select a union select a) -1 1 CREATE TABLE t1 ( id int(3) unsigned default '0') TYPE=MyISAM; INSERT INTO t1 (id) VALUES("1"); CREATE TABLE t2 ( id int(3) unsigned default '0', id_master int(5) default '0', text1 varchar(5) default NULL, text2 varchar(5) default NULL) TYPE=MyISAM; @@ -286,10 +295,6 @@ id_master id text1 text2 1 3 NULL bar3 1 4 foo4 bar4 drop table if exists t1,t2; -(SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2); -1 3 -1 3 -2 1 create table t1 (a int not null primary key auto_increment, b int, key(b)); create table t2 (a int not null primary key auto_increment, b int); insert into t1 (b) values (1),(2),(2),(3); @@ -323,11 +328,3 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 2 UNION t1 ref b b 5 const 1 Using where drop table t1,t2; -(select 1) union (select 2) order by 0; -Unknown column '0' in 'order clause' -SELECT @a:=1 UNION SELECT @a:=@a+1; -@a:=1 -1 -2 -(SELECT 1) UNION (SELECT 2) ORDER BY (SELECT a); -Unknown column 'a' in 'field list' diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index c308b8fcbcd..1d483da2c77 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -137,7 +137,10 @@ a b 13 2 111 100 111 100 -drop table t1; +create table t2 (a int not null, b int not null); +insert into t2 values (1,1),(1,2),(1,3); +update t1 set b=(select distinct 1 from (select * from t2) a); +drop table t1,t2; CREATE TABLE t1 ( `id_param` smallint(3) unsigned NOT NULL default '0', `nom_option` char(40) NOT NULL default '', diff --git a/mysql-test/t/ansi.test b/mysql-test/t/ansi.test index e1ac8ffd4f9..da82b7a9e31 100644 --- a/mysql-test/t/ansi.test +++ b/mysql-test/t/ansi.test @@ -2,7 +2,9 @@ # Test of ansi mode # +--disable_warnings drop table if exists t1; +--enable_warnings # Test some functions that works different in ansi mode diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 3a02e5d67e8..9bc37a0864d 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -145,9 +145,13 @@ drop table t1; # 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); +--error 1048 +insert into t1 values ("c", NULL); +--error 1048 +insert into t1 values (NULL, 3); +--error 1048 +insert into t1 values (NULL, NULL); +drop table t1; # # Test create with foreign keys diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 0330bbd23b4..68526806166 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -26,3 +26,4 @@ SHOW FIELDS FROM таблица; SET CHARACTER SET koi8r; DROP TABLE ÔÁÂÌÉÃÁ; +SET CHARACTER SET default; diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test index cd1dc965000..7308f26a8cf 100644 --- a/mysql-test/t/ctype_ujis.test +++ b/mysql-test/t/ctype_ujis.test @@ -1,7 +1,9 @@ # # Tests with the ujis character set # +--disable_warnings drop table if exists t1; +--enable_warnings # # Test problem with LEFT() diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 1c579ddcc62..40ac7f905c7 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -180,11 +180,9 @@ drop table t1; # 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/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index a0cb104df48..3736f4a2ddc 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -807,7 +807,6 @@ 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; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 49f13abe7c2..df7e5b1524d 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -417,7 +417,7 @@ 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); diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index ceb5c47af11..d7e84590dc0 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -2,7 +2,9 @@ # Some simple test of load data # +--disable_warnings drop table if exists t1; +--enable_warnings 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 ','; diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 5235eddd671..702feedc3ce 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -357,7 +357,7 @@ CREATE TABLE t1 ( KEY LongField (FieldKey,LongVal), KEY StringField (FieldKey,StringVal(32)) ); -INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3'); +INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3'); EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal; diff --git a/mysql-test/t/rpl_flush_tables.test b/mysql-test/t/rpl_flush_tables.test index e62ba2e94c7..67720343e83 100644 --- a/mysql-test/t/rpl_flush_tables.test +++ b/mysql-test/t/rpl_flush_tables.test @@ -17,12 +17,14 @@ rename table t1 to t5, t2 to t1; # first don't write it to the binlog, to test the NO_WRITE_TO_BINLOG keyword. flush no_write_to_binlog tables; # Check that it's not in the binlog. +--replace_result $SERVER_VERSION SERVER_VERSION show binlog events; # Check that the master is not confused. select * from t3; # This FLUSH should go into the binlog to not confuse the slave. flush tables; # Check that it's in the binlog. +--replace_result $SERVER_VERSION SERVER_VERSION show binlog events; save_master_pos; connection slave; diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 90d7f814359..30edcc79d9e 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -4,7 +4,7 @@ # This would work if mysqltest run would be threaded and handle each # connection in a separate thread. # --- source include/not_embedded.inc +--source include/not_embedded.inc connect (con1,localhost,root,,); connect (con2,localhost,root,,); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 8e8a3dfe1d4..4a171c36293 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -396,6 +396,8 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3); SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); -- error 1093 INSERT INTO t2 VALUES ((SELECT * FROM t2)); +-- error 1093 +INSERT INTO t2 VALUES ((SELECT id FROM t2)); SELECT * FROM t2; CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1; INSERT INTO t1 values (1),(1); diff --git a/sql/convert.cc b/sql/convert.cc index bfdf49bf42d..880c462f4aa 100644 --- a/sql/convert.cc +++ b/sql/convert.cc @@ -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 */ -#if 0 +#ifdef NOT_USED /* ** Convert tables between different character sets @@ -462,4 +462,4 @@ bool CONVERT::store(String *packet,const char *from,uint length) return 0; } -#endif +#endif /* NOT_USED */ diff --git a/sql/field.cc b/sql/field.cc index d6f9797071b..9557bca9b28 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3977,23 +3977,19 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), int Field_string::cmp(const char *a_ptr, const char *b_ptr) { -#ifdef USE_STRCOLL - if (field_charset->mbmaxlen > 1) + if (field_charset->strxfrm_multiply > 1) { /* 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(field_charset, - (const uchar*) a_ptr, a_length, - (const uchar*) b_ptr, b_length); + return field_charset->strnncollsp(field_charset, + (const uchar*) a_ptr, field_length, + (const uchar*) b_ptr, field_length); } -#endif - return my_strnncoll(field_charset, - (const uchar*) a_ptr, field_length, - (const uchar*) b_ptr, field_length); + return field_charset->strnncoll(field_charset, + (const uchar*) a_ptr, field_length, + (const uchar*) b_ptr, field_length); } void Field_string::sort_string(char *to,uint length) diff --git a/sql/filesort.cc b/sql/filesort.cc index 68b8737bc79..2130bdaeb93 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -76,7 +76,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ulong memavl, min_sort_memory; uint maxbuffer; BUFFPEK *buffpek; - ha_rows records; + ha_rows records= HA_POS_ERROR; uchar **sort_keys; IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; SORTPARAM param; diff --git a/sql/item.cc b/sql/item.cc index 7599ae6486f..636cefb511b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -90,28 +90,32 @@ bool Item::check_cols(uint c) return 0; } -void Item::set_name(const char *str,uint length, CHARSET_INFO *cs) + +void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) { if (!length) - name= (char*) str; // Empty string, used by AS - else { - while (length && !my_isgraph(cs,*str)) - { // Fix problem with yacc - length--; - str++; - } - if (length && !my_charset_same(cs, system_charset_info)) - { - String tmp; - tmp.copy(str, length, cs, system_charset_info); - name=sql_strmake(tmp.ptr(),min(tmp.length(),MAX_FIELD_WIDTH)); - } - else - name=sql_strmake(str,min(length,MAX_FIELD_WIDTH)); + /* Empty string, used by AS or internal function like last_insert_id() */ + name= (char*) str; + return; } + while (length && !my_isgraph(cs,*str)) + { // Fix problem with yacc + length--; + str++; + } + if (!my_charset_same(cs, system_charset_info)) + { + uint32 res_length; + name= sql_strmake_with_convert(str, length, cs, + MAX_ALIAS_NAME, system_charset_info, + &res_length); + } + else + name=sql_strmake(str, min(length,MAX_ALIAS_NAME)); } + /* This function is only called when comparing items in the WHERE clause */ @@ -1048,13 +1052,6 @@ 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) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 7cc07690fcc..4892516c080 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -90,7 +90,7 @@ static bool convert_constant_item(Field *field, Item **item) bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1, CHARSET_INFO *cs2, enum coercion co2) { - if((cs1 == &my_charset_bin) || (cs2 == &my_charset_bin)) + if ((cs1 == &my_charset_bin) || (cs2 == &my_charset_bin)) { cmp_charset= &my_charset_bin; return 0; @@ -114,29 +114,42 @@ bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1, { if (co1 == COER_COERCIBLE) { - CHARSET_INFO *c= get_charset_by_csname(cs1->csname,MY_CS_PRIMARY,MYF(0)); - if (c) + CHARSET_INFO *c; + if ((c= get_charset_by_csname(cs1->csname, MY_CS_PRIMARY, MYF(0)))) { cmp_charset= c; return 0; } - else - return 1; } - else - return 1; + return 1; } } return 0; } + +bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables, + Item ** ref) +{ + if (Item_int_func::fix_fields(thd, tables, ref)) + return 1; + if (!cmp_charset) + { + /* set_cmp_charset() failed */ + my_error(ER_WRONG_ARGUMENTS,MYF(0),func_name()); + return 1; + } + return 0; +} + + void Item_bool_func2::fix_length_and_dec() { max_length= 1; // Function returns 0 or 1 /* As some compare functions are generated after sql_yacc, - we have to check for out of memory conditons here + we have to check for out of memory conditions here */ if (!args[0] || !args[1]) return; @@ -149,7 +162,8 @@ void Item_bool_func2::fix_length_and_dec() if (convert_constant_item(field,&args[1])) { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, - INT_RESULT); // Works for all types. + INT_RESULT); // Works for all types. + cmp_charset= &my_charset_bin; // For test in fix_fields return; } } @@ -163,17 +177,19 @@ void Item_bool_func2::fix_length_and_dec() { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, INT_RESULT); // Works for all types. + cmp_charset= &my_charset_bin; // For test in fix_fields return; } } } - if (set_cmp_charset(args[0]->charset(), args[0]->coercibility, - args[1]->charset(), args[1]->coercibility)) - { - my_error(ER_WRONG_ARGUMENTS,MYF(0),func_name()); - return; - } set_cmp_func(); + /* + We must set cmp_charset here as we may be called from for an automatic + generated item, like in natural join + */ +end: + set_cmp_charset(args[0]->charset(), args[0]->coercibility, + args[1]->charset(), args[1]->coercibility); } @@ -191,22 +207,22 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) comparators= 0; return 1; } - if ((comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n))) - for (uint i=0; i < n; i++) - { - if ((*a)->el(i)->cols() != (*b)->el(i)->cols()) - { - my_error(ER_CARDINALITY_COL, MYF(0), (*a)->el(i)->cols()); - return 1; - } - comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); - } - else + if (!(comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n))) return 1; + for (uint i=0; i < n; i++) + { + if ((*a)->el(i)->cols() != (*b)->el(i)->cols()) + { + my_error(ER_CARDINALITY_COL, MYF(0), (*a)->el(i)->cols()); + return 1; + } + comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); + } } return 0; } + int Arg_comparator::compare_string() { String *res1,*res2; @@ -1875,13 +1891,6 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) if (Item_bool_func2::fix_fields(thd, tlist, ref)) return 1; - if (set_cmp_charset(args[0]->charset(), args[0]->coercibility, - args[1]->charset(), args[1]->coercibility)) - { - my_error(ER_WRONG_ARGUMENTS,MYF(0),func_name()); - return 1; - } - /* We could also do boyer-more for non-const items, but as we would have to recompute the tables for each row it's not worth it. diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 5e246e3e285..ff469deab30 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -116,7 +116,8 @@ protected: public: Item_bool_func2(Item *a,Item *b): - Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {} + Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), cmp_charset(0) {} + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref); void fix_length_and_dec(); void set_cmp_func() { diff --git a/sql/item_func.cc b/sql/item_func.cc index eeab2367b2e..cc428822dd8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -40,8 +40,8 @@ eval_const_cond(COND *cond) } -Item_func::Item_func(List &list): - allowed_arg_cols(1) +Item_func::Item_func(List &list) + :allowed_arg_cols(1) { arg_count=list.elements; if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) @@ -109,10 +109,12 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { // Print purify happy for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - Item *item= *arg; - if (item->fix_fields(thd, tables, arg) || - item->check_cols(allowed_arg_cols)) + Item *item; + /* We can't yet set item to *arg as fix_fields may change *arg */ + if ((*arg)->fix_fields(thd, tables, arg) || + (*arg)->check_cols(allowed_arg_cols)) return 1; /* purecov: inspected */ + item= *arg; if (item->maybe_null) maybe_null=1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d28341c3bd0..ff96e1060a3 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2174,7 +2174,7 @@ void Item_func_set_collation::fix_length_and_dec() const char *colname; String tmp, *str= args[1]->val_str(&tmp); colname= str->c_ptr(); - if (!strncmp(colname,"BINARY",6)) + if (colname == binary_keyword) set_collation= get_charset_by_csname(args[0]->charset()->csname, MY_CS_BINSORT,MYF(0)); else diff --git a/sql/log_event.cc b/sql/log_event.cc index be5b5079eee..900d0a482aa 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -195,9 +195,9 @@ static inline int read_str(char * &buf, char *buf_end, char * &str, } -/**************************************************************************/ +/************************************************************************** Log_event methods -***************************************************************************/ +**************************************************************************/ /* Log_event::get_type_str() @@ -715,9 +715,9 @@ void Log_event::set_log_pos(MYSQL_LOG* log) #endif // !MYSQL_CLIENT -/**************************************************************************/ +/************************************************************************** Query_log_event methods -***************************************************************************/ +**************************************************************************/ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) @@ -982,9 +982,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) #endif -/**************************************************************************/ +/************************************************************************** Start_log_event methods -***************************************************************************/ +**************************************************************************/ /* Start_log_event::pack_info() @@ -1093,9 +1093,9 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli) } #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ -/**************************************************************************/ +/************************************************************************** Load_log_event methods -***************************************************************************/ +**************************************************************************/ /* Load_log_event::pack_info() @@ -1651,9 +1651,9 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, #endif -/****************************************************************************/ +/************************************************************************** Rotate_log_event methods -*****************************************************************************/ +**************************************************************************/ /* Rotate_log_event::pack_info() @@ -1788,9 +1788,9 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli) #endif -/***************************************************************************/ +/************************************************************************** Intvar_log_event methods -****************************************************************************/ +**************************************************************************/ /* Intvar_log_event::pack_info() @@ -1902,9 +1902,9 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) #endif -/**************************************************************************** +/************************************************************************** Rand_log_event methods -****************************************************************************/ +**************************************************************************/ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) void Rand_log_event::pack_info(Protocol *protocol) @@ -1964,9 +1964,9 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli) #endif // !MYSQL_CLIENT -/*************************************************************************** +/************************************************************************** User_var_log_event methods -***************************************************************************/ +**************************************************************************/ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) void User_var_log_event::pack_info(Protocol* protocol) @@ -2195,9 +2195,9 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) #endif // !MYSQL_CLIENT -/**************************************************************************** +/************************************************************************** Slave_log_event methods -****************************************************************************/ +**************************************************************************/ #ifdef HAVE_REPLICATION #ifdef MYSQL_CLIENT @@ -2342,9 +2342,9 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli) #endif // !MYSQL_CLIENT -/***************************************************************************/ +/************************************************************************** Stop_log_event methods -****************************************************************************/ +**************************************************************************/ /* Stop_log_event::print() @@ -2403,9 +2403,9 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli) #endif /* HAVE_REPLICATION */ -/***************************************************************************/ +/************************************************************************** Create_file_log_event methods -****************************************************************************/ +**************************************************************************/ /* Create_file_log_event ctor @@ -2622,9 +2622,9 @@ err: #endif -/***************************************************************************/ +/************************************************************************** Append_block_log_event methods -****************************************************************************/ +**************************************************************************/ /* Append_block_log_event ctor @@ -2739,9 +2739,9 @@ err: #endif -/***************************************************************************/ +/************************************************************************** Delete_file_log_event methods -****************************************************************************/ +**************************************************************************/ /* Delete_file_log_event ctor @@ -2829,9 +2829,9 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli) #endif -/**************************************************************************/ +/************************************************************************** Execute_load_log_event methods -***************************************************************************/ +**************************************************************************/ /* Execute_load_log_event ctor @@ -2971,9 +2971,9 @@ err: #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ -/**************************************************************************/ +/************************************************************************** sql_ex_info methods -***************************************************************************/ +**************************************************************************/ /* sql_ex_info::write_data() diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5caa93115ab..a3545ee6098 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -45,6 +45,10 @@ char *sql_strdup(const char *str); char *sql_strmake(const char *str,uint len); gptr sql_memdup(const void * ptr,unsigned size); void sql_element_free(void *ptr); +char *sql_strmake_with_convert(const char *str, uint32 arg_length, + CHARSET_INFO *from_cs, + uint32 max_res_length, + CHARSET_INFO *to_cs, uint32 *result_length); void kill_one_thread(THD *thd, ulong id); bool net_request_file(NET* net, const char* fname); char* query_table_status(THD *thd,const char *db,const char *table_name); @@ -687,7 +691,7 @@ extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) extern MY_TMPDIR mysql_tmpdir_list; extern const char *command_name[]; -extern const char *first_keyword, *localhost, *delayed_user; +extern const char *first_keyword, *localhost, *delayed_user, *binary_keyword; extern const char **errmesg; /* Error messages */ extern const char *myisam_recover_options_str; extern uchar *days_in_month; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c75b1981426..dca881557f1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -116,7 +116,7 @@ int deny_severity = LOG_WARNING; #define my_fromhost(A) fromhost() #define my_hosts_access(A) hosts_access() #define my_eval_client(A) eval_client() -#endif +#endif /* __STDC__ */ #endif /* HAVE_LIBWRAP */ #ifdef HAVE_SYS_MMAN_H @@ -128,8 +128,8 @@ int deny_severity = LOG_WARNING; #include #include -event_handle_t eh; -Report_t ref; +static event_handle_t eh; +static Report_t ref; #endif /* __NETWARE__ */ #ifdef _AIX41 @@ -169,6 +169,7 @@ inline void reset_floating_point_exceptions() #else #define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads #endif +#define MYSQL_KILL_SIGNAL SIGTERM #ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R #include @@ -183,26 +184,6 @@ inline void reset_floating_point_exceptions() extern "C" int gethostname(char *name, int namelen); #endif -#define MYSQL_KILL_SIGNAL SIGTERM - -#ifndef DBUG_OFF -static const char* default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", - "d:t:i:o,/tmp/mysqld.trace"); -#endif - -#ifdef __NT__ -static char szPipeName [ 257 ]; -static SECURITY_ATTRIBUTES saPipeSecurity; -static SECURITY_DESCRIPTOR sdPipeDescriptor; -static HANDLE hPipe = INVALID_HANDLE_VALUE; -#endif -#ifdef __WIN__ -static pthread_cond_t COND_handler_count; -static uint handler_count; -static bool start_mode=0, use_opt_args; -static int opt_argc; -static char **opt_argv; -#endif /* Set prefix for windows binary */ #ifdef __WIN__ @@ -220,192 +201,78 @@ static char **opt_argv; #endif /* __NT__ */ #endif /* __WIN__ */ -#ifdef HAVE_BERKELEY_DB -SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_NO; -#endif -#ifdef HAVE_INNOBASE_DB -SHOW_COMP_OPTION have_innodb=SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_innodb=SHOW_OPTION_NO; -#endif -#ifdef HAVE_ISAM -SHOW_COMP_OPTION have_isam=SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_isam=SHOW_OPTION_NO; -#endif -#ifdef USE_RAID -SHOW_COMP_OPTION have_raid=SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_raid=SHOW_OPTION_NO; -#endif -#ifdef HAVE_OPENSSL -SHOW_COMP_OPTION have_openssl=SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_openssl=SHOW_OPTION_NO; -#endif -#ifdef HAVE_BROKEN_REALPATH -SHOW_COMP_OPTION have_symlink=SHOW_OPTION_NO; -#else -SHOW_COMP_OPTION have_symlink=SHOW_OPTION_YES; -#endif -#ifdef HAVE_QUERY_CACHE -SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_NO; -#endif -#ifdef HAVE_CRYPT -SHOW_COMP_OPTION have_crypt=SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_crypt=SHOW_OPTION_NO; -#endif -#ifdef HAVE_COMPRESS -SHOW_COMP_OPTION have_compress= SHOW_OPTION_YES; -#else -SHOW_COMP_OPTION have_compress= SHOW_OPTION_NO; -#endif + +/* Constants */ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; - -bool opt_large_files= sizeof(my_off_t) > 4; +const char *sql_mode_names[] = +{ + "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", + "SERIALIZE", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", + "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS", + "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", + NullS +}; +TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", + sql_mode_names }; +const char *first_keyword= "first", *binary_keyword= "BINARY"; +const char *localhost= "localhost", *delayed_user= "DELAYED"; #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) #define GET_HA_ROWS GET_ULL #else #define GET_HA_ROWS GET_ULONG #endif -#ifdef HAVE_LIBWRAP -char *libwrapName= NULL; -#endif - -/* - Variables to store startup options -*/ - -my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted -/* - If set, some standard measures to enforce slave data integrity will not - be performed -*/ -my_bool opt_reckless_slave = 0; - -ulong back_log, connect_timeout, concurrency; -char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], time_zone[30]; -char log_error_file[FN_REFLEN]; -bool opt_log, opt_update_log, opt_bin_log, opt_slow_log; -bool opt_error_log= IF_WIN(1,0); -bool opt_disable_networking=0, opt_skip_show_db=0; -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 my_bool opt_do_pstack = 0; -static ulong opt_specialflag=SPECIAL_ENGLISH; - -static ulong opt_myisam_block_size; -static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET; -static my_string opt_logname=0,opt_update_logname=0, - opt_binlog_index_name = 0,opt_slow_logname=0; - -static char* mysql_home_ptr= mysql_home; -static char* pidfile_name_ptr= pidfile_name; -char* log_error_file_ptr= log_error_file; -static pthread_t select_thread; -static my_bool opt_noacl=0, opt_bootstrap=0, opt_myisam_log=0; -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_old_passwords=0, use_old_passwords=0; -my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam; - -volatile bool mqh_used = 0; -FILE *bootstrap_file=0; - -static bool kill_in_progress=0, segfaulted= 0; -struct rand_struct sql_rand; // used by sql_class.cc:THD::THD() -static int cleanup_done; -static char **defaults_argv; -char glob_hostname[FN_REFLEN]; - -#include "sslopt-vars.h" -#ifdef HAVE_OPENSSL -char *des_key_file = 0; -struct st_VioSSLAcceptorFd *ssl_acceptor_fd= 0; -#endif /* HAVE_OPENSSL */ - -I_List replicate_rewrite_db; -I_List replicate_do_db, replicate_ignore_db; -// allow the user to tell us which db to replicate and which to ignore -I_List binlog_do_db, binlog_ignore_db; - -/* if we guessed server_id , we need to know about it */ -ulong server_id= 0; // Must be long becasue of set_var.cc -bool server_id_supplied = 0; - -uint mysql_port; -uint test_flags = 0, select_errors=0, dropping_tables=0,ha_open_options=0; -uint volatile thread_count=0, thread_running=0, kill_cached_threads=0, - wake_thread=0; -ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL | - OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE ); -uint protocol_version=PROTOCOL_VERSION; -struct system_variables global_system_variables; -struct system_variables max_system_variables; -ulonglong keybuff_size; -ulong table_cache_size, - thread_stack, - thread_stack_min,what_to_log= ~ (1L << (uint) COM_TIME), - query_buff_size, - slow_launch_time = 2L, - slave_open_temp_tables=0, - open_files_limit=0, max_binlog_size; -ulong com_stat[(uint) SQLCOM_END], com_other; -ulong slave_net_timeout; -ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0; -ulong query_cache_size=0; -#ifdef HAVE_QUERY_CACHE -ulong query_cache_limit= 0; -ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE; -Query_cache query_cache; -#endif +bool opt_large_files= sizeof(my_off_t) > 4; arg_cmp_func Arg_comparator::comparator_matrix[4][2] = {{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string}, {&Arg_comparator::compare_real, &Arg_comparator::compare_e_real}, {&Arg_comparator::compare_int, &Arg_comparator::compare_e_int}, {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row}}; -#ifdef HAVE_SMEM -char *shared_memory_base_name=default_shared_memory_base_name; -my_bool opt_enable_shared_memory = 0; -#endif -volatile ulong cached_thread_count=0; -// replication parameters, if master_host is not NULL, we are a slave -my_string master_user = (char*) "test", master_password = 0, master_host=0, - master_info_file = (char*) "master.info", - relay_log_info_file = (char*) "relay-log.info", - master_ssl_key=0, master_ssl_cert=0, master_ssl_capath=0, master_ssl_cipher=0; -my_string report_user = 0, report_password = 0, report_host=0; - -const char *localhost=LOCAL_HOST; -const char *delayed_user="DELAYED"; -uint master_port = MYSQL_PORT, master_connect_retry = 60; -uint report_port = MYSQL_PORT; -my_bool master_ssl = 0; - -ulong master_retry_count=0; -ulong bytes_sent = 0L, bytes_received = 0L; +/* Global variables */ +bool opt_log, opt_update_log, opt_bin_log, opt_slow_log; +bool opt_error_log= IF_WIN(1,0); +bool opt_disable_networking=0, opt_skip_show_db=0; +bool server_id_supplied = 0; bool opt_endinfo,using_udf_functions, locked_in_memory; bool opt_using_transactions, using_update_log; bool volatile abort_loop, select_thread_in_use, signal_thread_in_use; bool volatile ready_to_exit, shutdown_in_progress, grant_option; + +my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted +my_bool opt_reckless_slave = 0; +my_bool opt_enable_named_pipe= 0; +my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol; +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_old_passwords=0, use_old_passwords=0; +my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam; +my_bool opt_readonly, use_temp_pool, relay_log_purge; +volatile bool mqh_used = 0; + +uint mysql_port, test_flags, select_errors, dropping_tables, ha_open_options; +uint delay_key_write_options, protocol_version; +uint volatile thread_count, thread_running, kill_cached_threads, wake_thread; + +ulong back_log, connect_timeout, concurrency; +ulong server_id, thd_startup_options; +ulong table_cache_size, thread_stack, thread_stack_min, what_to_log; +ulong query_buff_size, slow_launch_time, slave_open_temp_tables; +ulong open_files_limit, max_binlog_size; +ulong slave_net_timeout; +ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0; +ulong query_cache_size=0; +ulong com_stat[(uint) SQLCOM_END], com_other; +ulong bytes_sent, bytes_received; ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */ -ulong query_id=1L,long_query_count,aborted_threads, - aborted_connects,delayed_insert_timeout,delayed_insert_limit, - delayed_queue_size,delayed_insert_threads,delayed_insert_writes, - delayed_rows_in_use,delayed_insert_errors,flush_time, thread_created; +ulong query_id, long_query_count, aborted_threads, aborted_connects; +ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size; +ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use; +ulong delayed_insert_errors,flush_time, thread_created; ulong filesort_rows, filesort_range_count, filesort_scan_count; ulong filesort_merge_passes; ulong select_range_check_count, select_range_count, select_scan_count; @@ -417,51 +284,52 @@ ulong max_connections,max_insert_delayed_threads,max_used_connections, ulong thread_id=1L,current_pid; ulong slow_launch_threads = 0; ulong expire_logs_days = 0; +ulong rpl_recovery_rank=0; +ulong my_bind_addr; /* the address we bind to */ +volatile ulong cached_thread_count= 0; +ulonglong keybuff_size; + +double log_10[32]; /* 10 potences */ + +time_t start_time; + +char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], time_zone[30]; +char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN]; +char* log_error_file_ptr= log_error_file; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *charsets_list, 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 -bool mysql_embedded=0; -#else -bool mysql_embedded=1; -#endif - -static char *opt_bin_logname = 0; -char *opt_relay_logname = 0, *opt_relaylog_index_name=0; char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION; -const char *first_keyword="first"; +char *mysql_unix_port, *opt_mysql_tmpdir; +char *my_bind_addr_str; const char **errmesg; /* Error messages */ const char *myisam_recover_options_str="OFF"; const char *sql_mode_str="OFF"; -ulong rpl_recovery_rank=0; -my_bool relay_log_purge=1; -my_string mysql_unix_port=NULL, opt_mysql_tmpdir=NULL; -MY_TMPDIR mysql_tmpdir_list; -ulong my_bind_addr; /* the address we bind to */ -char *my_bind_addr_str; -DATE_FORMAT dayord; -double log_10[32]; /* 10 potences */ +FILE *bootstrap_file; + +I_List replicate_rewrite_db; +I_List replicate_do_db, replicate_ignore_db; +// allow the user to tell us which db to replicate and which to ignore +I_List binlog_do_db, binlog_ignore_db; I_List threads,thread_cache; -time_t start_time; -const char *sql_mode_names[] = -{ - "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", - "SERIALIZE", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", - "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS", - "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", - NullS -}; -TYPELIB sql_mode_typelib= {array_elements(sql_mode_names)-1,"", - sql_mode_names}; +struct system_variables global_system_variables; +struct system_variables max_system_variables; +MY_TMPDIR mysql_tmpdir_list; +DATE_FORMAT dayord; MY_BITMAP temp_pool; -my_bool use_temp_pool=0; + +SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam; +SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache; +SHOW_COMP_OPTION have_crypt, have_compress; + +/* Thread specific variables */ pthread_key(MEM_ROOT*,THR_MALLOC); pthread_key(THD*, THR_THD); @@ -479,24 +347,98 @@ pthread_cond_t COND_thread_cache,COND_flush_thread_cache; pthread_t signal_thread; pthread_attr_t connection_attrib; +/* replication parameters, if master_host is not NULL, we are a slave */ +my_bool master_ssl; +uint master_port= MYSQL_PORT, master_connect_retry = 60; +uint report_port= MYSQL_PORT; +ulong master_retry_count=0; +char *master_user, *master_password, *master_host, *master_info_file; +char *relay_log_info_file, *master_ssl_key, *master_ssl_cert; +char *master_ssl_capath, *master_ssl_cipher, *report_user; +char *report_password, *report_host; +char *opt_relay_logname = 0, *opt_relaylog_index_name=0; + +/* Static variables */ + +static bool kill_in_progress, segfaulted; +static my_bool opt_do_pstack, opt_noacl, opt_bootstrap, opt_myisam_log; +static int cleanup_done; +static ulong opt_specialflag, opt_myisam_block_size; +static char *opt_logname, *opt_update_logname, *opt_binlog_index_name; +static char *opt_slow_logname; +static char *mysql_home_ptr, *pidfile_name_ptr; +static char **defaults_argv; +static char *opt_bin_logname; + +static my_socket unix_sock,ip_sock; +static pthread_t select_thread; +struct rand_struct sql_rand; // used by sql_class.cc:THD::THD() + +/* OS specific variables */ + #ifdef __WIN__ #undef getpid #include + +static pthread_cond_t COND_handler_count; +static uint handler_count; +static bool start_mode=0, use_opt_args; +static int opt_argc; +static char **opt_argv; + #if !defined(EMBEDDED_LIBRARY) -HANDLE hEventShutdown; +static HANDLE hEventShutdown; static char shutdown_event_name[40]; #include "nt_servc.h" static NTService Service; // Service object for WinNT -#endif +#endif /* EMBEDDED_LIBRARY */ +#endif /* __WIN__ */ + +#ifdef __NT__ +static char szPipeName [ 257 ]; +static SECURITY_ATTRIBUTES saPipeSecurity; +static SECURITY_DESCRIPTOR sdPipeDescriptor; +static HANDLE hPipe = INVALID_HANDLE_VALUE; #endif #ifdef OS2 pthread_cond_t eventShutdown; #endif +#ifndef EMBEDDED_LIBRARY +bool mysql_embedded=0; +#else +bool mysql_embedded=1; +#endif + +#ifndef DBUG_OFF +static const char* default_dbug_option; +#endif +#ifdef HAVE_LIBWRAP +char *libwrapName= NULL; +#endif +#ifdef HAVE_QUERY_CACHE +ulong query_cache_limit= 0; +ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE; +Query_cache query_cache; +#endif +#ifdef HAVE_SMEM +char *shared_memory_base_name= default_shared_memory_base_name; +my_bool opt_enable_shared_memory; +#endif + +#include "sslopt-vars.h" +#ifdef HAVE_OPENSSL +char *des_key_file; +struct st_VioSSLAcceptorFd *ssl_acceptor_fd; +#endif /* HAVE_OPENSSL */ + + +/* Function declarations */ + static void start_signal_handler(void); extern "C" pthread_handler_decl(signal_hand, arg); -static void set_options(void); +static void mysql_init_variables(void); static void get_options(int argc,char **argv); static int init_thread_environment(); static char *get_relative_path(const char *path); @@ -1998,6 +1940,7 @@ static int init_common_variables(const char *conf_file_name, int argc, max_system_variables.pseudo_thread_id= (ulong)~0; start_time=time((time_t*) 0); + mysql_init_variables(); #ifdef OS2 { @@ -2036,7 +1979,6 @@ static int init_common_variables(const char *conf_file_name, int argc, load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; - set_options(); get_options(argc,argv); if (init_thread_environment()) return 1; @@ -4610,18 +4552,110 @@ To see what values a running MySQL server is using, type\n\ } -static void set_options(void) +/* + Initialize all MySQL global variables to default values + + SYNOPSIS + mysql_init_variables() + + NOTES + The reason to set a lot of global variables to zero is to allow one to + restart the embedded server with a clean environment + It's also needed on some exotic platforms where global variables are + not set to 0 when a program starts. + + We don't need to set numeric variables refered to in my_long_options + as these are initialized by my_getopt. +*/ + +static void mysql_init_variables(void) { -#if !defined( my_pthread_setprio ) && !defined( HAVE_PTHREAD_SETSCHEDPARAM ) - opt_specialflag |= SPECIAL_NO_PRIOR; -#endif + /* Things reset to zero */ + opt_skip_slave_start= opt_reckless_slave = 0; + mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; + opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0; + opt_disable_networking= opt_skip_show_db=0; + opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname=0; + opt_bootstrap= opt_myisam_log= use_old_passwords= 0; + mqh_used= 0; + segfaulted= kill_in_progress= 0; + cleanup_done= 0; + defaults_argv= 0; + server_id_supplied= 0; + test_flags= select_errors= dropping_tables= ha_open_options=0; + thread_count= thread_running= kill_cached_threads= wake_thread=0; + slave_open_temp_tables= 0; + com_other= 0; + cached_thread_count= 0; + bytes_sent= bytes_received= 0; + opt_endinfo= using_udf_functions= 0; + opt_using_transactions= using_update_log= 0; + abort_loop= select_thread_in_use= signal_thread_in_use= 0; + ready_to_exit= shutdown_in_progress= grant_option= 0; + long_query_count= aborted_threads= aborted_connects= 0; + delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0; + delayed_insert_errors= thread_created= 0; + filesort_rows= filesort_range_count= filesort_scan_count= 0; + filesort_merge_passes= select_range_check_count= select_range_count= 0; + select_scan_count= select_full_range_join_count= select_full_join_count= 0; + specialflag= opened_tables= created_tmp_tables= created_tmp_disk_tables= 0; + max_used_connections= slow_launch_threads = 0; + max_sort_char= 0; + mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0; + errmesg= 0; + mysql_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; + bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); + bzero((gptr) &com_stat, sizeof(com_stat)); + /* Things with default values that are not zero */ + delay_key_write_options= (uint) DELAY_KEY_WRITE_ON; + opt_specialflag= SPECIAL_ENGLISH; + unix_sock= ip_sock= INVALID_SOCKET; + mysql_home_ptr= mysql_home; + pidfile_name_ptr= pidfile_name; + log_error_file_ptr= log_error_file; + language_ptr= language; + mysql_data_home= mysql_real_data_home; + thd_startup_options= (OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL | + OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE); + protocol_version= PROTOCOL_VERSION; + what_to_log= ~ (1L << (uint) COM_TIME); + refresh_version= flush_version= 1L; /* Increments on each reload */ + thread_id= 1L; + strmov(server_version, MYSQL_SERVER_VERSION); + myisam_recover_options_str= sql_mode_str= "OFF"; + my_bind_addr = htonl(INADDR_ANY); + threads.empty(); + thread_cache.empty(); + + /* Initialize structures that is used when processing options */ + replicate_rewrite_db.empty(); + replicate_do_db.empty(); + replicate_ignore_db.empty(); + binlog_do_db.empty(); + binlog_ignore_db.empty(); + + /* Set directory paths */ + strmake(language, LANGUAGE, sizeof(language)-1); + strmake(mysql_real_data_home, get_relative_path(DATADIR), + sizeof(mysql_real_data_home)-1); + mysql_data_home_buff[0]=FN_CURLIB; // all paths are relative from here + mysql_data_home_buff[1]=0; + + /* Replication parameters */ + master_user= (char*) "test"; + master_password= master_host= 0; + master_info_file= (char*) "master.info", + relay_log_info_file= (char*) "relay-log.info", + master_ssl_key= master_ssl_cert= master_ssl_capath= master_ssl_cipher= 0; + report_user= report_password = report_host= 0; /* TO BE DELETED */ + opt_relay_logname= opt_relaylog_index_name= 0; + + /* Variables in libraries */ + charsets_dir= 0; sys_charset.value= (char*) MYSQL_CHARSET; - (void) strmake(language, LANGUAGE, sizeof(language)-1); - (void) strmake(mysql_real_data_home, get_relative_path(DATADIR), - sizeof(mysql_real_data_home)-1); - /* Set default values for some variables */ + /* Set default values for some option variables */ global_system_variables.collation_results= default_charset_info; global_system_variables.collation_client= default_charset_info; global_system_variables.collation_connection= default_charset_info; @@ -4632,6 +4666,71 @@ static void set_options(void) global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; + /* Variables that depends on compile options */ +#ifndef DBUG_OFF + default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", + "d:t:i:o,/tmp/mysqld.trace"); +#endif + opt_error_log= IF_WIN(1,0); +#ifdef HAVE_BERKELEY_DB + have_berkeley_db= SHOW_OPTION_YES; +#else + have_berkeley_db= SHOW_OPTION_NO; +#endif +#ifdef HAVE_INNOBASE_DB + have_innodb=SHOW_OPTION_YES; +#else + have_innodb=SHOW_OPTION_NO; +#endif +#ifdef HAVE_ISAM + have_isam=SHOW_OPTION_YES; +#else + have_isam=SHOW_OPTION_NO; +#endif +#ifdef USE_RAID + have_raid=SHOW_OPTION_YES; +#else + have_raid=SHOW_OPTION_NO; +#endif +#ifdef HAVE_OPENSSL + have_openssl=SHOW_OPTION_YES; +#else + have_openssl=SHOW_OPTION_NO; +#endif +#ifdef HAVE_BROKEN_REALPATH + have_symlink=SHOW_OPTION_NO; +#else + have_symlink=SHOW_OPTION_YES; +#endif +#ifdef HAVE_QUERY_CACHE + have_query_cache=SHOW_OPTION_YES; +#else + have_query_cache=SHOW_OPTION_NO; +#endif +#ifdef HAVE_CRYPT + have_crypt=SHOW_OPTION_YES; +#else + have_crypt=SHOW_OPTION_NO; +#endif +#ifdef HAVE_COMPRESS + SHOW_COMP_OPTION have_compress= SHOW_OPTION_YES; +#else + SHOW_COMP_OPTION have_compress= SHOW_OPTION_NO; +#endif +#ifdef HAVE_LIBWRAP + libwrapName= NullS; +#endif +#ifdef HAVE_OPENSSL + des_key_file = 0; + ssl_acceptor_fd= 0; +#endif +#ifdef HAVE_SMEM + shared_memory_base_name= default_shared_memory_base_name; +#endif +#if !defined(my_pthread_setprio) && !defined(HAVE_PTHREAD_SETSCHEDPARAM) + opt_specialflag |= SPECIAL_NO_PRIOR; +#endif + #if defined(__WIN__) || defined(__NETWARE__) /* Allow Win32 and NetWare users to move MySQL anywhere */ { @@ -4646,10 +4745,6 @@ static void set_options(void) tmpenv = DEFAULT_MYSQL_HOME; (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1); #endif - - my_disable_locking=myisam_single_user= 1; - opt_external_locking=0; - my_bind_addr = htonl( INADDR_ANY ); } diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index b96c6383bbb..34cce98d087 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -280,6 +280,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) if (!error && reckey_in_range(1, &ref, item_field->field, conds, range_fl, prefix_len)) error= HA_ERR_KEY_NOT_FOUND; + } if (table->key_read) { table->key_read=0; diff --git a/sql/set_var.cc b/sql/set_var.cc index 0071f50f7a0..3071bc7ff92 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -232,8 +232,7 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout", &slave_net_timeout); #endif -sys_var_bool_ptr sys_readonly("read_only", - &opt_readonly); +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", diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index accbc9cf205..ec6db64ea73 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2672,9 +2672,12 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table) want_access &= ~table->grant.privilege; if (!want_access) - return 0; // Already checked + return 0; // Already checked if (!grant_option) + { + field= table->field[0]; // To give a meaningful error message goto err2; + } rw_rdlock(&LOCK_grant); @@ -3134,7 +3137,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } global.append(" ON `",5); global.append(grant_table->db); - global.append("`.`,3); + global.append("`.`",3); global.append(grant_table->tname); global.append("` TO '",6); global.append(lex_user->user.str,lex_user->user.length); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index b288dc68b42..e0a592d2450 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -434,7 +434,7 @@ 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)); + raid_dirs.push_back(dir=new String(newpath, &my_charset_latin1)); dir->copy(); continue; } @@ -448,7 +448,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, continue; } strxmov(filePath,org_path,"/",file->name,NullS); - if (db && !my_strcasecmp(&my_charset_latin1, + if (db && !my_strcasecmp(&my_charset_latin1, fn_ext(file->name), reg_ext)) { /* Drop the table nicely */ diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 7f555f37d40..2bf1a68e504 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -116,7 +116,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; /* Setting up. A must if a join or IGNORE, USE or similar are utilised */ if (setup_tables(first_table) || - setup_wild(thd, first_table, select_cursor->item_list, 0, select_cursor->with_wild)) + setup_wild(thd, first_table, select_cursor->item_list, 0, + select_cursor->with_wild)) { res= -1; goto exit; @@ -128,16 +129,18 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, (item_list.elements + select_cursor->with_sum_func + select_cursor->order_list.elements + select_cursor->group_list.elements)) || - setup_fields(thd, select_cursor->ref_pointer_array, first_table, item_list, - 0, 0, 1)) + setup_fields(thd, select_cursor->ref_pointer_array, first_table, + item_list, 0, 0, 1)) { res= -1; goto exit; } bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); tmp_table_param.field_count= item_list.elements; - /* temp table is created so that it hounours if UNION without ALL is to be - processed */ + /* + Temp table is created so that it hounours if UNION without ALL is to be + processed + */ if (!(table= create_tmp_table(thd, &tmp_table_param, item_list, (ORDER*) 0, is_union && !unit->union_option, 1, @@ -190,6 +193,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, org_table_list->table=table; table->derived_select_number= select_cursor->select_number; table->tmp_table= TMP_TABLE; + org_table_list->grant.privilege= SELECT_ACL; if (lex->describe) { // to fix a problem in EXPLAIN @@ -206,7 +210,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, /* Try to catch errors if this is accessed */ org_table_list->derived=(SELECT_LEX_UNIT *) 1; #endif -// This line is required to force read of table stats in the optimizer + // Force read of table stats in the optimizer table->file->info(HA_STATUS_VARIABLE); } } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 829300859cf..003c40077ed 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -483,7 +483,8 @@ int write_record(TABLE *table,COPY_INFO *info) key_copy((byte*) key,table,key_nr,0); if ((error=(table->file->index_read_idx(table->record[1],key_nr, (byte*) key, - table->key_info[key_nr].key_length, + table->key_info[key_nr]. + key_length, HA_READ_KEY_EXACT)))) goto err; } @@ -495,7 +496,7 @@ int write_record(TABLE *table,COPY_INFO *info) */ store_record(table,insert_values); restore_record(table,record[1]); - if (fill_record(*info->update_fields,*info->update_values)) + if (fill_record(*info->update_fields, *info->update_values, 0)) goto err; if ((error=table->file->update_row(table->record[1],table->record[0]))) goto err; @@ -506,10 +507,11 @@ int write_record(TABLE *table,COPY_INFO *info) { if (last_uniq_key(table,key_nr)) { - if ((error=table->file->update_row(table->record[1],table->record[0]))) + if ((error=table->file->update_row(table->record[1], + table->record[0]))) goto err; info->deleted++; - break; /* Update logfile and count */ + break; /* Update logfile and count */ } else if ((error=table->file->delete_row(table->record[1]))) goto err; diff --git a/sql/sql_list.h b/sql/sql_list.h index 27cdc117267..ff21663576a 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -368,6 +368,7 @@ template class I_List :private base_ilist { public: I_List() :base_ilist() {} + inline void empty() { base_ilist::empty(); } inline bool is_empty() { return base_ilist::is_empty(); } inline void append(T* a) { base_ilist::append(a); } inline void push_back(T* a) { base_ilist::push_back(a); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 45c5ea4d520..3c2380b619d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -213,7 +213,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user, thd->db=0; thd->db_length=0; USER_RESOURCES ur; - char tmp_passwd[SCRAMBL41_LENGTH]; + char tmp_passwd[SCRAMBLE41_LENGTH]; DBUG_ENTER("check_user"); /* @@ -231,7 +231,7 @@ static int 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)), @@ -1666,7 +1666,7 @@ mysql_execute_command(THD *thd) !(thd->slave_thread || (thd->master_access & SUPER_ACL)) && (uc_update_queries[lex->sql_command] > 0)) { - send_error(&thd->net,ER_CANT_UPDATE_WITH_READLOCK); + send_error(thd, ER_CANT_UPDATE_WITH_READLOCK); DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4456c631032..b03438bdbe0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -626,7 +626,7 @@ JOIN::optimize() Force MySQL to read the table in sorted order to get result in ORDER BY order. */ - join.tmp_table_param.quick_group=0; + tmp_table_param.quick_group=0; } order=0; } @@ -4264,7 +4264,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, table->blob_ptr_size=mi_portable_sizeof_char_ptr; table->map=1; table->tmp_table= TMP_TABLE; - table->derived_select_number= 0; table->db_low_byte_first=1; // True for HEAP and MyISAM table->temp_pool_slot = temp_pool_slot; table->copy_blobs= 1; @@ -7983,6 +7982,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, TABLE *table=tab->table; char buff[512],*buff_ptr=buff; char buff1[512], buff2[512]; + char derived_name[64]; String tmp1(buff1,sizeof(buff1),cs); String tmp2(buff2,sizeof(buff2),cs); tmp1.length(0); @@ -7996,13 +7996,13 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, cs)); if (tab->type == JT_ALL && tab->select && tab->select->quick) tab->type= JT_RANGE; - if (table->tmp_table == TMP_TABLE && table->derived_select_number != 0) + if (table->derived_select_number) { - // Derived table name generation - char buff[512]; - int len= my_snprintf(buff, 512, "", + /* Derived table name generation */ + int len= my_snprintf(derived_name, sizeof(derived_name)-1, + "", table->derived_select_number); - item_list.push_back(new Item_string(buff, len, cs)); + item_list.push_back(new Item_string(derived_name, len, cs)); } else item_list.push_back(new Item_string(table->table_name, @@ -8196,5 +8196,3 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) unit= unit->next_unit()) unit->cleanup(); } - - diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a77987e4806..25bbd4851ba 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1590,11 +1590,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, case SHOW_QUESTION: end= int10_to_str((long) thd->query_id, buff, 10); break; -#ifndef EMBEDDED_LIBRARY +#ifdef HAVE_REPLICATION case SHOW_RPL_STATUS: end= strmov(buff, rpl_status_type[(int)rpl_status]); break; -#ifdef HAVE_REPLICATION case SHOW_SLAVE_RUNNING: { LOCK_ACTIVE_MI; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index ca38651b3b6..bd101944160 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -34,9 +34,6 @@ CHARSET_INFO *national_charset_info= &my_charset_utf8; extern gptr sql_alloc(unsigned size); extern void sql_element_free(void *ptr); -static uint32 -copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, - const char *from, uint32 from_length, CHARSET_INFO *from_cs); #include "sql_string.h" @@ -630,7 +627,7 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) */ -static uint32 +uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, const char *from, uint32 from_length, CHARSET_INFO *from_cs) { diff --git a/sql/sql_string.h b/sql/sql_string.h index 9c494600058..8212bd0a2bd 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -27,6 +27,9 @@ class String; int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); +uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, + const char *from, uint32 from_length, + CHARSET_INFO *from_cs); class String { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 1526908f025..b0e6cd1e644 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -97,7 +97,7 @@ int mysql_update(THD *thd, setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array, order_num) || setup_order(thd, thd->lex.select_lex.ref_pointer_array, - &tables, fields, all_fields, order) || + &tables, all_fields, all_fields, order) || setup_ftfuncs(&thd->lex.select_lex)) DBUG_RETURN(-1); /* purecov: inspected */ @@ -207,7 +207,7 @@ int mysql_update(THD *thd, MYF(MY_FAE | MY_ZEROFILL)); if (!(sortorder=make_unireg_sortorder(order, &length)) || (table->sort.found_records = filesort(thd, table, sortorder, length, - select, 0L, limit, + select, limit, &examined_rows)) == HA_POS_ERROR) { @@ -755,7 +755,7 @@ bool multi_update::send_data(List ¬_used_values) { table->status|= STATUS_UPDATED; store_record(table,record[1]); - if (fill_record(*fields_for_table[offset], *values_for_table[offset]), 0) + if (fill_record(*fields_for_table[offset], *values_for_table[offset], 0)) DBUG_RETURN(1); found++; if (compare_record(table, thd->query_id)) @@ -793,7 +793,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(thd, table, tmp_table_param + offset, + if (create_myisam_from_heap(thd, tmp_table, tmp_table_param + offset, error, 1)) { do_update=0; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 659cddb1090..2adb7377348 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2180,8 +2180,10 @@ simple_expr: simple_ident | simple_expr COLLATE_SYM ident_or_text %prec NEG { - $$= new Item_func_set_collation($1,new Item_string($3.str,$3.length, - YYTHD->charset())); + $$= new Item_func_set_collation($1, + new Item_string($3.str, + $3.length, + YYTHD->charset())); } | literal | param_marker @@ -2228,8 +2230,8 @@ simple_expr: | ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); } | BINARY expr %prec NEG { - $$= new Item_func_set_collation($2,new Item_string("BINARY",6, - &my_charset_latin1)); + $$= new Item_func_set_collation($2,new Item_string(binary_keyword, + 6, &my_charset_latin1)); } | CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); } | CASE_SYM opt_expr WHEN_SYM when_list opt_else END @@ -2580,9 +2582,9 @@ sum_expr: | COUNT_SYM '(' in_sum_expr ')' { $$=new Item_sum_count($3); } | COUNT_SYM '(' DISTINCT - { Select->in_sum_expr++; } + { Select->select_lex()->in_sum_expr++; } expr_list - { Select->in_sum_expr--; } + { Select->select_lex()->in_sum_expr--; } ')' { $$=new Item_sum_count_distinct(* $5); } | GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')' diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc index 57560715fbe..fa678ec7de2 100644 --- a/sql/thr_malloc.cc +++ b/sql/thr_malloc.cc @@ -85,3 +85,33 @@ gptr sql_memdup(const void *ptr,uint len) void sql_element_free(void *ptr __attribute__((unused))) {} /* purecov: deadcode */ + + + +char *sql_strmake_with_convert(const char *str, uint32 arg_length, + CHARSET_INFO *from_cs, + uint32 max_res_length, + CHARSET_INFO *to_cs, uint32 *result_length) +{ + char *pos; + uint32 new_length= to_cs->mbmaxlen*arg_length; + max_res_length--; // Reserve place for end null + + set_if_smaller(new_length, max_res_length); + if (!(pos= sql_alloc(new_length+1))) + return pos; // Error + + if ((from_cs == &my_charset_bin) || (to_cs == &my_charset_bin)) + { + // Safety if to_cs->mbmaxlen > 0 + new_length= min(arg_length, max_res_length); + memcpy(pos, str, new_length); + } + else + new_length= copy_and_convert((char*) pos, new_length, to_cs, str, + arg_length, from_cs); + pos[new_length]= 0; + *result_length= new_length; + return pos; +} + diff --git a/sql/unireg.h b/sql/unireg.h index b3ea6e3fa21..6ddd9856724 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -45,6 +45,7 @@ #define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */ #define MAX_DBKEY_LENGTH (FN_LEN*2+6) /* extra 4 bytes for slave tmp * tables */ +#define MAX_ALIAS_NAME 256 #define MAX_FIELD_NAME 34 /* Max colum name length +2 */ #define MAX_SYS_VAR_LENGTH 32 #define MAX_KEY 32 /* Max used keys */ diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 92214868018..8a9863f7940 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8257,7 +8257,7 @@ my_mb_wc_euc_jp(CHARSET_INFO *cs,my_wc_t *pwc, const uchar *s, const uchar *e) { int c1,c2,c3; - if (s>e) + if (s >= e) return MY_CS_TOOFEW(0); c1=s[0]; From 530accbaae6d243885d5bcc5b04d55b61bd87ce7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 May 2003 14:54:02 -0400 Subject: [PATCH 199/399] fixed 'STARTING BY' in replication mysql-test/r/rpl_loaddata.result: added test for 'STARTING BY' mysql-test/std_data/rpl_loaddata2.dat: added test for 'STARTING BY' mysql-test/t/rpl_loaddata.test: added test for 'STARTING BY' sql/log_event.cc: fixed 'STARTING BY' --- mysql-test/r/rpl_loaddata.result | 2 +- mysql-test/std_data/rpl_loaddata2.dat | 8 ++++---- mysql-test/t/rpl_loaddata.test | 3 +-- sql/log_event.cc | 12 ++++++++++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result index c1518e8e29a..62071a07d0c 100644 --- a/mysql-test/r/rpl_loaddata.result +++ b/mysql-test/r/rpl_loaddata.result @@ -7,7 +7,7 @@ slave start; create table t1(a int not null auto_increment, b int, primary key(a) ); load data infile '../../std_data/rpl_loaddata.dat' into table t1; create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' ignore 1 lines; +load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); insert into t3 select * from t2; select * from t1; diff --git a/mysql-test/std_data/rpl_loaddata2.dat b/mysql-test/std_data/rpl_loaddata2.dat index 7a3d4ea7695..b883d9dcd58 100644 --- a/mysql-test/std_data/rpl_loaddata2.dat +++ b/mysql-test/std_data/rpl_loaddata2.dat @@ -1,8 +1,8 @@ -2003-01-21,6328,%a%,%aaaaa% +>2003-01-21,6328,%a%,%aaaaa% ## -2003-02-22,2461,b,%a a a @@ @% @b ' " a% +>2003-02-22,2461,b,%a a a @@ @% @b ' " a% ## -2003-03-22,2161,%c%,%asdf% +>2003-03-22,2161,%c%,%asdf% ## -2003-04-22,2416,%a%,%bbbbb% +>2003-04-22,2416,%a%,%bbbbb% ## diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test index 2acb67dfce2..1f34aa9d3f9 100644 --- a/mysql-test/t/rpl_loaddata.test +++ b/mysql-test/t/rpl_loaddata.test @@ -10,8 +10,7 @@ create table t1(a int not null auto_increment, b int, primary key(a) ); load data infile '../../std_data/rpl_loaddata.dat' into table t1; create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); -#load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionaly enclosed by '%' escaped by '@' lines terminated by '\n%%\n' ignore 1 lines; - load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' ignore 1 lines; +load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); insert into t3 select * from t2; diff --git a/sql/log_event.cc b/sql/log_event.cc index 3b499b8d502..dfa44e19ffc 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -309,15 +309,19 @@ void Load_log_event::pack_info(String* packet) pretty_print_str(&tmp, sql_ex.escaped, sql_ex.escaped_len); } + bool line_lexem_added= false; if (sql_ex.line_term_len) { tmp.append(" LINES TERMINATED BY "); pretty_print_str(&tmp, sql_ex.line_term, sql_ex.line_term_len); + line_lexem_added= true; } if (sql_ex.line_start_len) { - tmp.append(" LINES STARTING BY "); + if (!line_lexem_added) + tmp.append(" LINES"); + tmp.append(" STARTING BY "); pretty_print_str(&tmp, sql_ex.line_start, sql_ex.line_start_len); } @@ -1299,15 +1303,19 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db) pretty_print_str(file, sql_ex.escaped, sql_ex.escaped_len); } + bool line_lexem_added= false; if (sql_ex.line_term) { fprintf(file," LINES TERMINATED BY "); pretty_print_str(file, sql_ex.line_term, sql_ex.line_term_len); + line_lexem_added= true; } if (sql_ex.line_start) { - fprintf(file," LINES STARTING BY "); + if (!line_lexem_added) + fprintf(file," LINES"); + fprintf(file," STARTING BY "); pretty_print_str(file, sql_ex.line_start, sql_ex.line_start_len); } From b76adc62fbccc85f08563bffc5e2d91b21adf1d0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 May 2003 21:58:12 +0300 Subject: [PATCH 200/399] repair_part2 is made repeatable --- mysql-test/mysql-test-run.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 7ce6ffe14af..65f40c5dc73 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -19,6 +19,8 @@ TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work # Program Definitions #-- +LC_COLLATE=C +export LC_COLLATE PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$PATH MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master" From bddd75d28eba0c5dade8facd7484d0ad67f20176 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 May 2003 15:16:56 -0400 Subject: [PATCH 201/399] fixed "LINES STARTING" in load data replication BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/log_event.cc | 6 +++++- 2 files changed, 6 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/log_event.cc b/sql/log_event.cc index 7c4c893a823..9cf67e78029 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -697,15 +697,19 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db) pretty_print_char(file, sql_ex.escaped); } + bool line_lexem_added= false; if(!(sql_ex.empty_flags & LINE_TERM_EMPTY)) { fprintf(file," LINES TERMINATED BY "); pretty_print_char(file, sql_ex.line_term); + line_lexem_added= true; } if(!(sql_ex.empty_flags & LINE_START_EMPTY)) { - fprintf(file," LINES STARTING BY "); + if (!line_lexem_added) + fprintf(file," LINES"); + fprintf(file," STARTING BY "); pretty_print_char(file, sql_ex.line_start); } From eb4755c90e6f112277083fedbbe53faf922e65b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 00:05:33 +0300 Subject: [PATCH 202/399] row0ins.c: Disable UNIQU KEY error reporting in SHOW INNODB STATUS until we know if it slows down REPLACE significantly innobase/row/row0ins.c: Disable UNIQU KEY error reporting in SHOW INNODB STATUS until we know if it slows down REPLACE significantly --- innobase/row/row0ins.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 3af9e1b752b..e96c08a715b 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -1275,6 +1275,10 @@ row_ins_unique_report_err( dtuple_t* entry, /* in: index entry to insert in the index */ dict_index_t* index) /* in: index */ { +#ifdef notdefined + /* Disable reporting to test if the slowdown of REPLACE in 4.0.13 was + caused by this! */ + char* buf = dict_unique_err_buf; /* The foreign err mutex protects also dict_unique_err_buf */ @@ -1303,6 +1307,7 @@ row_ins_unique_report_err( ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); mutex_exit(&dict_foreign_err_mutex); +#endif } /******************************************************************* From a2867c7ae93f760106ffc45086efa372cbf884dd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 11:58:39 +0300 Subject: [PATCH 203/399] Updated results & after merge fix BitKeeper/etc/ignore: added include/readline/*.h mysql-test/r/create.result: Update results mysql-test/r/loaddata.result: Updated results sql/mysqld.cc: Fix after merge --- .bzrignore | 1 + mysql-test/r/create.result | 2 +- mysql-test/r/loaddata.result | 7 +++++++ sql/mysqld.cc | 9 +++++---- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.bzrignore b/.bzrignore index 6746bb863b7..82adbf625f3 100644 --- a/.bzrignore +++ b/.bzrignore @@ -616,3 +616,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +include/readline/*.h diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index b39bb96e36a..7a4ba1703a4 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -193,7 +193,7 @@ SELECT @@table_type; GEMINI CREATE TABLE t1 (a int not null); Warnings: -Warning 1259 Using storage engine MYISAM for table 't1' +Warning 1264 Using storage engine MYISAM for table 't1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index d121a4e6c40..7b4802136f3 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -1,6 +1,13 @@ 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 ','; +Warnings: +Warning 1263 Data truncated for column 'a' at row 1 +Warning 1263 Data truncated for column 'c' at row 1 +Warning 1263 Data truncated for column 'd' at row 1 +Warning 1263 Data truncated for column 'a' at row 2 +Warning 1263 Data truncated for column 'b' at row 2 +Warning 1263 Data truncated for column 'd' at row 2 load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES; SELECT * from t1; a b c d diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8037da06c33..6603e4c306a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -300,7 +300,7 @@ char* log_error_file_ptr= log_error_file; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file; -char *language_ptr= language; +char *language_ptr, *default_collation_name; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION; char *mysql_unix_port, *opt_mysql_tmpdir; @@ -2035,8 +2035,8 @@ static int init_common_variables(const char *conf_file_name, int argc, return 1; if (default_collation_name) { - CHARSET_INFO *default_collation= get_charset_by_name(default_collation_name, - MYF(0)); + CHARSET_INFO *default_collation; + default_collation= get_charset_by_name(default_collation_name, MYF(0)); if (!default_collation || !my_charset_same(default_charset_info, default_collation)) { @@ -4631,6 +4631,7 @@ static void mysql_init_variables(void) pidfile_name_ptr= pidfile_name; log_error_file_ptr= log_error_file; language_ptr= language; + default_collation_name= 0; mysql_data_home= mysql_real_data_home; thd_startup_options= (OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL | OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE); @@ -4787,7 +4788,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), strmake(mysql_home,argument,sizeof(mysql_home)-1); break; case 'C': - default_collation_name= NULL; + default_collation_name= 0; break; case 'l': opt_log=1; From 3565727359aaea5f2fab3740d71d36fb9015f77a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 14:37:01 +0500 Subject: [PATCH 204/399] mysqlimport.c, mysqldump.c, mysqlcheck.c: Bug fix: latin1 is not compiled charset and is not specified.. mysql.cc: Bug fix: latin1 is not compiled charset and is not specified... client/mysql.cc: Bug fix: latin1 is not compiled charset and is not specified... client/mysqlcheck.c: Bug fix: latin1 is not compiled charset and is not specified.. client/mysqldump.c: Bug fix: latin1 is not compiled charset and is not specified.. client/mysqlimport.c: Bug fix: latin1 is not compiled charset and is not specified.. --- client/mysql.cc | 3 ++- client/mysqlcheck.c | 3 ++- client/mysqldump.c | 3 ++- client/mysqlimport.c | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 155d8b03231..f421756f0b4 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -809,7 +809,8 @@ static int get_options(int argc, char **argv) opt_reconnect= 0; connect_flag= 0; /* Not in interactive mode */ } - if (!(charset_info= get_charset_by_name(default_charset, MYF(MY_WME)))) + if (!(charset_info= get_charset_by_csname(default_charset, + MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if (argc > 1) { diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index cd8cd0ef82e..8f599c9f497 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -308,7 +308,8 @@ static int get_options(int *argc, char ***argv) else what_to_do = DO_CHECK; } - if (!(charset_info= get_charset_by_name(default_charset, MYF(MY_WME)))) + if (!(charset_info= get_charset_by_csname(default_charset, + MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if (*argc > 0 && opt_alldbs) { diff --git a/client/mysqldump.c b/client/mysqldump.c index 17780458a2a..6a577af8792 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -492,7 +492,8 @@ static int get_options(int *argc, char ***argv) my_progname); return(1); } - if (!(charset_info= get_charset_by_name(default_charset, MYF(MY_WME)))) + if (!(charset_info= get_charset_by_csname(default_charset, + MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs)) { diff --git a/client/mysqlimport.c b/client/mysqlimport.c index efb117280c4..f247301c6dc 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -239,7 +239,8 @@ static int get_options(int *argc, char ***argv) fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n"); return(1); } - if (!(charset_info= get_charset_by_name(default_charset, MYF(MY_WME)))) + if (!(charset_info= get_charset_by_csname(default_charset, + MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); if (*argc < 2) { From 98e66d2059e9f758785f487e4cbb4eaa405ad493 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 16:57:06 +0500 Subject: [PATCH 205/399] Index.xml: Typos fixes sql/share/charsets/Index.xml: Typos fixes --- sql/share/charsets/Index.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 9b95326fe9e..84ef917fe00 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -19,7 +19,7 @@ To make maintaining easier please: csbig5 primary - compiled" + compiled @@ -245,7 +245,7 @@ To make maintaining easier please: euc-kr primary - compiled" + compiled @@ -285,7 +285,7 @@ To make maintaining easier please: iso-ir-58 primary - compiled" + compiled From 9b92f5858adcc25f696d8d06cab90288c16641ac Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 17:20:19 +0500 Subject: [PATCH 206/399] Variables were rename, binary collation names were added Fixed that SHOW CHARACTER SET displayed non-dynamic charsets even if they were not really compiled --- include/m_ctype.h | 36 ++++++++++++++-------- mysys/charset.c | 63 ++++++++++----------------------------- sql/sql_show.cc | 4 +-- sql/sql_string.cc | 6 ++-- strings/ctype-big5.c | 2 +- strings/ctype-czech.c | 2 +- strings/ctype-euc_kr.c | 2 +- strings/ctype-gb2312.c | 2 +- strings/ctype-gbk.c | 2 +- strings/ctype-latin1.c | 2 +- strings/ctype-sjis.c | 2 +- strings/ctype-tis620.c | 2 +- strings/ctype-ucs2.c | 4 +-- strings/ctype-ujis.c | 2 +- strings/ctype-utf8.c | 4 +-- strings/ctype-win1250ch.c | 2 +- strings/ctype.c | 2 ++ 17 files changed, 59 insertions(+), 80 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index e28d5687983..6cf0ecfbb8a 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -61,6 +61,7 @@ typedef struct unicase_info_st #define MY_CS_BINSORT 16 /* if binary sort order */ #define MY_CS_PRIMARY 32 /* if primary collation */ #define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */ +#define MY_CS_UNICODE 128 /* is a charset is full unicode */ #define MY_CHARSET_UNDEFINED 0 #define MY_CHARSET_CURRENT (default_charset_info->number) @@ -185,20 +186,29 @@ typedef struct charset_info_st extern CHARSET_INFO my_charset_bin; +extern CHARSET_INFO my_charset_big5_chinese_ci; +extern CHARSET_INFO my_charset_big5_bin; +extern CHARSET_INFO my_charset_euckr_korean_ci; +extern CHARSET_INFO my_charset_euckr_bin; +extern CHARSET_INFO my_charset_gb2312_chinese_ci; +extern CHARSET_INFO my_charset_gb2312_bin; +extern CHARSET_INFO my_charset_gbk_chinese_ci; +extern CHARSET_INFO my_charset_gbk_bin; extern CHARSET_INFO my_charset_latin1; -extern CHARSET_INFO my_charset_big5; -extern CHARSET_INFO my_charset_czech; -extern CHARSET_INFO my_charset_euc_kr; -extern CHARSET_INFO my_charset_gb2312; -extern CHARSET_INFO my_charset_gbk; -extern CHARSET_INFO my_charset_latin1_de; -extern CHARSET_INFO my_charset_sjis; -extern CHARSET_INFO my_charset_tis620; -extern CHARSET_INFO my_charset_ucs2; -extern CHARSET_INFO my_charset_ucse; -extern CHARSET_INFO my_charset_ujis; -extern CHARSET_INFO my_charset_utf8; -extern CHARSET_INFO my_charset_win1250ch; +extern CHARSET_INFO my_charset_latin1_german2_ci; +extern CHARSET_INFO my_charset_latin1_bin; +extern CHARSET_INFO my_charset_latin2_czech_ci; +extern CHARSET_INFO my_charset_sjis_japanese_ci; +extern CHARSET_INFO my_charset_sjis_bin; +extern CHARSET_INFO my_charset_tis620_thai_ci; +extern CHARSET_INFO my_charset_tis620_bin; +extern CHARSET_INFO my_charset_ucs2_general_ci; +extern CHARSET_INFO my_charset_ucs2_bin; +extern CHARSET_INFO my_charset_ujis_japanese_ci; +extern CHARSET_INFO my_charset_ujis_bin; +extern CHARSET_INFO my_charset_utf8_general_ci; +extern CHARSET_INFO my_charset_utf8_bin; +extern CHARSET_INFO my_charset_cp1250_czech_ci; extern my_bool my_parse_charset_xml(const char *bug, uint len, diff --git a/mysys/charset.c b/mysys/charset.c index d685104abac..9b8903bc6b7 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -313,6 +313,8 @@ static int add_collation(CHARSET_INFO *cs) { if (!all_charsets[cs->number]) { + if (cs->state & MY_CS_COMPILED) + return MY_XML_OK; if (!(all_charsets[cs->number]= (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0)))) return MY_XML_ERROR; @@ -422,57 +424,53 @@ CHARSET_INFO *default_charset_info = &my_charset_latin1; static my_bool init_compiled_charsets(myf flags __attribute__((unused))) { CHARSET_INFO *cs; - - MY_ADD_CHARSET(&my_charset_latin1); + MY_ADD_CHARSET(&my_charset_latin1); MY_ADD_CHARSET(&my_charset_bin); + MY_ADD_CHARSET(&my_charset_latin1_german2_ci); #ifdef HAVE_CHARSET_big5 - MY_ADD_CHARSET(&my_charset_big5); + MY_ADD_CHARSET(&my_charset_big5_chinese_ci); #endif #ifdef HAVE_CHARSET_czech - MY_ADD_CHARSET(&my_charset_czech); + MY_ADD_CHARSET(&my_charset_latin2_czech_ci); #endif #ifdef HAVE_CHARSET_euc_kr - MY_ADD_CHARSET(&my_charset_euc_kr); + MY_ADD_CHARSET(&my_charset_euckr_korean_ci); #endif #ifdef HAVE_CHARSET_gb2312 - MY_ADD_CHARSET(&my_charset_gb2312); + MY_ADD_CHARSET(&my_charset_gb2312_chinese_ci); #endif #ifdef HAVE_CHARSET_gbk - MY_ADD_CHARSET(&my_charset_gbk); -#endif - -#ifdef HAVE_CHARSET_latin1_de - MY_ADD_CHARSET(&my_charset_latin1_de); + MY_ADD_CHARSET(&my_charset_gbk_chinese_ci); #endif #ifdef HAVE_CHARSET_sjis - MY_ADD_CHARSET(&my_charset_sjis); + MY_ADD_CHARSET(&my_charset_sjis_japanese_ci); #endif #ifdef HAVE_CHARSET_tis620 - MY_ADD_CHARSET(&my_charset_tis620); + MY_ADD_CHARSET(&my_charset_tis620_thai_ci); #endif #ifdef HAVE_CHARSET_ucs2 - MY_ADD_CHARSET(&my_charset_ucs2); + MY_ADD_CHARSET(&my_charset_ucs2_general_ci); #endif #ifdef HAVE_CHARSET_ujis - MY_ADD_CHARSET(&my_charset_ujis); + MY_ADD_CHARSET(&my_charset_ujis_japanese_ci); #endif #ifdef HAVE_CHARSET_utf8 - MY_ADD_CHARSET(&my_charset_utf8); + MY_ADD_CHARSET(&my_charset_utf8_general_ci); #endif #ifdef HAVE_CHARSET_win1250ch - MY_ADD_CHARSET(&my_charset_win1250ch); + MY_ADD_CHARSET(&my_charset_cp1250_czech_ci); #endif /* Copy compiled charsets */ @@ -533,12 +531,6 @@ void free_charsets(void) } -static void get_charset_conf_name(const char *cs_name, char *buf) -{ - strxmov(get_charsets_dir(buf), cs_name, ".conf", NullS); -} - - uint get_charset_number(const char *charset_name) { CHARSET_INFO **cs; @@ -661,28 +653,3 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, return cs; } - - -/* Only append name if it doesn't exist from before */ - -static my_bool charset_in_string(const char *name, DYNAMIC_STRING *s) -{ - uint length= (uint) strlen(name); - const char *pos; - for (pos=s->str ; (pos=strstr(pos,name)) ; pos++) - { - if (! pos[length] || pos[length] == ' ') - return TRUE; /* Already existed */ - } - return FALSE; -} - - -static void charset_append(DYNAMIC_STRING *s, const char *name) -{ - if (!charset_in_string(name, s)) - { - dynstr_append(s, name); - dynstr_append(s, " "); - } -} diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 25bbd4851ba..660b8e7e572 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1420,8 +1420,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) static bool write_collation(Protocol *protocol, CHARSET_INFO *cs) { protocol->prepare_for_resend(); - protocol->store(cs->csname, system_charset_info); protocol->store(cs->name, system_charset_info); + protocol->store(cs->csname, system_charset_info); protocol->store_short((longlong) cs->number); protocol->store((cs->state & MY_CS_PRIMARY) ? "Y" : "",system_charset_info); protocol->store((cs->state & MY_CS_COMPILED)? "Y" : "",system_charset_info); @@ -1440,8 +1440,8 @@ int mysqld_show_collations(THD *thd, const char *wild) DBUG_ENTER("mysqld_show_charsets"); - field_list.push_back(new Item_empty_string("Charset",30)); field_list.push_back(new Item_empty_string("Collation",30)); + field_list.push_back(new Item_empty_string("Charset",30)); field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT)); field_list.push_back(new Item_empty_string("D",30)); field_list.push_back(new Item_empty_string("C",30)); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index bd101944160..126fb84d6d9 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -28,9 +28,9 @@ #include #endif -CHARSET_INFO *system_charset_info= &my_charset_utf8; -CHARSET_INFO *files_charset_info= &my_charset_utf8; -CHARSET_INFO *national_charset_info= &my_charset_utf8; +CHARSET_INFO *system_charset_info= &my_charset_utf8_general_ci; +CHARSET_INFO *files_charset_info= &my_charset_utf8_general_ci; +CHARSET_INFO *national_charset_info= &my_charset_utf8_general_ci; extern gptr sql_alloc(unsigned size); extern void sql_element_free(void *ptr); diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 57ee2d7c6ae..ec723e8690a 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6226,7 +6226,7 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), return 2; } -CHARSET_INFO my_charset_big5 = +CHARSET_INFO my_charset_big5_chinese_ci = { 1,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c index 9da2103fda3..788cd96ad13 100644 --- a/strings/ctype-czech.c +++ b/strings/ctype-czech.c @@ -605,7 +605,7 @@ int my_strnncollsp_czech(CHARSET_INFO * cs, } -CHARSET_INFO my_charset_czech = +CHARSET_INFO my_charset_latin2_czech_ci = { 2,0,0, /* number */ MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */ diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 21f01b6509c..3bf689910e6 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8634,7 +8634,7 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)), return 2; } -CHARSET_INFO my_charset_euc_kr = +CHARSET_INFO my_charset_euckr_korean_ci = { 19,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */ diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index f1ec5a9f363..20e1ce888e8 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5684,7 +5684,7 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)), return 2; } -CHARSET_INFO my_charset_gb2312 = +CHARSET_INFO my_charset_gb2312_chinese_ci = { 24,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */ diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index b1ea209d6ad..ec0cc01881b 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9881,7 +9881,7 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)), } -CHARSET_INFO my_charset_gbk = +CHARSET_INFO my_charset_gbk_chinese_ci = { 28,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 5781013a5e9..4340d0973aa 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -428,7 +428,7 @@ static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)), return dest - dest_orig; } -CHARSET_INFO my_charset_latin1_de = +CHARSET_INFO my_charset_latin1_german2_ci = { 31,0,0, /* number */ MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */ diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index fd911f1867e..058558fa419 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4468,7 +4468,7 @@ my_mb_wc_sjis(CHARSET_INFO *cs __attribute__((unused)), return 2; } -CHARSET_INFO my_charset_sjis = +CHARSET_INFO my_charset_sjis_japanese_ci = { 13,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index e108ffac6af..9fcecdfdffd 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -688,7 +688,7 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length) } -CHARSET_INFO my_charset_tis620 = +CHARSET_INFO my_charset_tis620_thai_ci = { 18,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index d2e75d1de9e..dae0632f754 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -997,10 +997,10 @@ uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)), return pos*2; } -CHARSET_INFO my_charset_ucs2 = +CHARSET_INFO my_charset_ucs2_general_ci = { 35,0,0, /* number */ - MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ + MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE, /* state */ "ucs2", /* cs name */ "ucs2_general_ci", /* name */ "", /* comment */ diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 8a9863f7940..76c69637906 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8425,7 +8425,7 @@ my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e) return MY_CS_ILUNI; } -CHARSET_INFO my_charset_ujis = +CHARSET_INFO my_charset_ujis_japanese_ci = { 12,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */ diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index e9fc2f6d17d..9f08ca2e169 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1950,10 +1950,10 @@ static int my_mbcharlen_utf8(CHARSET_INFO *cs __attribute__((unused)) , uint c) return 0; /* Illegal mb head */; } -CHARSET_INFO my_charset_utf8 = +CHARSET_INFO my_charset_utf8_general_ci = { 33,0,0, /* number */ - MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ + MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE, /* state */ "utf8", /* cs name */ "utf8_general_ci", /* name */ "", /* comment */ diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 2769925b54f..87ba58d0553 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -640,7 +640,7 @@ static my_bool my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)), } -CHARSET_INFO my_charset_win1250ch = +CHARSET_INFO my_charset_cp1250_czech_ci = { 34,0,0, /* number */ MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */ diff --git a/strings/ctype.c b/strings/ctype.c index 68d9a30048f..ce7bb9ca4a4 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -220,6 +220,8 @@ static int cs_value(MY_XML_PARSER *st,const char *attr, uint len) i->cs.state|= MY_CS_PRIMARY; else if (!strncmp("binary",attr,len)) i->cs.state|= MY_CS_BINSORT; + else if (!strncmp("compiled",attr,len)) + i->cs.state|= MY_CS_COMPILED; break; case _CS_UPPERMAP: fill_uchar(i->to_upper,MY_CS_TO_UPPER_TABLE_SIZE,attr,len); From bf71feca00efb199f7e055f5ec30b0fca5b2a642 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 18:22:21 +0500 Subject: [PATCH 207/399] mysqld.cc: default_collation is now displayed correctly in mysqld --help mysqld --help now displays default_collation corretly, according to --default-character-set sql/mysqld.cc: default_collation is now displayed correctly in mysqld --help --- sql/mysqld.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6603e4c306a..6831b4802d9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4533,6 +4533,12 @@ static void use_help(void) static void usage(void) { + if (!(default_charset_info= get_charset_by_csname(sys_charset.value, + MY_CS_PRIMARY, + MYF(MY_WME)))) + exit(1); + if (!default_collation_name) + default_collation_name= (char*) default_charset_info->name; print_version(); puts("\ Copyright (C) 2000 MySQL AB, by Monty and others\n\ From 1ad3551835ba4096034277d841be6575302f8957 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 18:41:47 +0500 Subject: [PATCH 208/399] USER, DATABASE and VERSION functions returns now IMPLICIT coercibility --- sql/item_create.cc | 2 +- sql/item_strfunc.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item_create.cc b/sql/item_create.cc index b027b156641..39e1c2dec22 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -437,7 +437,7 @@ Item *create_func_version(void) { return new Item_string(NullS,server_version, (uint) strlen(server_version), - system_charset_info); + system_charset_info, Item::COER_IMPLICIT); } Item *create_func_weekday(Item* a) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index abe2a5355be..c798faddfcb 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -333,7 +333,7 @@ public: class Item_func_database :public Item_str_func { public: - Item_func_database() {} + Item_func_database() { coercibility= COER_IMPLICIT; } String *val_str(String *); void fix_length_and_dec() { @@ -346,7 +346,7 @@ public: class Item_func_user :public Item_str_func { public: - Item_func_user() {} + Item_func_user() { coercibility= COER_IMPLICIT; } String *val_str(String *); void fix_length_and_dec() { From 46c730e62cd02a6e68aded98e03d633c14e61f3b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 May 2003 22:29:44 +0200 Subject: [PATCH 209/399] Cleaning DROP TABLE which is important if the tests are run in a certain order. This is because rpl_relayrotate.test uses InnoDB. Example of a failing sequence: rpl_relayrotate.test repl_user_variables.test rpl_relayrotate.test Explaination in the files. Btw all other tests which use InnoDB (innodb*.test) already have this final DROP TABLE. Removed a wrong comment of mine. mysql-test/r/rpl_relayrotate.result: result update mysql-test/t/rpl_relayrotate.test: cleaning DROP TABLE which is important if the tests are run in a certain order. --- mysql-test/r/rpl_relayrotate.result | 1 + mysql-test/t/rpl_relayrotate.test | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result index 45f425a3532..0ad61a7687e 100644 --- a/mysql-test/r/rpl_relayrotate.result +++ b/mysql-test/r/rpl_relayrotate.result @@ -16,3 +16,4 @@ master_pos_wait('master-bin.001',3000,120)=-1 select * from t1 where a=8000; a 8000 +drop table t1; diff --git a/mysql-test/t/rpl_relayrotate.test b/mysql-test/t/rpl_relayrotate.test index 4c330b8c9a2..09cf7cbb741 100644 --- a/mysql-test/t/rpl_relayrotate.test +++ b/mysql-test/t/rpl_relayrotate.test @@ -56,6 +56,14 @@ start slave; # Detect this with timeout. select master_pos_wait('master-bin.001',3000,120)=-1; select * from t1 where a=8000; -# Note that the simple fact to have less than around 30 slave's binlogs -# (the slave is started with --log-slave-updates) is already -# a proof that the transaction was not properly resumed. + +# The following DROP is a very important cleaning task: +# imagine the next test is run with --skip-innodb: it will do +# DROP TABLE IF EXISTS t1; but this will delete the frm and leave +# some data in the InnoDB datafile (because at that time mysqld +# does not know about InnoDB : --skip-innodb). So if later in the +# test suite a test wants to create an InnoDB table called t1, it +# will fail with +# InnoDB: Error: table t1 already exists in InnoDB internal +# InnoDB: data dictionary. Have you deleted the .frm file etc +drop table t1; From 5d4fbc021a0bba300f85c0136a467e6961af5555 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 10:45:46 +0500 Subject: [PATCH 210/399] Automatic conversion into supersets (utf8, ucs2) for comparison in some cases USER(), DATABASE() and VERSION() return in utf8 now --- sql/item_cmpfunc.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++ sql/item_strfunc.cc | 8 ++++--- sql/item_strfunc.h | 8 +++---- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index dfc46793ee7..7392ef6c276 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -133,6 +133,60 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables, { if (Item_int_func::fix_fields(thd, tables, ref)) return 1; + + /* + We allow to convert to Unicode character sets in some cases. + The conditions when conversion is possible are: + - arguments A and B have different charsets + - A wins according to coercibility rules + - character set of A is superset for character set of B + + If all of the above is true, then it's possible to convert + B into the character set of A, and then compare according + to the collation of A. + */ + + if (args[0] && args[1]) + { + uint strong= 0; + uint weak= 0; + + if ((args[0]->coercibility < args[1]->coercibility) && + !my_charset_same(args[0]->charset(), args[1]->charset()) && + (args[0]->charset()->state & MY_CS_UNICODE)) + { + weak= 1; + } + else if ((args[1]->coercibility < args[0]->coercibility) && + !my_charset_same(args[0]->charset(), args[1]->charset()) && + (args[1]->charset()->state & MY_CS_UNICODE)) + { + strong= 1; + } + + if (strong || weak) + { + Item* conv= 0; + if (args[weak]->type() == STRING_ITEM) + { + String tmp, cstr; + String *ostr= args[weak]->val_str(&tmp); + cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), + args[strong]->charset()); + conv= new Item_string(cstr.ptr(),cstr.length(),cstr.charset(), + args[weak]->coercibility); + ((Item_string*)conv)->str_value.copy(); + } + else + { + conv= new Item_func_conv_charset(args[weak],args[strong]->charset()); + conv->coercibility= args[weak]->coercibility; + } + args[weak]= conv ? conv : args[weak]; + set_cmp_charset(args[0]->charset(), args[0]->coercibility, + args[1]->charset(), args[1]->coercibility); + } + } if (!cmp_charset) { /* set_cmp_charset() failed */ @@ -156,6 +210,8 @@ void Item_bool_func2::fix_length_and_dec() */ if (!args[0] || !args[1]) return; + + // Make a special case of compare with fields to get nicer DATE comparisons if (args[0]->type() == FIELD_ITEM) { diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index dd48314596b..078e3f213a0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1459,10 +1459,12 @@ String *Item_func_database::val_str(String *str) { THD *thd= current_thd; if (!thd->db) + { str->length(0); + str->set_charset(system_charset_info); + } else - str->copy((const char*) thd->db,(uint) strlen(thd->db), - system_charset_info, default_charset()); + str->copy((const char*) thd->db,(uint) strlen(thd->db),system_charset_info); return str; } @@ -1471,7 +1473,7 @@ String *Item_func_database::val_str(String *str) String *Item_func_user::val_str(String *str) { THD *thd=current_thd; - CHARSET_INFO *cs= default_charset(); + CHARSET_INFO *cs= system_charset_info; const char *host= thd->host_or_ip; uint res_length; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index c798faddfcb..8ae5c995375 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -337,8 +337,8 @@ public: String *val_str(String *); void fix_length_and_dec() { - max_length= MAX_FIELD_NAME * default_charset()->mbmaxlen; - set_charset(default_charset()); + max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen; + set_charset(system_charset_info); } const char *func_name() const { return "database"; } }; @@ -350,8 +350,8 @@ public: String *val_str(String *); void fix_length_and_dec() { - max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*default_charset()->mbmaxlen; - set_charset(default_charset()); + max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*system_charset_info->mbmaxlen; + set_charset(system_charset_info); } const char *func_name() const { return "user"; } }; From 79decad27a7c8e8dd63ab90fe9a52ee9adc2ec9e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 10:55:49 +0500 Subject: [PATCH 211/399] More tests for system functions --- mysql-test/r/func_system.result | 48 ++++++++++++++++++++++++++++++--- mysql-test/t/func_system.test | 20 +++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result index 83e78a30396..15ff34a6d80 100644 --- a/mysql-test/r/func_system.result +++ b/mysql-test/r/func_system.result @@ -1,9 +1,51 @@ -select database(),user() like "%@%"; -database() user() like "%@%" -test 1 +select database(); +database() +test +select charset(database()); +charset(database()) +utf8 +select database() = "test"; +database() = "test" +1 +select database() = _utf8"test"; +database() = _utf8"test" +1 +select database() = _latin1"test"; +database() = _latin1"test" +1 +select user() like "%@%"; +user() like "%@%" +1 +select user() like _utf8"%@%"; +user() like _utf8"%@%" +1 +select user() like _latin1"%@%"; +user() like _latin1"%@%" +1 +select charset(user()); +charset(user()) +utf8 +select version()>="3.23.29"; +version()>="3.23.29" +1 select version()>=_utf8"3.23.29"; version()>=_utf8"3.23.29" 1 +select version()>=_latin1"3.23.29"; +version()>=_latin1"3.23.29" +1 +select charset(version()); +charset(version()) +utf8 +create table t1 select database(), user(), version(); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `database()` char(102) character set utf8 NOT NULL default '', + `user()` char(231) character set utf8 NOT NULL default '', + `version()` char(21) character set utf8 NOT NULL default '' +) TYPE=MyISAM CHARSET=latin1 +drop table t1; select TRUE,FALSE,NULL; TRUE FALSE NULL 1 0 NULL diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test index db366e3ab49..41b776719dc 100644 --- a/mysql-test/t/func_system.test +++ b/mysql-test/t/func_system.test @@ -2,6 +2,24 @@ # system functions # -select database(),user() like "%@%"; +select database(); +select charset(database()); +select database() = "test"; +select database() = _utf8"test"; +select database() = _latin1"test"; + +select user() like "%@%"; +select user() like _utf8"%@%"; +select user() like _latin1"%@%"; +select charset(user()); + +select version()>="3.23.29"; select version()>=_utf8"3.23.29"; +select version()>=_latin1"3.23.29"; +select charset(version()); + +create table t1 select database(), user(), version(); +show create table t1; +drop table t1; + select TRUE,FALSE,NULL; From a7fd4a2c84c074c1ba3b7df86222a7e8be8e9f80 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 03:06:00 -0300 Subject: [PATCH 212/399] Translation English -> Protuguese sql/share/portuguese/errmsg.txt: Translation English -> Portuguese BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/share/portuguese/errmsg.txt | 86 ++++++++++++++++----------------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 0f0947a8305..6761a96b06b 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -5,6 +5,7 @@ Administrator@fred. Miguel@light.local Sinisa@sinisa.nasamreza.org WAX@sergbook.mysql.com +administrador@light.hegel.local ahlentz@co3064164-a.rochd1.qld.optusnet.com.au akishkin@work.mysql.com arjen@co3064164-a.bitbike.com diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 99eb13aa856..ef051d957cb 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -219,46 +219,46 @@ "Não pode acrescentar uma restrição de chave estrangeira", "Não pode acrescentar uma linha filha: uma restrição de chave estrangeira falhou", "Não pode apagar uma linha pai: uma restrição de chave estrangeira falhou", -"Error connecting to master: %-.128s", -"Error running query on master: %-.128s", -"Error when executing command %s: %-.128s", -"Wrong usage of %s and %s", -"The used SELECT statements have a different number of columns", -"Can't execute the query because you have a conflicting read lock", -"Mixing of transactional and non-transactional tables is disabled", -"Option '%s' used twice in statement", -"User '%-.64s' has exceeded the '%s' resource (current value: %ld)", -"Access denied. You need the %-.128s privilege for this operation", -"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL", -"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL", -"Variable '%-.64s' doesn't have a default value", -"Variable '%-.64s' can't be set to the value of '%-.64s'", -"Wrong argument type to variable '%-.64s'", -"Variable '%-.64s' can only be set, not read", -"Wrong usage/placement of '%s'", -"This version of MySQL doesn't yet support '%s'", -"Got fatal error %d: '%-.128s' from master when reading data from binary log", -"Wrong foreign key definition for '%-.64s': %s", -"Key reference and table reference doesn't match", -"Cardinality error (more/less than %d columns)", -"Subselect returns more than 1 record", -"Unknown prepared statement handler (%ld) given to %s", -"Help database is corrupt or does not exist", -"Cyclic reference on subqueries", -"Converting column '%s' from %s to %s", -"Reference '%-.64s' not supported (%s)", -"Every derived table must have it's own alias", -"Select %u was reduced during optimisation", -"Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", -"All parts of a SPATIAL KEY must be NOT NULL", -"COLLATION '%s' is not valid for CHARACTER SET '%s'", -"The slave was already running", -"The slave was already stopped", -"Too big size of uncompressed data. The maximum size is %d. (probably, length of uncompressed data was corrupted)", -"Z_BUF_ERROR: Not enough memory available for zlib", -"Z_MEM_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", -"Z_DATA_ERROR: Input data was corrupted for zlib", -"%d line(s) was(were) cut by group_concat()", -"Using storage engine %s for table '%s'", -"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Erro connectando para o master: %-.128s", +"Erro rodando consulta no master: %-.128s", +"Erro quando executando comando %s: %-.128s", +"Uso errado de %s e %s", +"Os comandos SELECT usados têm diferentes números de colunas", +"Não pode executar a consulta porque você tem um conflitante travamento de leitura", +"Combinação de tabelas transacionais e não transacionais está desativada", +"Opção '%s' usada duas vezes no comando", +"Usuário '%-.64s' há excedido o '%s' de recursos (atual valor: %ld)", +"Acesso negado. Você necessita o privilégio %-.128s para essa operação", +"Variável '%-.64s' é uma LOCAL variável e não pode ser usada com SET GLOBAL", +"Variável '%-.64s' é uma GLOBAL variável e deve ser configurada com SET GLOBAL", +"Variável '%-.64s' não tem um valor default (padrão)", +"Variável '%-.64s' não pode ser configurada para o valor de '%-.64s'", +"Tipo de argumento errado para a variável '%-.64s'", +"Variável '%-.64s' somente pode ser configurada, não lida", +"Uso/localização errada de '%s'", +"Esta versão de MySQL não suporta ainda '%s'", +"Obteve fatal error %d: '%-.128s' a partir do master quando lendo dados do binary log", +"Definição errada da chave estrangeira para '%-.64s': %s", +"Referência da chave e referência da tabela não coincidem", +"Error de cardinalidade (mais/menos que %d colunas)", +"Subconsulta retorna mais que 1 registro", +"Desconhecido manipulador de declaração preparado (%ld) determinado para %s", +"Banco de dado de ajuda corrupto ou não existente", +"Referência cíclica em subconsultas", +"Convertendo coluna '%s' de %s para %s", +"Referência '%-.64s' não suportada (%s)", +"Cada tabela derivada deve ter seu próprio alias", +"Select %u foi reduzido durante otimização", +"Tabela '%-.64s' de um dos SELECT's não pode ser usada em %-.32s", +"Cliente não suporta o protocolo de autenticação exigido pelo servidor. Considere a atualização deo cliente MySQL", +"Todas as partes de uma SPATIAL KEY devem ser NOT NULL", +"COLLATION '%s' não é válida para CHARACTER SET '%s'", +"O slave já está rodando", +"O slave já está parado", +"Tamanho muito grande dos dados des comprimidos. O máximo tamanho é %d. (provavelmente, o comprimento dos dados descomprimidos está corrupto)", +"Z_BUF_ERROR: Não suficiente memória disponível para zlib", +"Z_MEM_ERROR: Não suficiente espaço no buffer emissor para zlib (provavelmente, o comprimento dos dados descomprimidos está corrupto)", +"Z_DATA_ERROR: Dados de entrada está corrupto para zlib", +"%d linha(s) foi(foram) cortada(s) por group_concat()", +"Usando engine de armazenamento %s para tabela '%s'", +"Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'", From 0ce726d5eeb78d9e44951542d9190fe003375b16 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 11:32:35 +0500 Subject: [PATCH 213/399] CREATE TABLE t1 SELECT left(_latin2'a',1) didn't work, the charset got lost Collation and coercibility tests for string functions mysql-test/r/func_str.result: Collation and coercibility tests for string functions mysql-test/t/func_str.test: Collation and coercibility tests for string functions sql/item_strfunc.cc: Collation and coercibility tests for string functions --- mysql-test/r/func_str.result | 42 ++++++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 23 ++++++++++++++++++++ sql/item_strfunc.cc | 4 +++- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 0b386eaf40a..b69af17edd7 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -249,3 +249,45 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf'); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); 1 DROP TABLE t1; +select collation(lcase(_latin2'a')), coercibility(lcase(_latin2'a')); +collation(lcase(_latin2'a')) coercibility(lcase(_latin2'a')) +latin2_general_ci 3 +select collation(ucase(_latin2'a')), coercibility(ucase(_latin2'a')); +collation(ucase(_latin2'a')) coercibility(ucase(_latin2'a')) +latin2_general_ci 3 +select collation(left(_latin2'a',1)), coercibility(left(_latin2'a',1)); +collation(left(_latin2'a',1)) coercibility(left(_latin2'a',1)) +latin2_general_ci 3 +select collation(right(_latin2'a',1)), coercibility(right(_latin2'a',1)); +collation(right(_latin2'a',1)) coercibility(right(_latin2'a',1)) +latin2_general_ci 3 +select collation(substring(_latin2'a',1,1)), coercibility(substring(_latin2'a',1,1)); +collation(substring(_latin2'a',1,1)) coercibility(substring(_latin2'a',1,1)) +latin2_general_ci 3 +select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b')); +collation(concat(_latin2'a',_latin2'b')) coercibility(concat(_latin2'a',_latin2'b')) +latin2_general_ci 3 +select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b')); +collation(concat_ws(_latin2'a',_latin2'b')) coercibility(concat_ws(_latin2'a',_latin2'b')) +latin2_general_ci 3 +create table t1 +select +left(_latin2'a',1), +right(_latin2'a',1), +lcase(_latin2'a'), +ucase(_latin2'a'), +substring(_latin2'a',1,1), +concat(_latin2'a',_latin2'b'), +concat_ws(_latin2'a',_latin2'b'); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `left(_latin2'a',1)` char(1) character set latin2 NOT NULL default '', + `right(_latin2'a',1)` char(1) character set latin2 NOT NULL default '', + `lcase(_latin2'a')` char(1) character set latin2 NOT NULL default '', + `ucase(_latin2'a')` char(1) character set latin2 NOT NULL default '', + `substring(_latin2'a',1,1)` char(1) character set latin2 NOT NULL default '', + `concat(_latin2'a',_latin2'b')` char(2) character set latin2 NOT NULL default '', + `concat_ws(_latin2'a',_latin2'b')` char(1) character set latin2 NOT NULL default '' +) TYPE=MyISAM CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 96d5b17abd7..43530aa640d 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -132,3 +132,26 @@ CREATE TABLE t1 (id int(11) NOT NULL auto_increment, tmp text NOT NULL, KEY id ( INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf'); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); DROP TABLE t1; + +# +# Test collation and coercibility +# +select collation(lcase(_latin2'a')), coercibility(lcase(_latin2'a')); +select collation(ucase(_latin2'a')), coercibility(ucase(_latin2'a')); +select collation(left(_latin2'a',1)), coercibility(left(_latin2'a',1)); +select collation(right(_latin2'a',1)), coercibility(right(_latin2'a',1)); +select collation(substring(_latin2'a',1,1)), coercibility(substring(_latin2'a',1,1)); +select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b')); +select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b')); +create table t1 +select + left(_latin2'a',1), + right(_latin2'a',1), + lcase(_latin2'a'), + ucase(_latin2'a'), + substring(_latin2'a',1,1), + concat(_latin2'a',_latin2'b'), + concat_ws(_latin2'a',_latin2'b'); + +show create table t1; +drop table t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 078e3f213a0..eb34c8691a3 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -928,7 +928,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()*default_charset_info->mbmaxlen; + int length=(int) args[1]->val_int()*charset()->mbmaxlen; if (length <= 0) max_length=0; else @@ -939,6 +939,7 @@ void Item_str_func::left_right_max_length() void Item_func_left::fix_length_and_dec() { + set_charset(args[0]->charset(), args[0]->coercibility); left_right_max_length(); } @@ -965,6 +966,7 @@ String *Item_func_right::val_str(String *str) void Item_func_right::fix_length_and_dec() { + set_charset(args[0]->charset(), args[0]->coercibility); left_right_max_length(); } From ab8418a59f9cdae88747ade62e2eab3005aa29b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 13:10:25 +0500 Subject: [PATCH 214/399] SHOW FIELDS changes, more SQL99 INFORMATION_SCHEMA.COLUMNS compatibility: Character set is not displayed in "Type" column anymore In "Collation" column NULL instead of BINARY is now displayd for for non-character data types mysql-test/r/alter_table.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/create.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/ctype_collate.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/ctype_recoding.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/gis.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/innodb.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/select.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/show_check.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/type_blob.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/type_float.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore mysql-test/r/type_ranges.result: Character set is not displayed in "Type" column of SHOW FIELDS anymore sql/field.cc: Character set is not displayed in "Type" column of SHOW FIELDS anymore sql/field.h: Character set is not displayed in "Type" column of SHOW FIELDS anymore sql/sql_show.cc: Character set is not displayed in "Type" column of SHOW FIELDS anymore --- mysql-test/r/alter_table.result | 6 +- mysql-test/r/create.result | 22 ++--- mysql-test/r/ctype_collate.result | 2 +- mysql-test/r/ctype_recoding.result | 6 +- mysql-test/r/gis.result | 66 +++++++-------- mysql-test/r/innodb.result | 2 +- mysql-test/r/select.result | 8 +- mysql-test/r/show_check.result | 40 ++++----- mysql-test/r/type_blob.result | 14 ++-- mysql-test/r/type_float.result | 28 +++---- mysql-test/r/type_ranges.result | 126 ++++++++++++++--------------- sql/field.cc | 29 ------- sql/field.h | 9 ++- sql/sql_show.cc | 43 ++++++---- 14 files changed, 195 insertions(+), 206 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index ec2f7220a3d..7bd836acefd 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -51,8 +51,8 @@ KEY NAME (NAME)); ALTER TABLE t1 CHANGE NAME NAME CHAR(80) not null; SHOW FULL COLUMNS FROM t1; Field Type Collation Null Key Default Extra Privileges Comment -GROUP_ID int(10) unsigned binary PRI 0 select,insert,update,references -LANG_ID smallint(5) unsigned binary PRI 0 select,insert,update,references +GROUP_ID int(10) unsigned NULL PRI 0 select,insert,update,references +LANG_ID smallint(5) unsigned NULL PRI 0 select,insert,update,references NAME char(80) latin1_swedish_ci MUL select,insert,update,references DROP TABLE t1; create table t1 (n int); @@ -157,7 +157,7 @@ alter table t1 rename t2; alter table t2 rename t1, add c char(10) comment "no comment"; show columns from t1; Field Type Collation Null Key Default Extra -i int(10) unsigned binary PRI NULL auto_increment +i int(10) unsigned NULL PRI NULL auto_increment c char(10) latin1_swedish_ci YES NULL drop table t1; create table t1 (a int, b int); diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 7a4ba1703a4..bd8343428c2 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -91,28 +91,28 @@ drop table t2; create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f; describe t2; Field Type Collation Null Key Default Extra -a datetime latin1_swedish_ci 0000-00-00 00:00:00 -b time latin1_swedish_ci 00:00:00 -c date latin1_swedish_ci 0000-00-00 -d bigint(17) binary 0 -e double(18,1) binary 0.0 -f bigint(17) binary 0 +a datetime NULL 0000-00-00 00:00:00 +b time NULL 00:00:00 +c date NULL 0000-00-00 +d bigint(17) NULL 0 +e double(18,1) NULL 0.0 +f bigint(17) NULL 0 drop table t2; create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt; describe t2; Field Type Collation Null Key Default Extra -d date latin1_swedish_ci 0000-00-00 -t time latin1_swedish_ci 00:00:00 -dt datetime latin1_swedish_ci 0000-00-00 00:00:00 +d date NULL 0000-00-00 +t time NULL 00:00:00 +dt datetime NULL 0000-00-00 00:00:00 drop table t1,t2; create table t1 (a tinyint); create table t2 (a int) select * from t1; describe t1; Field Type Collation Null Key Default Extra -a tinyint(4) binary YES NULL +a tinyint(4) NULL YES NULL describe t2; Field Type Collation Null Key Default Extra -a int(11) binary YES NULL +a int(11) NULL YES NULL drop table if exists t2; create table t2 (a int, a float) select * from t1; Duplicate column name 'a' diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result index e06651da30e..d2ae3950eaf 100644 --- a/mysql-test/r/ctype_collate.result +++ b/mysql-test/r/ctype_collate.result @@ -500,7 +500,7 @@ t1 CREATE TABLE `t1` ( ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM t1; Field Type Collation Null Key Default Extra -latin1_f char(32) character set latin1 latin1_bin YES NULL +latin1_f char(32) latin1_bin YES NULL ALTER TABLE t1 CHARACTER SET latin1 COLLATE latin1_bin; SHOW CREATE TABLE t1; Table Create Table diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 815445150cd..fb9e8224111 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -14,7 +14,7 @@ Table Create Table ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM ÔÁÂÌÉÃÁ; Field Type Collation Null Key Default Extra -ÐÏÌÅ char(32) character set koi8r koi8r_general_ci +ÐÏÌÅ char(32) koi8r_general_ci SET CHARACTER SET cp1251; SHOW TABLES; Tables_in_test @@ -26,7 +26,7 @@ Table Create Table ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM òàáëèöà; Field Type Collation Null Key Default Extra -ïîëå char(32) character set koi8r koi8r_general_ci +ïîëå char(32) koi8r_general_ci SET CHARACTER SET utf8; SHOW TABLES; Tables_in_test @@ -38,7 +38,7 @@ Table Create Table ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM таблица; Field Type Collation Null Key Default Extra -поле char(32) character set koi8r koi8r_general_ci +поле char(32) koi8r_general_ci SET CHARACTER SET koi8r; DROP TABLE ÔÁÂÌÉÃÁ; SET CHARACTER SET default; diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index a5a280b974f..746cdecdfdb 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -9,36 +9,36 @@ CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION); CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); SHOW FIELDS FROM pt; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g point binary YES NULL +fid int(11) NULL PRI 0 +g point NULL YES NULL SHOW FIELDS FROM ls; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g linestring binary YES NULL +fid int(11) NULL PRI 0 +g linestring NULL YES NULL SHOW FIELDS FROM p; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g polygon binary YES NULL +fid int(11) NULL PRI 0 +g polygon NULL YES NULL SHOW FIELDS FROM mpt; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g multipoint binary YES NULL +fid int(11) NULL PRI 0 +g multipoint NULL YES NULL SHOW FIELDS FROM mls; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g multilinestring binary YES NULL +fid int(11) NULL PRI 0 +g multilinestring NULL YES NULL SHOW FIELDS FROM mp; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g multipolygon binary YES NULL +fid int(11) NULL PRI 0 +g multipolygon NULL YES NULL SHOW FIELDS FROM gc; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g geometrycollection binary YES NULL +fid int(11) NULL PRI 0 +g geometrycollection NULL YES NULL SHOW FIELDS FROM geo; Field Type Collation Null Key Default Extra -fid int(11) binary PRI 0 -g geometry binary YES NULL +fid int(11) NULL PRI 0 +g geometry NULL YES NULL INSERT INTO pt VALUES (101, PointFromText('POINT(10 10)')), (102, PointFromText('POINT(20 10)')), @@ -367,26 +367,26 @@ gm geometry ); SHOW FIELDS FROM g1; Field Type Collation Null Key Default Extra -pt point binary YES NULL -ln linestring binary YES NULL -pg polygon binary YES NULL -mpt multipoint binary YES NULL -mln multilinestring binary YES NULL -mpg multipolygon binary YES NULL -gc geometrycollection binary YES NULL -gm geometry binary YES NULL +pt point NULL YES NULL +ln linestring NULL YES NULL +pg polygon NULL YES NULL +mpt multipoint NULL YES NULL +mln multilinestring NULL YES NULL +mpg multipolygon NULL YES NULL +gc geometrycollection NULL YES NULL +gm geometry NULL YES NULL ALTER TABLE g1 ADD fid INT NOT NULL; SHOW FIELDS FROM g1; Field Type Collation Null Key Default Extra -pt point binary YES NULL -ln linestring binary YES NULL -pg polygon binary YES NULL -mpt multipoint binary YES NULL -mln multilinestring binary YES NULL -mpg multipolygon binary YES NULL -gc geometrycollection binary YES NULL -gm geometry binary YES NULL -fid int(11) binary 0 +pt point NULL YES NULL +ln linestring NULL YES NULL +pg polygon NULL YES NULL +mpt multipoint NULL YES NULL +mln multilinestring NULL YES NULL +mpg multipolygon NULL YES NULL +gc geometrycollection NULL YES NULL +gm geometry NULL YES NULL +fid int(11) NULL 0 DROP TABLE g1; SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 98613dad628..0f65c8b0fe3 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -907,7 +907,7 @@ drop table t1; create table t1 (t int not null default 1, key (t)) type=innodb; desc t1; Field Type Collation Null Key Default Extra -t int(11) binary MUL 1 +t int(11) NULL MUL 1 drop table t1; CREATE TABLE t1 ( number bigint(20) NOT NULL default '0', diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 825a94c0ebf..8be189752ea 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3218,16 +3218,16 @@ show tables from test like "t?"; Tables_in_test (t?) show full columns from t2; Field Type Collation Null Key Default Extra Privileges Comment -auto int(11) binary PRI NULL auto_increment select,insert,update,references -fld1 int(6) unsigned zerofill binary UNI 000000 select,insert,update,references -companynr tinyint(2) unsigned zerofill binary 00 select,insert,update,references +auto int(11) NULL PRI NULL auto_increment select,insert,update,references +fld1 int(6) unsigned zerofill NULL UNI 000000 select,insert,update,references +companynr tinyint(2) unsigned zerofill NULL 00 select,insert,update,references fld3 char(30) latin1_swedish_ci MUL select,insert,update,references fld4 char(35) latin1_swedish_ci select,insert,update,references fld5 char(35) latin1_swedish_ci select,insert,update,references fld6 char(4) latin1_swedish_ci select,insert,update,references show full columns from t2 from test like 'f%'; Field Type Collation Null Key Default Extra Privileges Comment -fld1 int(6) unsigned zerofill binary UNI 000000 select,insert,update,references +fld1 int(6) unsigned zerofill NULL UNI 000000 select,insert,update,references fld3 char(30) latin1_swedish_ci MUL select,insert,update,references fld4 char(35) latin1_swedish_ci select,insert,update,references fld5 char(35) latin1_swedish_ci select,insert,update,references diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index b1072fd41ce..c1f2adc1e31 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -101,7 +101,7 @@ show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment test_set set('val1','val2','val3') latin1_swedish_ci select,insert,update,references name char(20) latin1_swedish_ci YES O'Brien select,insert,update,references O'Brien as default -c int(11) binary 0 select,insert,update,references int column +c int(11) NULL 0 select,insert,update,references int column drop table t1; create table t1 (a int not null, unique aa (a)); show create table t1; @@ -156,20 +156,20 @@ drop table t1; create table t1 (a decimal(9,2), b decimal (9,0), e double(9,2), f double(5,0), h float(3,2), i float(3,0)); show columns from t1; Field Type Collation Null Key Default Extra -a decimal(9,2) binary YES NULL -b decimal(9,0) binary YES NULL -e double(9,2) binary YES NULL -f double(5,0) binary YES NULL -h float(3,2) binary YES NULL -i float(3,0) binary YES NULL +a decimal(9,2) NULL YES NULL +b decimal(9,0) NULL YES NULL +e double(9,2) NULL YES NULL +f double(5,0) NULL YES NULL +h float(3,2) NULL YES NULL +i float(3,0) NULL YES NULL show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment -a decimal(9,2) binary YES NULL select,insert,update,references -b decimal(9,0) binary YES NULL select,insert,update,references -e double(9,2) binary YES NULL select,insert,update,references -f double(5,0) binary YES NULL select,insert,update,references -h float(3,2) binary YES NULL select,insert,update,references -i float(3,0) binary YES NULL select,insert,update,references +a decimal(9,2) NULL YES NULL select,insert,update,references +b decimal(9,0) NULL YES NULL select,insert,update,references +e double(9,2) NULL YES NULL select,insert,update,references +f double(5,0) NULL YES NULL select,insert,update,references +h float(3,2) NULL YES NULL select,insert,update,references +i float(3,0) NULL YES NULL select,insert,update,references drop table t1; create table t1 ( type_bool bool not null, @@ -230,15 +230,15 @@ drop table t1; create table t1 (c decimal, d double, f float, r real); show columns from t1; Field Type Collation Null Key Default Extra -c decimal(10,0) binary YES NULL -d double binary YES NULL -f float binary YES NULL -r double binary YES NULL +c decimal(10,0) NULL YES NULL +d double NULL YES NULL +f float NULL YES NULL +r double NULL YES NULL drop table t1; create table t1 (c decimal(3,3), d double(3,3), f float(3,3)); show columns from t1; Field Type Collation Null Key Default Extra -c decimal(4,3) binary YES NULL -d double(4,3) binary YES NULL -f float(4,3) binary YES NULL +c decimal(4,3) NULL YES NULL +d double(4,3) NULL YES NULL +f float(4,3) NULL YES NULL drop table t1; diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index 6d1b1189185..f97e2bc06b5 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -2,9 +2,9 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7; CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000)); show columns from t1; Field Type Collation Null Key Default Extra -a blob binary YES NULL +a blob NULL YES NULL b text latin1_swedish_ci YES NULL -c blob binary YES NULL +c blob NULL YES NULL d mediumtext latin1_swedish_ci YES NULL e longtext latin1_swedish_ci YES NULL CREATE TABLE t2 (a char(257), b varchar(70000) binary, c varchar(70000000)); @@ -15,7 +15,7 @@ Warning 1244 Converting column 'c' from CHAR to TEXT show columns from t2; Field Type Collation Null Key Default Extra a text latin1_swedish_ci YES NULL -b mediumblob binary YES NULL +b mediumblob NULL YES NULL c longtext latin1_swedish_ci YES NULL create table t3 (a long, b long byte); show create TABLE t3; @@ -72,15 +72,15 @@ show full fields from t1; Field Type Collation Null Key Default Extra Privileges Comment t text latin1_swedish_ci YES NULL select,insert,update,references c varchar(10) latin1_swedish_ci YES NULL select,insert,update,references -b blob binary YES NULL select,insert,update,references -d varchar(10) binary binary YES NULL select,insert,update,references +b blob NULL YES NULL select,insert,update,references +d varchar(10) binary YES NULL select,insert,update,references lock tables t1 WRITE; show full fields from t1; Field Type Collation Null Key Default Extra Privileges Comment t text latin1_swedish_ci YES NULL select,insert,update,references c varchar(10) latin1_swedish_ci YES NULL select,insert,update,references -b blob binary YES NULL select,insert,update,references -d varchar(10) binary binary YES NULL select,insert,update,references +b blob NULL YES NULL select,insert,update,references +d varchar(10) binary YES NULL select,insert,update,references unlock tables; select t from t1 where t like "hello"; t diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index eb9f6a00341..92cf4f70843 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -11,8 +11,8 @@ SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1; create table t1 (f1 float(24),f2 float(52)); show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment -f1 float binary YES NULL select,insert,update,references -f2 double binary YES NULL select,insert,update,references +f1 float NULL YES NULL select,insert,update,references +f2 double NULL YES NULL select,insert,update,references insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150); Warnings: Warning 1262 Data truncated, out of range for column 'f1' at row 7 @@ -73,18 +73,18 @@ drop table t1; create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6)); show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment -f float binary YES NULL select,insert,update,references -f2 float binary YES NULL select,insert,update,references -f3 float(6,2) binary YES NULL select,insert,update,references -d double binary YES NULL select,insert,update,references -d2 double binary YES NULL select,insert,update,references -d3 double(10,3) binary YES NULL select,insert,update,references -de decimal(10,0) binary YES NULL select,insert,update,references -de2 decimal(6,0) binary YES NULL select,insert,update,references -de3 decimal(5,2) binary YES NULL select,insert,update,references -n decimal(10,0) binary YES NULL select,insert,update,references -n2 decimal(8,0) binary YES NULL select,insert,update,references -n3 decimal(7,6) binary YES NULL select,insert,update,references +f float NULL YES NULL select,insert,update,references +f2 float NULL YES NULL select,insert,update,references +f3 float(6,2) NULL YES NULL select,insert,update,references +d double NULL YES NULL select,insert,update,references +d2 double NULL YES NULL select,insert,update,references +d3 double(10,3) NULL YES NULL select,insert,update,references +de decimal(10,0) NULL YES NULL select,insert,update,references +de2 decimal(6,0) NULL YES NULL select,insert,update,references +de3 decimal(5,2) NULL YES NULL select,insert,update,references +n decimal(10,0) NULL YES NULL select,insert,update,references +n2 decimal(8,0) NULL YES NULL select,insert,update,references +n3 decimal(7,6) NULL YES NULL select,insert,update,references drop table t1; create table t1 (a decimal(7,3) not null, key (a)); insert into t1 values ("0"),("-0.00"),("-0.01"),("-0.002"),("1"); diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index 54e1dea59c8..c059d5b58a0 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -39,28 +39,28 @@ KEY (options,flags) ); show full fields from t1; Field Type Collation Null Key Default Extra Privileges Comment -auto int(5) unsigned binary PRI NULL auto_increment select,insert,update,references +auto int(5) unsigned NULL PRI NULL auto_increment select,insert,update,references string varchar(10) latin1_swedish_ci YES hello select,insert,update,references -tiny tinyint(4) binary MUL 0 select,insert,update,references -short smallint(6) binary MUL 1 select,insert,update,references -medium mediumint(8) binary MUL 0 select,insert,update,references -long_int int(11) binary 0 select,insert,update,references -longlong bigint(13) binary MUL 0 select,insert,update,references -real_float float(13,1) binary MUL 0.0 select,insert,update,references -real_double double(16,4) binary YES NULL select,insert,update,references -utiny tinyint(3) unsigned binary MUL 0 select,insert,update,references -ushort smallint(5) unsigned zerofill binary MUL 00000 select,insert,update,references -umedium mediumint(8) unsigned binary MUL 0 select,insert,update,references -ulong int(11) unsigned binary MUL 0 select,insert,update,references -ulonglong bigint(13) unsigned binary MUL 0 select,insert,update,references -time_stamp timestamp latin1_swedish_ci YES NULL select,insert,update,references -date_field date latin1_swedish_ci YES NULL select,insert,update,references -time_field time latin1_swedish_ci YES NULL select,insert,update,references -date_time datetime latin1_swedish_ci YES NULL select,insert,update,references -blob_col blob binary YES NULL select,insert,update,references -tinyblob_col tinyblob binary YES NULL select,insert,update,references -mediumblob_col mediumblob binary select,insert,update,references -longblob_col longblob binary select,insert,update,references +tiny tinyint(4) NULL MUL 0 select,insert,update,references +short smallint(6) NULL MUL 1 select,insert,update,references +medium mediumint(8) NULL MUL 0 select,insert,update,references +long_int int(11) NULL 0 select,insert,update,references +longlong bigint(13) NULL MUL 0 select,insert,update,references +real_float float(13,1) NULL MUL 0.0 select,insert,update,references +real_double double(16,4) NULL YES NULL select,insert,update,references +utiny tinyint(3) unsigned NULL MUL 0 select,insert,update,references +ushort smallint(5) unsigned zerofill NULL MUL 00000 select,insert,update,references +umedium mediumint(8) unsigned NULL MUL 0 select,insert,update,references +ulong int(11) unsigned NULL MUL 0 select,insert,update,references +ulonglong bigint(13) unsigned NULL MUL 0 select,insert,update,references +time_stamp timestamp NULL YES NULL select,insert,update,references +date_field date NULL YES NULL select,insert,update,references +time_field time NULL YES NULL select,insert,update,references +date_time datetime NULL YES NULL select,insert,update,references +blob_col blob NULL YES NULL select,insert,update,references +tinyblob_col tinyblob NULL YES NULL select,insert,update,references +mediumblob_col mediumblob NULL select,insert,update,references +longblob_col longblob NULL select,insert,update,references options enum('one','two','tree') latin1_swedish_ci MUL one select,insert,update,references flags set('one','two','tree') latin1_swedish_ci select,insert,update,references show keys from t1; @@ -206,53 +206,53 @@ Warning 1263 Data truncated for column 'options' at row 6 update t2 set string="changed" where auto=16; show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment -auto int(5) unsigned binary MUL NULL auto_increment select,insert,update,references +auto int(5) unsigned NULL MUL NULL auto_increment select,insert,update,references string varchar(10) latin1_swedish_ci YES new defaul select,insert,update,references -tiny tinyint(4) binary MUL 0 select,insert,update,references -short smallint(6) binary MUL 0 select,insert,update,references -medium mediumint(8) binary MUL 0 select,insert,update,references -long_int int(11) binary 0 select,insert,update,references -longlong bigint(13) binary MUL 0 select,insert,update,references -real_float float(13,1) binary MUL 0.0 select,insert,update,references -real_double double(16,4) binary YES NULL select,insert,update,references -utiny tinyint(3) unsigned binary 0 select,insert,update,references -ushort smallint(5) unsigned zerofill binary 00000 select,insert,update,references -umedium mediumint(8) unsigned binary MUL 0 select,insert,update,references -ulong int(11) unsigned binary MUL 0 select,insert,update,references -ulonglong bigint(13) unsigned binary MUL 0 select,insert,update,references -time_stamp timestamp latin1_swedish_ci YES NULL select,insert,update,references +tiny tinyint(4) NULL MUL 0 select,insert,update,references +short smallint(6) NULL MUL 0 select,insert,update,references +medium mediumint(8) NULL MUL 0 select,insert,update,references +long_int int(11) NULL 0 select,insert,update,references +longlong bigint(13) NULL MUL 0 select,insert,update,references +real_float float(13,1) NULL MUL 0.0 select,insert,update,references +real_double double(16,4) NULL YES NULL select,insert,update,references +utiny tinyint(3) unsigned NULL 0 select,insert,update,references +ushort smallint(5) unsigned zerofill NULL 00000 select,insert,update,references +umedium mediumint(8) unsigned NULL MUL 0 select,insert,update,references +ulong int(11) unsigned NULL MUL 0 select,insert,update,references +ulonglong bigint(13) unsigned NULL MUL 0 select,insert,update,references +time_stamp timestamp NULL YES NULL select,insert,update,references date_field varchar(10) latin1_swedish_ci YES NULL select,insert,update,references -time_field time latin1_swedish_ci YES NULL select,insert,update,references -date_time datetime latin1_swedish_ci YES NULL select,insert,update,references +time_field time NULL YES NULL select,insert,update,references +date_time datetime NULL YES NULL select,insert,update,references new_blob_col varchar(20) latin1_swedish_ci YES NULL select,insert,update,references -tinyblob_col tinyblob binary YES NULL select,insert,update,references -mediumblob_col mediumblob binary select,insert,update,references +tinyblob_col tinyblob NULL YES NULL select,insert,update,references +mediumblob_col mediumblob NULL select,insert,update,references options enum('one','two','tree') latin1_swedish_ci MUL one select,insert,update,references flags set('one','two','tree') latin1_swedish_ci select,insert,update,references new_field varchar(10) latin1_swedish_ci new select,insert,update,references show full columns from t2; Field Type Collation Null Key Default Extra Privileges Comment -auto int(5) unsigned binary 0 select,insert,update,references +auto int(5) unsigned NULL 0 select,insert,update,references string varchar(10) latin1_swedish_ci YES new defaul select,insert,update,references -tiny tinyint(4) binary 0 select,insert,update,references -short smallint(6) binary 0 select,insert,update,references -medium mediumint(8) binary 0 select,insert,update,references -long_int int(11) binary 0 select,insert,update,references -longlong bigint(13) binary 0 select,insert,update,references -real_float float(13,1) binary 0.0 select,insert,update,references -real_double double(16,4) binary YES NULL select,insert,update,references -utiny tinyint(3) unsigned binary 0 select,insert,update,references -ushort smallint(5) unsigned zerofill binary 00000 select,insert,update,references -umedium mediumint(8) unsigned binary 0 select,insert,update,references -ulong int(11) unsigned binary 0 select,insert,update,references -ulonglong bigint(13) unsigned binary 0 select,insert,update,references -time_stamp timestamp latin1_swedish_ci YES NULL select,insert,update,references +tiny tinyint(4) NULL 0 select,insert,update,references +short smallint(6) NULL 0 select,insert,update,references +medium mediumint(8) NULL 0 select,insert,update,references +long_int int(11) NULL 0 select,insert,update,references +longlong bigint(13) NULL 0 select,insert,update,references +real_float float(13,1) NULL 0.0 select,insert,update,references +real_double double(16,4) NULL YES NULL select,insert,update,references +utiny tinyint(3) unsigned NULL 0 select,insert,update,references +ushort smallint(5) unsigned zerofill NULL 00000 select,insert,update,references +umedium mediumint(8) unsigned NULL 0 select,insert,update,references +ulong int(11) unsigned NULL 0 select,insert,update,references +ulonglong bigint(13) unsigned NULL 0 select,insert,update,references +time_stamp timestamp NULL YES NULL select,insert,update,references date_field varchar(10) latin1_swedish_ci YES NULL select,insert,update,references -time_field time latin1_swedish_ci YES NULL select,insert,update,references -date_time datetime latin1_swedish_ci YES NULL select,insert,update,references +time_field time NULL YES NULL select,insert,update,references +date_time datetime NULL YES NULL select,insert,update,references new_blob_col varchar(20) latin1_swedish_ci YES NULL select,insert,update,references -tinyblob_col tinyblob binary YES NULL select,insert,update,references -mediumblob_col mediumblob binary select,insert,update,references +tinyblob_col tinyblob NULL YES NULL select,insert,update,references +mediumblob_col mediumblob NULL select,insert,update,references options enum('one','two','tree') latin1_swedish_ci one select,insert,update,references flags set('one','two','tree') latin1_swedish_ci select,insert,update,references new_field varchar(10) latin1_swedish_ci new select,insert,update,references @@ -266,11 +266,11 @@ drop table t2; create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, "a" as t2, repeat("a",256) as t3, binary repeat("b",256) as t4 from t1; show full columns from t2; Field Type Collation Null Key Default Extra Privileges Comment -auto bigint(17) unsigned binary PRI 0 select,insert,update,references -t1 bigint(1) binary 0 select,insert,update,references +auto bigint(17) unsigned NULL PRI 0 select,insert,update,references +t1 bigint(1) NULL 0 select,insert,update,references t2 char(1) latin1_swedish_ci select,insert,update,references t3 mediumtext latin1_swedish_ci select,insert,update,references -t4 mediumtext character set latin1 latin1_bin select,insert,update,references +t4 mediumtext latin1_bin select,insert,update,references select * from t2; auto t1 t2 t3 t4 11 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb @@ -289,9 +289,9 @@ Duplicate column name 'c' create table t3 select t1.c AS c1, t2.c AS c2,1 as "const" from t1, t2; show full columns from t3; Field Type Collation Null Key Default Extra Privileges Comment -c1 int(11) binary YES NULL select,insert,update,references -c2 int(11) binary YES NULL select,insert,update,references -const bigint(1) binary 0 select,insert,update,references +c1 int(11) NULL YES NULL select,insert,update,references +c2 int(11) NULL YES NULL select,insert,update,references +const bigint(1) NULL 0 select,insert,update,references drop table t1,t2,t3; create table t1 ( myfield INT NOT NULL, UNIQUE INDEX (myfield), unique (myfield), index(myfield)); drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 5c3961a949e..3288aa2c4c7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -254,26 +254,6 @@ void Field_str::make_field(Send_field *field) } -void Field_str::add_binary_or_charset(String &res) const -{ - if (charset() == &my_charset_bin) - res.append(" binary"); - else if (field_charset != table->table_charset && - !(current_thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS) && - !(current_thd->variables.sql_mode & MODE_MYSQL323) && - !(current_thd->variables.sql_mode & MODE_MYSQL40) && - !(current_thd->variables.sql_mode & MODE_POSTGRESQL) && - !(current_thd->variables.sql_mode & MODE_ORACLE) && - !(current_thd->variables.sql_mode & MODE_MSSQL) && - !(current_thd->variables.sql_mode & MODE_DB2) && - !(current_thd->variables.sql_mode & MODE_SAPDB)) - { - res.append(" character set "); - res.append(field_charset->csname); - } -} - - uint Field::fill_cache_field(CACHE_FIELD *copy) { copy->str=ptr; @@ -4027,7 +4007,6 @@ void Field_string::sql_type(String &res) const "varchar" : "char"), (int) field_length); res.length(length); - add_binary_or_charset(res); } @@ -4194,7 +4173,6 @@ void Field_varstring::sql_type(String &res) const res.alloced_length(),"varchar(%u)", field_length); res.length(length); - add_binary_or_charset(res); } char *Field_varstring::pack(char *to, const char *from, uint max_length) @@ -4640,11 +4618,6 @@ void Field_blob::sql_type(String &res) const else { res.append("text"); - if (field_charset != table->table_charset) - { - res.append(" character set "); - res.append(field_charset->csname); - } } } @@ -5098,7 +5071,6 @@ void Field_enum::sql_type(String &res) const flag=1; } res.append(')'); - add_binary_or_charset(res); } @@ -5243,7 +5215,6 @@ void Field_set::sql_type(String &res) const flag=1; } res.append(')'); - add_binary_or_charset(res); } /* returns 1 if the fields are equally defined */ diff --git a/sql/field.h b/sql/field.h index cf08b1a9717..7d4abbd1d41 100644 --- a/sql/field.h +++ b/sql/field.h @@ -211,6 +211,7 @@ public: virtual bool get_date(TIME *ltime,bool fuzzydate); virtual bool get_time(TIME *ltime); virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } + virtual bool has_charset(void) const { return FALSE; } virtual void set_charset(CHARSET_INFO *charset) { } virtual void set_warning(const unsigned int level, const unsigned int code); @@ -277,12 +278,10 @@ public: flags|=BINARY_FLAG; } Item_result result_type () const { return STRING_RESULT; } - void add_binary_or_charset(String &res) const; uint decimals() const { return NOT_FIXED_DEC; } void make_field(Send_field *); uint size_of() const { return sizeof(*this); } CHARSET_INFO *charset(void) const { return field_charset; } - void set_charset(CHARSET_INFO *charset) { field_charset=charset; } bool binary() const { return field_charset->state & MY_CS_BINSORT ? 1 : 0; } friend class create_field; @@ -807,6 +806,7 @@ public: uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_STRING; } + bool has_charset(void) const { return TRUE; } }; @@ -849,6 +849,7 @@ public: uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } + bool has_charset(void) const { return TRUE; } }; @@ -936,6 +937,8 @@ public: inline void clear_temporary() { bzero((char*) &value,sizeof(value)); } friend void field_conv(Field *to,Field *from); uint size_of() const { return sizeof(*this); } + bool has_charset(void) const + { return charset() == &my_charset_bin ? FALSE : TRUE; } }; @@ -1004,6 +1007,7 @@ public: virtual bool zero_pack() const { return 0; } bool optimize_range(uint idx) { return 0; } bool eq_def(Field *field); + bool has_charset(void) const { return TRUE; } }; @@ -1028,6 +1032,7 @@ public: String *val_str(String*,String *); void sql_type(String &str) const; enum_field_types real_type() const { return FIELD_TYPE_SET; } + bool has_charset(void) const { return TRUE; } }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 660b8e7e572..16934e33798 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -719,8 +719,8 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, protocol->store(field->field_name, system_charset_info); field->sql_type(type); protocol->store(type.ptr(), type.length(), system_charset_info); - protocol->store(field->charset()->name, system_charset_info); - + protocol->store(field->has_charset() ? field->charset()->name : "NULL", + system_charset_info); pos=(byte*) ((flags & NOT_NULL_FLAG) && field->type() != FIELD_TYPE_TIMESTAMP ? "" : "YES"); @@ -1073,22 +1073,35 @@ store_create_info(THD *thd, TABLE *table, String *packet) field->sql_type(type); packet->append(type.ptr(),type.length()); + if (field->has_charset()) + { + if (field->charset() == &my_charset_bin) + packet->append(" binary"); + else if (!limited_mysql_mode && !foreign_db_mode) + { + if (field->charset() != table->table_charset) + { + packet->append(" character set "); + packet->append(field->charset()->csname); + } + /* + For string types dump collation name only if + collation is not primary for the given charset + */ + if (!(field->charset()->state & MY_CS_PRIMARY)) + { + packet->append(" collate ", 9); + packet->append(field->charset()->name); + } + } + } + + if (flags & NOT_NULL_FLAG) + packet->append(" NOT NULL", 9); + bool has_default = (field->type() != FIELD_TYPE_BLOB && field->type() != FIELD_TYPE_TIMESTAMP && field->unireg_check != Field::NEXT_NUMBER); - - /* - For string types dump collation name only if - collation is not primary for the given charset - */ - if (!(field->charset()->state & MY_CS_PRIMARY) && - !limited_mysql_mode && !foreign_db_mode) - { - packet->append(" collate ", 9); - packet->append(field->charset()->name); - } - if (flags & NOT_NULL_FLAG) - packet->append(" NOT NULL", 9); if (has_default) { From 3a1501d60e45552f7cbf2522b1cceb2d0f0f7c92 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 14:02:27 +0500 Subject: [PATCH 215/399] convert.cc was removed BitKeeper/deleted/.del-convert.cc~437689acaffb7446: Delete: sql/convert.cc --- libmysqld/Makefile.am | 2 +- sql/Makefile.am | 2 +- sql/convert.cc | 465 ------------------------------------------ 3 files changed, 2 insertions(+), 467 deletions(-) delete mode 100644 sql/convert.cc diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index b36f8d92490..93702e5b6d0 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -36,7 +36,7 @@ libmysqlsources = errmsg.c get_password.c noinst_HEADERS = embedded_priv.h -sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \ +sqlsources = derror.cc field.cc field_conv.cc filesort.cc \ ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \ ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \ hostname.cc init.cc password.c \ diff --git a/sql/Makefile.am b/sql/Makefile.am index a4858ab2b38..608b959a8b9 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -67,7 +67,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ net_serv.cc protocol.cc lock.cc my_lock.c \ sql_string.cc sql_manager.cc sql_map.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \ - convert.cc set_var.cc sql_parse.cc sql_yacc.yy \ + set_var.cc sql_parse.cc sql_yacc.yy \ sql_base.cc table.cc sql_select.cc sql_insert.cc \ sql_prepare.cc sql_error.cc \ sql_update.cc sql_delete.cc uniques.cc sql_do.cc \ diff --git a/sql/convert.cc b/sql/convert.cc deleted file mode 100644 index 880c462f4aa..00000000000 --- a/sql/convert.cc +++ /dev/null @@ -1,465 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ - -#ifdef NOT_USED - -/* -** Convert tables between different character sets -** Some of the tables are hidden behind IFDEF to reduce some space. -** One can enable them by removing the // characters from the next comment -** One must also give a name to each mapping that one wants to use... -*/ - -/* #define DEFINE_ALL_CHARACTER_SETS */ - -#include "mysql_priv.h" - -/**************************************************************************** - Convert tables -****************************************************************************/ - -/* Windows cp1251->koi8 and reverse conversion by Timur I. Bakeyev */ -/* based on Russian-Apache Team tables by Dmitry M. Klimoff */ - -static unsigned char cp1251_koi8[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, -144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, -160,161,162,163,164,189,166,167,179,169,180,171,172,173,174,183, -176,177,182,166,173,181,182,183,163,185,164,187,188,189,190,167, -225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240, -242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241, -193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208, -210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209 -}; - -static unsigned char koi8_cp1251[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, -144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, -160,161,162,184,186,165,179,191,168,169,170,171,172,180,174,175, -176,177,178,168,170,181,178,175,184,185,186,187,188,165,190,191, -254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238, -239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250, -222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206, -207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218 -}; - - -#ifdef DEFINE_ALL_CHARACTER_SETS - -/* These tables was generated from package 'cstools' (author Jan "Yenya" Kasprzak ) */ - -/* Windows pc1250 to iso 8859-2 */ - -static unsigned char t1250_til2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129, 0,131, 0, 0, 0, 0,136, 0,169, 0,166,171,174,172, -144, 0, 0, 0, 0, 0, 0, 0,152, 0,185, 0,182,187,190,188, -160,183,162,163,164,161, 0,167,168, 0,170, 0, 0,173, 0,175, -176, 0,178,179,180, 0, 0, 0,184,177,186, 0,165,189,181,191, -192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, -208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, -224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, -240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 -}; - -static unsigned char til2_t1250[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129, 0,131, 0, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, -144, 0, 0, 0, 0, 0, 0, 0,152, 0, 0, 0, 0, 0, 0, 0, -160,165,162,163,164,188,140,167,168,138,170,141,143,173,142,175, -176,185,178,179,180,190,156,161,184,154,186,157,159,189,158,191, -192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, -208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, -224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, -240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 -}; - -/* Windows pc1252 to iso 8859-2 */ - -static unsigned char t1252_til2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129, 0, 0, 0, 0, 0, 0,136, 0,169, 0, 0,141,142,143, -144, 0, 0, 0, 0, 0, 0, 0,189, 0,185, 0, 0,157,158, 0, -160, 0, 0, 0,164, 0, 0,167,168, 0, 0, 0, 0,173, 0, 0, -176, 0, 0, 0,180, 0, 0, 0,184, 0, 0, 0, 0, 0, 0, 0, - 0,193,194, 0,196, 0, 0,199, 0,201, 0,203, 0,205,206, 0, -208, 0, 0,211,212, 0,214,215, 0, 0,218, 0,220,221, 0,223, - 0,225,226, 0,228, 0, 0,231, 0,233, 0,235, 0,237,238, 0, -240, 0, 0,243,244, 0,246,247, 0, 0,250, 0,252,253, 0, 0 -}; -static unsigned char til2_t1252[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129, 0, 0, 0, 0, 0, 0,136, 0, 0, 0, 0,141,142,143, -144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,157,158, 0, -160, 0, 0, 0,164, 0, 0,167,168,138, 0, 0, 0,173, 0, 0, -176, 0, 0, 0,180, 0, 0, 0,184,154, 0, 0, 0,152, 0, 0, - 0,193,194, 0,196, 0, 0,199, 0,201, 0,203, 0,205,206, 0, -208, 0, 0,211,212, 0,214,215, 0, 0,218, 0,220,221, 0,223, - 0,225,226, 0,228, 0, 0,231, 0,233, 0,235, 0,237,238, 0, -240, 0, 0,243,244, 0,246,247, 0, 0,250, 0,252,253, 0, 0 -}; - -/* MSDOS Kamenicky encoding (for Czech/Slovak) to iso 8859-2 */ - -static unsigned char tkam_til2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -200,252,233,239,228,207,171,232,236,204,197,205,181,229,196,193, -201,190,174,244,246,211,249,218,253,214,220,169,165,221,216,187, -225,237,243,250,242,210,217,212,185,248,224,192, 0,167, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,247, 0,176, 0, 0, 0, 0, 0, 0, 0 -}; -static unsigned char til2_tkam[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,156, 0,173, 0,155, 0,134, 0, 0,146, 0, -248, 0, 0, 0, 0,140, 0, 0, 0,168, 0,159, 0, 0,145, 0, -171,143, 0, 0,142,138, 0, 0,128,144, 0, 0,137,139, 0,133, - 0, 0,165,149,167, 0,153, 0,158,166,151, 0,154,157, 0, 0, -170,160, 0, 0,132,141, 0, 0,135,130, 0, 0,136,161, 0,131, - 0, 0,164,162,147, 0,148,246,169,150,163, 0,129,152, 0, 0 -}; - -/* Macintosh Roman encoding to iso 8859-2 */ - -static unsigned char tmac_til2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -196, 0,199,201, 0,214,220,225, 0,226,228, 0, 0,231,233, 0, - 0,235,237, 0,238, 0, 0,243, 0,244,246, 0,250, 0, 0,252, - 0,176, 0, 0,167, 0, 0,223, 0, 0, 0,180,168, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,247, 0, 0, 0, 0,164, 0, 0, 0, 0, - 0, 0, 0, 0, 0,194, 0,193,203, 0,205,206, 0, 0,211,212, - 0, 0,218, 0, 0, 0, 0, 0, 0,162,255, 0,184,189,178,183 -}; -static unsigned char til2_tmac[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0,249, 0,219, 0, 0,164,172, 0, 0, 0, 0, 0, 0, 0, -161, 0,254, 0,171, 0, 0,255,252, 0, 0, 0, 0,253, 0, 0, - 0,231,229, 0,128, 0, 0,130, 0,131, 0,232, 0,234,235, 0, - 0, 0, 0,238,239, 0,133, 0, 0, 0,242, 0,134, 0, 0,167, - 0,135,137, 0,138, 0, 0,141, 0,142, 0,145, 0,146,148, 0, - 0, 0, 0,151,153, 0,154,214, 0, 0,156, 0,159, 0, 0,250 -}; - -/* Macintosh Central European encodingto iso 8859-2 */ - -static unsigned char tmacce_til2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -196, 0, 0,201,161,214,220,225,177,200,228,232,198,230,233,172, -188,207,237,239, 0, 0, 0,243, 0,244,246, 0,250,204,236,252, - 0,176,202, 0,167, 0, 0,223, 0, 0, 0,234,168, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0,165,181,197,229, 0, - 0,209, 0, 0,241,210, 0, 0, 0, 0,160,242,213, 0,245, 0, - 0, 0, 0, 0, 0, 0,247, 0, 0,192,224,216, 0, 0,248, 0, - 0,169, 0, 0,185,166,182,193,171,187,205,174,190, 0,211,212, - 0,217,218,249,219,251, 0, 0,221,253, 0,175,163,191, 0,183 -}; -static unsigned char til2_tmacce[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202,132, 0,252, 0,187,229,164,172,225, 0,232,143, 0,235,251, -161,136, 0,184, 0,188,230,255, 0,228, 0,233,144, 0,236,253, -217,231, 0, 0,128,189,140, 0,137,131,162, 0,157,234, 0,145, - 0,193,197,238,239,204,133, 0,219,241,242,244,134,248, 0,167, -218,135, 0, 0,138,190,141, 0,139,142,171, 0,158,146, 0,147, - 0,196,203,151,153,206,154,214,222,243,156,245,159,249, 0, 0 -}; - -/* PC-Latin2 encoding, supported by M$-DOS to iso 8859-2 */ - -static unsigned char tpc2_til2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -199,252,233,226,228,249,230,231,179,235,213,245,238,172,196,198, -201,197,229,244,246,165,181,166,182,214,220,171,187,163,215,232, -225,237,243,250,161,177,174,190,202,234, 0,188,200,186, 0, 0, - 0, 0, 0, 0, 0,193,194,204,170, 0, 0, 0, 0,175,191, 0, - 0, 0, 0, 0, 0, 0,195,227, 0, 0, 0, 0, 0, 0, 0,164, -240,208,207,203,239,210,205,206,236, 0, 0, 0, 0,222,217, 0, -211,223,212,209,241,242,169,185,192,218,224,219,253,221,254,180, - 0,189,178,183,162,167,247,184, 0,168,255,251,216,248, 0, 0 -}; -static unsigned char til2_tpc2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,164,244,157,207,149,151,245,249,230,184,155,141, 0,166,189, - 0,165,242,136,239,150,152,243,247,231,173,156,171,241,167,190, -232,181,182,198,142,145,143,128,172,144,168,211,183,214,215,210, -209,227,213,224,226,138,153,158,252,222,233,235,154,237,221,225, -234,160,131,199,132,146,134,135,159,130,169,137,216,161,140,212, -208,228,229,162,147,139,148,246,253,133,163,251,129,236,238,250 -}; - -/* Encoding used by standard IBM PC vga cards to iso8859-2 */ -static unsigned char tvga_til2[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -199,252,233,226,228, 0, 0,231, 0,235, 0, 0,238, 0,196, 0, -201, 0, 0,244,246, 0, 0, 0, 0,214,220, 0, 0, 0, 0, 0, -225,237,243,250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,247, 0,176, 0, 0, 0, 0, 0, 0, 0 -}; -static unsigned char til2_tvga[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,142, 0, 0,128, 0,144, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,153, 0, 0, 0, 0, 0,154, 0, 0, 0, - 0,160,131, 0,132, 0, 0,135, 0,130, 0,137, 0,161,140, 0, - 0, 0, 0,162,147, 0,148,246, 0, 0,163, 0,129, 0, 0, 0 -}; - -//Ukrainian koi8 and win1251 converting tables by Max Veremayenko -//(verem@tg.kiev.ua - -static unsigned char koi8_ukr_win1251ukr[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, -144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, -160,161,162,184,186,165,179,191,168,169,170,171,172,180,174,175, -176,177,178,168,170,181,178,175,184,185,186,187,188,165,190,191, -254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238, -239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250, -222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206, -207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218 -}; - -static unsigned char win1251ukr_koi8_ukr[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, -112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, -144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, -160,161,162,163,164,189,166,167,179,169,180,171,172,173,174,183, -176,177,182,166,173,181,182,183,163,185,164,187,188,189,190,167, -225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240, -242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241, -193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208, -210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209 -}; - -#endif /* DEFINE_ALL_CHARACTER_SETS */ - -/**************************************************************************** -** Declare mapping variables -****************************************************************************/ - - -CONVERT conv_cp1251_koi8("cp1251_koi8", cp1251_koi8, koi8_cp1251, 1); -#ifdef DEFINE_ALL_CHARACTER_SETS -CONVERT conv_cp1250_latin2("cp1250_latin2", t1250_til2, til2_t1250, 2); -CONVERT conv_kam_latin2("kam_latin2", tkam_til2, til2_tkam, 3); -CONVERT conv_mac_latin2("mac_latin2", tmac_til2, til2_tmac, 4); -CONVERT conv_macce_latin2("macce_latin2", tmacce_til2, til2_tmacce, 5); -CONVERT conv_pc2_latin2("pc2_latin2", tpc2_til2, til2_tpc2, 6); -CONVERT conv_vga_latin2("vga_latin2", tvga_til2, til2_tvga, 7); -CONVERT conv_koi8_cp1251("koi8_cp1251", koi8_cp1251, cp1251_koi8, 8); -CONVERT conv_win1251ukr_koi8_ukr("win1251ukr_koi8_ukr", win1251ukr_koi8_ukr, - koi8_ukr_win1251ukr, 9); -CONVERT conv_koi8_ukr_win1251ukr("koi8_ukr_win1251ukr", koi8_ukr_win1251ukr, - win1251ukr_koi8_ukr, 10); -#endif /* DEFINE_ALL_CHARACTER_SETS */ - -CONVERT *convert_tables[]= { - &conv_cp1251_koi8, -#ifdef DEFINE_ALL_CHARACTER_SETS - &conv_cp1250_latin2, - &conv_kam_latin2, - &conv_mac_latin2, - &conv_macce_latin2, - &conv_pc2_latin2, - &conv_vga_latin2, - &conv_koi8_cp1251, - &conv_win1251ukr_koi8_ukr, - &conv_koi8_ukr_win1251ukr, -#endif /* DEFINE_ALL_CHARACTER_SETS */ - NULL -}; - - -CONVERT *get_convert_set(const char *name) -{ - for (CONVERT **ptr=convert_tables ; *ptr ; ptr++) - { - if (!my_strcasecmp(&my_charset_latin1,(*ptr)->name,name)) - return (*ptr); - } - return 0; -} - - -void CONVERT::convert_array(const uchar *map, uchar * buf, uint len) -{ - for (uchar *end=buf+len ; buf != end ; buf++) - *buf= map[*buf]; -} - - -/* This is identical as net_store_data, but with a conversion */ - -bool CONVERT::store(String *packet,const char *from,uint length) -{ - uint packet_length=packet->length(); - if (packet_length+5+length > packet->alloced_length() && - packet->realloc(packet_length+5+length)) - return 1; - char *to=(char*) net_store_length((char*) packet->ptr()+packet_length, - (ulonglong)length); - packet->length((uint) (store_dest(to, from, length)-packet->ptr())); - return 0; -} - -#endif /* NOT_USED */ From d7ab5da88fd11c69af7144cd56af283a31502ff6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 14:24:52 +0500 Subject: [PATCH 216/399] charset.c: Bug fix: if latin2_czech_ci is not compiled, loader din't load other latin2 collations mysys/charset.c: Bug fix: if latin2_czech_ci is not compiled, loader din't load other latin2 collations --- mysys/charset.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysys/charset.c b/mysys/charset.c index 9b8903bc6b7..af4d3620df2 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -314,7 +314,7 @@ static int add_collation(CHARSET_INFO *cs) if (!all_charsets[cs->number]) { if (cs->state & MY_CS_COMPILED) - return MY_XML_OK; + goto clear; if (!(all_charsets[cs->number]= (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0)))) return MY_XML_ERROR; @@ -343,6 +343,7 @@ static int add_collation(CHARSET_INFO *cs) if (cs->comment) dst->comment= my_once_strdup(cs->comment,MYF(MY_WME)); } +clear: cs->number= 0; cs->primary_number= 0; cs->binary_number= 0; From f985f468ef02549ad512ff0eccdc170900f6d0cd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 11:38:37 +0200 Subject: [PATCH 217/399] - Portability fix: FreeBSD 4.8-STABLE (480101) and 5.0-CURRENT (500110) now have a thread safe realpath(3) implementation - added check to only define -DHAVE_BROKEN_REALPATH where required (thanks to Martin Blapp from the FreeBSD team for the patch) configure.in: - FreeBSD 4.8-STABLE (480101) and 5.0-CURRENT (500110) now have a thread safe realpath(3) implementation - added check to only define -DHAVE_BROKEN_REALPATH where required --- configure.in | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index df83f7e715e..8a5ab75a494 100644 --- a/configure.in +++ b/configure.in @@ -1025,8 +1025,16 @@ case $SYSTEM_TYPE in ;; *freebsd*) echo "Adding fix for interrupted reads" - CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH" - CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH" + OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'` + if test "$OSVERSION" -gt "480100" && \ + test "$OSVERSION" -lt "500000" || \ + test "$OSVERSION" -gt "500109" + then + CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000" + else + CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH" + CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH" + fi ;; *netbsd*) echo "Adding flag -Dunix" From f461dea4d7066c6dfe14b33cc549f7e0183f6b8e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 15:10:05 +0500 Subject: [PATCH 218/399] Character set sets now check if required non-dynamic charsets were really compiled BitKeeper/deleted/.del-ctype_ujis-master.opt~9f5cc09930fc1cf9: Delete: mysql-test/t/ctype_ujis-master.opt --- mysql-test/include/have_ucs2.inc | 4 ++++ mysql-test/include/have_ujis.inc | 4 ++++ mysql-test/r/have_ucs2.require | 2 ++ mysql-test/r/have_ujis.require | 2 ++ mysql-test/r/isam.result | 12 ++++++------ mysql-test/t/ctype_many.test | 2 ++ mysql-test/t/ctype_ujis-master.opt | 1 - mysql-test/t/ctype_ujis.test | 4 +++- sql/share/charsets/Index.xml | 15 ++++++++++++--- 9 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 mysql-test/include/have_ucs2.inc create mode 100644 mysql-test/include/have_ujis.inc create mode 100644 mysql-test/r/have_ucs2.require create mode 100644 mysql-test/r/have_ujis.require delete mode 100644 mysql-test/t/ctype_ujis-master.opt diff --git a/mysql-test/include/have_ucs2.inc b/mysql-test/include/have_ucs2.inc new file mode 100644 index 00000000000..92ec9b5fb44 --- /dev/null +++ b/mysql-test/include/have_ucs2.inc @@ -0,0 +1,4 @@ +-- require r/have_ucs2.require +disable_query_log; +show collation like "ucs2_general_ci"; +enable_query_log; diff --git a/mysql-test/include/have_ujis.inc b/mysql-test/include/have_ujis.inc new file mode 100644 index 00000000000..ecceb7a8408 --- /dev/null +++ b/mysql-test/include/have_ujis.inc @@ -0,0 +1,4 @@ +-- require r/have_ujis.require +disable_query_log; +show collation like "ujis_japanese_ci"; +enable_query_log; diff --git a/mysql-test/r/have_ucs2.require b/mysql-test/r/have_ucs2.require new file mode 100644 index 00000000000..9d7079740ad --- /dev/null +++ b/mysql-test/r/have_ucs2.require @@ -0,0 +1,2 @@ +Collation Charset Id D C Sortlen +ucs2_general_ci ucs2 35 Y 0 diff --git a/mysql-test/r/have_ujis.require b/mysql-test/r/have_ujis.require new file mode 100644 index 00000000000..5f7ce2a50c7 --- /dev/null +++ b/mysql-test/r/have_ujis.require @@ -0,0 +1,2 @@ +Collation Charset Id D C Sortlen +ujis_japanese_ci ujis 12 Y 0 diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result index 6621be98073..5975ac8a8a0 100644 --- a/mysql-test/r/isam.result +++ b/mysql-test/r/isam.result @@ -73,14 +73,14 @@ test.t2 check error Table 't2' was not locked with LOCK TABLES test.t1 check status OK show columns from t1; Field Type Collation Null Key Default Extra -a int(11) binary PRI 0 -b int(11) binary MUL 0 -c int(11) binary 0 +a int(11) NULL PRI 0 +b int(11) NULL MUL 0 +c int(11) NULL 0 show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment -a int(11) binary PRI 0 select,insert,update,references -b int(11) binary MUL 0 select,insert,update,references -c int(11) binary 0 select,insert,update,references +a int(11) NULL PRI 0 select,insert,update,references +b int(11) NULL MUL 0 select,insert,update,references +c int(11) NULL 0 select,insert,update,references show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 0 PRIMARY 1 a A 4 NULL NULL BTREE diff --git a/mysql-test/t/ctype_many.test b/mysql-test/t/ctype_many.test index ab528dc11e7..66732520f4d 100644 --- a/mysql-test/t/ctype_many.test +++ b/mysql-test/t/ctype_many.test @@ -1,3 +1,5 @@ +-- source include/have_ucs2.inc + --disable_warnings DROP TABLE IF EXISTS t1; --enable_warnings diff --git a/mysql-test/t/ctype_ujis-master.opt b/mysql-test/t/ctype_ujis-master.opt deleted file mode 100644 index 1f4183d5027..00000000000 --- a/mysql-test/t/ctype_ujis-master.opt +++ /dev/null @@ -1 +0,0 @@ ---default-character-set=ujis diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test index 7308f26a8cf..e41caf55948 100644 --- a/mysql-test/t/ctype_ujis.test +++ b/mysql-test/t/ctype_ujis.test @@ -1,3 +1,5 @@ +-- source include/have_ujis.inc + # # Tests with the ujis character set # @@ -9,7 +11,7 @@ drop table if exists t1; # Test problem with LEFT() # -create table t1 (c text); +create table t1 (c text character set ujis); insert into t1 values (0xa4a2),(0xa4a3); select hex(left(c,1)) from t1 group by c; drop table t1; diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 84ef917fe00..1278cb6c54a 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -169,7 +169,10 @@ To make maintaining easier please: Japanese EUC-JP Japanese euc-jp - + + primary + compiled + @@ -178,7 +181,10 @@ To make maintaining easier please: s-jis shift-jis x-sjis - + + primary + compiled + @@ -376,7 +382,10 @@ To make maintaining easier please: Unicode UCS-2 Unicode - + + primary + compiled + From 5aae66c1017aaef0efc0080c095436f954288bd6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 17:45:52 +0500 Subject: [PATCH 219/399] CHARSET_INFO structure reorganization for easier maintainance --- client/sql_string.cc | 12 ++-- heap/hp_hash.c | 4 +- include/m_ctype.h | 117 +++++++++++++++++++++----------------- myisam/mi_unique.c | 2 +- mysys/charset.c | 38 ++----------- mysys/hash.c | 2 +- sql/field.cc | 57 ++++++++++--------- sql/field.h | 2 +- sql/item_cmpfunc.cc | 4 +- sql/item_strfunc.cc | 6 +- sql/item_timefunc.cc | 10 ++-- sql/sql_string.cc | 14 ++--- strings/ctype-big5.c | 67 +++++++++++++--------- strings/ctype-bin.c | 65 ++++++++++++--------- strings/ctype-czech.c | 40 +++++-------- strings/ctype-euc_kr.c | 66 ++++++++++++--------- strings/ctype-extra.c | 26 --------- strings/ctype-gb2312.c | 66 ++++++++++++--------- strings/ctype-gbk.c | 66 ++++++++++++--------- strings/ctype-latin1.c | 95 +++++++++++++------------------ strings/ctype-simple.c | 35 ++++++++++++ strings/ctype-sjis.c | 67 +++++++++++++--------- strings/ctype-tis620.c | 66 ++++++++++++--------- strings/ctype-ucs2.c | 89 ++++++++++++++++------------- strings/ctype-ujis.c | 67 +++++++++++++--------- strings/ctype-utf8.c | 67 +++++++++++++--------- strings/ctype-win1250ch.c | 40 +++++-------- 27 files changed, 633 insertions(+), 557 deletions(-) diff --git a/client/sql_string.cc b/client/sql_string.cc index 8ab205d9fb1..65a9ff68c53 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -97,13 +97,13 @@ bool String::set(longlong num, CHARSET_INFO *cs) if (alloc(l)) return TRUE; - if (cs->snprintf == my_snprintf_8bit) + if (cs->cset->snprintf == my_snprintf_8bit) { str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr); } else { - str_length=cs->snprintf(cs,Ptr,l,"%d",num); + str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num); } str_charset=cs; return FALSE; @@ -115,13 +115,13 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) if (alloc(l)) return TRUE; - if (cs->snprintf == my_snprintf_8bit) + if (cs->cset->snprintf == my_snprintf_8bit) { str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr); } else { - str_length=cs->snprintf(cs,Ptr,l,"%d",num); + str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num); } str_charset=cs; return FALSE; @@ -255,7 +255,7 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET for (str_length=new_length ; s < se && d < de ; ) { - if ((cnvres=from->mb_wc(from,&wc,s,se)) > 0 ) + if ((cnvres=from->cset->mb_wc(from,&wc,s,se)) > 0 ) { s+=cnvres; } @@ -268,7 +268,7 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET break; outp: - if((cnvres=to->wc_mb(to,wc,d,de)) >0 ) + if((cnvres=to->cset->wc_mb(to,wc,d,de)) >0 ) { d+=cnvres; } diff --git a/heap/hp_hash.c b/heap/hp_hash.c index e315c1bbcb8..2a946dcd7b9 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -215,7 +215,7 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key) } if (seg->type == HA_KEYTYPE_TEXT) { - seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,&nr2); + seg->charset->coll->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,&nr2); } else { @@ -250,7 +250,7 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec) } if (seg->type == HA_KEYTYPE_TEXT) { - seg->charset->hash_sort(seg->charset,pos,end-pos,&nr,&nr2); + seg->charset->coll->hash_sort(seg->charset,pos,end-pos,&nr,&nr2); } else { diff --git a/include/m_ctype.h b/include/m_ctype.h index 6cf0ecfbb8a..59f75081ff9 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -91,27 +91,11 @@ enum my_lex_states MY_LEX_STRING_OR_DELIMITER }; +struct charset_info_st; -typedef struct charset_info_st +typedef struct my_collation_handler_st { - uint number; - uint primary_number; - uint binary_number; - uint state; - const char *csname; - const char *name; - const char *comment; - uchar *ctype; - uchar *to_lower; - uchar *to_upper; - uchar *sort_order; - uint16 *tab_to_uni; - MY_UNI_IDX *tab_from_uni; - uchar state_map[256]; - uchar ident_map[256]; - /* Collation routines */ - uint strxfrm_multiply; int (*strnncoll)(struct charset_info_st *, const uchar *, uint, const uchar *, uint); int (*strnncollsp)(struct charset_info_st *, @@ -128,9 +112,21 @@ typedef struct charset_info_st const char *str,const char *str_end, const char *wildstr,const char *wildend, int escape,int w_one, int w_many); + + int (*strcasecmp)(struct charset_info_st *, const char *, const char *); + /* Hash calculation */ + void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len, + ulong *nr1, ulong *nr2); +} MY_COLLATION_HANDLER; + +extern MY_COLLATION_HANDLER my_collation_bin_handler; +extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler; + + +typedef struct my_charset_handler_st +{ /* Multibyte routines */ - uint mbmaxlen; int (*ismbchar)(struct charset_info_st *, const char *, const char *); int (*mbcharlen)(struct charset_info_st *, uint); uint (*numchars)(struct charset_info_st *, const char *b, const char *e); @@ -148,15 +144,6 @@ typedef struct charset_info_st void (*caseup)(struct charset_info_st *, char *, uint); void (*casedn)(struct charset_info_st *, char *, uint); - /* Functions for case comparison */ - int (*strcasecmp)(struct charset_info_st *, const char *, const char *); - - /* Hash calculation */ - void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len, - ulong *nr1, ulong *nr2); - - char max_sort_char; /* For LIKE optimization */ - /* Charset dependant snprintf() */ int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt, ...); @@ -181,6 +168,35 @@ typedef struct charset_info_st ulong (*scan)(struct charset_info_st *, const char *b, const char *e, int sq); +} MY_CHARSET_HANDLER; + +extern MY_CHARSET_HANDLER my_charset_8bit_handler; + + + +typedef struct charset_info_st +{ + uint number; + uint primary_number; + uint binary_number; + uint state; + const char *csname; + const char *name; + const char *comment; + uchar *ctype; + uchar *to_lower; + uchar *to_upper; + uchar *sort_order; + uint16 *tab_to_uni; + MY_UNI_IDX *tab_from_uni; + uchar state_map[256]; + uchar ident_map[256]; + uint strxfrm_multiply; + uint mbmaxlen; + char max_sort_char; /* For LIKE optimization */ + + MY_CHARSET_HANDLER *cset; + MY_COLLATION_HANDLER *coll; } CHARSET_INFO; @@ -211,9 +227,6 @@ extern CHARSET_INFO my_charset_utf8_bin; extern CHARSET_INFO my_charset_cp1250_czech_ci; -extern my_bool my_parse_charset_xml(const char *bug, uint len, - int (*add)(CHARSET_INFO *cs)); - /* declarations for simple charsets */ extern int my_strnxfrm_simple(CHARSET_INFO *, uchar *, uint, const uchar *, uint); @@ -254,7 +267,6 @@ ulonglong my_strntoull_8bit(CHARSET_INFO *, const char *s, uint l, int base, char **e, int *err); double my_strntod_8bit(CHARSET_INFO *, char *s, uint l,char **e, int *err); - int my_long10_to_str_8bit(CHARSET_INFO *, char *to, uint l, int radix, long int val); int my_longlong10_to_str_8bit(CHARSET_INFO *, char *to, uint l, int radix, @@ -279,7 +291,6 @@ uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos); -#ifdef USE_MB /* Functions for multibyte charsets */ extern void my_caseup_str_mb(CHARSET_INFO *, char *); extern void my_casedn_str_mb(CHARSET_INFO *, char *); @@ -294,7 +305,10 @@ int my_wildcmp_mb(CHARSET_INFO *, uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); -#endif + +extern my_bool my_parse_charset_xml(const char *bug, uint len, + int (*add)(CHARSET_INFO *cs)); + #define _U 01 /* Upper case */ #define _L 02 /* Lower case */ @@ -329,27 +343,26 @@ uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); #define my_isvar_start(s,c) (my_isalpha(s,c) || (c) == '_') #define use_strnxfrm(s) ((s)->state & MY_CS_STRNXFRM) -#define my_strnxfrm(s, a, b, c, d) ((s)->strnxfrm((s), (a), (b), (c), (d))) -#define my_strnncoll(s, a, b, c, d) ((s)->strnncoll((s), (a), (b), (c), (d))) +#define my_strnxfrm(s, a, b, c, d) ((s)->coll->strnxfrm((s), (a), (b), (c), (d))) +#define my_strnncoll(s, a, b, c, d) ((s)->coll->strnncoll((s), (a), (b), (c), (d))) #define my_like_range(s, a, b, c, d, e, f, g, h, i, j) \ - ((s)->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j))) -#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m))) + ((s)->coll->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j))) +#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->coll->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m))) +#define my_strcasecmp(s, a, b) ((s)->coll->strcasecmp((s), (a), (b))) -#define use_mb(s) ((s)->ismbchar != NULL) -#define my_ismbchar(s, a, b) ((s)->ismbchar((s), (a), (b))) -#define my_mbcharlen(s, a) ((s)->mbcharlen((s),(a))) +#define use_mb(s) ((s)->cset->ismbchar != NULL) +#define my_ismbchar(s, a, b) ((s)->cset->ismbchar((s), (a), (b))) +#define my_mbcharlen(s, a) ((s)->cset->mbcharlen((s),(a))) -#define my_caseup(s, a, l) ((s)->caseup((s), (a), (l))) -#define my_casedn(s, a, l) ((s)->casedn((s), (a), (l))) -#define my_caseup_str(s, a) ((s)->caseup_str((s), (a))) -#define my_casedn_str(s, a) ((s)->casedn_str((s), (a))) -#define my_strcasecmp(s, a, b) ((s)->strcasecmp((s), (a), (b))) - -#define my_strntol(s, a, b, c, d, e) ((s)->strntol((s),(a),(b),(c),(d),(e))) -#define my_strntoul(s, a, b, c, d, e) ((s)->strntoul((s),(a),(b),(c),(d),(e))) -#define my_strntoll(s, a, b, c, d, e) ((s)->strntoll((s),(a),(b),(c),(d),(e))) -#define my_strntoull(s, a, b, c,d, e) ((s)->strntoull((s),(a),(b),(c),(d),(e))) -#define my_strntod(s, a, b, c, d) ((s)->strntod((s),(a),(b),(c),(d))) +#define my_caseup(s, a, l) ((s)->cset->caseup((s), (a), (l))) +#define my_casedn(s, a, l) ((s)->cset->casedn((s), (a), (l))) +#define my_caseup_str(s, a) ((s)->cset->caseup_str((s), (a))) +#define my_casedn_str(s, a) ((s)->cset->casedn_str((s), (a))) +#define my_strntol(s, a, b, c, d, e) ((s)->cset->strntol((s),(a),(b),(c),(d),(e))) +#define my_strntoul(s, a, b, c, d, e) ((s)->cset->strntoul((s),(a),(b),(c),(d),(e))) +#define my_strntoll(s, a, b, c, d, e) ((s)->cset->strntoll((s),(a),(b),(c),(d),(e))) +#define my_strntoull(s, a, b, c,d, e) ((s)->cset->strntoull((s),(a),(b),(c),(d),(e))) +#define my_strntod(s, a, b, c, d) ((s)->cset->strntod((s),(a),(b),(c),(d))) /* XXX: still need to take care of this one */ diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c index 3eb25aefe0e..f4ee39e55ca 100644 --- a/myisam/mi_unique.c +++ b/myisam/mi_unique.c @@ -109,7 +109,7 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record) if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) { ulong nr=1, nr2=4; - keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2); + keyseg->charset->coll->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2); crc=nr; } else diff --git a/mysys/charset.c b/mysys/charset.c index af4d3620df2..f5d07403948 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -120,45 +120,15 @@ static void simple_cs_init_functions(CHARSET_INFO *cs) if (cs->state & MY_CS_BINSORT) { - CHARSET_INFO *b= &my_charset_bin; - cs->strnxfrm = b->strnxfrm; - cs->like_range = b->like_range; - cs->wildcmp = b->wildcmp; - cs->strnncoll = b->strnncoll; - cs->strnncollsp = b->strnncollsp; - cs->strcasecmp = b->strcasecmp; - cs->hash_sort = b->hash_sort; + cs->coll= &my_collation_bin_handler; } else { - cs->strnxfrm = my_strnxfrm_simple; - cs->like_range = my_like_range_simple; - cs->wildcmp = my_wildcmp_8bit; - cs->strnncoll = my_strnncoll_simple; - cs->strnncollsp = my_strnncollsp_simple; - cs->strcasecmp = my_strcasecmp_8bit; - cs->hash_sort = my_hash_sort_simple; + cs->coll= &my_collation_8bit_simple_ci_handler; } - cs->caseup_str = my_caseup_str_8bit; - cs->casedn_str = my_casedn_str_8bit; - cs->caseup = my_caseup_8bit; - cs->casedn = my_casedn_8bit; - cs->mb_wc = my_mb_wc_8bit; - cs->wc_mb = my_wc_mb_8bit; - cs->snprintf = my_snprintf_8bit; - cs->long10_to_str= my_long10_to_str_8bit; - cs->longlong10_to_str= my_longlong10_to_str_8bit; - cs->fill = my_fill_8bit; - cs->strntol = my_strntol_8bit; - cs->strntoul = my_strntoul_8bit; - cs->strntoll = my_strntoll_8bit; - cs->strntoull = my_strntoull_8bit; - cs->strntod = my_strntod_8bit; - cs->scan = my_scan_8bit; + cs->cset= &my_charset_8bit_handler; cs->mbmaxlen = 1; - cs->numchars = my_numchars_8bit; - cs->charpos = my_charpos_8bit; } @@ -329,10 +299,10 @@ static int add_collation(CHARSET_INFO *cs) if (!(all_charsets[cs->number]->state & MY_CS_COMPILED)) { + simple_cs_init_functions(all_charsets[cs->number]); simple_cs_copy_data(all_charsets[cs->number],cs); if (simple_cs_is_full(all_charsets[cs->number])) { - simple_cs_init_functions(all_charsets[cs->number]); all_charsets[cs->number]->state |= MY_CS_LOADED; } } diff --git a/mysys/hash.c b/mysys/hash.c index 9169613c39f..0b2dbc484bc 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -36,7 +36,7 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); static uint calc_hash(HASH *hash,const byte *key,uint length) { ulong nr1=1, nr2=4; - hash->charset->hash_sort(hash->charset,key,length,&nr1,&nr2); + hash->charset->coll->hash_sort(hash->charset,key,length,&nr1,&nr2); return nr1; } diff --git a/sql/field.cc b/sql/field.cc index 3288aa2c4c7..7da9c9309cb 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -932,7 +932,7 @@ void Field_decimal::sql_type(String &res) const tmp--; if (dec) tmp--; - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "decimal(%d,%d)",tmp,dec)); add_zerofill_and_unsigned(res); } @@ -1100,9 +1100,11 @@ String *Field_tiny::val_str(String *val_buffer, char *to=(char*) val_buffer->ptr(); if (unsigned_flag) - length= (uint) cs->long10_to_str(cs,to,mlength, 10,(long) *((uchar*) ptr)); + length= (uint) cs->cset->long10_to_str(cs,to,mlength, 10, + (long) *((uchar*) ptr)); else - length= (uint) cs->long10_to_str(cs,to,mlength,-10,(long) *((signed char*) ptr)); + length= (uint) cs->cset->long10_to_str(cs,to,mlength,-10, + (long) *((signed char*) ptr)); val_buffer->length(length); if (zerofill) @@ -1135,7 +1137,7 @@ void Field_tiny::sort_string(char *to,uint length __attribute__((unused))) void Field_tiny::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "tinyint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -1345,9 +1347,10 @@ String *Field_short::val_str(String *val_buffer, shortget(j,ptr); if (unsigned_flag) - length=(uint) cs->long10_to_str(cs, to, mlength, 10, (long) (uint16) j); + length=(uint) cs->cset->long10_to_str(cs, to, mlength, 10, + (long) (uint16) j); else - length=(uint) cs->long10_to_str(cs, to, mlength,-10, (long) j); + length=(uint) cs->cset->long10_to_str(cs, to, mlength,-10, (long) j); val_buffer->length(length); if (zerofill) prepend_zeros(val_buffer); @@ -1408,7 +1411,7 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused))) void Field_short::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "smallint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -1583,7 +1586,7 @@ String *Field_medium::val_str(String *val_buffer, char *to=(char*) val_buffer->ptr(); long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr); - length=(uint) cs->long10_to_str(cs,to,mlength,-10,j); + length=(uint) cs->cset->long10_to_str(cs,to,mlength,-10,j); val_buffer->length(length); if (zerofill) prepend_zeros(val_buffer); /* purecov: inspected */ @@ -1627,7 +1630,7 @@ void Field_medium::sort_string(char *to,uint length __attribute__((unused))) void Field_medium::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "mediumint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -1643,7 +1646,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) int error= 0; char *end; - tmp= cs->scan(cs, from, from+len, MY_SEQ_SPACES); + tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); len-= tmp; from+= tmp; my_errno=0; @@ -1821,9 +1824,9 @@ String *Field_long::val_str(String *val_buffer, longget(j,ptr); if (unsigned_flag) - length=cs->long10_to_str(cs,to,mlength, 10,(long) (uint32)j); + length=cs->cset->long10_to_str(cs,to,mlength, 10,(long) (uint32)j); else - length=cs->long10_to_str(cs,to,mlength,-10,(long) j); + length=cs->cset->long10_to_str(cs,to,mlength,-10,(long) j); val_buffer->length(length); if (zerofill) prepend_zeros(val_buffer); @@ -1886,7 +1889,7 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused))) void Field_long::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "int(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -1901,7 +1904,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) int error= 0; char *end; - tmp= cs->scan(cs, from, from+len, MY_SEQ_SPACES); + tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); len-= (uint)tmp; from+= tmp; my_errno=0; @@ -2045,7 +2048,7 @@ String *Field_longlong::val_str(String *val_buffer, #endif longlongget(j,ptr); - length=(uint) (cs->longlong10_to_str)(cs,to,mlength, + length=(uint) (cs->cset->longlong10_to_str)(cs,to,mlength, unsigned_flag ? 10 : -10, j); val_buffer->length(length); if (zerofill) @@ -2119,7 +2122,7 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused))) void Field_longlong::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "bigint(%d)",(int) field_length)); add_zerofill_and_unsigned(res); } @@ -2391,7 +2394,7 @@ void Field_float::sql_type(String &res) const else { CHARSET_INFO *cs= res.charset(); - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "float(%d,%d)",(int) field_length,dec)); } add_zerofill_and_unsigned(res); @@ -2648,7 +2651,7 @@ void Field_double::sql_type(String &res) const } else { - res.length(cs->snprintf(cs,(char*) res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(), "double(%d,%d)",(int) field_length,dec)); } add_zerofill_and_unsigned(res); @@ -3281,7 +3284,7 @@ String *Field_year::val_str(String *val_buffer, void Field_year::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - res.length(cs->snprintf(cs,(char*)res.ptr(),res.alloced_length(), + res.length(cs->cset->snprintf(cs,(char*)res.ptr(),res.alloced_length(), "year(%d)",(int) field_length)); } @@ -3898,7 +3901,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { memcpy(ptr,from,length); if (length < field_length) - field_charset->fill(field_charset,ptr+length,field_length-length,' '); + field_charset->cset->fill(field_charset,ptr+length,field_length-length,' '); } else { @@ -3907,7 +3910,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { // Check if we loosed some info const char *end=from+length; from+= field_length; - from+= field_charset->scan(field_charset, from, end, MY_SEQ_SPACES); + from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); if (from != end) { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); @@ -3934,7 +3937,7 @@ int Field_string::store(longlong nr) char buff[64]; int l; CHARSET_INFO *cs=charset(); - l= (cs->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr); + l= (cs->cset->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr); return Field_string::store(buff,(uint)l,cs); } @@ -3977,11 +3980,11 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr) We have to remove end space to be able to compare multi-byte-characters like in latin_de 'ae' and 0xe4 */ - return field_charset->strnncollsp(field_charset, + return field_charset->coll->strnncollsp(field_charset, (const uchar*) a_ptr, field_length, (const uchar*) b_ptr, field_length); } - return field_charset->strnncoll(field_charset, + return field_charset->coll->strnncoll(field_charset, (const uchar*) a_ptr, field_length, (const uchar*) b_ptr, field_length); } @@ -3999,7 +4002,7 @@ void Field_string::sort_string(char *to,uint length) void Field_string::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - ulong length= cs->snprintf(cs,(char*) res.ptr(), + ulong length= cs->cset->snprintf(cs,(char*) res.ptr(), res.alloced_length(), "%s(%d)", (field_length > 3 && (table->db_options_in_use & @@ -4112,7 +4115,7 @@ int Field_varstring::store(longlong nr) char buff[64]; int l; CHARSET_INFO *cs=charset(); - l= (cs->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr); + l= (cs->cset->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr); return Field_varstring::store(buff,(uint)l,cs); } @@ -4169,7 +4172,7 @@ void Field_varstring::sort_string(char *to,uint length) void Field_varstring::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - ulong length= cs->snprintf(cs,(char*) res.ptr(), + ulong length= cs->cset->snprintf(cs,(char*) res.ptr(), res.alloced_length(),"varchar(%u)", field_length); res.length(length); diff --git a/sql/field.h b/sql/field.h index 7d4abbd1d41..3f3e32af285 100644 --- a/sql/field.h +++ b/sql/field.h @@ -788,7 +788,7 @@ public: enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } bool zero_pack() const { return 0; } - void reset(void) { charset()->fill(charset(),ptr,field_length,' '); } + void reset(void) { charset()->cset->fill(charset(),ptr,field_length,' '); } int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 7392ef6c276..4f55357f288 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1491,7 +1491,7 @@ bool Item_func_in::nulls_in_row() static int srtcmp_in(const String *x,const String *y) { CHARSET_INFO *cs= x->charset(); - return cs->strnncollsp(cs, + return cs->coll->strnncollsp(cs, (unsigned char *) x->ptr(),x->length(), (unsigned char *) y->ptr(),y->length()); } @@ -1499,7 +1499,7 @@ static int srtcmp_in(const String *x,const String *y) static int bincmp_in(const String *x,const String *y) { CHARSET_INFO *cs= &my_charset_bin; - return cs->strnncollsp(cs, + return cs->coll->strnncollsp(cs, (unsigned char *) x->ptr(),x->length(), (unsigned char *) y->ptr(),y->length()); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index eb34c8691a3..ae48aeb115a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1489,7 +1489,7 @@ String *Item_func_user::val_str(String *str) null_value=1; return 0; } - res_length=cs->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s", + res_length=cs->cset->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s", thd->user, host); str->length(res_length); str->set_charset(cs); @@ -2133,7 +2133,7 @@ String *Item_func_conv_charset3::val_str(String *str) while (1) { - cnvres=from_charset->mb_wc(from_charset,&wc,s,se); + cnvres=from_charset->cset->mb_wc(from_charset,&wc,s,se); if (cnvres>0) { s+=cnvres; @@ -2147,7 +2147,7 @@ String *Item_func_conv_charset3::val_str(String *str) break; outp: - cnvres=to_charset->wc_mb(to_charset,wc,d,de); + cnvres=to_charset->cset->wc_mb(to_charset,wc,d,de); if (cnvres>0) { d+=cnvres; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 997247b6141..61c869cddba 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -511,7 +511,7 @@ void Item_func_curtime::fix_length_and_dec() (ulong) (((uint) start->tm_min)*100L+ (uint) start->tm_sec)); - buff_length=cs->snprintf(cs,buff,sizeof(buff),"%02d:%02d:%02d", + buff_length=cs->cset->snprintf(cs,buff,sizeof(buff),"%02d:%02d:%02d", (int) start->tm_hour, (int) start->tm_min, (int) start->tm_sec); @@ -543,7 +543,7 @@ void Item_func_now::fix_length_and_dec() (ulong) (((uint) start->tm_min)*100L+ (uint) start->tm_sec))); - buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff), + buff_length= (uint) cs->cset->snprintf(cs,buff, sizeof(buff), "%04d-%02d-%02d %02d:%02d:%02d", ((int) (start->tm_year+1900)) % 10000, (int) start->tm_mon+1, @@ -950,7 +950,7 @@ String *Item_func_from_unixtime::val_str(String *str) l=20*cs->mbmaxlen+32; if (str->alloc(l)) return str; /* purecov: inspected */ - l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d", + l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d", (int) start->tm_year+1900, (int) start->tm_mon+1, (int) start->tm_mday, @@ -1134,7 +1134,7 @@ String *Item_date_add_interval::val_str(String *str) l=11*cs->mbmaxlen+32; if (str->alloc(l)) goto null_date; - l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d", + l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d", ltime.year,ltime.month,ltime.day); str->length(l); } @@ -1143,7 +1143,7 @@ String *Item_date_add_interval::val_str(String *str) l=20*cs->mbmaxlen+32; if (str->alloc(l)) goto null_date; - l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d", + l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d", ltime.year,ltime.month,ltime.day, ltime.hour,ltime.minute,ltime.second); str->length(l); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 126fb84d6d9..6077c42bd1d 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -101,7 +101,7 @@ bool String::set(longlong num, CHARSET_INFO *cs) if (alloc(l)) return TRUE; - str_length=(uint32) (cs->longlong10_to_str)(cs,Ptr,l,-10,num); + str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,-10,num); str_charset=cs; return FALSE; } @@ -112,7 +112,7 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) if (alloc(l)) return TRUE; - str_length=(uint32) (cs->longlong10_to_str)(cs,Ptr,l,10,num); + str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,10,num); str_charset=cs; return FALSE; } @@ -396,13 +396,13 @@ bool String::append(IO_CACHE* file, uint32 arg_length) uint32 String::numchars() { - return str_charset->numchars(str_charset, Ptr, Ptr+str_length); + return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length); } int String::charpos(int i,uint32 offset) { if (i<0) return i; - return str_charset->charpos(str_charset,Ptr+offset,Ptr+str_length,i); + return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i); } int String::strstr(const String &s,uint32 offset) @@ -580,7 +580,7 @@ void String::qs_append(const char &c) int sortcmp(const String *x,const String *y, CHARSET_INFO *cs) { - return cs->strnncollsp(cs, + return cs->coll->strnncollsp(cs, (unsigned char *) x->ptr(),x->length(), (unsigned char *) y->ptr(),y->length()); } @@ -639,7 +639,7 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, while (1) { - if ((cnvres=from_cs->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0) + if ((cnvres=from_cs->cset->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0) from+= cnvres; else if (cnvres == MY_CS_ILSEQ) { @@ -650,7 +650,7 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, break; // Impossible char. outp: - if ((cnvres= to_cs->wc_mb(to_cs, wc, (uchar*) to, to_end)) > 0) + if ((cnvres= to_cs->cset->wc_mb(to_cs, wc, (uchar*) to, to_end)) > 0) to+= cnvres; else if (cnvres == MY_CS_ILUNI && wc != '?') { diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index ec723e8690a..3f7218b20fc 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6226,6 +6226,42 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), return 2; } +static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler = +{ + my_strnncoll_big5, + my_strnncollsp_big5, + my_strnxfrm_big5, + my_like_range_big5, + my_wildcmp_mb, + my_strcasecmp_mb, + my_hash_sort_simple +}; + +static MY_CHARSET_HANDLER my_charset_big5_handler= +{ + ismbchar_big5, + mbcharlen_big5, + my_numchars_mb, + my_charpos_mb, + my_mb_wc_big5, /* mb_wc */ + my_wc_mb_big5, /* wc_mb */ + my_caseup_str_mb, + my_casedn_str_mb, + my_caseup_mb, + my_casedn_mb, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + CHARSET_INFO my_charset_big5_chinese_ci = { 1,0,0, /* number */ @@ -6241,37 +6277,12 @@ CHARSET_INFO my_charset_big5_chinese_ci = NULL, /* tab_from_uni */ "","", 1, /* strxfrm_multiply */ - my_strnncoll_big5, - my_strnncollsp_big5, - my_strnxfrm_big5, - my_like_range_big5, - my_wildcmp_mb, 2, /* mbmaxlen */ - ismbchar_big5, - mbcharlen_big5, - my_numchars_mb, - my_charpos_mb, - my_mb_wc_big5, /* mb_wc */ - my_wc_mb_big5, /* wc_mb */ - my_caseup_str_mb, - my_casedn_str_mb, - my_caseup_mb, - my_casedn_mb, - my_strcasecmp_mb, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_big5_handler, + &my_collation_big5_chinese_ci_handler }; + #endif diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 77152db845c..ebe73016db7 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -262,6 +262,42 @@ static int my_strnxfrm_bin(CHARSET_INFO *cs __attribute__((unused)), return len; } + +MY_COLLATION_HANDLER my_collation_bin_handler = +{ + my_strnncoll_binary, + my_strnncollsp_binary, + my_strnxfrm_bin, + my_like_range_simple, + my_wildcmp_bin, + my_strcasecmp_bin, + my_hash_sort_bin +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + NULL, /* ismbchar */ + NULL, /* mbcharlen */ + my_numchars_8bit, + my_charpos_8bit, + my_mb_wc_bin, + my_wc_mb_bin, + my_caseup_str_bin, + my_casedn_str_bin, + my_caseup_bin, + my_casedn_bin, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + CHARSET_INFO my_charset_bin = { 63,0,0, /* number */ @@ -277,33 +313,8 @@ CHARSET_INFO my_charset_bin = NULL, /* tab_from_uni */ "","", 0, /* strxfrm_multiply */ - my_strnncoll_binary, /* strnncoll */ - my_strnncollsp_binary, - my_strnxfrm_bin, /* strxnfrm */ - my_like_range_simple, /* like_range */ - my_wildcmp_bin, /* wildcmp */ 1, /* mbmaxlen */ - NULL, /* ismbchar */ - NULL, /* mbcharlen */ - my_numchars_8bit, - my_charpos_8bit, - my_mb_wc_bin, /* mb_wc */ - my_wc_mb_bin, /* wc_mb */ - my_caseup_str_bin, /* caseup_str */ - my_casedn_str_bin, /* casedn_str */ - my_caseup_bin, /* caseup */ - my_casedn_bin, /* casedn */ - my_strcasecmp_bin, /* strcasecmp */ - my_hash_sort_bin, /* hash_sort */ (char) 255, /* max_sort_char */ - my_snprintf_8bit, /* snprintf */ - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_bin_handler }; diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c index 788cd96ad13..fc3ff137778 100644 --- a/strings/ctype-czech.c +++ b/strings/ctype-czech.c @@ -604,6 +604,16 @@ int my_strnncollsp_czech(CHARSET_INFO * cs, return my_strnncoll_czech(cs,s,slen,t,tlen); } +static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler = +{ + my_strnncoll_czech, + my_strnncollsp_czech, + my_strnxfrm_czech, + my_like_range_czech, + my_wildcmp_8bit, + my_strcasecmp_8bit, + my_hash_sort_simple, +}; CHARSET_INFO my_charset_latin2_czech_ci = { @@ -620,37 +630,13 @@ CHARSET_INFO my_charset_latin2_czech_ci = idx_uni_8859_2, /* tab_from_uni */ "","", 4, /* strxfrm_multiply */ - my_strnncoll_czech, - my_strnncollsp_czech, - my_strnxfrm_czech, - my_like_range_czech, - my_wildcmp_8bit, 1, /* mbmaxlen */ - NULL, /* ismbchar */ - NULL, /* mbcharlen */ - my_numchars_8bit, - my_charpos_8bit, - my_mb_wc_8bit, /* mb_wc */ - my_wc_mb_8bit, /* wc_mb */ - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, - my_strcasecmp_8bit, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_8bit_handler, + &my_collation_latin2_czech_ci_handler }; + #endif #endif diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 3bf689910e6..8c5b394cc1f 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8634,6 +8634,43 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)), return 2; } + +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_simple,/* strnncoll */ + my_strnncollsp_simple, + my_strnxfrm_simple, /* strnxfrm */ + my_like_range_simple,/* like_range */ + my_wildcmp_mb, /* wildcmp */ + my_strcasecmp_mb, + my_hash_sort_simple, +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + ismbchar_euc_kr, + mbcharlen_euc_kr, + my_numchars_mb, + my_charpos_mb, + my_mb_wc_euc_kr, /* mb_wc */ + my_wc_mb_euc_kr, /* wc_mb */ + my_caseup_str_mb, + my_casedn_str_mb, + my_caseup_mb, + my_casedn_mb, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + + CHARSET_INFO my_charset_euckr_korean_ci = { 19,0,0, /* number */ @@ -8649,35 +8686,10 @@ CHARSET_INFO my_charset_euckr_korean_ci = NULL, /* tab_from_uni */ "","", 0, /* strxfrm_multiply */ - my_strnncoll_simple,/* strnncoll */ - my_strnncollsp_simple, - my_strnxfrm_simple, /* strnxfrm */ - my_like_range_simple,/* like_range */ - my_wildcmp_mb, /* wildcmp */ 2, /* mbmaxlen */ - ismbchar_euc_kr, - mbcharlen_euc_kr, - my_numchars_mb, - my_charpos_mb, - my_mb_wc_euc_kr, /* mb_wc */ - my_wc_mb_euc_kr, /* wc_mb */ - my_caseup_str_mb, - my_casedn_str_mb, - my_caseup_mb, - my_casedn_mb, - my_strcasecmp_mb, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler }; #endif diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c index 40d2b7ab1da..55bfa09ea5f 100644 --- a/strings/ctype-extra.c +++ b/strings/ctype-extra.c @@ -32,35 +32,9 @@ CHARSET_INFO compiled_charsets[] = { NULL, /* tab_from_uni */ "","", 0, - NULL, /* strnncoll */ - NULL, /* strnncollsp */ - NULL, /* strnxfrm */ - NULL, /* like_range */ - NULL, /* wildcmp */ 0, - NULL, - NULL, - NULL, - NULL, - NULL, /* mb_wc */ - NULL, /* wc_mb */ - - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* hash_sort */ 0, NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, NULL } }; diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 20e1ce888e8..b3aa58bb38a 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5684,6 +5684,43 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)), return 2; } + +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_simple,/* strnncoll */ + my_strnncollsp_simple, + my_strnxfrm_simple, /* strnxfrm */ + my_like_range_simple,/* like_range */ + my_wildcmp_mb, /* wildcmp */ + my_strcasecmp_mb, + my_hash_sort_simple, +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + ismbchar_gb2312, + mbcharlen_gb2312, + my_numchars_mb, + my_charpos_mb, + my_mb_wc_gb2312, /* mb_wc */ + my_wc_mb_gb2312, /* wc_mb */ + my_caseup_str_mb, + my_casedn_str_mb, + my_caseup_mb, + my_casedn_mb, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + + CHARSET_INFO my_charset_gb2312_chinese_ci = { 24,0,0, /* number */ @@ -5699,35 +5736,10 @@ CHARSET_INFO my_charset_gb2312_chinese_ci = NULL, /* tab_from_uni */ "","", 0, /* strxfrm_multiply */ - my_strnncoll_simple,/* strnncoll */ - my_strnncollsp_simple, - my_strnxfrm_simple, /* strnxfrm */ - my_like_range_simple,/* like_range */ - my_wildcmp_mb, /* wildcmp */ 2, /* mbmaxlen */ - ismbchar_gb2312, - mbcharlen_gb2312, - my_numchars_mb, - my_charpos_mb, - my_mb_wc_gb2312, /* mb_wc */ - my_wc_mb_gb2312, /* wc_mb */ - my_caseup_str_mb, - my_casedn_str_mb, - my_caseup_mb, - my_casedn_mb, - my_strcasecmp_mb, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler }; #endif diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index ec0cc01881b..9d249143db8 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9881,6 +9881,43 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)), } + +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_gbk, + my_strnncollsp_gbk, + my_strnxfrm_gbk, + my_like_range_gbk, + my_wildcmp_mb, + my_strcasecmp_mb, + my_hash_sort_simple, +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + ismbchar_gbk, + mbcharlen_gbk, + my_numchars_mb, + my_charpos_mb, + my_mb_wc_gbk, + my_wc_mb_gbk, + my_caseup_str_mb, + my_casedn_str_mb, + my_caseup_mb, + my_casedn_mb, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + + CHARSET_INFO my_charset_gbk_chinese_ci = { 28,0,0, /* number */ @@ -9896,35 +9933,10 @@ CHARSET_INFO my_charset_gbk_chinese_ci = NULL, /* tab_from_uni */ "","", 1, /* strxfrm_multiply */ - my_strnncoll_gbk, - my_strnncollsp_gbk, - my_strnxfrm_gbk, - my_like_range_gbk, - my_wildcmp_mb, /* wildcmp */ 2, /* mbmaxlen */ - ismbchar_gbk, - mbcharlen_gbk, - my_numchars_mb, - my_charpos_mb, - my_mb_wc_gbk, /* mb_wc */ - my_wc_mb_gbk, /* wc_mb */ - my_caseup_str_mb, - my_casedn_str_mb, - my_caseup_mb, - my_casedn_mb, - my_strcasecmp_mb, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler }; diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 4340d0973aa..5ac60326e62 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -174,6 +174,30 @@ int my_wc_mb_latin1(CHARSET_INFO *cs __attribute__((unused)), return ((wc < 256) && ((str[0]=uni_latin1[wc]) || (!wc))) ? 1 : MY_CS_ILUNI; } +static MY_CHARSET_HANDLER my_charset_handler= +{ + NULL, + NULL, + my_numchars_8bit, + my_charpos_8bit, + my_mb_wc_latin1, + my_wc_mb_latin1, + my_caseup_str_8bit, + my_casedn_str_8bit, + my_caseup_8bit, + my_casedn_8bit, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + CHARSET_INFO my_charset_latin1 = { @@ -190,35 +214,10 @@ CHARSET_INFO my_charset_latin1 = NULL, /* tab_from_uni */ "","", 0, /* strxfrm_multiply */ - my_strnncoll_simple, - my_strnncollsp_simple, - my_strnxfrm_simple, - my_like_range_simple, - my_wildcmp_8bit, /* wildcmp */ 1, /* mbmaxlen */ - NULL, /* ismbchar */ - NULL, /* mbcharlen */ - my_numchars_8bit, - my_charpos_8bit, - my_mb_wc_latin1, /* mb_wc */ - my_wc_mb_latin1, /* wc_mb */ - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, - my_strcasecmp_8bit, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_8bit_simple_ci_handler }; @@ -428,6 +427,19 @@ static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)), return dest - dest_orig; } + +static MY_COLLATION_HANDLER my_collation_german2_ci_handler = +{ + my_strnncoll_latin1_de, + my_strnncollsp_latin1_de, + my_strnxfrm_latin1_de, + my_like_range_simple, + my_wildcmp_8bit, + my_strcasecmp_8bit, + my_hash_sort_simple +}; + + CHARSET_INFO my_charset_latin1_german2_ci = { 31,0,0, /* number */ @@ -443,34 +455,9 @@ CHARSET_INFO my_charset_latin1_german2_ci = NULL, /* tab_from_uni */ "","", 2, /* strxfrm_multiply */ - my_strnncoll_latin1_de, - my_strnncollsp_latin1_de, - my_strnxfrm_latin1_de, - my_like_range_simple, - my_wildcmp_8bit, /* wildcmp */ 1, /* mbmaxlen */ - NULL, /* ismbchar */ - NULL, /* mbcharlen */ - my_numchars_8bit, - my_charpos_8bit, - my_mb_wc_latin1, /* mb_wc */ - my_wc_mb_latin1, /* wc_mb */ - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, - my_strcasecmp_8bit, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_german2_ci_handler }; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 7d8f5b9535b..8f3e66f782e 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1019,3 +1019,38 @@ uint my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)), { return pos; } + +MY_CHARSET_HANDLER my_charset_8bit_handler= +{ + NULL, /* ismbchar */ + NULL, /* mbcharlen */ + my_numchars_8bit, + my_charpos_8bit, + my_mb_wc_8bit, + my_wc_mb_8bit, + my_caseup_str_8bit, + my_casedn_str_8bit, + my_caseup_8bit, + my_casedn_8bit, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + +MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler = +{ + my_strnncoll_simple, + my_strnncollsp_simple, + my_strnxfrm_simple, + my_like_range_simple, + my_wildcmp_8bit, + my_strcasecmp_8bit, + my_hash_sort_simple +}; diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 058558fa419..3e33fb3810a 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4468,6 +4468,43 @@ my_mb_wc_sjis(CHARSET_INFO *cs __attribute__((unused)), return 2; } + +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_sjis, + my_strnncollsp_sjis, + my_strnxfrm_sjis, + my_like_range_sjis, + my_wildcmp_mb, /* wildcmp */ + my_strcasecmp_8bit, + my_hash_sort_simple, +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + ismbchar_sjis, + mbcharlen_sjis, + my_numchars_mb, + my_charpos_mb, + my_mb_wc_sjis, /* mb_wc */ + my_wc_mb_sjis, /* wc_mb */ + my_caseup_str_8bit, + my_casedn_str_8bit, + my_caseup_8bit, + my_casedn_8bit, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + + CHARSET_INFO my_charset_sjis_japanese_ci = { 13,0,0, /* number */ @@ -4483,35 +4520,11 @@ CHARSET_INFO my_charset_sjis_japanese_ci = NULL, /* tab_from_uni */ "","", 1, /* strxfrm_multiply */ - my_strnncoll_sjis, - my_strnncollsp_sjis, - my_strnxfrm_sjis, - my_like_range_sjis, - my_wildcmp_mb, /* wildcmp */ 2, /* mbmaxlen */ - ismbchar_sjis, - mbcharlen_sjis, - my_numchars_mb, - my_charpos_mb, - my_mb_wc_sjis, /* mb_wc */ - my_wc_mb_sjis, /* wc_mb */ - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, - my_strcasecmp_8bit, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler + }; #endif diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 9fcecdfdffd..8574b3d7d84 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -688,6 +688,43 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length) } +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_tis620, + my_strnncollsp_tis620, + my_strnxfrm_tis620, + my_like_range_tis620, + my_wildcmp_8bit, /* wildcmp */ + my_strcasecmp_8bit, + my_hash_sort_simple, +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + NULL, /* ismbchar */ + NULL, /* mbcharlen */ + my_numchars_8bit, + my_charpos_8bit, + my_mb_wc_8bit, /* mb_wc */ + my_wc_mb_8bit, /* wc_mb */ + my_caseup_str_8bit, + my_casedn_str_8bit, + my_caseup_8bit, + my_casedn_8bit, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + + + CHARSET_INFO my_charset_tis620_thai_ci = { 18,0,0, /* number */ @@ -703,35 +740,10 @@ CHARSET_INFO my_charset_tis620_thai_ci = NULL, /* tab_from_uni */ "","", 4, /* strxfrm_multiply */ - my_strnncoll_tis620, - my_strnncollsp_tis620, - my_strnxfrm_tis620, - my_like_range_tis620, - my_wildcmp_8bit, /* wildcmp */ 1, /* mbmaxlen */ - NULL, /* ismbchar */ - NULL, /* mbcharlen */ - my_numchars_8bit, - my_charpos_8bit, - my_mb_wc_8bit, /* mb_wc */ - my_wc_mb_8bit, /* wc_mb */ - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, - my_strcasecmp_8bit, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler }; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index dae0632f754..3e3981f1be9 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -403,7 +403,7 @@ long my_strntol_ucs2(CHARSET_INFO *cs, *err= 0; do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { switch (wc) { @@ -438,7 +438,7 @@ bs: cutlim = (uint) (((ulong)~0L) % (unsigned long int) base); do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { s+=cnv; if ( wc>='0' && wc<='9') @@ -518,7 +518,7 @@ ulong my_strntoul_ucs2(CHARSET_INFO *cs, *err= 0; do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { switch (wc) { @@ -554,7 +554,7 @@ bs: do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { s+=cnv; if ( wc>='0' && wc<='9') @@ -628,7 +628,7 @@ longlong my_strntoll_ucs2(CHARSET_INFO *cs, *err= 0; do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { switch (wc) { @@ -663,7 +663,7 @@ bs: cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base); do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { s+=cnv; if ( wc>='0' && wc<='9') @@ -745,7 +745,7 @@ ulonglong my_strntoull_ucs2(CHARSET_INFO *cs, *err= 0; do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { switch (wc) { @@ -781,7 +781,7 @@ bs: do { - if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + if ((cnv=cs->cset->mb_wc(cs,&wc,s,e))>0) { s+=cnv; if ( wc>='0' && wc<='9') @@ -853,7 +853,7 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), length= sizeof(buf)-1; end= s+length; - while ((cnv=cs->mb_wc(cs,&wc,s,end)) > 0) + while ((cnv=cs->cset->mb_wc(cs,&wc,s,end)) > 0) { s+=cnv; if (wc > (int) (uchar) 'e' || !wc) @@ -913,7 +913,7 @@ int my_l10tostr_ucs2(CHARSET_INFO *cs, for ( db=dst, de=dst+len ; (dstwc_mb(cs,(my_wc_t)p[0],(uchar*) dst, (uchar*) de); + int cnvres=cs->cset->wc_mb(cs,(my_wc_t)p[0],(uchar*) dst, (uchar*) de); if (cnvres>0) dst+=cnvres; else @@ -972,7 +972,7 @@ cnv: for ( db=dst, de=dst+len ; (dstwc_mb(cs, (my_wc_t) p[0], (uchar*) dst, (uchar*) de); + int cnvres=cs->cset->wc_mb(cs, (my_wc_t) p[0], (uchar*) dst, (uchar*) de); if (cnvres>0) dst+=cnvres; else @@ -997,6 +997,44 @@ uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)), return pos*2; } + +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_ucs2, + my_strnncoll_ucs2, + my_strnxfrm_ucs2, + my_like_range_simple, + my_wildcmp_mb, + my_strcasecmp_ucs2, + my_hash_sort_ucs2 +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + my_ismbchar_ucs2, /* ismbchar */ + my_mbcharlen_ucs2, /* mbcharlen */ + my_numchars_ucs2, + my_charpos_ucs2, + my_ucs2_uni, /* mb_wc */ + my_uni_ucs2, /* wc_mb */ + my_caseup_str_ucs2, + my_casedn_str_ucs2, + my_caseup_ucs2, + my_casedn_ucs2, + my_snprintf_ucs2, + my_l10tostr_ucs2, + my_ll10tostr_ucs2, + my_fill_8bit, + my_strntol_ucs2, + my_strntoul_ucs2, + my_strntoll_ucs2, + my_strntoull_ucs2, + my_strntod_ucs2, + my_scan_8bit +}; + + + CHARSET_INFO my_charset_ucs2_general_ci = { 35,0,0, /* number */ @@ -1012,35 +1050,10 @@ CHARSET_INFO my_charset_ucs2_general_ci = NULL, /* tab_from_uni */ "","", 1, /* strxfrm_multiply */ - my_strnncoll_ucs2, /* strnncoll */ - my_strnncoll_ucs2, - my_strnxfrm_ucs2, /* strnxfrm */ - my_like_range_simple,/* like_range */ - my_wildcmp_mb, /* wildcmp */ 2, /* mbmaxlen */ - my_ismbchar_ucs2, /* ismbchar */ - my_mbcharlen_ucs2, /* mbcharlen */ - my_numchars_ucs2, - my_charpos_ucs2, - my_ucs2_uni, /* mb_wc */ - my_uni_ucs2, /* wc_mb */ - my_caseup_str_ucs2, - my_casedn_str_ucs2, - my_caseup_ucs2, - my_casedn_ucs2, - my_strcasecmp_ucs2, - my_hash_sort_ucs2, /* hash_sort */ 0, - my_snprintf_ucs2, - my_l10tostr_ucs2, - my_ll10tostr_ucs2, - my_fill_8bit, - my_strntol_ucs2, - my_strntoul_ucs2, - my_strntoll_ucs2, - my_strntoull_ucs2, - my_strntod_ucs2, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler }; diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 76c69637906..bf81269059c 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8425,6 +8425,44 @@ my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e) return MY_CS_ILUNI; } + +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_simple,/* strnncoll */ + my_strnncollsp_simple, + my_strnxfrm_simple, /* strnxfrm */ + my_like_range_simple,/* like_range */ + my_wildcmp_mb, /* wildcmp */ + my_strcasecmp_mb, + my_hash_sort_simple, +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + ismbchar_ujis, + mbcharlen_ujis, + my_numchars_mb, + my_charpos_mb, + my_mb_wc_euc_jp, /* mb_wc */ + my_wc_mb_euc_jp, /* wc_mb */ + my_caseup_str_mb, + my_casedn_str_mb, + my_caseup_mb, + my_casedn_mb, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + + + CHARSET_INFO my_charset_ujis_japanese_ci = { 12,0,0, /* number */ @@ -8440,35 +8478,10 @@ CHARSET_INFO my_charset_ujis_japanese_ci = NULL, /* tab_from_uni */ "","", 0, /* strxfrm_multiply */ - my_strnncoll_simple,/* strnncoll */ - my_strnncollsp_simple, - my_strnxfrm_simple, /* strnxfrm */ - my_like_range_simple,/* like_range */ - my_wildcmp_mb, /* wildcmp */ 3, /* mbmaxlen */ - ismbchar_ujis, - mbcharlen_ujis, - my_numchars_mb, - my_charpos_mb, - my_mb_wc_euc_jp, /* mb_wc */ - my_wc_mb_euc_jp, /* wc_mb */ - my_caseup_str_mb, - my_casedn_str_mb, - my_caseup_mb, - my_casedn_mb, - my_strcasecmp_mb, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler }; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 9f08ca2e169..16e42385300 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1950,6 +1950,44 @@ static int my_mbcharlen_utf8(CHARSET_INFO *cs __attribute__((unused)) , uint c) return 0; /* Illegal mb head */; } + +static MY_COLLATION_HANDLER my_collation_ci_handler = +{ + my_strnncoll_utf8, + my_strnncollsp_utf8, + my_strnxfrm_utf8, + my_like_range_simple, + my_wildcmp_mb, + my_strcasecmp_utf8, + my_hash_sort_utf8 +}; + +static MY_CHARSET_HANDLER my_charset_handler= +{ + my_ismbchar_utf8, + my_mbcharlen_utf8, + my_numchars_mb, + my_charpos_mb, + my_utf8_uni, + my_uni_utf8, + my_caseup_str_utf8, + my_casedn_str_utf8, + my_caseup_utf8, + my_casedn_utf8, + my_snprintf_8bit, + my_long10_to_str_8bit, + my_longlong10_to_str_8bit, + my_fill_8bit, + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit, + my_scan_8bit +}; + + + CHARSET_INFO my_charset_utf8_general_ci = { 33,0,0, /* number */ @@ -1965,35 +2003,10 @@ CHARSET_INFO my_charset_utf8_general_ci = NULL, /* tab_from_uni */ "","", 1, /* strxfrm_multiply */ - my_strnncoll_utf8, /* strnncoll */ - my_strnncollsp_utf8, - my_strnxfrm_utf8, /* strnxfrm */ - my_like_range_simple,/* like_range */ - my_wildcmp_mb, /* wildcmp */ 3, /* mbmaxlen */ - my_ismbchar_utf8, /* ismbchar */ - my_mbcharlen_utf8, /* mbcharlen */ - my_numchars_mb, - my_charpos_mb, - my_utf8_uni, /* mb_wc */ - my_uni_utf8, /* wc_mb */ - my_caseup_str_utf8, - my_casedn_str_utf8, - my_caseup_utf8, - my_casedn_utf8, - my_strcasecmp_utf8, - my_hash_sort_utf8, /* hash_sort */ 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_handler, + &my_collation_ci_handler }; diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 87ba58d0553..af4faca46e1 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -640,6 +640,17 @@ static my_bool my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)), } +static MY_COLLATION_HANDLER my_collation_czech_ci_handler = +{ + my_strnncoll_win1250ch, + my_strnncollsp_win1250ch, + my_strnxfrm_win1250ch, + my_like_range_win1250ch, + my_wildcmp_8bit, + my_strcasecmp_8bit, + my_hash_sort_simple +}; + CHARSET_INFO my_charset_cp1250_czech_ci = { 34,0,0, /* number */ @@ -655,35 +666,10 @@ CHARSET_INFO my_charset_cp1250_czech_ci = idx_uni_cp1250, /* tab_from_uni */ "","", 2, /* strxfrm_multiply */ - my_strnncoll_win1250ch, - my_strnncollsp_win1250ch, - my_strnxfrm_win1250ch, - my_like_range_win1250ch, - my_wildcmp_8bit, /* wildcmp */ 1, /* mbmaxlen */ - NULL, /* ismbchar */ - NULL, /* mbcharlen */ - my_numchars_8bit, - my_charpos_8bit, - my_mb_wc_8bit, /* mb_wc */ - my_wc_mb_8bit, /* wc_mb */ - my_caseup_str_8bit, - my_casedn_str_8bit, - my_caseup_8bit, - my_casedn_8bit, - my_strcasecmp_8bit, - my_hash_sort_simple, 0, - my_snprintf_8bit, - my_long10_to_str_8bit, - my_longlong10_to_str_8bit, - my_fill_8bit, - my_strntol_8bit, - my_strntoul_8bit, - my_strntoll_8bit, - my_strntoull_8bit, - my_strntod_8bit, - my_scan_8bit + &my_charset_8bit_handler, + &my_collation_czech_ci_handler }; From afc839691988a185e35f59dedef2f6630d9bbe4e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 18:39:55 +0500 Subject: [PATCH 220/399] BINARY collations for every character set --- mysys/charset.c | 13 +++++++++++- sql/share/charsets/Index.xml | 39 ++++++++++++++++++++++++++++++++++-- strings/ctype-big5.c | 27 +++++++++++++++++++++++-- strings/ctype-euc_kr.c | 28 ++++++++++++++++++++++++-- strings/ctype-gb2312.c | 27 +++++++++++++++++++++++-- strings/ctype-gbk.c | 27 +++++++++++++++++++++++-- strings/ctype-latin1.c | 29 ++++++++++++++++++++++++--- strings/ctype-sjis.c | 26 ++++++++++++++++++++++-- strings/ctype-tis620.c | 27 +++++++++++++++++++++++-- strings/ctype-ucs2.c | 28 ++++++++++++++++++++++++-- strings/ctype-ujis.c | 24 +++++++++++++++++++++- strings/ctype-utf8.c | 28 ++++++++++++++++++++++++-- 12 files changed, 300 insertions(+), 23 deletions(-) diff --git a/mysys/charset.c b/mysys/charset.c index f5d07403948..82bace7fb2c 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -395,13 +395,16 @@ CHARSET_INFO *default_charset_info = &my_charset_latin1; static my_bool init_compiled_charsets(myf flags __attribute__((unused))) { CHARSET_INFO *cs; + + MY_ADD_CHARSET(&my_charset_bin); MY_ADD_CHARSET(&my_charset_latin1); - MY_ADD_CHARSET(&my_charset_bin); + MY_ADD_CHARSET(&my_charset_latin1_bin); MY_ADD_CHARSET(&my_charset_latin1_german2_ci); #ifdef HAVE_CHARSET_big5 MY_ADD_CHARSET(&my_charset_big5_chinese_ci); + MY_ADD_CHARSET(&my_charset_big5_bin); #endif #ifdef HAVE_CHARSET_czech @@ -410,34 +413,42 @@ static my_bool init_compiled_charsets(myf flags __attribute__((unused))) #ifdef HAVE_CHARSET_euc_kr MY_ADD_CHARSET(&my_charset_euckr_korean_ci); + MY_ADD_CHARSET(&my_charset_euckr_bin); #endif #ifdef HAVE_CHARSET_gb2312 MY_ADD_CHARSET(&my_charset_gb2312_chinese_ci); + MY_ADD_CHARSET(&my_charset_gb2312_bin); #endif #ifdef HAVE_CHARSET_gbk MY_ADD_CHARSET(&my_charset_gbk_chinese_ci); + MY_ADD_CHARSET(&my_charset_gbk_bin); #endif #ifdef HAVE_CHARSET_sjis MY_ADD_CHARSET(&my_charset_sjis_japanese_ci); + MY_ADD_CHARSET(&my_charset_sjis_bin); #endif #ifdef HAVE_CHARSET_tis620 MY_ADD_CHARSET(&my_charset_tis620_thai_ci); + MY_ADD_CHARSET(&my_charset_tis620_bin); #endif #ifdef HAVE_CHARSET_ucs2 MY_ADD_CHARSET(&my_charset_ucs2_general_ci); + MY_ADD_CHARSET(&my_charset_ucs2_bin); #endif #ifdef HAVE_CHARSET_ujis MY_ADD_CHARSET(&my_charset_ujis_japanese_ci); + MY_ADD_CHARSET(&my_charset_ujis_bin); #endif #ifdef HAVE_CHARSET_utf8 MY_ADD_CHARSET(&my_charset_utf8_general_ci); + MY_ADD_CHARSET(&my_charset_utf8_bin); #endif #ifdef HAVE_CHARSET_win1250ch diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 1278cb6c54a..8c2b7a05d03 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -1,6 +1,6 @@ - + This file lists all of the available character sets. @@ -21,6 +21,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + @@ -96,7 +100,10 @@ To make maintaining easier please: - + + binary + compiled + Dutch English @@ -173,6 +180,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + @@ -185,6 +196,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + @@ -242,6 +257,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + @@ -253,6 +272,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + @@ -293,6 +316,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + @@ -333,6 +360,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + @@ -386,6 +417,10 @@ To make maintaining easier please: primary compiled + + binary + compiled + diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 3f7218b20fc..10b6898ce24 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6262,7 +6262,7 @@ static MY_CHARSET_HANDLER my_charset_big5_handler= my_scan_8bit }; -CHARSET_INFO my_charset_big5_chinese_ci = +CHARSET_INFO my_charset_big5_chinese_ci= { 1,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ @@ -6275,7 +6275,8 @@ CHARSET_INFO my_charset_big5_chinese_ci = sort_order_big5, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 1, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, @@ -6284,5 +6285,27 @@ CHARSET_INFO my_charset_big5_chinese_ci = }; +CHARSET_INFO my_charset_big5_bin= +{ + 84,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "big5", /* cs name */ + "big5_bin", /* name */ + "", /* comment */ + ctype_big5, + to_lower_big5, + to_upper_big5, + sort_order_big5, + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 2, /* mbmaxlen */ + 0, + &my_charset_big5_handler, + &my_collation_bin_handler +}; + #endif diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 8c5b394cc1f..4a5757bf5c4 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8671,7 +8671,7 @@ static MY_CHARSET_HANDLER my_charset_handler= }; -CHARSET_INFO my_charset_euckr_korean_ci = +CHARSET_INFO my_charset_euckr_korean_ci= { 19,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */ @@ -8684,7 +8684,8 @@ CHARSET_INFO my_charset_euckr_korean_ci = sort_order_euc_kr, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 0, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, @@ -8692,4 +8693,27 @@ CHARSET_INFO my_charset_euckr_korean_ci = &my_collation_ci_handler }; + +CHARSET_INFO my_charset_euckr_bin= +{ + 85,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "euckr", /* cs name */ + "euckr_bin", /* name */ + "", /* comment */ + ctype_euc_kr, + to_lower_euc_kr, + to_upper_euc_kr, + sort_order_euc_kr, + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 2, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler +}; + #endif diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index b3aa58bb38a..378931eecc7 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5721,7 +5721,7 @@ static MY_CHARSET_HANDLER my_charset_handler= }; -CHARSET_INFO my_charset_gb2312_chinese_ci = +CHARSET_INFO my_charset_gb2312_chinese_ci= { 24,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */ @@ -5734,7 +5734,8 @@ CHARSET_INFO my_charset_gb2312_chinese_ci = sort_order_gb2312, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 0, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, @@ -5742,4 +5743,26 @@ CHARSET_INFO my_charset_gb2312_chinese_ci = &my_collation_ci_handler }; +CHARSET_INFO my_charset_gb2312_bin= +{ + 86,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "gb2312", /* cs name */ + "gb2312_bin", /* name */ + "", /* comment */ + ctype_gb2312, + to_lower_gb2312, + to_upper_gb2312, + sort_order_gb2312, + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 2, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler +}; + #endif diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 9d249143db8..58d281ae485 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9918,7 +9918,7 @@ static MY_CHARSET_HANDLER my_charset_handler= }; -CHARSET_INFO my_charset_gbk_chinese_ci = +CHARSET_INFO my_charset_gbk_chinese_ci= { 28,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ @@ -9931,7 +9931,8 @@ CHARSET_INFO my_charset_gbk_chinese_ci = sort_order_gbk, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 1, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, @@ -9939,5 +9940,27 @@ CHARSET_INFO my_charset_gbk_chinese_ci = &my_collation_ci_handler }; +CHARSET_INFO my_charset_gbk_bin= +{ + 87,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "gbk", /* cs name */ + "gbk_bin", /* name */ + "", /* comment */ + ctype_gbk, + to_lower_gbk, + to_upper_gbk, + sort_order_gbk, + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 2, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler +}; + #endif diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 5ac60326e62..b0c60e2e3eb 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -199,7 +199,7 @@ static MY_CHARSET_HANDLER my_charset_handler= }; -CHARSET_INFO my_charset_latin1 = +CHARSET_INFO my_charset_latin1= { 8,0,0, /* number */ MY_CS_COMPILED | MY_CS_PRIMARY, /* state */ @@ -428,7 +428,7 @@ static int my_strnxfrm_latin1_de(CHARSET_INFO *cs __attribute__((unused)), } -static MY_COLLATION_HANDLER my_collation_german2_ci_handler = +static MY_COLLATION_HANDLER my_collation_german2_ci_handler= { my_strnncoll_latin1_de, my_strnncollsp_latin1_de, @@ -440,7 +440,7 @@ static MY_COLLATION_HANDLER my_collation_german2_ci_handler = }; -CHARSET_INFO my_charset_latin1_german2_ci = +CHARSET_INFO my_charset_latin1_german2_ci= { 31,0,0, /* number */ MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */ @@ -461,3 +461,26 @@ CHARSET_INFO my_charset_latin1_german2_ci = &my_collation_german2_ci_handler }; + +CHARSET_INFO my_charset_latin1_bin= +{ + 47,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "latin1", /* cs name */ + "latin1_bin", /* name */ + "", /* comment */ + ctype_latin1, + to_lower_latin1, + to_upper_latin1, + sort_order_latin1_de, + latin1_uni, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 1, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler +}; + diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 3e33fb3810a..00d51dd23b5 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4505,7 +4505,7 @@ static MY_CHARSET_HANDLER my_charset_handler= }; -CHARSET_INFO my_charset_sjis_japanese_ci = +CHARSET_INFO my_charset_sjis_japanese_ci= { 13,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ @@ -4518,13 +4518,35 @@ CHARSET_INFO my_charset_sjis_japanese_ci = sort_order_sjis, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 1, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, &my_charset_handler, &my_collation_ci_handler +}; +CHARSET_INFO my_charset_sjis_bin= +{ + 88,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "sjis", /* cs name */ + "sjis_bin", /* name */ + "", /* comment */ + ctype_sjis, + to_lower_sjis, + to_upper_sjis, + sort_order_sjis, + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 2, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler }; #endif diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 8574b3d7d84..ab51ddd013f 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -725,7 +725,7 @@ static MY_CHARSET_HANDLER my_charset_handler= -CHARSET_INFO my_charset_tis620_thai_ci = +CHARSET_INFO my_charset_tis620_thai_ci= { 18,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ @@ -738,7 +738,8 @@ CHARSET_INFO my_charset_tis620_thai_ci = sort_order_tis620, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 4, /* strxfrm_multiply */ 1, /* mbmaxlen */ 0, @@ -746,5 +747,27 @@ CHARSET_INFO my_charset_tis620_thai_ci = &my_collation_ci_handler }; +CHARSET_INFO my_charset_tis620_bin= +{ + 89,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "tis620", /* cs name */ + "tis620_bin", /* name */ + "", /* comment */ + ctype_tis620, + to_lower_tis620, + to_upper_tis620, + sort_order_tis620, + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 1, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler +}; + #endif diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 3e3981f1be9..17bc920a381 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1035,7 +1035,7 @@ static MY_CHARSET_HANDLER my_charset_handler= -CHARSET_INFO my_charset_ucs2_general_ci = +CHARSET_INFO my_charset_ucs2_general_ci= { 35,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE, /* state */ @@ -1048,7 +1048,8 @@ CHARSET_INFO my_charset_ucs2_general_ci = to_upper_ucs2, /* sort_order */ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 1, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, @@ -1057,4 +1058,27 @@ CHARSET_INFO my_charset_ucs2_general_ci = }; +CHARSET_INFO my_charset_ucs2_bin= +{ + 90,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE, /* state */ + "ucs2", /* cs name */ + "ucs2_bin", /* name */ + "", /* comment */ + ctype_ucs2, /* ctype */ + to_lower_ucs2, /* to_lower */ + to_upper_ucs2, /* to_upper */ + to_upper_ucs2, /* sort_order */ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 2, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler +}; + + #endif diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index bf81269059c..eb31c49013a 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8463,7 +8463,7 @@ static MY_CHARSET_HANDLER my_charset_handler= -CHARSET_INFO my_charset_ujis_japanese_ci = +CHARSET_INFO my_charset_ujis_japanese_ci= { 12,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */ @@ -8485,4 +8485,26 @@ CHARSET_INFO my_charset_ujis_japanese_ci = }; +CHARSET_INFO my_charset_ujis_bin= +{ + 91,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT, /* state */ + "ujis", /* cs name */ + "ujis_bin", /* name */ + "", /* comment */ + ctype_ujis, + to_lower_ujis, + to_upper_ujis, + sort_order_ujis, + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "","", + 0, /* strxfrm_multiply */ + 3, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_bin_handler +}; + + #endif diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 16e42385300..4d9c735de21 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1988,7 +1988,7 @@ static MY_CHARSET_HANDLER my_charset_handler= -CHARSET_INFO my_charset_utf8_general_ci = +CHARSET_INFO my_charset_utf8_general_ci= { 33,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE, /* state */ @@ -2001,7 +2001,8 @@ CHARSET_INFO my_charset_utf8_general_ci = to_upper_utf8, /* sort_order */ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + "", + "", 1, /* strxfrm_multiply */ 3, /* mbmaxlen */ 0, @@ -2010,6 +2011,29 @@ CHARSET_INFO my_charset_utf8_general_ci = }; +CHARSET_INFO my_charset_utf8_bin= +{ + 83,0,0, /* number */ + MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE, /* state */ + "utf8", /* cs name */ + "utf8_bin", /* name */ + "", /* comment */ + ctype_utf8, /* ctype */ + to_lower_utf8, /* to_lower */ + to_upper_utf8, /* to_upper */ + to_upper_utf8, /* sort_order */ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + "", + "", + 0, /* strxfrm_multiply */ + 3, /* mbmaxlen */ + 0, + &my_charset_handler, + &my_collation_ci_handler +}; + + #ifdef MY_TEST_UTF8 #include From bb01fb82ab4e8198941c84cf4ec2bebf3c84940a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 18:54:48 +0500 Subject: [PATCH 221/399] latin7.xml: c Index.xml: Collation names form lati7 were mixed sql/share/charsets/Index.xml: Collation names form lati7 were mixed sql/share/charsets/latin7.xml: c --- sql/share/charsets/Index.xml | 2 +- sql/share/charsets/latin7.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 8c2b7a05d03..8cfd7923f9f 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -284,7 +284,7 @@ To make maintaining easier please: BalticRim iso-8859-13 l7 - + Estonian diff --git a/sql/share/charsets/latin7.xml b/sql/share/charsets/latin7.xml index d50601b5a90..1c25f5894b6 100644 --- a/sql/share/charsets/latin7.xml +++ b/sql/share/charsets/latin7.xml @@ -93,7 +93,7 @@ - + 00 02 03 04 05 06 07 08 09 2E 2F 30 31 32 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B @@ -115,7 +115,7 @@ - + @@ -139,7 +139,7 @@ - + From 7dcf24a3a49802897cc75ca37191d8dc0db1bdd6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 16:40:21 +0200 Subject: [PATCH 222/399] Fix for #468 [Ver]: SHOW VARIABLES trims innodb_data_file_path (this bug was already fixed in 4.0, I just copied and pasted two lines). --- sql/ha_innobase.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index b8a794a61a0..34ad45bfb18 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -107,6 +107,8 @@ my_bool innobase_log_archive = FALSE; my_bool innobase_use_native_aio = FALSE; my_bool innobase_fast_shutdown = TRUE; +static char *internal_innobase_data_file_path = NULL; + /* innodb_flush_log_at_trx_commit can now have 3 values: 0 : write to the log file once per second and flush it to disk; 1 : write to the log file at each commit and flush it to disk; @@ -522,8 +524,14 @@ innobase_init(void) srv_arch_dir = (innobase_log_arch_dir ? innobase_log_arch_dir : current_dir); - ret = (bool) - srv_parse_data_file_paths_and_sizes(innobase_data_file_path, + /* Since InnoDB edits the argument in the next call, we make another + copy of it: */ + + internal_innobase_data_file_path = my_strdup(innobase_data_file_path, + MYF(MY_WME)); + + ret = (bool) srv_parse_data_file_paths_and_sizes( + internal_innobase_data_file_path, &srv_data_file_names, &srv_data_file_sizes, &srv_data_file_is_raw_partition, From 4198322bef9550577d317046b642ccaa6f0f0702 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 May 2003 18:20:57 +0200 Subject: [PATCH 223/399] Outcome of discussions with Lenz and Monty about handling ccache in the build commands. BUILD/SETUP.sh: Quote $CXX to make a test work even if CXX had spaces in it. Automatically add ccache to CC and CXX if ccache is present. configure.in: Accept "ccache gcc" in the test. --- BUILD/SETUP.sh | 18 +++++++++++++++++- configure.in | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 55b82e38d63..150f9e28b41 100644 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -71,6 +71,22 @@ else make=make fi -if test -z $CXX ; then +if test -z "$CXX" ; then CXX=gcc fi + +# If ccache (a compiler cache which reduces build time) +# (http://samba.org/ccache) is installed, use it. +# We use 'grep' and hope 'grep' will work as expected +# (returns 0 if finds lines) +if ccache -V > /dev/null 2>&1 +then + if ! (echo "$CC" | grep "ccache" > /dev/null) + then + CC="ccache $CC" + fi + if ! (echo "$CXX" | grep "ccache" > /dev/null) + then + CXX="ccache $CXX" + fi +fi diff --git a/configure.in b/configure.in index c7cf4f66b70..5c794714889 100644 --- a/configure.in +++ b/configure.in @@ -361,7 +361,7 @@ then # we will gets some problems when linking static programs. # The following code is used to fix this problem. - if test "$CXX" = "gcc" + if test "$CXX" = "gcc" -o "$CXX" = "ccache gcc" then if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1 then From 73e80314aa17b13d8bb0a6f0f230b99c439bee8a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 May 2003 16:43:53 +0200 Subject: [PATCH 224/399] Fix for bug #490 and #491 (see details below) mysql-test/r/insert_select.result: Result update. mysql-test/r/rpl_insert_id.result: Test update mysql-test/t/insert_select.test: Check if a partly completed INSERT SELECT (failing because of "Duplicate key" after successfully inserting other rows) is written to the binlog if the table is not transactional and at least one row has been inserted (bug #491) mysql-test/t/rpl_insert_id.test: Test for bug #490 (INSERT SELECT in auto_increment) sql/sql_insert.cc: - In INSERT ... SELECT, if it fails with error but one row has been inserted and the table is not transactional, we must write to the binlog (the slave will stop because of the error code in the binlog event, this is normal). bug 491. - we must set INSERT_ID before writing to the binlog (bug 490 accidentally introduced by another dev in 4.0.13). --- mysql-test/r/insert_select.result | 14 +++++++++++++ mysql-test/r/rpl_insert_id.result | 28 ++++++++++++++++++++++++++ mysql-test/t/insert_select.test | 19 ++++++++++++++++++ mysql-test/t/rpl_insert_id.test | 33 +++++++++++++++++++++++++------ sql/sql_insert.cc | 24 +++++++++++++++++++--- 5 files changed, 109 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index e24c3179a0c..b49ca3a6c2f 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -66,3 +66,17 @@ INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip) SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2 WHERE numeropost=9 ORDER BY numreponse ASC; DROP TABLE IF EXISTS crash1,crash2; +drop table if exists t1; +drop table if exists t2; +create table t1(a int, unique(a)); +insert into t1 values(2); +create table t2(a int); +insert into t2 values(1),(2); +reset master; +insert into t1 select * from t2; +Duplicate entry '2' for key 1 +show binlog events; +Log_name Pos Event_type Server_id Orig_log_pos Info +master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3 +master-bin.001 79 Query 1 79 use test; insert into t1 select * from t2 +drop table t1, t2; diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index d524818985e..6d996481a5c 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -39,3 +39,31 @@ b c 6 11 drop table t1; drop table t2; +create table t1(a int auto_increment, key(a)); +create table t2(b int auto_increment, c int, key(b)); +insert into t1 values (10); +insert into t1 values (null),(null),(null); +insert into t2 values (5,0); +insert into t2 (c) select * from t1; +select * from t2; +b c +5 0 +6 10 +7 11 +8 12 +9 13 +select * from t1; +a +10 +11 +12 +13 +select * from t2; +b c +5 0 +6 10 +7 11 +8 12 +9 13 +drop table t1; +drop table t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 42f65858d77..695f891f678 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -68,3 +68,22 @@ WHERE numeropost=9 ORDER BY numreponse ASC; DROP TABLE IF EXISTS crash1,crash2; + +# Addendum by Guilhem: +# Check if a partly-completed INSERT SELECT in a MyISAM table goes +# into the binlog +drop table if exists t1; +drop table if exists t2; +create table t1(a int, unique(a)); +insert into t1 values(2); +create table t2(a int); +insert into t2 values(1),(2); +reset master; +--error 1062 +insert into t1 select * from t2; +# The above should produce an error, but still be in the binlog; +# verify the binlog : +let $VERSION=`select version()`; +--replace_result $VERSION VERSION +show binlog events; +drop table t1, t2; diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 3f3636d3082..3478aedf3eb 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -1,6 +1,7 @@ -#see if queries that use both -#auto_increment and LAST_INSERT_ID() -#are replicated well +# see if queries that use both +# auto_increment and LAST_INSERT_ID() +# are replicated well + source include/master-slave.inc; connection master; drop table if exists t1; @@ -15,9 +16,11 @@ sync_with_master; select * from t1; select * from t2; connection master; -#check if multi-line inserts, -#which set last_insert_id to the first id inserted, -#are replicated the same way + +# check if multi-line inserts, +# which set last_insert_id to the first id inserted, +# are replicated the same way + drop table t1; drop table t2; create table t1(a int auto_increment, key(a)); @@ -32,6 +35,24 @@ sync_with_master; select * from t1; select * from t2; connection master; + +# check if INSERT SELECT in auto_increment is well replicated (bug #490) + +drop table t1; +drop table t2; +create table t1(a int auto_increment, key(a)); +create table t2(b int auto_increment, c int, key(b)); +insert into t1 values (10); +insert into t1 values (null),(null),(null); +insert into t2 values (5,0); +insert into t2 (c) select * from t1; +select * from t2; +save_master_pos; +connection slave; +sync_with_master; +select * from t1; +select * from t2; +connection master; drop table t1; drop table t2; save_master_pos; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 33a13fabdc6..167ccf974c7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1350,6 +1350,24 @@ void select_insert::send_error(uint errcode,const char *err) ::send_error(&thd->net,errcode,err); table->file->extra(HA_EXTRA_NO_CACHE); table->file->activate_all_index(thd); + /* + If at least one row has been inserted/modified and will stay in the table + (the table doesn't have transactions) (example: we got a duplicate key + error while inserting into a MyISAM table) we must write to the binlog (and + the error code will make the slave stop). + */ + if ((info.copied || info.deleted) && !table->file->has_transactions()) + { + if (last_insert_id) + thd->insert_id(last_insert_id); // For binary log + mysql_update_log.write(thd,thd->query,thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, + table->file->has_transactions()); + mysql_bin_log.write(&qinfo); + } + } ha_rollback_stmt(thd); if (info.copied || info.deleted) { @@ -1365,7 +1383,10 @@ bool select_insert::send_eof() error=table->file->activate_all_index(thd); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + if (last_insert_id) + thd->insert_id(last_insert_id); // For binary log /* Write to binlog before commiting transaction */ + mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, @@ -1393,10 +1414,7 @@ bool select_insert::send_eof() else sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, thd->cuted_fields); - if (last_insert_id) - thd->insert_id(last_insert_id); // For update log ::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 a6ebf38d72b9e3852e51314a87d636e2c6f8c37d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 May 2003 23:30:55 +0500 Subject: [PATCH 225/399] symlink.result: Character set in this test results was displayed dispite the fact that the table has the same character set mysql-test/r/symlink.result: Character set in this test results was displayed dispite the fact that the table has the same character set --- mysql-test/r/symlink.result | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 1eb595eb2a9..3efc69d2f64 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -36,7 +36,7 @@ show create table t9; Table Create Table t9 CREATE TABLE `t9` ( `a` int(11) NOT NULL auto_increment, - `b` char(16) character set latin1 NOT NULL default '', + `b` char(16) NOT NULL default '', `c` int(11) NOT NULL default '0', PRIMARY KEY (`a`) ) TYPE=MyISAM CHARSET=latin1 @@ -45,6 +45,8 @@ alter table t8 rename t7; rename table t7 to t9; drop table t1; Got one of the listed errors +Warnings: +Note 1008 Can't drop database 'test_mysqltest'. Database doesn't exist Got one of the listed errors Got one of the listed errors Got one of the listed errors @@ -57,7 +59,7 @@ show create table test_mysqltest.t9; Table Create Table t9 CREATE TABLE `t9` ( `a` int(11) NOT NULL auto_increment, - `b` char(16) character set latin1 NOT NULL default '', + `b` char(16) NOT NULL default '', `c` int(11) NOT NULL default '0', `d` int(11) NOT NULL default '0', PRIMARY KEY (`a`) From dc90f5ccd798c411a85b7fbc98768728fb1bc888 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 25 May 2003 23:37:32 +0300 Subject: [PATCH 226/399] log.cc: If FOREIGN_KEY_CHECKS=0, wrap in binlog SQL statements inside SET FOREIGN_...=0; ... ; SET FOREIGN_...=1 sql/log.cc: If FOREIGN_KEY_CHECKS=0, wrap in binlog SQL statements inside SET FOREIGN_...=0; ... ; SET FOREIGN_...=1 --- sql/log.cc | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index 79ee59eedf8..8bf51100147 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1071,6 +1071,12 @@ bool MYSQL_LOG::write(Log_event* event_info) No check for auto events flag here - this write method should never be called if auto-events are enabled */ + + /* + 1. Write first log events which describe the 'run environment' + of the SQL command + */ + if (thd) { if (thd->last_insert_id_used) @@ -1109,11 +1115,50 @@ bool MYSQL_LOG::write(Log_event* event_info) if (e.write(file)) goto err; } + + /* If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL + command in the binlog inside: + SET FOREIGN_KEY_CHECKS=0; + ; + SET FOREIGN_KEY_CHECKS=1; */ + + if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + char buf[256], *p; + p= strmov(buf, "SET FOREIGN_KEY_CHECKS=0"); + Query_log_event e(thd, buf, (ulong) (p - buf), 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } } + + /* + 2. Write the SQL command + */ + event_info->set_log_pos(this); if (event_info->write(file) || - file == &log_file && flush_io_cache(file)) + file == &log_file && flush_io_cache(file)) goto err; + + /* + 3. Write log events to reset the 'run environment' of the SQL command + */ + + if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + char buf[256], *p; + + p= strmov(buf, "SET FOREIGN_KEY_CHECKS=1"); + Query_log_event e(thd, buf, (ulong) (p - buf), 0); + e.set_log_pos(this); + + if (e.write(file) || + file == &log_file && flush_io_cache(file)) + goto err; + } + error=0; /* From 2917fdb9d38c798cdc8e9341bec667ce4cb3c281 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 25 May 2003 23:09:46 +0200 Subject: [PATCH 227/399] - Fix for memory leak if the SQL slave thread is killed just after reading an event. - A few more mutex locks and unlocks of rli.log_space_lock for doing clean reads of rli.ignore_log_space_limit - Broadcast after unlock, not before (small speed optimisation). --- sql/slave.cc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index e6215356ad1..b620603dc63 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1322,6 +1322,8 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) !rli->ignore_log_space_limit) { pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); + /* Re-acquire the mutex as pthread_cond_wait released it */ + pthread_mutex_lock(&rli->log_space_lock); } thd->proc_info = save_proc_info; pthread_mutex_unlock(&rli->log_space_lock); @@ -2028,7 +2030,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) Log_event * ev = next_event(rli); DBUG_ASSERT(rli->sql_thd==thd); if (sql_slave_killed(thd,rli)) + { + /* do not forget to free ev ! */ + if (ev) delete ev; return 1; + } if (ev) { int type_code = ev->get_type_code(); @@ -2302,6 +2308,18 @@ reconnect done to recover from failed read"); goto err; } flush_master_info(mi); + /* + See if the relay logs take too much space. + We don't lock mi->rli.log_space_lock here; this dirty read saves time + and does not introduce any problem: + - if mi->rli.ignore_log_space_limit is 1 but becomes 0 just after (so + the clean value is 0), then we are reading only one more event as we + should, and we'll block only at the next event. No big deal. + - if mi->rli.ignore_log_space_limit is 0 but becomes 1 just after (so + the clean value is 1), then we are going into wait_for_relay_log_space() + for no reason, but this function will do a clean read, notice the clean + value and exit immediately. + */ if (mi->rli.log_space_limit && mi->rli.log_space_limit < mi->rli.log_space_total && !mi->rli.ignore_log_space_limit) @@ -2416,7 +2434,9 @@ slave_begin: rli->pending = 0; //tell the I/O thread to take relay_log_space_limit into account from now on + pthread_mutex_lock(&rli->log_space_lock); rli->ignore_log_space_limit= 0; + pthread_mutex_unlock(&rli->log_space_lock); if (init_relay_log_pos(rli, rli->relay_log_name, @@ -3122,9 +3142,14 @@ Log_event* next_event(RELAY_LOG_INFO* rli) pthread_mutex_lock(&rli->log_space_lock); // prevent the I/O thread from blocking next times rli->ignore_log_space_limit= 1; - // If the I/O thread is blocked, unblock it - pthread_cond_broadcast(&rli->log_space_cond); + /* + If the I/O thread is blocked, unblock it. + Ok to broadcast after unlock, because the mutex is only destroyed in + ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be + destroyed before we exit the present function. + */ pthread_mutex_unlock(&rli->log_space_lock); + pthread_cond_broadcast(&rli->log_space_cond); // Note that wait_for_update unlocks lock_log ! rli->relay_log.wait_for_update(rli->sql_thd); // re-acquire data lock since we released it earlier From 069141f2295297923c25d8b732d468ef1578c118 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 05:57:27 +0300 Subject: [PATCH 228/399] Remove not used flag --- include/mysql_com.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index fcc9abc5bcd..4ea1a77c836 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -86,7 +86,6 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY, #define CLIENT_ODBC 64 /* Odbc client */ #define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ #define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ -#define CLIENT_CHANGE_USER 512 /* Support the mysql_change_user() */ #define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ #define CLIENT_SSL 2048 /* Switch to SSL after handshake */ #define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ From ea99087e8843a80948edd98df09474118b7e31d2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 06:16:50 +0300 Subject: [PATCH 229/399] Added missing free for last patch --- sql/ha_innobase.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 34ad45bfb18..d1db50dfa89 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -637,6 +637,7 @@ innobase_end(void) err = innobase_shutdown_for_mysql(); hash_free(&innobase_open_tables); + my_free(internal_innobase_data_file_path,MYF(MY_ALLOW_ZERO_PTR)); if (err != DB_SUCCESS) { From e864f2592de68f04891d9611b0debfb123e8fd88 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 11:47:03 +0300 Subject: [PATCH 230/399] Added testing of LOAD DATA ... STARTING BY Added read_only variable mysql-test/r/loaddata.result: Added testing of STARTING BY mysql-test/t/loaddata.test: Added testing of STARTING BY sql/log_event.cc: Code cleanup sql/set_var.cc: Added read_only variable sql/sql_update.cc: Remove not used variable --- mysql-test/r/loaddata.result | 7 +++++++ mysql-test/t/loaddata.test | 8 ++++++++ sql/log_event.cc | 3 +-- sql/set_var.cc | 5 ++--- sql/sql_update.cc | 1 - 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index d121a4e6c40..59153f3353a 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -8,4 +8,11 @@ a b c d 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 +truncate table t1; +load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d); +SELECT * from t1; +a b c d +NULL NULL 0000-00-00 0000-00-00 +NULL 0000-00-00 0000-00-00 0000-00-00 +NULL 2003-03-03 2003-03-03 NULL drop table t1; diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index ceb5c47af11..e63f0780e3e 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -8,4 +8,12 @@ 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; +truncate table t1; + +load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d); +SELECT * from t1; drop table t1; + + + + diff --git a/sql/log_event.cc b/sql/log_event.cc index bbea89bfd3f..76151026590 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1946,8 +1946,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, sql_error= ER_UNKNOWN_ERROR; slave_print_error(rli,sql_error, "Error '%s' running load data infile", - sql_error ? thd->net.last_error : - ER_SAFE(ER_UNKNOWN_ERROR)); + ER_SAFE(sql_error)); free_root(&thd->mem_root,0); return 1; } diff --git a/sql/set_var.cc b/sql/set_var.cc index 2ca12cdb802..1da187598c4 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -185,6 +185,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count", sys_var_thd_bool sys_new_mode("new", &SV::new_mode); sys_var_thd_ulong sys_read_buff_size("read_buffer_size", &SV::read_buff_size); +sys_var_bool_ptr sys_readonly("read_only", &opt_readonly); sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size", &SV::read_rnd_buff_size); sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank", @@ -204,8 +205,6 @@ 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", @@ -516,6 +515,7 @@ struct show_var_st init_vars[]= { {"port", (char*) &mysql_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, + {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, #ifdef HAVE_QUERY_CACHE @@ -525,7 +525,6 @@ 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_update.cc b/sql/sql_update.cc index ed4d6fd9b81..b4e7750addf 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -182,7 +182,6 @@ int mysql_update(THD *thd, */ uint length; SORT_FIELD *sortorder; - List fields; ha_rows examined_rows; table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), From 306b74fcc86b946577aa0a87231d43aac0b20395 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 13:10:08 +0300 Subject: [PATCH 231/399] Fixed core dump bug when shuting down mysqld --- include/thr_alarm.h | 2 +- mysys/thr_alarm.c | 75 ++++++++++++++++++++++++++++----------------- sql/mysqld.cc | 7 +++-- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 30825d49158..439f046252f 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -103,7 +103,7 @@ void init_thr_alarm(uint max_alarm); bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); void thr_alarm_kill(pthread_t thread_id); void thr_end_alarm(thr_alarm_t *alarmed); -void end_thr_alarm(void); +void end_thr_alarm(my_bool free_structures); sig_handler process_alarm(int); #ifndef thr_got_alarm bool thr_got_alarm(thr_alarm_t *alrm); diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index add5335a7af..1b58a0274ff 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -27,6 +27,7 @@ #include #include #include "thr_alarm.h" +#include #ifdef HAVE_SYS_SELECT_H #include /* AIX needs this for fd_set */ @@ -36,7 +37,7 @@ #define ETIME ETIMEDOUT #endif -static my_bool alarm_aborted=1; +static int alarm_aborted=1; /* No alarm thread */ my_bool thr_alarm_inited=0; static sig_handler process_alarm_part2(int sig); @@ -136,19 +137,24 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) now=(ulong) time((time_t*) 0); pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ - if (alarm_aborted) + if (alarm_aborted > 0) { /* No signal thread */ DBUG_PRINT("info", ("alarm aborted")); + *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_RETURN(1); } + if (alarm_aborted < 0) + sec= 1; /* Abort mode */ + if (alarm_queue.elements >= max_used_alarms) { if (alarm_queue.elements == alarm_queue.max_elements) { DBUG_PRINT("info", ("alarm queue full")); fprintf(stderr,"Warning: thr_alarm queue is full\n"); + *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_RETURN(1); @@ -219,6 +225,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) break; } } + DBUG_ASSERT(!*alarmed || found); if (!found) { #ifdef MAIN @@ -228,14 +235,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n", (long) *alarmed)); } - if (alarm_aborted && !alarm_queue.elements) - { - delete_queue(&alarm_queue); - pthread_mutex_unlock(&LOCK_alarm); - pthread_mutex_destroy(&LOCK_alarm); - } - else - pthread_mutex_unlock(&LOCK_alarm); + pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_VOID_RETURN; } @@ -365,31 +365,49 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) /* - Shedule all alarms now. - When all alarms are given, Free alarm memory and don't allow more alarms. + Schedule all alarms now and optionally free all structures + + SYNPOSIS + end_thr_alarm() + free_structures Set to 1 if we should free memory used for + the alarm queue. + When we call this we should KNOW that there + is no active alarms + IMPLEMENTATION + Set alarm_abort to -1 which will change the behavior of alarms as follows: + - All old alarms will be rescheduled at once + - All new alarms will be rescheduled to one second */ -void end_thr_alarm(void) +void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); - if (!alarm_aborted) + if (alarm_aborted != 1) { - my_bool deleted=0; pthread_mutex_lock(&LOCK_alarm); DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); - alarm_aborted=1; /* mark aborted */ - if (!alarm_queue.elements) - { - deleted= 1; - delete_queue(&alarm_queue); - } + alarm_aborted= -1; /* mark aborted */ if (pthread_equal(pthread_self(),alarm_thread)) alarm(1); /* Shut down everything soon */ else reschedule_alarms(); - pthread_mutex_unlock(&LOCK_alarm); - if (deleted) - pthread_mutex_destroy(&LOCK_alarm); + if (free_structures) + { + /* + The following test is just for safety, the caller should not + depend on this + */ + DBUG_ASSERT(!alarm_queue.elements); + if (!alarm_queue.elements) + { + delete_queue(&alarm_queue); + alarm_aborted= 1; + pthread_mutex_unlock(&LOCK_alarm); + pthread_mutex_destroy(&LOCK_alarm); + } + } + else + pthread_mutex_unlock(&LOCK_alarm); } DBUG_VOID_RETURN; } @@ -629,7 +647,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr) } } -void end_thr_alarm(void) +void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); alarm_aborted=1; /* No more alarms */ @@ -708,7 +726,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr) } } -void end_thr_alarm(void) +void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); alarm_aborted=1; /* No more alarms */ @@ -907,7 +925,7 @@ static void *signal_hand(void *arg __attribute__((unused))) case SIGHUP: #endif printf("Aborting nicely\n"); - end_thr_alarm(); + end_thr_alarm(0); break; #ifdef SIGTSTP case SIGTSTP: @@ -1004,10 +1022,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) if (thread_count == 1) { printf("Calling end_thr_alarm. This should cancel the last thread\n"); - end_thr_alarm(); + end_thr_alarm(0); } } pthread_mutex_unlock(&LOCK_thread_count); + end_thr_alarm(1); thr_alarm_info(&alarm_info); printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", alarm_info.active_alarms, alarm_info.max_used_alarms, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 67fb7798ebd..2992fcfd908 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -596,7 +596,7 @@ static void close_connections(void) unix_sock= INVALID_SOCKET; } #endif - end_thr_alarm(); // Don't allow alarms + end_thr_alarm(0); // Abort old alarms. end_slave(); /* First signal all threads that it's time to die */ @@ -905,6 +905,7 @@ void clean_up(bool print_message) #endif (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ end_key_cache(); + end_thr_alarm(1); /* Free allocated memory */ #ifdef USE_RAID end_raid(); #endif @@ -2313,14 +2314,14 @@ The server will not act as a slave."); if (opt_bootstrap) { int error=bootstrap(stdin); - end_thr_alarm(); // Don't allow alarms + end_thr_alarm(1); // Don't allow alarms unireg_abort(error ? 1 : 0); } if (opt_init_file) { if (read_init_file(opt_init_file)) { - end_thr_alarm(); // Don't allow alarms + end_thr_alarm(1); // Don't allow alarms unireg_abort(1); } } From ecdd47a72fe49738549e3e0b2cccec776a6fba26 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 15:08:17 +0300 Subject: [PATCH 232/399] code cleanup mysql-test/r/rpl_insert_id.result: Test logging of FOREIGN_KEY_CHECKS mysql-test/t/rpl_insert_id.test: Test logging of FOREIGN_KEY_CHECKS sql/log.cc: Code cleanup --- mysql-test/r/rpl_insert_id.result | 2 ++ mysql-test/t/rpl_insert_id.test | 10 ++++-- sql/log.cc | 57 ++++++++++++++----------------- 3 files changed, 34 insertions(+), 35 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index d524818985e..70f9ff0de0f 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -23,10 +23,12 @@ drop table t1; drop table t2; create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); +SET FOREIGN_KEY_CHECKS=0; insert into t1 values (10); insert into t1 values (null),(null),(null); insert into t2 values (5,0); insert into t2 values (null,last_insert_id()); +SET FOREIGN_KEY_CHECKS=1; select * from t1; a 10 diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 3f3636d3082..a9e4de21e5c 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -1,6 +1,8 @@ -#see if queries that use both -#auto_increment and LAST_INSERT_ID() -#are replicated well +# See if queries that use both auto_increment and LAST_INSERT_ID() +# are replicated well + +# We also check how the foreign_key_check variable is replicated + source include/master-slave.inc; connection master; drop table if exists t1; @@ -22,10 +24,12 @@ drop table t1; drop table t2; create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); +SET FOREIGN_KEY_CHECKS=0; insert into t1 values (10); insert into t1 values (null),(null),(null); insert into t2 values (5,0); insert into t2 values (null,last_insert_id()); +SET FOREIGN_KEY_CHECKS=1; save_master_pos; connection slave; sync_with_master; diff --git a/sql/log.cc b/sql/log.cc index 8bf51100147..99bc6ee32b4 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1116,50 +1116,38 @@ bool MYSQL_LOG::write(Log_event* event_info) goto err; } - /* If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL - command in the binlog inside: - SET FOREIGN_KEY_CHECKS=0; - ; - SET FOREIGN_KEY_CHECKS=1; */ + /* + If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL + command in the binlog inside: + SET FOREIGN_KEY_CHECKS=0; + ; + SET FOREIGN_KEY_CHECKS=1; + */ if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { - char buf[256], *p; - p= strmov(buf, "SET FOREIGN_KEY_CHECKS=0"); - Query_log_event e(thd, buf, (ulong) (p - buf), 0); + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0); e.set_log_pos(this); if (e.write(file)) goto err; } } - /* - 2. Write the SQL command - */ + /* Write the SQL command */ event_info->set_log_pos(this); - if (event_info->write(file) || - file == &log_file && flush_io_cache(file)) + if (event_info->write(file)) goto err; - /* - 3. Write log events to reset the 'run environment' of the SQL command - */ + /* Write log events to reset the 'run environment' of the SQL command */ if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { - char buf[256], *p; - - p= strmov(buf, "SET FOREIGN_KEY_CHECKS=1"); - Query_log_event e(thd, buf, (ulong) (p - buf), 0); + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0); e.set_log_pos(this); - - if (e.write(file) || - file == &log_file && flush_io_cache(file)) + if (e.write(file)) goto err; } - - error=0; /* Tell for transactional table handlers up to which position in the @@ -1180,6 +1168,9 @@ bool MYSQL_LOG::write(Log_event* event_info) if (file == &log_file) // we are writing to the real log (disk) { + if (flush_io_cache(file)) + goto err; + if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log)) { /* @@ -1189,8 +1180,8 @@ bool MYSQL_LOG::write(Log_event* event_info) 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 (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); @@ -1200,6 +1191,7 @@ bool MYSQL_LOG::write(Log_event* event_info) /* we wrote to the real log, check automatic rotation */ should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size); } + error=0; err: if (error) @@ -1222,13 +1214,14 @@ 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 */ + /* + 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) { + if (called_handler_commit) ha_commit_complete(thd); - } DBUG_RETURN(error); } From 1ed4e006bd7e70f50d29950c03024d09aaec64f0 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 17:24:16 +0300 Subject: [PATCH 233/399] Fixed problem with 'kill pid-of-mysqld' on Mac OS X --- sql/mysqld.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4e88a6fcb32..f729dcfd17a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1346,6 +1346,7 @@ information that should help you find out what is causing the crash\n"); static void init_signals(void) { sigset_t set; + struct sigaction sa; DBUG_ENTER("init_signals"); sigset(THR_KILL_SIGNAL,end_thread_signal); @@ -1353,7 +1354,6 @@ static void init_signals(void) if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) { - struct sigaction sa; sa.sa_flags = SA_RESETHAND | SA_NODEFER; sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); @@ -1378,15 +1378,22 @@ static void init_signals(void) sigaddset(&set,SIGQUIT); sigaddset(&set,SIGTERM); sigaddset(&set,SIGHUP); - sigset(SIGTERM,print_signal_warning); // If it's blocked by parent - signal(SIGHUP,print_signal_warning); // If it's blocked by parent + + /* Fix signals if blocked by parents (can happen on Mac OS X) */ + sa.sa_flags = 0; + sa.sa_handler = print_signal_warning; + sigaction(SIGTERM, &sa, (struct sigaction*) 0); + sa.sa_flags = 0; + sa.sa_handler = print_signal_warning; + sigaction(SIGHUP, &sa, (struct sigaction*) 0); #ifdef SIGTSTP sigaddset(&set,SIGTSTP); #endif sigaddset(&set,THR_SERVER_ALARM); sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT sigdelset(&set,THR_CLIENT_ALARM); // For alarms - (void) pthread_sigmask(SIG_SETMASK,&set,NULL); + sigprocmask(SIG_SETMASK,&set,NULL); + pthread_sigmask(SIG_SETMASK,&set,NULL); DBUG_VOID_RETURN; } From 12604089b6acd8242a506d021449bdc515b72e14 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 20:01:18 +0500 Subject: [PATCH 234/399] Index.xml: cp1250_czech_ci was displayed even when not compiled-in in mistake. sql/share/charsets/Index.xml: cp1250_czech_ci was displayed even when not compiled-in in mistake. --- sql/share/charsets/Index.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 8cfd7923f9f..28cddb90fc5 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -348,7 +348,9 @@ To make maintaining easier please: Slovenian Sorbian - + + compiled + From 720584b0c6eb435fa87b5da42578f214d83735d1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 20:22:23 +0500 Subject: [PATCH 235/399] --with-charset was not up to date ctype_ucs2 and ctype_ujis were skipped in mistake --- acconfig.h | 29 +++--- configure.in | 164 ++++++++++++++++----------------- mysql-test/r/ctype_ujis.result | 2 +- mysql-test/r/have_ucs2.require | 2 +- mysql-test/r/have_ujis.require | 2 +- mysys/charset.c | 12 +-- strings/ctype-czech.c | 2 +- strings/ctype-euc_kr.c | 2 +- strings/ctype-win1250ch.c | 5 + 9 files changed, 108 insertions(+), 112 deletions(-) diff --git a/acconfig.h b/acconfig.h index 5f47365709c..6bd017bbbce 100644 --- a/acconfig.h +++ b/acconfig.h @@ -68,40 +68,37 @@ /* Define charsets you want */ #undef HAVE_CHARSET_armscii8 +#undef HAVE_CHARSET_ascii #undef HAVE_CHARSET_big5 +#undef HAVE_CHARSET_cp1250 #undef HAVE_CHARSET_cp1251 +#undef HAVE_CHARSET_cp1256 #undef HAVE_CHARSET_cp1257 -#undef HAVE_CHARSET_croat -#undef HAVE_CHARSET_czech -#undef HAVE_CHARSET_danish +#undef HAVE_CHARSET_cp850 +#undef HAVE_CHARSET_cp852 +#undef HAVE_CHARSET_cp866 #undef HAVE_CHARSET_dec8 -#undef HAVE_CHARSET_dos -#undef HAVE_CHARSET_estonia -#undef HAVE_CHARSET_euc_kr +#undef HAVE_CHARSET_euckr #undef HAVE_CHARSET_gb2312 #undef HAVE_CHARSET_gbk -#undef HAVE_CHARSET_german1 #undef HAVE_CHARSET_greek #undef HAVE_CHARSET_hebrew #undef HAVE_CHARSET_hp8 -#undef HAVE_CHARSET_hungarian -#undef HAVE_CHARSET_koi8_ru -#undef HAVE_CHARSET_koi8_ukr +#undef HAVE_CHARSET_keybcs2 +#undef HAVE_CHARSET_koi8r +#undef HAVE_CHARSET_koi8u #undef HAVE_CHARSET_latin1 -#undef HAVE_CHARSET_latin1_de #undef HAVE_CHARSET_latin2 #undef HAVE_CHARSET_latin5 +#undef HAVE_CHARSET_latin7 +#undef HAVE_CHARSET_macce +#undef HAVE_CHARSET_macroman #undef HAVE_CHARSET_sjis #undef HAVE_CHARSET_swe7 #undef HAVE_CHARSET_tis620 #undef HAVE_CHARSET_ucs2 #undef HAVE_CHARSET_ujis -#undef HAVE_CHARSET_usa7 #undef HAVE_CHARSET_utf8 -#undef HAVE_CHARSET_win1250 -#undef HAVE_CHARSET_win1250ch -#undef HAVE_CHARSET_win1251ukr -#undef HAVE_CHARSET_win1251 /* ZLIB and compress: */ #undef HAVE_COMPRESS diff --git a/configure.in b/configure.in index c0ce5221832..63286db74c5 100644 --- a/configure.in +++ b/configure.in @@ -2226,28 +2226,35 @@ AC_SUBST(readline_h_ln_cmd) dnl In order to add new charset, you must add charset name to -dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index. +dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index.xml. dnl If the character set uses strcoll or other special handling, dnl you must also create strings/ctype-$charset_name.c AC_DIVERT_PUSH(0) -CHARSETS_AVAILABLE="armscii8 big5 cp1251 cp1257 - croat czech danish dec8 dos estonia euc_kr gb2312 gbk - german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr - latin1 latin1_de latin2 latin5 sjis swe7 tis620 ucs2 ujis - usa7 utf8 win1250 win1250ch win1251ukr" -CHARSETS_DEPRECATED="win1251" -CHARSETS_COMPLEX="big5 czech euc_kr gb2312 gbk latin1_de sjis tis620 ucs2 ujis utf8 win1250ch" + +define(CHARSETS_AVAILABLE1,ascii armscii8 ascii big5 cp1250 cp1251 cp1256 cp1257) +define(CHARSETS_AVAILABLE2,cp850 cp852 cp866 dec8 euckr gb2312 gbk) +define(CHARSETS_AVAILABLE3,greek hebrew hp8 keybcs2 koi8r koi8u) +define(CHARSETS_AVAILABLE4,latin1 latin2 latin5 latin7 macce macroman) +define(CHARSETS_AVAILABLE5,sjis swe7 tis620 ucs2 ujis utf8) + DEFAULT_CHARSET=latin1 +CHARSETS_AVAILABLE="CHARSETS_AVAILABLE1 CHARSETS_AVAILABLE2 CHARSETS_AVAILABLE3 CHARSETS_AVAILABLE4 CHARSETS_AVAILABLE5" +CHARSETS_COMPLEX="big5 cp1250 euckr gb2312 gbk latin1 latin2 sjis tis620 ucs2 ujis utf8" + AC_DIVERT_POP -dnl fix this later.. -dnl [ --with-charset=CHARSET Use CHARSET by default (one of: $CHARSETS_AVAILABLE; Default is $DEFAULT_CHARSET)], - AC_ARG_WITH(charset, - [ --with-charset=CHARSET Use CHARSET by default (Default is latin1)], - [default_charset="$withval"], - [default_charset="$DEFAULT_CHARSET"]) + [ --with-charset=CHARSET + Default character set, use one of: + CHARSETS_AVAILABLE1 + CHARSETS_AVAILABLE2 + CHARSETS_AVAILABLE3 + CHARSETS_AVAILABLE4 + CHARSETS_AVAILABLE5], + [default_charset="$withval"], + [default_charset="$DEFAULT_CHARSET"]) + AC_ARG_WITH(extra-charsets, [ --with-extra-charsets=CHARSET[,CHARSET,...] @@ -2256,73 +2263,77 @@ AC_ARG_WITH(extra-charsets, [extra_charsets="$withval"], [extra_charsets="none"]) + AC_MSG_CHECKING("character sets") +CHARSETS="$default_charset latin1 utf8" + if test "$extra_charsets" = no; then - CHARSETS="" + CHARSETS="$CHARSETS" elif test "$extra_charsets" = none; then - CHARSETS="" + CHARSETS="$CHARSETS" elif test "$extra_charsets" = complex; then - CHARSETS="$CHARSETS_COMPLEX" + CHARSETS="$CHARSETS $CHARSETS_COMPLEX" elif test "$extra_charsets" = all; then - CHARSETS="$CHARSETS_AVAILABLE $CHARSETS_DEPRECATED" + CHARSETS="$CHARSETS $CHARSETS_AVAILABLE" else - CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'` + EXTRA_CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'` + CHARSETS="$CHARSETS $EXTRA_CHARSETS" fi -CHARSETS="$default_charset $CHARSETS" - -use_mb="no" for cs in $CHARSETS do case $cs in armscii8) AC_DEFINE(HAVE_CHARSET_armscii8) - use_mb="yes" + ;; + ascii) + AC_DEFINE(HAVE_CHARSET_ascii) ;; big5) AC_DEFINE(HAVE_CHARSET_big5) - use_mb="yes" + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) + ;; + cp1250) + AC_DEFINE(HAVE_CHARSET_cp1250) ;; cp1251) AC_DEFINE(HAVE_CHARSET_cp1251) ;; + cp1256) + AC_DEFINE(HAVE_CHARSET_cp1256) + ;; cp1257) AC_DEFINE(HAVE_CHARSET_cp1257) ;; - croat) - AC_DEFINE(HAVE_CHARSET_croat) + cp850) + AC_DEFINE(HAVE_CHARSET_cp850) ;; - czech) - AC_DEFINE(HAVE_CHARSET_czech) + cp852) + AC_DEFINE(HAVE_CHARSET_cp852) ;; - danish) - AC_DEFINE(HAVE_CHARSET_danish) + cp866) + AC_DEFINE(HAVE_CHARSET_cp866) ;; dec8) AC_DEFINE(HAVE_CHARSET_dec8) ;; - dos) - AC_DEFINE(HAVE_CHARSET_dos) - ;; - estonia) - AC_DEFINE(HAVE_CHARSET_estonia) - ;; - euc_kr) - AC_DEFINE(HAVE_CHARSET_euc_kr) - use_mb="yes" + euckr) + AC_DEFINE(HAVE_CHARSET_euckr) + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) ;; gb2312) AC_DEFINE(HAVE_CHARSET_gb2312) - use_mb="yes" + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) ;; gbk) AC_DEFINE(HAVE_CHARSET_gbk) - use_mb="yes" - ;; - german1) - AC_DEFINE(HAVE_CHARSET_german1) + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) ;; greek) AC_DEFINE(HAVE_CHARSET_greek) @@ -2333,30 +2344,37 @@ do hp8) AC_DEFINE(HAVE_CHARSET_hp8) ;; - hungarian) - AC_DEFINE(HAVE_CHARSET_hungarian) + keybcs2) + AC_DEFINE(HAVE_CHARSET_keybcs2) ;; - koi8_ru) - AC_DEFINE(HAVE_CHARSET_koi8_ru) + koi8r) + AC_DEFINE(HAVE_CHARSET_koi8r) ;; - koi8_ukr) - AC_DEFINE(HAVE_CHARSET_koi8_ukr) + koi8u) + AC_DEFINE(HAVE_CHARSET_koi8u) ;; latin1) AC_DEFINE(HAVE_CHARSET_latin1) ;; - latin1_de) - AC_DEFINE(HAVE_CHARSET_latin1_de) - ;; latin2) AC_DEFINE(HAVE_CHARSET_latin2) ;; latin5) AC_DEFINE(HAVE_CHARSET_latin5) ;; + latin7) + AC_DEFINE(HAVE_CHARSET_latin7) + ;; + macce) + AC_DEFINE(HAVE_CHARSET_macce) + ;; + macroman) + AC_DEFINE(HAVE_CHARSET_macroman) + ;; sjis) AC_DEFINE(HAVE_CHARSET_sjis) - use_mb="yes" + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) ;; swe7) AC_DEFINE(HAVE_CHARSET_swe7) @@ -2366,49 +2384,25 @@ do ;; ucs2) AC_DEFINE(HAVE_CHARSET_ucs2) - use_mb="yes" + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) ;; ujis) AC_DEFINE(HAVE_CHARSET_ujis) - use_mb="yes" - ;; - usa7) - AC_DEFINE(HAVE_CHARSET_usa7) + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) ;; utf8) AC_DEFINE(HAVE_CHARSET_utf8) - use_mb="yes" - ;; - win1250) - AC_DEFINE(HAVE_CHARSET_win1250) - ;; - win1250ch) - AC_DEFINE(HAVE_CHARSET_win1250ch) - ;; - win1251) - AC_DEFINE(HAVE_CHARSET_win1251) - ;; - win1251ukr) - AC_DEFINE(HAVE_CHARSET_win1251ukr) + AC_DEFINE(USE_MB) + AC_DEFINE(USE_MB_IDENT) ;; *) - AC_MSG_ERROR([Charset $cs not available. (Available $CHARSETS_AVAILABLE). + AC_MSG_ERROR([Charset $cs not available. (Available are: $CHARSETS_AVAILABLE). See the Installation chapter in the Reference Manual.]); esac done -dnl Always compile latin1 -AC_DEFINE(HAVE_CHARSET_latin1) - -dnl Always compile utf8 -AC_DEFINE(HAVE_CHARSET_utf8) -use_mb=yes - -if test "$use_mb" = "yes" -then - AC_DEFINE(USE_MB) - AC_DEFINE(USE_MB_IDENT) -fi AC_SUBST(default_charset) AC_DEFINE_UNQUOTED(DEFAULT_CHARSET_NAME,"$default_charset") diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result index 223a18f19e9..ffb305a81cf 100644 --- a/mysql-test/r/ctype_ujis.result +++ b/mysql-test/r/ctype_ujis.result @@ -1,5 +1,5 @@ drop table if exists t1; -create table t1 (c text); +create table t1 (c text character set ujis); insert into t1 values (0xa4a2),(0xa4a3); select hex(left(c,1)) from t1 group by c; hex(left(c,1)) diff --git a/mysql-test/r/have_ucs2.require b/mysql-test/r/have_ucs2.require index 9d7079740ad..4f2ef7e83e4 100644 --- a/mysql-test/r/have_ucs2.require +++ b/mysql-test/r/have_ucs2.require @@ -1,2 +1,2 @@ Collation Charset Id D C Sortlen -ucs2_general_ci ucs2 35 Y 0 +ucs2_general_ci ucs2 35 Y Y 1 diff --git a/mysql-test/r/have_ujis.require b/mysql-test/r/have_ujis.require index 5f7ce2a50c7..b4b0a4d256c 100644 --- a/mysql-test/r/have_ujis.require +++ b/mysql-test/r/have_ujis.require @@ -1,2 +1,2 @@ Collation Charset Id D C Sortlen -ujis_japanese_ci ujis 12 Y 0 +ujis_japanese_ci ujis 12 Y Y 0 diff --git a/mysys/charset.c b/mysys/charset.c index 82bace7fb2c..ad0468a5087 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -407,11 +407,15 @@ static my_bool init_compiled_charsets(myf flags __attribute__((unused))) MY_ADD_CHARSET(&my_charset_big5_bin); #endif -#ifdef HAVE_CHARSET_czech +#ifdef HAVE_CHARSET_cp1250 + MY_ADD_CHARSET(&my_charset_cp1250_czech_ci); +#endif + +#ifdef HAVE_CHARSET_latin2 MY_ADD_CHARSET(&my_charset_latin2_czech_ci); #endif -#ifdef HAVE_CHARSET_euc_kr +#ifdef HAVE_CHARSET_euckr MY_ADD_CHARSET(&my_charset_euckr_korean_ci); MY_ADD_CHARSET(&my_charset_euckr_bin); #endif @@ -451,10 +455,6 @@ static my_bool init_compiled_charsets(myf flags __attribute__((unused))) MY_ADD_CHARSET(&my_charset_utf8_bin); #endif -#ifdef HAVE_CHARSET_win1250ch - MY_ADD_CHARSET(&my_charset_cp1250_czech_ci); -#endif - /* Copy compiled charsets */ for (cs=compiled_charsets; cs->name; cs++) { diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c index fc3ff137778..2398bc33d45 100644 --- a/strings/ctype-czech.c +++ b/strings/ctype-czech.c @@ -77,7 +77,7 @@ #endif -#ifdef HAVE_CHARSET_czech +#ifdef HAVE_CHARSET_latin2 /* These are four tables for four passes of the algorithm. Please see diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 4a5757bf5c4..8e288ee8e55 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -30,7 +30,7 @@ #include "m_string.h" #include "m_ctype.h" -#ifdef HAVE_CHARSET_euc_kr +#ifdef HAVE_CHARSET_euckr static uchar NEAR ctype_euc_kr[257] = diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index af4faca46e1..0b75a782b17 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -45,6 +45,9 @@ #include "m_string.h" #include "m_ctype.h" +#ifdef HAVE_CHARSET_cp1250 + + static uint16 tab_cp1250_uni[256]={ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, @@ -673,4 +676,6 @@ CHARSET_INFO my_charset_cp1250_czech_ci = }; +#endif + #endif From 5d3eec14dd3e8b2e4656e5559114650bee54a5e6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 19:01:20 +0300 Subject: [PATCH 236/399] New 4.1 protocol; SQLSTATE, CLIENT_MULTI_RESULTS, client character set Docs/internals.texi: Updated protocol information include/mysql.h: Added catalog to MYSQL_FIELD Added sqlstate handling to protocol include/mysql_com.h: New 4.1 protocol libmysql/libmysql.c: Added sqlstate handling Added CLIENT_MULTI_RESULTS sql/field.cc: Indentation cleanup sql/field.h: Indentation cleanup sql/mysql_priv.h: Changed arguments to close_connection() sql/mysqld.cc: Changed arguments to close_connection() Added checking of extra arguments to mysqld sql/protocol.cc: Fixed bug in TIME handling Added SQLSTATE on errors Removed net_send_error() sql/protocol.h: Removed net_send_error() sql/repl_failsafe.cc: Fixed arguments to close_connection() sql/sql_parse.cc: New 4.1 protocol --- Docs/internals.texi | 18 ++-- include/mysql.h | 5 + include/mysql_com.h | 17 +-- libmysql/libmysql.c | 244 +++++++++++++++++++++++++++++-------------- sql/field.cc | 2 +- sql/field.h | 3 +- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 32 +++--- sql/protocol.cc | 84 +++++++-------- sql/protocol.h | 1 - sql/repl_failsafe.cc | 2 +- sql/sql_parse.cc | 31 ++++-- 12 files changed, 278 insertions(+), 163 deletions(-) diff --git a/Docs/internals.texi b/Docs/internals.texi index ddaedbe5b9b..ac79724dbe5 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -1766,7 +1766,10 @@ following connection establishment sequence is followed: +--------------------------------------------------------------------+ | Header | CLIENT_xxx options supported | max_allowed_packet | | | by client | for client | -| | 2 Bytes | 3 bytes | +| | 4 Bytes | 4 bytes | +|--------------------------------------------------------------------| +| Character set | Reserved for the future | +| 1 Bytes | 23 bytes | |--------------------------------------------------------------------| | User Name | 0x00 | Crypted Password | 0x00 | Database Name | | n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes | @@ -2326,7 +2329,7 @@ Warnings @item Prepared statements @item -Binary protocol (will be faster than the current protocol that +Binary protocol (is be faster than the current protocol that converts everything to strings) @end itemize @@ -2335,7 +2338,7 @@ What has changed in 4.1 are: @itemize @bullet @item -A lot of new field information (database, real table name etc) +A lot of new field information (catalog, database, real table name etc) @item The 'ok' packet has more status fields @item @@ -2374,15 +2377,16 @@ The field description result set contains the meta info for a result set. @multitable @columnfractions .20 .80 @item Type @tab Comment +@item string @tab Catalog name (for 5.x) @item string @tab Database name @item string @tab Table name alias (or table name if no alias) @item string @tab Real table name @item string @tab Alias for column name (or column name if not used) -@item 11 byte @tab Fixed length fields in one field part: +@item 12 byte @tab Fixed length fields in one field part: @itemize @item 2 byte int @tab Character set number -@item 3 byte int @tab Length of column definition +@item 4 byte int @tab Length of column definition @item 1 byte int @tab Enum value for field type @item 3 byte int @tab 2 byte column flags (NOT_NULL_FLAG etc..) + 1 byte number of decimals. @item 2 byte int @tab zero (reserved for future use) @@ -2457,7 +2461,9 @@ The error packet has the following structure: @item Size @tab Comment @item 1 @tab 255 Error packet marker @item 2 @tab Error code -@item 1-255 @tab Null terminated error message +@item 1 @tab '#' marker that SQLSTATE follows +@item 6 @tab SQLSTATE code (000000 for many messages) +@item 1-512 @tab Null terminated error message @end multitable The client/server protocol is designed in such a way that a packet diff --git a/include/mysql.h b/include/mysql.h index 67dc9ae08c9..94f2152655d 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -83,6 +83,7 @@ typedef struct st_mysql_field { char *table; /* Table of column if column was a field */ char *org_table; /* Org table name, if table was an alias */ char *db; /* Database for table */ + char *catalog; /* Catalog for table */ char *def; /* Default value (set by mysql_list_fields) */ unsigned long length; /* Width of column */ unsigned long max_length; /* Max width of selected set */ @@ -91,6 +92,7 @@ typedef struct st_mysql_field { unsigned int table_length; unsigned int org_table_length; unsigned int db_length; + unsigned int catalog_length; unsigned int def_length; unsigned int flags; /* Div flags */ unsigned int decimals; /* Number of decimals in field */ @@ -346,6 +348,7 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql); my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql); unsigned int STDCALL mysql_errno(MYSQL *mysql); const char * STDCALL mysql_error(MYSQL *mysql); +const char *STDCALL mysql_sqlstate(MYSQL *mysql); unsigned int STDCALL mysql_warning_count(MYSQL *mysql); const char * STDCALL mysql_info(MYSQL *mysql); unsigned long STDCALL mysql_thread_id(MYSQL *mysql); @@ -543,6 +546,7 @@ typedef struct st_mysql_stmt unsigned int last_errno; /* error code */ enum PREP_STMT_STATE state; /* statement state */ char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ + char sqlstate[SQLSTATE_LENGTH+1]; my_bool long_alloced; /* flag to indicate long alloced */ my_bool send_types_to_server; /* Types sent to server */ my_bool param_buffers; /* param bound buffers */ @@ -560,6 +564,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); +const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt); my_bool STDCALL mysql_commit(MYSQL * mysql); my_bool STDCALL mysql_rollback(MYSQL * mysql); my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode); diff --git a/include/mysql_com.h b/include/mysql_com.h index bbfb869927b..e2fa30e3a18 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -25,6 +25,7 @@ #define HOSTNAME_LENGTH 60 #define USERNAME_LENGTH 16 #define SERVER_VERSION_LENGTH 60 +#define SQLSTATE_LENGTH 6 #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." @@ -100,20 +101,22 @@ enum enum_server_command #define CLIENT_ODBC 64 /* Odbc client */ #define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ #define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ +#define CLIENT_PROTOCOL_41 512 /* New 4.1 protocol */ #define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ -#define CLIENT_SSL 2048 /* Switch to SSL after handshake */ -#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ +#define CLIENT_SSL 2048 /* Switch to SSL after handshake */ +#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ -#define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */ -#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ -#define CLIENT_MULTI_QUERIES 65536 /* Enable/disable multi query support */ +#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */ +#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ +#define CLIENT_MULTI_QUERIES 65536 /* Enable/disable multiquery support */ +#define CLIENT_MULTI_RESULTS 131072 /* Enable/disable multi-results */ #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ #define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */ #define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */ -#define MYSQL_ERRMSG_SIZE 200 +#define MYSQL_ERRMSG_SIZE 512 #define NET_READ_TIMEOUT 30 /* Timeout on read */ #define NET_WRITE_TIMEOUT 60 /* Timeout on write */ #define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */ @@ -149,7 +152,7 @@ typedef struct st_net { queries in cache that have not stored its results yet */ #endif - char last_error[MYSQL_ERRMSG_SIZE]; + char last_error[MYSQL_ERRMSG_SIZE], sqlstate[SQLSTATE_LENGTH+1]; unsigned int last_errno; unsigned char error; gptr query_cache_query; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 34dcb7b287e..5971fda141b 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -64,6 +64,7 @@ ulong net_buffer_length=8192; ulong max_allowed_packet= 1024L*1024L*1024L; ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT; +const char *unknown_sqlstate= "000000"; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \ @@ -324,6 +325,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (GetLastError() != ERROR_PIPE_BUSY) { net->last_errno=CR_NAMEDPIPEOPEN_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -332,6 +334,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (! WaitNamedPipe(szPipeName, connect_timeout*1000) ) { net->last_errno=CR_NAMEDPIPEWAIT_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -340,6 +343,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (hPipe == INVALID_HANDLE_VALUE) { net->last_errno=CR_NAMEDPIPEOPEN_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -349,6 +353,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, { CloseHandle( hPipe ); net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -552,6 +557,7 @@ err: if (error_allow) { net->last_errno=error_allow; + strmov(net->sqlstate, unknown_sqlstate); if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR) sprintf(net->last_error,ER(net->last_errno),suffix_pos,error_code); else @@ -590,6 +596,7 @@ net_safe_read(MYSQL *mysql) CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST); strmov(net->last_error,ER(net->last_errno)); + strmov(net->sqlstate, unknown_sqlstate); return (packet_error); } if (net->read_pos[0] == 255) @@ -600,16 +607,22 @@ net_safe_read(MYSQL *mysql) net->last_errno=uint2korr(pos); pos+=2; len-=2; + if (protocol_41(mysql) && pos[0] == '#') + { + strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH); + pos+= SQLSTATE_LENGTH+1; + } (void) strmake(net->last_error,(char*) pos, min((uint) len,(uint) sizeof(net->last_error)-1)); } else { net->last_errno=CR_UNKNOWN_ERROR; - (void) strmov(net->last_error,ER(net->last_errno)); + strmov(net->sqlstate, unknown_sqlstate); + strmov(net->last_error, ER(net->last_errno)); } - DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno, - net->last_error)); + DBUG_PRINT("error",("Got error: %d/%s (%s)", + net->last_errno, net->sqlstate, net->last_error)); return(packet_error); } return len; @@ -645,11 +658,13 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, if (mysql->status != MYSQL_STATUS_READY) { strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + strmov(net->sqlstate, unknown_sqlstate); return 1; } - mysql->net.last_error[0]=0; - mysql->net.last_errno=0; + net->last_error[0]=0; + net->last_errno=0; + strmov(net->sqlstate, unknown_sqlstate); mysql->info=0; mysql->affected_rows= ~(my_ulonglong) 0; net_clear(&mysql->net); /* Clear receive buffer */ @@ -911,8 +926,8 @@ static const char *default_options[]= "character-sets-dir", "default-character-set", "interactive-timeout", "connect-timeout", "local-infile", "disable-local-infile", "replication-probe", "enable-reads-from-master", "repl-parse-query", - "ssl-cipher", "max-allowed-packet", - "protocol", "shared-memory-base-name", + "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", + "multi-results", "multi-queries", NullS }; @@ -1101,6 +1116,12 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); #endif break; + case 30: + options->client_flag|= CLIENT_MULTI_RESULTS; + break; + case 31: + options->client_flag|= CLIENT_MULTI_QUERIES | CLIENT_MULTI_RESULTS; + break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); } @@ -1122,7 +1143,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, { MYSQL_ROWS *row; MYSQL_FIELD *field,*result; - ulong lengths[8]; /* Max of fields */ + ulong lengths[9]; /* Max of fields */ DBUG_ENTER("unpack_fields"); field=result=(MYSQL_FIELD*) alloc_root(alloc, @@ -1139,33 +1160,35 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, for (row=data->data; row ; row = row->next,field++) { uchar *pos; - fetch_lengths(&lengths[0], row->data, default_value ? 7 : 6); - field->db = strdup_root(alloc,(char*) row->data[0]); - field->table = strdup_root(alloc,(char*) row->data[1]); - field->org_table= strdup_root(alloc,(char*) row->data[2]); - field->name = strdup_root(alloc,(char*) row->data[3]); - field->org_name = strdup_root(alloc,(char*) row->data[4]); + fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7); + field->catalog = strdup_root(alloc,(char*) row->data[0]); + field->db = strdup_root(alloc,(char*) row->data[1]); + field->table = strdup_root(alloc,(char*) row->data[2]); + field->org_table= strdup_root(alloc,(char*) row->data[3]); + field->name = strdup_root(alloc,(char*) row->data[4]); + field->org_name = strdup_root(alloc,(char*) row->data[5]); - field->db_length= lengths[0]; - field->table_length= lengths[1]; - field->org_table_length= lengths[2]; - field->name_length= lengths[3]; - field->org_name_length= lengths[4]; + field->catalog_length= lengths[0]; + field->db_length= lengths[1]; + field->table_length= lengths[2]; + field->org_table_length= lengths[3]; + field->name_length= lengths[4]; + field->org_name_length= lengths[5]; /* Unpack fixed length parts */ - pos= (uchar*) row->data[5]; + pos= (uchar*) row->data[6]; field->charsetnr= uint2korr(pos); - field->length= (uint) uint3korr(pos+2); - field->type= (enum enum_field_types) pos[5]; - field->flags= uint2korr(pos+6); - field->decimals= (uint) pos[8]; + field->length= (uint) uint4korr(pos+2); + field->type= (enum enum_field_types) pos[6]; + field->flags= uint2korr(pos+7); + field->decimals= (uint) pos[9]; if (INTERNAL_NUM_FIELD(field)) field->flags|= NUM_FLAG; - if (default_value && row->data[6]) + if (default_value && row->data[7]) { - field->def=strdup_root(alloc,(char*) row->data[6]); - field->def_length= lengths[6]; + field->def=strdup_root(alloc,(char*) row->data[7]); + field->def_length= lengths[7]; } else field->def=0; @@ -1236,6 +1259,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, MYF(MY_WME | MY_ZEROFILL)))) { net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); DBUG_RETURN(0); } @@ -1264,6 +1288,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, { free_rows(result); net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); DBUG_RETURN(0); } @@ -1284,6 +1309,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, { free_rows(result); net->last_errno=CR_MALFORMED_PACKET; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); DBUG_RETURN(0); } @@ -1328,17 +1354,18 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) ulong pkt_len,len; uchar *pos, *end_pos; uchar *prev_pos; + NET *net= &mysql->net; if ((pkt_len=net_safe_read(mysql)) == packet_error) return -1; - if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) + if (pkt_len <= 8 && net->read_pos[0] == 254) { if (pkt_len > 1) /* MySQL 4.1 protocol */ - mysql->warning_count= uint2korr(mysql->net.read_pos+1); + mysql->warning_count= uint2korr(net->read_pos+1); return 1; /* End of data */ } prev_pos= 0; /* allowed to write at packet[-1] */ - pos=mysql->net.read_pos; + pos=net->read_pos; end_pos=pos+pkt_len; for (field=0 ; field < fields ; field++) { @@ -1351,8 +1378,9 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) { if (len > (ulong) (end_pos - pos)) { - mysql->net.last_errno=CR_UNKNOWN_ERROR; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + net->last_errno=CR_UNKNOWN_ERROR; + strmov(net->last_error,ER(net->last_errno)); + strmov(net->sqlstate, unknown_sqlstate); return -1; } row[field] = (char*) pos; @@ -1871,6 +1899,7 @@ static my_bool mysql_autenticate(MYSQL *mysql, const char *passwd) if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net)) { net->last_errno= CR_SERVER_LOST; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); goto error; } @@ -1945,6 +1974,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); net->vio = 0; /* If something goes wrong */ + mysql->client_flag=0; /* For handshake */ /* use default options */ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) { @@ -2025,6 +2055,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) { net->last_errno=CR_SOCKET_CREATE_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),socket_errno); goto error; } @@ -2038,6 +2069,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("error",("Got error %d on connect to local server", socket_errno)); net->last_errno=CR_CONNECTION_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); goto error; } @@ -2092,6 +2124,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if ((sock = (my_socket) socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR) { net->last_errno=CR_IPSOCK_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),socket_errno); goto error; } @@ -2118,6 +2151,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, { my_gethostbyname_r_free(); net->last_errno=CR_UNKNOWN_HOST; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); goto error; } @@ -2131,6 +2165,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, host)); net->last_errno= CR_CONN_HOST_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); goto error; } @@ -2139,6 +2174,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, { DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); net->last_errno= CR_CONN_UNKNOW_PROTOCOL; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL)); goto error; } @@ -2148,6 +2184,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, vio_delete(net->vio); net->vio = 0; net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); goto error; } @@ -2159,6 +2196,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, vio_poll_read(net->vio, mysql->options.connect_timeout)) { net->last_errno= CR_SERVER_LOST; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); goto error; } @@ -2174,6 +2212,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (mysql->protocol_version != PROTOCOL_VERSION) { net->last_errno= CR_VERSION_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, PROTOCOL_VERSION); goto error; @@ -2216,6 +2255,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (!mysql->charset) { net->last_errno=CR_CANT_READ_CHARSET; + strmov(net->sqlstate, unknown_sqlstate); if (mysql->options.charset_dir) sprintf(net->last_error,ER(net->last_errno), charset_name ? charset_name : "unknown", @@ -2245,6 +2285,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, !(mysql->user=my_strdup(user,MYF(0))) || !(mysql->passwd=my_strdup(passwd,MYF(0)))) { + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); goto error; } @@ -2260,6 +2301,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Send client information for access check */ client_flag|=CLIENT_CAPABILITIES; + if (client_flag & CLIENT_MULTI_QUERIES) + client_flag|= CLIENT_MULTI_RESULTS; #ifdef HAVE_OPENSSL if (mysql->options.ssl_key || mysql->options.ssl_cert || @@ -2282,10 +2325,12 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (client_flag & CLIENT_PROTOCOL_41) { - /* 4.1 server and 4.1 client has a 4 byte option flag */ + /* 4.1 server and 4.1 client has a 32 byte option flag */ int4store(buff,client_flag); int4store(buff+4,max_allowed_packet); - end= buff+8; + buff[8]= mysql->charset->number; + bzero(buff+9, 32-9); + end= buff+32; } else { @@ -2305,6 +2350,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, struct st_mysql_options *options= &mysql->options; if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SERVER_LOST; strmov(net->last_error,ER(net->last_errno)); goto error; @@ -2317,6 +2363,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, options->ssl_capath, options->ssl_cipher))) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SSL_CONNECTION_ERROR; strmov(net->last_error,ER(net->last_errno)); goto error; @@ -2325,6 +2372,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), mysql->net.vio, (long) (mysql->options.connect_timeout))) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SSL_CONNECTION_ERROR; strmov(net->last_error,ER(net->last_errno)); goto error; @@ -2385,6 +2433,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Write authentication package */ if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SERVER_LOST; strmov(net->last_error,ER(net->last_errno)); goto error; @@ -2434,7 +2483,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, error: reset_sigpipe(mysql); - DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); + DBUG_PRINT("error",("message: %u/%s (%s)", + net->last_errno, net->sqlstate, net->last_error)); { /* Free alloced memory */ my_bool free_me=mysql->free_me; @@ -2477,6 +2527,7 @@ static my_bool mysql_reconnect(MYSQL *mysql) { /* Allow reconnect next time */ mysql->server_status&= ~SERVER_STATUS_IN_TRANS; + strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->net.last_errno=CR_SERVER_GONE_ERROR; strmov(mysql->net.last_error,ER(mysql->net.last_errno)); DBUG_RETURN(1); @@ -2491,6 +2542,7 @@ static my_bool mysql_reconnect(MYSQL *mysql) { mysql->net.last_errno= tmp_mysql.net.last_errno; strmov(mysql->net.last_error, tmp_mysql.net.last_error); + strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); DBUG_RETURN(1); } tmp_mysql.free_me=mysql->free_me; @@ -2864,46 +2916,52 @@ send_file_to_server(MYSQL *mysql, const char *filename) my_bool result= 1; uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); char *buf, tmp_name[FN_REFLEN]; + NET *net= &mysql->net; DBUG_ENTER("send_file_to_server"); if (!(buf=my_malloc(packet_length,MYF(0)))) { - strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY)); + strmov(net->sqlstate, unknown_sqlstate); + strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); DBUG_RETURN(1); } fn_format(tmp_name,filename,"","",4); /* Convert to client format */ if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) { - my_net_write(&mysql->net,"",0); /* Server needs one packet */ - net_flush(&mysql->net); - mysql->net.last_errno=EE_FILENOTFOUND; - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - EE(mysql->net.last_errno),tmp_name, errno); + my_net_write(net,"",0); /* Server needs one packet */ + net_flush(net); + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=EE_FILENOTFOUND; + my_snprintf(net->last_error,sizeof(net->last_error)-1, + EE(net->last_errno),tmp_name, errno); goto err; } while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) { - if (my_net_write(&mysql->net,buf,readcount)) + if (my_net_write(net,buf,readcount)) { DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); - mysql->net.last_errno=CR_SERVER_LOST; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); goto err; } } /* Send empty packet to mark end of file */ - if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net)) + if (my_net_write(net,"",0) || net_flush(net)) { - mysql->net.last_errno=CR_SERVER_LOST; - sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno); + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=CR_SERVER_LOST; + sprintf(net->last_error,ER(net->last_errno),errno); goto err; } if (readcount < 0) { - mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */ - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=EE_READ; /* the errmsg for not entire file read */ + my_snprintf(net->last_error,sizeof(net->last_error)-1, tmp_name,errno); goto err; } @@ -2935,6 +2993,7 @@ mysql_store_result(MYSQL *mysql) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { + strmov(mysql->net.sqlstate, unknown_sqlstate); strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); DBUG_RETURN(0); @@ -2945,6 +3004,7 @@ mysql_store_result(MYSQL *mysql) mysql->field_count), MYF(MY_WME | MY_ZEROFILL)))) { + strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->net.last_errno=CR_OUT_OF_MEMORY; strmov(mysql->net.last_error, ER(mysql->net.last_errno)); DBUG_RETURN(0); @@ -2990,6 +3050,7 @@ mysql_use_result(MYSQL *mysql) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { + strmov(mysql->net.sqlstate, unknown_sqlstate); strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); DBUG_RETURN(0); @@ -3319,6 +3380,7 @@ mysql_stat(MYSQL *mysql) mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */ if (!mysql->net.read_pos[0]) { + strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->net.last_errno=CR_WRONG_HOST_INFO; strmov(mysql->net.last_error, ER(mysql->net.last_errno)); return mysql->net.last_error; @@ -3511,6 +3573,11 @@ uint STDCALL mysql_errno(MYSQL *mysql) return mysql->net.last_errno; } +const char *STDCALL mysql_sqlstate(MYSQL *mysql) +{ + return mysql->net.sqlstate; +} + const char * STDCALL mysql_error(MYSQL *mysql) { return mysql->net.last_error; @@ -3761,7 +3828,8 @@ myodbc_remove_escape(MYSQL *mysql,char *name) Set the internal stmt error messages */ -static void set_stmt_error(MYSQL_STMT * stmt, int errcode) +static void set_stmt_error(MYSQL_STMT * stmt, int errcode, + const char *sqlstate) { DBUG_ENTER("set_stmt_error"); DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode))); @@ -3769,6 +3837,7 @@ static void set_stmt_error(MYSQL_STMT * stmt, int errcode) stmt->last_errno= errcode; strmov(stmt->last_error, ER(errcode)); + strmov(stmt->sqlstate, sqlstate); DBUG_VOID_RETURN; } @@ -3778,15 +3847,17 @@ static void set_stmt_error(MYSQL_STMT * stmt, int errcode) Copy error message to statement handler */ -static void set_stmt_errmsg(MYSQL_STMT * stmt, char *err, int errcode) +static void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode, + const char *sqlstate) { DBUG_ENTER("set_stmt_error_msg"); - DBUG_PRINT("enter", ("error: %d '%s'", errcode, err)); + DBUG_PRINT("enter", ("error: %d/%s '%s'", errcode, sqlstate, err)); DBUG_ASSERT(stmt != 0); stmt->last_errno= errcode; if (err && err[0]) strmov(stmt->last_error, err); + strmov(stmt->sqlstate, sqlstate); DBUG_VOID_RETURN; } @@ -3796,7 +3867,7 @@ static void set_stmt_errmsg(MYSQL_STMT * stmt, char *err, int errcode) Set the internal error message to mysql handler */ -static void set_mysql_error(MYSQL * mysql, int errcode) +static void set_mysql_error(MYSQL * mysql, int errcode, const char *sqlstate) { DBUG_ENTER("set_mysql_error"); DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode))); @@ -3804,6 +3875,7 @@ static void set_mysql_error(MYSQL * mysql, int errcode) mysql->net.last_errno= errcode; strmov(mysql->net.last_error, ER(errcode)); + strmov(mysql->net.sqlstate, sqlstate); } @@ -3873,7 +3945,7 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) mysql->server_status|= SERVER_STATUS_IN_TRANS; mysql->extra_info= net_field_length_ll(&pos); - if (!(fields_data= read_rows(mysql, (MYSQL_FIELD*) 0, 8))) + if (!(fields_data= read_rows(mysql, (MYSQL_FIELD*) 0, 9))) DBUG_RETURN(1); if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root, field_count,0, @@ -3885,7 +3957,7 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) (param_count + field_count)))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(0); } stmt->bind= (stmt->params + param_count); @@ -3915,7 +3987,7 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) #ifdef CHECK_EXTRA_ARGUMENTS if (!query) { - set_mysql_error(mysql, CR_NULL_POINTER); + set_mysql_error(mysql, CR_NULL_POINTER, unknown_sqlstate); DBUG_RETURN(0); } #endif @@ -3925,7 +3997,7 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) !(stmt->query= my_strdup_with_length((byte *) query, length, MYF(0)))) { my_free((gptr) stmt, MYF(MY_ALLOW_ZERO_PTR)); - set_mysql_error(mysql, CR_OUT_OF_MEMORY); + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(0); } if (simple_command(mysql, COM_PREPARE, query, length, 1)) @@ -4266,7 +4338,7 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) */ if ((my_realloc_str(net, 9 + *param->length))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(1); } (*param->store_param_func)(net, param); @@ -4293,7 +4365,7 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length) length, 1) || mysql_read_query_result(mysql)) { - set_stmt_errmsg(stmt, net->last_error, net->last_errno); + set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); DBUG_RETURN(1); } stmt->state= MY_ST_EXECUTE; @@ -4315,7 +4387,7 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt) if (stmt->state == MY_ST_UNKNOWN) { - set_stmt_error(stmt, CR_NO_PREPARE_STMT); + set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); DBUG_RETURN(1); } if (stmt->param_count) @@ -4331,7 +4403,7 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt) if (!stmt->param_buffers) { /* Parameters exists, but no bound buffers */ - set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND); + set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND, unknown_sqlstate); DBUG_RETURN(1); } #endif @@ -4366,7 +4438,7 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt) /* TODO: Look into avoding the following memdup */ if (!(param_data= my_memdup((const char*) net->buff, length, MYF(0)))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(1); } net->write_pos= net->buff; /* Reset for net_write() */ @@ -4417,12 +4489,12 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind) #ifdef CHECK_EXTRA_ARGUMENTS if (stmt->state == MY_ST_UNKNOWN) { - set_stmt_error(stmt, CR_NO_PREPARE_STMT); + set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); DBUG_RETURN(1); } if (!stmt->param_count) { - set_stmt_error(stmt, CR_NO_PARAMETERS_EXISTS); + set_stmt_error(stmt, CR_NO_PARAMETERS_EXISTS, unknown_sqlstate); DBUG_RETURN(1); } #endif @@ -4505,6 +4577,7 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind) param->store_param_func= store_param_str; break; default: + strmov(stmt->sqlstate, unknown_sqlstate); sprintf(stmt->last_error, ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE), param->buffer_type, count); @@ -4550,7 +4623,7 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number, if (param_number >= stmt->param_count) { - set_stmt_error(stmt, CR_INVALID_PARAMETER_NO); + set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate); DBUG_RETURN(1); } param= stmt->params+param_number; @@ -4561,6 +4634,7 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number, Long data handling should be used only for string/binary types only */ + strmov(stmt->sqlstate, unknown_sqlstate); sprintf(stmt->last_error, ER(stmt->last_errno= CR_INVALID_BUFFER_USE), param->param_number); DBUG_RETURN(1); @@ -4583,8 +4657,8 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number, if (advanced_command(mysql, COM_LONG_DATA, extra_data, MYSQL_LONG_DATA_HEADER, data, length, 1)) { - set_stmt_errmsg(stmt,(char *) mysql->net.last_error, - mysql->net.last_errno); + set_stmt_errmsg(stmt, mysql->net.last_error, + mysql->net.last_errno, mysql->net.sqlstate); DBUG_RETURN(1); } } @@ -5123,12 +5197,12 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) #ifdef CHECK_EXTRA_ARGUMENTS if (stmt->state == MY_ST_UNKNOWN) { - set_stmt_error(stmt, CR_NO_PREPARE_STMT); + set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); DBUG_RETURN(1); } if (!bind) { - set_stmt_error(stmt, CR_NULL_POINTER); + set_stmt_error(stmt, CR_NULL_POINTER, unknown_sqlstate); DBUG_RETURN(1); } #endif @@ -5208,6 +5282,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) param->fetch_result= fetch_result_str; break; default: + strmov(stmt->sqlstate, unknown_sqlstate); sprintf(stmt->last_error, ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE), param->buffer_type, param_count); @@ -5296,8 +5371,8 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt) { if (packet_error == net_safe_read(mysql)) { - set_stmt_errmsg(stmt,(char *)mysql->net.last_error, - mysql->net.last_errno); + set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, + mysql->net.sqlstate); DBUG_RETURN(1); } if (mysql->net.read_pos[0] == 254) @@ -5447,8 +5522,9 @@ static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt) mysql= mysql->last_used_con; if ((pkt_len= net_safe_read(mysql)) == packet_error) { - set_stmt_errmsg(stmt,(char *)mysql->net.last_error, - mysql->net.last_errno); + set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, + mysql->net.sqlstate); + DBUG_RETURN(0); } if (mysql->net.read_pos[0] == 254) /* end of data */ @@ -5457,8 +5533,8 @@ static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt) if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) { - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); + set_stmt_errmsg(stmt, ER(CR_OUT_OF_MEMORY), CR_OUT_OF_MEMORY, + unknown_sqlstate); DBUG_RETURN(0); } init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ @@ -5474,8 +5550,8 @@ static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt) !(cur->data= ((MYSQL_ROW) alloc_root(&result->alloc, pkt_len)))) { free_rows(result); - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->last_error,ER(net->last_errno)); + set_stmt_errmsg(stmt, ER(CR_OUT_OF_MEMORY), CR_OUT_OF_MEMORY, + unknown_sqlstate); DBUG_RETURN(0); } *prev_ptr= cur; @@ -5514,7 +5590,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { - set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC); + set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); DBUG_RETURN(1); } mysql->status= MYSQL_STATUS_READY; /* server is ready */ @@ -5523,7 +5599,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) stmt->field_count), MYF(MY_WME | MY_ZEROFILL)))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(1); } stmt->result_buffered= 1; @@ -5663,7 +5739,8 @@ static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) int4store(buff, stmt->stmt_id); if (simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)) { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno); + set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, + mysql->net.sqlstate); stmt->mysql= NULL; /* connection isn't valid anymore */ DBUG_RETURN(1); } @@ -5694,6 +5771,12 @@ uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt) DBUG_RETURN(stmt->last_errno); } +const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt) +{ + DBUG_ENTER("mysql_stmt_sqlstate"); + DBUG_RETURN(stmt->sqlstate); +} + /* Return statement error message */ @@ -5775,6 +5858,7 @@ my_bool STDCALL mysql_next_result(MYSQL *mysql) mysql->net.last_error[0]= 0; mysql->net.last_errno= 0; + strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->affected_rows= ~(my_ulonglong) 0; if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) diff --git a/sql/field.cc b/sql/field.cc index 5c3961a949e..3397e9fa0ea 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5519,6 +5519,6 @@ void Field::set_warning(const uint level, const uint code) { THD *thd= current_thd; thd->cuted_fields++; - push_warning_printf(thd, (MYSQL_ERROR::enum_warning_level)level, + push_warning_printf(thd, (MYSQL_ERROR::enum_warning_level) level, code, ER(code), field_name, thd->row_count); } diff --git a/sql/field.h b/sql/field.h index cf08b1a9717..f16af9cfe0f 100644 --- a/sql/field.h +++ b/sql/field.h @@ -212,8 +212,7 @@ public: virtual bool get_time(TIME *ltime); virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } virtual void set_charset(CHARSET_INFO *charset) { } - virtual void set_warning(const unsigned int level, - const unsigned int code); + void set_warning(const unsigned int level, const unsigned int code); friend bool reopen_table(THD *,struct st_table *,bool); friend int cre_myisam(my_string name, register TABLE *form, uint options, ulonglong auto_increment_value); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c618b6bacd3..712c8853a20 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -384,7 +384,7 @@ void table_cache_init(void); void table_cache_free(void); uint cached_tables(void); void kill_mysql(void); -void close_connection(NET *net,uint errcode=0,bool lock=1); +void close_connection(THD *thd, uint errcode, bool lock); bool check_access(THD *thd, ulong access, const char *db=0, ulong *save_priv=0, bool no_grant=0, bool no_errors=0); bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6603e4c306a..fe78c0fe27c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -597,7 +597,6 @@ static void close_connections(void) /* Force remaining threads to die by closing the connection to the client */ - (void) my_net_init(&net, (st_vio*) 0); for (;;) { DBUG_PRINT("quit",("Locking LOCK_thread_count")); @@ -609,17 +608,16 @@ static void close_connections(void) break; } #ifndef __bsdi__ // Bug in BSDI kernel - if ((net.vio=tmp->net.vio) != 0) + if (tmp->net.vio) { sql_print_error(ER(ER_FORCING_CLOSE),my_progname, tmp->thread_id,tmp->user ? tmp->user : ""); - close_connection(&net,0,0); + close_connection(tmp,0,0); } #endif DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); (void) pthread_mutex_unlock(&LOCK_thread_count); } - net_end(&net); /* All threads has now been aborted */ DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); (void) pthread_mutex_lock(&LOCK_thread_count); @@ -1215,19 +1213,20 @@ void yyerror(const char *s) #ifndef EMBEDDED_LIBRARY -void close_connection(NET *net,uint errcode,bool lock) +void close_connection(THD *thd, uint errcode, bool lock) { - st_vio* vio; + st_vio *vio; DBUG_ENTER("close_connection"); DBUG_PRINT("enter",("fd: %s error: '%s'", - net->vio? vio_description(net->vio):"(not connected)", - errcode ? ER(errcode) : "")); + thd->net.vio ? vio_description(thd->net.vio) : + "(not connected)", + errcode ? ER(errcode) : "")); if (lock) (void) pthread_mutex_lock(&LOCK_thread_count); - if ((vio=net->vio) != 0) + if ((vio=thd->net.vio) != 0) { if (errcode) - net_send_error(net,errcode,ER(errcode)); /* purecov: inspected */ + send_error(thd, errcode, ER(errcode)); /* purecov: inspected */ vio_close(vio); /* vio is freed in delete thd */ } if (lock) @@ -2717,7 +2716,7 @@ static void create_new_thread(THD *thd) if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop) { DBUG_PRINT("error",("Too many connections")); - close_connection(net,ER_CON_COUNT_ERROR); + close_connection(thd, ER_CON_COUNT_ERROR, 1); delete thd; DBUG_VOID_RETURN; } @@ -2772,7 +2771,7 @@ static void create_new_thread(THD *thd) (void) pthread_mutex_unlock(&LOCK_thread_count); net_printf(thd,ER_CANT_CREATE_THREAD,error); (void) pthread_mutex_lock(&LOCK_thread_count); - close_connection(net,0,0); + close_connection(thd,0,0); delete thd; (void) pthread_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; @@ -3093,7 +3092,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) || my_net_init(&thd->net, thd->net.vio)) { - close_connection(&thd->net,ER_OUT_OF_RESOURCES); + close_connection(thd, ER_OUT_OF_RESOURCES, 1); delete thd; continue; } @@ -3294,7 +3293,7 @@ Send number of connection to client event_client_read,event_server_wrote,event_server_read)) || my_net_init(&thd->net, thd->net.vio)) { - close_connection(&thd->net,ER_OUT_OF_RESOURCES); + close_connection(thd, ER_OUT_OF_RESOURCES, 1); delete thd; error_allow = TRUE; } @@ -5284,6 +5283,11 @@ static void get_options(int argc,char **argv) if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); + if (argc > 0) + { + fprintf(stderr, "%s: Too many arguments.\nUse --help to get a list of available options\n", my_progname); + exit(ho_error); + } #if defined(HAVE_BROKEN_REALPATH) my_use_symdir=0; diff --git a/sql/protocol.cc b/sql/protocol.cc index 09531f0922c..848321c1576 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -52,7 +52,7 @@ void send_error(THD *thd, uint sql_errno, const char *err) { #ifndef EMBEDDED_LIBRARY uint length; - char buff[MYSQL_ERRMSG_SIZE+2]; + char buff[MYSQL_ERRMSG_SIZE+2], *pos; #endif NET *net= &thd->net; DBUG_ENTER("send_error"); @@ -98,7 +98,14 @@ void send_error(THD *thd, uint sql_errno, const char *err) if (net->return_errno) { // new client code; Add errno before message int2store(buff,sql_errno); - length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff); + pos= buff+2; + if (thd->client_capabilities & CLIENT_PROTOCOL_41) + { + /* The first # is to make the protocol backward compatible */ + strmov(buff+2, "#000000"); + pos= buff + 2 + SQLSTATE_LENGTH +1; + } + length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff); err=buff; } else @@ -113,26 +120,6 @@ void send_error(THD *thd, uint sql_errno, const char *err) DBUG_VOID_RETURN; } -/* - Send an error to the client when a connection is forced close - This is used by mysqld.cc, which doesn't have a THD -*/ - -#ifndef EMBEDDED_LIBRARY -void net_send_error(NET *net, uint sql_errno, const char *err) -{ - char buff[2]; - uint length; - DBUG_ENTER("send_net_error"); - - int2store(buff,sql_errno); - length=(uint) strlen(err); - set_if_smaller(length,MYSQL_ERRMSG_SIZE-1); - net_write_command(net,(uchar) 255, buff, 2, err, length); - DBUG_VOID_RETURN; -} -#endif - /* Send a warning to the end user @@ -173,7 +160,7 @@ net_printf(THD *thd, uint errcode, ...) #ifndef EMBEDDED_LIBRARY const char *text_pos; #else - char text_pos[500]; + char text_pos[1024]; #endif int head_length= NET_HEADER_SIZE; NET *net= &thd->net; @@ -199,9 +186,11 @@ net_printf(THD *thd, uint errcode, ...) format=va_arg(args,char*); errcode= ER_UNKNOWN_ERROR; } - offset= net->return_errno ? 2 : 0; + offset= (net->return_errno ? + ((thd->client_capabilities & CLIENT_PROTOCOL_41) ? + 2+SQLSTATE_LENGTH+1 : 2) : 0); #ifndef EMBEDDED_LIBRARY - text_pos=(char*) net->buff+head_length+offset+1; + text_pos=(char*) net->buff + head_length + offset + 1; #endif (void) vsprintf(my_const_cast(char*) (text_pos),format,args); length=(uint) strlen((char*) text_pos); @@ -228,7 +217,15 @@ net_printf(THD *thd, uint errcode, ...) net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); net->buff[head_length]=(uchar) 255; // Error package if (offset) - int2store(text_pos-2, errcode); + { + uchar *pos= net->buff+head_length+1; + int2store(pos, errcode); + if (thd->client_capabilities & CLIENT_PROTOCOL_41) + { + /* The first # is to make the protocol backward compatible */ + memcpy(pos+2, "#000000", SQLSTATE_LENGTH +1); + } + } VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset)); #else net->last_errno= errcode; @@ -502,6 +499,7 @@ bool Protocol::send_fields(List *list, uint flag) String tmp((char*) buff,sizeof(buff),&my_charset_bin); Protocol_simple prot(thd); String *packet= prot.storage_packet(); + CHARSET_INFO *thd_charset= thd->charset(); DBUG_ENTER("send_fields"); if (flag & 1) @@ -526,36 +524,37 @@ bool Protocol::send_fields(List *list, uint flag) if (thd->client_capabilities & CLIENT_PROTOCOL_41) { - if (prot.store(field.db_name, (uint) strlen(field.db_name), - cs, thd->charset()) || + if (prot.store("std", 3, cs, thd_charset) || + prot.store(field.db_name, (uint) strlen(field.db_name), + cs, thd_charset) || prot.store(field.table_name, (uint) strlen(field.table_name), - cs, thd->charset()) || + cs, thd_charset) || prot.store(field.org_table_name, (uint) strlen(field.org_table_name), - cs, thd->charset()) || + cs, thd_charset) || prot.store(field.col_name, (uint) strlen(field.col_name), - cs, thd->charset()) || + cs, thd_charset) || prot.store(field.org_col_name, (uint) strlen(field.org_col_name), - cs, thd->charset()) || + cs, thd_charset) || packet->realloc(packet->length()+12)) goto err; /* Store fixed length fields */ pos= (char*) packet->ptr()+packet->length(); - *pos++= 11; // Length of packed fields + *pos++= 12; // Length of packed fields int2store(pos, field.charsetnr); - int3store(pos+2, field.length); - pos[5]= field.type; - int2store(pos+6,field.flags); - pos[8]= (char) field.decimals; - pos[9]= 0; // For the future + int4store(pos+2, field.length); + pos[6]= field.type; + int2store(pos+7,field.flags); + pos[9]= (char) field.decimals; pos[10]= 0; // For the future - pos+= 11; + pos[11]= 0; // For the future + pos+= 12; } else { if (prot.store(field.table_name, (uint) strlen(field.table_name), - cs, thd->charset()) || + cs, thd_charset) || prot.store(field.col_name, (uint) strlen(field.col_name), - cs, thd->charset()) || + cs, thd_charset) || packet->realloc(packet->length()+10)) goto err; pos= (char*) packet->ptr()+packet->length(); @@ -893,9 +892,10 @@ bool Protocol_simple::store_time(TIME *tm) #endif char buff[40]; uint length; + uint day= (tm->year || tm->month) ? 0 : tm->day; length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d", tm->neg ? "-" : "", - (long) tm->day*3600L+(long) tm->hour, + (long) day*24L+(long) tm->hour, (int) tm->minute, (int) tm->second)); return net_store_data((char*) buff, length); diff --git a/sql/protocol.h b/sql/protocol.h index dd644afd335..2110f1877c2 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -162,7 +162,6 @@ void net_printf(THD *thd,uint sql_errno, ...); void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); void send_eof(THD *thd, bool no_flush=0); -void net_send_error(NET *net, uint sql_errno, const char *err); char *net_store_length(char *packet,ulonglong length); char *net_store_length(char *packet,uint length); char *net_store_data(char *to,const char *from, uint length); diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 58769827bed..896537dfe04 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -72,7 +72,7 @@ static int init_failsafe_rpl_thread(THD* thd) if (init_thr_lock() || thd->store_globals()) { - close_connection(&thd->net,ER_OUT_OF_RESOURCES); // is this needed? + close_connection(thd, ER_OUT_OF_RESOURCES, 1); // is this needed? end_thread(thd,0); DBUG_RETURN(-1); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e8f028e3720..e6ffec7ef26 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -601,8 +601,8 @@ check_connections(THD *thd) { /* buff[] needs to big enough to hold the server_version variable */ char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64]; - int client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | - CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION); + ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | + CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION); if (opt_using_transactions) client_flags|=CLIENT_TRANSACTIONS; @@ -644,11 +644,26 @@ check_connections(THD *thd) return(ER_OUT_OF_RESOURCES); thd->client_capabilities=uint2korr(net->read_pos); +#ifdef TO_BE_REMOVED_IN_4_1_RELEASE + /* + This is just a safety check against any client that would use the old + CLIENT_CHANGE_USER flag + */ + if ((thd->client_capabilities & CLIENT_PROTOCOL_41) && + !(thd->client_capabilities & (CLIENT_RESERVED | + CLIENT_SECURE_CONNECTION | + CLIENT_MULTI_RESULTS))) + thd->client_capabilities&= ~CLIENT_PROTOCOL_41; +#endif if (thd->client_capabilities & CLIENT_PROTOCOL_41) { thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16; thd->max_client_packet_length= uint4korr(net->read_pos+4); - end= (char*) net->read_pos+8; + if (!(thd->variables.character_set_client= + get_charset((uint) net->read_pos[8], MYF(0)))) + thd->variables.character_set_client= + global_system_variables.character_set_client; + end= (char*) net->read_pos+32; } else { @@ -778,7 +793,7 @@ pthread_handler_decl(handle_one_connection,arg) // The following calls needs to be done before we call DBUG_ macros if (!(test_flags & TEST_NO_THREADS) & my_thread_init()) { - close_connection(&thd->net,ER_OUT_OF_RESOURCES); + close_connection(thd, ER_OUT_OF_RESOURCES, 1); statistic_increment(aborted_connects,&LOCK_status); end_thread(thd,0); return 0; @@ -805,7 +820,7 @@ pthread_handler_decl(handle_one_connection,arg) #endif if (thd->store_globals()) { - close_connection(&thd->net,ER_OUT_OF_RESOURCES); + close_connection(thd, ER_OUT_OF_RESOURCES, 1); statistic_increment(aborted_connects,&LOCK_status); end_thread(thd,0); return 0; @@ -863,7 +878,7 @@ pthread_handler_decl(handle_one_connection,arg) } end_thread: - close_connection(net); + close_connection(thd, 0, 1); end_thread(thd,1); /* If end_thread returns, we are either running with --one-thread @@ -889,7 +904,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) /* The following must be called before DBUG_ENTER */ if (my_thread_init() || thd->store_globals()) { - close_connection(&thd->net,ER_OUT_OF_RESOURCES); + close_connection(thd, ER_OUT_OF_RESOURCES, 1); thd->fatal_error(); goto end; } @@ -1419,7 +1434,7 @@ restore_user: #ifndef OS2 send_eof(thd); // This is for 'quit request' #endif - close_connection(net); + close_connection(thd, 0, 1); close_thread_tables(thd); // Free before kill free_root(&thd->mem_root,MYF(0)); free_root(&thd->transaction.mem_root,MYF(0)); From cf381ae46b639a9f928a706e7268214aac8b5b48 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 19:10:43 +0300 Subject: [PATCH 237/399] ha_innodb.cc: Remove accidenatlly committed debug printfs when query cache is used sql_update.cc, sql_load.cc, sql_insert.cc, sql_delete.cc: For the transactional query cache algorithm to work we must invalidate the query cache in INSERT/DELETE/UPDATE before writing to the binlog or calling ha_autocommit_... Note that binlog writing may also call commit. The crucial thing is that the transaction which modified data must not be committed BEFORE the query cache is invalidated. sql/sql_delete.cc: For the transactional query cache algorithm to work we must invalidate the query cache in INSERT/DELETE/UPDATE before writing to the binlog or calling ha_autocommit_... Note that binlog writing may also call commit. The crucial thing is that the transaction which modified data must not be committed BEFORE the query cache is invalidated. sql/sql_insert.cc: For the transactional query cache algorithm to work we must invalidate the query cache in INSERT/DELETE/UPDATE before writing to the binlog or calling ha_autocommit_... Note that binlog writing may also call commit. The crucial thing is that the transaction which modified data must not be committed BEFORE the query cache is invalidated. sql/sql_load.cc: For the transactional query cache algorithm to work we must invalidate the query cache in INSERT/DELETE/UPDATE before writing to the binlog or calling ha_autocommit_... Note that binlog writing may also call commit. The crucial thing is that the transaction which modified data must not be committed BEFORE the query cache is invalidated. sql/sql_update.cc: For the transactional query cache algorithm to work we must invalidate the query cache in INSERT/DELETE/UPDATE before writing to the binlog or calling ha_autocommit_... Note that binlog writing may also call commit. The crucial thing is that the transaction which modified data must not be committed BEFORE the query cache is invalidated. sql/ha_innodb.cc: Remove accidenatlly committed debug printfs when query cache is used --- sql/ha_innodb.cc | 4 ++-- sql/sql_delete.cc | 24 +++++++++++++----------- sql/sql_insert.cc | 33 ++++++++++++++++++++------------- sql/sql_load.cc | 6 ++++-- sql/sql_update.cc | 41 +++++++++++++++++++++++------------------ 5 files changed, 62 insertions(+), 46 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index a426dc5a9a9..bf4dc7e5066 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -560,12 +560,12 @@ innobase_query_caching_of_table_permitted( #endif if (row_search_check_if_query_cache_permitted(trx, norm_name)) { - printf("Query cache for %s permitted\n", norm_name); + /* printf("Query cache for %s permitted\n", norm_name); */ return((my_bool)TRUE); } - printf("Query cache for %s NOT permitted\n", norm_name); + /* printf("Query cache for %s NOT permitted\n", norm_name); */ return((my_bool)FALSE); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a12f6efb006..9c1743eeb12 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -178,6 +178,15 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, (void) table->file->extra(HA_EXTRA_NORMAL); cleanup: + /* + Invalidate the table in the query cache if something changed. This must + be before binlog writing and ha_autocommit_... + */ + if (deleted) + { + query_cache_invalidate3(thd, table_list, 1); + } + transactional_table= table->file->has_transactions(); log_delayed= (transactional_table || table->tmp_table); if (deleted && (error <= 0 || !transactional_table)) @@ -199,14 +208,6 @@ cleanup: error=1; } - /* - Store table for future invalidation or invalidate it in - the query cache if something changed - */ - if (deleted) - { - query_cache_invalidate3(thd, table_list, 1); - } if (thd->lock) { mysql_unlock_tables(thd, thd->lock); @@ -480,6 +481,10 @@ bool multi_delete::send_eof() /* reset used flags */ thd->proc_info="end"; + /* We must invalidate the query cache before binlog writing and + ha_autocommit_... */ + if (deleted) + query_cache_invalidate3(thd, delete_tables, 1); /* Write the SQL statement to the binlog if we deleted @@ -504,9 +509,6 @@ bool multi_delete::send_eof() if (transactional_tables) if (ha_autocommit_or_rollback(thd,local_error > 0)) local_error=1; - - if (deleted) - query_cache_invalidate3(thd, delete_tables, 1); if (local_error) ::send_error(thd); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9be0270947a..48cc6d4e254 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -344,7 +344,18 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, else if (table->next_number_field) id=table->next_number_field->val_int(); // Return auto_increment value + /* + Invalidate the table in the query cache if something changed. + For the transactional algorithm to work the invalidation must be + before binlog writing and ha_autocommit_... + */ + if (info.copied || info.deleted) + { + query_cache_invalidate3(thd, table_list, 1); + } + transactional_table= table->file->has_transactions(); + log_delayed= (transactional_table || table->tmp_table); if ((info.copied || info.deleted) && (error <= 0 || !transactional_table)) { @@ -362,14 +373,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, if (transactional_table) error=ha_autocommit_or_rollback(thd,error); - /* - Store table for future invalidation or invalidate it in - the query cache if something changed - */ - if (info.copied || info.deleted) - { - query_cache_invalidate3(thd, table_list, 1); - } if (thd->lock) { mysql_unlock_tables(thd, thd->lock); @@ -1420,11 +1423,11 @@ void select_insert::send_error(uint errcode,const char *err) ::send_error(thd,errcode,err); table->file->extra(HA_EXTRA_NO_CACHE); table->file->activate_all_index(thd); - ha_rollback_stmt(thd); if (info.copied || info.deleted) { query_cache_invalidate3(thd, table, 1); } + ha_rollback_stmt(thd); } @@ -1435,6 +1438,14 @@ bool select_insert::send_eof() error=table->file->activate_all_index(thd); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + /* We must invalidate the table in the query cache before binlog writing + and ha_autocommit_... */ + + if (info.copied || info.deleted) + { + query_cache_invalidate3(thd, table, 1); + } + /* Write to binlog before commiting transaction */ if (mysql_bin_log.is_open()) { @@ -1444,10 +1455,6 @@ bool select_insert::send_eof() } if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error) error=error2; - if (info.copied || info.deleted) - { - query_cache_invalidate3(thd, table, 1); - } if (error) { table->file->print_error(error,MYF(0)); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 7476472a79a..b79a3b739d7 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -283,6 +283,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->copy_blobs=0; thd->count_cuted_fields=0; /* Don`t calc cuted fields */ + /* We must invalidate the table in query cache before binlog writing and + ha_autocommit_... */ + query_cache_invalidate3(thd, table_list, 0); + if (error) { if (transactional_table) @@ -344,8 +348,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } if (transactional_table) error=ha_autocommit_or_rollback(thd,error); - query_cache_invalidate3(thd, table_list, 0); - err: if (thd->lock) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 9d4d7ccbbab..62fcb02163d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -332,6 +332,21 @@ int mysql_update(THD *thd, free_io_cache(table); // If ORDER BY thd->proc_info="end"; VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY)); + + /* + Invalidate the table in the query cache if something changed. + This must be before binlog writing and ha_autocommit_... + */ + if (updated) + { + query_cache_invalidate3(thd, table_list, 1); + } + if (thd->lock) + { + mysql_unlock_tables(thd, thd->lock); + thd->lock=0; + } + transactional_table= table->file->has_transactions(); log_delayed= (transactional_table || table->tmp_table); if (updated && (error <= 0 || !transactional_table)) @@ -353,20 +368,6 @@ int mysql_update(THD *thd, error=1; } - /* - Store table for future invalidation or invalidate it in - the query cache if something changed - */ - if (updated) - { - query_cache_invalidate3(thd, table_list, 1); - } - if (thd->lock) - { - mysql_unlock_tables(thd, thd->lock); - thd->lock=0; - } - delete select; free_underlaid_joins(thd, &thd->lex.select_lex); if (error >= 0) @@ -950,6 +951,14 @@ bool multi_update::send_eof() int local_error = (table_count) ? do_updates(0) : 0; thd->proc_info= "end"; + /* We must invalidate the query cache before binlog writing and + ha_autocommit_... */ + + if (updated) + { + query_cache_invalidate3(thd, update_tables, 1); + } + /* Write the SQL statement to the binlog if we updated rows and we succeeded or if we updated some non @@ -988,10 +997,6 @@ bool multi_update::send_eof() sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated, (long) thd->cuted_fields); - if (updated) - { - query_cache_invalidate3(thd, update_tables, 1); - } ::send_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, thd->insert_id_used ? thd->insert_id() : 0L,buff); From 6f8e0d13642a43f35f4deb15437be029df023b45 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 19:11:22 +0300 Subject: [PATCH 238/399] Fix for 64 bit machines (To remove warnings on Itanium) mysys/thr_alarm.c: Safety fix --- include/my_global.h | 5 +++++ mysys/thr_alarm.c | 1 + 2 files changed, 6 insertions(+) diff --git a/include/my_global.h b/include/my_global.h index 15495c60dd7..ca24c21c688 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -634,7 +634,12 @@ extern double my_atof(const char*); Max size that must be added to a so that we know Size to make adressable obj. */ +#if SIZEOF_CHARP == 4 typedef long my_ptrdiff_t; +#else +typedef long long my_ptrdiff_t; +#endif + #define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) #define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) /* Size to make adressable obj. */ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 1b58a0274ff..ca8e4e8bcb6 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -169,6 +169,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME)))) { DBUG_PRINT("info", ("failed my_malloc()")); + *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_RETURN(1); From cd554e9ed61f3140cf213f62b8ce17bdf197467b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 20:09:53 +0300 Subject: [PATCH 239/399] Fixed bug when installing mysqld as a service with 2 arguments (option + service-name) --- sql/mysqld.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f729dcfd17a..b0b9837dff3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2230,9 +2230,12 @@ int main(int argc, char **argv) return 0; if (Service.IsService(argv[2])) { - /* start an optional service */ + /* + mysqld was started as + mysqld --defaults-file=my_path\my.ini service-name + */ use_opt_args=1; - opt_argc=argc; + opt_argc= 2; // Skip service-name opt_argv=argv; start_mode= 1; Service.Init(argv[2], mysql_service); From da9bf1dec30f9d1cda414d0a96ca93c11b1a77e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 20:48:40 +0300 Subject: [PATCH 240/399] ixed wrong unlock of tables (new bug) sql/sql_delete.cc: Comment cleanup sql/sql_insert.cc: Comment cleanup sql/sql_load.cc: Comment cleanup sql/sql_update.cc: Fixed wrong unlock of tables. (Unlock must be done after writing to binary log --- sql/sql_delete.cc | 6 ++++-- sql/sql_insert.cc | 12 ++++-------- sql/sql_load.cc | 6 ++++-- sql/sql_update.cc | 13 ++++++------- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 9c1743eeb12..ebb09b99df7 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -481,8 +481,10 @@ bool multi_delete::send_eof() /* reset used flags */ thd->proc_info="end"; - /* We must invalidate the query cache before binlog writing and - ha_autocommit_... */ + /* + We must invalidate the query cache before binlog writing and + ha_autocommit_... + */ if (deleted) query_cache_invalidate3(thd, delete_tables, 1); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 48cc6d4e254..1908f898a27 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -350,9 +350,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, before binlog writing and ha_autocommit_... */ if (info.copied || info.deleted) - { query_cache_invalidate3(thd, table_list, 1); - } transactional_table= table->file->has_transactions(); @@ -1424,9 +1422,7 @@ void select_insert::send_error(uint errcode,const char *err) table->file->extra(HA_EXTRA_NO_CACHE); table->file->activate_all_index(thd); if (info.copied || info.deleted) - { query_cache_invalidate3(thd, table, 1); - } ha_rollback_stmt(thd); } @@ -1438,13 +1434,13 @@ bool select_insert::send_eof() error=table->file->activate_all_index(thd); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); - /* We must invalidate the table in the query cache before binlog writing - and ha_autocommit_... */ + /* + We must invalidate the table in the query cache before binlog writing + and ha_autocommit_... + */ if (info.copied || info.deleted) - { query_cache_invalidate3(thd, table, 1); - } /* Write to binlog before commiting transaction */ if (mysql_bin_log.is_open()) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index b79a3b739d7..758ff88477b 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -283,8 +283,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->copy_blobs=0; thd->count_cuted_fields=0; /* Don`t calc cuted fields */ - /* We must invalidate the table in query cache before binlog writing and - ha_autocommit_... */ + /* + We must invalidate the table in query cache before binlog writing and + ha_autocommit_... + */ query_cache_invalidate3(thd, table_list, 0); if (error) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 62fcb02163d..1f6364ec427 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -338,14 +338,7 @@ int mysql_update(THD *thd, This must be before binlog writing and ha_autocommit_... */ if (updated) - { query_cache_invalidate3(thd, table_list, 1); - } - if (thd->lock) - { - mysql_unlock_tables(thd, thd->lock); - thd->lock=0; - } transactional_table= table->file->has_transactions(); log_delayed= (transactional_table || table->tmp_table); @@ -368,6 +361,12 @@ int mysql_update(THD *thd, error=1; } + if (thd->lock) + { + mysql_unlock_tables(thd, thd->lock); + thd->lock=0; + } + delete select; free_underlaid_joins(thd, &thd->lex.select_lex); if (error >= 0) From 1ef96d2b76452c06d6b9aa6ed57767abbb96c769 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 May 2003 20:59:09 +0300 Subject: [PATCH 241/399] Portability fix --- sql/field.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/field.h b/sql/field.h index 3f3e32af285..bd3e942fe6a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -83,7 +83,8 @@ public: virtual void reset_fields() {} virtual void set_default() { - my_ptrdiff_t offset = table->default_values - table->record[0]; + my_ptrdiff_t offset = (my_ptrdiff_t) (table->default_values - + table->record[0]); memcpy(ptr, ptr + offset, pack_length()); if (null_ptr) *null_ptr= ((*null_ptr & (uchar) ~null_bit) | From cf240ee47c0068d6cc241a5a4fc276678a8c9626 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 12:57:02 +0500 Subject: [PATCH 242/399] Index.xml: utf8 was not marked as compiled sql/share/charsets/Index.xml: utf8 was not marked as compiled --- sql/share/charsets/Index.xml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 28cddb90fc5..6e091066654 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -408,8 +408,14 @@ To make maintaining easier please: Unicode UTF-8 Unicode utf-8 - - + + primary + compiled + + + binary + compiled + From b090bd08b8087d97cc3b3ea698917bcc781da3c9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 12:59:08 +0500 Subject: [PATCH 243/399] conf_to_src.c: Changes according to CHARSET_INFO structure strings/conf_to_src.c: Changes according to CHARSET_INFO structure --- strings/conf_to_src.c | 64 +++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/strings/conf_to_src.c b/strings/conf_to_src.c index 69dccbca0a7..b21740f9dbb 100644 --- a/strings/conf_to_src.c +++ b/strings/conf_to_src.c @@ -55,7 +55,7 @@ print_array16(FILE *f, const char *set, const char *name, uint16 *a, int n) { int i; - fprintf(f,"uchar %s_%s[] = {\n", name, set); + fprintf(f,"uint16 %s_%s[] = {\n", name, set); for (i=0 ;icsname && cs->tab_to_uni && cs->ctype && cs->to_upper && cs->to_lower) && - (cs->number && cs->name && cs->sort_order)); + (cs->number && cs->name && + (cs->sort_order || (cs->state & MY_CS_BINSORT)))); } static int add_collation(CHARSET_INFO *cs) @@ -177,18 +178,23 @@ static int my_read_charset_file(const char *filename) void dispcset(FILE *f,CHARSET_INFO *cs) { fprintf(f,"{\n"); - fprintf(f," %d,\n",cs->number); - fprintf(f," MY_CS_COMPILED,\n"); + fprintf(f," %d,%d,%d,\n",cs->number,0,0); + fprintf(f," MY_CS_COMPILED%s%s,\n", + cs->state & MY_CS_BINSORT ? "|MY_CS_BINSORT" : "", + cs->state & MY_CS_PRIMARY ? "|MY_CS_PRIMARY" : ""); if (cs->name) { - fprintf(f," \"%s\",\n",cs->name); fprintf(f," \"%s\",\n",cs->csname); + fprintf(f," \"%s\",\n",cs->name); fprintf(f," \"\",\n"); fprintf(f," ctype_%s,\n",cs->name); fprintf(f," to_lower_%s,\n",cs->name); fprintf(f," to_upper_%s,\n",cs->name); - fprintf(f," sort_order_%s,\n",cs->name); + if (cs->sort_order) + fprintf(f," sort_order_%s,\n",cs->name); + else + fprintf(f," NULL,\n"); fprintf(f," to_uni_%s,\n",cs->name); fprintf(f," from_uni_%s,\n",cs->name); } @@ -205,37 +211,16 @@ void dispcset(FILE *f,CHARSET_INFO *cs) fprintf(f," NULL,\n"); } - fprintf(f," %d,\n",cs->strxfrm_multiply); - fprintf(f," my_strnncoll_simple,\n"); - fprintf(f," my_strnxfrm_simple,\n"); - fprintf(f," my_like_range_simple,\n"); - fprintf(f," my_wild_cmp_8bit,\n"); - fprintf(f," %d,\n",cs->mbmaxlen); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," my_mb_wc_8bit,\n"); - fprintf(f," my_wc_mb_8bit,\n"); - fprintf(f," my_caseup_str_8bit,\n"); - fprintf(f," my_casedn_str_8bit,\n"); - fprintf(f," my_caseup_8bit,\n"); - fprintf(f," my_casedn_8bit,\n"); - fprintf(f," my_tosort_8bit,\n"); - fprintf(f," my_strcasecmp_8bit,\n"); - fprintf(f," my_strncasecmp_8bit,\n"); - fprintf(f," my_hash_caseup_simple,\n"); - fprintf(f," my_hash_sort_simple,\n"); + fprintf(f," \"\",\n"); + fprintf(f," \"\",\n"); fprintf(f," 0,\n"); - fprintf(f," my_snprintf_8bit,\n"); - fprintf(f," my_long10_to_str_8bit,\n"); - fprintf(f," my_longlong10_to_str_8bit,\n"); - fprintf(f," my_fill_8bit,\n"); - fprintf(f," my_strntol_8bit,\n"); - fprintf(f," my_strntoul_8bit,\n"); - fprintf(f," my_strntoll_8bit,\n"); - fprintf(f," my_strntoull_8bit,\n"); - fprintf(f," my_strntod_8bit,\n"); - fprintf(f," my_scan_8bit\n"); + fprintf(f," 0,\n"); + fprintf(f," 0,\n"); + fprintf(f," &my_charset_8bit_handler,\n"); + if (cs->state & MY_CS_BINSORT) + fprintf(f," &my_collation_bin_handler,\n"); + else + fprintf(f," &my_collation_8bit_simple_ci_handler,\n"); fprintf(f,"}\n"); } @@ -262,9 +247,9 @@ main(int argc, char **argv __attribute__((unused))) for (cs=all_charsets; cs < all_charsets+256; cs++) { - if (cs->number) + if (cs->number && !(cs->state & MY_CS_COMPILED)) { - if ( (!simple_cs_is_full(cs)) && (cs->csname) ) + if ( (!simple_cs_is_full(cs)) && (cs->csname)) { sprintf(filename,"%s/%s.xml",argv[1],cs->csname); my_read_charset_file(filename); @@ -280,7 +265,8 @@ main(int argc, char **argv __attribute__((unused))) print_array(f, cs->name, "ctype", cs->ctype, MY_CS_CTYPE_TABLE_SIZE); print_array(f, cs->name, "to_lower", cs->to_lower, MY_CS_TO_LOWER_TABLE_SIZE); print_array(f, cs->name, "to_upper", cs->to_upper, MY_CS_TO_UPPER_TABLE_SIZE); - print_array(f, cs->name, "sort_order", cs->sort_order, MY_CS_SORT_ORDER_TABLE_SIZE); + if (cs->sort_order) + print_array(f, cs->name, "sort_order", cs->sort_order, MY_CS_SORT_ORDER_TABLE_SIZE); print_array16(f, cs->name, "to_uni", cs->tab_to_uni, MY_CS_TO_UNI_TABLE_SIZE); fprintf(f,"#endif\n"); fprintf(f,"\n"); From 245c5086c177f8067c6f1f83e46b183ec8d270fe Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 16:58:57 +0500 Subject: [PATCH 244/399] fixed small merge bug BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + scripts/mysql_install_db.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 6761a96b06b..065b2aee15b 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -114,6 +114,7 @@ venu@myvenu.com venu@work.mysql.com vva@eagle.mysql.r18.ru vva@genie.(none) +vva@mysql.r18.ru walrus@kishkin.ru walrus@mysql.com wax@kishkin.ru diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index b5048054832..15bc834e850 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -164,7 +164,7 @@ then fi # Create database directories mysql & test -if test "$in_rpm" -eq 0 || "$windows" -eq 0 + 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 From 685498e0ad0c9282ef3f605c6378a59e6295ec04 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 15:31:18 +0200 Subject: [PATCH 245/399] Deleted internals.texi (moved to mysqldoc tree - Monty req). BitKeeper/deleted/.del-internals.texi~62b6f580a41c2a43: Delete: Docs/internals.texi --- Docs/internals.texi | 6338 ------------------------------------------- 1 file changed, 6338 deletions(-) delete mode 100644 Docs/internals.texi diff --git a/Docs/internals.texi b/Docs/internals.texi deleted file mode 100644 index ac79724dbe5..00000000000 --- a/Docs/internals.texi +++ /dev/null @@ -1,6338 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c Copyright 2002 MySQL AB -@c -@c %**start of header -@setfilename internals.info - -@c We want the types in the same index -@synindex cp fn - -@iftex -@afourpaper -@end iftex - -@c Get version and other info -@include include.texi - -@ifclear tex-debug -@c This removes the black squares in the right margin -@finalout -@end ifclear - -@c Set background for HTML -@set _body_tags BGCOLOR=#FFFFFF TEXT=#000000 LINK=#101090 VLINK=#7030B0 -@settitle @strong{MySQL} Internals Manual for version @value{mysql_version}. -@setchapternewpage odd -@paragraphindent 0 - -@c %**end of header - -@ifinfo -@format -START-INFO-DIR-ENTRY -* mysql-internals: (mysql-internals). @strong{MySQL} internals. -END-INFO-DIR-ENTRY -@end format -@end ifinfo - -@titlepage -@sp 10 -@center @titlefont{@strong{MySQL} Internals Manual} -@sp 10 -@center Copyright @copyright{} 1998-2002 MySQL AB -@page -@end titlepage - -@node Top, coding guidelines, (dir), (dir) - -@ifinfo -This is a manual about @strong{MySQL} internals. -@end ifinfo - -@menu -* coding guidelines:: Coding Guidelines -* caching:: How MySQL Handles Caching -* flush tables:: How MySQL Handles @code{FLUSH TABLES} -* Algorithms:: -* selects:: How MySQL performs different selects -* transformations:: How MySQL transforms subqueries -* mysys functions:: Functions In The @code{mysys} Library -* DBUG:: DBUG Tags To Use -* protocol:: MySQL Client/Server Protocol -* Fulltext Search:: Fulltext Search in MySQL -* MyISAM Record Structure:: MyISAM Record Structure -* InnoDB Record Structure:: InnoDB Record Structure -* InnoDB Page Structure:: InnoDB Page Structure -* Files in MySQL Sources:: Annotated List Of Files in the MySQL Source Code Distribution -* Files in InnoDB Sources:: Annotated List Of Files in the InnoDB Source Code Distribution -@end menu - - -@node coding guidelines, caching, Top, Top -@chapter Coding Guidelines - -@itemize @bullet - -@item -We use @uref{http://www.bitkeeper.com/, BitKeeper} for source management. - -@item -You should use the @strong{MySQL} 4.1 or 5.0 source for all developments. - -@item -If you have any questions about the @strong{MySQL} source, you can post these -to @email{internals@@lists.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 -least a clean, easy to change interface. - -@item -Reuse code; There is already a lot of algorithms in MySQL for list handling, -queues, dynamic and hashed arrays, sorting, etc. that can be reused. - -@item -Use the @code{my_*} functions like @code{my_read()}/@code{my_write()}/ -@code{my_malloc()} that you can find in the @code{mysys} library instead -of the direct system calls; This will make your code easier to debug and -more portable. - -@item -Try to always write optimized code, so that you don't have to -go back and rewrite it a couple of months later. It's better to -spend 3 times as much time designing and writing an optimal function than -having to do it all over again later on. - -@item -Avoid CPU wasteful code, even where it does not matter, so that -you will not develop sloppy coding habits. - -@item -If you can write it in fewer lines, do it (as long as the code will not -be slower or much harder to read). - -@item -Don't use two commands on the same line. - -@item -Do not check the same pointer for @code{NULL} more than once. - -@item -Use long function and variable names in English. This makes your code -easier to read. - -@item -Use @code{my_var} as opposed to @code{myVar} or @code{MyVar} (@samp{_} -rather than dancing SHIFT to seperate words in identifiers). - -@item -Think assembly - make it easier for the compiler to optimize your code. - -@item -Comment your code when you do something that someone else may think -is not ``trivial''. - -@item -Use @code{libstring} functions (in the @file{strings} directory) -instead of standard @code{libc} string functions whenever possible. - -@item -Avoid using @code{malloc()} (its REAL slow); For memory allocations -that only need to live for the lifetime of one thread, one should use -@code{sql_alloc()} instead. - -@item -Before making big design decisions, please first post a summary of -what you want to do, why you want to do it, and how you plan to do -it. This way we can easily provide you with feedback and also -easily discuss it thoroughly if some other developer thinks there is better -way to do the same thing! - -@item -Class names start with a capital letter. - -@item -Structure types are @code{typedef}'ed to an all-caps identifier. - -@item -Any @code{#define}'s are in all-caps. - -@item -Matching @samp{@{} are in the same column. - -@item -Put the @samp{@{} after a @code{switch} on the same line, as this gives -better overall indentation for the switch statement: - -@example -switch (arg) @{ -@end example - -@item -In all other cases, @samp{@{} and @samp{@}} should be on their own line, except -if there is nothing inside @samp{@{} and @samp{@}}. - -@item -Have a space after @code{if} - -@item -Put a space after @samp{,} for function arguments - -@item -Functions return @samp{0} on success, and non-zero on error, so you can do: - -@example -if(a() || b() || c()) @{ error("something went wrong"); @} -@end example - -@item -Using @code{goto} is okay if not abused. - -@item -Avoid default variable initalizations, use @code{LINT_INIT()} if the -compiler complains after making sure that there is really no way -the variable can be used uninitialized. - -@item -Do not instantiate a class if you do not have to. - -@item -Use pointers rather than array indexing when operating on strings. - -@end itemize - -Suggested mode in emacs: - -@example -(load "cc-mode") -(setq c-mode-common-hook '(lambda () - (turn-on-font-lock) - (setq comment-column 48))) -(setq c-style-alist - (cons - '("MY" - (c-basic-offset . 2) - (c-comment-only-line-offset . 0) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . 0) - (substatement-open . 0) - (label . -) - (statement-cont . +) - (arglist-intro . c-lineup-arglist-intro-after-paren) - (arglist-close . c-lineup-arglist) - )) - ) - c-style-alist)) -(c-set-style "MY") -(setq c-default-style "MY") -@end example - -@node caching, flush tables, coding guidelines, 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 - -@menu -* join_buffer_size:: -@end menu - -@node join_buffer_size, , caching, caching -@section 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, caching, 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, selects, 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 - -@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 selects, transformations, Algorithms, Top -@chapter How MySQL performs different selects - -@menu -* select steps:: -* select select_result:: -* select simple:: -* select structure:: -* select union:: -* select derived:: -* select subselect:: -* select select engine:: -* select union engine:: -* selectexplain:: -@end menu - -@node select steps, select select_result, selects, selects -@section Steps of select executing - -Every select performed in such base steps: -@itemize -@item - JOIN::prepare -@itemize @bullet -@item - initialization and linking JOIN structure to st_select_lex -@item - fix_fields() for all items (after fix_fields we know everything - about item) -@item - moving HAVING to WHERE if possible -@item - initialization procedure if exists -@end itemize -@item - JOIN::optimize -@itemize @bullet -@item - single select optimization -@item - creation first temporary table if need -@end itemize -@item - JOIN::exec -@itemize @bullet -@item - performing select (may be created second temporary table) -@end itemize -@item - JOIN::cleanup -@itemize @bullet -@item - removing all temporary tables, other cleanup -@end itemize -@item - JOIN::reinit -@itemize @bullet -@item - prepare all structures to SELECT executing (with JOIN::exec) -@end itemize -@end itemize - -@node select select_result, select simple, select steps, selects -@section select_result CLASS - -Very important role in SELECT performing have select_result class and -classes inherited from it (usually called with "select_" prefix). This -class provide interface for results transmitting. - -Key methods in this class are following: -@itemize @bullet -@item - @strong{send_fields} sends giving item list headers (type, name, etc..) -@item - @strong{send_data} sends giving item list values as row of table of result -@item - @strong{send_error} send error to used used mainly for error interception, - making some operation and then ::send_error will be called. -@end itemize - -For example there are fillowing select_result classes: -@itemize -@item - @strong{select_send} used for sending results though network layer -@item - @strong{select_export} used for exporting data to file -@item - @strong{multi_delete} used for multi-delete -@item - @strong{select_insert} used for INSERT ... SELECT ... -@item - @strong{multi_update} used for multi-update -@end itemize - -@node select simple, select structure, select select_result, selects -@section SIMPLE or PRIMARY SELECT. - -For performing single primary select SELECT used function mysql_select, -which: -@itemize @bullet -@item - allocate JOIN; -@item - JOIN::prepare; -@item - JOIN::optimize; -@item - JOIN::exec; -@item - JOIN::cleanup. -@end itemize -In previous versions of mysql all SELECTs was performed with help of this -function and mysql_select() was not divided on parts. - -@node select structure, select union, select simple, selects -@section Structure Of Complex Select - -There 2 structures which describe SELECTS: -@itemize @bullet -@item - st_select_lex (SELECT_LEX) it represent SELECT itself -@item - st_select_lex_unit (SELECT_LEX_UNIT) group several selects in bunch -@end itemize -and represent UNION operation (absence of UNION is union -with 1 SELECT and this structure present in any case). In future this -structure will be used for EXCEPT and INTERSECT. - -For example: -@example -(SELECT ... )UNION(SELECT ... (SELECT...)...(SELECT...UNION...SELECT)) - 1 2 3 4 5 6 7 -@end example - -will be represent as -@example ------------------------------------------------------------------------- - level 1 -SELECT_LEX_UNIT(2) -| -+---------------+ -| | -SELECT_LEX(1) SELECT_LEX(3) - | ---------------- | ------------------------------------------------------ - | level 2 - +-------------------+ - | | - SELECT_LEX_UNIT(4) SELECT_LEX_UNIT(6) - | | - | +--------------+ - | | | - SELECT_LEX(4) SELECT_LEX(5) SELECT_LEX(7) - ------------------------------------------------------------------------- -@end example -Note: single subselect 4 have it's own SELECT_LEX_UNIT. - -Most upper SELECT_LEX_UNIT (#2 in example) stored in LEX. -First and most upper SELECT_LEX (#1 in example) stored in LEX, too. -This two structures always exist. - -In time of creating or performing any JOIN::* operation -LEX::current_select point on appropriate SELECT_LEX. - -Only during parsing global (for whole UNION) ORDER_BY & LIMIT clauses -LEX::current_select points to SELECT_LEX_UNIT of this unit to store this -parameter in this SELECT_LEX_UNIT (SELECT_LEX and SELECT_LEX_UNIT are -inherited from st_select_lex_node). - -@node select union, select derived, select structure, selects -@section Non-Subselect UNIONs Executing - -Non subselect unions performed with help of mysql_union(). for now it -divided on following steps: -@itemize -@item - st_select_lex_unit::prepare -@itemize @bullet -@item - create temporary table for union results storing (if UNION witout - ALL option, 'distinct' parameter will be passed to table creation - procedure). Types/lengths of table's fields will be determinated - by first SELECT item list. -@item - create select_union (inherited from select_result) which will - write selects results in this temporary table -@item - allocate JOIN and perform JOIN::prepare for all SELECTs belonged - to UNION -@end itemize -@item - st_select_lex_unit::exec -@itemize @bullet -@item - delete rows from temporary table if it is not first call -@item - if first call call JOIN::optimize else JOIN::reinit and then - JOIN::exec for all SELECTs (select_union will write result for - temporary table). If union is cacheable and this method called - second, (third, ...) time it will do nothing. -@item - call mysql_select on temporary table with global ORDER BY and - LIMIT parameters after collecting results from all SELECTs. -@end itemize -@end itemize -As far as mysql_select need SELECT_LEX structure SELECT_LEX of first -SELECT of this UNION will be passed to it, but also fake_select_lex -parameter will be passed to mysql_select() too, to prevent linking -this SELECT_LEX with JOIN on this mysql_select() session. - -PROBLEM: this fake select need workaround in many places. - -@node select derived, select subselect, select union, selects -@section Derived Tables Executing - -Derived tables processing is first operation on any query. It performed -before creation list of tables of whole query and opening/locking this -tables. - -If lex->derived_tables flag present will be scanned all SELECT_LEX (there -are list of all SELECT_LEX in reverse order (first SELECT in query will -be last in this list) lex->all_selects_list). - -Pointer on derived table SELECT_LEX_UNIT stored in TABLE_LIST structure -(TABLE_LIST::derived). And for any table which have this pointer will -be called mysql_derived(). - -mysql_derived(): -@itemize @bullet -@item - Creates list of all tables used in this query, opens and locks it -@item - Creates temporary table for storing results -@item - Creates union_result for writing result in this table -@item - Calls mysql_select or mysql_union for execute query -@item - Removes all derived table subtree from SELECTs tree (if it is - not EXPLAIN) -@item - Stores pointer to this temporary table in TABLE_LIST structure, then - this table will be used by outer query. This table table will not be - skipped in checking grants, because tables from which this table was - received was checked in mysql_derived. -@item - Links this temporary table in thd->derived_tables for removing after - query executing. this table will be closed in close_thread_tables if - second parameter of it (bool skip_derived) will be true. -@end itemize - -@node select subselect, select select engine, select derived, selects -@section Subselects - -In expression subselect represented by Item inherited from Item_subselect. - -To hide difference in performing single SELECTs and UNIONs -Item_subselect use two different engines, which provide uniformed -interface for access to underplaid SELECT or UNION -(subselect_single_select_engine and subselect_union_engine, both are -inherited from subselect_engine). - -Engine will be created in time of Item_select constructing -(Item_subselect::init method). - -On Item_subselect::fix_fields() will be called engine->prepare(). - -Before calling any value getting method (val, val_int, val_str, -bring_value (in case of row result)) will be called engine->exec(), -which execute query or just do nothing if subselect is cacheable and -already executed. - -Items inherited from provide it's own select_result classes. There are -2 type of it: -@itemize @bullet -@item - select_singlerow_subselect it store values of giving row in - Item_singlerow_subselect cache on send_data() call and report error - if Item_subselect have 'assigned' attribute. -@item - select_exists_subselect just store 1 as value of - Item_exists_subselect on send_data() call. As far as - Item_in_subselect and Item_allany_subselect inherited from - Item_exists_subselect, they use same select_result class. -@end itemize - -Item_select will never call cleanup() procedure for JOIN. Every -JOIN::cleanup will call cleanup() for inner JOINs. Most upper -JOIN::cleanup will be called by mysql_select() or mysql_union(). - -@node select select engine, select union engine, select subselect, selects -@section Single Select Engine - -subselect_single_select_engine: -@itemize @bullet -@item - @strong{constructor} allocate JOIN and store pointers on SELECT_LEX and JOIN -@item - @strong{prepare()} call JOIN::prepare -@item - @strong{fix_length_and_dec()} prepare cache and receive type and - parameters of returning items (it called only by - Item_singlerow_subselect) -@item - @strong{exec()} drop 'assigned flag of Item_subselect. If called first time - JOIN::optimize and JOINexec(), else do nothing or JOIN::reinit() - JOIN::exec() depending of type of subquery. -@end itemize - -@node select union engine, selectexplain, select select engine, selects -@section Union Engine - -subselect_union_engine: -@itemize @bullet -@item - @strong{constructor} just store pointer to st_select_lex_union - (SELECT_LEX_UNION) -@item - @strong{prepare()} call st_select_lex_unit::prepare -@item - @strong{fix_length_and_dec()} prepare cache and receive type and - parameters (maximum of length) of returning items (it called - only by Item_singlerow_subselect) -@item - @strong{exec()} call st_select_lex_unit::exec(). st_select_lex_unit::exec() - can drop 'assigned' flag of Item_subselect if - st_select_lex_unit::item is not 0. -@end itemize - -@node selectexplain, , select union engine, selects -@section Explain Execution - -For EXPLAIN result showing for every SELECT will be called mysql_select -with option SELECT_DESCRIBE. - -For main UNION will be called mysql_explain_union. - -mysql_explain_union call mysql_explain_select for every SELECT in given -union. - -mysql_explain_select call mysql_select with SELECT_DESCRIBE. - -mysql_select create JOIN for select (if it not exists, because if it -called for subselect JOIN can be created in JOIN::optimize of outer -query when it decided to calculate value of subselect). Then it call -JOIN::prepare, JOIN::optimize, JOIN exec and JOIN::cleanup as usual. - -JOIN::exec called for SELECT with SELECT_DESCRIBE option call -select_describe. - -select_describe return to user description of SELECT and call -mysql_explain_union for every inner UNION - -PROBLEM: how it will work with global query optimization? - -@node transformations, mysys functions, selects, Top -@chapter How MySQL transforms subqueries - -Item_subselect virtual method select_transformer is used to rewrite -subqueries. It is called from Item_subselect::init (which called in -Item_subselect constructor) - -@menu -* transformation IN:: -* transformations all any:: -* transformations singlerow:: -@end menu - -@node transformation IN, transformations all any, transformations, transformations -@section Item_in_subselect::select_transformer - -Item_in_subselect::select_transformer is divided on two parts for -scalar left part and row left part: - -@menu -* transformation scalar IN:: -* transformations row IN:: -@end menu - -@node transformation scalar IN, transformations row IN, transformation IN, transformation IN -@subsection Scalar IN Subselect - -To rewrite scalar IN subselect used method -Item_in_subselect::single_value_transformer, Scalar IN subselect will -be replaced with Item_in_optimizer. - -Item_in_optimizer item is special boolean function. On value request -(one of val, val_int or val_str methods) it evaluate left expression of -IN by storing it value in cache item (one of Item_cache* items), then it -test cache is it NULL. If left expression (cache) is NULL then -Item_in_optimizer return NULL, else it evaluate Item_in_subselect. - -Example queries. -@example -a) SELECT * from t1 where t1.a in (SELECT t2.a FROM t2); -b) SELECT * from t1 where t1.a in (SELECT t2.a FROM t2 GROUP BY t2.a); -@end example - -@itemize -@item -Item_in_subselect inherit mechanism of getting value from - Item_exists_subselect. -@item -Select_transformer stores reference to left expression in its - conditions: (in WHERE & HAVING in case 'a' and in a HAVING in case 'b') -@item -Item from item list of this select (t2.a) can be referred with special - reference (Item_ref_null_helper or Item_asterisk_remover). - This reference informs Item_in_optimizer if item (t2.a) is NULL by - setting the 'was_null' flag. -@item -The return value from Item_in_subselect will be evaluated as following: -@itemize @bullet -@item - If TRUE return true -@item - If NULL return null -@item - If FALSE and 'was_null' is set, return null -@item - return FALSE -@end itemize -@end itemize - - IN (SELECT ...) will be represented like -following: -@example - +-----------------+ - |Item_in_optimizer| - +-----------------+ - | - +---------------------+------------+ - | | -+-----------------------+ +-----------------+ -| | |Item_in_subselect| -| | +-----------------+ -+-----------------------+ | -|| +-----------+-----------+ -| | | | -+-----------------------+ | | - ^ +----------+ +--------------------+ - +<<<<<<<<<<<<<<<<<| Item_ref | +<<<|Item_ref_null_helper| - +----------+ V +--------------------+ - V +--------------------+ - +>>>| | - +--------------------+ -@end example -where '<<<<<<<<<' is reference in meaning of Item_ref. - -Item_ref used for point to , because in time of -transformation we know only address of variable where pointer on cache -will be stored. - -If select have ORDER BY clause it will be wiped out, because no sense in -ORDER BY without LIMIT here. - -If IN subselect union condition of every select in UNION will be changed -personally. - -If condition should be added to WHERE clause it will be presented as -"(item OR item IS NULL)" and Item_is_not_null_test(item) will be added -to HAVING clause. Item_is_not_null_test register NULL value as -Item_ref_null_helper does it and return FALSE if argument is NULL. -With above trick we will register NULL value of Item even in case -of index optimization of WHERE clause (case 'a' of following example). - -Following is examples of IN transformations: -@example -a) IN (SELECT FROM t - WHERE ) - -will be represented as - - (SELECT 1 FROM t - WHERE - and - (Item_ref()=)> or - is null) - HAVING Item_is_not_null_test()) - - -b) IN (SELECT FROM t - HAVING - ORDER BY 1) - -will be represented as - (SELECT as ref_null_helper FROM t - HAVING AND - Item_ref() = ref_null_helper) - - -c) IN (SELECT UNION ...) - -will be represented as - - (SELECT 1 - HAVING Item_ref()= - )> - UNION ...) - -(having without FROM is syntax error, but having condition is checked -even for subselect without FROM) - -d) IN (select ) - -will be completely replaced with = -@end example - -Now conditions (WHERE (a) or HAVING (b)) will be changed depends of -select in following way: - -If subselect have HAVING , sum function or GROUP BY (case a) then item -list will be unchanged and Item_ref_null_helper reference will be -created on item list element. Condition will be added to HAVING condition. - -If subselect have not HAVING, sum function or GROUP BY (case b) then: -@itemize @bullet -@item - @strong{item list} will be replaced with 1. -@item - @strong{} from item list will be stored in Item_asterisk_remover, which - inherit from Item_ref_null_helper, but store item on which refer by - itself, and also it can resolve '*' item. -@item - @strong{ = } will be added to - WHERE clause this item or to HAVING clause if this subselect have - no FROM clause and subselect is union (case c). -@end itemize - -Single select without FROM will be reduced to just - = without using Item_in_optimizer. - -@node transformations row IN, , transformation scalar IN, transformation IN -@subsection Row IN Subselect - -To rewrite row IN subselect used method -Item_in_subselect::row_value_transformer. It work in almost same way as -scalar analog, but work with Item_cache_row for caching left expression -and use references on elements of Item_cache_row. -To refer on item list it use Item_ref_on_list_position. - -Item_ref_on_list_position::fix_fields will find item in item list of -subselect by number and create Item_ref_null_helper to refer on it. It -used to find reference when all '*' items will be translated in item -list. Subselect with have HAVING, sum functions or GROUP BY will -transformed in following way: - -@example -ROW(l1, l2, ... lN) IN (SELECT i1, i2, ... iM FROM t HAVING ) - -will be following: - -(SELECT i1, i2, ... iM FROM t - HAVING and - = AND - = AND - ... - = ) -@end example - -In this way will be transformed select without FROM, too. - -For other subselect it will be same but for WHERE clause. - -@node transformations all any, transformations singlerow, transformation IN, transformations -@section Item_allany_subselect - -Item_allany_subselect is inherited from Item_in_subselect. -ALL/ANY/SOME use same algorithm (and same method of Item_in_subselect) -as scalar IN, but use different function instead of '='. - -ANY/SOME use same function that was listed after left expression. - -ALL use inverted function, and all subselect passed as argument to -Item_func_not. - -@node transformations singlerow, , transformations all any, transformations -@section Item_singlerow_subselect - -Item_singlerow_subselect will be rewritten only if it have not FROM -clause, it is not part of UNION and it is scalar subselect. For now will -not be converted subselects with field or reference on top of item list -(we can't change name of such items from one hand, but from other hand -we should assign to it name of whole subselect which will be reduced); - -Following will not be reduced: -@example -SELECT a; -SELECT 1 UNION SELECT 2; -SELECT 1 FROM t1; -@end example - -Following select will be reduced: -@example -SELECT 1; -SELECT a+2; -@end example - -Such subselect will be completely replaced by its expression from item -list and its SELECT_LEX and SELECT_LEX_UNIT will be removed from -SELECT_LEX's tree. - -But all Item_fields and Item_ref of that expression will be marked for -special fix_fields() procedure. fix_fields() for such Item will be -performed is same way as for items of inner subselect. Also if this -expression is Item_fields or Item_ref then name of this new item will -be same as name of this item (but not '(SELECT ...)'). It is done to -prevent broke references on such items from more inner subselects. - -@node mysys functions, DBUG, transformations, Top -@chapter Functions In The @code{mysys} Library - -Functions in @code{mysys}: (For flags see @file{my_sys.h}) - -@table @code -@item int my_copy _A((const char *from, const char *to, myf MyFlags)); -Copy file from @code{from} to @code{to}. - -@item int my_delete _A((const char *name, myf MyFlags)); -Delete file @code{name}. - -@item int my_getwd _A((string buf, uint size, myf MyFlags)); -@item int my_setwd _A((const char *dir, myf MyFlags)); -Get and set working directory. - -@item string my_tempnam _A((const char *pfx, myf MyFlags)); -Make a unique temporary file name by using dir and adding something after -@code{pfx} to make name unique. The file name is made by adding a unique -six character string and @code{TMP_EXT} after @code{pfx}. -Returns pointer to @code{malloc()}'ed area for filename. Should be freed by -@code{free()}. - -@item File my_open _A((const char *FileName,int Flags,myf MyFlags)); -@item File my_create _A((const char *FileName, int CreateFlags, int AccsesFlags, myf MyFlags)); -@item int my_close _A((File Filedes, myf MyFlags)); -@item uint my_read _A((File Filedes, byte *Buffer, uint Count, myf MyFlags)); -@item uint my_write _A((File Filedes, const byte *Buffer, uint Count, myf MyFlags)); -@item ulong my_seek _A((File fd,ulong pos,int whence,myf MyFlags)); -@item ulong my_tell _A((File fd,myf MyFlags)); -Use instead of open, open-with-create-flag, close, read, and write -to get automatic error messages (flag @code{MYF_WME}) and only have -to test for != 0 if error (flag @code{MY_NABP}). - -@item int my_rename _A((const char *from, const char *to, myf MyFlags)); -Rename file from @code{from} to @code{to}. - -@item FILE *my_fopen _A((const char *FileName,int Flags,myf MyFlags)); -@item FILE *my_fdopen _A((File Filedes,int Flags,myf MyFlags)); -@item int my_fclose _A((FILE *fd,myf MyFlags)); -@item uint my_fread _A((FILE *stream,byte *Buffer,uint Count,myf MyFlags)); -@item uint my_fwrite _A((FILE *stream,const byte *Buffer,uint Count, myf MyFlags)); -@item ulong my_fseek _A((FILE *stream,ulong pos,int whence,myf MyFlags)); -@item ulong my_ftell _A((FILE *stream,myf MyFlags)); -Same read-interface for streams as for files. - -@item gptr _mymalloc _A((uint uSize,const char *sFile,uint uLine, myf MyFlag)); -@item gptr _myrealloc _A((string pPtr,uint uSize,const char *sFile,uint uLine, myf MyFlag)); -@item void _myfree _A((gptr pPtr,const char *sFile,uint uLine)); -@item int _sanity _A((const char *sFile,unsigned int uLine)); -@item gptr _myget_copy_of_memory _A((const byte *from,uint length,const char *sFile, uint uLine,myf MyFlag)); -@code{malloc(size,myflag)} is mapped to these functions if not compiled -with @code{-DSAFEMALLOC}. - -@item void TERMINATE _A((void)); -Writes @code{malloc()} info on @code{stdout} if compiled with -@code{-DSAFEMALLOC}. - -@item int my_chsize _A((File fd, ulong newlength, myf MyFlags)); -Change size of file @code{fd} to @code{newlength}. - -@item void my_error _D((int nr, myf MyFlags, ...)); -Writes message using error number (see @file{mysys/errors.h}) on @code{stdout}, -or using curses, if @code{MYSYS_PROGRAM_USES_CURSES()} has been called. - -@item void my_message _A((const char *str, myf MyFlags)); -Writes @code{str} on @code{stdout}, or using curses, if -@code{MYSYS_PROGRAM_USES_CURSES()} has been called. - -@item void my_init _A((void )); -Start each program (in @code{main()}) with this. - -@item void my_end _A((int infoflag)); -Gives info about program. -If @code{infoflag & MY_CHECK_ERROR}, prints if some files are left open. -If @code{infoflag & MY_GIVE_INFO}, prints timing info and malloc info -about program. - -@item int my_redel _A((const char *from, const char *to, int MyFlags)); -Delete @code{from} before rename of @code{to} to @code{from}. Copies state -from old file to new file. If @code{MY_COPY_TIME} is set, sets old time. - -@item int my_copystat _A((const char *from, const char *to, int MyFlags)); -Copy state from old file to new file. If @code{MY_COPY_TIME} is set, -sets old time. - -@item string my_filename _A((File fd)); -Returns filename of open file. - -@item int dirname _A((string to, const char *name)); -Copy name of directory from filename. - -@item int test_if_hard_path _A((const char *dir_name)); -Test if @code{dir_name} is a hard path (starts from root). - -@item void convert_dirname _A((string name)); -Convert dirname according to system. -In MSDOS, changes all characters to capitals and changes @samp{/} to @samp{\}. - -@item string fn_ext _A((const char *name)); -Returns pointer to extension in filename. - -@item string fn_format _A((string to,const char *name,const char *dsk,const char *form,int flag)); - format a filename with replace of library and extension and - converts between different systems. - params to and name may be identicall - function dosn't change name if name != to - Flag may be: 1 force replace filnames library with 'dsk' - 2 force replace extension with 'form' */ - 4 force Unpack filename (replace ~ with home) - 8 Pack filename as short as possibly for output to - user. - All open requests should allways use at least: - "open(fn_format(temp_buffe,name,"","",4),...)" to unpack home and - convert filename to system-form. - -@item string fn_same _A((string toname, const char *name, int flag)); -Copys directory and extension from @code{name} to @code{toname} if neaded. -Copying can be forced by same flags used in @code{fn_format()}. - -@item int wild_compare _A((const char *str, const char *wildstr)); -Compare if @code{str} matches @code{wildstr}. @code{wildstr} can contain -@samp{*} and @samp{?} as wildcard characters. -Returns 0 if @code{str} and @code{wildstr} match. - -@item void get_date _A((string to, int timeflag)); -Get current date in a form ready for printing. - -@item void soundex _A((string out_pntr, string in_pntr)) -Makes @code{in_pntr} to a 5 char long string. All words that sound -alike have the same string. - -@item int init_key_cache _A((ulong use_mem, ulong leave_this_much_mem)); -Use caching of keys in MISAM, PISAM, and ISAM. -@code{KEY_CACHE_SIZE} is a good size. -Remember to lock databases for optimal caching. - -@item void end_key_cache _A((void)); -End key caching. -@end table - - - -@node DBUG, protocol, mysys functions, Top -@chapter DBUG Tags To Use - -Here is some of the tags we now use: -(We should probably add a couple of new ones) - -@table @code -@item enter -Arguments to the function. - -@item exit -Results from the function. - -@item info -Something that may be interesting. - -@item warning -When something doesn't go the usual route or may be wrong. - -@item error -When something went wrong. - -@item loop -Write in a loop, that is probably only useful when debugging -the loop. These should normally be deleted when one is -satisfied with the code and it has been in real use for a while. -@end table - -Some specific to mysqld, because we want to watch these carefully: - -@table @code -@item trans -Starting/stopping transactions. - -@item quit -@code{info} when mysqld is preparing to die. - -@item query -Print query. -@end table - - -@node protocol, Fulltext Search, DBUG, Top -@chapter MySQL Client/Server Protocol - -@menu -* raw packet without compression:: -* raw packet with compression:: -* basic packets:: -* communication:: -* 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 -@section Raw Packet Without Compression - -@example -+-----------------------------------------------+ -| Packet Length | Packet no | Data | -| 3 Bytes | 1 Byte | n Bytes | -+-----------------------------------------------+ -@end example - -@table @asis -@item 3 Byte packet length -The length is calculated with int3store -See include/global.h for details. -The max packetsize can be 16 MB. - -@item 1 Byte packet no -If no compression is used the first 4 bytes of each packet is the header -of the packet. The packet number is incremented for each sent packet. -The first packet starts with 0. -@item n Byte data - -@end table - -The packet length can be recalculated with: - -@example -length = byte1 + (256 * byte2) + (256 * 256 * byte3) -@end example - - -@node raw packet with compression, basic packets, raw packet without compression, protocol -@section Raw Packet With Compression - -@example -+---------------------------------------------------+ -| Packet Length | Packet no | Uncomp. Packet Length | -| 3 Bytes | 1 Byte | 3 Bytes | -+---------------------------------------------------+ -@end example - -@table @asis -@item 3 Byte packet length -The length is calculated with int3store -See include/global.h for details. -The max packetsize can be 16 MB. - -@item 1 Byte packet no -@item 3 Byte uncompressed packet length -@end table - -If compression is used the first 7 bytes of each packet -is the header of the packet. - - -@node basic packets, communication, raw packet with compression, protocol -@section Basic Packets - -@menu -* ok packet:: -* error packet:: -@end menu - - -@node ok packet, error packet, basic packets, basic packets -@subsection OK Packet - -For details, see @file{sql/net_pkg.cc::send_ok()}. - -@example -+-----------------------------------------------+ -| Header | No of Rows | Affected Rows | -| | 1 Byte | 1-8 Byte | -|-----------------------------------------------| -| ID (last_insert_id) | Status | Length | -| 1-8 Byte | 2 Byte | 1-8 Byte | -|-----------------------------------------------| -| Messagetext | -| n Byte | -+-----------------------------------------------+ -@end example - -@table @asis -@item Header -@item 1 byte number of rows ? (always 0 ?) -@item 1-8 bytes affected rows -@item 1-8 byte id (last_insert_id) -@item 2 byte Status (usually 0) -@item If the OK-packege includes a message: -@item 1-8 bytes length of message -@item n bytes messagetext -@end table - - -@node error packet, , ok packet, basic packets -@subsection Error Packet - -@example -+-----------------------------------------------+ -| Header | Status code | Error no | -| | 1 Byte | 2 Byte | -|-----------------------------------------------| -| Messagetext | 0x00 | -| n Byte | 1 Byte | -+-----------------------------------------------+ -@end example - -@table @asis -@item Header -@item 1 byte status code (0xFF = ERROR) -@item 2 byte error number (is only sent to new 3.23 clients. -@item n byte errortext -@item 1 byte 0x00 -@end table - - -@node communication, fieldtype codes, basic packets, protocol -@section Communication - -@example -> Packet from server to client -< Paket from client tor server - - Login - ------ - > 1. packet - Header - 1 byte protocolversion - n byte serverversion - 1 byte 0x00 - 4 byte threadnumber - 8 byte crypt seed - 1 byte 0x00 - 2 byte CLIENT_xxx options (see include/mysql_com.h - that is supported by the server - 1 byte number of current server charset - 2 byte server status variables (SERVER_STATUS_xxx flags) - 13 byte 0x00 (not used yet). - - < 2. packet - Header - 2 byte CLIENT_xxx options - 3 byte max_allowed_packet for the client - n byte username - 1 byte 0x00 - 8 byte crypted password - 1 byte 0x00 - n byte databasename - 1 byte 0x00 - - > 3. packet - OK-packet - - - Command - -------- - < 1. packet - Header - 1 byte command type (e.g.0x03 = query) - n byte query - - Result set (after command) - -------------------------- - > 2. packet - Header - 1-8 byte field_count (packed with net_store_length()) - - If field_count == 0 (command): - 1-8 byte affected rows - 1-8 byte insert id - 2 bytes server_status (SERVER_STATUS_xx) - - If field_count == NULL_LENGTH (251) - LOAD DATA LOCAL INFILE - - If field_count > 0 Result Set: - - > n packets - Header Info - Column description: 5 data object /column - (See code in unpack_fields()) - - Columninfo for each column: - 1 data block table_name - 1 byte length of block - n byte data - 1 data block field_name - 1 byte length of block... - n byte data - 1 data block display length of field - 1 byte length of block - 3 bytes display length of filed - 1 data block type field of type (enum_field_types) - 1 byte length of block - 1 bytexs field of type - 1 data block flags - 1 byte length of block - 2 byte flags for the columns (NOT_NULL_FLAG, ZEROFILL_FLAG....) - 1 byte decimals - - if table definition: - 1 data block default value - - Actual result (one packet per row): - 4 byte header - 1-8 byte length of data - n data -@end example - -@node fieldtype codes, protocol functions, communication, protocol -@section Fieldtype Codes - -@example - display_length |enum_field_type |flags - ---------------------------------------------------- -Blob 03 FF FF 00 |01 FC |03 90 00 00 -Mediumblob 03 FF FF FF |01 FC |03 90 00 00 -Tinyblob 03 FF 00 00 |01 FC |03 90 00 00 -Text 03 FF FF 00 |01 FC |03 10 00 00 -Mediumtext 03 FF FF FF |01 FC |03 10 00 00 -Tinytext 03 FF 00 00 |01 FC |03 10 00 00 -Integer 03 0B 00 00 |01 03 |03 03 42 00 -Mediumint 03 09 00 00 |01 09 |03 00 00 00 -Smallint 03 06 00 00 |01 02 |03 00 00 00 -Tinyint 03 04 00 00 |01 01 |03 00 00 00 -Varchar 03 XX 00 00 |01 FD |03 00 00 00 -Enum 03 05 00 00 |01 FE |03 00 01 00 -Datetime 03 13 00 00 |01 0C |03 00 00 00 -Timestamp 03 0E 00 00 |01 07 |03 61 04 00 -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 -@section Functions used to implement the protocol - -@c This should be merged with the above one and changed to texi format - -@example - -Raw packets ------------ - -- The my_net_xxxx() functions handles the packaging of a stream of data - into a raw packet that contains a packet number, length and data. - -- This is implemented for the server in sql/net_serv.cc. - The client file, libmysql/net.c, is symlinked to this file - -The important functions are: - -my_net_write() Store a packet (= # number of bytes) to be sent -net_flush() Send the packets stored in the buffer -net_write_command() Send a command (1 byte) + packet to the server. -my_net_read() Read a packet - - -Include files -------------- - -- include/mysql.h is included by all MySQL clients. It includes the - MYSQL and MYSQL_RES structures. -- include/mysql_com.h is include by mysql.h and mysql_priv.h (the - server) and includes a lot of common functions and structures to - handle the client/server protocol. - - -Packets from server to client: ------------------------------ - -sql/net_pkg.cc: - - - Sending of error packets - - Sending of OK packets (= end of data) - - Storing of values in a packet - - -sql/sql_base.cc: - - - Function send_fields() sends the field description to the client. - -sql/sql_show.cc: - - - Sends results for a lot of SHOW commands, including: - SHOW DATABASES [like 'wildcard'] - SHOW TABLES [like 'wildcard'] - - -Packets from client to server: ------------------------------- - -This is done in libmysql/libmysql.c - -The important ones are: - -- mysql_real_connect() Connects to a mysqld server -- mysql_real_query() Sends a query to the server and - reads the ok packet or columns header. -- mysql_store_result() Read a result set from the server to memory -- mysql_use_result() Read a result set row by row from the server. - -- net_safe_read() Read a packet from the server with - error handling. -- net_field_length() Reads the length of a packet string. -- simple_command() Sends a command/query to the server. - - - -Connecting to mysqld (the MySQL server) ---------------------------------------- - -- On the client side: libmysql/libmysql.c::mysql_real_connect(). -- On the server side: sql/sql_parse.cc::check_connections() - -The packets sent during a connection are as follows - -Server: Send greeting package (includes server capabilites, server - version and a random string of bytes to be used to scramble - the password. -Client: Sends package with client capabilites, user name, scrambled - password, database name - -Server: Sends ok package or error package. - -Client: If init command specified, send it t the server and read - ok/error package. - - -Password functions ------------------- - -The passwords are scrambled to a random number and are stored in hex -format on the server. - -The password handling is done in sql/password.c. The important -function is 'scramble()', which takes the a password in clear text -and uses this to 'encrypt' the random string sent by the server -to a new message. - -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, 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. - -@example -***************************** -* -* PROTOCOL OVERVIEW -* -***************************** - -The MySQL protocol is relatively simple, and is designed for high performance -through minimisation of overhead, and extensibility through versioning and -options flags. It is a request-response protocol, and does not allow -multitasking or multiplexing over a single connection. There are two packet -formats, 'raw' and 'compressed' (which is used when both client and -server support zlib compression, and the client requests that data be -compressed): - -* RAW PACKET, shorter than 16 M * - -+-----------------------------------------------+ -| Packet Length | Packet no | Data | -| 3 Bytes | 1 Byte | n Bytes | -+-----------------------------------------------+ -^ ^ -| 'HEADER' | -+-------------------------------+ - - - * Packet Length: Calculated with int3store. See include/global.h for - details. The basic computation is length = byte1 + - (256 * byte2) + (256 * 256 * byte3). The max packetsize - can be 16 MB. - - * Packet no: The packet number is incremented for each sent packet. - The first packet for each query from the client - starts with 0. - - * Data: Specific to the operation being performed. Most often - used to send string data, such as a SQL query. - -* COMPRESSED PACKET * - -+---------------------------------------------------+-----------------+ -| Packet Length | Packet no | Uncomp. Packet Length | Compressed Data | -| 3 Bytes | 1 Byte | 3 Bytes | n bytes | -+---------------------------------------------------+-----------------+ -^ ^ -| 'HEADER' | -+---------------------------------------------------+ - - * Packet Length: Calculated with int3store. See include/my_global.h for - details. The basic computation is length = byte1 + - (256 * byte2) + (256 * 256 * byte3). The max packetsize - can be 16 MB. - - * Packet no: The packet number is incremented for each sent packet. - The first packet starts with 0. - - * Uncomp. Packet Length: The length of the original, uncompressed packet - If this is zero then the data is not compressed. - - * Compressed Data: The original packet, compressed with zlib compression - - -When using the compressed protocol, the client/server will only compress -send packets where the new packet is smaller than the not compressed one. -In other words, some packets may be compressed while others will not. - -The 'compressed data' is one or more packets in *RAW PACKET* format. - -***************************** -* -* FLOW OF EVENTS -* -***************************** - -To understand how a client communicates with a MySQL server, it is easiest -to start with a high-level flow of events. Each event section will then be -followed by details of the exact contents of each type of packet involved -in the event flow. - -* * -* CONNECTION ESTABLISHMENT * -* * - -Clients connect to the server via a TCP/IP socket (port 3306 by default), a -Unix Domain Socket, or named pipes (on Windows). Once connected, the -following connection establishment sequence is followed: - -+--------+ +--------+ -| Client | | Server | -+--------+ +--------+ - | | - | Handshake initialisation, including MySQL server version, | - | protocol version and options supported, as well as the seed | - | for the password hash | - | | - | <-------------------------------------------------------------- | - | | - | Client options supported, max packet size for client | - | username, password crypted with seed from server, database | - | name. | - | | - | --------------------------------------------------------------> | - | | - | 'OK' packet if authentication succeeds, 'ERROR' packet if | - | authentication fails. | - | | - | <-------------------------------------------------------------- | - | | - - - -* HANDSHAKE INITIALISATION PACKET * - - -+--------------------------------------------------------------------+ -| Header | Prot. Version | Server Version String | 0x00 | -| | 1 Byte | n bytes | 1 byte | -|--------------------------------------------------------------------| -| Thread Number | Crypt Seed | 0x00 | CLIENT_xxx options | -| | | | supported by server | -| 4 Bytes | 8 Bytes | 1 Byte | 2 Bytes | -|--------------------------------------------------------------------| -| Server charset no. | Server status variables | 0x00 padding | -| 1 Byte | 2 Bytes | 13 bytes | -+--------------------------------------------------------------------+ - - * Protocol version (currently '10') - * Server Version String (e.g. '4.0.5-beta-log'). Can be any length as - it's followed by a 0 byte. - * Thread Number - ID of server thread handling this connection - * Crypt seed - seed used to crypt password in auth packet from client - * CLIENT_xxx options - see include/mysql_com.h - * Server charset no. - Index of charset in use by server - * Server status variables - see include/mysql_com.h - * The padding bytes are reserverd for future extensions to the protocol - -* CLIENT AUTH PACKET * - - -+--------------------------------------------------------------------+ -| Header | CLIENT_xxx options supported | max_allowed_packet | -| | by client | for client | -| | 4 Bytes | 4 bytes | -|--------------------------------------------------------------------| -| Character set | Reserved for the future | -| 1 Bytes | 23 bytes | -|--------------------------------------------------------------------| -| User Name | 0x00 | Crypted Password | 0x00 | Database Name | -| n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes | -|--------------------------------------------------------------------| -| 0x00 | -| 1 Byte | -+--------------------------------------------------------------------+ - - * CLIENT_xxx options that this client supports: - -#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */ -#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */ -#define CLIENT_LONG_FLAG 4 /* Get all column flags */ -#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */ -#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */ -#define CLIENT_COMPRESS 32 /* Can use compression protocol */ -#define CLIENT_ODBC 64 /* Odbc client */ -#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ -#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ -#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ -#define CLIENT_SSL 2048 /* Switch to SSL after handshake */ -#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ -#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ - - * max_allowed_packet for the client (in 'int3store' form) - * User Name - user to authenticate as. Is followed by a null byte. - * Crypted Password - password crypted with seed given in packet from - server, see scramble() in sql/password.c - * Database name (optional) - initial database to use once connected - Is followed by a null byte - -At the end of every client/server exchange there is either an 'OK' packet -or an 'ERROR' packet sent from the server. To determine whether a packet is -an 'OK' packet, or an 'ERROR' packet, check if the first byte (after the -header) is 0xFF. If it has the value of 0xFF, the packet is an 'ERROR' -packet. - - -* OK PACKET * - -For details, see sql/net_pkg.cc::send_ok() - -+-----------------------------------------------+ -| Header | No of Rows | Affected Rows | -| | 1 Byte | 1-9 Byte | -|-----------------------------------------------| -| ID (last_insert_id) | Status | Length | -| 1-9 Byte | 2 Byte | 1-9 Byte | -|-----------------------------------------------| -| Messagetext | -| n Byte | -+-----------------------------------------------+ - - * Number of rows, always 0 - * Affected rows - * ID (last_insert_id) - value for auto_increment column (if any) - * Status (usually 0) - -In general, in the MySQL protocol, fields in a packet that that -represent numeric data, such as lengths, that are labeled as '1-9' -bytes can be decoded by the following logic: - - If the first byte is '251', the - corresponding column value is NULL (only appropriate in - 'ROW DATA' packets). - - If the first byte is '252', the value stored can be read - from the following 2 bytes as a 16-bit integer. - - - If the first byte is '253' the value stored can be read - from the following 4 bytes as a 32-bit long integer - - - If the first byte is '254', the value stored can be read - from the following 8 bytes as a 64-byte long - - Otherwise (values 0-250), the value stored is the value of the - first byte itself. - - -If the OK-packet includes a message: - - * Length of message - * Message Text - - -* ERROR PACKET * - -+-----------------------------------------------+ -| Header | Status code | Error no | -| | 1 Byte | 2 Byte | -|-----------------------------------------------| -| Messagetext | | -| n Byte | | -+-----------------------------------------------+ - - * Status code (0xFF = ERROR) - * Error number (is only sent to 3.23 and newer clients) - * Error message text (ends at end of packet) - -Note that the error message is not null terminated. -The client code can however assume that the packet ends with a null -as my_net_read() will always add an end-null to all read packets to -make things easier for the client. - -Example: - -Packet dump of client connecting to server: - -+------------------------- Protocol Version (10) -| -| +---------------------- Server Version String (0x00 terminated) -| | -| | -0a 34 2e 30 2e 35 2d 62 . 4 . 0 . 5 - b -65 74 61 2d 6c 6f 67 00 e t a - l o g . -15 00 00 00 2b 5a 65 6c . . . . + Z e l - | | - | +------------ First 4 bytes of crypt seed - | - +------------------------ Thread Number - -+------------------------- Last 4 bytes of crypt seed -| -| +-------- CLIENT_XXX Options supported by server -| | -| +-+--+ +--- Server charset index -| | | | -6f 69 41 46 00 2c 28 08 o i A F . , ( . -02 00 00 00 00 00 00 00 . . . . . . . . -| | -| +---------------------- 0x00 padding begins -| -+------------------------- Server status (0x02 = - SERVER_STATUS_AUTOCOMMIT) - -00 00 00 00 00 00 00 00 . . . . . . . . - -* Client Authentication Response (Username 'test', no database - selected) * - - +--------------------- Packet Length (0x13 = 19 bytes) - | - | +--------------- Packet Sequence # - | | - | | +----------- CLIENT_XXX Options supported by client - | | -+---+---+ | +-+-+ -| | | | | -13 00 00 01 03 00 1e 00 . . . . . . . . -00 74 65 73 74 00 48 5e . t e s t . H ^ - | | | - +----+-----+ +------- Scrambled password, 0x00 terminated - | - +----------------- Username, 0x00 terminated - -57 4a 4e 41 4a 4e 00 00 W J N A J N . . -00 . - - ->From this point on, the server waits for 'commands' from the client -which include queries, database shutdown, quit, change user, etc (see -the COM_xxxx values in include/mysql_com.h for the latest -command codes). - -* * -* COMMAND PROCESSING * -* * - -+--------+ +--------+ -| Client | | Server | -+--------+ +--------+ - | | - | A command packet, with a command code, and string data | - | when appropriate (e.g. a query), (see the COM_xxxx values | - | in include/mysql_com.h for the command codes) | - | | - | --------------------------------------------------------------> | - | | - | A 'RESULT' packet if the command completed successfully, | - | an 'ERROR' packet if the command failed. 'RESULT' packets | - | take different forms (see the details following this chart) | - | depending on whether or not the command returns rows. | - | | - | <-------------------------------------------------------------- | - | | - | n 'FIELD PACKET's (if rows are returned) | - | | - | <-------------------------------------------------------------- | - | | - | 'LAST DATA' packet | - | | - | <-------------------------------------------------------------- | - | | - | n 'ROW PACKET's (if rows are returned) | - | | - | <-------------------------------------------------------------- | - | | - | 'LAST DATA' packet | - | | - | <-------------------------------------------------------------- | - | | - - -* Command Packet * - -+------------------------------------------------------+ -| Header | Command type | Query (if applicable) | -| | 1 Byte | n Bytes | -+------------------------------------------------------+ - - * Command type: (e.g.0x03 = query, see the COM_xxxx values in - include/mysql_com.h) - * Query (if applicable) - -Note that my_net_read() null-terminates all packets on the -receiving side of the channel to make it easier for the code -examining the packets. - -The current command codes are: - - 0x00 COM_SLEEP - 0x01 COM_QUIT - 0x02 COM_INIT_DB - 0x03 COM_QUERY - 0x04 COM_FIELD_LIST - 0x05 COM_CREATE_DB - 0x06 COM_DROP_DB - 0x07 COM_REFRESH - 0x08 COM_SHUTDOWN - 0x09 COM_STATISTICS - 0x0a COM_PROCESS_INFO - 0x0b COM_CONNECT - 0x0c COM_PROCESS_KILL - 0x0d COM_DEBUG - 0x0e COM_PING - 0x0f COM_TIME - 0x10 COM_DELAYED_INSERT - 0x11 COM_CHANGE_USER - 0x12 COM_BINLOG_DUMP - 0x13 COM_TABLE_DUMP - 0x14 COM_CONNECT_OUT - 0x15 COM_REGISTER_SLAVE - -* Result Packet * - -Result packet for a command returning _no_ rows: - -+-----------------------------------------------+ -| Header | Field Count | Affected Rows | -| | 1-9 Bytes | 1-9 Bytes | -|-----------------------------------------------| -| ID (last_insert_id) | Server Status | -| 1-9 Bytes | 2 Bytes | -+-----------------------------------------------+ - - * Field Count: Has value of '0' for commands returning _no_ rows - * Affected rows: Count of rows affected by INSERT/UPDATE/DELETE, etc. - * ID: value of auto_increment column in row (if any). 0 if - * Server Status: Usually 0 - -Result packet for a command returning rows: - -+-------------------------------+ -| Header | Field Count | -| | 1-9 Bytes | -+-------------------------------+ - - * Field Count: number of columns/fields in result set, - (packed with net_store_length() in sql/net_pkg.cc) - -This is followed by as many packets as the number of fields ('Field Count') -that contain the metadata for each column/field (see unpack_fields() in -libmysql/libmysql.c): - - -* FIELD PACKET * - -+-----------------------------------------------+ -| Header | Table Name | -| | length-coded-string | -|-----------------------------------------------| -| Field Name | -| length-code-string | -|-----------------------------------------------| -| Display length of field -| length-coded-binary (4 bytes) | -|-----------------------------------------------| -| Field Type (enum_field_types in mysql_com.h) | -| length-coded-binary (2 bytes) | -|-----------------------------------------------| -| Field Flags | Decimal Places| -| length-coded-binary (3 bytes) | 1 Byte | -+--------------+-------------+------------------+ - - * A length coded string is a string where we first have a packet - length (1-9 bytes, packed_with net_store_length()) followed - by a string. - * A length coded binary is a length (1 byte) followed by an integer - value in low-byte-first order. For the moment this type is always - fixed length in this packet. - - * Table Name - the name of the table the column comes from - * Field Name - the name of the column/field - * Display length of field - length of field - * Field Type - Type of field, see enum_field_types in - include/mysql_com.h - - Current field types are: - - 0x00 FIELD_TYPE_DECIMAL - 0x01 FIELD_TYPE_TINY - 0x02 FIELD_TYPE_SHORT - 0x03 FIELD_TYPE_LONG - 0x04 FIELD_TYPE_FLOAT - 0x05 FIELD_TYPE_DOUBLE - 0x06 FIELD_TYPE_NULL - 0x07 FIELD_TYPE_TIMESTAMP - 0x08 FIELD_TYPE_LONGLONG - 0x09 FIELD_TYPE_INT24 - 0x0a FIELD_TYPE_DATE - 0x0b FIELD_TYPE_TIME - 0x0c FIELD_TYPE_DATETIME - 0x0d FIELD_TYPE_YEAR - 0x0e FIELD_TYPE_NEWDATE - 0xf7 FIELD_TYPE_ENUM - 0xf8 FIELD_TYPE_SET - 0xf9 FIELD_TYPE_TINY_BLOB - 0xfa FIELD_TYPE_MEDIUM_BLOB - 0xfb FIELD_TYPE_LONG_BLOB - 0xfc FIELD_TYPE_BLOB - 0xfd FIELD_TYPE_VAR_STRING - 0xfe FIELD_TYPE_STRING - 0xff FIELD_TYPE_GEOMETRY - - * Field Flags - NOT_NULL_FLAG, PRI_KEY_FLAG, xxx_FLAG in - include/mysql_com.h - - -Note that the packet format in 4.1 has slightly changed to allow more values. - - -* ROW PACKET * - -+-----------------------------------------------+ -| Header | Data Length | Column Data | ....for each column -| | 1-9 Bytes | n Bytes | -+-----------------------------------------------+ - - * Data Length: (packed with net_store_length() in sql/net_pkg.cc) - - If 'Data Length' == 0, this is an 'ERROR PACKET'. - - * Column Data: String representation of data. MySQL always sends result set - data as strings. - -* LAST DATA PACKET * - -Packet length is < 9 bytes, and first byte is 0xFE - -+--------+ -| 0xFE | -| 1 Byte | -+--------+ - -Examples: - -*********** -* -* INITDB Command -* -*********** - -A client issuing an 'INITDB' (select the database to use) command, -followed by an 'OK' packet with no rows and no affected rows from -the server: - -* INITDB (select database to use) 'COMMAND' Packet * - - +--------------------- Packet Length (5 bytes) - | - | +--------------- Packet Sequence # - | | - | | +------------ Command # (INITDB = 0x02) - | | -+---+---+ | | +---------- Beginning of query data -| | | | | -05 00 00 00 02 74 65 73 . . . . . t e s -74 t - -* 'OK' Packet with no rows, and no rows affected * - - +--------------------- Packet Length (3 bytes) - | - | +--------------- Packet Sequence # - | | -+---+---+ | -| | | -03 00 00 01 00 00 00 . . . . . . . - - -*********** -* -* SELECT query example -* -*********** - -Client issuing a 'SELECT *' query on the following table: - - CREATE TABLE number_test (minBigInt bigint, - maxBigInt bigint, - testBigInt bigint) - -* 'COMMAND' Packet with QUERY (select ...) * - - +--------------------- Packet Length (26) - | - | +--------------- Packet Sequence # - | | - | | +------------ Command # (QUERY = 0x03) - | | -+---+---+ | | +---------- Beginning of query data -| | | | | -1a 00 00 00 03 53 45 4c . . . . . S E L -45 43 54 20 2a 20 66 72 E C T . * . f r -6f 6d 20 6e 75 6d 62 65 o m . n u m b e -72 5f 74 65 73 74 r _ t e s t - - -and receiving an 'OK' packet with a 'FIELD COUNT' of 3 - - -* 'OK' Packet with 3 fields * - - +--------------------- Packet Length (3 bytes) - | - | +--------------- Packet Sequence # - | | -+---+---+ | -| | | -01 00 00 01 03 . . . . . - -Followed immediately by 3 'FIELD' Packets. Note, the individual packets -are delimitted by =======, so that all fields can be annotated in the first -'FIELD' packet example: - -============================================================= - - +--------------------- Packet Length (0x1f = 31 bytes) - | - | +--------------- Packet Sequence # - | | - | | +------------ Block Length (0x0b = 11 bytes) - | | | -+---+---+ | | +--------- Table Name (11 bytes long) -| | | | | -1f 00 00 02 0b 6e 75 6d . . . . . n u m -62 65 72 5f 74 65 73 74 b e r _ t e s t - - +------------------------ Block Length (9 bytes) - | - | +--------------------- Column Name (9 bytes long) - | | -09 6d 69 6e 42 69 67 49 . m i n B i g I -6e 74 03 14 00 00 01 08 n t . . . . . . - | | | | | - | +---+---+ | +--- Field Type (0x08 = FIELD_TYPE_LONGLONG) - | | | - | | +------ Block Length (1) - | | - | +--------------- Display Length (0x14 = 20 chars) - | - +------------------ Block Length (3) - - +------------------------ Block Length (2) - | - | +-------------------- Field Flags (0 - no flags set) - | | - | +---+ +--------------- Decimal Places (0) - | | | | -02 00 00 00 . . . . - -============================================================= - -'FIELD' packet for the 'number_Test.maxBigInt' column - -1f 00 00 03 0b 6e 75 6d . . . . . n u m -62 65 72 5f 74 65 73 74 b e r _ t e s t -09 6d 61 78 42 69 67 49 . m a x B i g I -6e 74 03 14 00 00 01 08 n t . . . . . . -02 00 00 00 . . . . - -============================================================= - -'FIELD' packet for the 'number_test.testBigInt' column - -20 00 00 04 0b 6e 75 6d . . . . . n u m -62 65 72 5f 74 65 73 74 b e r _ t e s t -0a 74 65 73 74 42 69 67 . t e st B i g -49 6e 74 03 14 00 00 01 I n t . . . . . -08 02 00 00 00 . . . . . -============================================================= - -Followed immediately by one 'LAST DATA' packet: - -fe 00 . . - -Followed immediately by 'n' row packets (in this case, only -one packet is sent from the server, for simplicity's sake): - - - +--------------------- Packet Length (0x52 = 82 bytes) - | - | +--------------- Packet Sequence # - | | - | | +------------ Data Length (0x14 = 20 bytes) - | | | -+---+---+ | | +--------- String Data '-9223372036854775808' -| | | | | (repeat Data Length/Data sequence) - -52 00 00 06 14 2d 39 32 . . . . . - 9 2 -32 33 33 37 32 30 33 36 2 3 3 7 2 0 3 6 -38 35 34 37 37 35 38 30 8 5 4 7 7 5 8 0 -38 13 39 32 32 33 33 37 8 . 9 2 2 3 3 7 -32 30 33 36 38 35 34 37 2 0 3 6 8 5 4 7 -37 35 38 30 37 0a 36 31 7 5 8 0 7 . 6 1 -34 37 34 38 33 36 34 37 4 7 4 8 3 6 4 7 - -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) - -@c @node Index -@c @unnumbered Index - -@c @printindex fn - -@c @node 4.1 protocol,,, -@c @chapter MySQL 4.1 protocol - -@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 -with an old 4.0 or 3.x client we will use the old protocol. - -The new things that we support with 4.1 are: - -@itemize @bullet -@item -Warnings -@item -Prepared statements -@item -Binary protocol (is be faster than the current protocol that -converts everything to strings) -@end itemize - - -What has changed in 4.1 are: - -@itemize @bullet -@item -A lot of new field information (catalog, database, real table name etc) -@item -The 'ok' packet has more status fields -@item -The 'end' packet (send last for each result set) now contains some -extra information -@item -New protocol for prepared statements. In this case all parameters and -results will sent as binary (low-byte-first). -@end itemize - - -@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 -contains a result set. It can be distinguished from a ok packet by -the fact that the first byte can't be 0 for a field packet. -@xref{4.1 ok packet}. - -The header packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1-9 @tab Number of columns in result set (never 0) -@item 1-9 @tab Extra information sent be some command (SHOW COLUMNS -uses this to send the number of rows in the table) -@end multitable - -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, protocol -@section 4.1 field description result set - -The field description result set contains the meta info for a result set. - -@multitable @columnfractions .20 .80 -@item Type @tab Comment -@item string @tab Catalog name (for 5.x) -@item string @tab Database name -@item string @tab Table name alias (or table name if no alias) -@item string @tab Real table name -@item string @tab Alias for column name (or column name if not used) - -@item 12 byte @tab Fixed length fields in one field part: -@itemize -@item 2 byte int @tab Character set number -@item 4 byte int @tab Length of column definition -@item 1 byte int @tab Enum value for field type -@item 3 byte int @tab 2 byte column flags (NOT_NULL_FLAG etc..) + 1 byte number of decimals. -@item 2 byte int @tab zero (reserved for future use) -@end itemize - -@item string int @tab Default value, only set when using mysql_list_fields(). -@end multitable - - -@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 -that didn't return a result set. - -The ok packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1 @tab 0 ; Marker for ok packet -@item 1-9 @tab Affected rows -@item 1-9 @tab Last insert id (0 if one wasn't used) -@item 2 @tab Server status; Can be used by client to check if we are inside an transaction -@item 2 @tab Warning count -@item 1-9 @tab Message length (optional) -@item xxx @tab Message (optional) -@end multitable - -Size 1-9 means that the parameter is packed in to 1-9 bytes depending on -the value. (See function sql/net_pkg.cc::net_store_length). - -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, protocol -@section 4.1 end packet - -The end packet is sent as the last packet for - -@itemize @bullet -@item -End of field information -@item -End of parameter type information -@item -End of result set -@end itemize - -The end packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1 @tab 254 ; Marker for EOF packet -@item 2 @tab Warning count -@item 2 @tab Status flags (For flags like SERVER_STATUS_MORE_RESULTS) -@end multitable - -Note that a normal packet may start with byte 254, which means -'length stored in 9 bytes'. One can different between these cases -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, protocol -@section 4.1 error packet. - -The error packet is sent when something goes wrong. -The error packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1 @tab 255 Error packet marker -@item 2 @tab Error code -@item 1 @tab '#' marker that SQLSTATE follows -@item 6 @tab SQLSTATE code (000000 for many messages) -@item 1-512 @tab Null terminated error message -@end multitable - -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, protocol -@section 4.1 prepared statement init packet - -This is the return packet when one sends a query with the COM_PREPARE -command (packet length is always '9'). - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1 @tab 0 ; Marker for OK packet -@item 4 @tab Statement handler id -@item 2 @tab Number of columns in result set -@item 2 @tab Number of parameters in query -@end multitable - -After this, there is a packet that contains the following for each -parameter in the query: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 2 @tab Enum value for field type. (MYSQL_TYPE_UNKNOWN if not known) -@item 2 @tab 2 byte column flags (NOT_NULL_FLAG etc) -@item 1 @tab Number of decimals -@item 4 @tab Max column length. -@end multitable - -Note that the above is not yet in 4.1 but will be added this month. - -As MySQL can have a parameter 'anywhere' it will in many cases not be -able to provide the optimal information for all parameters. - -If number of columns, in the header packet, is not 0 then the -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, protocol -@section 4.1 long data handling - -This is used by mysql_send_long_data() to set any parameter to a string -value. One can call mysql_send_long_data() multiple times for the -same parameter; The server will concatenate the results to a one big -string. - -The server will not require an end packet for the string. -mysql_send_long_data() is responsible updating a flag that all data -has been sent. (Ie; That the last call to mysql_send_long_data() has -the 'last_data' flag set). - -This packet is sent from client -> server: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 4 @tab Statement handler -@item 2 @tab Parameter number -@item 2 @tab Type of parameter (not used at this point) -@item # @tab data (Rest of packet) -@end multitable - -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, protocol -@section 4.1 execute - -On execute we send all parameters to the server in a COM_EXECUTE -packet. - -The packet contains the following information: - -@multitable @columnfractions .30 .70 -@item Size @tab Comment -@item (param_count+9)/8 @tab Null bit map (2 bits reserved for protocol) -@item 1 @tab new_parameter_bound flag. Is set to 1 for first -execute or if one has rebound the parameters. -@item 2*param_count @tab Type of parameters (only given if new_parameter_bound flag is 1) -@item # @tab Parameter data, repeated for each parameter that are -NOT NULL and not used with mysql_send_long_data(). -@end multitable - -The null-bit-map is for all parameters (including parameters sent with -'mysql_send_long_data). If parameter 0 is NULL, then bit 0 in the -null-bit-map should be 1 (ie: first byte should be 1) - -The parameters are stored the following ways: - -@multitable @columnfractions .20 .10 .70 -@item Type @tab Size @tab Comment -@item tinyint @tab 1 @tab One byte integer -@item short @tab 2 @tab -@item int @tab 4 @tab -@item longlong @tab 8 @tab -@item float @tab 4 @tab -@item double @tab 8 @tab -@item string @tab 1-9 + # @tab Packed string length + string -@end multitable - -The result for this will be either an ok packet or a binary result -set. - -@node 4.1 binary result, , 4.1 execute, protocol -@section 4.1 binary result set - -A binary result are sent the following way. - -For each result row: - -@itemize -@item -null bit map with first two bits set to 01 (bit 0,1 value 1) -@item -parameter data, repeated for each not null result column. -@end itemize - -The idea with the reserving two bits in the null map is that we can -use standard error (first byte 255) and ok packets (first byte 0) -to end a result sets. - -Except that the null-bit-map is shifted two steps, the server is -sending the data to the client the same way that the server is sending -bound parameters to the client. The server is always sending the data -as type given for 'column type' for respective column. It's up to the -client to convert the parameter to the requested type. - -DATETIME, DATE and TIME are sent to the server in a binary format as follows: - -@multitable @columnfractions .20 .10 .70 -@item Type @tab Size @tab Comment -@item date @tab 1 + 0-11 @tab Length + 2 byte year, 1 byte MMDDHHMMSS, 4 byte billionth of a second -@item datetime @tab 1 + 0-11 @tab Length + 2 byte year, 1 byte MMDDHHMMSS, 4 byte billionth of a second -@item time @tab 1 + 0-14 @tab Length + sign (0 = pos, 1= neg), 4 byte days, 1 byte HHMMDD, 4 byte billionth of a second -@end multitable - -The first byte is a length byte and then comes all parameters that are -not 0. (Always counted from the beginning). - -@node Fulltext Search, MyISAM Record Structure, protocol, Top -@chapter Fulltext Search in MySQL - -Hopefully, sometime there will be complete description of -fulltext search algorithms. -Now it's just unsorted notes. - -@menu -* Weighting in boolean mode:: -@end menu - -@node Weighting in boolean mode, , Fulltext Search, Fulltext Search -@section Weighting in boolean mode - -The basic idea is as follows: in expression -@code{A or B or (C and D and E)}, either @code{A} or @code{B} alone -is enough to match the whole expression. While @code{C}, -@code{D}, and @code{E} should @strong{all} match. So it's -reasonable to assign weight 1 to @code{A}, @code{B}, and -@code{(C and D and E)}. And @code{C}, @code{D}, and @code{E} -should get a weight of 1/3. - -Things become more complicated when considering boolean -operators, as used in MySQL FTB. Obvioulsy, @code{+A +B} -should be treated as @code{A and B}, and @code{A B} - -as @code{A or B}. The problem is, that @code{+A B} can @strong{not} -be rewritten in and/or terms (that's the reason why this - extended - -set of operators was chosen). Still, aproximations can be used. -@code{+A B C} can be approximated as @code{A or (A and (B or C))} -or as @code{A or (A and B) or (A and C) or (A and B and C)}. -Applying the above logic (and omitting mathematical -transformations and normalization) one gets that for -@code{+A_1 +A_2 ... +A_N B_1 B_2 ... B_M} the weights -should be: @code{A_i = 1/N}, @code{B_j=1} if @code{N==0}, and, -otherwise, in the first rewritting approach @code{B_j = 1/3}, -and in the second one - @code{B_j = (1+(M-1)*2^M)/(M*(2^(M+1)-1))}. - -The second expression gives somewhat steeper increase in total -weight as number of matched B's increases, because it assigns -higher weights to individual B's. Also the first expression in -much simplier. So it is the first one, that is implemented in MySQL. - - -@node MyISAM Record Structure, InnoDB Record Structure, Fulltext Search, Top -@chapter MyISAM Record Structure - -@section Introduction - -When you say: -@* - -@strong{CREATE TABLE Table1 ...} -@* - -MySQL creates files named Table1.MYD ("MySQL Data"), Table1.MYI -("MySQL Index"), and Table1.frm ("Format"). These files will be in the -directory: @* -/// -@* - -For example, if you use Linux, you might find the files here (assume -your database name is "test"): @* -/usr/local/var/test -@* - -And if you use Windows, you might find the files in this directory: @* -\mysql\data\test\ -@*@* - -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). -@* - -@item Record Header -The minimal record header is a set of flags: -@itemize @bullet -@item -"X bit" = 0 if row is deleted, = 1 if row is not deleted -@item -"Null Bits" = 0 if column is not NULL, = 1 if column is NULL -@item -"Filler Bits" = 1 -@end itemize -@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: -@* - -@strong{CREATE TABLE Table1 (column1 CHAR(1), column2 CHAR(1), column3 CHAR(1))} -@* - -@strong{INSERT INTO Table1 VALUES ('a', 'b', 'c')} -@* - -@strong{INSERT INTO Table1 VALUES ('d', NULL, 'e')} -@* - -A CHAR(1) column takes precisely one byte (plus one bit of overhead -that is assigned to every column -- I'll describe the details of -column storage later). So the file Table1.MYD looks like this: -@* - -@strong{Hexadecimal Display of Table1.MYD file}@* -@code{ -F1 61 62 63 00 F5 64 00 66 00 ... .abc..d e. -} -@* - -Here's how to read this hexadecimal-dump display:@* -@itemize @bullet -@item -The hexadecimal numbers @code{F1 61 62 63 00 F5 64 20 66 00} are byte -values and the column on the right is an attempt to show the -same bytes in ASCII. -@item -The @code{F1} byte means that there are no null fields in the first row. -@item -The @code{F5} byte means that the second column of the second row is NULL. -@end itemize - -(It's probably easier to understand the flag setting if you restate -@code{F5} as @code{11110101 binary}, and (a) notice that the third flag bit from the -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 -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 -@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. -The format depends entirely on the data type and the size of the -column, so, for every data type, I'll give a description and an example. -@* - -@table @strong -@item The character data types - -@strong{CHAR} -@itemize @bullet -@item -Storage: fixed-length string with space padding on the right. -@item -Example: a CHAR(5) column containing the value 'A' looks like:@* -@code{hexadecimal 41 20 20 20 20} -- (length = 5, value = @code{'A '}) -@end itemize - -@strong{VARCHAR} -@itemize @bullet -@item -Storage: variable-length string with a preceding length. -@item -Example: a VARCHAR(7) column containing 'A' looks like:@* -@code{hexadecimal 01 41} -- (length = 1, value = @code{'A'}) -@end itemize - -@item The numeric data types - -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. -@* - -@strong{TINYINT} -@itemize @bullet -@item -Storage: fixed-length binary, always one byte. -@item -Example: a TINYINT column containing 65 looks like:@* -@code{hexadecimal 41} -- (length = 1, value = 65) -@end itemize - -@strong{SMALLINT} -@itemize @bullet -@item -Storage: fixed-length binary, always two bytes. -@item -Example: a SMALLINT column containing 65 looks like:@* -@code{hexadecimal 41 00} -- (length = 2, value = 65) -@end itemize - -@strong{MEDIUMINT} -@itemize @bullet -@item -Storage: fixed-length binary, always three bytes. -@item -Example: a MEDIUMINT column containing 65 looks like:@* -@code{hexadecimal 41 00 00} -- (length = 3, value = 65) -@end itemize - -@strong{INT} -@itemize @bullet -@item -Storage: fixed-length binary, always four bytes. -@item -Example: an INT column containing 65 looks like:@* -@code{hexadecimal 41 00 00 00} -- (length = 4, value = 65) -@end itemize - -@strong{BIGINT} -@itemize @bullet -@item -Storage: fixed-length binary, always eight bytes. -@item -Example: a BIGINT column containing 65 looks like:@* -@code{hexadecimal 41 00 00 00 00 00 00 00} -- (length = 8, value = 65) -@end itemize - -@strong{FLOAT} -@itemize @bullet -@item -Storage: fixed-length binary, always four bytes. -@item -Example: a FLOAT column containing approximately 65 looks like:@* -@code{hexadecimal 00 00 82 42} -- (length = 4, value = 65) -@end itemize - -@strong{DOUBLE PRECISION} -@itemize @bullet -@item -Storage: fixed-length binary, always eight bytes. -@item -Example: a DOUBLE PRECISION column containing approximately 65 looks like:@* -@code{hexadecimal 00 00 00 00 00 40 50 40} -- (length = 8, value = 65) -@end itemize - -@strong{REAL} -@itemize @bullet -@item -Storage: same as FLOAT, or same as DOUBLE PRECISION, depending on setting of the --ansi switch. -@end itemize - -@strong{DECIMAL} -@itemize @bullet -@item -Storage: fixed-length string, with a leading byte for the sign, if any. -@item -Example: a DECIMAL(2) column containing 65 looks like:@* -@code{hexadecimal 20 36 35} -- (length = 3, value = @code{' 65'}) -@item -Example: a DECIMAL(2) UNSIGNED column containing 65 looks like:@* -@code{hexadecimal 36 35} -- (length = 2, value = @code{'65'}) -@item -Example: a DECIMAL(4,2) UNSIGNED column containing 65 looks like:@* -@code{hexadecimal 36 35 2E 30 30} -- (length = 5, value = @code{'65.00'}) -@end itemize - -@strong{NUMERIC} -@itemize @bullet -@item -Storage: same as DECIMAL. -@end itemize - -@strong{BOOL} -@itemize @bullet -@item -Storage: same as TINYINT. -@end itemize - -@item The temporal data types - -@strong{DATE} -@itemize @bullet -@item -Storage: 3 byte integer, low byte first. -Packed as: 'day + month*32 + year*16*32' -@item -Example: a DATE column containing '1962-01-02' looks like:@* -@code{hexadecimal 22 54 0F} -@end itemize - -@strong{DATETIME} -@itemize @bullet -@item -Storage: eight bytes. -@item -Part 1 is a 32-bit integer containing year*10000 + month*100 + day. -@item -Part 2 is a 32-bit integer containing hour*10000 + minute*100 + second. -@item -Example: a DATETIME column for '0001-01-01 01:01:01' looks like:@* -@code{hexadecimal B5 2E 11 5A 02 00 00 00} -@end itemize - -@strong{TIME} -@itemize @bullet -@item -Storage: 3 bytes, low byte first. -This is stored as seconds: days*24*3600+hours*3600+minutes*60+seconds -@item -Example: a TIME column containing '1 02:03:04' (1 day 2 hour 3 minutes and 4 seconds) looks like:@* -@code{hexadecimal 58 6E 01} -@end itemize - -@strong{TIMESTAMP} -@itemize @bullet -@item -Storage: 4 bytes, low byte first. -Stored as unix @code{time()}, which is seconds since the Epoch -(00:00:00 UTC, January 1, 1970). -@item -Example: a TIMESTAMP column containing '2003-01-01 01:01:01' looks like:@* -@code{hexadecimal 4D AE 12 23} -@end itemize - -@strong{YEAR} -@itemize @bullet -@item -Storage: same as unsigned TINYINT with a base value of 0 = 1901. -@end itemize - -@item Others - -@strong{SET} -@itemize @bullet -@item -Storage: one byte for each eight members in the set. -@item -Maximum length: eight bytes (for maximum 64 members). -@item -This is a bit list. The least significant bit corresponds to the -first listed member of the set. -@item -Example: a SET('A','B','C') column containing 'A' looks like:@* -@code{01} -- (length = 1, value = 'A') -@end itemize - -@strong{ENUM} -@itemize @bullet -@item -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 an erroneous value. This -explains why 'A' is 1 instead of 0.) -@item -Example: an ENUM('A','B','C') column containing 'A' looks like:@* -@code{01} -- (length = 1, value = 'A') -@end itemize - -@item The Large-Object data types - -Warning: Because TINYBLOB's preceding length is one byte long (the -size of a TINYINT) and MEDIUMBLOB's preceding length is three bytes -long (the size of a MEDIUMINT), it's easy to think there's some sort -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). -@* - -@strong{TINYBLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding one-byte length. -@item -Example: a TINYBLOB column containing 'A' looks like:@* -@code{hexadecimal 01 41} -- (length = 2, value = 'A') -@end itemize - -@strong{TINYTEXT} -@itemize @bullet -@item -Storage: same as TINYBLOB. -@end itemize - -@strong{BLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding two-byte length. -@item -Example: a BLOB column containing 'A' looks like:@* -@code{hexadecimal 01 00 41} -- (length = 2, value = 'A') -@end itemize - -@strong{TEXT} -@itemize @bullet -@item -Storage: same as BLOB. -@end itemize - -@strong{MEDIUMBLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding length. -@item -Example: a MEDIUMBLOB column containing 'A' looks like:@* -@code{hexadecimal 01 00 00 41} -- (length = 4, value = 'A') -@end itemize - -@strong{MEDIUMTEXT} -@itemize @bullet -@item -Storage: same as MEDIUMBLOB. -@end itemize - -@strong{LONGBLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding four-byte length. -@item -Example: a LONGBLOB column containing 'A' looks like:@* -@code{hexadecimal 01 00 00 00 41} -- (length = 5, value = 'A') -@end itemize - -@strong{LONGTEXT} -@itemize @bullet -@item -Storage: same as LONGBLOB. -@end itemize - -@end table - -@section Where to Look For More Information - -@strong{References:} @* -Most of the formatting work for MyISAM columns is visible -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 -@chapter InnoDB Record Structure - -This page contains: -@itemize @bullet -@item -A high-altitude "summary" picture of the parts of a MySQL/InnoDB -record structure. -@item -A description of each part. -@item -An example. -@end itemize - -After reading this page, you will know how MySQL/InnoDB stores a -physical record. -@* - -@section High-Altitude Picture - -The chart below shows the three parts of a physical record. - -@multitable @columnfractions .10 .35 - -@item @strong{Name} @tab @strong{Size} -@item Field Start Offsets -@tab (F*1) or (F*2) bytes -@item Extra Bytes -@tab 6 bytes -@item Field Contents -@tab depends on content - -@end multitable - -Legend: The letter 'F' stands for 'Number Of Fields'. - -The meaning of the parts is as follows: -@itemize @bullet -@item -The FIELD START OFFSETS is a list of numbers containing the -information "where a field starts". -@item -The EXTRA BYTES is a fixed-size header. -@item -The FIELD CONTENTS contains the actual data. -@end itemize - -@strong{An Important Note About The Word "Origin"}@* -The "Origin" or "Zero Point" of a record is the first byte of the -Field Contents -- not the first byte of the Field Start Offsets. If -there is a pointer to a record, that pointer is pointing to the -Origin. Therefore the first two parts of the record are addressed by -subtracting from the pointer, and only the third part is addressed by -adding to the pointer. - -@subsection FIELD START OFFSETS - -The Field Start Offsets is a list in which each entry is the -position, relative to the Origin, of the start of the next field. The -entries are in reverse order, that is, the first field's offset is at -the end of the list. -@* - -An example: suppose there are three columns. The first column's length -is 1, the second column's length is 2, and the third column's length is 4. -In this case, the offset values are, respectively, 1, 3 (1+2), and 7 (1+2+4). -Because values are reversed, a core dump of the Field Start Offsets -would look like this: @code{07,03,01}. -@* - -There are two complications for special cases: -@itemize @bullet -@item -Complication #1: The size of each offset can be either one byte or -two bytes. One-byte offsets are only usable if the total record size -is less than 127. There is a flag in the "Extra Bytes" part which will -tell you whether the size is one byte or two bytes. -@item -Complication #2: The most significant bits of an offset may contain -flag values. The next two paragraphs explain what the contents are. -@end itemize - -@strong{When The Size Of Each Offset Is One Byte} -@itemize @bullet -@item -1 bit = 0 if field is non-NULL, = 1 if field is NULL -@item -7 bits = the actual offset, a number between 0 and 127 -@end itemize - -@strong{When The Size Of Each Offset Is Two Bytes} -@itemize @bullet -@item -1 bit = 0 if field is non-NULL, = 1 if field is NULL -@item -1 bit = 0 if field is on same page as offset, = 1 if field and offset are on different pages -@item -14 bits = the actual offset, a number between 0 and 16383 -@end itemize - -It is unlikely that the "field and offset are on different pages" -unless the record contains a large BLOB. - -@subsection EXTRA BYTES - -The Extra Bytes are a fixed six-byte header. - -@multitable @columnfractions .10 .25 .35 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Description} -@item @strong{info_bits:} -@item () -@tab 1 bit -@tab unused or unknown -@item () -@tab 1 bit -@tab unused or unknown -@item deleted_flag -@tab 1 bit -@tab 1 if record is deleted -@item min_rec_flag -@tab 1 bit -@tab 1 if record is predefined minimum record -@item n_owned -@tab 4 bits -@tab number of records owned by this record -@item heap_no -@tab 13 bits -@tab record's order number in heap of index page -@item n_fields -@tab 10 bits -@tab number of fields in this record, 1 to 1023 -@item 1byte_offs_flag -@tab 1 bit -@tab 1 if each Field Start Offsets is 1 byte long (this item is also called the "short" flag) -@item @strong{next 16 bits} -@tab 16 bits -@tab pointer to next record in page -@item @strong{TOTAL} -@tab 48 bits - -@end multitable - -Total size is 48 bits, which is six bytes. -@* - -If you're just trying to read the record, the key bit in the Extra -Bytes is 1byte_offs_flag -- you need to know if 1byte_offs_flag is 1 -(i.e.: "short 1-byteoffsets") or 0 (i.e.: "2-byte offsets"). -@* - -Given a pointer to the Origin, InnoDB finds the start of the record as follows: -@itemize @bullet -@item -Let X = n_fields (the number of fields is by definition equal to the -number of entries in the Field Start Offsets Table). -@item -If 1byte_offs_flag equals 0, then let X = X * 2 because there are -two bytes for each entry instead of just one. -@item -Let X = X + 6, because the fixed size of Extra Bytes is 6. -@item -The start of the record is at (pointer value minus X). -@end itemize - -@subsection FIELD CONTENTS - -The Field Contents part of the record has all the data. Fields are -stored in the order they were defined in. -@* - -There are no markers between fields, and there is no marker or filler -at the end of a record. -@* - -Here's an example. -@itemize @bullet -@item -I made a table with this definition: -@*@* - -@strong{CREATE TABLE T - (FIELD1 VARCHAR(3), FIELD2 VARCHAR(3), FIELD3 VARCHAR(3)) - Type=InnoDB;} -@*@* - -To understand what follows, you must know that table T has six columns --- not three -- because InnoDB automatically added three "system -columns" at the start for its own housekeeping. It happens that these -system columns are the row ID, the transaction ID, and the rollback -pointer, but their values don't matter now. Regard them as three black -boxes. -@*@* - -@item -I put some rows in the table. My last three INSERTs were: -@*@* - -@strong{INSERT INTO T VALUES ('PP', 'PP', 'PP')} -@*@* - -@strong{INSERT INTO T VALUES ('Q', 'Q', 'Q')} -@*@* - -@strong{INSERT INTO T VALUES ('R', NULL, NULL)} -@*@* - -@item -I ran Borland's TDUMP to get a hexadecimal dump of -the contents of \mysql\data\ibdata1, which (in my case) is the -MySQL/InnoDB data file (on Windows). -@end itemize - -Here is an extract of the dump: - -@multitable @columnfractions .05 .95 - -@item @strong{Address Values In Hexadecimal} @tab @strong{Values In ASCII} -@item @code{0D4280: 00 00 2D 00 84 4F 4F 4F 4F 4F 4F 4F 4F 4F 19 17} -@tab @code{..-..OOOOOOOOO..} -@item @code{0D4290: 15 13 0C 06 00 00 78 0D 02 BF 00 00 00 00 04 21} -@tab @code{......x........!} -@item @code{0D42A0: 00 00 00 00 09 2A 80 00 00 00 2D 00 84 50 50 50} -@tab @code{.....*....-..PPP} -@item @code{0D42B0: 50 50 50 16 15 14 13 0C 06 00 00 80 0D 02 E1 00} -@tab @code{PPP.............} -@item @code{0D42C0: 00 00 00 04 22 00 00 00 00 09 2B 80 00 00 00 2D} -@tab @code{....".....+....-} -@item @code{0D42D0: 00 84 51 51 51 94 94 14 13 0C 06 00 00 88 0D 00} -@tab @code{..QQQ...........} -@item @code{0D42E0: 74 00 00 00 00 04 23 00 00 00 00 09 2C 80 00 00} -@tab @code{t.....#.....,...} -@item @code{0D42F0: 00 2D 00 84 52 00 00 00 00 00 00 00 00 00 00 00} -@tab @code{.-..R...........} - -@end multitable - -A reformatted version of the dump, showing only the relevant bytes, -looks like this (I've put a line break after each field and added labels): - -@strong{Reformatted Hexadecimal Dump}@* -@code{ - 19 17 15 13 0C 06 Field Start Offsets /* First Row */@* - 00 00 78 0D 02 BF Extra Bytes@* - 00 00 00 00 04 21 System Column #1@* - 00 00 00 00 09 2A System Column #2@* - 80 00 00 00 2D 00 84 System Column #3@* - 50 50 Field1 'PP'@* - 50 50 Field2 'PP'@* - 50 50 Field3 'PP'}@* - -@code{ - 16 15 14 13 0C 06 Field Start Offsets /* Second Row */@* - 00 00 80 0D 02 E1 Extra Bytes@* - 00 00 00 00 04 22 System Column #1@* - 00 00 00 00 09 2B 80 System Column #2@* - 00 00 00 2D 00 84 System Column #3@* - 51 Field1 'Q'@* - 51 Field2 'Q'@* - 51 Field3 'Q'}@* - -@code{ - 94 94 14 13 0C 06 Field Start Offsets /* Third Row */@* - 00 00 88 0D 00 74 Extra Bytes@* - 00 00 00 00 04 23 System Column #1@* - 00 00 00 00 09 2C System Column #2@* - 80 00 00 00 2D 00 84 System Column #3@* - 52 Field1 'R'}@* -@* - -You won't need explanation if you followed everything I've said, but -I'll add helpful notes for the three trickiest details. -@itemize @bullet -@item -Helpful Notes About "Field Start Offsets": @* -Notice that the sizes of the record's fields, in forward order, are: -6, 6, 7, 2, 2, 2. Since each offset is for the start of the "next" -field, the hexadecimal offsets are 06, 0c (6+6), 13 (6+6+7), 15 -(6+6+7+2), 17 (6+6+7+2+2), 19 (6+6+7+2+2+2). Reversing the order, the -Field Start Offsets of the first record are: @code{19,17,15,13,0c,06}. -@item -Helpful Notes About "Extra Bytes": @* -Look at the Extra Bytes of the first record: @code{00 00 78 0D 02 BF}. The -fourth byte is @code{0D hexadecimal}, which is @code{1101 binary} ... the 110 is the -last bits of n_fields (@code{110 binary} is 6 which is indeed the number of -fields in the record) and the final 1 bit is 1byte_offs_flag. The -fifth and sixth bytes, which contain @code{02 BF}, constitute the "next" -field. Looking at the original hexadecimal dump, at address -@code{0D42BF} (which is position @code{02BF} within the page), you'll see the beginning bytes of -System Column #1 of the second row. In other words, the "next" field -points to the "Origin" of the following row. -@item -Helpful Notes About NULLs:@* -For the third row, I inserted NULLs in FIELD2 and FIELD3. Therefore in -the Field Start Offsets the top bit is @code{on} for these fields (the -values are @code{94 hexadecimal}, @code{94 hexadecimal}, instead of -@code{14 hexadecimal}, @code{14 hexadecimal}). And the row is -shorter because the NULLs take no space. -@end itemize - -@section Where to Look For More Information - -@strong{References:} @* -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 -@chapter InnoDB Page Structure - -InnoDB stores all records inside a fixed-size unit which is commonly called a -"page" (though InnoDB sometimes calls it a "block" instead). -Currently all pages are the same size, 16KB. -@* - -A page contains records, but it also contains headers and trailers. -I'll start this description with a high-altitude view of a page's parts, -then I'll describe each part of a page. Finally, I'll show an example. This -discussion deals only with the most common format, for the leaf page of a data file. -@* - -@section High-Altitude View - -An InnoDB page has seven parts: -@itemize @bullet -@item -Fil Header -@item -Page Header -@item -Infimum + Supremum Records -@item -User Records -@item -Free Space -@item -Page Directory -@item -Fil Trailer -@end itemize - -As you can see, a page has two header/trailer pairs. The inner pair, "Page Header" and -"Page Directory", are mostly the concern of the \page program group, -while the outer pair, "Fil Header" and "Fil Trailer", are mostly the -concern of the \fil program group. The "Fil" header also goes goes by -the name of "File Page Header". -@* - -Sandwiched between the headers and trailers, are the records and -the free (unused) space. A page always begins with two unchanging -records called the Infimum and the Supremum. Then come the user -records. Between the user records (which grow downwards) and the page -directory (which grows upwards) there is space for new records. -@* - -@subsection Fil Header - -The Fil Header has eight parts, as follows: - -@multitable @columnfractions .10 .30 .35 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Remarks} -@item FIL_PAGE_SPACE -@tab 4 -@tab 4 ID of the space the page is in -@item FIL_PAGE_OFFSET -@tab 4 -@tab ordinal page number from start of space -@item FIL_PAGE_PREV -@tab 4 -@tab offset of previous page in key order -@item FIL_PAGE_NEXT -@tab 4 -@tab offset of next page in key order -@item FIL_PAGE_LSN -@tab 8 -@tab log serial number of page's latest log record -@item FIL_PAGE_TYPE -@tab 2 -@tab current defined types are: FIL_PAGE_INDEX, FIL_PAGE_UNDO_LOG, FIL_PAGE_INODE, FIL_PAGE_IBUF_FREE_LIST -@item FIL_PAGE_FILE_FLUSH_LSN -@tab 8 -@tab "the file has been flushed to disk at least up to this lsn" (log serial number), - valid only on the first page of the file -@item FIL_PAGE_ARCH_LOG_NO -@tab 4 -@tab the latest archived log file number at the time that FIL_PAGE_FILE_FLUSH_LSN was written (in the log) -@end multitable - -@itemize -@item -FIL_PAGE_SPACE is a necessary identifier because different pages might belong to -different (table) spaces within the same file. The word -"space" is generic jargon for either "log" or "tablespace". -@*@* - -@item -FIL_PAGE_PREV and FIL_PAGE_NEXT are the page's "backward" and -"forward" pointers. To show what they're about, I'll draw a two-level -B-tree. -@*@* - -@example - -------- - - root - - -------- - | - ---------------------- - | | - | | - -------- -------- - - leaf - <--> - leaf - - -------- -------- -@end example -@* - -Everyone has seen a B-tree and knows that the entries in the root page -point to the leaf pages. (I indicate those pointers with vertical '|' -bars in the drawing.) But sometimes people miss the detail that leaf -pages can also point to each other (I indicate those pointers with a horizontal -two-way pointer '<-->' in the drawing). This feature allows InnoDB to navigate from -leaf to leaf without having to back up to the root level. This is a -sophistication which you won't find in the classic B-tree, which is -why InnoDB should perhaps be called a B+-tree instead. -@*@* - -@item -The fields FIL_PAGE_FILE_FLUSH_LSN, FIL_PAGE_PREV, and FIL_PAGE_NEXT -all have to do with logs, so I'll refer you to my article "How Logs -Work With MySQL And InnoDB" on devarticles.com. -@*@* - -@item -FIL_PAGE_FILE_FLUSH_LSN and FIL_PAGE_ARCH_LOG_NO are only valid for -the first page of a data file. -@end itemize - -@subsection Page Header - -The Page Header has 14 parts, as follows: -@*@* - -@multitable @columnfractions .10 .20 .30 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Remarks} -@item PAGE_N_DIR_SLOTS -@tab 2 -@tab number of directory slots in the Page Directory part; initial value = 2 -@item PAGE_HEAP_TOP -@tab 2 -@tab record pointer to first record in heap -@item PAGE_N_HEAP -@tab 2 -@tab number of heap records; initial value = 2 -@item PAGE_FREE -@tab 2 -@tab record pointer to first free record -@item PAGE_GARBAGE -@tab 2 -@tab "number of bytes in deleted records" -@item PAGE_LAST_INSERT -@tab 2 -@tab record pointer to the last inserted record -@item PAGE_DIRECTION -@tab 2 -@tab either PAGE_LEFT, PAGE_RIGHT, or PAGE_NO_DIRECTION -@item PAGE_N_DIRECTION -@tab 2 -@tab number of consecutive inserts in the same direction, e.g. "last 5 were all to the left" -@item PAGE_N_RECS -@tab 2 -@tab number of user records -@item PAGE_MAX_TRX_ID -@tab 8 -@tab the highest ID of a transaction which might have changed a record on the page (only set for secondary indexes) -@item PAGE_LEVEL -@tab 2 -@tab level within the index (0 for a leaf page) -@item PAGE_INDEX_ID -@tab 8 -@tab identifier of the index the page belongs to -@item PAGE_BTR_SEG_LEAF -@tab 10 -@tab "file segment header for the leaf pages in a B-tree" (this is irrelevant here) -@item PAGE_BTR_SEG_TOP -@tab 10 -@tab "file segment header for the non-leaf pages in a B-tree" (this is irrelevant here) - -@end multitable -@* - -(Note: I'll clarify what a "heap" is when I discuss the User Records part of the page.) -@*@* - -Some of the Page Header parts require further explanation: -@itemize @bullet -@item -PAGE_FREE: @* -Records which have been freed (due to deletion or migration) are in a -one-way linked list. The PAGE_FREE pointer in the page header points -to the first record in the list. The "next" pointer in the record -header (specifically, in the record's Extra Bytes) points to the next -record in the list. -@item -PAGE_DIRECTION and PAGE_N_DIRECTION: @* -It's useful to know whether inserts are coming in a constantly -ascending sequence. That can affect InnoDB's efficiency. -@item -PAGE_HEAP_TOP and PAGE_FREE and PAGE_LAST_INSERT: @* -Warning: Like all record pointers, these point not to the beginning of the -record but to its Origin (see the earlier discussion of Record -Structure). -@item -PAGE_BTR_SEG_LEAF and PAGE_BTR_SEG_TOP: @* -These variables contain information (space ID, page number, and byte offset) about -index node file segments. InnoDB uses the information for allocating new pages. -There are two different variables because InnoDB allocates separately for leaf -pages and upper-level pages. -@end itemize - -@subsection The Infimum And Supremum Records - -"Infimum" and "supremum" are real English words but they are found -only in arcane mathematical treatises, and in InnoDB comments. To -InnoDB, an infimum is lower than the the lowest possible real value -(negative infinity) and a supremum is greater than the greatest -possible real value (positive infinity). InnoDB sets up an infimum -record and a supremum record automatically at page-create time, and -never deletes them. They make a useful barrier to navigation so that -"get-prev" won't pass the beginning and "get-next" won't pass the end. -Also, the infimum record can be a dummy target for temporary record -locks. -@*@* - -The InnoDB code comments distinguish between "the infimum and supremum -records" and the "user records" (all other kinds). -@*@* - -It's sometimes unclear whether InnoDB considers the infimum and -supremum to be part of the header or not. Their size is fixed and -their position is fixed, so I guess so. - -@subsection User Records - -In the User Records part of a page, you'll find all the records that the user -inserted. -@*@* - -There are two ways to navigate through the user records, depending -whether you want to think of their organization as an unordered or an -ordered list. -@*@* - -An unordered list is often called a "heap". If you make a pile of -stones by saying "whichever one I happen to pick up next will go on -top" -- rather than organizing them according to size and colour -- -then you end up with a heap. Similarly, InnoDB does not want to insert -new rows according to the B-tree's key order (that would involve -expensive shifting of large amounts of data), so it inserts new rows -right after the end of the existing rows (at the -top of the Free Space part) or wherever there's space left by a -deleted row. -@*@* - -But by definition the records of a B-tree must be accessible in order -by key value, so there is a record pointer in each record (the "next" -field in the Extra Bytes) which points to the next record in key -order. In other words, the records are a one-way linked list. So -InnoDB can access rows in key order when searching. - -@subsection Free Space - -I think it's clear what the Free Space part of a page is, from the discussion of -other parts. - -@subsection Page Directory - -The Page Directory part of a page has a variable number of record pointers. -Sometimes the record pointers are called "slots" or "directory slots". -Unlike other DBMSs, InnoDB does not have a slot for every record in -the page. Instead it keeps a sparse directory. In a fullish page, -there will be one slot for every six records. -@*@* - -The slots track the records' logical order (the order by key rather -than the order by placement on the heap). Therefore, if the records -are @code{'A' 'B' 'F' 'D'} the slots will be @code{(pointer to 'A') (pointer to -'B') (pointer to 'D') (pointer to 'F')}. Because the slots are in key -order, and each slot has a fixed size, it's easy to do a binary -search of the records on the page via the slots. -@*@* - -(Since the Page Directory does not have a slot for every record, -binary search can only give a rough position and then InnoDB must -follow the "next" record pointers. InnoDB's "sparse slots" policy also -accounts for the n_owned field in the Extra Bytes part of a record: -n_owned indicates how many more records must be gone through because -they don't have their own slots.) - -@subsection Fil Trailer - -The Fil Trailer has one part, as follows: -@*@* - -@multitable @columnfractions .10 .35 .40 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Remarks} -@item FIL_PAGE_END_LSN -@tab 8 -@tab low 4 bytes = checksum of page, last 4 bytes = same as FIL_PAGE_LSN -@end multitable -@* - -The final part of a page, the fil trailer (or File Page Trailer), -exists because InnoDB's architect worried about integrity. It's -impossible for a page to be only half-written, or corrupted by -crashes, because the log-recovery mechanism restores to a consistent -state. But if something goes really wrong, then it's nice to have a -checksum, and to have a value at the very end of the page which must -be the same as a value at the very beginning of the page. - -@section Example - -For this example, I used Borland's TDUMP again, as I did for the earlier chapter on -Record Format. This is what a page looked like: -@*@* - -@multitable @columnfractions .05 .95 - -@item @strong{Address Values In Hexadecimal} @tab @strong{Values In ASCII} -@item @code{0D4000: 00 00 00 00 00 00 00 35 FF FF FF FF FF FF FF FF} -@tab @code{.......5........} -@item @code{0D4010: 00 00 00 00 00 00 E2 64 45 BF 00 00 00 00 00 00} -@tab @code{.......dE.......} -@item @code{0D4020: 00 00 00 00 00 00 00 05 02 F5 00 12 00 00 00 00} -@tab @code{................} -@item @code{0D4030: 02 E1 00 02 00 0F 00 10 00 00 00 00 00 00 00 00} -@tab @code{................} -@item @code{0D4040: 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00} -@tab @code{................} -@item @code{0D4050: 00 02 16 B2 00 00 00 00 00 00 00 02 15 F2 08 01} -@tab @code{................} -@item @code{0D4060: 00 00 03 00 89 69 6E 66 69 6D 75 6D 00 09 05 00} -@tab @code{.....infimum....} -@item @code{0D4070: 08 03 00 00 73 75 70 72 65 6D 75 6D 00 22 1D 18} -@tab @code{....supremum."..} -@item @code{0D4080: 13 0C 06 00 00 10 0D 00 B7 00 00 00 00 04 14 00} -@tab @code{................} -@item @code{0D4090: 00 00 00 09 1D 80 00 00 00 2D 00 84 41 41 41 41} -@tab @code{.........-..AAAA} -@item @code{0D40A0: 41 41 41 41 41 41 41 41 41 41 41 1F 1B 17 13 0C} -@tab @code{AAAAAAAAAAA.....} -@item @code{ ... } -@item @code{ ... } -@item @code{0D7FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 74} -@tab @code{...............t} -@item @code{0D7FF0: 02 47 01 AA 01 0A 00 65 3A E0 AA 71 00 00 E2 64} -@tab @code{.G.....e:..q...d} -@end multitable -@*@* - -Let's skip past the first 38 bytes, which are Fil Header. The bytes -of the Page Header start at location @code{0d4026 hexadecimal}: -@*@* - -@multitable @columnfractions .10 .45 .60 - -@item @strong{Location} @tab @strong{Name} @tab @strong{Description} -@item @code{00 05} -@tab PAGE_N_DIR_SLOTS -@tab There are 5 directory slots. -@item @code{02 F5} -@tab PAGE_HEAP_TOP -@tab At location @code{0402F5}, not shown, is the beginning of free space. -Maybe a better name would have been PAGE_HEAP_END -@item @code{00 12} -@tab PAGE_N_HEAP -@tab There are 18 (hexadecimal 12) records in the page. -@item @code{00 00} -@tab PAGE_FREE -@tab There are zero free (deleted) records. -@item @code{00 00} -@tab PAGE_GARBAGE -@tab There are zero bytes in deleted records. -@item @code{02 E1} -@tab PAGE_LAST_INSERT -@tab The last record was inserted at location @code{02E1}, not shown, within the page. -@item @code{00 02} -@tab PAGE_DIRECTION -@tab A glance at page0page.h will tell you that 2 is the #defined value for PAGE_RIGHT. -@item @code{00 0F} -@tab PAGE_N_DIRECTION -@tab The last 15 (hexadecimal 0F) inserts were all done "to the right" -because I was inserting in ascending order. -@item @code{00 10} -@tab PAGE_N_RECS -@tab There are 16 (hexadecimal 10) user records. Notice that PAGE_N_RECS is -smaller than the earlier field, PAGE_N_HEAP. -@item @code{00 00 00 00 00 00 00} -@tab PAGE_MAX_TRX_ID -@item @code{00 00} -@tab PAGE_LEVEL -@tab Zero because this is a leaf page. -@item @code{00 00 00 00 00 00 00 14} -@tab PAGE_INDEX_ID -@tab This is index number 20. -@item @code{00 00 00 00 00 00 00 02 16 B2} -@tab PAGE_BTR_SEG_LEAF -@item @code{00 00 00 00 00 00 00 02 15 F2} -@tab PAGE_BTR_SEG_TOP -@end multitable -@* - -Immediately after the page header are the infimum and supremum -records. Looking at the "Values In ASCII" column in the hexadecimal -dump, you will see that the contents are in fact the words "infimum" -and "supremum" respectively. -@*@* - -Skipping past the User Records and the Free Space, many bytes later, -is the end of the 16KB page. The values shown there are the two trailers. -@itemize @bullet -@item -The first trailer (@code{00 74, 02 47, 01 AA, 01 0A, 00 65}) is the page -directory. It has 5 entries, because the header field PAGE_N_DIR_SLOTS -says there are 5. -@item -The next trailer (@code{3A E0 AA 71, 00 00 E2 64}) is the fil trailer. Notice -that the last four bytes, @code{00 00 E2 64}, appeared before in the fil -header. -@end itemize - -@section Where to Look For More Information - -@strong{References:} @* -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 -@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 -source code of MySQL. This description begins with a list -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. - -@section Directory Listing - -@strong{Directory -- Short Comment} -@itemize @bullet -@item -bdb -- The Berkeley Database table handler -@item -BitKeeper -- BitKeeper administration (not part of the source distribution) -@item -BUILD -- Frequently used build scripts -@item -Build-tools -- Build tools (not part of the source distribution) -@item -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; will eventually be moved to the mysqldoc repository -@item -extra -- Some minor standalone utility programs -@item -heap -- The HEAP table handler -@item -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 -libmysql -- For producing MySQL as a library (e.g. a Windows .DLL) -@item -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 -myisam -- The MyISAM table handler -@item -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.) -@item -netware -- Files related to the Novell NetWare version of MySQL -@item -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 (not currently used) -@item -regex -- Henry Spencer's Regular Expression library for support of REGEXP function -@item -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 -@item -sql-bench -- The MySQL benchmarks -@item -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 and in C -@item -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 -@end itemize - -@subsection bdb - -The Berkeley Database table handler. -@*@* - -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 -http://www.sleepycat.com/docs/. Since it's reasonably thorough -documentation, a description of the BDB program files is not included -in this document. -@*@* - -@subsection BitKeeper - -BitKeeper administration. -@*@* - -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. Please see @url{http://www.mysql.com/doc/en/Installing_source_tree.html} -for more information. -@*@* - -@subsection BUILD - -Frequently used build scripts. -@*@* - -This directory contains the build switches for compilation on various -platforms. There is a subdirectory for each set of options. The main -ones are: -@itemize @bullet -@item -alpha -@item -ia64 -@item -pentium (with and without debug or bdb, etc.) -@item -solaris -@end itemize -@*@* - -@subsection Build-tools - -Build tools. -@*@* - -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 - -Client library. -@*@* - -The client library includes mysql.cc (the source of the 'mysql' -executable) and other utilities. Most of the utilities are mentioned -in the MySQL Reference Manual. Generally these are standalone C -programs which one runs in "client mode", that is, they call the -server. -@*@* - -The C program files in the directory are: -@itemize @bullet -@item -get_password.c -- ask for a password from the console -@item -mysql.cc -- "The MySQL command tool" -@item -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, suitable to backup a MySQL database -@item -mysqlimport.c -- import text files in different formats into tables -@item -mysqlmanager-pwgen.c -- pwgen stands for "password generation" (not currently maintained) -@item -mysqlmanagerc.c -- entry point for mysql manager (not currently maintained) -@item -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 (version 4.1 and up) -@end itemize -@*@* - -@subsection cmd-line-utils - -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 -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. -@*@* - -The \readline subdirectory contains the files of the GNU Readline -Library, "a library for reading lines of text with interactive input -and history editing". The programs are copyrighted by the Free -Software Foundation. -@*@* - -The \libedit (library of edit functions) subdirectory has files -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 -@item -common.c -- common editor functions -@item -el.c -- editline interface functions -@item -emacs.c -- emacs functions -@item -fgetln.c -- get line -@item -hist.c -- history access functions -@item -history.c -- more history access functions -@item -key.c -- procedures for maintaining the extended-key map -@item -map.c -- editor function definitions -@item -parse.c -- parse an editline extended command -@item -prompt.c -- prompt printing functions -@item -read.c -- terminal read functions -@item -readline.c -- read line -@item -refresh.c -- "lower level screen refreshing functions" -@item -search.c -- "history and character search functions" -@item -sig.c -- for signal handling -@item -strlcpy.c -- string copy -@item -term.c -- "editor/termcap-curses interface" -@item -tokenizer.c -- Bourne shell line tokenizer -@item -tty.c -- for a tty interface -@item -vi.c -- commands used when in the vi (editor) mode -@end itemize -@*@* - -@subsection dbug - -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 -package. -@*@* - -How it works: One inserts a function call that begins with DBUG_* in -one of the regular MYSQL programs. For example, in get_password.c, you -will find this line: @* -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 -(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 -@item -dbug_analyze.c -- Reads a file produced by trace functions -@item -example1.c -- A tiny example -@item -example2.c -- A tiny example -@item -example3.c -- A tiny example -@item -factorial.c -- A tiny example -@item -main.c -- A tiny example -@item -sanity.c -- Declaration of a variable -@end itemize -@*@* - -@subsection Docs - -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. 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 -@item -flags -- images of flags of countries -@item -images -- flag backgrounds and the MySQL dolphin logo -@item -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 -@item -to-be-included... -- contains a MySQL-for-dummies file -@item -translations -- some Portuguese myodbc documentation -@end itemize -@*@* - -In the main directory, you'll find some .txt files related to the -methods that MySQL uses to produce its printed and html documents, odd -bits in various languages, and the single file in the directory which -has any importance -- internals.texi -- The "MySQL Internals" -document. -@*@* - -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 - -Some minor standalone utility programs. -@*@* - -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: -@itemize @bullet -@item -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_waitpid.c -- wait for a program to terminate. Useful for shell scripts when one needs to wait until a process terminates. -@item -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 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 -@end itemize -@*@* - -@subsection heap - -The HEAP table handler. -@*@* - -All the MySQL table handlers (i.e. the handlers that MySQL itself -produces) have files with similar names and functions. Thus, this -(heap) directory contains a lot of duplication of the myisam directory -(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. (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 -@item -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 -@item -hp_create.c -- * create a table -@item -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 -@item -hp_info.c -- * Information about database status -@item -hp_open.c -- * open database -@item -hp_panic.c -- * the hp_panic routine, for shutdowns and flushes -@item -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 -@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 -@item -hp_rrnd.c -- * read a row based on position -@item -hp_rsame.c -- * find current row using positional read or key-based -read -@item -hp_scan.c -- * read all rows sequentially -@item -hp_static.c -- * static variables (very short) -@item -hp_test1.c -- * testing basic functions -@item -hp_test2.c -- * testing database and storing results -@item -hp_update.c -- * update an existing row -@item -hp_write.c -- * insert a new row -@end itemize -@*@* - -There are fewer files in the heap directory than in the myisam -directory, because fewer are necessary. For example, there is no need -for a \myisam\mi_cache.c equivalent (to cache reads) or a -\myisam\log.c equivalent (to log statements). -@*@* - -@subsection include - -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 -individual directory will also have its own *.h files, for including -in its own *.c programs. The *.h files in the include directory are -ones that might be included from more than one place. -@*@* - -For example, the mysys directory contains a C file named rijndael.c, -but does not include rijndael.h. The include directory contains -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 (header) files. -@*@* - -@subsection innobase - -The Innobase (InnoDB) table handler. -@*@* - -A full description of these files can be found elsewhere in this -document. -@*@* - -@subsection libmysql - -The MySQL Library, Part 1. -@*@* - -The files here are for producing MySQL as a library (e.g. a Windows -DLL). The idea is that, instead of producing separate mysql (client) -and mysqld (server) programs, one produces a library. Instead of -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). -@*@* - -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 -@item -dll.c -- initialization of the dll library -@item -errmsg.c -- English error messages, compare \mysys\errors.c -@item -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 -@end itemize -@*@* - -@subsection libmysql_r - -The MySQL Library, Part 2. -@*@* - -There is only one file here, used to build a thread-safe libmysql library: -@itemize @bullet -@item -makefile.am -@end itemize -@*@* - -@subsection libmysqld - -The MySQL library, Part 3. -@*@* - -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 -libmysqld.c -- The called side, compare the mysqld.exe source -@item -lib_vio.c -- Emulate the vio directory's communication buffer -@end itemize -@*@* - -@subsection man - -Some user-contributed manual pages -@*@* - -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 - -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 -@item -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 -@item -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 -@item -sort.c -- this is a single file that sorts keys for index-create purposes -@end itemize -@*@* - -The "full text" and "rtree" and "spatial" program sets are for special -purposes, so this document focuses only on the mi*.c "myisam" C -programs. They are: -@itemize @bullet -@item -mi_cache.c -- for reading records from a cache -@item -mi_changed.c -- a single routine for setting a "changed" flag (very short) -@item -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 -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) -@item -mi_delete.c -- delete a row -@item -mi_delete_all.c -- delete all rows -@item -mi_delete_table.c -- delete a table (very short) -@item -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 -- return useful base information for an open table -@item -mi_key.c -- for handling keys -@item -mi_locking.c -- lock database -@item -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 -@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 -@item -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 -@item -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 -@item -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 -@item -mi_rsame.c -- find current row using positional read or key-based read -@item -mi_rsamepos.c -- positional read -@item -mi_scan.c -- read all rows sequentially -@item -mi_search.c -- key-handling functions -@item -mi_static.c -- static variables (very short) -@item -mi_statrec.c -- functions to handle fixed-length records -@item -mi_test1.c -- testing basic functions -@item -mi_test2.c -- testing database and storing results -@item -mi_test3.c -- testing locking -@item -mi_unique.c -- functions to check if a row is unique -@item -mi_update.c -- update an existing row -@item -mi_write.c -- insert a new row -@end itemize -@*@* - -@subsection myisammrg - -MyISAM Merge table handler. -@*@* - -As with other table handlers, you'll find that the *.c files in the -myissammrg directory have counterparts in the myisam directory. In -fact, this general description of a myisammrg program is almost always -true: The myisammrg -function checks an argument, the myisammrg function formulates an -expression for passing to a myisam function, the myisammrg calls a -myisam function, the myisammrg function returns. -@*@* - -These are the 21 files in the myisammrg directory, with notes about -the myisam functions or programs they're connected with: -@itemize @bullet -@item -myrg_close.c -- mi_close.c -@item -myrg_create.c -- mi_create.c -@item -myrg_delete.c -- mi_delete.c / delete last-read record -@item -myrg_extra.c -- mi_extra.c / "extra functions we want to do ..." -@item -myrg_info.c -- mi_info.c / display information about a mymerge file -@item -myrg_locking.c -- mi_locking.c / lock databases -@item -myrg_open.c -- mi_open.c / open a MyISAM MERGE table -@item -myrg_panic.c -- mi_panic.c / close in a hurry -@item -myrg_queue.c -- read record based on a key -@item -myrg_range.c -- mi_range.c / find records in a range -@item -myrg_rfirst.c -- mi_rfirst.c / read first record according to -specific key -@item -myrg_rkey.c -- mi_rkey.c / read record based on a key -@item -myrg_rlast.c -- mi_rlast.c / read last row with same key as previous -read -@item -myrg_rnext.c -- mi_rnext.c / read next row with same key as previous -read -@item -myrg_rnext_same.c -- mi_rnext_same.c / read next row with same key -@item -myrg_rprev.c -- mi_rprev.c / read previous row with same key -@item -myrg_rrnd.c -- mi_rrnd.c / read record with random access -@item -myrg_rsame.c -- mi_rsame.c / call mi_rsame function, see -\myisam\mi_rsame.c -@item -myrg_static.c -- mi_static.c / static variable declaration -@item -myrg_update.c -- mi_update.c / call mi_update function, see -\myisam\mi_update.c -@item -myrg_write.c -- mi_write.c / call mi_write function, see -\myisam\mi_write.c -@end itemize -@*@* - -@subsection mysql-test - -A test suite for mysqld. -@*@* - -The directory has a README file which explains how to run the tests, -how to make new tests (in files with the filename extension "*.test"), -and how to report errors. -@*@* - -There are four subdirectories: -@itemize @bullet -@item -\misc -- contains one minor Perl program -@item -\r -- contains *.result, i.e. "what happened" files and -*.required, i.e. "what should happen" file -@item -\std_data -- contains standard data for input to tests -@item -\t -- contains tests -@end itemize -@*@* - -There are 186 *.test files in the \t subdirectory. Primarily these are -SQL scripts which try out a feature, output a result, and compare the -result with what's required. Some samples of what the test files check -are: latin1_de comparisons, date additions, the HAVING clause, outer -joins, openSSL, load data, logging, truncate, and UNION. -@*@* - -There are other tests in these directories: -@itemize @bullet -@item -sql-bench -@item -tests -@end itemize - -@subsection mysys - -MySQL system library. Low level routines for file access and so on. -@*@* - -There are 115 *.c programs in this directory: -@itemize @bullet -@item -array.c -- Dynamic array handling -@item -charset.c -- Using dynamic character sets, set default character set, ... -@item -charset2html.c -- Check what character set a browser is using -@item -checksum.c -- Calculate checksum for a memory block, used for pack_isam -@item -default.c -- Find defaults from *.cnf or *.ini files -@item -errors.c -- English text of global errors -@item -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" -@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 (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" -@item -mf_dirname.c -- Parse/convert directory names -@item -mf_fn_ext.c -- Get filename extension -@item -mf_format.c -- Format a filename -@item -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 -@item -mf_iocache2.c -- Continuation of mf_iocache.c -@item -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 -@item -mf_qsort.c -- Quicksort -@item -mf_qsort2.c -- Quicksort, part 2 (allows the passing of an extra argument to the sort-compare routine) -@item -mf_radix.c -- Radix sort -@item -mf_same.c -- Determine whether filenames are the same -@item -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) -@item -mf_strip.c -- Strip trail spaces from a string -@item -mf_tempdir.c -- Initialize/find/free temporary directory -@item -mf_tempfile.c -- Create a temporary file -@item -mf_unixpath.c -- Convert filename to UNIX-style filename -@item -mf_util.c -- Routines, #ifdef'd, which may be missing on some -machines -@item -mf_wcomp.c -- Comparisons with wildcards -@item -mf_wfile.c -- Finding files with wildcards -@item -mulalloc.c -- Malloc many pointers at the same time -@item -my_aes.c -- AES encryption -@item -my_alarm.c -- Set a variable value when an alarm is received -@item -my_alloc.c -- malloc of results which will be freed simultaneously -@item -my_append.c -- one file to another -@item -my_bit.c -- smallest X where 2^X >= value, maybe useful for -divisions -@item -my_bitmap.c -- Handle uchar arrays as large bitmaps -@item -my_chsize.c -- Truncate file if shorter, else fill with a filler -character -@item -my_clock.c -- Time-of-day ("clock()") function, with OS-dependent -#ifdef's -@item -my_compress.c -- Compress packet (see also description of \zlib -directory) -@item -my_copy.c -- Copy files -@item -my_create.c -- Create file -@item -my_delete.c -- Delete file -@item -my_div.c -- Get file's name -@item -my_dup.c -- Open a duplicated file -@item -my_error.c -- Return formatted error to user -@item -my_fopen.c -- File open -@item -my_fstream.c -- Streaming file read/write -@item -my_getwd.c -- Get working directory -@item -my_gethostbyname.c -- Thread-safe version of standard net -gethostbyname() func -@item -my_getopt.c -- Find out what options are in effect -@item -my_handler.c -- Compare two keys in various possible formats -@item -my_init.c -- Initialize variables and functions in the mysys library -@item -my_lib.c -- Compare/convert directory names and file names -@item -my_lock.c -- Lock part of a file -@item -my_lockmem.c -- "Allocate a block of locked memory" -@item -my_lread.c -- Read a specified number of bytes from a file into -memory -@item -my_lwrite.c -- Write a specified number of bytes from memory into a -file -@item -my_malloc.c -- Malloc (memory allocate) and dup functions -@item -my_messnc.c -- Put out a message on stderr with "no curses" -@item -my_mkdir.c -- Make directory -@item -my_net.c -- Thread-safe version of net inet_ntoa function -@item -my_netware.c -- Functions used only with the Novell Netware version -of MySQL -@item -my_once.c -- Allocation / duplication for "things we don't need to -free" -@item -my_open.c -- Open a file -@item -my_os2cond.c -- OS2-specific: "A simple implementation of posix conditions" -@item -my_os2dirsrch.c -- OS2-specific: Emulate a Win32 directory search -@item -my_os2dlfcn.c -- OS2-specific: Emulate UNIX dynamic loading -@item -my_os2file64.c -- OS2-specific: For File64bit setting -@item -my_os2mutex.c -- OS2-specific: For mutex handling -@item -my_os2thread.c -- OS2-specific: For thread handling -@item -my_os2tls.c -- OS2-specific: For thread-local storage -@item -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 -@item -my_quick.c -- Read/write (labelled a "quicker" interface, perhaps -obsolete) -@item -my_read.c -- Read a specified number of bytes from a file, possibly -retry -@item -my_realloc.c -- Reallocate memory allocated with my_alloc.c -(probably) -@item -my_redel.c -- Rename and delete file -@item -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 -@item -my_sleep.c -- Wait n microseconds -@item -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 -@item -my_tempnam.c -- Obsolete temporary-filename routine used by ISAM table handler -@item -my_thr_init.c -- initialize/allocate "all mysys & debug thread variables" -@item -my_wincond.c -- Windows-specific: emulate Posix conditions -@item -my_winsem.c -- Windows-specific: emulate Posix threads -@item -my_winthread.c -- Windows-specific: emulate Posix threads -@item -my_write.c -- Write a specified number of bytes to a file -@item -ptr_cmp.c -- Point to an optimal byte-comparison function -@item -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") -@item -safemalloc.c -- A version of the standard malloc() with safety checking -@item -sha1.c -- Implementation of Secure Hashing Algorithm 1 -@item -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 -@item -test_charset.c -- Standalone program: display character set information -@item -test_dir.c -- Standalone program: placeholder for "test all functions" idea -@item -test_fn.c -- Standalone program: apparently tests a function -@item -test_xml.c -- Standalone program: test XML routines -@item -thr_alarm.c -- Thread alarms and signal handling -@item -thr_lock.c -- "Read and write locks for Posix threads" -@item -thr_mutex.c -- A wrapper for mutex functions -@item -thr_rwlock.c -- Synchronizes the readers' thread locks with the writer's lock -@item -tree.c -- Initialize/search/free binary trees -@item -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: -@*@* - -@example -"int my_getwd _A((string buf, uint size, myf MyFlags)); @* - int my_setwd _A((const char *dir, myf MyFlags)); @* - Get and set working directory." @* -@end example - -@subsection netware - -Files related to the Novell NetWare version of MySQL. -@*@* - -There are 39 files on this directory. Most have filename extensions of -*.def, *.sql, or *.c. -@*@* - -The twenty-five *.def files are all from Novell Inc. They contain import or -export symbols. (".def" is a common filename extension for -"definition".) -@*@* - -The two *.sql files are short scripts of SQL statements used in -testing. -@*@* - -These are the five *.c files, all from Novell Inc.: -@itemize @bullet -@item -libmysqlmain.c -- Only one function: init_available_charsets() -@item -my_manage.c -- Standalone management utility -@item -mysql_install_db.c -- Compare \scripts\mysql_install_db.sh -@item -mysql_test_run.c -- Short test program -@item -mysqld_safe.c -- Compare \scripts\mysqld_safe.sh -@end itemize - -Perhaps the most important file is: -@itemize @bullet -@item -netware.patch -- NetWare-specific build instructions and switches -(compare \mysql-4.1\ltmain.sh) -@end itemize -@*@* - -For instructions about basic installation, see "Deployment Guide For -NetWare AMP" at: -@url{http://developer.novell.com/ndk/whitepapers/namp.htm} -@* - -@subsection NEW-RPMS - -Directory to place RPMs while making a distribution. -@*@* - -This directory is not part of the Windows distribution. It is -a temporary directory used during RPM builds with Linux distributions. -@*@* - -@subsection os2 - -Routines for working with the OS2 operating system. -@*@* - -The files in this directory are the product of the efforts of three -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: -@itemize @bullet -@item -A Readme.Txt file -@item -An \include subdirectory containing .h files which are for OS/2 only -@item -Files used in the build process (configuration, switches, and one -.obj) -@end itemize -@*@* - -The README file refers to MySQL version 3.23, which suggests that -there have been no updates for MySQL 4.0 for this section. -@*@* - -@subsection pstack - -Process stack display (not currently used). -@*@* - -This is a set of publicly-available debugging aids which all do pretty -well the same thing: display the contents of the stack, along with -symbolic information, for a running process. There are versions for -various object file formats (such as ELF and IEEE-695). Most of the -programs are copyrighted by the Free Software Foundation and are -marked as "part of GNU Binutils". -@*@* - -In other words, the pstack files are not really part of the MySQL -library. They are merely useful when you re-program some MYSQL code -and it crashes. -@*@* - -@subsection regex - -Henry Spencer's Regular Expression library for support of REGEXP function. -@*@* - -This is the copyrighted product of Henry Spencer from the University -of Toronto. It's a fairly-well-known implementation of the -requirements of POSIX 1003.2 Section 2.8. The library is bundled with -Apache and is the default implementation for regular-expression -handling in BSD Unix. MySQL's Monty Widenius has made minor changes in -three programs (debug.c, engine.c, regexec.c) but this is not a MySQL -package. MySQL calls it only in order to support two MySQL functions: -REGEXP and RLIKE. -@*@* - -Some of Mr Spencer's documentation for the regex library can be found -in the README and WHATSNEW files. -@*@* - -One MySQL program which uses regex is \cmd-line-utils\libedit\search.c -@*@* - -This program calls the 'regcomp' function, which is the entry point in -\regex\regexp.c. -@*@* - -@subsection SCCS - -Source Code Control System (not part of source distribution). -@*@* - -You will see this directory if and only if you used BitKeeper for -downloading the source. The files here are for BitKeeper -administration and are not of interest to application programmers. -@*@* - -@subsection scripts - -SQL batches, e.g. mysqlbug and mysql_install_db. -@*@* - -The *.sh filename extension stands for "shell script". Linux -programmers use it where Windows programmers would use a *.bat -(batch filename extension). -@*@* - -The *.sh files on this directory are: -@itemize @bullet -@item -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 (partly) mSQL programs and scripts to MySQL -@item -mysqlbug.sh -- Create a bug report and mail it -@item -mysqld_multi.sh -- Start/stop any number of mysqld instances -@item -mysqld_safe-watch.sh -- Start/restart in safe mode -@item -mysqld_safe.sh -- Start/restart in safe mode -@item -mysqldumpslow.sh -- Parse and summarize the slow query log -@item -mysqlhotcopy.sh -- Hot backup -@item -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 -@item -mysql_explain_log.sh -- Put a log (made with --log) into a MySQL table -@item -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. 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. -@item -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 -mysql_zap.sh -- Kill processes which match pattern -@end itemize -@*@* - -@subsection sql - -Programs for handling SQL commands. The "core" of MySQL. -@*@* - -These are the .c and .cc files in the sql directory: -@itemize @bullet -@item -convert.cc -- convert tables between different character sets -@item -derror.cc -- read language-dependent message file -@item -des_key_file.cc -- load DES keys from plaintext file -@item -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 -@item -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 -@item -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 -@item -ha_heap.cc -- Handler: Heap -@item -ha_innodb.cc -- Handler: InnoDB -@item -ha_isam.cc -- Handler: ISAM -@item -ha_isammrg.cc -- Handler: (ISAM MERGE) -@item -ha_myisam.cc -- Handler: MyISAM -@item -ha_myisammrg.cc -- Handler: (MyISAM MERGE) -@item -hostname.cc -- Given IP, return hostname -@item -init.cc -- Init and dummy functions for interface with unireg -@item -item.cc -- Item functions -@item -item_buff.cc -- Buffers to save and compare item values -@item -item_cmpfunc.cc -- Definition of all compare functions -@item -item_create.cc -- Create an item. Used by lex.h. -@item -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 -item_strfunc.cc -- String functions -@item -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 -key.cc -- Functions to create keys from records and compare a key to a key in a record -@item -lock.cc -- Locks -@item -log.cc -- Logs -@item -log_event.cc -- Log event (a binary log consists of a stream of log events) -@item -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; used by the replication code -@item -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 (like /mysys/my_lock.c, but with timeout handling for threads) -@item -net_serv.cc -- Read/write of packets on a network socket -@item -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 -opt_range.cc -- Range of keys -@item -opt_sum.cc -- Optimize functions in presence of (implied) GROUP BY -@item -password.c -- Password checking -@item -procedure.cc -- Procedure interface, as used in SELECT * FROM Table_name PROCEDURE ANALYSE -@item -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 -repl_failsafe.cc -- Replication fail-save (not yet implemented) -@item -set_var.cc -- Set and retrieve MySQL user variables -@item -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; checks, stores, retrieves, and deletes MySQL user level privileges -@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, like opening and closing tables with table cache management -@item -sql_cache.cc -- SQL query cache, with long comments about how caching works -@item -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 -sql_db.cc -- Create / drop database -@item -sql_delete.cc -- The DELETE statement -@item -sql_derived.cc -- Derived tables, with long comments -@item -sql_do.cc -- The DO statement -@item -sql_error.cc -- Errors and warnings -@item -sql_handler.cc -- Implements the HANDLER interface, which gives direct access to rows in MyISAM and InnoDB -@item -sql_help.cc -- The HELP statement -@item -sql_insert.cc -- The INSERT statement -@item -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 (the rest of the list class is implemented in sql_list.h) -@item -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; used with BDB table logs -@item -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, or use a prepared statement -@item -sql_repl.cc -- Replication -@item -sql_rename.cc -- Rename table -@item -sql_select.cc -- Select and join optimisation -@item -sql_show.cc -- The SHOW statement -@item -sql_string.cc -- String functions: alloc, realloc, copy, convert, etc. -@item -sql_table.cc -- The DROP TABLE and ALTER TABLE statements -@item -sql_test.cc -- Some debugging information -@item -sql_udf.cc -- User-defined functions -@item -sql_union.cc -- The UNION operator -@item -sql_update.cc -- The UPDATE statement -@item -stacktrace.c -- Display stack trace (Linux/Intel only) -@item -table.cc -- Table metadata retrieval; read the table definition from a .frm file and store it in a TABLE object -@item -thr_malloc.cc -- Thread-safe interface to /mysys/my_alloc.c -@item -time.cc -- Date and time functions -@item -udf_example.cc -- Example file of user-defined functions -@item -uniques.cc -- Function to handle quick removal of duplicates -@item -unireg.cc -- Create a unireg form file (.frm) from a FIELD and field-info struct -@end itemize -@*@* - -@subsection sql-bench - -The MySQL Benchmarks. -@*@* - -This directory has the programs and input files which MySQL uses for -its comparisons of MySQL, PostgreSQL, mSQL, Solid, etc. Since MySQL -publishes the comparative results, it's only right that it should make -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. -@item -\Data\ATIS -- .txt files containing input data for the "ATIS" tests -@item -\Data\Wisconsin -- .txt files containing input data for the "Wisconsin" tests -@item -\Results -- old test results -@item -\Results-win32 -- old test results from Windows 32-bit tests -@end itemize -@*@* - -There are twenty-four *.sh (shell script) files, which involve Perl -programs. -@*@* - -There are three *.bat (batch) files. -@*@* - -There is one README file and one TODO file. -@*@* - -@subsection SSL - -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 -(the NOTES file) and seven *.pem files. PEM stands for "Privacy -Enhanced Mail" and is an Internet standard for adding security to -electronic mail. Finally, there are two short scripts for running -clients and servers over SSL connections. -@*@* - -@subsection strings - -The string library. -@*@* - -Many of the files in this subdirectory are equivalent to well-known -functions that appear in most C string libraries. For those, there is -documentation available in most compiler handbooks. -@*@* - -On the other hand, some of the files are MySQL additions or -improvements. Often the MySQL changes are attempts to optimize the -standard libraries. It doesn't seem that anyone tried to optimize for -recent Pentium class processors, though. -@*@* - -The .C files are: -@itemize @bullet -@item -atof.c -- ascii-to-float, MySQL version -@item -bchange.c -- short replacement routine written by Monty Widenius in -1987 -@item -bcmp.c -- binary compare, rarely used -@item -bcopy-duff.c -- block copy: attempt to copy memory blocks faster -than cmemcpy -@item -bfill.c -- byte fill, to fill a buffer with (length) copies of a -byte -@item -bmove.c -- block move -@item -bmove512.c -- "should be the fastest way to move a multiple of 512 -bytes" -@item -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 -@item -ctype*.c -- string handling programs for each char type MySQL -handles -@item -do_ctype.c -- display case-conversion and sort-conversion tables -@item -int2str.c -- integer-to-string -@item -is_prefix.c -- checks whether string1 starts with string2 -@item -llstr.c -- convert long long to temporary-buffer string, return -pointer -@item -longlong2str.c -- ditto, but to argument-buffer -@item -memcmp.c -- memory compare -@item -memset.c -- memory set -@item -my_vsnprintf.c -- variant of printf -@item -r_strinstr.c -- see if one string is within another -@item -str2int.c -- convert string to integer -@item -strappend.c -- fill up a string to n characters -@item -strcat.c -- concatenate strings -@item -strcend.c -- point to where a character C occurs within str, or NULL -@item -strchr.c -- point to first place in string where character occurs -@item -strcmp.c -- compare two strings -@item -strcont.c -- point to where any one of a set of characters appears -@item -strend.c -- point to the '\0' byte which terminates str -@item -strfill.c -- fill a string with n copies of a byte -@item -strinstr.c -- find string within string -@item -strlen.c -- return length of string in bytes -@item -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 -@item -strnlen.c -- return min(length of string, n) -@item -strnmov.c -- move source to dest for source size, or for n bytes -@item -strrchr.c -- find a character within string, searching from end -@item -strstr.c -- find an instance of pattern within source -@item -strto.c -- string to long, to long long, to unsigned long, etc. -@item -strtol.c -- string to long -@item -strtoll.c -- string to long long -@item -strtoul.c -- string to unsigned long -@item -strtoull.c -- string to unsigned long long -@item -strxmov.c -- move a series of concatenated source strings to dest -@item -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, for operating systems that don't support these -@item -xml.c -- read and parse XML strings; used to read character definition information stored in /sql/share/charsets -@end itemize -@*@* - -There are also four .ASM files -- macros.asm, ptr_cmp.asm, -strings.asm, and strxmov.asm -- which can replace some of the -C-program functions. But again, they look like optimizations for old -members of the Intel processor family. -@*@* - -@subsection 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. They -include example my.cnf files one can use as a default setup for -MySQL. -@*@* - -@subsection tests - -Tests in Perl and in C. -@*@* - -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 - -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. Related to fail-safe -replication. -@end itemize -@*@* - -@subsection VC++Files - -Visual C++ Files. -@*@* - -Includes this entire directory, repeated for VC++ (Windows) use. -@*@* - -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 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. -@*@* - -In addition to the "subdirectories which are duplicates of -directories", VC++Files contains these subdirectories, which are not -duplicates: -@itemize @bullet -@item -comp_err -- (nearly empty) -@item -contrib -- (nearly empty) -@item -InstallShield -- script files -@item -isamchk -- (nearly empty) -@item -libmysqltest -- one small non-MySQL test program: mytest.c -@item -myisamchk -- (nearly empty) -@item -myisamlog -- (nearly empty) -@item -myisammrg -- (nearly empty) -@item -mysqlbinlog -- (nearly empty) -@item -mysqlmanager -- MFC foundation class files created by AppWizard -@item -mysqlserver -- (nearly empty) -@item -mysqlshutdown -- one short program, mysqlshutdown.c -@item -mysqlwatch.c -- Windows service initialization and monitoring -@item -my_print_defaults -- (nearly empty) -@item -pack_isam -- (nearly empty) -@item -perror -- (nearly empty) -@item -prepare -- (nearly empty) -@item -replace -- (nearly empty) -@item -SCCS -- source code control system -@item -test1 -- tests connecting via X threads -@item -thr_insert_test -- (nearly empty) -@item -thr_test -- one short program used to test for memory-allocation bug -@item -winmysqladmin -- the winmysqladmin.exe source -@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. -@*@* - -The VIO routines are wrappers for the various network I/O calls that -happen with different protocols. The idea is that in the main modules -one won't have to write separate bits of code for each protocol. Thus -vio's purpose is somewhat like the purpose of Microsoft's winsock -library. -@*@* - -The underlying protocols at this moment are: TCP/IP, Named Pipes (for -WindowsNT), Shared Memory, and Secure Sockets (SSL). -@*@* - -The C programs are: -@itemize @bullet -@item -test-ssl.c -- Short standalone test program: SSL -@item -test-sslclient.c -- Short standalone test program: clients -@item -test-sslserver.c -- Short standalone test program: server -@item -vio.c -- Declarations + open/close functions -@item -viosocket.c -- Send/retrieve functions -@item -viossl.c -- SSL variations for the above -@item -viosslfactories.c -- Certification / Verification -@item -viotest.cc -- Short standalone test program: general -@item -viotest-ssl.c -- Short standalone test program: SSL -@item -viotest-sslconnect.cc -- Short standalone test program: SSL connect -@end itemize -@*@* - -The older functions -- raw_net_read, raw_net_write -- are now -obsolete. -@*@* - -@subsection zlib - -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 -package. It was produced by the GNU Zip (gzip.org) people. Zlib is a -variation of the famous "Lempel-Ziv" method, which is also used by -"Zip". The method for reducing the size of any arbitrary string of -bytes is as follows: -@itemize @bullet -@item -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. -@end itemize - -There is a full description of the library's functions in the gzip -manual at: @* -@url{http://www.gzip.org/zlib/manual.html} @* -There is therefore no need to list the modules in this document. -@*@* - -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 - -ERRATUM BY HEIKKI TUURI (START) -@*@* - -Errata about InnoDB row locks:@*@* - -@example - #define LOCK_S 4 /* shared */ - #define LOCK_X 5 /* exclusive */ -... -@strong{/* Waiting lock flag */} - #define LOCK_WAIT 256 -/* this wait bit should be so high that it can be ORed to the lock -mode and type; when this bit is set, it means that the lock has not -yet been granted, it is just waiting for its turn in the wait queue */ -... -@strong{/* Precise modes */} - #define LOCK_ORDINARY 0 -/* this flag denotes an ordinary next-key lock in contrast to LOCK_GAP -or LOCK_REC_NOT_GAP */ - #define LOCK_GAP 512 -/* this gap bit should be so high that it can be ORed to the other -flags; when this bit is set, it means that the lock holds only on the -gap before the record; for instance, an x-lock on the gap does not -give permission to modify the record on which the bit is set; locks of -this type are created when records are removed from the index chain of -records */ - #define LOCK_REC_NOT_GAP 1024 -/* this bit means that the lock is only on the index record and does -NOT block inserts to the gap before the index record; this is used in -the case when we retrieve a record with a unique key, and is also used -in locking plain SELECTs (not part of UPDATE or DELETE) when the user -has set the READ COMMITTED isolation level */ - #define LOCK_INSERT_INTENTION 2048 -/* this bit is set when we place a waiting gap type record lock -request in order to let an insert of an index record to wait until -there are no conflicting locks by other transactions on the gap; note -that this flag remains set when the waiting lock is granted, or if the -lock is inherited to a neighboring record */ -@end example -@* - -ERRATUM BY HEIKKI TUURI (END) -@*@* - -The InnoDB source files are the best place to look for information -about internals of the file structure that MySQLites can optionally -use for transaction support. But when you first look at all the -subdirectories and file names you'll wonder: Where Do I Start? It can -be daunting. -@*@* - -Well, I've been through that phase, so I'll pass on what I had to -learn on the first day that I looked at InnoDB source files. I am very -sure that this will help you grasp, in overview, the organization of -InnoDB modules. I'm also going to add comments about what is going on --- which you should mistrust! These comments are reasonable working -hypotheses; nevertheless, they have not been subjected to expert peer -review. -@*@* - -Here's how I'm going to organize the discussion. I'll take each of the -32 InnoDB subdirectories that come with the MySQL 4.0 source code in -\mysql\innobase (on my Windows directory). The format of each section -will be like this every time: -@*@* - -@strong{\subdirectory-name (LONGER EXPLANATORY NAME)}@* -@multitable @columnfractions .10 .20 .40 .50 -@item @strong{File Name} @tab @strong{What Name Stands For} @tab @strong{Size} @tab @strong{Comment Inside File} -@item file-name -@tab my-own-guess -@tab in-bytes -@tab from-the-file-itself -@end multitable -...@* -My-Comments@* -@* - -For example: @* -@example -" -@strong{\ha (HASHING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ha0ha.c Hashing/Hashing 7,452 Hash table with external chains - - Comments about hashing will be here. -" -@end example -@* - -The "Comment Inside File" column is a direct copy from the first /* -comment */ line inside the file. All other comments are mine. After -I've discussed each directory, I'll finish with some notes about -naming conventions and a short list of URLs that you can use for -further reference. -@*@* - -Now let's begin. -@*@* - -@example - -@strong{\ha (HASHING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ha0ha.c Hashing / Hashing 7,452 Hash table with external chains - -I'll hold my comments until the next section, \hash (HASHING). - -@strong{\hash (HASHING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - hash0hash.c Hashing / Hashing 3,257 Simple hash table utility - -The two C programs in the \ha and \hashing directories -- ha0ha.c and -hash0hash.c -- both refer to a "hash table" but hash0hash.c is -specialized, it is mostly about accessing points in the table under -mutex control. - -When a "database" is so small that InnoDB can load it all into memory -at once, it's more efficient to access it via a hash table. After all, -no disk i/o can be saved by using an index lookup, if there's no disk. - -@strong{\os (OPERATING SYSTEM)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - os0shm.c OS / Shared Memory 3,150 To shared memory primitives - os0file.c OS / File 64,412 To i/o primitives - os0thread.c OS / Thread 6,827 To thread control primitives - os0proc.c OS / Process 3,700 To process control primitives - os0sync.c OS / Synchronization 10,208 To synchronization primitives - -This is a group of utilities that other modules may call whenever they -want to use an operating-system resource. For example, in os0file.c -there is a public InnoDB function named os_file_create_simple(), which -simply calls the Windows-API function CreateFile. Naturally the -contents of this group are somewhat different for other operating systems. - -The "Shared Memory" functions in os0shm.c are only called from the -communications program com0shm.c (see \com COMMUNICATIONS). The i/o -and thread-control primitives are called extensively. The word -"synchronization" in this context refers to the mutex-create and -mutex-wait functionality. - -@strong{\ut (UTILITIES)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ut0ut.c Utilities / Utilities 7,041 Various utilities - ut0byte.c Utilities / Debug 1,856 Byte utilities - ut0rnd.c Utilities / Random 1,475 Random numbers and hashing - ut0mem.c Utilities / Memory 5,530 Memory primitives - ut0dbg.c Utilities / Debug 642 Debug utilities - -The two functions in ut0byte.c are just for lower/upper case -conversion and comparison. The single function in ut0rnd.c is for -finding a prime slightly greater than the given argument, which is -useful for hash functions, but unrelated to randomness. The functions -in ut0mem.c are wrappers for "malloc" and "free" calls -- for the -real "memory" module see section \mem (MEMORY). Finally, the -functions in ut0ut.c are a miscellany that didn't fit better elsewhere: -get_high_bytes, clock, time, difftime, get_year_month_day, and "sprintf" -for various diagnostic purposes. - -In short: the \ut group is trivial. - -@strong{\buf (BUFFERING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - buf0buf.c Buffering / Buffering 53,246 The database buffer buf_pool - buf0flu.c Buffering / Flush 23,711 ... flush algorithm - buf0lru.c / least-recently-used 20,245 ... replacement algorithm - buf0rea.c Buffering / read 17,399 ... read - -There is a separate file group (\mem MEMORY) which handles memory -requests in general.A "buffer" usually has a more specific -definition, as a memory area which contains copies of pages that -ordinarily are in the main data file. The "buffer pool" is the set -of all buffers (there are lots of them because InnoDB doesn't -depend on the OS's caching to make things faster). - -The pool size is fixed (at the time of this writing) but the rest of -the buffering architecture is sophisticated, involving a host of -control structures. In general: when InnoDB needs to access a new page -it looks first in the buffer pool; InnoDB reads from disk to a new -buffer when the page isn't there; InnoDB chucks old buffers (basing -its decision on a conventional Least-Recently-Used algorithm) when it -has to make space for a new buffer. - -There are routines for checking a page's validity, and for read-ahead. -An example of "read-ahead" use: if a sequential scan is going on, then -a DBMS can read more than one page at a time, which is efficient -because reading 32,768 bytes (two pages) takes less than twice as long -as reading 16,384 bytes (one page). - -@strong{\btr (B-TREE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - btr0btr.c B-tree / B-tree 74,255 B-tree - btr0cur.c B-tree / Cursor 94,950 index tree cursor - btr0sea.c B-tree / Search 36,580 index tree adaptive search - btr0pcur.c B-tree / persistent cursor 14,548 index tree persistent cursor - -If you total up the sizes of the C files, you'll see that \btr is the -second-largest file group in InnoDB. This is understandable because -maintaining a B-tree is a relatively complex task. Luckily, there has -been a lot of work done to describe efficient management of B-tree and -B+-tree structures, much of it open-source or public-domain, since -their original invention over thirty years ago. - -InnoDB likes to put everything in B-trees. This is what I'd call a -"distinguishing characteristic" because in all the major DBMSs (like -IBM DB2, Microsoft SQL Server, and Oracle), the main or default or -classic structure is the heap-and-index. In InnoDB the main structure -is just the index. To put it another way: InnoDB keeps the rows in the -leaf node of the index, rather than in a separate file. Compare -Oracle's Index Organized Tables, and Microsoft SQL Server's Clustered -Indexes. - -This, by the way, has some consequences. For example, you may as well -have a primary key since otherwise InnoDB will make one anyway. And -that primary key should be the shortest of the candidate keys, since -InnoDB -will use it as a pointer if there are secondary indexes. - -Most importantly, it means that rows have no fixed address. Therefore -the routines for managing file pages should be good. We'll see about -that when we look at the \row (ROW) program group later. - -@strong{\com (COMMUNCATION)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - com0com.c Communication 6,913 Communication primitives - com0shm.c Communication / 24,633 ... through shared memory - Shared Memory - -The communication primitives in com0com.c are said to be modelled -after the ones in Microsoft's winsock library (the Windows Sockets -interface). The communication primitives in com0shm.c are at a -slightly lower level, and are called from the routines in com0com.c. - -I was interested in seeing how InnoDB would handle inter-process -communication, since there are many options -- named pipes, TCP/IP, -Windows messaging, and Shared Memory being the main ones that come to -mind. It appears that InnoDB prefers Shared Memory. The main idea is: -there is an area of memory which two different processes (or threads, -of course) can both access. To communicate, a thread gets an -appropriate mutex, puts in a request, and waits for a response. Thread -interaction is also a subject for the os0thread.c program in another -program group, \os (OPERATING SYSTEM). - -@strong{\dyn (DYNAMICALLY ALLOCATED ARRAY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - dyn0dyn.c Dynamic / Dynamic 994 dynamically allocated array - -There is a single function in the dyn0dyn.c program, for adding a -block to the dynamically allocated array. InnoDB might use the array -for managing concurrency between threads. - -At the moment, the \dyn program group is trivial. - -@strong{\fil (FILE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - fil0fil.c File / File 39,725 The low-level file system - -The reads and writes to the database files happen here, in -co-ordination with the low-level file i/o routines (see os0file.h in -the \os program group). - -Briefly: a table's contents are in pages, which are in files, which -are in tablespaces. Files do not grow; instead one can add new files -to the tablespace. As we saw earlier (discussing the \btr program group) -the pages are nodes of B-trees. Since that's the case, new additions can -happen at various places in the logical file structure, not -necessarily at the end. Reads and writes are asynchronous, and go into -buffers, which are set up by routines in the \buf program group. - -@strong{\fsp (FILE SPACE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - fsp0fsp.c File Space Management 100,271 File space management - -I would have thought that the \fil (FILE) and \fsp (FILE SPACE) -MANAGEMENT programs would fit together in the same program group; -however, I guess the InnoDB folk are splitters rather than lumpers. - -It's in fsp0fsp.c that one finds some of the descriptions and comments -of extents, segments, and headers. For example, the "descriptor bitmap -of the pages in the extent" is in here, and you can find as well how -the free-page list is maintained, what's in the bitmaps, and what -various header fields' contents are. - -@strong{\fut (FILE UTILITY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - fut0fut.c File Utility / Utility 293 File-based utilities - fut0lst.c File Utility / List 14,129 File-based list utilities - -Mainly these small programs affect only file-based lists, so maybe -saying "File Utility" is too generic. The real work with data files -goes on in the \fsp program group. - -@strong{\log (LOGGING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - log0log.c Logging / Logging 77,834 Database log - log0recv.c Logging / Recovery 80,701 Recovery - -I've already written about the \log program group, so here's a link to -my previous article: "How Logs work with MySQL and InnoDB": -@url{http://www.devarticles.com/art/1/181/2} - -@strong{\mem (MEMORY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - mem0mem.c Memory / Memory 9,971 The memory management - mem0dbg.c Memory / Debug 21,297 ... the debug code - mem0pool.c Memory / Pool 16,293 ... the lowest level - -There is a long comment at the start of the mem0pool.c program, which -explains what the memory-consumers are, and how InnoDB tries to -satisfy them. The main thing to know is that there are really three -pools: the buffer pool (see the \buf program group), the log pool (see the \log -program group), and the common pool, which is where everything that's -not in the buffer or log pools goes (for example the parsed SQL -statements and the data dictionary cache). - -@strong{\mtr (MINI-TRANSACTION)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - mtr0mtr.c Mini-transaction / 12,433 Mini-transaction buffer - mtr0log.c Mini-transaction / Log 8,180 ... log routines - -The mini-transaction routines are called from most of the other -program groups. I'd describe this as a low-level utility set. - -@strong{\que (QUERY GRAPH)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - que0que.c Query Graph / Query 35,964 Query graph - -The program que0que.c ostensibly is about the execution of stored -procedures which contain commit/rollback statements. I took it that -this has little importance for the average MySQL user. - -@strong{\rem (RECORD MANAGER)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - rem0rec.c Record Manager 14,961 Record Manager - rem0cmp.c Record Manager / 25,263 Comparison services for records - Comparison - -There's an extensive comment near the start of rem0rec.c title -"Physical Record" and it's recommended reading. At some point you'll -ask what are all those bits that surround the data in the rows on a page, -and this is where you'll find the answer. - -@strong{\row (ROW)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - row0row.c Row / Row 16,764 General row routines - row0uins.c Row / Undo Insert 7,199 Fresh insert undo - row0umod.c Row / Undo Modify 17,147 Undo modify of a row - row0undo.c Row / Undo 10,254 Row undo - row0vers.c Row / Version 12,288 Row versions - row0mysql.c Row / MySQL 63,556 Interface [to MySQL] - row0ins.c Row / Insert 42,829 Insert into a table - row0sel.c Row / Select 85,923 Select - row0upd.c Row / Update 44,456 Update of a row - row0purge.c Row / Purge 14,961 Purge obsolete records - -Rows can be selected, inserted, updated/deleted, or purged (a -maintenance activity). These actions have ancillary actions, for -example after insert there can be an index-update test, but it seems -to me that sometimes the ancillary action has no MySQL equivalent (yet) -and so is inoperative. - -Speaking of MySQL, notice that one of the larger programs in the \row -program group is the "interface between Innobase row operations and -MySQL" (row0mysql.c) -- information interchange happens at this level -because rows in InnoDB and in MySQL are analogous, something which -can't be said for pages and other levels. - -@strong{\srv (Server)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - srv0srv.c Server / Server 79,058 Server main program - srv0que.c Server / Query 2,361 Server query execution - srv0start.c Server / Start 34,586 Starts the server - -This is where the server reads the initial configuration files, splits -up the threads, and gets going. There is a long comment deep in the -program (you might miss it at first glance) titled "IMPLEMENTATION OF -THE SERVER MAIN PROGRAM" in which you'll find explanations about -thread priority, and about what the responsibiities are for various -thread types. - -InnoDB has many threads, for example "user threads" (which wait for -client requests and reply to them), "parallel communication threads" -(which take part of a user thread's job if a query process can be -split), "utility threads" (background priority), and a "master thread" -(high priority, usually asleep). - -@strong{\thr (Thread Local Storage)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - thr0loc.c Thread / Local 5,261 The thread local storage - -InnoDB doesn't use the Windows-API thread-local-storage functions, -perhaps because they're not portable enough. - -@strong{\trx (Transaction)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - trx0trx.c Transaction / 37,447 The transaction - trx0purge.c Transaction / Purge 26,782 ... Purge old versions - trx0rec.c Transaction / Record 36,525 ... Undo log record - trx0sys.c Transaction / System 20,671 ... System - trx0rseg.c / Rollback segment 6,214 ... Rollback segment - trx0undo.c Transaction / Undo 46,595 ... Undo log - -InnoDB's transaction management is supposedly "in the style of Oracle" -and that's close to true but can mislead you. -@itemize -@item -First: InnoDB uses rollback segments like Oracle8i does -- but -Oracle9i uses a different name -@item -Second: InnoDB uses multi-versioning like Oracle does -- but I see -nothing that looks like an Oracle ITL being stored in the InnoDB data -pages. -@item -Third: InnoDB and Oracle both have short (back-to-statement-start) -versioning for the READ COMMITTED isolation level and long -(back-to-transaction-start) versioning for higher levels -- but InnoDB -and Oracle have different "default" isolation levels. -@item -Finally: InnoDB's documentation says it has to lock "the gaps before -index keys" to prevent phantoms -- but any Oracle user will tell you that -phantoms are impossible anyway at the SERIALIZABLE isolation level, so -key-locks are unnecessary. -@end itemize - -The main idea, though, is that InnoDB has multi-versioning. So does -Oracle. This is very different from the way that DB2 and SQL Server do -things. - -@strong{\usr (USER)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - usr0sess.c User / Session 27,415 Sessions - -One user can have multiple sessions (the session being all the things -that happen betweeen a connect and disconnect). This is where InnoDB -tracks session IDs, and server/client messaging. It's another of those -items which is usually MySQL's job, though. - -@strong{\data (DATA)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - data0data.c Data / Data 26,002 SQL data field and tuple - data0type.c Data / Type 2,122 Data types - -This is a collection of minor utility routines affecting rows. - -@strong{\dict (DICTIONARY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - dict0dict.c Dictionary / Dictionary 84,667 Data dictionary system - dict0boot.c Dictionary / boot 12,134 ... creation and booting - dict0load.c Dictionary / load 26,546 ... load to memory cache - dict0mem.c Dictionary / memory 8,221 ... memory object creation - -The data dictionary (known in some circles as the catalog) has the -metadata information about objects in the database -- column sizes, -table names, and the like. - -@strong{\eval (EVALUATING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - eval0eval.c Evaluating/Evaluating 15,682 SQL evaluator - eval0proc.c Evaluating/Procedures 5,000 Executes SQL procedures - -The evaluating step is a late part of the process of interpreting an -SQL statement -- parsing has already occurred during \pars (PARSING). - -The ability to execute SQL stored procedures is an InnoDB feature, but -not a MySQL feature, so the eval0proc.c program is unimportant. - -@strong{\ibuf (INSERT BUFFER)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ibuf0ibuf.c Insert Buffer / 69,884 Insert buffer - -The words "Insert Buffer" mean not "buffer used for INSERT" but -"insertion of a buffer into the buffer pool" (see the \buf BUFFER -program group description). The matter is complex due to possibilities -for deadlocks, a problem to which the comments in the ibuf0ibuf.c -program devote considerable attention. - -@strong{\mach (MACHINE FORMAT)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - mach0data.c Machine/Data 2,319 Utilities for converting - -The mach0data.c program has two small routines for reading compressed -ulints (unsigned long integers). - -@strong{\lock (LOCKING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - lock0lock.c Lock / Lock 127,646 The transaction lock system - -If you've used DB2 or SQL Server, you might think that locks have their -own in-memory table, that row locks might need occasional escalation to -table locks, and that there are three lock types: Shared, Update, Exclusive. - -All those things are untrue with InnoDB! Locks are kept in the database -pages. A bunch of row locks can't be rolled together into a single table -lock. And most importantly there's only one lock type. I call this type -"Update" because it has the characteristics of DB2 / SQL Server Update -locks, that is, it blocks other updates but doesn't block reads. -Unfortunately, InnoDB comments refer to them as "x-locks" etc. - -To sum it up: if your background is Oracle you won't find too much -surprising, but if your background is DB2 or SQL Server the locking -concepts and terminology will probably confuse you at first. - -You can find an online article about the differences between -Oracle-style and DB2/SQL-Server-style locks at: -@url{http://dbazine.com/gulutzan6.html} - -@strong{\odbc (ODBC)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - odbc0odbc.c ODBC / ODBC 16,865 ODBC client library - -The odbc0odbc.c program has a small selection of old ODBC-API -functions: SQLAllocEnv, SQLAllocConnect, SQLAllocStmt, SQLConnect, -SQLError, SQLPrepare, SQLBindParameter, SQLExecute. - -@strong{\page (PAGE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - page0page.c Page / Page 44,309 Index page routines - page0cur.c Page / Cursor 30,305 The page cursor - -It's in the page0page.c program that you'll learn as follows: index -pages start with a header, entries in the page are in order, at the -end of the page is a sparse "page directory" (what I would have called -a slot table) which makes binary searches easier. - -Incidentally, the program comments refer to "a page size of 8 kB" -which seems obsolete. In univ.i (a file containing universal -constants) the page size is now #defined as 16KB. - -@strong{\pars (PARSING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - pars0pars.c Parsing/Parsing 49,947 SQL parser - pars0grm.c Parsing/Grammar 62,685 A Bison parser - pars0opt.c Parsing/Optimizer 30,809 Simple SQL Optimizer - pars0sym.c Parsing/Symbol Table 5,541 SQL parser symbol table - lexyy.c ?/Lexer 59,948 Lexical scanner - -The job is to input a string containing an SQL statement and output an -in-memory parse tree. The EVALUATING (subdirectory \eval) programs -will use the tree. - -As is common practice, the Bison and Flex tools were used -- pars0grm.c -is what the Bison parser produced from an original file named pars0grm.y -(not supplied), and lexyy.c is what Flex produced. - -Since InnoDB is a DBMS by itself, it's natural to find SQL parsing in -it. But in the MySQL/InnoDB combination, MySQL handles most of the -parsing. These files are unimportant. - -@strong{\read (READ)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - read0read.c Read / Read 6,244 Cursor read - -The read0read.c program opens a "read view" of a query result, using -some functions in the \trx program group. - -@strong{\sync (SYNCHRONIZATION)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - sync0sync.c Synchronization / 35,918 Mutex, the basic sync primitive - sync0arr.c ... / array 26,461 Wait array used in primitives - sync0ipm.c ... / interprocess 4,027 for interprocess sync - sync0rw.c ... / read-write 22,220 read-write lock for thread sync - -A mutex (Mutual Exclusion) is an object which only one thread/process -can hold at a time. Any modern operating system API has some functions -for mutexes; however, as the comments in the sync0sync.c code indicate, it -can be faster to write one's own low-level mechanism. In fact the old -assembly-language XCHG trick is in here -- this is the only program -that contains any assembly code. -@end example -@* -@* - -This is the end of the section-by-section account of InnoDB -subdirectories. -@*@* - -@strong{A Note About File Naming} @*@* - -There appears to be a naming convention. The first letters of the file -name are the same as the subdirectory name, then there is a '0' -separator, then there is an individual name. For the main program in a -subdirectory, the individual name may be a repeat of the subdirectory -name. For example, there is a file named ha0ha.c (the first two -letters ha mean "it's in in subdirectory ..\ha", the next letter 0 -means "0 separator", the next two letters mean "this is the main ha -program"). This naming convention is not strict, though: for example -the file lexyy.c is in the \pars subdirectory. -@*@* - -@strong{A Note About Copyrights} @*@* - -Most of the files begin with a copyright notice or a creation date, -for example "Created 10/25/1995 Heikki Tuuri". I don't know a great -deal about the history of InnoDB, but found it interesting that most -creation dates were between 1994 and 1998. -@*@* - -@strong{References} @*@* - -Ryan Bannon, Alvin Chin, Faryaaz Kassam and Andrew Roszko @* -"InnoDB Concrete Architecture" @* -@url{http://www.swen.uwaterloo.ca/~mrbannon/cs798/assignment_02/innodb.pdf} - -A student paper. It's an interesting attempt to figure out InnoDB's -architecture using tools, but I didn't end up using it for the specific -purposes of this article. -@*@* - -Peter Gulutzan @* -"How Logs Work With MySQL And InnoDB" @* -@url{http://www.devarticles.com/art/1/181/2} -@*@* - -Heikki Tuuri @* -"InnoDB Engine in MySQL-Max-3.23.54 / MySQL-4.0.9: The Up-to-Date -Reference Manual of InnoDB" @* -@url{http://www.innodb.com/ibman.html} - -This is the natural starting point for all InnoDB information. Mr -Tuuri also appears frequently on MySQL forums. -@*@* - -@summarycontents -@contents - -@bye From 4920a3326fc96be2cfa661232b6fe5f731b22eae Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 16:40:14 +0300 Subject: [PATCH 246/399] Fixed problem with mysql prompt when server disconnect. (Bug 356) Fixed problem with localtime -> gmt where some times resulted in different (but correct) timestamps. Now MySQL should use the smallest possible timestamp value in this case. (Bug 316) client/mysql.cc: Fixed problem with prompt when server disconnect. (Bug 356) client/mysqltest.c: More debug information mysql-test/mysql-test-run.sh: Added support for --timezone in -master.opt mysql-test/t/raid.test: Fixed test if raid is enabled sql/field.cc: New my_gmt_sec() parameters sql/mysql_priv.h: New my_gmt_sec() parameters sql/mysqld.cc: Remove LOCK_timezone. Code cleanup sql/time.cc: Fixed problem with localtime -> gmt where some times resulted in different (but correct) timestamps. Now MySQL should use the smallest possible timestamp value in this case. (Bug 316) --- client/mysql.cc | 19 ++++++--- client/mysqltest.c | 6 ++- mysql-test/mysql-test-run.sh | 12 +++++- mysql-test/r/have_mest_timezone.require | 2 + mysql-test/r/timezone.result | 25 +++++++++++ mysql-test/t/raid.test | 2 + mysql-test/t/timezone-master.opt | 1 + mysql-test/t/timezone.test | 28 +++++++++++++ sql/field.cc | 3 +- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 10 ----- sql/time.cc | 56 +++++++++++++++---------- 12 files changed, 126 insertions(+), 40 deletions(-) create mode 100644 mysql-test/r/have_mest_timezone.require create mode 100644 mysql-test/r/timezone.result create mode 100644 mysql-test/t/timezone-master.opt create mode 100644 mysql-test/t/timezone.test diff --git a/client/mysql.cc b/client/mysql.cc index a237561d83d..9b0e85aa41a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -40,7 +40,7 @@ #include #include -const char *VER= "12.20"; +const char *VER= "12.21"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -2613,14 +2613,18 @@ static const char* construct_prompt() add_int_to_prompt(++prompt_counter); break; case 'v': - processed_prompt.append(mysql_get_server_info(&mysql)); + if (connected) + processed_prompt.append(mysql_get_server_info(&mysql)); + else + processed_prompt.append("not_connected"); break; case 'd': processed_prompt.append(current_db ? current_db : "(none)"); break; case 'h': { - const char *prompt=mysql_get_host_info(&mysql); + const char *prompt; + prompt= connected ? mysql_get_host_info(&mysql) : "not_connected"; if (strstr(prompt, "Localhost")) processed_prompt.append("localhost"); else @@ -2631,8 +2635,13 @@ static const char* construct_prompt() break; } case 'p': - if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || - ! mysql.unix_socket) + if (!connected) + { + processed_prompt.append("not_connected"); + break; + } + if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || ! + mysql.unix_socket) add_int_to_prompt(mysql.port); else { diff --git a/client/mysqltest.c b/client/mysqltest.c index 4bc941e8b56..f6c999b18e4 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -515,8 +515,12 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname) if (!my_stat(eval_file, &stat_info, MYF(MY_WME))) die(NullS); - if (!eval_result && stat_info.st_size != ds->length) + if (!eval_result && (uint) stat_info.st_size != ds->length) + { + DBUG_PRINT("info",("Size differs: result size: %u file size: %u", + ds->length, stat_info.st_size)); DBUG_RETURN(2); + } if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME)))) die(NullS); diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 65f40c5dc73..ab4a5354dae 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -13,7 +13,8 @@ DB=test DBPASSWD= VERBOSE="" USE_MANAGER=0 -TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work +MY_TZ=GMT-3 +TZ=$MY_TZ; export TZ # for UNIX_TIMESTAMP tests to work #++ # Program Definitions @@ -1161,9 +1162,18 @@ run_testcase () if [ -f $master_opt_file ] ; then EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"` + case "$EXTRA_MASTER_OPT" in + --timezone=*) + TZ=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--timezone=;;"` + export TZ + # Note that this must be set to space, not "" for test-reset to work + EXTRA_MASTER_OPT=" " + ;; + esac stop_master echo "CURRENT_TEST: $tname" >> $MASTER_MYERR start_master + TZ=$MY_TZ; export TZ else if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ] then diff --git a/mysql-test/r/have_mest_timezone.require b/mysql-test/r/have_mest_timezone.require new file mode 100644 index 00000000000..2a219f39b7e --- /dev/null +++ b/mysql-test/r/have_mest_timezone.require @@ -0,0 +1,2 @@ +Variable_name Value +timezone MEST diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result new file mode 100644 index 00000000000..b82b39da262 --- /dev/null +++ b/mysql-test/r/timezone.result @@ -0,0 +1,25 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (ts int); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01')); +SELECT ts,from_unixtime(ts) FROM t1; +ts from_unixtime(ts) +1035673200 2002-10-27 01:00:00 +1035680400 2002-10-27 02:00:00 +1035684000 2002-10-27 03:00:00 +1035680400 2002-10-27 02:00:00 +1035673200 2002-10-27 01:00:00 +1035680400 2002-10-27 02:00:00 +1048986000 2003-03-30 03:00:00 +1048986000 2003-03-30 03:00:00 +1048989599 2003-03-30 03:59:59 +1048989601 2003-03-30 04:00:01 +DROP TABLE t1; diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test index 4dbaf84a836..4032993f2da 100644 --- a/mysql-test/t/raid.test +++ b/mysql-test/t/raid.test @@ -1,5 +1,7 @@ -- require r/have_raid.require +disable_query_log; show variables like "have_raid"; +enable_query_log; # # Test of raided tables diff --git a/mysql-test/t/timezone-master.opt b/mysql-test/t/timezone-master.opt new file mode 100644 index 00000000000..0477f941e9d --- /dev/null +++ b/mysql-test/t/timezone-master.opt @@ -0,0 +1 @@ +--timezone=MET diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test new file mode 100644 index 00000000000..14facc0374a --- /dev/null +++ b/mysql-test/t/timezone.test @@ -0,0 +1,28 @@ +# +# Test of timezone handling. This script must be run with TZ=MEST + +-- require r/have_mest_timezone.require +disable_query_log; +show variables like "timezone"; +enable_query_log; + +# Initialization +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + + +CREATE TABLE t1 (ts int); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59')); +INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01')); + +SELECT ts,from_unixtime(ts) FROM t1; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index a2663626723..9babe069300 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2552,6 +2552,7 @@ void Field_timestamp::store(longlong nr) if ((nr=fix_datetime(nr))) { + long not_used; part1=(long) (nr/LL(1000000)); part2=(long) (nr - (longlong) part1*LL(1000000)); l_time.year= (int) (part1/10000L); part1%=10000L; @@ -2560,7 +2561,7 @@ void Field_timestamp::store(longlong nr) l_time.hour= (int) (part2/10000L); part2%=10000L; l_time.minute=(int) part2 / 100; l_time.second=(int) part2 % 100; - timestamp=my_gmt_sec(&l_time); + timestamp=my_gmt_sec(&l_time, ¬_used); } else timestamp=0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2c28fcf03bb..614cb8cadf6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -755,7 +755,7 @@ uint calc_days_in_year(uint year); void get_date_from_daynr(long daynr,uint *year, uint *month, uint *day); void init_time(void); -long my_gmt_sec(TIME *); +long my_gmt_sec(TIME *, long *current_timezone); time_t str_to_timestamp(const char *str,uint length); bool str_to_time(const char *str,uint length,TIME *l_time); longlong str_to_datetime(const char *str,uint length,bool fuzzy_date); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e4f86a1818c..c2ee940af49 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -968,7 +968,6 @@ static void clean_up_mutexes() (void) pthread_mutex_destroy(&LOCK_crypt); (void) pthread_mutex_destroy(&LOCK_bytes_sent); (void) pthread_mutex_destroy(&LOCK_bytes_received); - (void) pthread_mutex_destroy(&LOCK_timezone); (void) pthread_mutex_destroy(&LOCK_user_conn); (void) pthread_mutex_destroy(&LOCK_rpl_status); (void) pthread_mutex_destroy(&LOCK_active_mi); @@ -1998,19 +1997,11 @@ int main(int argc, char **argv) } #endif #ifdef HAVE_TZNAME -#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) { struct tm tm_tmp; localtime_r(&start_time,&tm_tmp); strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]); } -#else - { - struct tm *start_tm; - start_tm=localtime(&start_time); - strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]); - } -#endif #endif if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0) @@ -2067,7 +2058,6 @@ int main(int argc, char **argv) (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); diff --git a/sql/time.cc b/sql/time.cc index cc8cd4fbcf9..321a8ba16e5 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037 /* Currently only my_time_zone is inited */ static long my_time_zone=0; -pthread_mutex_t LOCK_timezone; void init_time(void) { @@ -39,14 +38,14 @@ void init_time(void) seconds= (time_t) time((time_t*) 0); localtime_r(&seconds,&tm_tmp); l_time= &tm_tmp; - my_time_zone=0; + my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */ my_time.year= (uint) l_time->tm_year+1900; my_time.month= (uint) l_time->tm_mon+1; my_time.day= (uint) l_time->tm_mday; my_time.hour= (uint) l_time->tm_hour; my_time.minute= (uint) l_time->tm_min; - my_time.second= (uint) l_time->tm_sec; - VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */ + my_time.second= (uint) l_time->tm_sec; + my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */ } /* @@ -57,26 +56,39 @@ void init_time(void) */ -long my_gmt_sec(TIME *t) +long my_gmt_sec(TIME *t, long *my_timezone) { uint loop; time_t tmp; struct tm *l_time,tm_tmp; - long diff; + long diff, current_timezone; if (t->hour >= 24) { /* Fix for time-loop */ t->day+=t->hour/24; t->hour%=24; } - pthread_mutex_lock(&LOCK_timezone); - tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - - (long) days_at_timestart)*86400L + (long) t->hour*3600L + - (long) (t->minute*60 + t->second)) + (time_t) my_time_zone; + + /* + Calculate the gmt time based on current time and timezone + The -1 on the end is to ensure that if have a date that exists twice + (like 2002-10-27 02:00:0 MET), we will find the initial date. + + By doing -3600 we will have to call localtime_r() several times, but + I couldn't come up with a better way to get a repeatable result :( + + We can't use mktime() as it's buggy on many platforms and not thread safe. + */ + tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - + (long) days_at_timestart)*86400L + (long) t->hour*3600L + + (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - + 3600); + current_timezone= my_time_zone; + localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; for (loop=0; - loop < 3 && + loop < 2 && (t->hour != (uint) l_time->tm_hour || t->minute != (uint) l_time->tm_min); loop++) @@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t) days= -1; diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) + (long) (60*((int) t->minute - (int) l_time->tm_min))); - my_time_zone+=diff; - tmp+=(time_t) diff; + current_timezone+= diff+3600; // Compensate for -3600 above + tmp+= (time_t) diff; localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; } - /* Fix that if we are in the not existing daylight saving time hour - we move the start of the next real hour */ - if (loop == 3 && t->hour != (uint) l_time->tm_hour) + /* + Fix that if we are in the not existing daylight saving time hour + we move the start of the next real hour + */ + if (loop == 2 && t->hour != (uint) l_time->tm_hour) { int days= t->day - l_time->tm_mday; if (days < -1) @@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t) if (diff == 3600) tmp+=3600 - t->minute*60 - t->second; // Move to next hour else if (diff == -3600) - tmp-=t->minute*60 + t->second; // Move to next hour + tmp-=t->minute*60 + t->second; // Move to previous hour } - if ((my_time_zone >=0 ? my_time_zone: -my_time_zone) > 3600L*12) - my_time_zone=0; /* Wrong date */ - pthread_mutex_unlock(&LOCK_timezone); + *my_timezone= current_timezone; return (long) tmp; } /* my_gmt_sec */ @@ -399,6 +411,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) time_t str_to_timestamp(const char *str,uint length) { TIME l_time; + long not_used; + if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) return(0); if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) @@ -406,7 +420,7 @@ time_t str_to_timestamp(const char *str,uint length) current_thd->cuted_fields++; return(0); } - return(my_gmt_sec(&l_time)); + return(my_gmt_sec(&l_time, ¬_used)); } From ef6d3a806085efdc138e6e894a832e4330692e64 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 18:40:37 +0300 Subject: [PATCH 247/399] ORDER BY optimization Fixed new bug when reading field types client/mysql.cc: Fixed output for -T libmysql/libmysql.c: Filled missing fields in new MYSQL_FIELD structure Fixed new bug when reading field types mysql-test/r/order_by.result: Result after new order by optimization sql/opt_range.cc: New ORDER BY optimization sql/opt_range.h: New ORDER BY optimization sql/set_var.cc: Speed optimization sql/sql_select.cc: New ORDER BY optimization This alllows MySQL to change a ref/range index from (a,b) to (a,c) when 'b' was not used to find rows and one did ORDER BY a,c or ORDER BY c --- client/mysql.cc | 5 ++--- libmysql/libmysql.c | 6 +++++- mysql-test/r/order_by.result | 2 +- sql/opt_range.cc | 5 +++-- sql/opt_range.h | 2 +- sql/set_var.cc | 4 ++-- sql/sql_select.cc | 36 ++++++++++++++++++++++++++---------- 7 files changed, 40 insertions(+), 20 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index f421756f0b4..812673d34c2 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1793,9 +1793,8 @@ print_field_types(MYSQL_RES *result) MYSQL_FIELD *field; while ((field = mysql_fetch_field(result))) { - tee_fprintf(PAGER,"%s '%s' %d %d %d %d %d\n", - field->name, - field->table ? "" : field->table, + tee_fprintf(PAGER,"'%s.%s.%s.%s' %d %d %d %d %d\n", + field->catalog, field->db, field->table, field->name, (int) field->type, field->length, field->max_length, field->flags, field->decimals); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 5971fda141b..514de2a87a6 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1207,6 +1207,10 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, field->length= (uint) uint3korr(row->data[2]); field->type= (enum enum_field_types) (uchar) row->data[3][0]; + field->catalog=(char*) ""; + field->db= (char*) ""; + field->catalog_length= 0; + field->db_length= 0; field->org_table_length= field->table_length= lengths[0]; field->name_length= lengths[1]; @@ -2883,7 +2887,7 @@ get_info: mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ - if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 6 : 5))) + if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7 : 5))) DBUG_RETURN(1); if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, (uint) field_count,0, diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 08176aeb2f8..3524b38e659 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -557,7 +557,7 @@ KEY StringField (FieldKey,StringVal(32)) INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3'); EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref FieldKey,LongField,StringField StringField 36 const 3 Using where; Using filesort +1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 36 const 3 Using where SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; FieldKey LongVal StringVal 1 0 2 diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d40f2e22ea2..6c1c49e23fc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -379,8 +379,8 @@ SQL_SELECT::~SQL_SELECT() #undef index // Fix for Unixware 7 QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc) - :dont_free(0),error(0),index(key_nr),max_used_key_length(0),head(table), - it(ranges),range(0) + :dont_free(0),error(0),index(key_nr),max_used_key_length(0), + used_key_parts(0), head(table), it(ranges),range(0) { if (!no_alloc) { @@ -2326,6 +2326,7 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key, flag); set_if_bigger(quick->max_used_key_length,range->min_length); set_if_bigger(quick->max_used_key_length,range->max_length); + set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1); if (!range) // Not enough memory return 1; quick->ranges.push_back(range); diff --git a/sql/opt_range.h b/sql/opt_range.h index bc56fb99b4b..00736bfc22f 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -70,7 +70,7 @@ class QUICK_SELECT { public: bool next,dont_free; int error; - uint index,max_used_key_length; + uint index, max_used_key_length, used_key_parts; TABLE *head; handler *file; byte *record; diff --git a/sql/set_var.cc b/sql/set_var.cc index fe6ee46068c..3145504951d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1697,7 +1697,7 @@ sys_var *find_sys_var(const char *str, uint length) int sql_set_variables(THD *thd, List *var_list) { int error= 0; - List_iterator it(*var_list); + List_iterator_fast it(*var_list); set_var_base *var; while ((var=it++)) @@ -1813,5 +1813,5 @@ int set_var_password::update(THD *thd) #ifdef __GNUC__ template class List; -template class List_iterator; +template class List_iterator_fast; #endif diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 832058ff935..4167da5802a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6275,14 +6275,14 @@ is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part, */ static uint -test_if_subkey(ORDER *order, TABLE *table, uint ref, key_map usable_keys) +test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, + key_map usable_keys) { uint nr; uint min_length= (uint) ~0; uint best= MAX_KEY; uint not_used; KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part; - uint ref_key_parts= table->key_info[ref].key_parts; KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts; for (nr= 0; usable_keys; usable_keys>>= 1, nr++) @@ -6317,10 +6317,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, bool no_changes) { int ref_key; + uint ref_key_parts; TABLE *table=tab->table; SQL_SELECT *select=tab->select; key_map usable_keys; DBUG_ENTER("test_if_skip_sort_order"); + LINT_INIT(ref_key_parts); /* Check which keys can be used to resolve ORDER BY */ usable_keys= ~(key_map) 0; @@ -6336,9 +6338,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ref_key= -1; if (tab->ref.key >= 0) // Constant range in WHERE - ref_key=tab->ref.key; + { + ref_key= tab->ref.key; + ref_key_parts= tab->ref.key_parts; + } else if (select && select->quick) // Range found by opt_range - ref_key=select->quick->index; + { + ref_key= select->quick->index; + ref_key_parts= select->quick->used_key_parts; + } if (ref_key >= 0) { @@ -6352,20 +6360,28 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, /* We come here when ref_key is not among usable_keys */ - uint a; - if ((a= test_if_subkey(order, table, ref_key, usable_keys)) < MAX_KEY) + uint new_ref_key; + /* + If using index only read, only consider other possible index only + keys + */ + if (table->used_keys & (((key_map) 1 << ref_key))) + usable_keys|= table->used_keys; + if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts, + usable_keys)) < MAX_KEY) { + /* Found key that can be used to retrieve data in sorted order */ if (tab->ref.key >= 0) { - tab->ref.key= a; - table->file->index_init(a); + tab->ref.key= new_ref_key; + table->file->index_init(new_ref_key); } else { - select->quick->index= a; + select->quick->index= new_ref_key; select->quick->init(); } - ref_key= a; + ref_key= new_ref_key; } } /* Check if we get the rows in requested sorted order by using the key */ From c1607401de71e400b5d2c1e1e1351edbe428cd4e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 18:16:50 +0200 Subject: [PATCH 248/399] Removed bad mutex locking --- sql/slave.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index b620603dc63..b655b17c258 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1320,11 +1320,7 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) while (rli->log_space_limit < rli->log_space_total && !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) - { pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); - /* Re-acquire the mutex as pthread_cond_wait released it */ - pthread_mutex_lock(&rli->log_space_lock); - } thd->proc_info = save_proc_info; pthread_mutex_unlock(&rli->log_space_lock); DBUG_RETURN(slave_killed); From 8e20fc57ed1ee05dbb47114186e99ecfec509422 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 18:34:03 +0200 Subject: [PATCH 249/399] - removed internals.texi (has been moved to the "mysqldoc" BK tree) BitKeeper/deleted/.del-internals.texi~62b6f580a41c2a43: Delete: Docs/internals.texi --- Docs/internals.texi | 694 -------------------------------------------- 1 file changed, 694 deletions(-) delete mode 100644 Docs/internals.texi diff --git a/Docs/internals.texi b/Docs/internals.texi deleted file mode 100644 index 2195b42d9a0..00000000000 --- a/Docs/internals.texi +++ /dev/null @@ -1,694 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c Copyright 1998 TcX AB, Detron HB and Monty Program KB -@c -@c %**start of header -@setfilename internals.info -@c We want the types in the same index -@c @synindex tp fn cp -@synindex cp fn -@iftex -@c Well this is normal in Europe. Maybe this should go into the include.texi? -@afourpaper -@end iftex -@c Get version and other info -@include include.texi -@ifclear tex-debug -@c This removes the black squares in the right margin -@finalout -@end ifclear -@c Set background for HTML -@set _body_tags BGCOLOR=#FFFFFF TEXT=#000000 LINK=#101090 VLINK=#7030B0 -@settitle @strong{MySQL} internals Manual for version @value{mysql_version}. -@setchapternewpage off -@paragraphindent 0 -@c %**end of header - -@ifinfo -@format -START-INFO-DIR-ENTRY -* mysql-internals: (mysql-internals). @strong{MySQL} internals. -END-INFO-DIR-ENTRY -@end format -@end ifinfo - -@titlepage -@sp 10 -@center @titlefont{@strong{MySQL} Internals Manual} -@sp 10 -@center Copyright @copyright{} 1998 TcX AB, Detron HB and Monty Program KB -@end titlepage - -@node Top, Introduction, (dir), (dir) - -@ifinfo -This is a manual about @strong{MySQL} internals. -@end ifinfo - -@menu -@end menu - -@node caching,,, -@chapter How MySQL handles caching - -@strong{MySQL} has the following caches: -(Note that the some of the filename have a wrong spelling of cache. :) - -@itemize @bullet - -@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 GROUP BY or DISTINCT caches all found -rows in a HEAP table (this is a very quick in-memory table with hash index) - -@item Join row cache. -For every full join in a 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 SELECT query can use many -join caches in the worst case. -@end itemize - -@node flush tables,,, -@chapter How MySQL handles flush tables - -@itemize @bullet - -@item -Flush tables is handled in @code{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 refresh_version. If not it will close it and broadcast -a signal on 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 -@code{sql/lock.cc::mysql_lock_tables()} and -@code{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,,, -@chapter How MySQL does sorting (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 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,,, -@chapter Coding guidelines - -@itemize @bullet - -@item -We are using @uref{http://www.bitkeeper.com/, BitKeeper} for source management. - -@item -You should use the @strong{MySQL} 3.23 or 4.0 source for all developments. - -@item -If you have any questions about the @strong{MySQL} source, you can post these -to @email{developers@@mysql.com} and we will answer them. -Note that we will shortly change the name of this list to -@email{internals@@mysql.com}, to more accurately reflect what should be -posted to this list. - -@item -Try to write code in a lot of black boxes that can be reused or at -least have a clean interface. - -@item -Reuse code; There is already a lot of algorithms in MySQL for list handling, -queues, dynamic and hashed arrays, sorting, etc. that can be reused. - -@item -Try to always write optimized code, so that you don't have to -go back and rewrite it a couple of months later. It's better to -spend 3 times as much time designing and writing an optimal function than -having to do it all over again later on. - -@item -Avoid CPU wasteful code, even where it does not matter, so that -you will not develop sloppy coding habits. - -@item -If you can write it in fewer lines, do it (as long as the code will not -be slower or much harder to read). - -@item -Don't use two commands on the same line. - -@item -Do not check the same pointer for @code{NULL} more than once. - -@item -Use long function and variable names in English; This makes your code -easier to read. Use the 'varible_name' style instead of 'VariableName'. - -@item -Think assembly - make it easier for the compiler to optimize your code. - -@item -Comment your code when you do something that someone else may think -is not ''trivial''. - -@item -Use the @code{my_*} functions like @code{my_read()}/@code{my_write()}/ -@code{my_malloc()} that you can find in the @code{mysys} library instead -of the direct system calls; This will make your code easier to debug and -more portable. - -@item -Use @code{libstring} functions instead of standard libc string functions -whenever possible. - -@item -Avoid using @code{malloc()} (its REAL slow); For memory allocations -that only need to live for the lifetime of one thread, one should use -@code{sql_alloc()} instead. - -@item -Before making big design decisions, please first post a summary of -what you want to do, why you want to do it, and how you plan to do -it. This way we can easily provide you with feedback and also -easily discuss it thoroughly if some other developer thinks there is better -way to do the same thing! - -@item -Use my_var as opposed to myVar or MyVar (@samp{_} rather than dancing SHIFT -to seperate words in identifiers). - -@item -Class names start with a capital letter. - -@item -Structure types are @code{typedef}'ed to an all-caps identifier. - -@item -Any @code{#define}'s are in all-caps. - -@item -Matching @samp{@{} are in the same column. - -@item -Put the @samp{@{} after a 'switch' on the same line - -@example -switch (arg) { -@end example - -Because this gives better overall indentation for the switch statement. - -@item -In all other cases, @{ and @} should be on their own line, except -if there is nothing inside @{ @}. - -@item -Have a space after 'if' - -@item -Put a space after ',' for function arguments - -@item -Functions return 0 on success, and non-zero on error, so you can do: - -@example -if(a() || b() || c()) { error("something went wrong"); } -@end example - -@item -Using @code{goto} is okay if not abused. - -@item -Avoid default variable initalizations, use @code{LINT_INIT()} if the -compiler complains after making sure that there is really no way -the variable can be used uninitialized. - -@item -Do not instantiate a class if you do not have to. - -@item -Use pointers rather than array indexing when operating on strings. - -@end itemize - -Suggested mode in emacs: - -@example -(load "cc-mode") -(setq c-mode-common-hook '(lambda () - (turn-on-font-lock) - (setq comment-column 48))) -(setq c-style-alist - (cons - '("MY" - (c-basic-offset . 2) - (c-comment-only-line-offset . 0) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . 0) - (substatement-open . 0) - (label . -) - (statement-cont . +) - (arglist-intro . c-lineup-arglist-intro-after-paren) - (arglist-close . c-lineup-arglist) - )) - ) - c-style-alist)) -(c-set-style "MY") -(setq c-default-style "MY") -@end example - -@node mysys functions,,, -@chapter mysys functions - -Functions i mysys: (For flags se my_sys.h) - - int my_copy _A((const char *from,const char *to,myf MyFlags)); - - Copy file - - int my_delete _A((const char *name,myf MyFlags)); - - Delete file - - int my_getwd _A((string buf,uint size,myf MyFlags)); - int my_setwd _A((const char *dir,myf MyFlags)); - - Get and set working directory - - string my_tempnam _A((const char *pfx,myf MyFlags)); - - Make a uniq temp file name by using dir and adding something after - pfx to make name uniq. Name is made by adding a uniq 6 length-string - and TMP_EXT after pfx. - Returns pointer to malloced area for filename. Should be freed by - free(). - - File my_open _A((const char *FileName,int Flags,myf MyFlags)); - File my_create _A((const char *FileName,int CreateFlags, - int AccsesFlags, myf MyFlags)); - int my_close _A((File Filedes,myf MyFlags)); - uint my_read _A((File Filedes,byte *Buffer,uint Count,myf MyFlags)); - uint my_write _A((File Filedes,const byte *Buffer,uint Count, - myf MyFlags)); - ulong my_seek _A((File fd,ulong pos,int whence,myf MyFlags)); - ulong my_tell _A((File fd,myf MyFlags)); - - Use instead of open,open-with-create-flag, close read and write - to get automatic error-messages (flag: MYF_WME) and only have - to test for != 0 if error (flag: MY_NABP). - - int my_rename _A((const char *from,const char *to,myf MyFlags)); - - Rename file - - FILE *my_fopen _A((const char *FileName,int Flags,myf MyFlags)); - FILE *my_fdopen _A((File Filedes,int Flags,myf MyFlags)); - int my_fclose _A((FILE *fd,myf MyFlags)); - uint my_fread _A((FILE *stream,byte *Buffer,uint Count,myf MyFlags)); - uint my_fwrite _A((FILE *stream,const byte *Buffer,uint Count, - myf MyFlags)); - ulong my_fseek _A((FILE *stream,ulong pos,int whence,myf MyFlags)); - ulong my_ftell _A((FILE *stream,myf MyFlags)); - - Same read-interface for streams as for files - - gptr _mymalloc _A((uint uSize,const char *sFile, - uint uLine, myf MyFlag)); - gptr _myrealloc _A((string pPtr,uint uSize,const char *sFile, - uint uLine, myf MyFlag)); - void _myfree _A((gptr pPtr,const char *sFile,uint uLine)); - int _sanity _A((const char *sFile,unsigned int uLine)); - gptr _myget_copy_of_memory _A((const byte *from,uint length, - const char *sFile, uint uLine, - myf MyFlag)); - - malloc(size,myflag) is mapped to this functions if not compiled - with -DSAFEMALLOC - - void TERMINATE _A((void)); - - Writes malloc-info on stdout if compiled with -DSAFEMALLOC. - - int my_chsize _A((File fd,ulong newlength,myf MyFlags)); - - Change size of file - - void my_error _D((int nr,myf MyFlags, ...)); - - Writes message using error number (se mysys/errors.h) on - stdout or curses if MYSYS_PROGRAM_USES_CURSES() is called. - - void my_message _A((const char *str,myf MyFlags)); - - Writes message-string on - stdout or curses if MYSYS_PROGRAM_USES_CURSES() is called. - - void my_init _A((void )); - - Start each program (in main) with this. - void my_end _A((int infoflag)); - - Gives info about program. - - If infoflag & MY_CHECK_ERROR prints if some files are left open - - If infoflag & MY_GIVE_INFO prints timing info and malloc info - about prog. - - int my_redel _A((const char *from, const char *to, int MyFlags)); - - Delete from before rename of to to from. Copyes state from old - file to new file. If MY_COPY_TIME is set sets old time. - - int my_copystat _A((const char *from, const char *to, int MyFlags)); - - Copye state from old file to new file. - If MY_COPY_TIME is set sets copy also time. - - string my_filename _A((File fd)); - - Give filename of open file. - - int dirname _A((string to,const char *name)); - - Copy name of directory from filename. - - int test_if_hard_path _A((const char *dir_name)); - - Test if dirname is a hard path (Starts from root) - - void convert_dirname _A((string name)); - - Convert dirname acording to system. - - In MSDOS changes all caracters to capitals and changes '/' to - '\' - string fn_ext _A((const char *name)); - - Returns pointer to extension in filename - string fn_format _A((string to,const char *name,const char *dsk, - const char *form,int flag)); - format a filename with replace of library and extension and - converts between different systems. - params to and name may be identicall - function dosn't change name if name != to - Flag may be: 1 force replace filnames library with 'dsk' - 2 force replace extension with 'form' */ - 4 force Unpack filename (replace ~ with home) - 8 Pack filename as short as possibly for output to - user. - All open requests should allways use at least: - "open(fn_format(temp_buffe,name,"","",4),...)" to unpack home and - convert filename to system-form. - - string fn_same _A((string toname,const char *name,int flag)); - - Copys directory and extension from name to toname if neaded. - copy can be forced by same flags that in fn_format. - - int wild_compare _A((const char *str,const char *wildstr)); - - Compare if str matches wildstr. Wildstr can contain "*" and "?" - as match-characters. - Returns 0 if match. - - void get_date _A((string to,int timeflag)); - - Get current date in a form ready for printing. - - void soundex _A((string out_pntr, string in_pntr)) - - Makes in_pntr to a 5 chars long string. All words that sounds - alike have the same string. - - int init_key_cache _A((ulong use_mem,ulong leave_this_much_mem)); - - Use cacheing of keys in MISAM, PISAM, and ISAM. - KEY_CACHE_SIZE is a good size. - - Remember to lock databases for optimal cacheing - - void end_key_cache _A((void)); - - End key-cacheing. - -@node protocol,,, -@chapter MySQL client/server protocol - -Raw packet without compression -============================== -------------------------------------------------- -| Packet Length | Packet no | Data | -| 3 Bytes | 1 Byte | n Bytes | -------------------------------------------------- - -3 Byte packet length - The length is calculated with int3store - See include/global.h for details. - The max packetsize can be 16 MB. -1 Byte packet no - -If no compression is used the first 4 bytes of each paket -is the header of the paket. -The packet number is incremented for each sent packet. The first -packet starts with 0 - -n Byte data - -The packet length can be recalculated with: -length = byte1 + (256 * byte2) + (256 * 256 * byte3) - -Raw packet with compression -=========================== ------------------------------------------------------ -| Packet Length | Packet no | Uncomp. Packet Length | -| 3 Bytes | 1 Byte | 3 Bytes | ------------------------------------------------------ - -3 Byte packet length - The length is calculated with int3store - See include/global.h for details. - The max packetsize can be 16 MB. -1 Byte packet no -3 Byte uncompressed packet length - -If compression is used the first 7 bytes of each paket -is the header of the paket. - -Basic packets -============== -OK-packet - For details see sql/net_pkg.cc - function send_ok - ------------------------------------------------- - | Header | No of Rows | Affected Rows | - | | 1 Byte | 1-8 Byte | - ------------------------------------------------- - | ID (last_insert_id) | Status | Length | - | 1-8 Byte | 2 Byte | 1-8 Byte | - ------------------------------------------------- - | Messagetext | - | n Byte | - ------------------------------------------------- - - Header - 1 byte number of rows ? (always 0 ?) - 1-8 bytes affected rows - 1-8 byte id (last_insert_id) - 2 byte Status (usually 0) - If the OK-packege includes a message: - 1-8 bytes length of message - n bytes messagetext - -Error-packet - ------------------------------------------------- - | Header | Statuscode | Error no | - | | 1 Byte | 2 Byte | - ------------------------------------------------- - | Messagetext | 0x00 | - | n Byte | 1 Byte | - ------------------------------------------------- - - Header - 1 byte status code (0xFF = ERROR) - 2 byte error number (is only sent to new 3.23 clients. - n byte errortext - 1 byte 0x00 - - - -The communication -================= - -> Packet from server to client -< Paket from client tor server - - Login - ------ - > 1. packet - Header - 1 byte protocolversion - n byte serverversion - 1 byte 0x00 - 4 byte threadnumber - 8 byte crypt seed - 1 byte 0x00 - 2 byte CLIENT_xxx options (see include/mysql_com.h - that is supported by the server - 1 byte number of current server charset - 2 byte server status variables (SERVER_STATUS_xxx flags) - 13 byte 0x00 (not used yet). - - < 2. packet - Header - 2 byte CLIENT_xxx options - 3 byte max_allowed_packet for the client - n byte username - 1 byte 0x00 - 8 byte crypted password - 1 byte 0x00 - n byte databasename - 1 byte 0x00 - - > 3. packet - OK-packet - - - Command - -------- - < 1. packet - Header - 1 byte command type (e.g.0x03 = query) - n byte query - - Result set (after command) - -------------------------- - > 2. packet - Header - 1-8 byte field_count (packed with net_store_length()) - - If field_count == 0 (command): - 1-8 byte affected rows - 1-8 byte insert id - 2 bytes server_status (SERVER_STATUS_xx) - - If field_count == NULL_LENGTH (251) - LOAD DATA LOCAL INFILE - - If field_count > 0 Result Set: - - > n packets - Header Info - Column description: 5 data object /column - (See code in unpack_fields()) - - Columninfo for each column: - 1 data block table_name - 1 byte length of block - n byte data - 1 data block field_name - 1 byte length of block... - n byte data - 1 data block display length of field - 1 byte length of block - 3 bytes display length of filed - 1 data block type field of type (enum_field_types) - 1 byte length of block - 1 bytexs field of type - 1 data block flags - 1 byte length of block - 2 byte flags for the columns (NOT_NULL_FLAG, ZEROFILL_FLAG....) - 1 byte decimals - - if table definition: - 1 data block default value - - Actual result (one packet per row): - 4 byte header - 1-8 byte length of data - n data - - -Fieldtype Codes: -================ - - display_length |enum_field_type |flags - ---------------------------------------------------- -Blob 03 FF FF 00 |01 FC |03 90 00 00 -Mediumblob 03 FF FF FF |01 FC |03 90 00 00 -Tinyblob 03 FF 00 00 |01 FC |03 90 00 00 -Text 03 FF FF 00 |01 FC |03 10 00 00 -Mediumtext 03 FF FF FF |01 FC |03 10 00 00 -Tinytext 03 FF 00 00 |01 FC |03 10 00 00 -Integer 03 0B 00 00 |01 03 |03 03 42 00 -Mediumint 03 09 00 00 |01 09 |03 00 00 00 -Smallint 03 06 00 00 |01 02 |03 00 00 00 -Tinyint 03 04 00 00 |01 01 |03 00 00 00 -Varchar 03 XX 00 00 |01 FD |03 00 00 00 -Enum 03 05 00 00 |01 FE |03 00 01 00 -Datetime 03 13 00 00 |01 0C |03 00 00 00 -Timestamp 03 0E 00 00 |01 07 |03 61 04 00 -Time 03 08 00 00 |01 0B |03 00 00 00 -Date 03 0A 00 00 |01 0A |03 00 00 00 - - -@c The Index was empty, and ugly, so I removed it. (jcole, Sep 7, 2000) - -@c @node Index -@c @unnumbered Index - -@c @printindex fn - -@summarycontents -@contents - -@bye From d272a9e4d623775e6963e40b01f0515319e2efa6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 18:47:50 +0200 Subject: [PATCH 250/399] - removed internals.texi (has been moved to mysqldoc BK tree) BitKeeper/deleted/.del-internals.texi~62b6f580a41c2a43: Delete: Docs/internals.texi Docs/Makefile.am: - removed all traces of internals.texi --- Docs/Makefile.am | 47 - Docs/internals.texi | 5707 ------------------------------------------- 2 files changed, 5754 deletions(-) delete mode 100644 Docs/internals.texi diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 00eb936c408..f3df055a7dd 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -157,53 +157,6 @@ manual_letter.de.ps: manual.de.texi include.texi touch $@ -# -# Internals Manual -# - -# GNU Info -internals.info: internals.texi include.texi - cd $(srcdir) && $(MAKEINFO) --no-split -I $(srcdir) $< - -# Plain Text -internals.txt: internals.texi include.texi - cd $(srcdir) && \ - $(MAKEINFO) -I $(srcdir) --no-headers --no-split --output $@ $< - -# HTML, all in one file -internals.html: internals.texi include.texi $(srcdir)/Support/texi2html - cd $(srcdir) && @PERL@ $(srcdir)/Support/texi2html $(TEXI2HTML_FLAGS) $< -internals_toc.html: internals.html - -# PDF, Portable Document Format -internals.pdf: internals.texi - sed -e 's|@image{[^}]*} *||g' <$< >internals-tmp.texi - pdftex --interaction=nonstopmode internals-tmp.texi - texindex internals-tmp.?? - pdftex --interaction=nonstopmode internals-tmp.texi - texindex internals-tmp.?? - pdftex --interaction=nonstopmode internals-tmp.texi - mv internals-tmp.pdf $@ - rm -f internals-tmp.* - touch $@ - -# Postscript, A4 Paper -internals_a4.ps: internals.texi include.texi - TEXINPUTS=$(srcdir):$$TEXINPUTS \ - MAKEINFO='$(MAKEINFO) -I $(srcdir)' \ - $(TEXI2DVI) --batch --texinfo --quiet '@afourpaper' $< - $(DVIPS) -t a4 internals.dvi -o $@ - touch $@ - -# Postscript, US Letter Paper -internals_letter.ps: internals.texi include.texi - TEXINPUTS=$(srcdir):$$TEXINPUTS \ - MAKEINFO='$(MAKEINFO) -I $(srcdir)' \ - $(TEXI2DVI) --batch $< - $(DVIPS) -t letter internals.dvi -o $@ - touch $@ - - # # Miscellaneous # diff --git a/Docs/internals.texi b/Docs/internals.texi deleted file mode 100644 index a54f5098e5d..00000000000 --- a/Docs/internals.texi +++ /dev/null @@ -1,5707 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c Copyright 2002 MySQL AB -@c -@c %**start of header -@setfilename internals.info - -@c We want the types in the same index -@synindex cp fn - -@iftex -@afourpaper -@end iftex - -@c Get version and other info -@include include.texi - -@ifclear tex-debug -@c This removes the black squares in the right margin -@finalout -@end ifclear - -@c Set background for HTML -@set _body_tags BGCOLOR=#FFFFFF TEXT=#000000 LINK=#101090 VLINK=#7030B0 -@settitle @strong{MySQL} Internals Manual for version @value{mysql_version}. -@setchapternewpage odd -@paragraphindent 0 - -@c %**end of header - -@ifinfo -@format -START-INFO-DIR-ENTRY -* mysql-internals: (mysql-internals). @strong{MySQL} internals. -END-INFO-DIR-ENTRY -@end format -@end ifinfo - -@titlepage -@sp 10 -@center @titlefont{@strong{MySQL} Internals Manual} -@sp 10 -@center Copyright @copyright{} 1998-2002 MySQL AB -@page -@end titlepage - -@node Top, coding guidelines, (dir), (dir) - -@ifinfo -This is a manual about @strong{MySQL} internals. -@end ifinfo - -@menu -* 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 -* Fulltext Search:: Fulltext Search in MySQL -* MyISAM Record Structure:: MyISAM Record Structure -* InnoDB Record Structure:: InnoDB Record Structure -* InnoDB Page Structure:: InnoDB Page Structure -* Files in MySQL Sources:: Annotated List Of Files in the MySQL Source Code Distribution -* Files in InnoDB Sources:: Annotated List Of Files in the InnoDB Source Code Distribution -@end menu - - -@node coding guidelines, caching, Top, Top -@chapter Coding Guidelines - -@itemize @bullet - -@item -We use @uref{http://www.bitkeeper.com/, BitKeeper} for source management. - -@item -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{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 -least a clean, easy to change interface. - -@item -Reuse code; There is already a lot of algorithms in MySQL for list handling, -queues, dynamic and hashed arrays, sorting, etc. that can be reused. - -@item -Use the @code{my_*} functions like @code{my_read()}/@code{my_write()}/ -@code{my_malloc()} that you can find in the @code{mysys} library instead -of the direct system calls; This will make your code easier to debug and -more portable. - -@item -Try to always write optimized code, so that you don't have to -go back and rewrite it a couple of months later. It's better to -spend 3 times as much time designing and writing an optimal function than -having to do it all over again later on. - -@item -Avoid CPU wasteful code, even where it does not matter, so that -you will not develop sloppy coding habits. - -@item -If you can write it in fewer lines, do it (as long as the code will not -be slower or much harder to read). - -@item -Don't use two commands on the same line. - -@item -Do not check the same pointer for @code{NULL} more than once. - -@item -Use long function and variable names in English. This makes your code -easier to read. - -@item -Use @code{my_var} as opposed to @code{myVar} or @code{MyVar} (@samp{_} -rather than dancing SHIFT to seperate words in identifiers). - -@item -Think assembly - make it easier for the compiler to optimize your code. - -@item -Comment your code when you do something that someone else may think -is not ``trivial''. - -@item -Use @code{libstring} functions (in the @file{strings} directory) -instead of standard @code{libc} string functions whenever possible. - -@item -Avoid using @code{malloc()} (its REAL slow); For memory allocations -that only need to live for the lifetime of one thread, one should use -@code{sql_alloc()} instead. - -@item -Before making big design decisions, please first post a summary of -what you want to do, why you want to do it, and how you plan to do -it. This way we can easily provide you with feedback and also -easily discuss it thoroughly if some other developer thinks there is better -way to do the same thing! - -@item -Class names start with a capital letter. - -@item -Structure types are @code{typedef}'ed to an all-caps identifier. - -@item -Any @code{#define}'s are in all-caps. - -@item -Matching @samp{@{} are in the same column. - -@item -Put the @samp{@{} after a @code{switch} on the same line, as this gives -better overall indentation for the switch statement: - -@example -switch (arg) @{ -@end example - -@item -In all other cases, @samp{@{} and @samp{@}} should be on their own line, except -if there is nothing inside @samp{@{} and @samp{@}}. - -@item -Have a space after @code{if} - -@item -Put a space after @samp{,} for function arguments - -@item -Functions return @samp{0} on success, and non-zero on error, so you can do: - -@example -if(a() || b() || c()) @{ error("something went wrong"); @} -@end example - -@item -Using @code{goto} is okay if not abused. - -@item -Avoid default variable initalizations, use @code{LINT_INIT()} if the -compiler complains after making sure that there is really no way -the variable can be used uninitialized. - -@item -Do not instantiate a class if you do not have to. - -@item -Use pointers rather than array indexing when operating on strings. - -@end itemize - -Suggested mode in emacs: - -@example -(load "cc-mode") -(setq c-mode-common-hook '(lambda () - (turn-on-font-lock) - (setq comment-column 48))) -(setq c-style-alist - (cons - '("MY" - (c-basic-offset . 2) - (c-comment-only-line-offset . 0) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . 0) - (substatement-open . 0) - (label . -) - (statement-cont . +) - (arglist-intro . c-lineup-arglist-intro-after-paren) - (arglist-close . c-lineup-arglist) - )) - ) - c-style-alist)) -(c-set-style "MY") -(setq c-default-style "MY") -@end example - -@node caching, join_buffer_size, coding guidelines, 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, 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}) - -@table @code -@item int my_copy _A((const char *from, const char *to, myf MyFlags)); -Copy file from @code{from} to @code{to}. - -@item int my_delete _A((const char *name, myf MyFlags)); -Delete file @code{name}. - -@item int my_getwd _A((string buf, uint size, myf MyFlags)); -@item int my_setwd _A((const char *dir, myf MyFlags)); -Get and set working directory. - -@item string my_tempnam _A((const char *pfx, myf MyFlags)); -Make a unique temporary file name by using dir and adding something after -@code{pfx} to make name unique. The file name is made by adding a unique -six character string and @code{TMP_EXT} after @code{pfx}. -Returns pointer to @code{malloc()}'ed area for filename. Should be freed by -@code{free()}. - -@item File my_open _A((const char *FileName,int Flags,myf MyFlags)); -@item File my_create _A((const char *FileName, int CreateFlags, int AccsesFlags, myf MyFlags)); -@item int my_close _A((File Filedes, myf MyFlags)); -@item uint my_read _A((File Filedes, byte *Buffer, uint Count, myf MyFlags)); -@item uint my_write _A((File Filedes, const byte *Buffer, uint Count, myf MyFlags)); -@item ulong my_seek _A((File fd,ulong pos,int whence,myf MyFlags)); -@item ulong my_tell _A((File fd,myf MyFlags)); -Use instead of open, open-with-create-flag, close, read, and write -to get automatic error messages (flag @code{MYF_WME}) and only have -to test for != 0 if error (flag @code{MY_NABP}). - -@item int my_rename _A((const char *from, const char *to, myf MyFlags)); -Rename file from @code{from} to @code{to}. - -@item FILE *my_fopen _A((const char *FileName,int Flags,myf MyFlags)); -@item FILE *my_fdopen _A((File Filedes,int Flags,myf MyFlags)); -@item int my_fclose _A((FILE *fd,myf MyFlags)); -@item uint my_fread _A((FILE *stream,byte *Buffer,uint Count,myf MyFlags)); -@item uint my_fwrite _A((FILE *stream,const byte *Buffer,uint Count, myf MyFlags)); -@item ulong my_fseek _A((FILE *stream,ulong pos,int whence,myf MyFlags)); -@item ulong my_ftell _A((FILE *stream,myf MyFlags)); -Same read-interface for streams as for files. - -@item gptr _mymalloc _A((uint uSize,const char *sFile,uint uLine, myf MyFlag)); -@item gptr _myrealloc _A((string pPtr,uint uSize,const char *sFile,uint uLine, myf MyFlag)); -@item void _myfree _A((gptr pPtr,const char *sFile,uint uLine)); -@item int _sanity _A((const char *sFile,unsigned int uLine)); -@item gptr _myget_copy_of_memory _A((const byte *from,uint length,const char *sFile, uint uLine,myf MyFlag)); -@code{malloc(size,myflag)} is mapped to these functions if not compiled -with @code{-DSAFEMALLOC}. - -@item void TERMINATE _A((void)); -Writes @code{malloc()} info on @code{stdout} if compiled with -@code{-DSAFEMALLOC}. - -@item int my_chsize _A((File fd, ulong newlength, myf MyFlags)); -Change size of file @code{fd} to @code{newlength}. - -@item void my_error _D((int nr, myf MyFlags, ...)); -Writes message using error number (see @file{mysys/errors.h}) on @code{stdout}, -or using curses, if @code{MYSYS_PROGRAM_USES_CURSES()} has been called. - -@item void my_message _A((const char *str, myf MyFlags)); -Writes @code{str} on @code{stdout}, or using curses, if -@code{MYSYS_PROGRAM_USES_CURSES()} has been called. - -@item void my_init _A((void )); -Start each program (in @code{main()}) with this. - -@item void my_end _A((int infoflag)); -Gives info about program. -If @code{infoflag & MY_CHECK_ERROR}, prints if some files are left open. -If @code{infoflag & MY_GIVE_INFO}, prints timing info and malloc info -about program. - -@item int my_redel _A((const char *from, const char *to, int MyFlags)); -Delete @code{from} before rename of @code{to} to @code{from}. Copies state -from old file to new file. If @code{MY_COPY_TIME} is set, sets old time. - -@item int my_copystat _A((const char *from, const char *to, int MyFlags)); -Copy state from old file to new file. If @code{MY_COPY_TIME} is set, -sets old time. - -@item string my_filename _A((File fd)); -Returns filename of open file. - -@item int dirname _A((string to, const char *name)); -Copy name of directory from filename. - -@item int test_if_hard_path _A((const char *dir_name)); -Test if @code{dir_name} is a hard path (starts from root). - -@item void convert_dirname _A((string name)); -Convert dirname according to system. -In MSDOS, changes all characters to capitals and changes @samp{/} to @samp{\}. - -@item string fn_ext _A((const char *name)); -Returns pointer to extension in filename. - -@item string fn_format _A((string to,const char *name,const char *dsk,const char *form,int flag)); - format a filename with replace of library and extension and - converts between different systems. - params to and name may be identicall - function dosn't change name if name != to - Flag may be: 1 force replace filnames library with 'dsk' - 2 force replace extension with 'form' */ - 4 force Unpack filename (replace ~ with home) - 8 Pack filename as short as possibly for output to - user. - All open requests should allways use at least: - "open(fn_format(temp_buffe,name,"","",4),...)" to unpack home and - convert filename to system-form. - -@item string fn_same _A((string toname, const char *name, int flag)); -Copys directory and extension from @code{name} to @code{toname} if neaded. -Copying can be forced by same flags used in @code{fn_format()}. - -@item int wild_compare _A((const char *str, const char *wildstr)); -Compare if @code{str} matches @code{wildstr}. @code{wildstr} can contain -@samp{*} and @samp{?} as wildcard characters. -Returns 0 if @code{str} and @code{wildstr} match. - -@item void get_date _A((string to, int timeflag)); -Get current date in a form ready for printing. - -@item void soundex _A((string out_pntr, string in_pntr)) -Makes @code{in_pntr} to a 5 char long string. All words that sound -alike have the same string. - -@item int init_key_cache _A((ulong use_mem, ulong leave_this_much_mem)); -Use caching of keys in MISAM, PISAM, and ISAM. -@code{KEY_CACHE_SIZE} is a good size. -Remember to lock databases for optimal caching. - -@item void end_key_cache _A((void)); -End key caching. -@end table - - - -@node DBUG, protocol, mysys functions, Top -@chapter DBUG Tags To Use - -Here is some of the tags we now use: -(We should probably add a couple of new ones) - -@table @code -@item enter -Arguments to the function. - -@item exit -Results from the function. - -@item info -Something that may be interesting. - -@item warning -When something doesn't go the usual route or may be wrong. - -@item error -When something went wrong. - -@item loop -Write in a loop, that is probably only useful when debugging -the loop. These should normally be deleted when one is -satisfied with the code and it has been in real use for a while. -@end table - -Some specific to mysqld, because we want to watch these carefully: - -@table @code -@item trans -Starting/stopping transactions. - -@item quit -@code{info} when mysqld is preparing to die. - -@item query -Print query. -@end table - - -@node protocol, Fulltext Search, DBUG, Top -@chapter MySQL Client/Server Protocol - -@menu -* raw packet without compression:: -* raw packet with compression:: -* basic packets:: -* communication:: -* 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 -@section Raw Packet Without Compression - -@example -+-----------------------------------------------+ -| Packet Length | Packet no | Data | -| 3 Bytes | 1 Byte | n Bytes | -+-----------------------------------------------+ -@end example - -@table @asis -@item 3 Byte packet length -The length is calculated with int3store -See include/global.h for details. -The max packetsize can be 16 MB. - -@item 1 Byte packet no -If no compression is used the first 4 bytes of each packet is the header -of the packet. The packet number is incremented for each sent packet. -The first packet starts with 0. -@item n Byte data - -@end table - -The packet length can be recalculated with: - -@example -length = byte1 + (256 * byte2) + (256 * 256 * byte3) -@end example - - -@node raw packet with compression, basic packets, raw packet without compression, protocol -@section Raw Packet With Compression - -@example -+---------------------------------------------------+ -| Packet Length | Packet no | Uncomp. Packet Length | -| 3 Bytes | 1 Byte | 3 Bytes | -+---------------------------------------------------+ -@end example - -@table @asis -@item 3 Byte packet length -The length is calculated with int3store -See include/global.h for details. -The max packetsize can be 16 MB. - -@item 1 Byte packet no -@item 3 Byte uncompressed packet length -@end table - -If compression is used the first 7 bytes of each packet -is the header of the packet. - - -@node basic packets, communication, raw packet with compression, protocol -@section Basic Packets - -@menu -* ok packet:: -* error packet:: -@end menu - - -@node ok packet, error packet, basic packets, basic packets -@subsection OK Packet - -For details, see @file{sql/net_pkg.cc::send_ok()}. - -@example -+-----------------------------------------------+ -| Header | No of Rows | Affected Rows | -| | 1 Byte | 1-8 Byte | -|-----------------------------------------------| -| ID (last_insert_id) | Status | Length | -| 1-8 Byte | 2 Byte | 1-8 Byte | -|-----------------------------------------------| -| Messagetext | -| n Byte | -+-----------------------------------------------+ -@end example - -@table @asis -@item Header -@item 1 byte number of rows ? (always 0 ?) -@item 1-8 bytes affected rows -@item 1-8 byte id (last_insert_id) -@item 2 byte Status (usually 0) -@item If the OK-packege includes a message: -@item 1-8 bytes length of message -@item n bytes messagetext -@end table - - -@node error packet, , ok packet, basic packets -@subsection Error Packet - -@example -+-----------------------------------------------+ -| Header | Status code | Error no | -| | 1 Byte | 2 Byte | -|-----------------------------------------------| -| Messagetext | 0x00 | -| n Byte | 1 Byte | -+-----------------------------------------------+ -@end example - -@table @asis -@item Header -@item 1 byte status code (0xFF = ERROR) -@item 2 byte error number (is only sent to new 3.23 clients. -@item n byte errortext -@item 1 byte 0x00 -@end table - - -@node communication, fieldtype codes, basic packets, protocol -@section Communication - -@example -> Packet from server to client -< Paket from client tor server - - Login - ------ - > 1. packet - Header - 1 byte protocolversion - n byte serverversion - 1 byte 0x00 - 4 byte threadnumber - 8 byte crypt seed - 1 byte 0x00 - 2 byte CLIENT_xxx options (see include/mysql_com.h - that is supported by the server - 1 byte number of current server charset - 2 byte server status variables (SERVER_STATUS_xxx flags) - 13 byte 0x00 (not used yet). - - < 2. packet - Header - 2 byte CLIENT_xxx options - 3 byte max_allowed_packet for the client - n byte username - 1 byte 0x00 - 8 byte crypted password - 1 byte 0x00 - n byte databasename - 1 byte 0x00 - - > 3. packet - OK-packet - - - Command - -------- - < 1. packet - Header - 1 byte command type (e.g.0x03 = query) - n byte query - - Result set (after command) - -------------------------- - > 2. packet - Header - 1-8 byte field_count (packed with net_store_length()) - - If field_count == 0 (command): - 1-8 byte affected rows - 1-8 byte insert id - 2 bytes server_status (SERVER_STATUS_xx) - - If field_count == NULL_LENGTH (251) - LOAD DATA LOCAL INFILE - - If field_count > 0 Result Set: - - > n packets - Header Info - Column description: 5 data object /column - (See code in unpack_fields()) - - Columninfo for each column: - 1 data block table_name - 1 byte length of block - n byte data - 1 data block field_name - 1 byte length of block... - n byte data - 1 data block display length of field - 1 byte length of block - 3 bytes display length of filed - 1 data block type field of type (enum_field_types) - 1 byte length of block - 1 bytexs field of type - 1 data block flags - 1 byte length of block - 2 byte flags for the columns (NOT_NULL_FLAG, ZEROFILL_FLAG....) - 1 byte decimals - - if table definition: - 1 data block default value - - Actual result (one packet per row): - 4 byte header - 1-8 byte length of data - n data -@end example - -@node fieldtype codes, protocol functions, communication, protocol -@section Fieldtype Codes - -@example - display_length |enum_field_type |flags - ---------------------------------------------------- -Blob 03 FF FF 00 |01 FC |03 90 00 00 -Mediumblob 03 FF FF FF |01 FC |03 90 00 00 -Tinyblob 03 FF 00 00 |01 FC |03 90 00 00 -Text 03 FF FF 00 |01 FC |03 10 00 00 -Mediumtext 03 FF FF FF |01 FC |03 10 00 00 -Tinytext 03 FF 00 00 |01 FC |03 10 00 00 -Integer 03 0B 00 00 |01 03 |03 03 42 00 -Mediumint 03 09 00 00 |01 09 |03 00 00 00 -Smallint 03 06 00 00 |01 02 |03 00 00 00 -Tinyint 03 04 00 00 |01 01 |03 00 00 00 -Varchar 03 XX 00 00 |01 FD |03 00 00 00 -Enum 03 05 00 00 |01 FE |03 00 01 00 -Datetime 03 13 00 00 |01 0C |03 00 00 00 -Timestamp 03 0E 00 00 |01 07 |03 61 04 00 -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 -@section Functions used to implement the protocol - -@c This should be merged with the above one and changed to texi format - -@example - -Raw packets ------------ - -- The my_net_xxxx() functions handles the packaging of a stream of data - into a raw packet that contains a packet number, length and data. - -- This is implemented for the server in sql/net_serv.cc. - The client file, libmysql/net.c, is symlinked to this file - -The important functions are: - -my_net_write() Store a packet (= # number of bytes) to be sent -net_flush() Send the packets stored in the buffer -net_write_command() Send a command (1 byte) + packet to the server. -my_net_read() Read a packet - - -Include files -------------- - -- include/mysql.h is included by all MySQL clients. It includes the - MYSQL and MYSQL_RES structures. -- include/mysql_com.h is include by mysql.h and mysql_priv.h (the - server) and includes a lot of common functions and structures to - handle the client/server protocol. - - -Packets from server to client: ------------------------------ - -sql/net_pkg.cc: - - - Sending of error packets - - Sending of OK packets (= end of data) - - Storing of values in a packet - - -sql/sql_base.cc: - - - Function send_fields() sends the field description to the client. - -sql/sql_show.cc: - - - Sends results for a lot of SHOW commands, including: - SHOW DATABASES [like 'wildcard'] - SHOW TABLES [like 'wildcard'] - - -Packets from client to server: ------------------------------- - -This is done in libmysql/libmysql.c - -The important ones are: - -- mysql_real_connect() Connects to a mysqld server -- mysql_real_query() Sends a query to the server and - reads the ok packet or columns header. -- mysql_store_result() Read a result set from the server to memory -- mysql_use_result() Read a result set row by row from the server. - -- net_safe_read() Read a packet from the server with - error handling. -- net_field_length() Reads the length of a packet string. -- simple_command() Sends a command/query to the server. - - - -Connecting to mysqld (the MySQL server) ---------------------------------------- - -- On the client side: libmysql/libmysql.c::mysql_real_connect(). -- On the server side: sql/sql_parse.cc::check_connections() - -The packets sent during a connection are as follows - -Server: Send greeting package (includes server capabilites, server - version and a random string of bytes to be used to scramble - the password. -Client: Sends package with client capabilites, user name, scrambled - password, database name - -Server: Sends ok package or error package. - -Client: If init command specified, send it t the server and read - ok/error package. - - -Password functions ------------------- - -The passwords are scrambled to a random number and are stored in hex -format on the server. - -The password handling is done in sql/password.c. The important -function is 'scramble()', which takes the a password in clear text -and uses this to 'encrypt' the random string sent by the server -to a new message. - -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, 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. - -@example -***************************** -* -* PROTOCOL OVERVIEW -* -***************************** - -The MySQL protocol is relatively simple, and is designed for high performance -through minimisation of overhead, and extensibility through versioning and -options flags. It is a request-response protocol, and does not allow -multitasking or multiplexing over a single connection. There are two packet -formats, 'raw' and 'compressed' (which is used when both client and -server support zlib compression, and the client requests that data be -compressed): - -* RAW PACKET, shorter than 16 M * - -+-----------------------------------------------+ -| Packet Length | Packet no | Data | -| 3 Bytes | 1 Byte | n Bytes | -+-----------------------------------------------+ -^ ^ -| 'HEADER' | -+-------------------------------+ - - - * Packet Length: Calculated with int3store. See include/global.h for - details. The basic computation is length = byte1 + - (256 * byte2) + (256 * 256 * byte3). The max packetsize - can be 16 MB. - - * Packet no: The packet number is incremented for each sent packet. - The first packet for each query from the client - starts with 0. - - * Data: Specific to the operation being performed. Most often - used to send string data, such as a SQL query. - -* COMPRESSED PACKET * - -+---------------------------------------------------+-----------------+ -| Packet Length | Packet no | Uncomp. Packet Length | Compressed Data | -| 3 Bytes | 1 Byte | 3 Bytes | n bytes | -+---------------------------------------------------+-----------------+ -^ ^ -| 'HEADER' | -+---------------------------------------------------+ - - * Packet Length: Calculated with int3store. See include/my_global.h for - details. The basic computation is length = byte1 + - (256 * byte2) + (256 * 256 * byte3). The max packetsize - can be 16 MB. - - * Packet no: The packet number is incremented for each sent packet. - The first packet starts with 0. - - * Uncomp. Packet Length: The length of the original, uncompressed packet - If this is zero then the data is not compressed. - - * Compressed Data: The original packet, compressed with zlib compression - - -When using the compressed protocol, the client/server will only compress -send packets where the new packet is smaller than the not compressed one. -In other words, some packets may be compressed while others will not. - -The 'compressed data' is one or more packets in *RAW PACKET* format. - -***************************** -* -* FLOW OF EVENTS -* -***************************** - -To understand how a client communicates with a MySQL server, it is easiest -to start with a high-level flow of events. Each event section will then be -followed by details of the exact contents of each type of packet involved -in the event flow. - -* * -* CONNECTION ESTABLISHMENT * -* * - -Clients connect to the server via a TCP/IP socket (port 3306 by default), a -Unix Domain Socket, or named pipes (on Windows). Once connected, the -following connection establishment sequence is followed: - -+--------+ +--------+ -| Client | | Server | -+--------+ +--------+ - | | - | Handshake initialisation, including MySQL server version, | - | protocol version and options supported, as well as the seed | - | for the password hash | - | | - | <-------------------------------------------------------------- | - | | - | Client options supported, max packet size for client | - | username, password crypted with seed from server, database | - | name. | - | | - | --------------------------------------------------------------> | - | | - | 'OK' packet if authentication succeeds, 'ERROR' packet if | - | authentication fails. | - | | - | <-------------------------------------------------------------- | - | | - - - -* HANDSHAKE INITIALISATION PACKET * - - -+--------------------------------------------------------------------+ -| Header | Prot. Version | Server Version String | 0x00 | -| | 1 Byte | n bytes | 1 byte | -|--------------------------------------------------------------------| -| Thread Number | Crypt Seed | 0x00 | CLIENT_xxx options | -| | | | supported by server | -| 4 Bytes | 8 Bytes | 1 Byte | 2 Bytes | -|--------------------------------------------------------------------| -| Server charset no. | Server status variables | 0x00 padding | -| 1 Byte | 2 Bytes | 13 bytes | -+--------------------------------------------------------------------+ - - * Protocol version (currently '10') - * Server Version String (e.g. '4.0.5-beta-log'). Can be any length as - it's followed by a 0 byte. - * Thread Number - ID of server thread handling this connection - * Crypt seed - seed used to crypt password in auth packet from client - * CLIENT_xxx options - see include/mysql_com.h - * Server charset no. - Index of charset in use by server - * Server status variables - see include/mysql_com.h - * The padding bytes are reserverd for future extensions to the protocol - -* CLIENT AUTH PACKET * - - -+--------------------------------------------------------------------+ -| Header | CLIENT_xxx options supported | max_allowed_packet | -| | by client | for client | -| | 2 Bytes | 3 bytes | -|--------------------------------------------------------------------| -| User Name | 0x00 | Crypted Password | 0x00 | Database Name | -| n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes | -|--------------------------------------------------------------------| -| 0x00 | -| 1 Byte | -+--------------------------------------------------------------------+ - - * CLIENT_xxx options that this client supports: - -#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */ -#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */ -#define CLIENT_LONG_FLAG 4 /* Get all column flags */ -#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */ -#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */ -#define CLIENT_COMPRESS 32 /* Can use compression protocol */ -#define CLIENT_ODBC 64 /* Odbc client */ -#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ -#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ -#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ -#define CLIENT_SSL 2048 /* Switch to SSL after handshake */ -#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ -#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ - - * max_allowed_packet for the client (in 'int3store' form) - * User Name - user to authenticate as. Is followed by a null byte. - * Crypted Password - password crypted with seed given in packet from - server, see scramble() in sql/password.c - * Database name (optional) - initial database to use once connected - Is followed by a null byte - -At the end of every client/server exchange there is either an 'OK' packet -or an 'ERROR' packet sent from the server. To determine whether a packet is -an 'OK' packet, or an 'ERROR' packet, check if the first byte (after the -header) is 0xFF. If it has the value of 0xFF, the packet is an 'ERROR' -packet. - - -* OK PACKET * - -For details, see sql/net_pkg.cc::send_ok() - -+-----------------------------------------------+ -| Header | No of Rows | Affected Rows | -| | 1 Byte | 1-9 Byte | -|-----------------------------------------------| -| ID (last_insert_id) | Status | Length | -| 1-9 Byte | 2 Byte | 1-9 Byte | -|-----------------------------------------------| -| Messagetext | -| n Byte | -+-----------------------------------------------+ - - * Number of rows, always 0 - * Affected rows - * ID (last_insert_id) - value for auto_increment column (if any) - * Status (usually 0) - -In general, in the MySQL protocol, fields in a packet that that -represent numeric data, such as lengths, that are labeled as '1-9' -bytes can be decoded by the following logic: - - If the first byte is '251', the - corresponding column value is NULL (only appropriate in - 'ROW DATA' packets). - - If the first byte is '252', the value stored can be read - from the following 2 bytes as a 16-bit integer. - - - If the first byte is '253' the value stored can be read - from the following 4 bytes as a 32-bit long integer - - - If the first byte is '254', the value stored can be read - from the following 8 bytes as a 64-byte long - - Otherwise (values 0-250), the value stored is the value of the - first byte itself. - - -If the OK-packet includes a message: - - * Length of message - * Message Text - - -* ERROR PACKET * - -+-----------------------------------------------+ -| Header | Status code | Error no | -| | 1 Byte | 2 Byte | -|-----------------------------------------------| -| Messagetext | | -| n Byte | | -+-----------------------------------------------+ - - * Status code (0xFF = ERROR) - * Error number (is only sent to 3.23 and newer clients) - * Error message text (ends at end of packet) - -Note that the error message is not null terminated. -The client code can however assume that the packet ends with a null -as my_net_read() will always add an end-null to all read packets to -make things easier for the client. - -Example: - -Packet dump of client connecting to server: - -+------------------------- Protocol Version (10) -| -| +---------------------- Server Version String (0x00 terminated) -| | -| | -0a 34 2e 30 2e 35 2d 62 . 4 . 0 . 5 - b -65 74 61 2d 6c 6f 67 00 e t a - l o g . -15 00 00 00 2b 5a 65 6c . . . . + Z e l - | | - | +------------ First 4 bytes of crypt seed - | - +------------------------ Thread Number - -+------------------------- Last 4 bytes of crypt seed -| -| +-------- CLIENT_XXX Options supported by server -| | -| +-+--+ +--- Server charset index -| | | | -6f 69 41 46 00 2c 28 08 o i A F . , ( . -02 00 00 00 00 00 00 00 . . . . . . . . -| | -| +---------------------- 0x00 padding begins -| -+------------------------- Server status (0x02 = - SERVER_STATUS_AUTOCOMMIT) - -00 00 00 00 00 00 00 00 . . . . . . . . - -* Client Authentication Response (Username 'test', no database - selected) * - - +--------------------- Packet Length (0x13 = 19 bytes) - | - | +--------------- Packet Sequence # - | | - | | +----------- CLIENT_XXX Options supported by client - | | -+---+---+ | +-+-+ -| | | | | -13 00 00 01 03 00 1e 00 . . . . . . . . -00 74 65 73 74 00 48 5e . t e s t . H ^ - | | | - +----+-----+ +------- Scrambled password, 0x00 terminated - | - +----------------- Username, 0x00 terminated - -57 4a 4e 41 4a 4e 00 00 W J N A J N . . -00 . - - ->From this point on, the server waits for 'commands' from the client -which include queries, database shutdown, quit, change user, etc (see -the COM_xxxx values in include/mysql_com.h for the latest -command codes). - -* * -* COMMAND PROCESSING * -* * - -+--------+ +--------+ -| Client | | Server | -+--------+ +--------+ - | | - | A command packet, with a command code, and string data | - | when appropriate (e.g. a query), (see the COM_xxxx values | - | in include/mysql_com.h for the command codes) | - | | - | --------------------------------------------------------------> | - | | - | A 'RESULT' packet if the command completed successfully, | - | an 'ERROR' packet if the command failed. 'RESULT' packets | - | take different forms (see the details following this chart) | - | depending on whether or not the command returns rows. | - | | - | <-------------------------------------------------------------- | - | | - | n 'FIELD PACKET's (if rows are returned) | - | | - | <-------------------------------------------------------------- | - | | - | 'LAST DATA' packet | - | | - | <-------------------------------------------------------------- | - | | - | n 'ROW PACKET's (if rows are returned) | - | | - | <-------------------------------------------------------------- | - | | - | 'LAST DATA' packet | - | | - | <-------------------------------------------------------------- | - | | - - -* Command Packet * - -+------------------------------------------------------+ -| Header | Command type | Query (if applicable) | -| | 1 Byte | n Bytes | -+------------------------------------------------------+ - - * Command type: (e.g.0x03 = query, see the COM_xxxx values in - include/mysql_com.h) - * Query (if applicable) - -Note that my_net_read() null-terminates all packets on the -receiving side of the channel to make it easier for the code -examining the packets. - -The current command codes are: - - 0x00 COM_SLEEP - 0x01 COM_QUIT - 0x02 COM_INIT_DB - 0x03 COM_QUERY - 0x04 COM_FIELD_LIST - 0x05 COM_CREATE_DB - 0x06 COM_DROP_DB - 0x07 COM_REFRESH - 0x08 COM_SHUTDOWN - 0x09 COM_STATISTICS - 0x0a COM_PROCESS_INFO - 0x0b COM_CONNECT - 0x0c COM_PROCESS_KILL - 0x0d COM_DEBUG - 0x0e COM_PING - 0x0f COM_TIME - 0x10 COM_DELAYED_INSERT - 0x11 COM_CHANGE_USER - 0x12 COM_BINLOG_DUMP - 0x13 COM_TABLE_DUMP - 0x14 COM_CONNECT_OUT - 0x15 COM_REGISTER_SLAVE - -* Result Packet * - -Result packet for a command returning _no_ rows: - -+-----------------------------------------------+ -| Header | Field Count | Affected Rows | -| | 1-9 Bytes | 1-9 Bytes | -|-----------------------------------------------| -| ID (last_insert_id) | Server Status | -| 1-9 Bytes | 2 Bytes | -+-----------------------------------------------+ - - * Field Count: Has value of '0' for commands returning _no_ rows - * Affected rows: Count of rows affected by INSERT/UPDATE/DELETE, etc. - * ID: value of auto_increment column in row (if any). 0 if - * Server Status: Usually 0 - -Result packet for a command returning rows: - -+-------------------------------+ -| Header | Field Count | -| | 1-9 Bytes | -+-------------------------------+ - - * Field Count: number of columns/fields in result set, - (packed with net_store_length() in sql/net_pkg.cc) - -This is followed by as many packets as the number of fields ('Field Count') -that contain the metadata for each column/field (see unpack_fields() in -libmysql/libmysql.c): - - -* FIELD PACKET * - -+-----------------------------------------------+ -| Header | Table Name | -| | length-coded-string | -|-----------------------------------------------| -| Field Name | -| length-code-string | -|-----------------------------------------------| -| Display length of field -| length-coded-binary (4 bytes) | -|-----------------------------------------------| -| Field Type (enum_field_types in mysql_com.h) | -| length-coded-binary (2 bytes) | -|-----------------------------------------------| -| Field Flags | Decimal Places| -| length-coded-binary (3 bytes) | 1 Byte | -+--------------+-------------+------------------+ - - * A length coded string is a string where we first have a packet - length (1-9 bytes, packed_with net_store_length()) followed - by a string. - * A length coded binary is a length (1 byte) followed by an integer - value in low-byte-first order. For the moment this type is always - fixed length in this packet. - - * Table Name - the name of the table the column comes from - * Field Name - the name of the column/field - * Display length of field - length of field - * Field Type - Type of field, see enum_field_types in - include/mysql_com.h - - Current field types are: - - 0x00 FIELD_TYPE_DECIMAL - 0x01 FIELD_TYPE_TINY - 0x02 FIELD_TYPE_SHORT - 0x03 FIELD_TYPE_LONG - 0x04 FIELD_TYPE_FLOAT - 0x05 FIELD_TYPE_DOUBLE - 0x06 FIELD_TYPE_NULL - 0x07 FIELD_TYPE_TIMESTAMP - 0x08 FIELD_TYPE_LONGLONG - 0x09 FIELD_TYPE_INT24 - 0x0a FIELD_TYPE_DATE - 0x0b FIELD_TYPE_TIME - 0x0c FIELD_TYPE_DATETIME - 0x0d FIELD_TYPE_YEAR - 0x0e FIELD_TYPE_NEWDATE - 0xf7 FIELD_TYPE_ENUM - 0xf8 FIELD_TYPE_SET - 0xf9 FIELD_TYPE_TINY_BLOB - 0xfa FIELD_TYPE_MEDIUM_BLOB - 0xfb FIELD_TYPE_LONG_BLOB - 0xfc FIELD_TYPE_BLOB - 0xfd FIELD_TYPE_VAR_STRING - 0xfe FIELD_TYPE_STRING - 0xff FIELD_TYPE_GEOMETRY - - * Field Flags - NOT_NULL_FLAG, PRI_KEY_FLAG, xxx_FLAG in - include/mysql_com.h - - -Note that the packet format in 4.1 has slightly changed to allow more values. - - -* ROW PACKET * - -+-----------------------------------------------+ -| Header | Data Length | Column Data | ....for each column -| | 1-9 Bytes | n Bytes | -+-----------------------------------------------+ - - * Data Length: (packed with net_store_length() in sql/net_pkg.cc) - - If 'Data Length' == 0, this is an 'ERROR PACKET'. - - * Column Data: String representation of data. MySQL always sends result set - data as strings. - -* LAST DATA PACKET * - -Packet length is < 9 bytes, and first byte is 0xFE - -+--------+ -| 0xFE | -| 1 Byte | -+--------+ - -Examples: - -*********** -* -* INITDB Command -* -*********** - -A client issuing an 'INITDB' (select the database to use) command, -followed by an 'OK' packet with no rows and no affected rows from -the server: - -* INITDB (select database to use) 'COMMAND' Packet * - - +--------------------- Packet Length (5 bytes) - | - | +--------------- Packet Sequence # - | | - | | +------------ Command # (INITDB = 0x02) - | | -+---+---+ | | +---------- Beginning of query data -| | | | | -05 00 00 00 02 74 65 73 . . . . . t e s -74 t - -* 'OK' Packet with no rows, and no rows affected * - - +--------------------- Packet Length (3 bytes) - | - | +--------------- Packet Sequence # - | | -+---+---+ | -| | | -03 00 00 01 00 00 00 . . . . . . . - - -*********** -* -* SELECT query example -* -*********** - -Client issuing a 'SELECT *' query on the following table: - - CREATE TABLE number_test (minBigInt bigint, - maxBigInt bigint, - testBigInt bigint) - -* 'COMMAND' Packet with QUERY (select ...) * - - +--------------------- Packet Length (26) - | - | +--------------- Packet Sequence # - | | - | | +------------ Command # (QUERY = 0x03) - | | -+---+---+ | | +---------- Beginning of query data -| | | | | -1a 00 00 00 03 53 45 4c . . . . . S E L -45 43 54 20 2a 20 66 72 E C T . * . f r -6f 6d 20 6e 75 6d 62 65 o m . n u m b e -72 5f 74 65 73 74 r _ t e s t - - -and receiving an 'OK' packet with a 'FIELD COUNT' of 3 - - -* 'OK' Packet with 3 fields * - - +--------------------- Packet Length (3 bytes) - | - | +--------------- Packet Sequence # - | | -+---+---+ | -| | | -01 00 00 01 03 . . . . . - -Followed immediately by 3 'FIELD' Packets. Note, the individual packets -are delimitted by =======, so that all fields can be annotated in the first -'FIELD' packet example: - -============================================================= - - +--------------------- Packet Length (0x1f = 31 bytes) - | - | +--------------- Packet Sequence # - | | - | | +------------ Block Length (0x0b = 11 bytes) - | | | -+---+---+ | | +--------- Table Name (11 bytes long) -| | | | | -1f 00 00 02 0b 6e 75 6d . . . . . n u m -62 65 72 5f 74 65 73 74 b e r _ t e s t - - +------------------------ Block Length (9 bytes) - | - | +--------------------- Column Name (9 bytes long) - | | -09 6d 69 6e 42 69 67 49 . m i n B i g I -6e 74 03 14 00 00 01 08 n t . . . . . . - | | | | | - | +---+---+ | +--- Field Type (0x08 = FIELD_TYPE_LONGLONG) - | | | - | | +------ Block Length (1) - | | - | +--------------- Display Length (0x14 = 20 chars) - | - +------------------ Block Length (3) - - +------------------------ Block Length (2) - | - | +-------------------- Field Flags (0 - no flags set) - | | - | +---+ +--------------- Decimal Places (0) - | | | | -02 00 00 00 . . . . - -============================================================= - -'FIELD' packet for the 'number_Test.maxBigInt' column - -1f 00 00 03 0b 6e 75 6d . . . . . n u m -62 65 72 5f 74 65 73 74 b e r _ t e s t -09 6d 61 78 42 69 67 49 . m a x B i g I -6e 74 03 14 00 00 01 08 n t . . . . . . -02 00 00 00 . . . . - -============================================================= - -'FIELD' packet for the 'number_test.testBigInt' column - -20 00 00 04 0b 6e 75 6d . . . . . n u m -62 65 72 5f 74 65 73 74 b e r _ t e s t -0a 74 65 73 74 42 69 67 . t e st B i g -49 6e 74 03 14 00 00 01 I n t . . . . . -08 02 00 00 00 . . . . . -============================================================= - -Followed immediately by one 'LAST DATA' packet: - -fe 00 . . - -Followed immediately by 'n' row packets (in this case, only -one packet is sent from the server, for simplicity's sake): - - - +--------------------- Packet Length (0x52 = 82 bytes) - | - | +--------------- Packet Sequence # - | | - | | +------------ Data Length (0x14 = 20 bytes) - | | | -+---+---+ | | +--------- String Data '-9223372036854775808' -| | | | | (repeat Data Length/Data sequence) - -52 00 00 06 14 2d 39 32 . . . . . - 9 2 -32 33 33 37 32 30 33 36 2 3 3 7 2 0 3 6 -38 35 34 37 37 35 38 30 8 5 4 7 7 5 8 0 -38 13 39 32 32 33 33 37 8 . 9 2 2 3 3 7 -32 30 33 36 38 35 34 37 2 0 3 6 8 5 4 7 -37 35 38 30 37 0a 36 31 7 5 8 0 7 . 6 1 -34 37 34 38 33 36 34 37 4 7 4 8 3 6 4 7 - -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) - -@c @node Index -@c @unnumbered Index - -@c @printindex fn - -@c @node 4.1 protocol,,, -@c @chapter MySQL 4.1 protocol - -@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 -with an old 4.0 or 3.x client we will use the old protocol. - -The new things that we support with 4.1 are: - -@itemize @bullet -@item -Warnings -@item -Prepared statements -@item -Binary protocol (will be faster than the current protocol that -converts everything to strings) -@end itemize - - -What has changed in 4.1 are: - -@itemize @bullet -@item -A lot of new field information (database, real table name etc) -@item -The 'ok' packet has more status fields -@item -The 'end' packet (send last for each result set) now contains some -extra information -@item -New protocol for prepared statements. In this case all parameters and -results will sent as binary (low-byte-first). -@end itemize - - -@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 -contains a result set. It can be distinguished from a ok packet by -the fact that the first byte can't be 0 for a field packet. -@xref{4.1 ok packet}. - -The header packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1-9 @tab Number of columns in result set (never 0) -@item 1-9 @tab Extra information sent be some command (SHOW COLUMNS -uses this to send the number of rows in the table) -@end multitable - -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, protocol -@section 4.1 field description result set - -The field description result set contains the meta info for a result set. - -@multitable @columnfractions .20 .80 -@item Type @tab Comment -@item string @tab Database name -@item string @tab Table name alias (or table name if no alias) -@item string @tab Real table name -@item string @tab Alias for column name (or column name if not used) -@item 3 byte int @tab Length of column definition -@item 1 byte int @tab Enum value for field type -@item 3 byte int @tab 2 byte column flags (NOT_NULL_FLAG etc..) + 1 byte number of decimals. -@item string int @tab Default value, only set when using mysql_list_fields(). -@end multitable - - -@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 -that didn't return a result set. - -The ok packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1 @tab 0 ; Marker for ok packet -@item 1-9 @tab Affected rows -@item 1-9 @tab Last insert id (0 if one wasn't used) -@item 2 @tab Server status; Can be used by client to check if we are inside an transaction -@item 2 @tab Warning count -@item 1-9 @tab Message length (optional) -@item xxx @tab Message (optional) -@end multitable - -Size 1-9 means that the parameter is packed in to 1-9 bytes depending on -the value. (See function sql/net_pkg.cc::net_store_length). - -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, protocol -@section 4.1 end packet - -The end packet is sent as the last packet for - -@itemize @bullet -@item -End of field information -@item -End of parameter type information -@item -End of result set -@end itemize - -The end packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1 @tab 254 ; Marker for EOF packet -@item 2 @tab Warning count -@item 2 @tab Status flags (For flags like SERVER_STATUS_MORE_RESULTS) -@end multitable - -Note that a normal packet may start with byte 254, which means -'length stored in 9 bytes'. One can different between these cases -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, protocol -@section 4.1 error packet. - -The error packet is sent when something goes wrong. -The error packet has the following structure: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 1 @tab 255 Error packet marker -@item 2 @tab Error code -@item 1-255 @tab Null terminated error message -@end multitable - -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, protocol -@section 4.1 prepared statement init packet - -This is the return packet when one sends a query with the COM_PREPARE -command. - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 4 @tab Statement handler id -@item 2 @tab Number of columns in result set -@item 2 @tab Number of parameters in query -@end multitable - -After this, there is a packet that contains the following for each -parameter in the query: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 2 @tab Enum value for field type. (MYSQL_TYPE_UNKNOWN if not known) -@item 2 @tab 2 byte column flags (NOT_NULL_FLAG etc) -@item 1 @tab Number of decimals -@item 4 @tab Max column length. -@end multitable - -Note that the above is not yet in 4.1 but will be added this month. - -As MySQL can have a parameter 'anywhere' it will in many cases not be -able to provide the optimal information for all parameters. - -If number of columns, in the header packet, is not 0 then the -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, protocol -@section 4.1 long data handling - -This is used by mysql_send_long_data() to set any parameter to a string -value. One can call mysql_send_long_data() multiple times for the -same parameter; The server will concatenate the results to a one big -string. - -The server will not require an end packet for the string. -mysql_send_long_data() is responsible updating a flag that all data -has been sent. (Ie; That the last call to mysql_send_long_data() has -the 'last_data' flag set). - -This packet is sent from client -> server: - -@multitable @columnfractions .10 .90 -@item Size @tab Comment -@item 4 @tab Statement handler -@item 2 @tab Parameter number -@item 2 @tab Type of parameter (not used at this point) -@item # @tab data (Rest of packet) -@end multitable - -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, protocol -@section 4.1 execute - -On execute we send all parameters to the server in a COM_EXECUTE -packet. - -The packet contains the following information: - -@multitable @columnfractions .30 .70 -@item Size @tab Comment -@item (param_count+9)/8 @tab Null bit map (2 bits reserved for protocol) -@item 1 @tab new_parameter_bound flag. Is set to 1 for first -execute or if one has rebound the parameters. -@item 2*param_count @tab Type of parameters (only given if new_parameter_bound flag is 1) -@item # @tab Parameter data, repeated for each parameter that are -NOT NULL and not used with mysql_send_long_data(). -@end multitable - -The null-bit-map is for all parameters (including parameters sent with -'mysql_send_long_data). If parameter 0 is NULL, then bit 0 in the -null-bit-map should be 1 (ie: first byte should be 1) - -The parameters are stored the following ways: - -@multitable @columnfractions .20 .10 .70 -@item Type @tab Size @tab Comment -@item tinyint @tab 1 @tab One byte integer -@item short @tab 2 @tab -@item int @tab 4 @tab -@item longlong @tab 8 @tab -@item float @tab 4 @tab -@item double @tab 8 @tab -@item string @tab 1-9 + # @tab Packed string length + string -@end multitable - -The result for this will be either an ok packet or a binary result -set. - -@node 4.1 binary result, , 4.1 execute, protocol -@section 4.1 binary result set - -A binary result are sent the following way. - -For each result row: - -@itemize -@item -null bit map with first two bits set to 01 (bit 0,1 value 1) -@item -parameter data, repeated for each not null result column. -@end itemize - -The idea with the reserving two bits in the null map is that we can -use standard error (first byte 255) and ok packets (first byte 0) -to end a result sets. - -Except that the null-bit-map is shifted two steps, the server is -sending the data to the client the same way that the server is sending -bound parameters to the client. The server is always sending the data -as type given for 'column type' for respective column. It's up to the -client to convert the parameter to the requested type. - -DATETIME, DATE and TIME are sent to the server in a binary format as follows: - -@multitable @columnfractions .20 .10 .70 -@item Type @tab Size @tab Comment -@item date @tab 1 + 0-11 @tab Length + 2 byte year, 1 byte MMDDHHMMSS, 4 byte billionth of a second -@item datetime @tab 1 + 0-11 @tab Length + 2 byte year, 1 byte MMDDHHMMSS, 4 byte billionth of a second -@item time @tab 1 + 0-14 @tab Length + sign (0 = pos, 1= neg), 4 byte days, 1 byte HHMMDD, 4 byte billionth of a second -@end multitable - -The first byte is a length byte and then comes all parameters that are -not 0. (Always counted from the beginning). - -@node Fulltext Search, MyISAM Record Structure, protocol, Top -@chapter Fulltext Search in MySQL - -Hopefully, sometime there will be complete description of -fulltext search algorithms. -Now it's just unsorted notes. - -@menu -* Weighting in boolean mode:: -@end menu - -@node Weighting in boolean mode, , Fulltext Search, Fulltext Search -@section Weighting in boolean mode - -The basic idea is as follows: in expression -@code{A or B or (C and D and E)}, either @code{A} or @code{B} alone -is enough to match the whole expression. While @code{C}, -@code{D}, and @code{E} should @strong{all} match. So it's -reasonable to assign weight 1 to @code{A}, @code{B}, and -@code{(C and D and E)}. And @code{C}, @code{D}, and @code{E} -should get a weight of 1/3. - -Things become more complicated when considering boolean -operators, as used in MySQL FTB. Obvioulsy, @code{+A +B} -should be treated as @code{A and B}, and @code{A B} - -as @code{A or B}. The problem is, that @code{+A B} can @strong{not} -be rewritten in and/or terms (that's the reason why this - extended - -set of operators was chosen). Still, aproximations can be used. -@code{+A B C} can be approximated as @code{A or (A and (B or C))} -or as @code{A or (A and B) or (A and C) or (A and B and C)}. -Applying the above logic (and omitting mathematical -transformations and normalization) one gets that for -@code{+A_1 +A_2 ... +A_N B_1 B_2 ... B_M} the weights -should be: @code{A_i = 1/N}, @code{B_j=1} if @code{N==0}, and, -otherwise, in the first rewritting approach @code{B_j = 1/3}, -and in the second one - @code{B_j = (1+(M-1)*2^M)/(M*(2^(M+1)-1))}. - -The second expression gives somewhat steeper increase in total -weight as number of matched B's increases, because it assigns -higher weights to individual B's. Also the first expression in -much simplier. So it is the first one, that is implemented in MySQL. - - -@node MyISAM Record Structure, InnoDB Record Structure, Fulltext Search, Top -@chapter MyISAM Record Structure - -@section Introduction - -When you say: -@* - -@strong{CREATE TABLE Table1 ...} -@* - -MySQL creates files named Table1.MYD ("MySQL Data"), Table1.MYI -("MySQL Index"), and Table1.frm ("Format"). These files will be in the -directory: @* -/// -@* - -For example, if you use Linux, you might find the files here (assume -your database name is "test"): @* -/usr/local/var/test -@* - -And if you use Windows, you might find the files in this directory: @* -\mysql\data\test\ -@*@* - -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). -@* - -@item Record Header -The minimal record header is a set of flags: -@itemize @bullet -@item -"X bit" = 0 if row is deleted, = 1 if row is not deleted -@item -"Null Bits" = 0 if column is not NULL, = 1 if column is NULL -@item -"Filler Bits" = 1 -@end itemize -@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: -@* - -@strong{CREATE TABLE Table1 (column1 CHAR(1), column2 CHAR(1), column3 CHAR(1))} -@* - -@strong{INSERT INTO Table1 VALUES ('a', 'b', 'c')} -@* - -@strong{INSERT INTO Table1 VALUES ('d', NULL, 'e')} -@* - -A CHAR(1) column takes precisely one byte (plus one bit of overhead -that is assigned to every column -- I'll describe the details of -column storage later). So the file Table1.MYD looks like this: -@* - -@strong{Hexadecimal Display of Table1.MYD file}@* -@code{ -F1 61 62 63 00 F5 64 00 66 00 ... .abc..d e. -} -@* - -Here's how to read this hexadecimal-dump display:@* -@itemize @bullet -@item -The hexadecimal numbers @code{F1 61 62 63 00 F5 64 20 66 00} are byte -values and the column on the right is an attempt to show the -same bytes in ASCII. -@item -The @code{F1} byte means that there are no null fields in the first row. -@item -The @code{F5} byte means that the second column of the second row is NULL. -@end itemize - -(It's probably easier to understand the flag setting if you restate -@code{F5} as @code{11110101 binary}, and (a) notice that the third flag bit from the -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 -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 -@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. -The format depends entirely on the data type and the size of the -column, so, for every data type, I'll give a description and an example. -@* - -@table @strong -@item The character data types - -@strong{CHAR} -@itemize @bullet -@item -Storage: fixed-length string with space padding on the right. -@item -Example: a CHAR(5) column containing the value 'A' looks like:@* -@code{hexadecimal 41 20 20 20 20} -- (length = 5, value = @code{'A '}) -@end itemize - -@strong{VARCHAR} -@itemize @bullet -@item -Storage: variable-length string with a preceding length. -@item -Example: a VARCHAR(7) column containing 'A' looks like:@* -@code{hexadecimal 01 41} -- (length = 1, value = @code{'A'}) -@end itemize - -@item The numeric data types - -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. -@* - -@strong{TINYINT} -@itemize @bullet -@item -Storage: fixed-length binary, always one byte. -@item -Example: a TINYINT column containing 65 looks like:@* -@code{hexadecimal 41} -- (length = 1, value = 65) -@end itemize - -@strong{SMALLINT} -@itemize @bullet -@item -Storage: fixed-length binary, always two bytes. -@item -Example: a SMALLINT column containing 65 looks like:@* -@code{hexadecimal 41 00} -- (length = 2, value = 65) -@end itemize - -@strong{MEDIUMINT} -@itemize @bullet -@item -Storage: fixed-length binary, always three bytes. -@item -Example: a MEDIUMINT column containing 65 looks like:@* -@code{hexadecimal 41 00 00} -- (length = 3, value = 65) -@end itemize - -@strong{INT} -@itemize @bullet -@item -Storage: fixed-length binary, always four bytes. -@item -Example: an INT column containing 65 looks like:@* -@code{hexadecimal 41 00 00 00} -- (length = 4, value = 65) -@end itemize - -@strong{BIGINT} -@itemize @bullet -@item -Storage: fixed-length binary, always eight bytes. -@item -Example: a BIGINT column containing 65 looks like:@* -@code{hexadecimal 41 00 00 00 00 00 00 00} -- (length = 8, value = 65) -@end itemize - -@strong{FLOAT} -@itemize @bullet -@item -Storage: fixed-length binary, always four bytes. -@item -Example: a FLOAT column containing approximately 65 looks like:@* -@code{hexadecimal 00 00 82 42} -- (length = 4, value = 65) -@end itemize - -@strong{DOUBLE PRECISION} -@itemize @bullet -@item -Storage: fixed-length binary, always eight bytes. -@item -Example: a DOUBLE PRECISION column containing approximately 65 looks like:@* -@code{hexadecimal 00 00 00 00 00 40 50 40} -- (length = 8, value = 65) -@end itemize - -@strong{REAL} -@itemize @bullet -@item -Storage: same as FLOAT, or same as DOUBLE PRECISION, depending on setting of the --ansi switch. -@end itemize - -@strong{DECIMAL} -@itemize @bullet -@item -Storage: fixed-length string, with a leading byte for the sign, if any. -@item -Example: a DECIMAL(2) column containing 65 looks like:@* -@code{hexadecimal 20 36 35} -- (length = 3, value = @code{' 65'}) -@item -Example: a DECIMAL(2) UNSIGNED column containing 65 looks like:@* -@code{hexadecimal 36 35} -- (length = 2, value = @code{'65'}) -@item -Example: a DECIMAL(4,2) UNSIGNED column containing 65 looks like:@* -@code{hexadecimal 36 35 2E 30 30} -- (length = 5, value = @code{'65.00'}) -@end itemize - -@strong{NUMERIC} -@itemize @bullet -@item -Storage: same as DECIMAL. -@end itemize - -@strong{BOOL} -@itemize @bullet -@item -Storage: same as TINYINT. -@end itemize - -@item The temporal data types - -@strong{DATE} -@itemize @bullet -@item -Storage: 3 byte integer, low byte first. -Packed as: 'day + month*32 + year*16*32' -@item -Example: a DATE column containing '1962-01-02' looks like:@* -@code{hexadecimal 22 54 0F} -@end itemize - -@strong{DATETIME} -@itemize @bullet -@item -Storage: eight bytes. -@item -Part 1 is a 32-bit integer containing year*10000 + month*100 + day. -@item -Part 2 is a 32-bit integer containing hour*10000 + minute*100 + second. -@item -Example: a DATETIME column for '0001-01-01 01:01:01' looks like:@* -@code{hexadecimal B5 2E 11 5A 02 00 00 00} -@end itemize - -@strong{TIME} -@itemize @bullet -@item -Storage: 3 bytes, low byte first. -This is stored as seconds: days*24*3600+hours*3600+minutes*60+seconds -@item -Example: a TIME column containing '1 02:03:04' (1 day 2 hour 3 minutes and 4 seconds) looks like:@* -@code{hexadecimal 58 6E 01} -@end itemize - -@strong{TIMESTAMP} -@itemize @bullet -@item -Storage: 4 bytes, low byte first. -Stored as unix @code{time()}, which is seconds since the Epoch -(00:00:00 UTC, January 1, 1970). -@item -Example: a TIMESTAMP column containing '2003-01-01 01:01:01' looks like:@* -@code{hexadecimal 4D AE 12 23} -@end itemize - -@strong{YEAR} -@itemize @bullet -@item -Storage: same as unsigned TINYINT with a base value of 0 = 1901. -@end itemize - -@item Others - -@strong{SET} -@itemize @bullet -@item -Storage: one byte for each eight members in the set. -@item -Maximum length: eight bytes (for maximum 64 members). -@item -This is a bit list. The least significant bit corresponds to the -first listed member of the set. -@item -Example: a SET('A','B','C') column containing 'A' looks like:@* -@code{01} -- (length = 1, value = 'A') -@end itemize - -@strong{ENUM} -@itemize @bullet -@item -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 an erroneous value. This -explains why 'A' is 1 instead of 0.) -@item -Example: an ENUM('A','B','C') column containing 'A' looks like:@* -@code{01} -- (length = 1, value = 'A') -@end itemize - -@item The Large-Object data types - -Warning: Because TINYBLOB's preceding length is one byte long (the -size of a TINYINT) and MEDIUMBLOB's preceding length is three bytes -long (the size of a MEDIUMINT), it's easy to think there's some sort -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). -@* - -@strong{TINYBLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding one-byte length. -@item -Example: a TINYBLOB column containing 'A' looks like:@* -@code{hexadecimal 01 41} -- (length = 2, value = 'A') -@end itemize - -@strong{TINYTEXT} -@itemize @bullet -@item -Storage: same as TINYBLOB. -@end itemize - -@strong{BLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding two-byte length. -@item -Example: a BLOB column containing 'A' looks like:@* -@code{hexadecimal 01 00 41} -- (length = 2, value = 'A') -@end itemize - -@strong{TEXT} -@itemize @bullet -@item -Storage: same as BLOB. -@end itemize - -@strong{MEDIUMBLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding length. -@item -Example: a MEDIUMBLOB column containing 'A' looks like:@* -@code{hexadecimal 01 00 00 41} -- (length = 4, value = 'A') -@end itemize - -@strong{MEDIUMTEXT} -@itemize @bullet -@item -Storage: same as MEDIUMBLOB. -@end itemize - -@strong{LONGBLOB} -@itemize @bullet -@item -Storage: variable-length string with a preceding four-byte length. -@item -Example: a LONGBLOB column containing 'A' looks like:@* -@code{hexadecimal 01 00 00 00 41} -- (length = 5, value = 'A') -@end itemize - -@strong{LONGTEXT} -@itemize @bullet -@item -Storage: same as LONGBLOB. -@end itemize - -@end table - -@section Where to Look For More Information - -@strong{References:} @* -Most of the formatting work for MyISAM columns is visible -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 -@chapter InnoDB Record Structure - -This page contains: -@itemize @bullet -@item -A high-altitude "summary" picture of the parts of a MySQL/InnoDB -record structure. -@item -A description of each part. -@item -An example. -@end itemize - -After reading this page, you will know how MySQL/InnoDB stores a -physical record. -@* - -@section High-Altitude Picture - -The chart below shows the three parts of a physical record. - -@multitable @columnfractions .10 .35 - -@item @strong{Name} @tab @strong{Size} -@item Field Start Offsets -@tab (F*1) or (F*2) bytes -@item Extra Bytes -@tab 6 bytes -@item Field Contents -@tab depends on content - -@end multitable - -Legend: The letter 'F' stands for 'Number Of Fields'. - -The meaning of the parts is as follows: -@itemize @bullet -@item -The FIELD START OFFSETS is a list of numbers containing the -information "where a field starts". -@item -The EXTRA BYTES is a fixed-size header. -@item -The FIELD CONTENTS contains the actual data. -@end itemize - -@strong{An Important Note About The Word "Origin"}@* -The "Origin" or "Zero Point" of a record is the first byte of the -Field Contents -- not the first byte of the Field Start Offsets. If -there is a pointer to a record, that pointer is pointing to the -Origin. Therefore the first two parts of the record are addressed by -subtracting from the pointer, and only the third part is addressed by -adding to the pointer. - -@subsection FIELD START OFFSETS - -The Field Start Offsets is a list in which each entry is the -position, relative to the Origin, of the start of the next field. The -entries are in reverse order, that is, the first field's offset is at -the end of the list. -@* - -An example: suppose there are three columns. The first column's length -is 1, the second column's length is 2, and the third column's length is 4. -In this case, the offset values are, respectively, 1, 3 (1+2), and 7 (1+2+4). -Because values are reversed, a core dump of the Field Start Offsets -would look like this: @code{07,03,01}. -@* - -There are two complications for special cases: -@itemize @bullet -@item -Complication #1: The size of each offset can be either one byte or -two bytes. One-byte offsets are only usable if the total record size -is less than 127. There is a flag in the "Extra Bytes" part which will -tell you whether the size is one byte or two bytes. -@item -Complication #2: The most significant bits of an offset may contain -flag values. The next two paragraphs explain what the contents are. -@end itemize - -@strong{When The Size Of Each Offset Is One Byte} -@itemize @bullet -@item -1 bit = 0 if field is non-NULL, = 1 if field is NULL -@item -7 bits = the actual offset, a number between 0 and 127 -@end itemize - -@strong{When The Size Of Each Offset Is Two Bytes} -@itemize @bullet -@item -1 bit = 0 if field is non-NULL, = 1 if field is NULL -@item -1 bit = 0 if field is on same page as offset, = 1 if field and offset are on different pages -@item -14 bits = the actual offset, a number between 0 and 16383 -@end itemize - -It is unlikely that the "field and offset are on different pages" -unless the record contains a large BLOB. - -@subsection EXTRA BYTES - -The Extra Bytes are a fixed six-byte header. - -@multitable @columnfractions .10 .25 .35 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Description} -@item @strong{info_bits:} -@item () -@tab 1 bit -@tab unused or unknown -@item () -@tab 1 bit -@tab unused or unknown -@item deleted_flag -@tab 1 bit -@tab 1 if record is deleted -@item min_rec_flag -@tab 1 bit -@tab 1 if record is predefined minimum record -@item n_owned -@tab 4 bits -@tab number of records owned by this record -@item heap_no -@tab 13 bits -@tab record's order number in heap of index page -@item n_fields -@tab 10 bits -@tab number of fields in this record, 1 to 1023 -@item 1byte_offs_flag -@tab 1 bit -@tab 1 if each Field Start Offsets is 1 byte long (this item is also called the "short" flag) -@item @strong{next 16 bits} -@tab 16 bits -@tab pointer to next record in page -@item @strong{TOTAL} -@tab 48 bits - -@end multitable - -Total size is 48 bits, which is six bytes. -@* - -If you're just trying to read the record, the key bit in the Extra -Bytes is 1byte_offs_flag -- you need to know if 1byte_offs_flag is 1 -(i.e.: "short 1-byteoffsets") or 0 (i.e.: "2-byte offsets"). -@* - -Given a pointer to the Origin, InnoDB finds the start of the record as follows: -@itemize @bullet -@item -Let X = n_fields (the number of fields is by definition equal to the -number of entries in the Field Start Offsets Table). -@item -If 1byte_offs_flag equals 0, then let X = X * 2 because there are -two bytes for each entry instead of just one. -@item -Let X = X + 6, because the fixed size of Extra Bytes is 6. -@item -The start of the record is at (pointer value minus X). -@end itemize - -@subsection FIELD CONTENTS - -The Field Contents part of the record has all the data. Fields are -stored in the order they were defined in. -@* - -There are no markers between fields, and there is no marker or filler -at the end of a record. -@* - -Here's an example. -@itemize @bullet -@item -I made a table with this definition: -@*@* - -@strong{CREATE TABLE T - (FIELD1 VARCHAR(3), FIELD2 VARCHAR(3), FIELD3 VARCHAR(3)) - Type=InnoDB;} -@*@* - -To understand what follows, you must know that table T has six columns --- not three -- because InnoDB automatically added three "system -columns" at the start for its own housekeeping. It happens that these -system columns are the row ID, the transaction ID, and the rollback -pointer, but their values don't matter now. Regard them as three black -boxes. -@*@* - -@item -I put some rows in the table. My last three INSERTs were: -@*@* - -@strong{INSERT INTO T VALUES ('PP', 'PP', 'PP')} -@*@* - -@strong{INSERT INTO T VALUES ('Q', 'Q', 'Q')} -@*@* - -@strong{INSERT INTO T VALUES ('R', NULL, NULL)} -@*@* - -@item -I ran Borland's TDUMP to get a hexadecimal dump of -the contents of \mysql\data\ibdata1, which (in my case) is the -MySQL/InnoDB data file (on Windows). -@end itemize - -Here is an extract of the dump: - -@multitable @columnfractions .05 .95 - -@item @strong{Address Values In Hexadecimal} @tab @strong{Values In ASCII} -@item @code{0D4280: 00 00 2D 00 84 4F 4F 4F 4F 4F 4F 4F 4F 4F 19 17} -@tab @code{..-..OOOOOOOOO..} -@item @code{0D4290: 15 13 0C 06 00 00 78 0D 02 BF 00 00 00 00 04 21} -@tab @code{......x........!} -@item @code{0D42A0: 00 00 00 00 09 2A 80 00 00 00 2D 00 84 50 50 50} -@tab @code{.....*....-..PPP} -@item @code{0D42B0: 50 50 50 16 15 14 13 0C 06 00 00 80 0D 02 E1 00} -@tab @code{PPP.............} -@item @code{0D42C0: 00 00 00 04 22 00 00 00 00 09 2B 80 00 00 00 2D} -@tab @code{....".....+....-} -@item @code{0D42D0: 00 84 51 51 51 94 94 14 13 0C 06 00 00 88 0D 00} -@tab @code{..QQQ...........} -@item @code{0D42E0: 74 00 00 00 00 04 23 00 00 00 00 09 2C 80 00 00} -@tab @code{t.....#.....,...} -@item @code{0D42F0: 00 2D 00 84 52 00 00 00 00 00 00 00 00 00 00 00} -@tab @code{.-..R...........} - -@end multitable - -A reformatted version of the dump, showing only the relevant bytes, -looks like this (I've put a line break after each field and added labels): - -@strong{Reformatted Hexadecimal Dump}@* -@code{ - 19 17 15 13 0C 06 Field Start Offsets /* First Row */@* - 00 00 78 0D 02 BF Extra Bytes@* - 00 00 00 00 04 21 System Column #1@* - 00 00 00 00 09 2A System Column #2@* - 80 00 00 00 2D 00 84 System Column #3@* - 50 50 Field1 'PP'@* - 50 50 Field2 'PP'@* - 50 50 Field3 'PP'}@* - -@code{ - 16 15 14 13 0C 06 Field Start Offsets /* Second Row */@* - 00 00 80 0D 02 E1 Extra Bytes@* - 00 00 00 00 04 22 System Column #1@* - 00 00 00 00 09 2B 80 System Column #2@* - 00 00 00 2D 00 84 System Column #3@* - 51 Field1 'Q'@* - 51 Field2 'Q'@* - 51 Field3 'Q'}@* - -@code{ - 94 94 14 13 0C 06 Field Start Offsets /* Third Row */@* - 00 00 88 0D 00 74 Extra Bytes@* - 00 00 00 00 04 23 System Column #1@* - 00 00 00 00 09 2C System Column #2@* - 80 00 00 00 2D 00 84 System Column #3@* - 52 Field1 'R'}@* -@* - -You won't need explanation if you followed everything I've said, but -I'll add helpful notes for the three trickiest details. -@itemize @bullet -@item -Helpful Notes About "Field Start Offsets": @* -Notice that the sizes of the record's fields, in forward order, are: -6, 6, 7, 2, 2, 2. Since each offset is for the start of the "next" -field, the hexadecimal offsets are 06, 0c (6+6), 13 (6+6+7), 15 -(6+6+7+2), 17 (6+6+7+2+2), 19 (6+6+7+2+2+2). Reversing the order, the -Field Start Offsets of the first record are: @code{19,17,15,13,0c,06}. -@item -Helpful Notes About "Extra Bytes": @* -Look at the Extra Bytes of the first record: @code{00 00 78 0D 02 BF}. The -fourth byte is @code{0D hexadecimal}, which is @code{1101 binary} ... the 110 is the -last bits of n_fields (@code{110 binary} is 6 which is indeed the number of -fields in the record) and the final 1 bit is 1byte_offs_flag. The -fifth and sixth bytes, which contain @code{02 BF}, constitute the "next" -field. Looking at the original hexadecimal dump, at address -@code{0D42BF} (which is position @code{02BF} within the page), you'll see the beginning bytes of -System Column #1 of the second row. In other words, the "next" field -points to the "Origin" of the following row. -@item -Helpful Notes About NULLs:@* -For the third row, I inserted NULLs in FIELD2 and FIELD3. Therefore in -the Field Start Offsets the top bit is @code{on} for these fields (the -values are @code{94 hexadecimal}, @code{94 hexadecimal}, instead of -@code{14 hexadecimal}, @code{14 hexadecimal}). And the row is -shorter because the NULLs take no space. -@end itemize - -@section Where to Look For More Information - -@strong{References:} @* -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 -@chapter InnoDB Page Structure - -InnoDB stores all records inside a fixed-size unit which is commonly called a -"page" (though InnoDB sometimes calls it a "block" instead). -Currently all pages are the same size, 16KB. -@* - -A page contains records, but it also contains headers and trailers. -I'll start this description with a high-altitude view of a page's parts, -then I'll describe each part of a page. Finally, I'll show an example. This -discussion deals only with the most common format, for the leaf page of a data file. -@* - -@section High-Altitude View - -An InnoDB page has seven parts: -@itemize @bullet -@item -Fil Header -@item -Page Header -@item -Infimum + Supremum Records -@item -User Records -@item -Free Space -@item -Page Directory -@item -Fil Trailer -@end itemize - -As you can see, a page has two header/trailer pairs. The inner pair, "Page Header" and -"Page Directory", are mostly the concern of the \page program group, -while the outer pair, "Fil Header" and "Fil Trailer", are mostly the -concern of the \fil program group. The "Fil" header also goes goes by -the name of "File Page Header". -@* - -Sandwiched between the headers and trailers, are the records and -the free (unused) space. A page always begins with two unchanging -records called the Infimum and the Supremum. Then come the user -records. Between the user records (which grow downwards) and the page -directory (which grows upwards) there is space for new records. -@* - -@subsection Fil Header - -The Fil Header has eight parts, as follows: - -@multitable @columnfractions .10 .30 .35 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Remarks} -@item FIL_PAGE_SPACE -@tab 4 -@tab 4 ID of the space the page is in -@item FIL_PAGE_OFFSET -@tab 4 -@tab ordinal page number from start of space -@item FIL_PAGE_PREV -@tab 4 -@tab offset of previous page in key order -@item FIL_PAGE_NEXT -@tab 4 -@tab offset of next page in key order -@item FIL_PAGE_LSN -@tab 8 -@tab log serial number of page's latest log record -@item FIL_PAGE_TYPE -@tab 2 -@tab current defined types are: FIL_PAGE_INDEX, FIL_PAGE_UNDO_LOG, FIL_PAGE_INODE, FIL_PAGE_IBUF_FREE_LIST -@item FIL_PAGE_FILE_FLUSH_LSN -@tab 8 -@tab "the file has been flushed to disk at least up to this lsn" (log serial number), - valid only on the first page of the file -@item FIL_PAGE_ARCH_LOG_NO -@tab 4 -@tab the latest archived log file number at the time that FIL_PAGE_FILE_FLUSH_LSN was written (in the log) -@end multitable - -@itemize -@item -FIL_PAGE_SPACE is a necessary identifier because different pages might belong to -different (table) spaces within the same file. The word -"space" is generic jargon for either "log" or "tablespace". -@*@* - -@item -FIL_PAGE_PREV and FIL_PAGE_NEXT are the page's "backward" and -"forward" pointers. To show what they're about, I'll draw a two-level -B-tree. -@*@* - -@example - -------- - - root - - -------- - | - ---------------------- - | | - | | - -------- -------- - - leaf - <--> - leaf - - -------- -------- -@end example -@* - -Everyone has seen a B-tree and knows that the entries in the root page -point to the leaf pages. (I indicate those pointers with vertical '|' -bars in the drawing.) But sometimes people miss the detail that leaf -pages can also point to each other (I indicate those pointers with a horizontal -two-way pointer '<-->' in the drawing). This feature allows InnoDB to navigate from -leaf to leaf without having to back up to the root level. This is a -sophistication which you won't find in the classic B-tree, which is -why InnoDB should perhaps be called a B+-tree instead. -@*@* - -@item -The fields FIL_PAGE_FILE_FLUSH_LSN, FIL_PAGE_PREV, and FIL_PAGE_NEXT -all have to do with logs, so I'll refer you to my article "How Logs -Work With MySQL And InnoDB" on devarticles.com. -@*@* - -@item -FIL_PAGE_FILE_FLUSH_LSN and FIL_PAGE_ARCH_LOG_NO are only valid for -the first page of a data file. -@end itemize - -@subsection Page Header - -The Page Header has 14 parts, as follows: -@*@* - -@multitable @columnfractions .10 .20 .30 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Remarks} -@item PAGE_N_DIR_SLOTS -@tab 2 -@tab number of directory slots in the Page Directory part; initial value = 2 -@item PAGE_HEAP_TOP -@tab 2 -@tab record pointer to first record in heap -@item PAGE_N_HEAP -@tab 2 -@tab number of heap records; initial value = 2 -@item PAGE_FREE -@tab 2 -@tab record pointer to first free record -@item PAGE_GARBAGE -@tab 2 -@tab "number of bytes in deleted records" -@item PAGE_LAST_INSERT -@tab 2 -@tab record pointer to the last inserted record -@item PAGE_DIRECTION -@tab 2 -@tab either PAGE_LEFT, PAGE_RIGHT, or PAGE_NO_DIRECTION -@item PAGE_N_DIRECTION -@tab 2 -@tab number of consecutive inserts in the same direction, e.g. "last 5 were all to the left" -@item PAGE_N_RECS -@tab 2 -@tab number of user records -@item PAGE_MAX_TRX_ID -@tab 8 -@tab the highest ID of a transaction which might have changed a record on the page (only set for secondary indexes) -@item PAGE_LEVEL -@tab 2 -@tab level within the index (0 for a leaf page) -@item PAGE_INDEX_ID -@tab 8 -@tab identifier of the index the page belongs to -@item PAGE_BTR_SEG_LEAF -@tab 10 -@tab "file segment header for the leaf pages in a B-tree" (this is irrelevant here) -@item PAGE_BTR_SEG_TOP -@tab 10 -@tab "file segment header for the non-leaf pages in a B-tree" (this is irrelevant here) - -@end multitable -@* - -(Note: I'll clarify what a "heap" is when I discuss the User Records part of the page.) -@*@* - -Some of the Page Header parts require further explanation: -@itemize @bullet -@item -PAGE_FREE: @* -Records which have been freed (due to deletion or migration) are in a -one-way linked list. The PAGE_FREE pointer in the page header points -to the first record in the list. The "next" pointer in the record -header (specifically, in the record's Extra Bytes) points to the next -record in the list. -@item -PAGE_DIRECTION and PAGE_N_DIRECTION: @* -It's useful to know whether inserts are coming in a constantly -ascending sequence. That can affect InnoDB's efficiency. -@item -PAGE_HEAP_TOP and PAGE_FREE and PAGE_LAST_INSERT: @* -Warning: Like all record pointers, these point not to the beginning of the -record but to its Origin (see the earlier discussion of Record -Structure). -@item -PAGE_BTR_SEG_LEAF and PAGE_BTR_SEG_TOP: @* -These variables contain information (space ID, page number, and byte offset) about -index node file segments. InnoDB uses the information for allocating new pages. -There are two different variables because InnoDB allocates separately for leaf -pages and upper-level pages. -@end itemize - -@subsection The Infimum And Supremum Records - -"Infimum" and "supremum" are real English words but they are found -only in arcane mathematical treatises, and in InnoDB comments. To -InnoDB, an infimum is lower than the the lowest possible real value -(negative infinity) and a supremum is greater than the greatest -possible real value (positive infinity). InnoDB sets up an infimum -record and a supremum record automatically at page-create time, and -never deletes them. They make a useful barrier to navigation so that -"get-prev" won't pass the beginning and "get-next" won't pass the end. -Also, the infimum record can be a dummy target for temporary record -locks. -@*@* - -The InnoDB code comments distinguish between "the infimum and supremum -records" and the "user records" (all other kinds). -@*@* - -It's sometimes unclear whether InnoDB considers the infimum and -supremum to be part of the header or not. Their size is fixed and -their position is fixed, so I guess so. - -@subsection User Records - -In the User Records part of a page, you'll find all the records that the user -inserted. -@*@* - -There are two ways to navigate through the user records, depending -whether you want to think of their organization as an unordered or an -ordered list. -@*@* - -An unordered list is often called a "heap". If you make a pile of -stones by saying "whichever one I happen to pick up next will go on -top" -- rather than organizing them according to size and colour -- -then you end up with a heap. Similarly, InnoDB does not want to insert -new rows according to the B-tree's key order (that would involve -expensive shifting of large amounts of data), so it inserts new rows -right after the end of the existing rows (at the -top of the Free Space part) or wherever there's space left by a -deleted row. -@*@* - -But by definition the records of a B-tree must be accessible in order -by key value, so there is a record pointer in each record (the "next" -field in the Extra Bytes) which points to the next record in key -order. In other words, the records are a one-way linked list. So -InnoDB can access rows in key order when searching. - -@subsection Free Space - -I think it's clear what the Free Space part of a page is, from the discussion of -other parts. - -@subsection Page Directory - -The Page Directory part of a page has a variable number of record pointers. -Sometimes the record pointers are called "slots" or "directory slots". -Unlike other DBMSs, InnoDB does not have a slot for every record in -the page. Instead it keeps a sparse directory. In a fullish page, -there will be one slot for every six records. -@*@* - -The slots track the records' logical order (the order by key rather -than the order by placement on the heap). Therefore, if the records -are @code{'A' 'B' 'F' 'D'} the slots will be @code{(pointer to 'A') (pointer to -'B') (pointer to 'D') (pointer to 'F')}. Because the slots are in key -order, and each slot has a fixed size, it's easy to do a binary -search of the records on the page via the slots. -@*@* - -(Since the Page Directory does not have a slot for every record, -binary search can only give a rough position and then InnoDB must -follow the "next" record pointers. InnoDB's "sparse slots" policy also -accounts for the n_owned field in the Extra Bytes part of a record: -n_owned indicates how many more records must be gone through because -they don't have their own slots.) - -@subsection Fil Trailer - -The Fil Trailer has one part, as follows: -@*@* - -@multitable @columnfractions .10 .35 .40 - -@item @strong{Name} @tab @strong{Size} @tab @strong{Remarks} -@item FIL_PAGE_END_LSN -@tab 8 -@tab low 4 bytes = checksum of page, last 4 bytes = same as FIL_PAGE_LSN -@end multitable -@* - -The final part of a page, the fil trailer (or File Page Trailer), -exists because InnoDB's architect worried about integrity. It's -impossible for a page to be only half-written, or corrupted by -crashes, because the log-recovery mechanism restores to a consistent -state. But if something goes really wrong, then it's nice to have a -checksum, and to have a value at the very end of the page which must -be the same as a value at the very beginning of the page. - -@section Example - -For this example, I used Borland's TDUMP again, as I did for the earlier chapter on -Record Format. This is what a page looked like: -@*@* - -@multitable @columnfractions .05 .95 - -@item @strong{Address Values In Hexadecimal} @tab @strong{Values In ASCII} -@item @code{0D4000: 00 00 00 00 00 00 00 35 FF FF FF FF FF FF FF FF} -@tab @code{.......5........} -@item @code{0D4010: 00 00 00 00 00 00 E2 64 45 BF 00 00 00 00 00 00} -@tab @code{.......dE.......} -@item @code{0D4020: 00 00 00 00 00 00 00 05 02 F5 00 12 00 00 00 00} -@tab @code{................} -@item @code{0D4030: 02 E1 00 02 00 0F 00 10 00 00 00 00 00 00 00 00} -@tab @code{................} -@item @code{0D4040: 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00} -@tab @code{................} -@item @code{0D4050: 00 02 16 B2 00 00 00 00 00 00 00 02 15 F2 08 01} -@tab @code{................} -@item @code{0D4060: 00 00 03 00 89 69 6E 66 69 6D 75 6D 00 09 05 00} -@tab @code{.....infimum....} -@item @code{0D4070: 08 03 00 00 73 75 70 72 65 6D 75 6D 00 22 1D 18} -@tab @code{....supremum."..} -@item @code{0D4080: 13 0C 06 00 00 10 0D 00 B7 00 00 00 00 04 14 00} -@tab @code{................} -@item @code{0D4090: 00 00 00 09 1D 80 00 00 00 2D 00 84 41 41 41 41} -@tab @code{.........-..AAAA} -@item @code{0D40A0: 41 41 41 41 41 41 41 41 41 41 41 1F 1B 17 13 0C} -@tab @code{AAAAAAAAAAA.....} -@item @code{ ... } -@item @code{ ... } -@item @code{0D7FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 74} -@tab @code{...............t} -@item @code{0D7FF0: 02 47 01 AA 01 0A 00 65 3A E0 AA 71 00 00 E2 64} -@tab @code{.G.....e:..q...d} -@end multitable -@*@* - -Let's skip past the first 38 bytes, which are Fil Header. The bytes -of the Page Header start at location @code{0d4026 hexadecimal}: -@*@* - -@multitable @columnfractions .10 .45 .60 - -@item @strong{Location} @tab @strong{Name} @tab @strong{Description} -@item @code{00 05} -@tab PAGE_N_DIR_SLOTS -@tab There are 5 directory slots. -@item @code{02 F5} -@tab PAGE_HEAP_TOP -@tab At location @code{0402F5}, not shown, is the beginning of free space. -Maybe a better name would have been PAGE_HEAP_END -@item @code{00 12} -@tab PAGE_N_HEAP -@tab There are 18 (hexadecimal 12) records in the page. -@item @code{00 00} -@tab PAGE_FREE -@tab There are zero free (deleted) records. -@item @code{00 00} -@tab PAGE_GARBAGE -@tab There are zero bytes in deleted records. -@item @code{02 E1} -@tab PAGE_LAST_INSERT -@tab The last record was inserted at location @code{02E1}, not shown, within the page. -@item @code{00 02} -@tab PAGE_DIRECTION -@tab A glance at page0page.h will tell you that 2 is the #defined value for PAGE_RIGHT. -@item @code{00 0F} -@tab PAGE_N_DIRECTION -@tab The last 15 (hexadecimal 0F) inserts were all done "to the right" -because I was inserting in ascending order. -@item @code{00 10} -@tab PAGE_N_RECS -@tab There are 16 (hexadecimal 10) user records. Notice that PAGE_N_RECS is -smaller than the earlier field, PAGE_N_HEAP. -@item @code{00 00 00 00 00 00 00} -@tab PAGE_MAX_TRX_ID -@item @code{00 00} -@tab PAGE_LEVEL -@tab Zero because this is a leaf page. -@item @code{00 00 00 00 00 00 00 14} -@tab PAGE_INDEX_ID -@tab This is index number 20. -@item @code{00 00 00 00 00 00 00 02 16 B2} -@tab PAGE_BTR_SEG_LEAF -@item @code{00 00 00 00 00 00 00 02 15 F2} -@tab PAGE_BTR_SEG_TOP -@end multitable -@* - -Immediately after the page header are the infimum and supremum -records. Looking at the "Values In ASCII" column in the hexadecimal -dump, you will see that the contents are in fact the words "infimum" -and "supremum" respectively. -@*@* - -Skipping past the User Records and the Free Space, many bytes later, -is the end of the 16KB page. The values shown there are the two trailers. -@itemize @bullet -@item -The first trailer (@code{00 74, 02 47, 01 AA, 01 0A, 00 65}) is the page -directory. It has 5 entries, because the header field PAGE_N_DIR_SLOTS -says there are 5. -@item -The next trailer (@code{3A E0 AA 71, 00 00 E2 64}) is the fil trailer. Notice -that the last four bytes, @code{00 00 E2 64}, appeared before in the fil -header. -@end itemize - -@section Where to Look For More Information - -@strong{References:} @* -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 -@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 -source code of MySQL. This description begins with a list -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. - -@section Directory Listing - -@strong{Directory -- Short Comment} -@itemize @bullet -@item -bdb -- The Berkeley Database table handler -@item -BitKeeper -- BitKeeper administration (not part of the source distribution) -@item -BUILD -- Frequently used build scripts -@item -Build-tools -- Build tools (not part of the source distribution) -@item -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; will eventually be moved to the mysqldoc repository -@item -extra -- Some minor standalone utility programs -@item -heap -- The HEAP table handler -@item -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 -libmysql -- For producing MySQL as a library (e.g. a Windows .DLL) -@item -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 -myisam -- The MyISAM table handler -@item -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.) -@item -netware -- Files related to the Novell NetWare version of MySQL -@item -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 (not currently used) -@item -regex -- Henry Spencer's Regular Expression library for support of REGEXP function -@item -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 -@item -sql-bench -- The MySQL benchmarks -@item -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 and in C -@item -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 -@end itemize - -@subsection bdb - -The Berkeley Database table handler. -@*@* - -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 -http://www.sleepycat.com/docs/. Since it's reasonably thorough -documentation, a description of the BDB program files is not included -in this document. -@*@* - -@subsection BitKeeper - -BitKeeper administration. -@*@* - -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. Please see @url{http://www.mysql.com/doc/en/Installing_source_tree.html} -for more information. -@*@* - -@subsection BUILD - -Frequently used build scripts. -@*@* - -This directory contains the build switches for compilation on various -platforms. There is a subdirectory for each set of options. The main -ones are: -@itemize @bullet -@item -alpha -@item -ia64 -@item -pentium (with and without debug or bdb, etc.) -@item -solaris -@end itemize -@*@* - -@subsection Build-tools - -Build tools. -@*@* - -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 - -Client library. -@*@* - -The client library includes mysql.cc (the source of the 'mysql' -executable) and other utilities. Most of the utilities are mentioned -in the MySQL Reference Manual. Generally these are standalone C -programs which one runs in "client mode", that is, they call the -server. -@*@* - -The C program files in the directory are: -@itemize @bullet -@item -get_password.c -- ask for a password from the console -@item -mysql.cc -- "The MySQL command tool" -@item -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, suitable to backup a MySQL database -@item -mysqlimport.c -- import text files in different formats into tables -@item -mysqlmanager-pwgen.c -- pwgen stands for "password generation" (not currently maintained) -@item -mysqlmanagerc.c -- entry point for mysql manager (not currently maintained) -@item -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 (version 4.1 and up) -@end itemize -@*@* - -@subsection cmd-line-utils - -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 -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. -@*@* - -The \readline subdirectory contains the files of the GNU Readline -Library, "a library for reading lines of text with interactive input -and history editing". The programs are copyrighted by the Free -Software Foundation. -@*@* - -The \libedit (library of edit functions) subdirectory has files -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 -@item -common.c -- common editor functions -@item -el.c -- editline interface functions -@item -emacs.c -- emacs functions -@item -fgetln.c -- get line -@item -hist.c -- history access functions -@item -history.c -- more history access functions -@item -key.c -- procedures for maintaining the extended-key map -@item -map.c -- editor function definitions -@item -parse.c -- parse an editline extended command -@item -prompt.c -- prompt printing functions -@item -read.c -- terminal read functions -@item -readline.c -- read line -@item -refresh.c -- "lower level screen refreshing functions" -@item -search.c -- "history and character search functions" -@item -sig.c -- for signal handling -@item -strlcpy.c -- string copy -@item -term.c -- "editor/termcap-curses interface" -@item -tokenizer.c -- Bourne shell line tokenizer -@item -tty.c -- for a tty interface -@item -vi.c -- commands used when in the vi (editor) mode -@end itemize -@*@* - -@subsection dbug - -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 -package. -@*@* - -How it works: One inserts a function call that begins with DBUG_* in -one of the regular MYSQL programs. For example, in get_password.c, you -will find this line: @* -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 -(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 -@item -dbug_analyze.c -- Reads a file produced by trace functions -@item -example1.c -- A tiny example -@item -example2.c -- A tiny example -@item -example3.c -- A tiny example -@item -factorial.c -- A tiny example -@item -main.c -- A tiny example -@item -sanity.c -- Declaration of a variable -@end itemize -@*@* - -@subsection Docs - -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. 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 -@item -flags -- images of flags of countries -@item -images -- flag backgrounds and the MySQL dolphin logo -@item -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 -@item -to-be-included... -- contains a MySQL-for-dummies file -@item -translations -- some Portuguese myodbc documentation -@end itemize -@*@* - -In the main directory, you'll find some .txt files related to the -methods that MySQL uses to produce its printed and html documents, odd -bits in various languages, and the single file in the directory which -has any importance -- internals.texi -- The "MySQL Internals" -document. -@*@* - -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 - -Some minor standalone utility programs. -@*@* - -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: -@itemize @bullet -@item -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_waitpid.c -- wait for a program to terminate. Useful for shell scripts when one needs to wait until a process terminates. -@item -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 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 -@end itemize -@*@* - -@subsection heap - -The HEAP table handler. -@*@* - -All the MySQL table handlers (i.e. the handlers that MySQL itself -produces) have files with similar names and functions. Thus, this -(heap) directory contains a lot of duplication of the myisam directory -(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. (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 -@item -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 -@item -hp_create.c -- * create a table -@item -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 -@item -hp_info.c -- * Information about database status -@item -hp_open.c -- * open database -@item -hp_panic.c -- * the hp_panic routine, for shutdowns and flushes -@item -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 -@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 -@item -hp_rrnd.c -- * read a row based on position -@item -hp_rsame.c -- * find current row using positional read or key-based -read -@item -hp_scan.c -- * read all rows sequentially -@item -hp_static.c -- * static variables (very short) -@item -hp_test1.c -- * testing basic functions -@item -hp_test2.c -- * testing database and storing results -@item -hp_update.c -- * update an existing row -@item -hp_write.c -- * insert a new row -@end itemize -@*@* - -There are fewer files in the heap directory than in the myisam -directory, because fewer are necessary. For example, there is no need -for a \myisam\mi_cache.c equivalent (to cache reads) or a -\myisam\log.c equivalent (to log statements). -@*@* - -@subsection include - -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 -individual directory will also have its own *.h files, for including -in its own *.c programs. The *.h files in the include directory are -ones that might be included from more than one place. -@*@* - -For example, the mysys directory contains a C file named rijndael.c, -but does not include rijndael.h. The include directory contains -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 (header) files. -@*@* - -@subsection innobase - -The Innobase (InnoDB) table handler. -@*@* - -A full description of these files can be found elsewhere in this -document. -@*@* - -@subsection libmysql - -The MySQL Library, Part 1. -@*@* - -The files here are for producing MySQL as a library (e.g. a Windows -DLL). The idea is that, instead of producing separate mysql (client) -and mysqld (server) programs, one produces a library. Instead of -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). -@*@* - -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 -@item -dll.c -- initialization of the dll library -@item -errmsg.c -- English error messages, compare \mysys\errors.c -@item -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 -@end itemize -@*@* - -@subsection libmysql_r - -The MySQL Library, Part 2. -@*@* - -There is only one file here, used to build a thread-safe libmysql library: -@itemize @bullet -@item -makefile.am -@end itemize -@*@* - -@subsection libmysqld - -The MySQL library, Part 3. -@*@* - -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 -libmysqld.c -- The called side, compare the mysqld.exe source -@item -lib_vio.c -- Emulate the vio directory's communication buffer -@end itemize -@*@* - -@subsection man - -Some user-contributed manual pages -@*@* - -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 - -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 -@item -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 -@item -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 -@item -sort.c -- this is a single file that sorts keys for index-create purposes -@end itemize -@*@* - -The "full text" and "rtree" and "spatial" program sets are for special -purposes, so this document focuses only on the mi*.c "myisam" C -programs. They are: -@itemize @bullet -@item -mi_cache.c -- for reading records from a cache -@item -mi_changed.c -- a single routine for setting a "changed" flag (very short) -@item -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 -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) -@item -mi_delete.c -- delete a row -@item -mi_delete_all.c -- delete all rows -@item -mi_delete_table.c -- delete a table (very short) -@item -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 -- return useful base information for an open table -@item -mi_key.c -- for handling keys -@item -mi_locking.c -- lock database -@item -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 -@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 -@item -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 -@item -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 -@item -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 -@item -mi_rsame.c -- find current row using positional read or key-based read -@item -mi_rsamepos.c -- positional read -@item -mi_scan.c -- read all rows sequentially -@item -mi_search.c -- key-handling functions -@item -mi_static.c -- static variables (very short) -@item -mi_statrec.c -- functions to handle fixed-length records -@item -mi_test1.c -- testing basic functions -@item -mi_test2.c -- testing database and storing results -@item -mi_test3.c -- testing locking -@item -mi_unique.c -- functions to check if a row is unique -@item -mi_update.c -- update an existing row -@item -mi_write.c -- insert a new row -@end itemize -@*@* - -@subsection myisammrg - -MyISAM Merge table handler. -@*@* - -As with other table handlers, you'll find that the *.c files in the -myissammrg directory have counterparts in the myisam directory. In -fact, this general description of a myisammrg program is almost always -true: The myisammrg -function checks an argument, the myisammrg function formulates an -expression for passing to a myisam function, the myisammrg calls a -myisam function, the myisammrg function returns. -@*@* - -These are the 21 files in the myisammrg directory, with notes about -the myisam functions or programs they're connected with: -@itemize @bullet -@item -myrg_close.c -- mi_close.c -@item -myrg_create.c -- mi_create.c -@item -myrg_delete.c -- mi_delete.c / delete last-read record -@item -myrg_extra.c -- mi_extra.c / "extra functions we want to do ..." -@item -myrg_info.c -- mi_info.c / display information about a mymerge file -@item -myrg_locking.c -- mi_locking.c / lock databases -@item -myrg_open.c -- mi_open.c / open a MyISAM MERGE table -@item -myrg_panic.c -- mi_panic.c / close in a hurry -@item -myrg_queue.c -- read record based on a key -@item -myrg_range.c -- mi_range.c / find records in a range -@item -myrg_rfirst.c -- mi_rfirst.c / read first record according to -specific key -@item -myrg_rkey.c -- mi_rkey.c / read record based on a key -@item -myrg_rlast.c -- mi_rlast.c / read last row with same key as previous -read -@item -myrg_rnext.c -- mi_rnext.c / read next row with same key as previous -read -@item -myrg_rnext_same.c -- mi_rnext_same.c / read next row with same key -@item -myrg_rprev.c -- mi_rprev.c / read previous row with same key -@item -myrg_rrnd.c -- mi_rrnd.c / read record with random access -@item -myrg_rsame.c -- mi_rsame.c / call mi_rsame function, see -\myisam\mi_rsame.c -@item -myrg_static.c -- mi_static.c / static variable declaration -@item -myrg_update.c -- mi_update.c / call mi_update function, see -\myisam\mi_update.c -@item -myrg_write.c -- mi_write.c / call mi_write function, see -\myisam\mi_write.c -@end itemize -@*@* - -@subsection mysql-test - -A test suite for mysqld. -@*@* - -The directory has a README file which explains how to run the tests, -how to make new tests (in files with the filename extension "*.test"), -and how to report errors. -@*@* - -There are four subdirectories: -@itemize @bullet -@item -\misc -- contains one minor Perl program -@item -\r -- contains *.result, i.e. "what happened" files and -*.required, i.e. "what should happen" file -@item -\std_data -- contains standard data for input to tests -@item -\t -- contains tests -@end itemize -@*@* - -There are 186 *.test files in the \t subdirectory. Primarily these are -SQL scripts which try out a feature, output a result, and compare the -result with what's required. Some samples of what the test files check -are: latin1_de comparisons, date additions, the HAVING clause, outer -joins, openSSL, load data, logging, truncate, and UNION. -@*@* - -There are other tests in these directories: -@itemize @bullet -@item -sql-bench -@item -tests -@end itemize - -@subsection mysys - -MySQL system library. Low level routines for file access and so on. -@*@* - -There are 115 *.c programs in this directory: -@itemize @bullet -@item -array.c -- Dynamic array handling -@item -charset.c -- Using dynamic character sets, set default character set, ... -@item -charset2html.c -- Check what character set a browser is using -@item -checksum.c -- Calculate checksum for a memory block, used for pack_isam -@item -default.c -- Find defaults from *.cnf or *.ini files -@item -errors.c -- English text of global errors -@item -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" -@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 (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" -@item -mf_dirname.c -- Parse/convert directory names -@item -mf_fn_ext.c -- Get filename extension -@item -mf_format.c -- Format a filename -@item -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 -@item -mf_iocache2.c -- Continuation of mf_iocache.c -@item -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 -@item -mf_qsort.c -- Quicksort -@item -mf_qsort2.c -- Quicksort, part 2 (allows the passing of an extra argument to the sort-compare routine) -@item -mf_radix.c -- Radix sort -@item -mf_same.c -- Determine whether filenames are the same -@item -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) -@item -mf_strip.c -- Strip trail spaces from a string -@item -mf_tempdir.c -- Initialize/find/free temporary directory -@item -mf_tempfile.c -- Create a temporary file -@item -mf_unixpath.c -- Convert filename to UNIX-style filename -@item -mf_util.c -- Routines, #ifdef'd, which may be missing on some -machines -@item -mf_wcomp.c -- Comparisons with wildcards -@item -mf_wfile.c -- Finding files with wildcards -@item -mulalloc.c -- Malloc many pointers at the same time -@item -my_aes.c -- AES encryption -@item -my_alarm.c -- Set a variable value when an alarm is received -@item -my_alloc.c -- malloc of results which will be freed simultaneously -@item -my_append.c -- one file to another -@item -my_bit.c -- smallest X where 2^X >= value, maybe useful for -divisions -@item -my_bitmap.c -- Handle uchar arrays as large bitmaps -@item -my_chsize.c -- Truncate file if shorter, else fill with a filler -character -@item -my_clock.c -- Time-of-day ("clock()") function, with OS-dependent -#ifdef's -@item -my_compress.c -- Compress packet (see also description of \zlib -directory) -@item -my_copy.c -- Copy files -@item -my_create.c -- Create file -@item -my_delete.c -- Delete file -@item -my_div.c -- Get file's name -@item -my_dup.c -- Open a duplicated file -@item -my_error.c -- Return formatted error to user -@item -my_fopen.c -- File open -@item -my_fstream.c -- Streaming file read/write -@item -my_getwd.c -- Get working directory -@item -my_gethostbyname.c -- Thread-safe version of standard net -gethostbyname() func -@item -my_getopt.c -- Find out what options are in effect -@item -my_handler.c -- Compare two keys in various possible formats -@item -my_init.c -- Initialize variables and functions in the mysys library -@item -my_lib.c -- Compare/convert directory names and file names -@item -my_lock.c -- Lock part of a file -@item -my_lockmem.c -- "Allocate a block of locked memory" -@item -my_lread.c -- Read a specified number of bytes from a file into -memory -@item -my_lwrite.c -- Write a specified number of bytes from memory into a -file -@item -my_malloc.c -- Malloc (memory allocate) and dup functions -@item -my_messnc.c -- Put out a message on stderr with "no curses" -@item -my_mkdir.c -- Make directory -@item -my_net.c -- Thread-safe version of net inet_ntoa function -@item -my_netware.c -- Functions used only with the Novell Netware version -of MySQL -@item -my_once.c -- Allocation / duplication for "things we don't need to -free" -@item -my_open.c -- Open a file -@item -my_os2cond.c -- OS2-specific: "A simple implementation of posix conditions" -@item -my_os2dirsrch.c -- OS2-specific: Emulate a Win32 directory search -@item -my_os2dlfcn.c -- OS2-specific: Emulate UNIX dynamic loading -@item -my_os2file64.c -- OS2-specific: For File64bit setting -@item -my_os2mutex.c -- OS2-specific: For mutex handling -@item -my_os2thread.c -- OS2-specific: For thread handling -@item -my_os2tls.c -- OS2-specific: For thread-local storage -@item -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 -@item -my_quick.c -- Read/write (labelled a "quicker" interface, perhaps -obsolete) -@item -my_read.c -- Read a specified number of bytes from a file, possibly -retry -@item -my_realloc.c -- Reallocate memory allocated with my_alloc.c -(probably) -@item -my_redel.c -- Rename and delete file -@item -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 -@item -my_sleep.c -- Wait n microseconds -@item -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 -@item -my_tempnam.c -- Obsolete temporary-filename routine used by ISAM table handler -@item -my_thr_init.c -- initialize/allocate "all mysys & debug thread variables" -@item -my_wincond.c -- Windows-specific: emulate Posix conditions -@item -my_winsem.c -- Windows-specific: emulate Posix threads -@item -my_winthread.c -- Windows-specific: emulate Posix threads -@item -my_write.c -- Write a specified number of bytes to a file -@item -ptr_cmp.c -- Point to an optimal byte-comparison function -@item -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") -@item -safemalloc.c -- A version of the standard malloc() with safety checking -@item -sha1.c -- Implementation of Secure Hashing Algorithm 1 -@item -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 -@item -test_charset.c -- Standalone program: display character set information -@item -test_dir.c -- Standalone program: placeholder for "test all functions" idea -@item -test_fn.c -- Standalone program: apparently tests a function -@item -test_xml.c -- Standalone program: test XML routines -@item -thr_alarm.c -- Thread alarms and signal handling -@item -thr_lock.c -- "Read and write locks for Posix threads" -@item -thr_mutex.c -- A wrapper for mutex functions -@item -thr_rwlock.c -- Synchronizes the readers' thread locks with the writer's lock -@item -tree.c -- Initialize/search/free binary trees -@item -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: -@*@* - -@example -"int my_getwd _A((string buf, uint size, myf MyFlags)); @* - int my_setwd _A((const char *dir, myf MyFlags)); @* - Get and set working directory." @* -@end example - -@subsection netware - -Files related to the Novell NetWare version of MySQL. -@*@* - -There are 39 files on this directory. Most have filename extensions of -*.def, *.sql, or *.c. -@*@* - -The twenty-five *.def files are all from Novell Inc. They contain import or -export symbols. (".def" is a common filename extension for -"definition".) -@*@* - -The two *.sql files are short scripts of SQL statements used in -testing. -@*@* - -These are the five *.c files, all from Novell Inc.: -@itemize @bullet -@item -libmysqlmain.c -- Only one function: init_available_charsets() -@item -my_manage.c -- Standalone management utility -@item -mysql_install_db.c -- Compare \scripts\mysql_install_db.sh -@item -mysql_test_run.c -- Short test program -@item -mysqld_safe.c -- Compare \scripts\mysqld_safe.sh -@end itemize - -Perhaps the most important file is: -@itemize @bullet -@item -netware.patch -- NetWare-specific build instructions and switches -(compare \mysql-4.1\ltmain.sh) -@end itemize -@*@* - -For instructions about basic installation, see "Deployment Guide For -NetWare AMP" at: -@url{http://developer.novell.com/ndk/whitepapers/namp.htm} -@* - -@subsection NEW-RPMS - -Directory to place RPMs while making a distribution. -@*@* - -This directory is not part of the Windows distribution. It is -a temporary directory used during RPM builds with Linux distributions. -@*@* - -@subsection os2 - -Routines for working with the OS2 operating system. -@*@* - -The files in this directory are the product of the efforts of three -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: -@itemize @bullet -@item -A Readme.Txt file -@item -An \include subdirectory containing .h files which are for OS/2 only -@item -Files used in the build process (configuration, switches, and one -.obj) -@end itemize -@*@* - -The README file refers to MySQL version 3.23, which suggests that -there have been no updates for MySQL 4.0 for this section. -@*@* - -@subsection pstack - -Process stack display (not currently used). -@*@* - -This is a set of publicly-available debugging aids which all do pretty -well the same thing: display the contents of the stack, along with -symbolic information, for a running process. There are versions for -various object file formats (such as ELF and IEEE-695). Most of the -programs are copyrighted by the Free Software Foundation and are -marked as "part of GNU Binutils". -@*@* - -In other words, the pstack files are not really part of the MySQL -library. They are merely useful when you re-program some MYSQL code -and it crashes. -@*@* - -@subsection regex - -Henry Spencer's Regular Expression library for support of REGEXP function. -@*@* - -This is the copyrighted product of Henry Spencer from the University -of Toronto. It's a fairly-well-known implementation of the -requirements of POSIX 1003.2 Section 2.8. The library is bundled with -Apache and is the default implementation for regular-expression -handling in BSD Unix. MySQL's Monty Widenius has made minor changes in -three programs (debug.c, engine.c, regexec.c) but this is not a MySQL -package. MySQL calls it only in order to support two MySQL functions: -REGEXP and RLIKE. -@*@* - -Some of Mr Spencer's documentation for the regex library can be found -in the README and WHATSNEW files. -@*@* - -One MySQL program which uses regex is \cmd-line-utils\libedit\search.c -@*@* - -This program calls the 'regcomp' function, which is the entry point in -\regex\regexp.c. -@*@* - -@subsection SCCS - -Source Code Control System (not part of source distribution). -@*@* - -You will see this directory if and only if you used BitKeeper for -downloading the source. The files here are for BitKeeper -administration and are not of interest to application programmers. -@*@* - -@subsection scripts - -SQL batches, e.g. mysqlbug and mysql_install_db. -@*@* - -The *.sh filename extension stands for "shell script". Linux -programmers use it where Windows programmers would use a *.bat -(batch filename extension). -@*@* - -The *.sh files on this directory are: -@itemize @bullet -@item -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 (partly) mSQL programs and scripts to MySQL -@item -mysqlbug.sh -- Create a bug report and mail it -@item -mysqld_multi.sh -- Start/stop any number of mysqld instances -@item -mysqld_safe-watch.sh -- Start/restart in safe mode -@item -mysqld_safe.sh -- Start/restart in safe mode -@item -mysqldumpslow.sh -- Parse and summarize the slow query log -@item -mysqlhotcopy.sh -- Hot backup -@item -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 -@item -mysql_explain_log.sh -- Put a log (made with --log) into a MySQL table -@item -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. 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. -@item -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 -mysql_zap.sh -- Kill processes which match pattern -@end itemize -@*@* - -@subsection sql - -Programs for handling SQL commands. The "core" of MySQL. -@*@* - -These are the .c and .cc files in the sql directory: -@itemize @bullet -@item -convert.cc -- convert tables between different character sets -@item -derror.cc -- read language-dependent message file -@item -des_key_file.cc -- load DES keys from plaintext file -@item -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 -@item -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 -@item -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 -@item -ha_heap.cc -- Handler: Heap -@item -ha_innodb.cc -- Handler: InnoDB -@item -ha_isam.cc -- Handler: ISAM -@item -ha_isammrg.cc -- Handler: (ISAM MERGE) -@item -ha_myisam.cc -- Handler: MyISAM -@item -ha_myisammrg.cc -- Handler: (MyISAM MERGE) -@item -hostname.cc -- Given IP, return hostname -@item -init.cc -- Init and dummy functions for interface with unireg -@item -item.cc -- Item functions -@item -item_buff.cc -- Buffers to save and compare item values -@item -item_cmpfunc.cc -- Definition of all compare functions -@item -item_create.cc -- Create an item. Used by lex.h. -@item -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 -item_strfunc.cc -- String functions -@item -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 -key.cc -- Functions to create keys from records and compare a key to a key in a record -@item -lock.cc -- Locks -@item -log.cc -- Logs -@item -log_event.cc -- Log event (a binary log consists of a stream of log events) -@item -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; used by the replication code -@item -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 (like /mysys/my_lock.c, but with timeout handling for threads) -@item -net_serv.cc -- Read/write of packets on a network socket -@item -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 -opt_range.cc -- Range of keys -@item -opt_sum.cc -- Optimize functions in presence of (implied) GROUP BY -@item -password.c -- Password checking -@item -procedure.cc -- Procedure interface, as used in SELECT * FROM Table_name PROCEDURE ANALYSE -@item -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 -repl_failsafe.cc -- Replication fail-save (not yet implemented) -@item -set_var.cc -- Set and retrieve MySQL user variables -@item -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; checks, stores, retrieves, and deletes MySQL user level privileges -@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, like opening and closing tables with table cache management -@item -sql_cache.cc -- SQL query cache, with long comments about how caching works -@item -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 -sql_db.cc -- Create / drop database -@item -sql_delete.cc -- The DELETE statement -@item -sql_derived.cc -- Derived tables, with long comments -@item -sql_do.cc -- The DO statement -@item -sql_error.cc -- Errors and warnings -@item -sql_handler.cc -- Implements the HANDLER interface, which gives direct access to rows in MyISAM and InnoDB -@item -sql_help.cc -- The HELP statement -@item -sql_insert.cc -- The INSERT statement -@item -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 (the rest of the list class is implemented in sql_list.h) -@item -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; used with BDB table logs -@item -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, or use a prepared statement -@item -sql_repl.cc -- Replication -@item -sql_rename.cc -- Rename table -@item -sql_select.cc -- Select and join optimisation -@item -sql_show.cc -- The SHOW statement -@item -sql_string.cc -- String functions: alloc, realloc, copy, convert, etc. -@item -sql_table.cc -- The DROP TABLE and ALTER TABLE statements -@item -sql_test.cc -- Some debugging information -@item -sql_udf.cc -- User-defined functions -@item -sql_union.cc -- The UNION operator -@item -sql_update.cc -- The UPDATE statement -@item -stacktrace.c -- Display stack trace (Linux/Intel only) -@item -table.cc -- Table metadata retrieval; read the table definition from a .frm file and store it in a TABLE object -@item -thr_malloc.cc -- Thread-safe interface to /mysys/my_alloc.c -@item -time.cc -- Date and time functions -@item -udf_example.cc -- Example file of user-defined functions -@item -uniques.cc -- Function to handle quick removal of duplicates -@item -unireg.cc -- Create a unireg form file (.frm) from a FIELD and field-info struct -@end itemize -@*@* - -@subsection sql-bench - -The MySQL Benchmarks. -@*@* - -This directory has the programs and input files which MySQL uses for -its comparisons of MySQL, PostgreSQL, mSQL, Solid, etc. Since MySQL -publishes the comparative results, it's only right that it should make -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. -@item -\Data\ATIS -- .txt files containing input data for the "ATIS" tests -@item -\Data\Wisconsin -- .txt files containing input data for the "Wisconsin" tests -@item -\Results -- old test results -@item -\Results-win32 -- old test results from Windows 32-bit tests -@end itemize -@*@* - -There are twenty-four *.sh (shell script) files, which involve Perl -programs. -@*@* - -There are three *.bat (batch) files. -@*@* - -There is one README file and one TODO file. -@*@* - -@subsection SSL - -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 -(the NOTES file) and seven *.pem files. PEM stands for "Privacy -Enhanced Mail" and is an Internet standard for adding security to -electronic mail. Finally, there are two short scripts for running -clients and servers over SSL connections. -@*@* - -@subsection strings - -The string library. -@*@* - -Many of the files in this subdirectory are equivalent to well-known -functions that appear in most C string libraries. For those, there is -documentation available in most compiler handbooks. -@*@* - -On the other hand, some of the files are MySQL additions or -improvements. Often the MySQL changes are attempts to optimize the -standard libraries. It doesn't seem that anyone tried to optimize for -recent Pentium class processors, though. -@*@* - -The .C files are: -@itemize @bullet -@item -atof.c -- ascii-to-float, MySQL version -@item -bchange.c -- short replacement routine written by Monty Widenius in -1987 -@item -bcmp.c -- binary compare, rarely used -@item -bcopy-duff.c -- block copy: attempt to copy memory blocks faster -than cmemcpy -@item -bfill.c -- byte fill, to fill a buffer with (length) copies of a -byte -@item -bmove.c -- block move -@item -bmove512.c -- "should be the fastest way to move a multiple of 512 -bytes" -@item -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 -@item -ctype*.c -- string handling programs for each char type MySQL -handles -@item -do_ctype.c -- display case-conversion and sort-conversion tables -@item -int2str.c -- integer-to-string -@item -is_prefix.c -- checks whether string1 starts with string2 -@item -llstr.c -- convert long long to temporary-buffer string, return -pointer -@item -longlong2str.c -- ditto, but to argument-buffer -@item -memcmp.c -- memory compare -@item -memset.c -- memory set -@item -my_vsnprintf.c -- variant of printf -@item -r_strinstr.c -- see if one string is within another -@item -str2int.c -- convert string to integer -@item -strappend.c -- fill up a string to n characters -@item -strcat.c -- concatenate strings -@item -strcend.c -- point to where a character C occurs within str, or NULL -@item -strchr.c -- point to first place in string where character occurs -@item -strcmp.c -- compare two strings -@item -strcont.c -- point to where any one of a set of characters appears -@item -strend.c -- point to the '\0' byte which terminates str -@item -strfill.c -- fill a string with n copies of a byte -@item -strinstr.c -- find string within string -@item -strlen.c -- return length of string in bytes -@item -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 -@item -strnlen.c -- return min(length of string, n) -@item -strnmov.c -- move source to dest for source size, or for n bytes -@item -strrchr.c -- find a character within string, searching from end -@item -strstr.c -- find an instance of pattern within source -@item -strto.c -- string to long, to long long, to unsigned long, etc. -@item -strtol.c -- string to long -@item -strtoll.c -- string to long long -@item -strtoul.c -- string to unsigned long -@item -strtoull.c -- string to unsigned long long -@item -strxmov.c -- move a series of concatenated source strings to dest -@item -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, for operating systems that don't support these -@item -xml.c -- read and parse XML strings; used to read character definition information stored in /sql/share/charsets -@end itemize -@*@* - -There are also four .ASM files -- macros.asm, ptr_cmp.asm, -strings.asm, and strxmov.asm -- which can replace some of the -C-program functions. But again, they look like optimizations for old -members of the Intel processor family. -@*@* - -@subsection 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. They -include example my.cnf files one can use as a default setup for -MySQL. -@*@* - -@subsection tests - -Tests in Perl and in C. -@*@* - -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 - -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. Related to fail-safe -replication. -@end itemize -@*@* - -@subsection VC++Files - -Visual C++ Files. -@*@* - -Includes this entire directory, repeated for VC++ (Windows) use. -@*@* - -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 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. -@*@* - -In addition to the "subdirectories which are duplicates of -directories", VC++Files contains these subdirectories, which are not -duplicates: -@itemize @bullet -@item -comp_err -- (nearly empty) -@item -contrib -- (nearly empty) -@item -InstallShield -- script files -@item -isamchk -- (nearly empty) -@item -libmysqltest -- one small non-MySQL test program: mytest.c -@item -myisamchk -- (nearly empty) -@item -myisamlog -- (nearly empty) -@item -myisammrg -- (nearly empty) -@item -mysqlbinlog -- (nearly empty) -@item -mysqlmanager -- MFC foundation class files created by AppWizard -@item -mysqlserver -- (nearly empty) -@item -mysqlshutdown -- one short program, mysqlshutdown.c -@item -mysqlwatch.c -- Windows service initialization and monitoring -@item -my_print_defaults -- (nearly empty) -@item -pack_isam -- (nearly empty) -@item -perror -- (nearly empty) -@item -prepare -- (nearly empty) -@item -replace -- (nearly empty) -@item -SCCS -- source code control system -@item -test1 -- tests connecting via X threads -@item -thr_insert_test -- (nearly empty) -@item -thr_test -- one short program used to test for memory-allocation bug -@item -winmysqladmin -- the winmysqladmin.exe source -@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. -@*@* - -The VIO routines are wrappers for the various network I/O calls that -happen with different protocols. The idea is that in the main modules -one won't have to write separate bits of code for each protocol. Thus -vio's purpose is somewhat like the purpose of Microsoft's winsock -library. -@*@* - -The underlying protocols at this moment are: TCP/IP, Named Pipes (for -WindowsNT), Shared Memory, and Secure Sockets (SSL). -@*@* - -The C programs are: -@itemize @bullet -@item -test-ssl.c -- Short standalone test program: SSL -@item -test-sslclient.c -- Short standalone test program: clients -@item -test-sslserver.c -- Short standalone test program: server -@item -vio.c -- Declarations + open/close functions -@item -viosocket.c -- Send/retrieve functions -@item -viossl.c -- SSL variations for the above -@item -viosslfactories.c -- Certification / Verification -@item -viotest.cc -- Short standalone test program: general -@item -viotest-ssl.c -- Short standalone test program: SSL -@item -viotest-sslconnect.cc -- Short standalone test program: SSL connect -@end itemize -@*@* - -The older functions -- raw_net_read, raw_net_write -- are now -obsolete. -@*@* - -@subsection zlib - -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 -package. It was produced by the GNU Zip (gzip.org) people. Zlib is a -variation of the famous "Lempel-Ziv" method, which is also used by -"Zip". The method for reducing the size of any arbitrary string of -bytes is as follows: -@itemize @bullet -@item -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. -@end itemize - -There is a full description of the library's functions in the gzip -manual at: @* -@url{http://www.gzip.org/zlib/manual.html} @* -There is therefore no need to list the modules in this document. -@*@* - -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 - -ERRATUM BY HEIKKI TUURI (START) -@*@* - -Errata about InnoDB row locks:@*@* - -@example - #define LOCK_S 4 /* shared */ - #define LOCK_X 5 /* exclusive */ -... -@strong{/* Waiting lock flag */} - #define LOCK_WAIT 256 -/* this wait bit should be so high that it can be ORed to the lock -mode and type; when this bit is set, it means that the lock has not -yet been granted, it is just waiting for its turn in the wait queue */ -... -@strong{/* Precise modes */} - #define LOCK_ORDINARY 0 -/* this flag denotes an ordinary next-key lock in contrast to LOCK_GAP -or LOCK_REC_NOT_GAP */ - #define LOCK_GAP 512 -/* this gap bit should be so high that it can be ORed to the other -flags; when this bit is set, it means that the lock holds only on the -gap before the record; for instance, an x-lock on the gap does not -give permission to modify the record on which the bit is set; locks of -this type are created when records are removed from the index chain of -records */ - #define LOCK_REC_NOT_GAP 1024 -/* this bit means that the lock is only on the index record and does -NOT block inserts to the gap before the index record; this is used in -the case when we retrieve a record with a unique key, and is also used -in locking plain SELECTs (not part of UPDATE or DELETE) when the user -has set the READ COMMITTED isolation level */ - #define LOCK_INSERT_INTENTION 2048 -/* this bit is set when we place a waiting gap type record lock -request in order to let an insert of an index record to wait until -there are no conflicting locks by other transactions on the gap; note -that this flag remains set when the waiting lock is granted, or if the -lock is inherited to a neighboring record */ -@end example -@* - -ERRATUM BY HEIKKI TUURI (END) -@*@* - -The InnoDB source files are the best place to look for information -about internals of the file structure that MySQLites can optionally -use for transaction support. But when you first look at all the -subdirectories and file names you'll wonder: Where Do I Start? It can -be daunting. -@*@* - -Well, I've been through that phase, so I'll pass on what I had to -learn on the first day that I looked at InnoDB source files. I am very -sure that this will help you grasp, in overview, the organization of -InnoDB modules. I'm also going to add comments about what is going on --- which you should mistrust! These comments are reasonable working -hypotheses; nevertheless, they have not been subjected to expert peer -review. -@*@* - -Here's how I'm going to organize the discussion. I'll take each of the -32 InnoDB subdirectories that come with the MySQL 4.0 source code in -\mysql\innobase (on my Windows directory). The format of each section -will be like this every time: -@*@* - -@strong{\subdirectory-name (LONGER EXPLANATORY NAME)}@* -@multitable @columnfractions .10 .20 .40 .50 -@item @strong{File Name} @tab @strong{What Name Stands For} @tab @strong{Size} @tab @strong{Comment Inside File} -@item file-name -@tab my-own-guess -@tab in-bytes -@tab from-the-file-itself -@end multitable -...@* -My-Comments@* -@* - -For example: @* -@example -" -@strong{\ha (HASHING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ha0ha.c Hashing/Hashing 7,452 Hash table with external chains - - Comments about hashing will be here. -" -@end example -@* - -The "Comment Inside File" column is a direct copy from the first /* -comment */ line inside the file. All other comments are mine. After -I've discussed each directory, I'll finish with some notes about -naming conventions and a short list of URLs that you can use for -further reference. -@*@* - -Now let's begin. -@*@* - -@example - -@strong{\ha (HASHING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ha0ha.c Hashing / Hashing 7,452 Hash table with external chains - -I'll hold my comments until the next section, \hash (HASHING). - -@strong{\hash (HASHING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - hash0hash.c Hashing / Hashing 3,257 Simple hash table utility - -The two C programs in the \ha and \hashing directories -- ha0ha.c and -hash0hash.c -- both refer to a "hash table" but hash0hash.c is -specialized, it is mostly about accessing points in the table under -mutex control. - -When a "database" is so small that InnoDB can load it all into memory -at once, it's more efficient to access it via a hash table. After all, -no disk i/o can be saved by using an index lookup, if there's no disk. - -@strong{\os (OPERATING SYSTEM)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - os0shm.c OS / Shared Memory 3,150 To shared memory primitives - os0file.c OS / File 64,412 To i/o primitives - os0thread.c OS / Thread 6,827 To thread control primitives - os0proc.c OS / Process 3,700 To process control primitives - os0sync.c OS / Synchronization 10,208 To synchronization primitives - -This is a group of utilities that other modules may call whenever they -want to use an operating-system resource. For example, in os0file.c -there is a public InnoDB function named os_file_create_simple(), which -simply calls the Windows-API function CreateFile. Naturally the -contents of this group are somewhat different for other operating systems. - -The "Shared Memory" functions in os0shm.c are only called from the -communications program com0shm.c (see \com COMMUNICATIONS). The i/o -and thread-control primitives are called extensively. The word -"synchronization" in this context refers to the mutex-create and -mutex-wait functionality. - -@strong{\ut (UTILITIES)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ut0ut.c Utilities / Utilities 7,041 Various utilities - ut0byte.c Utilities / Debug 1,856 Byte utilities - ut0rnd.c Utilities / Random 1,475 Random numbers and hashing - ut0mem.c Utilities / Memory 5,530 Memory primitives - ut0dbg.c Utilities / Debug 642 Debug utilities - -The two functions in ut0byte.c are just for lower/upper case -conversion and comparison. The single function in ut0rnd.c is for -finding a prime slightly greater than the given argument, which is -useful for hash functions, but unrelated to randomness. The functions -in ut0mem.c are wrappers for "malloc" and "free" calls -- for the -real "memory" module see section \mem (MEMORY). Finally, the -functions in ut0ut.c are a miscellany that didn't fit better elsewhere: -get_high_bytes, clock, time, difftime, get_year_month_day, and "sprintf" -for various diagnostic purposes. - -In short: the \ut group is trivial. - -@strong{\buf (BUFFERING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - buf0buf.c Buffering / Buffering 53,246 The database buffer buf_pool - buf0flu.c Buffering / Flush 23,711 ... flush algorithm - buf0lru.c / least-recently-used 20,245 ... replacement algorithm - buf0rea.c Buffering / read 17,399 ... read - -There is a separate file group (\mem MEMORY) which handles memory -requests in general.A "buffer" usually has a more specific -definition, as a memory area which contains copies of pages that -ordinarily are in the main data file. The "buffer pool" is the set -of all buffers (there are lots of them because InnoDB doesn't -depend on the OS's caching to make things faster). - -The pool size is fixed (at the time of this writing) but the rest of -the buffering architecture is sophisticated, involving a host of -control structures. In general: when InnoDB needs to access a new page -it looks first in the buffer pool; InnoDB reads from disk to a new -buffer when the page isn't there; InnoDB chucks old buffers (basing -its decision on a conventional Least-Recently-Used algorithm) when it -has to make space for a new buffer. - -There are routines for checking a page's validity, and for read-ahead. -An example of "read-ahead" use: if a sequential scan is going on, then -a DBMS can read more than one page at a time, which is efficient -because reading 32,768 bytes (two pages) takes less than twice as long -as reading 16,384 bytes (one page). - -@strong{\btr (B-TREE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - btr0btr.c B-tree / B-tree 74,255 B-tree - btr0cur.c B-tree / Cursor 94,950 index tree cursor - btr0sea.c B-tree / Search 36,580 index tree adaptive search - btr0pcur.c B-tree / persistent cursor 14,548 index tree persistent cursor - -If you total up the sizes of the C files, you'll see that \btr is the -second-largest file group in InnoDB. This is understandable because -maintaining a B-tree is a relatively complex task. Luckily, there has -been a lot of work done to describe efficient management of B-tree and -B+-tree structures, much of it open-source or public-domain, since -their original invention over thirty years ago. - -InnoDB likes to put everything in B-trees. This is what I'd call a -"distinguishing characteristic" because in all the major DBMSs (like -IBM DB2, Microsoft SQL Server, and Oracle), the main or default or -classic structure is the heap-and-index. In InnoDB the main structure -is just the index. To put it another way: InnoDB keeps the rows in the -leaf node of the index, rather than in a separate file. Compare -Oracle's Index Organized Tables, and Microsoft SQL Server's Clustered -Indexes. - -This, by the way, has some consequences. For example, you may as well -have a primary key since otherwise InnoDB will make one anyway. And -that primary key should be the shortest of the candidate keys, since -InnoDB -will use it as a pointer if there are secondary indexes. - -Most importantly, it means that rows have no fixed address. Therefore -the routines for managing file pages should be good. We'll see about -that when we look at the \row (ROW) program group later. - -@strong{\com (COMMUNCATION)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - com0com.c Communication 6,913 Communication primitives - com0shm.c Communication / 24,633 ... through shared memory - Shared Memory - -The communication primitives in com0com.c are said to be modelled -after the ones in Microsoft's winsock library (the Windows Sockets -interface). The communication primitives in com0shm.c are at a -slightly lower level, and are called from the routines in com0com.c. - -I was interested in seeing how InnoDB would handle inter-process -communication, since there are many options -- named pipes, TCP/IP, -Windows messaging, and Shared Memory being the main ones that come to -mind. It appears that InnoDB prefers Shared Memory. The main idea is: -there is an area of memory which two different processes (or threads, -of course) can both access. To communicate, a thread gets an -appropriate mutex, puts in a request, and waits for a response. Thread -interaction is also a subject for the os0thread.c program in another -program group, \os (OPERATING SYSTEM). - -@strong{\dyn (DYNAMICALLY ALLOCATED ARRAY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - dyn0dyn.c Dynamic / Dynamic 994 dynamically allocated array - -There is a single function in the dyn0dyn.c program, for adding a -block to the dynamically allocated array. InnoDB might use the array -for managing concurrency between threads. - -At the moment, the \dyn program group is trivial. - -@strong{\fil (FILE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - fil0fil.c File / File 39,725 The low-level file system - -The reads and writes to the database files happen here, in -co-ordination with the low-level file i/o routines (see os0file.h in -the \os program group). - -Briefly: a table's contents are in pages, which are in files, which -are in tablespaces. Files do not grow; instead one can add new files -to the tablespace. As we saw earlier (discussing the \btr program group) -the pages are nodes of B-trees. Since that's the case, new additions can -happen at various places in the logical file structure, not -necessarily at the end. Reads and writes are asynchronous, and go into -buffers, which are set up by routines in the \buf program group. - -@strong{\fsp (FILE SPACE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - fsp0fsp.c File Space Management 100,271 File space management - -I would have thought that the \fil (FILE) and \fsp (FILE SPACE) -MANAGEMENT programs would fit together in the same program group; -however, I guess the InnoDB folk are splitters rather than lumpers. - -It's in fsp0fsp.c that one finds some of the descriptions and comments -of extents, segments, and headers. For example, the "descriptor bitmap -of the pages in the extent" is in here, and you can find as well how -the free-page list is maintained, what's in the bitmaps, and what -various header fields' contents are. - -@strong{\fut (FILE UTILITY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - fut0fut.c File Utility / Utility 293 File-based utilities - fut0lst.c File Utility / List 14,129 File-based list utilities - -Mainly these small programs affect only file-based lists, so maybe -saying "File Utility" is too generic. The real work with data files -goes on in the \fsp program group. - -@strong{\log (LOGGING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - log0log.c Logging / Logging 77,834 Database log - log0recv.c Logging / Recovery 80,701 Recovery - -I've already written about the \log program group, so here's a link to -my previous article: "How Logs work with MySQL and InnoDB": -@url{http://www.devarticles.com/art/1/181/2} - -@strong{\mem (MEMORY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - mem0mem.c Memory / Memory 9,971 The memory management - mem0dbg.c Memory / Debug 21,297 ... the debug code - mem0pool.c Memory / Pool 16,293 ... the lowest level - -There is a long comment at the start of the mem0pool.c program, which -explains what the memory-consumers are, and how InnoDB tries to -satisfy them. The main thing to know is that there are really three -pools: the buffer pool (see the \buf program group), the log pool (see the \log -program group), and the common pool, which is where everything that's -not in the buffer or log pools goes (for example the parsed SQL -statements and the data dictionary cache). - -@strong{\mtr (MINI-TRANSACTION)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - mtr0mtr.c Mini-transaction / 12,433 Mini-transaction buffer - mtr0log.c Mini-transaction / Log 8,180 ... log routines - -The mini-transaction routines are called from most of the other -program groups. I'd describe this as a low-level utility set. - -@strong{\que (QUERY GRAPH)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - que0que.c Query Graph / Query 35,964 Query graph - -The program que0que.c ostensibly is about the execution of stored -procedures which contain commit/rollback statements. I took it that -this has little importance for the average MySQL user. - -@strong{\rem (RECORD MANAGER)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - rem0rec.c Record Manager 14,961 Record Manager - rem0cmp.c Record Manager / 25,263 Comparison services for records - Comparison - -There's an extensive comment near the start of rem0rec.c title -"Physical Record" and it's recommended reading. At some point you'll -ask what are all those bits that surround the data in the rows on a page, -and this is where you'll find the answer. - -@strong{\row (ROW)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - row0row.c Row / Row 16,764 General row routines - row0uins.c Row / Undo Insert 7,199 Fresh insert undo - row0umod.c Row / Undo Modify 17,147 Undo modify of a row - row0undo.c Row / Undo 10,254 Row undo - row0vers.c Row / Version 12,288 Row versions - row0mysql.c Row / MySQL 63,556 Interface [to MySQL] - row0ins.c Row / Insert 42,829 Insert into a table - row0sel.c Row / Select 85,923 Select - row0upd.c Row / Update 44,456 Update of a row - row0purge.c Row / Purge 14,961 Purge obsolete records - -Rows can be selected, inserted, updated/deleted, or purged (a -maintenance activity). These actions have ancillary actions, for -example after insert there can be an index-update test, but it seems -to me that sometimes the ancillary action has no MySQL equivalent (yet) -and so is inoperative. - -Speaking of MySQL, notice that one of the larger programs in the \row -program group is the "interface between Innobase row operations and -MySQL" (row0mysql.c) -- information interchange happens at this level -because rows in InnoDB and in MySQL are analogous, something which -can't be said for pages and other levels. - -@strong{\srv (Server)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - srv0srv.c Server / Server 79,058 Server main program - srv0que.c Server / Query 2,361 Server query execution - srv0start.c Server / Start 34,586 Starts the server - -This is where the server reads the initial configuration files, splits -up the threads, and gets going. There is a long comment deep in the -program (you might miss it at first glance) titled "IMPLEMENTATION OF -THE SERVER MAIN PROGRAM" in which you'll find explanations about -thread priority, and about what the responsibiities are for various -thread types. - -InnoDB has many threads, for example "user threads" (which wait for -client requests and reply to them), "parallel communication threads" -(which take part of a user thread's job if a query process can be -split), "utility threads" (background priority), and a "master thread" -(high priority, usually asleep). - -@strong{\thr (Thread Local Storage)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - thr0loc.c Thread / Local 5,261 The thread local storage - -InnoDB doesn't use the Windows-API thread-local-storage functions, -perhaps because they're not portable enough. - -@strong{\trx (Transaction)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - trx0trx.c Transaction / 37,447 The transaction - trx0purge.c Transaction / Purge 26,782 ... Purge old versions - trx0rec.c Transaction / Record 36,525 ... Undo log record - trx0sys.c Transaction / System 20,671 ... System - trx0rseg.c / Rollback segment 6,214 ... Rollback segment - trx0undo.c Transaction / Undo 46,595 ... Undo log - -InnoDB's transaction management is supposedly "in the style of Oracle" -and that's close to true but can mislead you. -@itemize -@item -First: InnoDB uses rollback segments like Oracle8i does -- but -Oracle9i uses a different name -@item -Second: InnoDB uses multi-versioning like Oracle does -- but I see -nothing that looks like an Oracle ITL being stored in the InnoDB data -pages. -@item -Third: InnoDB and Oracle both have short (back-to-statement-start) -versioning for the READ COMMITTED isolation level and long -(back-to-transaction-start) versioning for higher levels -- but InnoDB -and Oracle have different "default" isolation levels. -@item -Finally: InnoDB's documentation says it has to lock "the gaps before -index keys" to prevent phantoms -- but any Oracle user will tell you that -phantoms are impossible anyway at the SERIALIZABLE isolation level, so -key-locks are unnecessary. -@end itemize - -The main idea, though, is that InnoDB has multi-versioning. So does -Oracle. This is very different from the way that DB2 and SQL Server do -things. - -@strong{\usr (USER)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - usr0sess.c User / Session 27,415 Sessions - -One user can have multiple sessions (the session being all the things -that happen betweeen a connect and disconnect). This is where InnoDB -tracks session IDs, and server/client messaging. It's another of those -items which is usually MySQL's job, though. - -@strong{\data (DATA)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - data0data.c Data / Data 26,002 SQL data field and tuple - data0type.c Data / Type 2,122 Data types - -This is a collection of minor utility routines affecting rows. - -@strong{\dict (DICTIONARY)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - dict0dict.c Dictionary / Dictionary 84,667 Data dictionary system - dict0boot.c Dictionary / boot 12,134 ... creation and booting - dict0load.c Dictionary / load 26,546 ... load to memory cache - dict0mem.c Dictionary / memory 8,221 ... memory object creation - -The data dictionary (known in some circles as the catalog) has the -metadata information about objects in the database -- column sizes, -table names, and the like. - -@strong{\eval (EVALUATING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - eval0eval.c Evaluating/Evaluating 15,682 SQL evaluator - eval0proc.c Evaluating/Procedures 5,000 Executes SQL procedures - -The evaluating step is a late part of the process of interpreting an -SQL statement -- parsing has already occurred during \pars (PARSING). - -The ability to execute SQL stored procedures is an InnoDB feature, but -not a MySQL feature, so the eval0proc.c program is unimportant. - -@strong{\ibuf (INSERT BUFFER)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - ibuf0ibuf.c Insert Buffer / 69,884 Insert buffer - -The words "Insert Buffer" mean not "buffer used for INSERT" but -"insertion of a buffer into the buffer pool" (see the \buf BUFFER -program group description). The matter is complex due to possibilities -for deadlocks, a problem to which the comments in the ibuf0ibuf.c -program devote considerable attention. - -@strong{\mach (MACHINE FORMAT)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - mach0data.c Machine/Data 2,319 Utilities for converting - -The mach0data.c program has two small routines for reading compressed -ulints (unsigned long integers). - -@strong{\lock (LOCKING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - lock0lock.c Lock / Lock 127,646 The transaction lock system - -If you've used DB2 or SQL Server, you might think that locks have their -own in-memory table, that row locks might need occasional escalation to -table locks, and that there are three lock types: Shared, Update, Exclusive. - -All those things are untrue with InnoDB! Locks are kept in the database -pages. A bunch of row locks can't be rolled together into a single table -lock. And most importantly there's only one lock type. I call this type -"Update" because it has the characteristics of DB2 / SQL Server Update -locks, that is, it blocks other updates but doesn't block reads. -Unfortunately, InnoDB comments refer to them as "x-locks" etc. - -To sum it up: if your background is Oracle you won't find too much -surprising, but if your background is DB2 or SQL Server the locking -concepts and terminology will probably confuse you at first. - -You can find an online article about the differences between -Oracle-style and DB2/SQL-Server-style locks at: -@url{http://dbazine.com/gulutzan6.html} - -@strong{\odbc (ODBC)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - odbc0odbc.c ODBC / ODBC 16,865 ODBC client library - -The odbc0odbc.c program has a small selection of old ODBC-API -functions: SQLAllocEnv, SQLAllocConnect, SQLAllocStmt, SQLConnect, -SQLError, SQLPrepare, SQLBindParameter, SQLExecute. - -@strong{\page (PAGE)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - page0page.c Page / Page 44,309 Index page routines - page0cur.c Page / Cursor 30,305 The page cursor - -It's in the page0page.c program that you'll learn as follows: index -pages start with a header, entries in the page are in order, at the -end of the page is a sparse "page directory" (what I would have called -a slot table) which makes binary searches easier. - -Incidentally, the program comments refer to "a page size of 8 kB" -which seems obsolete. In univ.i (a file containing universal -constants) the page size is now #defined as 16KB. - -@strong{\pars (PARSING)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - pars0pars.c Parsing/Parsing 49,947 SQL parser - pars0grm.c Parsing/Grammar 62,685 A Bison parser - pars0opt.c Parsing/Optimizer 30,809 Simple SQL Optimizer - pars0sym.c Parsing/Symbol Table 5,541 SQL parser symbol table - lexyy.c ?/Lexer 59,948 Lexical scanner - -The job is to input a string containing an SQL statement and output an -in-memory parse tree. The EVALUATING (subdirectory \eval) programs -will use the tree. - -As is common practice, the Bison and Flex tools were used -- pars0grm.c -is what the Bison parser produced from an original file named pars0grm.y -(not supplied), and lexyy.c is what Flex produced. - -Since InnoDB is a DBMS by itself, it's natural to find SQL parsing in -it. But in the MySQL/InnoDB combination, MySQL handles most of the -parsing. These files are unimportant. - -@strong{\read (READ)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - read0read.c Read / Read 6,244 Cursor read - -The read0read.c program opens a "read view" of a query result, using -some functions in the \trx program group. - -@strong{\sync (SYNCHRONIZATION)} - File Name What Name Stands For Size Comment Inside File - --------- -------------------- ------ ------------------- - sync0sync.c Synchronization / 35,918 Mutex, the basic sync primitive - sync0arr.c ... / array 26,461 Wait array used in primitives - sync0ipm.c ... / interprocess 4,027 for interprocess sync - sync0rw.c ... / read-write 22,220 read-write lock for thread sync - -A mutex (Mutual Exclusion) is an object which only one thread/process -can hold at a time. Any modern operating system API has some functions -for mutexes; however, as the comments in the sync0sync.c code indicate, it -can be faster to write one's own low-level mechanism. In fact the old -assembly-language XCHG trick is in here -- this is the only program -that contains any assembly code. -@end example -@* -@* - -This is the end of the section-by-section account of InnoDB -subdirectories. -@*@* - -@strong{A Note About File Naming} @*@* - -There appears to be a naming convention. The first letters of the file -name are the same as the subdirectory name, then there is a '0' -separator, then there is an individual name. For the main program in a -subdirectory, the individual name may be a repeat of the subdirectory -name. For example, there is a file named ha0ha.c (the first two -letters ha mean "it's in in subdirectory ..\ha", the next letter 0 -means "0 separator", the next two letters mean "this is the main ha -program"). This naming convention is not strict, though: for example -the file lexyy.c is in the \pars subdirectory. -@*@* - -@strong{A Note About Copyrights} @*@* - -Most of the files begin with a copyright notice or a creation date, -for example "Created 10/25/1995 Heikki Tuuri". I don't know a great -deal about the history of InnoDB, but found it interesting that most -creation dates were between 1994 and 1998. -@*@* - -@strong{References} @*@* - -Ryan Bannon, Alvin Chin, Faryaaz Kassam and Andrew Roszko @* -"InnoDB Concrete Architecture" @* -@url{http://www.swen.uwaterloo.ca/~mrbannon/cs798/assignment_02/innodb.pdf} - -A student paper. It's an interesting attempt to figure out InnoDB's -architecture using tools, but I didn't end up using it for the specific -purposes of this article. -@*@* - -Peter Gulutzan @* -"How Logs Work With MySQL And InnoDB" @* -@url{http://www.devarticles.com/art/1/181/2} -@*@* - -Heikki Tuuri @* -"InnoDB Engine in MySQL-Max-3.23.54 / MySQL-4.0.9: The Up-to-Date -Reference Manual of InnoDB" @* -@url{http://www.innodb.com/ibman.html} - -This is the natural starting point for all InnoDB information. Mr -Tuuri also appears frequently on MySQL forums. -@*@* - -@summarycontents -@contents - -@bye From 7f459bccbb8727363707b7d0ba6dbb8488b3e28a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 20:22:47 +0200 Subject: [PATCH 251/399] - removed all traces of internals.texi from Docs/Makefile.am to avoid compile problems Docs/Makefile.am: - removed all traces of internals.texi to avoid compile problems --- Docs/Makefile.am | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 00eb936c408..cf0a4632eda 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -156,54 +156,6 @@ manual_letter.de.ps: manual.de.texi include.texi $(DVIPS) -t letter manual.de.dvi -o $@ touch $@ - -# -# Internals Manual -# - -# GNU Info -internals.info: internals.texi include.texi - cd $(srcdir) && $(MAKEINFO) --no-split -I $(srcdir) $< - -# Plain Text -internals.txt: internals.texi include.texi - cd $(srcdir) && \ - $(MAKEINFO) -I $(srcdir) --no-headers --no-split --output $@ $< - -# HTML, all in one file -internals.html: internals.texi include.texi $(srcdir)/Support/texi2html - cd $(srcdir) && @PERL@ $(srcdir)/Support/texi2html $(TEXI2HTML_FLAGS) $< -internals_toc.html: internals.html - -# PDF, Portable Document Format -internals.pdf: internals.texi - sed -e 's|@image{[^}]*} *||g' <$< >internals-tmp.texi - pdftex --interaction=nonstopmode internals-tmp.texi - texindex internals-tmp.?? - pdftex --interaction=nonstopmode internals-tmp.texi - texindex internals-tmp.?? - pdftex --interaction=nonstopmode internals-tmp.texi - mv internals-tmp.pdf $@ - rm -f internals-tmp.* - touch $@ - -# Postscript, A4 Paper -internals_a4.ps: internals.texi include.texi - TEXINPUTS=$(srcdir):$$TEXINPUTS \ - MAKEINFO='$(MAKEINFO) -I $(srcdir)' \ - $(TEXI2DVI) --batch --texinfo --quiet '@afourpaper' $< - $(DVIPS) -t a4 internals.dvi -o $@ - touch $@ - -# Postscript, US Letter Paper -internals_letter.ps: internals.texi include.texi - TEXINPUTS=$(srcdir):$$TEXINPUTS \ - MAKEINFO='$(MAKEINFO) -I $(srcdir)' \ - $(TEXI2DVI) --batch $< - $(DVIPS) -t letter internals.dvi -o $@ - touch $@ - - # # Miscellaneous # From 546b2221a23e122550b6b1bacf22781b54eaf55d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 May 2003 23:07:32 +0200 Subject: [PATCH 252/399] A trick (a useless update) to force the slave to wait for TWO rotate events before stopping. This is to make the test's result predictable (depending on the machine the results could formerly be slightly different, though everything is sane in the code; it's not a bug). mysql-test/r/rpl_log.result: result update --- mysql-test/r/rpl_log.result | 22 ++++++++++++++-------- mysql-test/t/rpl_log.test | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result index 5415a153a98..425c376af1e 100644 --- a/mysql-test/r/rpl_log.result +++ b/mysql-test/r/rpl_log.result @@ -36,6 +36,8 @@ show binlog events from 79 limit 2,1; Log_name Pos Event_type Server_id Orig_log_pos Info master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL) flush logs; +create table t5 (a int); +drop table t5; slave start; flush logs; slave stop; @@ -56,9 +58,11 @@ master-bin.001 1079 Query 1 1079 use test; drop table t1 master-bin.001 1127 Rotate 1 1127 master-bin.002;pos=4 show binlog events in 'master-bin.002'; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.002 4 Query 1 4 use test; create table t1 (n int) -master-bin.002 62 Query 1 62 use test; insert into t1 values (1) -master-bin.002 122 Query 1 122 use test; drop table t1 +master-bin.002 4 Query 1 4 use test; create table t5 (a int) +master-bin.002 62 Query 1 62 use test; drop table t5 +master-bin.002 110 Query 1 110 use test; create table t1 (n int) +master-bin.002 168 Query 1 168 use test; insert into t1 values (1) +master-bin.002 228 Query 1 228 use test; drop table t1 show master logs; Log_name master-bin.001 @@ -79,14 +83,16 @@ slave-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null) slave-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581 slave-bin.001 1065 Exec_load 1 1056 ;file_id=1 slave-bin.001 1088 Query 1 1079 use test; drop table t1 -slave-bin.001 1136 Rotate 2 1136 slave-bin.002;pos=4 +slave-bin.001 1136 Query 1 4 use test; create table t5 (a int) +slave-bin.001 1194 Query 1 62 use test; drop table t5 +slave-bin.001 1242 Rotate 2 1242 slave-bin.002;pos=4 show binlog events in 'slave-bin.002' from 4; Log_name Pos Event_type Server_id Orig_log_pos Info -slave-bin.002 4 Query 1 4 use test; create table t1 (n int) -slave-bin.002 62 Query 1 62 use test; insert into t1 values (1) -slave-bin.002 122 Query 1 122 use test; drop table t1 +slave-bin.002 4 Query 1 110 use test; create table t1 (n int) +slave-bin.002 62 Query 1 168 use test; insert into t1 values (1) +slave-bin.002 122 Query 1 228 use test; drop table t1 show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space -127.0.0.1 root MASTER_PORT 1 master-bin.002 170 slave-relay-bin.002 1457 master-bin.002 Yes Yes 0 0 170 1461 +127.0.0.1 root MASTER_PORT 1 master-bin.002 276 slave-relay-bin.002 1522 master-bin.002 Yes Yes 0 0 276 1526 show binlog events in 'slave-bin.005' from 4; Error when executing command SHOW BINLOG EVENTS: Could not find target log diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test index 85782e78142..8cd9d21a087 100644 --- a/mysql-test/t/rpl_log.test +++ b/mysql-test/t/rpl_log.test @@ -22,10 +22,32 @@ show binlog events from 79 limit 2; show binlog events from 79 limit 2,1; flush logs; +# We need an extra update before doing save_master_pos. +# Otherwise, an unlikely scenario may occur: +# * When the master's binlog_dump thread reads the end of master-bin.001, +# it send the rotate event which is at this end, plus a fake rotate event +# because it's starting to read a new binlog. +# save_master_pos will record the position of the first of the two rotate +# (because the fake one is not in the master's binlog anyway). +# * Later the slave waits for the position of the first rotate event, +# and it may quickly stop (in 'slave stop') without having received the fake +# one. +# So, depending on a few milliseconds, we end up with 2 rotate events in the +# relay log or one, which influences the output of SHOW SLAVE STATUS, making +# it not predictable and causing random test failures. +# To make it predictable, we do a useless update now, but which has the interest +# of making the slave catch both rotate events. + +create table t5 (a int); +drop table t5; + # Sync slave and force it to start on another binary log save_master_pos; connection slave; +# Note that the above 'slave start' will cause a 3rd rotate event (a fake one) +# to go into the relay log (the master always sends a fake one when replication +# starts). slave start; sync_with_master; flush logs; From 2029fa02c330e07e9e77c765fc5d5aaa7667e3d2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 00:49:24 +0300 Subject: [PATCH 253/399] fixed priority checking bug in sub select handling mysql-test/r/subselect.result: fixed subselect test mysql-test/t/subselect.test: fixed subselect test --- mysql-test/r/subselect.result | 6 ++-- mysql-test/t/subselect.test | 2 +- sql/sql_parse.cc | 54 ++++++++++++++++++++++++++++------- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 1a4701d8d0e..41620bb6e7f 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -606,14 +606,14 @@ x 3 INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; You can't specify target table 't1' for update in FROM clause -INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2)); +INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); select * from t1; x 1 2 3 3 -0 +2 drop table t1, t2, t3; CREATE TABLE t1 (x int not null, y int, primary key (x)); create table t2 (a int); @@ -688,6 +688,8 @@ id 2 INSERT INTO t2 VALUES ((SELECT * FROM t2)); You can't specify target table 't2' for update in FROM clause +INSERT INTO t2 VALUES ((SELECT id FROM t2)); +You can't specify target table 't2' for update in FROM clause SELECT * FROM t2; id 1 diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 4a171c36293..8377a756c5b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -351,7 +351,7 @@ INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; select * from t1; -- error 1093 INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; -INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2)); +INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); -- sleep 1 select * from t1; drop table t1, t2, t3; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e6ffec7ef26..473c1dd07f6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2285,15 +2285,23 @@ mysql_execute_command(THD *thd) TABLE_LIST *table; if (check_db_used(thd,tables)) goto error; - for (table=tables ; table ; table=table->next) + + if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege)) + goto error; { - if (table->derived) - table->grant.privilege= SELECT_ACL; - else if (check_access(thd,UPDATE_ACL,table->db,&table->grant.privilege)) + // Show only 1 table for check_grant + TABLE_LIST *subselects_tables= tables->next; + tables->next= 0; + if (grant_option && check_grant(thd, UPDATE_ACL, tables)) + goto error; + tables->next= subselects_tables; + + // check rights on tables of subselect (if exists) + if (subselects_tables && + (res= check_table_access(thd, SELECT_ACL, subselects_tables))) goto error; } - if (grant_option && check_grant(thd,UPDATE_ACL,tables)) - goto error; + if (select_lex->item_list.elements != lex->value_list.elements) { send_error(thd,ER_WRONG_VALUE_COUNT); @@ -2349,8 +2357,21 @@ mysql_execute_command(THD *thd) INSERT_ACL | DELETE_ACL : INSERT_ACL | update); if (check_access(thd,privilege,tables->db,&tables->grant.privilege)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,privilege,tables)) - goto error; + + { + // Show only 1 table for check_grant + TABLE_LIST *subselects_tables= tables->next; + tables->next= 0; + if (grant_option && check_grant(thd, privilege, tables)) + goto error; + tables->next= subselects_tables; + + // check rights on tables of subselect (if exists) + if (subselects_tables && + (res= check_table_access(thd, SELECT_ACL, subselects_tables))) + goto error; + } + if (select_lex->item_list.elements != lex->value_list.elements) { send_error(thd,ER_WRONG_VALUE_COUNT); @@ -2434,8 +2455,21 @@ mysql_execute_command(THD *thd) { if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,DELETE_ACL,tables)) - goto error; + + { + // Show only 1 table for check_grant + TABLE_LIST *subselects_tables= tables->next; + tables->next= 0; + if (grant_option && check_grant(thd, DELETE_ACL, tables)) + goto error; + tables->next= subselects_tables; + + // check rights on tables of subselect (if exists) + if (subselects_tables && + (res= check_table_access(thd, SELECT_ACL, subselects_tables))) + goto error; + } + // Set privilege for the WHERE clause tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); res = mysql_delete(thd,tables, select_lex->where, From 15b3f3a0d8c11babff0f2e4dfa81c1716bcf533d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 02:06:56 +0300 Subject: [PATCH 254/399] after-review fix --- sql/sql_parse.cc | 89 ++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 473c1dd07f6..78b6a03e2fa 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -59,6 +59,9 @@ static void refresh_status(void); static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name); +inline bool single_table_command_access(THD *thd, ulong privilege, + TABLE_LIST *tables, int *res); + const char *any_db="*any*"; // Special symbol for check_access const char *command_name[]={ @@ -2286,21 +2289,8 @@ mysql_execute_command(THD *thd) if (check_db_used(thd,tables)) goto error; - if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege)) - goto error; - { - // Show only 1 table for check_grant - TABLE_LIST *subselects_tables= tables->next; - tables->next= 0; - if (grant_option && check_grant(thd, UPDATE_ACL, tables)) + if (single_table_command_access(thd, UPDATE_ACL, tables, &res)) goto error; - tables->next= subselects_tables; - - // check rights on tables of subselect (if exists) - if (subselects_tables && - (res= check_table_access(thd, SELECT_ACL, subselects_tables))) - goto error; - } if (select_lex->item_list.elements != lex->value_list.elements) { @@ -2355,22 +2345,9 @@ mysql_execute_command(THD *thd) my_bool update=(lex->value_list.elements ? UPDATE_ACL : 0); ulong privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL | update); - if (check_access(thd,privilege,tables->db,&tables->grant.privilege)) - goto error; /* purecov: inspected */ - - { - // Show only 1 table for check_grant - TABLE_LIST *subselects_tables= tables->next; - tables->next= 0; - if (grant_option && check_grant(thd, privilege, tables)) - goto error; - tables->next= subselects_tables; - // check rights on tables of subselect (if exists) - if (subselects_tables && - (res= check_table_access(thd, SELECT_ACL, subselects_tables))) + if (single_table_command_access(thd, privilege, tables, &res)) goto error; - } if (select_lex->item_list.elements != lex->value_list.elements) { @@ -2453,22 +2430,8 @@ mysql_execute_command(THD *thd) break; case SQLCOM_DELETE: { - if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege)) - goto error; /* purecov: inspected */ - - { - // Show only 1 table for check_grant - TABLE_LIST *subselects_tables= tables->next; - tables->next= 0; - if (grant_option && check_grant(thd, DELETE_ACL, tables)) - goto error; - tables->next= subselects_tables; - - // check rights on tables of subselect (if exists) - if (subselects_tables && - (res= check_table_access(thd, SELECT_ACL, subselects_tables))) - goto error; - } + if (single_table_command_access(thd, DELETE_ACL, tables, &res)) + goto error; // Set privilege for the WHERE clause tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); @@ -3128,6 +3091,44 @@ error: } +/* + Check grants for commands which work only with one table and all other + tables belong to subselects. + + SYNOPSYS + single_table_command_access() + thd - Thread handler + privilege - asked privelage + tables - table list of command + res - pointer on result code variable + + RETURN + 0 - OK + 1 - access denied +*/ + +inline bool single_table_command_access(THD *thd, ulong privilege, + TABLE_LIST *tables, int *res) + +{ + if (check_access(thd, privilege, tables->db, &tables->grant.privilege)) + return 1; + + // Show only 1 table for check_grant + TABLE_LIST *subselects_tables= tables->next; + tables->next= 0; + if (grant_option && check_grant(thd, privilege, tables)) + return 1; + tables->next= subselects_tables; + + // check rights on tables of subselect (if exists) + if (subselects_tables && + (*res= check_table_access(thd, SELECT_ACL, subselects_tables))) + return 1; + return 0; +} + + /**************************************************************************** Get the user (global) and database privileges for all used tables From 838c616397d33ac0e8e03d28403f03f32d728794 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 03:36:44 +0300 Subject: [PATCH 255/399] Removed not used variable --- libmysqld/lib_sql.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 83f398ca50b..7682d60d991 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -436,7 +436,6 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups) (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); From 99d306b77e9502aa14bcb6d76af724ce6ab28b34 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 11:24:48 +0500 Subject: [PATCH 256/399] item_cmpfunc.cc: Fix for multibyte charsets sql/item_cmpfunc.cc: Fix for multibyte charsets --- sql/item_cmpfunc.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d96069a17aa..3344f2bc01d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1454,7 +1454,11 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist) { const char* tmp = first + 1; for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ; +#ifdef USE_MB + canDoTurboBM = (tmp == last) && !use_mb(default_charset_info); +#else canDoTurboBM = tmp == last; +#endif } if (canDoTurboBM) From 1328c29e946df6553e5204c0d3b34803001945eb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 13:54:18 +0500 Subject: [PATCH 257/399] "mysql" now sends client character set to server. --- client/mysql.cc | 1 + libmysql/libmysql.c | 3 ++- sql/sql_parse.cc | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index 812673d34c2..33014b27ae8 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2549,6 +2549,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, select_limit,max_join_size); mysql_options(&mysql, MYSQL_INIT_COMMAND, init_command); } + mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (!mysql_real_connect(&mysql, host, user, password, database, opt_mysql_port, opt_mysql_unix_port, connect_flag | CLIENT_MULTI_QUERIES)) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 514de2a87a6..41fde189eb5 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2241,7 +2241,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, const char *save=charsets_dir; if (mysql->options.charset_dir) charsets_dir=mysql->options.charset_dir; - mysql->charset=get_charset_by_name(mysql->options.charset_name, + mysql->charset=get_charset_by_csname(mysql->options.charset_name, + MY_CS_PRIMARY, MYF(MY_WME)); charsets_dir=save; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 78b6a03e2fa..b1e0b2dc91d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -664,8 +664,17 @@ check_connections(THD *thd) thd->max_client_packet_length= uint4korr(net->read_pos+4); if (!(thd->variables.character_set_client= get_charset((uint) net->read_pos[8], MYF(0)))) + { thd->variables.character_set_client= global_system_variables.character_set_client; + thd->variables.collation_connection= + global_system_variables.collation_connection; + } + else + { + thd->variables.collation_connection= + thd->variables.character_set_client; + } end= (char*) net->read_pos+32; } else From af512c8d8c196b3132266dc76c8a458f42405f31 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 14:46:25 +0500 Subject: [PATCH 258/399] ctype-win1250ch.c: ifdef wrong structure has been fixed strings/ctype-win1250ch.c: ifdef wrong structure has been fixed --- strings/ctype-win1250ch.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 0b75a782b17..91271b16373 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -45,6 +45,13 @@ #include "m_string.h" #include "m_ctype.h" +#else + +#include +#define uchar unsigned char + +#endif + #ifdef HAVE_CHARSET_cp1250 @@ -253,12 +260,6 @@ static uchar NEAR to_upper_win1250ch[] = { 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff }; -#else - -#include -#define uchar unsigned char - -#endif static uchar NEAR sort_order_win1250ch[] = { From eb4f5e2d6c693faecf152478cbe7e3883985548a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 16:23:04 +0500 Subject: [PATCH 259/399] --with-collation argument for configure. Now one can for example use this: ./configure --with-charset=latin1 --with-collation=latin1_danish_ci --- acconfig.h | 5 +- client/mysql.cc | 2 +- client/mysqlcheck.c | 3 +- client/mysqldump.c | 2 +- client/mysqlimport.c | 2 +- configure.in | 171 ++++++++++++++++++++++++++++++++++++- include/mysql_version.h.in | 3 - sql/mysqld.cc | 4 +- 8 files changed, 178 insertions(+), 14 deletions(-) diff --git a/acconfig.h b/acconfig.h index 6bd017bbbce..0b822d67cf5 100644 --- a/acconfig.h +++ b/acconfig.h @@ -19,7 +19,10 @@ #undef CRAY_STACKSEG_END /* Define the default charset name */ -#undef DEFAULT_CHARSET_NAME +#undef MYSQL_DEFAULT_CHARSET_NAME + +/* Define the default charset name */ +#undef MYSQL_DEFAULT_COLLATION_NAME /* Version of .frm files */ #undef DOT_FRM_VERSION diff --git a/client/mysql.cc b/client/mysql.cc index 33014b27ae8..aa9dcca92db 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -139,7 +139,7 @@ static my_string opt_mysql_unix_port=0; static int connect_flag=CLIENT_INTERACTIVE; static char *current_host,*current_db,*current_user=0,*opt_password=0, *current_prompt=0, *delimiter_str= 0, - *default_charset= (char*) MYSQL_CHARSET; + *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; static char *histfile; static String glob_buffer,old_buffer; static String processed_prompt; diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 8f599c9f497..b21a73aae4f 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -38,7 +38,8 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0, static uint verbose = 0, opt_mysql_port=0; static my_string opt_mysql_unix_port = 0; static char *opt_password = 0, *current_user = 0, - *default_charset = (char *)MYSQL_CHARSET, *current_host = 0; + *default_charset = (char *)MYSQL_DEFAULT_CHARSET_NAME, + *current_host = 0; static int first_error = 0; DYNAMIC_ARRAY tables4repair; #ifdef HAVE_SMEM diff --git a/client/mysqldump.c b/client/mysqldump.c index 6a577af8792..86f03b46038 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -85,7 +85,7 @@ static MYSQL mysql_connection,*sock=0; static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, - *where=0, *default_charset= (char *)MYSQL_CHARSET, + *where=0, *default_charset= (char *)MYSQL_DEFAULT_CHARSET_NAME, *opt_compatible_mode_str= 0, *err_ptr= 0; static ulong opt_compatible_mode= 0; diff --git a/client/mysqlimport.c b/client/mysqlimport.c index f247301c6dc..8ee656f23b2 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -44,7 +44,7 @@ static char *opt_password=0, *current_user=0, *current_host=0, *current_db=0, *fields_terminated=0, *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, *opt_columns=0, - *default_charset= (char*) MYSQL_CHARSET; + *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; static uint opt_mysql_port=0; static my_string opt_mysql_unix_port=0; static my_string opt_ignore_lines=0; diff --git a/configure.in b/configure.in index 63286db74c5..f25cb213e0b 100644 --- a/configure.in +++ b/configure.in @@ -2255,6 +2255,12 @@ AC_ARG_WITH(charset, [default_charset="$withval"], [default_charset="$DEFAULT_CHARSET"]) +AC_ARG_WITH(collation, + [ --with-collation=COLLATION + Default collation], + [default_collation="$withval"], + [default_collation="default"]) + AC_ARG_WITH(extra-charsets, [ --with-extra-charsets=CHARSET[,CHARSET,...] @@ -2281,7 +2287,6 @@ else CHARSETS="$CHARSETS $EXTRA_CHARSETS" fi - for cs in $CHARSETS do case $cs in @@ -2404,11 +2409,169 @@ do done -AC_SUBST(default_charset) -AC_DEFINE_UNQUOTED(DEFAULT_CHARSET_NAME,"$default_charset") + default_charset_collations="" -AC_MSG_RESULT([default: $default_charset; compiled in: $CHARSETS]) +case $default_charset in + armscii8) + default_charset_default_collation="armscii8_general_ci" + default_charset_collations="armscii8_general_ci armscii_bin" + ;; + ascii) + default_charset_default_collation="ascii_general_ci" + default_charset_collations="ascii_general_ci ascii_bin" + ;; + big5) + default_charset_default_collation="big5_chinese_ci" + default_charset_collations="big5_chinese_ci big5_bin" + ;; + cp1250) + default_charset_default_collation="cp1250_general_ci" + default_charset_collations="cp1250_general_ci cp1250_czech_ci cp1250_bin" + ;; + cp1251) + default_charset_default_collation="cp1251_general_ci" + default_charset_collations="cp1251_general_ci cp1251_general_cs cp1251_bin cp1251_bulgarian_ci cp1251_ukrainian_ci" + ;; + cp1256) + default_charset_default_collation="cp1256_general_ci" + default_charset_collations="cp1256_general_ci cp1256_bin" + ;; + cp1257) + default_charset_default_collation="cp1257_general_ci" + default_charset_collations="cp1257_general_ci cp1257_lithuanian_ci cp1257_bin" + ;; + cp850) + default_charset_default_collation="cp850_general_ci" + default_charset_collations="cp850_general_ci cp850_bin" + ;; + cp852) + default_charset_default_collation="cp852_general_ci" + default_charset_collations="cp852_general_ci cp852_bin" + ;; + cp866) + default_charset_default_collation="cp866_general_ci" + default_charset_collations="cp866_general_ci cp866_bin" + ;; + dec8) + default_charset_default_collation="dec8_swedish_ci" + default_charset_collations="dec8_swedish_ci dec8_bin" + ;; + euckr) + default_charset_default_collation="euckr_korean_ci" + default_charset_collations="euckr_korean_ci euckr_bin" + ;; + gb2312) + default_charset_default_collation="gb2312_chinese_ci" + default_charset_collations="gb2312_chinese_ci gb2312_bin" + ;; + gbk) + default_charset_default_collation="gbk_chinese_ci" + default_charset_collations="gbk_chinese_ci gbk_bin" + ;; + greek) + default_charset_default_collation="greek_general_ci" + default_charset_collations="greek_general_ci greek_bin" + ;; + hebrew) + default_charset_default_collation="hebrew_general_ci" + default_charset_collations="hebrew_general_ci hebrew_bin" + ;; + hp8) + default_charset_default_collation="hp8_english_ci" + default_charset_collations="hp8_english_ci hp8_bin" + ;; + keybcs2) + default_charset_default_collation="keybcs2_general_ci" + default_charset_collations="keybcs2_general_ci keybcs2_bin" + ;; + koi8r) + default_charset_default_collation="koi8r_general_ci" + default_charset_collations="koi8r_general_ci koi8r_bin" + ;; + koi8u) + default_charset_default_collation="koi8u_general_ci" + default_charset_collations="koi8u_general_ci koi8u_bin" + ;; + latin1) + default_charset_default_collation="latin1_swedish_ci" + default_charset_collations="latin1_general_ci latin1_general_cs latin1_bin latin1_german1_ci latin1_german2_ci latin1_danish_ci latin1_swedish_ci" + ;; + latin2) + default_charset_default_collation="latin2_general_ci" + default_charset_collations="latin2_general_ci latin2_bin latin2_czech_ci latin2_hungarian_ci latin2_croatian_ci" + ;; + latin5) + default_charset_default_collation="latin5_turkish_ci" + default_charset_collations="latin5_turkish_ci latin5_bin" + ;; + latin7) + default_charset_default_collation="latin7_general_ci" + default_charset_collations="latin7_general_ci latin7_general_cs latin7_bin latin7_estonian_cs" + ;; + macce) + default_charset_default_collation="macce_general_ci" + default_charset_collations="macce_general_ci macce_bin" + ;; + macroman) + default_charset_default_collation="macroman_general_ci" + default_charset_collations="macroman_general_ci macroman_bin" + ;; + sjis) + default_charset_default_collation="sjis_japanese_ci" + default_charset_collations="sjis_japanese_ci sjis_bin" + ;; + swe7) + default_charset_default_collation="swe7_swedish_ci" + default_charset_collations="swe7_swedish_ci swe7_bin" + ;; + tis620) + default_charset_default_collation="tis620_thai_ci" + default_charset_collations="tis620_thai_ci tis620_bin" + ;; + ucs2) + default_charset_default_collation="ucs2_general_ci" + default_charset_collations="ucs2_general_ci ucs2_bin" + ;; + ujis) + default_charset_default_collation="ujis_japanese_ci" + default_charset_collations="ujis_japanese_ci ujis_bin" + ;; + utf8) + default_charset_default_collation="utf8_general_ci" + default_charset_collations="utf8_general_ci utf8_bin" + ;; + *) + AC_MSG_ERROR([Charset $cs not available. (Available are: $CHARSETS_AVAILABLE). + See the Installation chapter in the Reference Manual.]); +esac +if test "$default_collation" = default; then + default_collation=$default_charset_default_collation +fi + +valid_default_collation=no +for cl in $default_charset_collations +do + if test x"$cl" = x"$default_collation" + then + valid_default_collation=yes + break + fi +done + +if test x$valid_default_collation = xyes +then + AC_MSG_RESULT([default: $default_charset, collation: $default_collation; compiled in: $CHARSETS]) +else + AC_MSG_ERROR([ + Collation $default_collation is not valid for character set $default_charset. + Valid collations are: $default_charset_collations. + See the Installation chapter in the Reference Manual. + ]); +fi + +AC_DEFINE_UNQUOTED(MYSQL_DEFAULT_CHARSET_NAME,"$default_charset") +AC_DEFINE_UNQUOTED(MYSQL_DEFAULT_COLLATION_NAME,"$default_collation") MYSQL_CHECK_ISAM MYSQL_CHECK_BDB diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in index 793bf36e9fe..91cf3ecc074 100644 --- a/include/mysql_version.h.in +++ b/include/mysql_version.h.in @@ -20,8 +20,5 @@ #define MYSQL_CONFIG_NAME "my" /* mysqld compile time options */ -#ifndef MYSQL_CHARSET -#define MYSQL_CHARSET "@default_charset@" -#endif /* MYSQL_CHARSET */ #endif /* _CUSTOMCONFIG_ */ #endif /* _mysql_version_h */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 86ec00e1e92..6d31abc3dc9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4642,7 +4642,7 @@ static void mysql_init_variables(void) pidfile_name_ptr= pidfile_name; log_error_file_ptr= log_error_file; language_ptr= language; - default_collation_name= 0; + default_collation_name= (char*) MYSQL_DEFAULT_COLLATION_NAME; mysql_data_home= mysql_real_data_home; thd_startup_options= (OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL | OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE); @@ -4681,7 +4681,7 @@ static void mysql_init_variables(void) /* Variables in libraries */ charsets_dir= 0; - sys_charset.value= (char*) MYSQL_CHARSET; + sys_charset.value= (char*) MYSQL_DEFAULT_CHARSET_NAME; sys_charset_system.value= (char*) system_charset_info->csname; /* Set default values for some option variables */ From 9166602342853af34ee7f38ae638692e4fcdd46e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 16:48:48 +0500 Subject: [PATCH 260/399] ctype-win1250ch.c: bug #521 fix: ('3'='4') was true in cp1250_czech_ci strings/ctype-win1250ch.c: bug #521 fix: ('3'='4') was true in cp1250_czech_ci --- strings/ctype-win1250ch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 91271b16373..12a8edc4a8f 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -290,7 +290,7 @@ static uchar NEAR _sort_order_win1250ch1[] = { 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 0 ord 48 0x30 */ -0x92, 0x93, 0x94, 0x95, 0x95, 0x97, 0x98, 0x99, +0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, /* colon ord 58 0x3a */ 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, From 5f9d3e4276913351a9a8485654657d23b8aa7b6d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 17:57:58 +0500 Subject: [PATCH 261/399] CAST(expr AS char) now supports character set with conversion: SELECT CAST(_latin1'string' AS CHAR CHARACTER SET latin2) --- mysql-test/r/cast.result | 13 +++++++++++++ mysql-test/t/cast.test | 9 +++++++++ sql/item_create.cc | 7 +++++-- sql/item_create.h | 2 +- sql/sql_yacc.yy | 24 +++++++++++++----------- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 7909fabc971..42164a2111b 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -28,6 +28,19 @@ cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME) select cast("1:2:3" as TIME); cast("1:2:3" as TIME) 01:02:03 +select cast(_latin1'test' as char character set latin2); +cast(_latin1'test' as char character set latin2) +test +select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); +cast(_koi8r'ÔÅÓÔ' as char character set cp1251) +òåñò +create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` char(4) character set cp1251 NOT NULL default '' +) TYPE=MyISAM CHARSET=latin1 +drop table t1; select cast("2001-1-1" as date) = "2001-01-01"; cast("2001-1-1" as date) = "2001-01-01" 0 diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 8703a6b739d..59b8f3b0c75 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -13,6 +13,15 @@ select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); select cast("1:2:3" as TIME); +# +# Character set convertion +# +select cast(_latin1'test' as char character set latin2); +select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); +create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; +show create table t1; +drop table t1; + # # The following should be fixed in 4.1 # diff --git a/sql/item_create.cc b/sql/item_create.cc index 39e1c2dec22..723610c0df4 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -457,13 +457,16 @@ Item *create_load_file(Item* a) } -Item *create_func_cast(Item *a, Item_cast cast_type) +Item *create_func_cast(Item *a, Item_cast cast_type, CHARSET_INFO *cs) { Item *res; LINT_INIT(res); switch (cast_type) { case ITEM_CAST_BINARY: res= new Item_func_binary(a); break; - case ITEM_CAST_CHAR: res= new Item_char_typecast(a); break; + case ITEM_CAST_CHAR: + res= (cs == NULL) ? new Item_char_typecast(a) : + new Item_func_conv_charset(a,cs); + break; case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break; case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break; case ITEM_CAST_DATE: res= new Item_date_typecast(a); break; diff --git a/sql/item_create.h b/sql/item_create.h index c79fe07b8d4..b679c639244 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -28,7 +28,7 @@ Item *create_func_bit_length(Item* a); Item *create_func_coercibility(Item* a); Item *create_func_ceiling(Item* a); Item *create_func_char_length(Item* a); -Item *create_func_cast(Item *a, Item_cast cast_type); +Item *create_func_cast(Item *a, Item_cast cast_type, CHARSET_INFO *cs); Item *create_func_connection_id(void); Item *create_func_conv(Item* a, Item *b, Item *c); Item *create_func_cos(Item* a); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1d735730801..bab6d05a0e0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2233,10 +2233,12 @@ simple_expr: $$= new Item_func_set_collation($2,new Item_string(binary_keyword, 6, &my_charset_latin1)); } - | CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); } + | CAST_SYM '(' expr AS cast_type ')' + { $$= create_func_cast($3, $5, Lex->charset); } | CASE_SYM opt_expr WHEN_SYM when_list opt_else END { $$= new Item_func_case(* $4, $2, $5 ); } - | CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); } + | CONVERT_SYM '(' expr ',' cast_type ')' + { $$= create_func_cast($3, $5, Lex->charset); } | CONVERT_SYM '(' expr USING charset_name ')' { $$= new Item_func_conv_charset($3,$5); } | CONVERT_SYM '(' expr ',' expr ',' expr ')' @@ -2645,15 +2647,15 @@ in_sum_expr: }; cast_type: - BINARY { $$=ITEM_CAST_BINARY; } - | CHAR_SYM { $$=ITEM_CAST_CHAR; } - | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; } - | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; } - | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; } - | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; } - | DATE_SYM { $$=ITEM_CAST_DATE; } - | TIME_SYM { $$=ITEM_CAST_TIME; } - | DATETIME { $$=ITEM_CAST_DATETIME; } + BINARY { $$=ITEM_CAST_BINARY; Lex->charset= NULL; } + | CHAR_SYM opt_binary { $$=ITEM_CAST_CHAR; } + | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; } + | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; } + | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; } + | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; } + | DATE_SYM { $$=ITEM_CAST_DATE; Lex->charset= NULL; } + | TIME_SYM { $$=ITEM_CAST_TIME; Lex->charset= NULL; } + | DATETIME { $$=ITEM_CAST_DATETIME; Lex->charset= NULL; } ; expr_list: From a100c0e951cd4e2db8efbc385883e408fa164ee9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 16:52:56 +0300 Subject: [PATCH 262/399] added mem_root switching for subselect if it is necessary (bug #518 fixed) mysql-test/r/subselect.result: test of bug #518 mysql-test/t/subselect.test: test of bug #518 sql/item_subselect.cc: test and switch mem_root if it is necessary exec() - wrapper around engine->exec() to test and switch mem_root if necessary sql/item_subselect.h: added storing THD for mem_root testinmg & switching exec() - wrapper around engine->exec() to test and switch mem_root if necessary --- mysql-test/r/subselect.result | 14 +++++++++++++ mysql-test/t/subselect.test | 14 +++++++++++++ sql/item_subselect.cc | 38 +++++++++++++++++++++++++---------- sql/item_subselect.h | 3 +++ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 41620bb6e7f..511517ebdfd 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1134,3 +1134,17 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ref salary salary 5 const 1 Using where 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away drop table t1; +CREATE TABLE t1 ( +ID int(10) unsigned NOT NULL auto_increment, +SUB_ID int(3) unsigned NOT NULL default '0', +REF_ID int(10) unsigned default NULL, +REF_SUB int(3) unsigned default '0', +PRIMARY KEY (ID,SUB_ID), +UNIQUE KEY t1_PK (ID,SUB_ID), +KEY t1_FK (REF_ID,REF_SUB), +KEY t1_REFID (REF_ID) +) TYPE=MyISAM CHARSET=cp1251; +INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); +SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); +REF_ID +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 8377a756c5b..e47409046cd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -716,3 +716,17 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000); explain SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1); drop table t1; + +CREATE TABLE t1 ( + ID int(10) unsigned NOT NULL auto_increment, + SUB_ID int(3) unsigned NOT NULL default '0', + REF_ID int(10) unsigned default NULL, + REF_SUB int(3) unsigned default '0', + PRIMARY KEY (ID,SUB_ID), + UNIQUE KEY t1_PK (ID,SUB_ID), + KEY t1_FK (REF_ID,REF_SUB), + KEY t1_REFID (REF_ID) +) TYPE=MyISAM CHARSET=cp1251; +INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); +SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); +DROP TABLE t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c749fba616f..8c9b3eeebde 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -79,8 +79,10 @@ void Item_subselect::select_transformer(THD *thd, st_select_lex_unit *unit) } -bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) { + thd= thd_param; + if (substitution) { (*ref)= substitution; @@ -115,6 +117,20 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return res; } +bool Item_subselect::exec() +{ + MEM_ROOT *old_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC); + if (&thd->mem_root != old_root) + { + my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root); + int res= engine->exec(); + my_pthread_setspecific_ptr(THR_MALLOC, old_root); + return (res); + } + else + return engine->exec(); +} + Item::Type Item_subselect::type() const { return SUBSELECT_ITEM; @@ -253,12 +269,12 @@ bool Item_singlerow_subselect::null_inside() void Item_singlerow_subselect::bring_value() { - engine->exec(); + exec(); } double Item_singlerow_subselect::val () { - if (!engine->exec() && !value->null_value) + if (!exec() && !value->null_value) { null_value= 0; return value->val(); @@ -272,7 +288,7 @@ double Item_singlerow_subselect::val () longlong Item_singlerow_subselect::val_int () { - if (!engine->exec() && !value->null_value) + if (!exec() && !value->null_value) { null_value= 0; return value->val_int(); @@ -286,7 +302,7 @@ longlong Item_singlerow_subselect::val_int () String *Item_singlerow_subselect::val_str (String *str) { - if (!engine->exec() && !value->null_value) + if (!exec() && !value->null_value) { null_value= 0; return value->val_str(str); @@ -354,7 +370,7 @@ void Item_exists_subselect::fix_length_and_dec() double Item_exists_subselect::val () { - if (engine->exec()) + if (exec()) { reset(); return 0; @@ -364,7 +380,7 @@ double Item_exists_subselect::val () longlong Item_exists_subselect::val_int () { - if (engine->exec()) + if (exec()) { reset(); return 0; @@ -374,7 +390,7 @@ longlong Item_exists_subselect::val_int () String *Item_exists_subselect::val_str(String *str) { - if (engine->exec()) + if (exec()) { reset(); return 0; @@ -385,7 +401,7 @@ String *Item_exists_subselect::val_str(String *str) double Item_in_subselect::val () { - if (engine->exec()) + if (exec()) { reset(); null_value= 1; @@ -398,7 +414,7 @@ double Item_in_subselect::val () longlong Item_in_subselect::val_int () { - if (engine->exec()) + if (exec()) { reset(); null_value= 1; @@ -411,7 +427,7 @@ longlong Item_in_subselect::val_int () String *Item_in_subselect::val_str(String *str) { - if (engine->exec()) + if (exec()) { reset(); null_value= 1; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index fc4dad5a6b3..3ed3f2af0e9 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -36,6 +36,8 @@ class Item_subselect :public Item_result_field my_bool engine_owner; /* Is this item owner of engine */ my_bool value_assigned; /* value already assigned to subselect */ protected: + /* thread handler, will be assigned in fix_fields only */ + THD *thd; /* substitution instead of subselect in case of optimization */ Item *substitution; /* engine that perform execution of subselect (single select or union) */ @@ -81,6 +83,7 @@ public: return null_value; } bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + bool exec(); virtual void fix_length_and_dec(); table_map used_tables() const; From f440077bd03869f48ff278bc2b73fab7a30e282b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 18:02:14 +0300 Subject: [PATCH 263/399] manual types casting to satisfy gcc 3.2.1 compiler --- sql/item_create.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/item_create.cc b/sql/item_create.cc index 723610c0df4..3edec7fdab0 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -464,8 +464,8 @@ Item *create_func_cast(Item *a, Item_cast cast_type, CHARSET_INFO *cs) switch (cast_type) { case ITEM_CAST_BINARY: res= new Item_func_binary(a); break; case ITEM_CAST_CHAR: - res= (cs == NULL) ? new Item_char_typecast(a) : - new Item_func_conv_charset(a,cs); + res= (cs == NULL) ? (Item*) new Item_char_typecast(a) : + (Item*) new Item_func_conv_charset(a,cs); break; case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break; case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break; From 936a8aecd55b7c672401794d0fabb85ca95157a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 20:31:33 +0300 Subject: [PATCH 264/399] srv0srv.c: Prevent the InnoDB main thread from hogging CPU if a table lingers in the background drop queue (though it is essentially a bug if a table end up there at all) innobase/srv/srv0srv.c: Prevent the InnoDB main thread from hogging CPU if a table lingers in the background drop queue (though it is essentially a bug if a table end up there at all) --- innobase/srv/srv0srv.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 84d48bebf97..ac2622df78a 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -2790,6 +2790,15 @@ background_loop: n_tables_to_drop = row_drop_tables_for_mysql_in_background(); + if (n_tables_to_drop > 0) { + /* Do not monopolize the CPU even if there are tables waiting + in the background drop queue. (It is essentially a bug if + MySQL tries to drop a table while there are still open handles + to it and we had to put it to the background drop queue.) */ + + os_thread_sleep(100000); + } + srv_main_thread_op_info = (char*)""; srv_main_thread_op_info = (char*)"flushing buffer pool pages"; From 0829e8706dd7d3ebb415865493ea71297d5d8781 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 May 2003 14:52:25 +0500 Subject: [PATCH 265/399] Fix for bug #529 ("x509" no allowed as field name) --- sql/sql_yacc.yy | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 340fbc1b3dc..c79750c8014 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3397,6 +3397,7 @@ keyword: | USE_FRM {} | VARIABLES {} | WORK_SYM {} + | X509_SYM {} | YEAR_SYM {}; /* Option functions */ From 69e084af1eedff2dda70fcf073dd4fa349718b69 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 May 2003 17:47:31 -0400 Subject: [PATCH 266/399] new version of help --- client/mysql.cc | 83 +-- mysql-test/install_test_db.sh | 210 +------ mysql-test/r/connect.result | 3 + mysql-test/r/help.result | 254 ++++++--- mysql-test/t/help.test | 105 +++- scripts/Makefile.am | 20 +- scripts/fill_help_tables.sh | 596 ++++++++++++++----- scripts/mysql_create_system_tables.sh | 311 ++++++++++ scripts/mysql_install_db.sh | 220 +------ sql/mysql_priv.h | 1 + sql/protocol.h | 2 + sql/sql_help.cc | 790 +++++++++++++++++--------- sql/table.cc | 27 + 13 files changed, 1672 insertions(+), 950 deletions(-) create mode 100644 scripts/mysql_create_system_tables.sh diff --git a/client/mysql.cc b/client/mysql.cc index aa9dcca92db..1bfadb37eb2 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1457,6 +1457,16 @@ int mysql_store_result_for_lazy(MYSQL_RES **result) return 0; } +static void print_help_item(MYSQL_ROW *cur, int num_name, int num_cat, char *last_char) +{ + char ccat= (*cur)[num_cat][0]; + if (*last_char != ccat) + { + put_info(ccat == 'Y' ? "categories :" : "topics :", INFO_INFO); + *last_char= ccat; + } + tee_fprintf(PAGER, " %s\n", (*cur)[num_name]); +} static int com_server_help(String *buffer __attribute__((unused)), char *line __attribute__((unused)), char *help_arg) @@ -1465,14 +1475,15 @@ static int com_server_help(String *buffer __attribute__((unused)), const char *server_cmd= buffer->ptr(); char cmd_buf[100]; MYSQL_RES *result; + MYSQL_FIELD *fields; int error; - + if (help_arg[0] != '\'') { (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS); server_cmd= cmd_buf; } - + if (!status.batch) { old_buffer= *buffer; @@ -1482,15 +1493,16 @@ static int com_server_help(String *buffer __attribute__((unused)), if (!connected && reconnect()) return 1; - if ((error= mysql_real_query_for_lazy(server_cmd,strlen(server_cmd)))) - return error; - if ((error= mysql_store_result_for_lazy(&result))) + if ((error= mysql_real_query_for_lazy(server_cmd,strlen(server_cmd))) || + (error= mysql_store_result_for_lazy(&result))) return error; if (result) { - ulonglong num_rows= mysql_num_rows(result); - if (num_rows == 1) + unsigned int num_fields= mysql_num_fields(result); + my_ulonglong num_rows= mysql_num_rows(result); + fields= mysql_fetch_fields(result); + if (num_fields==3 && num_rows==1) { if (!(cur= mysql_fetch_row(result))) { @@ -1499,46 +1511,45 @@ static int com_server_help(String *buffer __attribute__((unused)), } init_pager(); - if (cur[1][0] == 'Y') - { - tee_fprintf(PAGER, "Help topic \'%s\'\n", cur[0]); - tee_fprintf(PAGER, "%s\n", cur[2]); - tee_fprintf(PAGER, "For help on specific function please type 'help '\nwhere function is one of next:\n%s\n", cur[3]); - } - else - { - tee_fprintf(PAGER, "Name: \'%s\'\n\n", cur[0]); - tee_fprintf(PAGER, "Description:\n%s\n\n", cur[2]); - if (cur[3]) - tee_fprintf(PAGER, "Examples:\n%s\n", cur[3]); - } + tee_fprintf(PAGER, "Name: \'%s\'\n", cur[0]); + tee_fprintf(PAGER, "Description:\n%s", cur[1]); + if (cur[2] && *((char*)cur[2])) + tee_fprintf(PAGER, "Examples:\n%s", cur[2]); + tee_fprintf(PAGER, "\n"); end_pager(); } - else if (num_rows > 1) + else if (num_fields >= 2 && num_rows) { - put_info("Many help items for your request exist", INFO_INFO); - put_info("For more specific request please type 'help ' where item is one of next:", INFO_INFO); - init_pager(); - char last_char= '_'; - while ((cur= mysql_fetch_row(result))) + char last_char; + + int num_name, num_cat; + if (num_fields == 2) { - if (cur[1][0]!=last_char) - { - put_info("-------------------------------------------", INFO_INFO); - put_info(cur[1][0] == 'Y' ? - "categories:" : "functions:", INFO_INFO); - put_info("-------------------------------------------", INFO_INFO); - } - last_char= cur[1][0]; - tee_fprintf(PAGER, "%s\n", cur[0]); + put_info("Many help items for your request exist", INFO_INFO); + put_info("For more specific request please type 'help ' where item is one of next", INFO_INFO); + num_name= 0; + num_cat= 1; + last_char= '_'; } + else if ((cur= mysql_fetch_row(result))) + { + tee_fprintf(PAGER, "You asked help about help category: \"%s\"\n", cur[0]); + put_info("For a more information type 'help ' where item is one of the following", INFO_INFO); + num_name= 1; + num_cat= 2; + print_help_item(&cur,1,2,&last_char); + } + + while ((cur= mysql_fetch_row(result))) + print_help_item(&cur,num_name,num_cat,&last_char); tee_fprintf(PAGER, "\n"); end_pager(); } else { - put_info("\nNothing found\n", INFO_INFO); + put_info("\nNothing found", INFO_INFO); + put_info("Please try to run 'help contents' for list of all accessible topics\n", INFO_INFO); } } diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh index fc3e00d8501..ca6d393e3b4 100644 --- a/mysql-test/install_test_db.sh +++ b/mysql-test/install_test_db.sh @@ -11,10 +11,12 @@ if [ x$1 = x"-bin" ]; then bindir=../bin BINARY_DIST=1 fix_bin=mysql-test + scriptdir=../bin else execdir=../sql bindir=../client fix_bin=. + scriptdir=../scripts fi vardir=var @@ -60,217 +62,11 @@ basedir=. EXTRA_ARG="--language=../sql/share/english/" fi -# Initialize variables -c_d="" i_d="" -c_h="" i_h="" -c_u="" i_u="" -c_f="" i_f="" -c_t="" c_c="" -c_hl="" c_hl="" -c_hc="" c_hc="" -c_clr="" c_clr="" - -# Check for old tables -if test ! -f $mdata/db.frm -then - # mysqld --bootstrap wants one command/line - c_d="$c_d CREATE TABLE db (" - c_d="$c_d Host char(60) DEFAULT '' NOT NULL," - c_d="$c_d Db char(64) DEFAULT '' NOT NULL," - c_d="$c_d User char(16) DEFAULT '' NOT NULL," - c_d="$c_d Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d PRIMARY KEY Host (Host,Db,User)," - c_d="$c_d KEY User (User)" - c_d="$c_d )" - c_d="$c_d comment='Database privileges';" - - i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); - INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');" -fi - -if test ! -f $mdata/host.frm -then - c_h="$c_h CREATE TABLE host (" - c_h="$c_h Host char(60) DEFAULT '' NOT NULL," - c_h="$c_h Db char(64) DEFAULT '' NOT NULL," - c_h="$c_h Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h PRIMARY KEY Host (Host,Db)" - c_h="$c_h )" - c_h="$c_h comment='Host privileges; Merged with database privileges';" -fi - -if test ! -f $mdata/user.frm -then - c_u="$c_u CREATE TABLE user (" - c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL," - c_u="$c_u User char(16) binary DEFAULT '' NOT NULL," - c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL," - c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Process_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u File_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Super_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL," - c_u="$c_u ssl_cipher BLOB NOT NULL," - c_u="$c_u x509_issuer BLOB NOT NULL," - c_u="$c_u x509_subject BLOB NOT NULL," - c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u PRIMARY KEY Host (Host,User)" - c_u="$c_u )" - c_u="$c_u comment='Users and global privileges';" - - i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user (host,user) values ('localhost',''); - INSERT INTO user (host,user) values ('$hostname','');" -fi - -if test ! -f $mdata/func.frm -then - c_f="$c_f CREATE TABLE func (" - c_f="$c_f name char(64) DEFAULT '' NOT NULL," - c_f="$c_f ret tinyint(1) DEFAULT '0' NOT NULL," - c_f="$c_f dl char(128) DEFAULT '' NOT NULL," - c_f="$c_f type enum ('function','aggregate') NOT NULL," - c_f="$c_f PRIMARY KEY (name)" - c_f="$c_f )" - c_f="$c_f comment='User defined functions';" -fi - -if test ! -f $mdata/tables_priv.frm -then - c_t="$c_t CREATE TABLE tables_priv (" - c_t="$c_t Host char(60) DEFAULT '' NOT NULL," - c_t="$c_t Db char(64) DEFAULT '' NOT NULL," - c_t="$c_t User char(16) DEFAULT '' NOT NULL," - c_t="$c_t Table_name char(60) DEFAULT '' NOT NULL," - c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," - c_t="$c_t Timestamp timestamp(14)," - c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL," - c_t="$c_t Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," - c_t="$c_t KEY Grantor (Grantor)" - c_t="$c_t )" - c_t="$c_t comment='Table privileges';" -fi - -if test ! -f $mdata/columns_priv.frm -then - c_c="$c_c CREATE TABLE columns_priv (" - c_c="$c_c Host char(60) DEFAULT '' NOT NULL," - c_c="$c_c Db char(64) DEFAULT '' NOT NULL," - c_c="$c_c User char(16) DEFAULT '' NOT NULL," - c_c="$c_c Table_name char(64) DEFAULT '' NOT NULL," - c_c="$c_c Column_name char(64) DEFAULT '' NOT NULL," - c_c="$c_c Timestamp timestamp(14)," - c_c="$c_c Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_c="$c_c PRIMARY KEY (Host,Db,User,Table_name,Column_name)" - c_c="$c_c )" - c_c="$c_c comment='Column privileges';" -fi - -if test ! -f $mdata/help_topic.frm -then - c_hl="$c_hl CREATE TABLE help_topic (" - c_hl="$c_hl help_topic_id int unsigned not null auto_increment," - c_hl="$c_hl name varchar(64) not null," - c_hl="$c_hl description text not null," - c_hl="$c_hl example text not null," - c_hl="$c_hl url varchar(128) not null," - c_hl="$c_hl primary key (help_topic_id)," - c_hl="$c_hl unique index (name)" - c_hl="$c_hl )" - c_hl="$c_hl comment='help topics';" -fi - -if test ! -f $mdata/help_category.frm -then - c_clr="$c_clr CREATE TABLE help_category (" - c_clr="$c_clr help_category_id smallint unsigned not null auto_increment," - c_clr="$c_clr name varchar(64) not null," - c_clr="$c_clr url varchar(128) not null," - c_clr="$c_clr primary key (help_category_id)," - c_clr="$c_clr unique index (name)" - c_clr="$c_clr )" - c_clr="$c_clr comment='help topics-categories relation';" -fi - -if test ! -f $mdata/help_relation.frm -then - c_hc="$c_hc CREATE TABLE help_relation (" - c_hc="$c_hc help_topic_id int unsigned not null references help_topic," - c_hc="$c_hc help_category_id smallint unsigned not null references help_category," - c_hc="$c_hc primary key (help_category_id, help_topic_id)," - c_hc="$c_hc )" - c_hc="$c_hc comment='categories of help topics';" -fi - mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \ --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG" echo "running $mysqld_boot" -if $mysqld_boot << END_OF_DATA -use mysql; -$c_d -$i_d - -$c_h -$i_h - -$c_u -$i_u - -$c_f -$i_f - -$c_t -$c_c - -$c_hl -$c_hc -$c_clr -END_OF_DATA +if $scriptdir/mysql_create_system_tables test $mdata $hostname | $mysqld_boot then exit 0 else diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index b7243ac5d0b..a80ddc24d05 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -4,6 +4,7 @@ columns_priv db func help_category +help_keyword help_relation help_topic host @@ -19,6 +20,7 @@ columns_priv db func help_category +help_keyword help_relation help_topic host @@ -34,6 +36,7 @@ columns_priv db func help_category +help_keyword help_relation help_topic host diff --git a/mysql-test/r/help.result b/mysql-test/r/help.result index 4da4a84d4ad..d22539b2bcb 100644 --- a/mysql-test/r/help.result +++ b/mysql-test/r/help.result @@ -1,123 +1,243 @@ -truncate mysql.help_topic; -truncate mysql.help_category; -truncate mysql.help_relation; -insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1'); -SELECT @topic1_id:=LAST_INSERT_ID(); -@topic1_id:=LAST_INSERT_ID() +insert into mysql.help_category(help_category_id,name)values(1,'impossible_category_1'); +select @category1_id:= 1; +@category1_id:= 1 1 -insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2'); -SELECT @topic2_id:=LAST_INSERT_ID(); -@topic2_id:=LAST_INSERT_ID() +insert into mysql.help_category(help_category_id,name)values(2,'impossible_category_2'); +select @category2_id:= 2; +@category2_id:= 2 2 -insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3'); -SELECT @topic3_id:=LAST_INSERT_ID(); -@topic3_id:=LAST_INSERT_ID() +insert into mysql.help_category(help_category_id,name,parent_category_id)values(3,'impossible_category_3',@category2_id); +select @category3_id:= 3; +@category3_id:= 3 3 -insert into mysql.help_category(name)values('impossible_category_1'); -SELECT @category1_id:=LAST_INSERT_ID(); -@category1_id:=LAST_INSERT_ID() +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(1,'impossible_function_1',@category1_id,'description of \n impossible_function1\n','example of \n impossible_function1'); +select @topic1_id:= 1; +@topic1_id:= 1 1 -insert into mysql.help_category(name)values('impossible_category_2'); -SELECT @category2_id:=LAST_INSERT_ID(); -@category2_id:=LAST_INSERT_ID() +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(2,'impossible_function_2',@category1_id,'description of \n impossible_function2\n','example of \n impossible_function2'); +select @topic2_id:= 2; +@topic2_id:= 2 2 -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id); +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(3,'impossible_function_3',@category2_id,'description of \n impossible_function3\n','example of \n impossible_function3'); +select @topic3_id:= 3; +@topic3_id:= 3 +3 +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(4,'impossible_function_4',@category2_id,'description of \n impossible_function4\n','example of \n impossible_function4'); +select @topic4_id:= 4; +@topic4_id:= 4 +4 +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(5,'impossible_function_7',@category3_id,'description of \n impossible_function5\n','example of \n impossible_function7'); +select @topic5_id:= 5; +@topic5_id:= 5 +5 +insert into mysql.help_keyword(help_keyword_id,name)values(1,'impossible_function_1'); +select @keyword1_id:= 1; +@keyword1_id:= 1 +1 +insert into mysql.help_keyword(help_keyword_id,name)values(2,'impossible_function_5'); +select @keyword2_id:= 2; +@keyword2_id:= 2 +2 +insert into mysql.help_keyword(help_keyword_id,name)values(3,'impossible_function_6'); +select @keyword3_id:= 3; +@keyword3_id:= 3 +3 +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword1_id,@topic2_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword2_id,@topic1_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic3_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic4_id); help 'function_of_my_dream'; -Name Category -impossible_category_1 Y -impossible_category_2 Y +name is_it_category help '%possible_f%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_func%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_category%'; -Name Category +name is_it_category impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y help 'impossible_%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y +help '%function_1'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 help '%function_2'; -Name Category Description Example -impossible_function_2 N description of - impossible_function2 example of +name description example +impossible_function_2 description of impossible_function2 + example of + impossible_function2 +help '%function_3'; +name description example +impossible_function_3 description of + impossible_function3 + example of + impossible_function3 +help '%function_4'; +name description example +impossible_function_4 description of + impossible_function4 + example of + impossible_function4 +help '%function_5'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 +help '%function_6'; +name is_it_category +impossible_function_3 N +impossible_function_4 N +help '%function_7'; +name description example +impossible_function_7 description of + impossible_function5 + example of + impossible_function7 help '%category_2'; -Name Category Description Example -impossible_category_2 Y impossible_function_2 -impossible_function_3 - +source_category_name name is_it_category +impossible_category_2 impossible_function_3 N +impossible_category_2 impossible_function_4 N +impossible_category_2 impossible_category_3 Y help 'impossible_function_1'; -Name Category Description Example -impossible_function_1 N description of - impossible_function1 example of +name description example +impossible_function_1 description of + impossible_function1 + example of impossible_function1 help 'impossible_category_1'; -Name Category Description Example -impossible_category_1 Y impossible_function_1 -impossible_function_2 - +source_category_name name is_it_category +impossible_category_1 impossible_function_1 N +impossible_category_1 impossible_function_2 N +alter table mysql.help_relation type=innodb; +alter table mysql.help_keyword type=innodb; alter table mysql.help_topic type=innodb; alter table mysql.help_category type=innodb; -alter table mysql.help_relation type=innodb; help 'function_of_my_dream'; -Name Category -impossible_category_1 Y -impossible_category_2 Y -help '%ble_f%'; -Name Category +name is_it_category +help '%possible_f%'; +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_func%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N help 'impossible_category%'; -Name Category +name is_it_category impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y help 'impossible_%'; -Name Category +name is_it_category impossible_function_1 N impossible_function_2 N impossible_function_3 N +impossible_function_4 N +impossible_function_7 N impossible_category_1 Y impossible_category_2 Y +impossible_category_3 Y +help '%function_1'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 help '%function_2'; -Name Category Description Example -impossible_function_2 N description of - impossible_function2 example of +name description example +impossible_function_2 description of impossible_function2 + example of + impossible_function2 +help '%function_3'; +name description example +impossible_function_3 description of + impossible_function3 + example of + impossible_function3 +help '%function_4'; +name description example +impossible_function_4 description of + impossible_function4 + example of + impossible_function4 +help '%function_5'; +name description example +impossible_function_1 description of + impossible_function1 + example of + impossible_function1 +help '%function_6'; +name is_it_category +impossible_function_3 N +impossible_function_4 N +help '%function_7'; +name description example +impossible_function_7 description of + impossible_function5 + example of + impossible_function7 help '%category_2'; -Name Category Description Example -impossible_category_2 Y impossible_function_2 -impossible_function_3 - +source_category_name name is_it_category +impossible_category_2 impossible_function_3 N +impossible_category_2 impossible_function_4 N +impossible_category_2 impossible_category_3 Y help 'impossible_function_1'; -Name Category Description Example -impossible_function_1 N description of - impossible_function1 example of +name description example +impossible_function_1 description of + impossible_function1 + example of impossible_function1 help 'impossible_category_1'; -Name Category Description Example -impossible_category_1 Y impossible_function_1 -impossible_function_2 - +source_category_name name is_it_category +impossible_category_1 impossible_function_1 N +impossible_category_1 impossible_function_2 N +alter table mysql.help_relation type=myisam; +alter table mysql.help_keyword type=myisam; alter table mysql.help_topic type=myisam; alter table mysql.help_category type=myisam; -alter table mysql.help_relation type=myisam; +delete from mysql.help_topic where help_topic_id=@topic1_id; +delete from mysql.help_topic where help_topic_id=@topic2_id; +delete from mysql.help_topic where help_topic_id=@topic3_id; +delete from mysql.help_topic where help_topic_id=@topic4_id; +delete from mysql.help_topic where help_topic_id=@topic5_id; +delete from mysql.help_category where help_category_id=@category3_id; +delete from mysql.help_category where help_category_id=@category2_id; +delete from mysql.help_category where help_category_id=@category1_id; +delete from mysql.help_keyword where help_keyword_id=@keyword1_id; +delete from mysql.help_keyword where help_keyword_id=@keyword2_id; +delete from mysql.help_keyword where help_keyword_id=@keyword3_id; +delete from mysql.help_relation where help_keyword_id=@keyword1_id and help_topic_id=@topic2_id; +delete from mysql.help_relation where help_keyword_id=@keyword2_id and help_topic_id=@topic1_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic3_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic4_id; diff --git a/mysql-test/t/help.test b/mysql-test/t/help.test index c36b670c6b3..82312340336 100644 --- a/mysql-test/t/help.test +++ b/mysql-test/t/help.test @@ -1,50 +1,115 @@ -- source include/have_innodb.inc -truncate mysql.help_topic; -truncate mysql.help_category; -truncate mysql.help_relation; +# category: topic: keyword: +# +# impossible_category_1 +# impossible_function_1 +# impossible_function_5 +# impossible_function_2 +# impossible_function_1 +# impossible_category_2 +# impossible_function_3 +# impossible_function_6 +# impossible_function_4 +# impossible_function_6 +# impossible_category_3 +# impossible_function_7 -insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1'); -SELECT @topic1_id:=LAST_INSERT_ID(); -insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2'); -SELECT @topic2_id:=LAST_INSERT_ID(); -insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3'); -SELECT @topic3_id:=LAST_INSERT_ID(); +insert into mysql.help_category(help_category_id,name)values(1,'impossible_category_1'); +select @category1_id:= 1; +insert into mysql.help_category(help_category_id,name)values(2,'impossible_category_2'); +select @category2_id:= 2; +insert into mysql.help_category(help_category_id,name,parent_category_id)values(3,'impossible_category_3',@category2_id); +select @category3_id:= 3; -insert into mysql.help_category(name)values('impossible_category_1'); -SELECT @category1_id:=LAST_INSERT_ID(); -insert into mysql.help_category(name)values('impossible_category_2'); -SELECT @category2_id:=LAST_INSERT_ID(); +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(1,'impossible_function_1',@category1_id,'description of \n impossible_function1\n','example of \n impossible_function1'); +select @topic1_id:= 1; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(2,'impossible_function_2',@category1_id,'description of \n impossible_function2\n','example of \n impossible_function2'); +select @topic2_id:= 2; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(3,'impossible_function_3',@category2_id,'description of \n impossible_function3\n','example of \n impossible_function3'); +select @topic3_id:= 3; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(4,'impossible_function_4',@category2_id,'description of \n impossible_function4\n','example of \n impossible_function4'); +select @topic4_id:= 4; +insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(5,'impossible_function_7',@category3_id,'description of \n impossible_function5\n','example of \n impossible_function7'); +select @topic5_id:= 5; -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id); -insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id); +insert into mysql.help_keyword(help_keyword_id,name)values(1,'impossible_function_1'); +select @keyword1_id:= 1; +insert into mysql.help_keyword(help_keyword_id,name)values(2,'impossible_function_5'); +select @keyword2_id:= 2; +insert into mysql.help_keyword(help_keyword_id,name)values(3,'impossible_function_6'); +select @keyword3_id:= 3; +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword1_id,@topic2_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword2_id,@topic1_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic3_id); +insert into mysql.help_relation(help_keyword_id,help_topic_id)values(@keyword3_id,@topic4_id); + +############## help 'function_of_my_dream'; help '%possible_f%'; help 'impossible_func%'; help 'impossible_category%'; help 'impossible_%'; + +help '%function_1'; help '%function_2'; +help '%function_3'; +help '%function_4'; +help '%function_5'; +help '%function_6'; +help '%function_7'; + help '%category_2'; help 'impossible_function_1'; help 'impossible_category_1'; +############## +alter table mysql.help_relation type=innodb; +alter table mysql.help_keyword type=innodb; alter table mysql.help_topic type=innodb; alter table mysql.help_category type=innodb; -alter table mysql.help_relation type=innodb; +############## help 'function_of_my_dream'; -help '%ble_f%'; +help '%possible_f%'; help 'impossible_func%'; help 'impossible_category%'; help 'impossible_%'; + +help '%function_1'; help '%function_2'; +help '%function_3'; +help '%function_4'; +help '%function_5'; +help '%function_6'; +help '%function_7'; + help '%category_2'; help 'impossible_function_1'; help 'impossible_category_1'; +############## +alter table mysql.help_relation type=myisam; +alter table mysql.help_keyword type=myisam; alter table mysql.help_topic type=myisam; alter table mysql.help_category type=myisam; -alter table mysql.help_relation type=myisam; + +delete from mysql.help_topic where help_topic_id=@topic1_id; +delete from mysql.help_topic where help_topic_id=@topic2_id; +delete from mysql.help_topic where help_topic_id=@topic3_id; +delete from mysql.help_topic where help_topic_id=@topic4_id; +delete from mysql.help_topic where help_topic_id=@topic5_id; + +delete from mysql.help_category where help_category_id=@category3_id; +delete from mysql.help_category where help_category_id=@category2_id; +delete from mysql.help_category where help_category_id=@category1_id; + +delete from mysql.help_keyword where help_keyword_id=@keyword1_id; +delete from mysql.help_keyword where help_keyword_id=@keyword2_id; +delete from mysql.help_keyword where help_keyword_id=@keyword3_id; + +delete from mysql.help_relation where help_keyword_id=@keyword1_id and help_topic_id=@topic2_id; +delete from mysql.help_relation where help_keyword_id=@keyword2_id and help_topic_id=@topic1_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic3_id; +delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic4_id; diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 88f561e0e6d..1134226bfaf 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -32,7 +32,9 @@ bin_SCRIPTS = @server_scripts@ \ mysqldumpslow \ mysql_explain_log \ mysql_tableinfo \ - mysqld_multi + mysqld_multi \ + fill_help_tables \ + mysql_create_system_tables EXTRA_SCRIPTS = make_binary_distribution.sh \ make_win_src_distribution.sh \ @@ -54,14 +56,13 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \ mysqld_multi.sh \ mysql_tableinfo.sh \ mysqld_safe.sh \ - fill_help_tables.sh + fill_help_tables.sh \ + mysql_create_system_tables.sh EXTRA_DIST = $(EXTRA_SCRIPTS) \ mysqlaccess.conf \ mysqlbug -pkgdata_DATA = fill_help_tables.sql - # mysqlbug should be distributed built so that people can report build # failures with it. CLEANFILES = @server_scripts@ \ @@ -81,7 +82,7 @@ CLEANFILES = @server_scripts@ \ mysqldumpslow \ mysqld_multi \ fill_help_tables \ - fill_help_tables.sql + mysql_create_system_tables SUPERCLEANFILES = mysqlbug @@ -137,12 +138,5 @@ SUFFIXES = .sh # Don't update the files from bitkeeper %::SCCS/s.% -all: fill_help_tables.sql make_win_src_distribution make_binary_distribution +all: make_win_src_distribution make_binary_distribution -# The following rule is here to ensure that build will continue -# even if we don't have perl installed. In this case the help tables -# will be empty - -fill_help_tables.sql: fill_help_tables ../Docs/manual.texi - -./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql - echo "" >> fill_help_tables.sql diff --git a/scripts/fill_help_tables.sh b/scripts/fill_help_tables.sh index e21b0ff2bb0..b8cf4ccb3a7 100644 --- a/scripts/fill_help_tables.sh +++ b/scripts/fill_help_tables.sh @@ -1,31 +1,178 @@ #!@PERL@ # -# Usage: fill_help_tables -# Example: ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql +# Copyright (C) 2003 MySQL AB +# For a more info consult the file COPYRIGHT distributed with this file. # # This script generates the SQL statements required by mysql_install_db to # fill up the tables for the server-side online function help, which can be # invoked with "help " from the MySQL client. # +# Usage: +# fill_help_tables OPTIONS < manual.texi > fill_help_tables.sql +# +# --help display this helpscreen and exit +# --verbose print information about help completeness to STDERR +# --lexems=path path to file with lexems. it is used with verbose option. +# default value is ../sql/lex.h +# Examples: +# ./fill_help_tables --help +# ./fill_help_tables --verbose < manual.texi > fill_help_tables.sql +# ./fill_help_tables < manual.texi > fill_help_tables.sql +# # Please note, that you first need to update Docs/manual.texi with the # manual file from the separate "mysqldoc" BitKeeper-Tree! The manual.texi # included in the source tree is just an empty stub file - the full manual # is now maintained in a separate tree. # +# extra tags in manual.texi: +# +# @c help_category [@] +# +# @c description_for_help_topic +# .... +# @c end_description_for_help_topic +# +# @c example_for_help_topic +# @example +# .... +# @example +# +# # Original version by Victor Vagin # -my $cat_name= ""; -my $func_name= ""; -my $text= ""; -my $example= ""; +use strict; +use Getopt::Long; -local $mode= ""; +my $insert_portion_size= 25; +my $error_prefix= "help parsing error:"; + +my $path_to_lex_file= "../sql/lex.h"; +my $verbose_option= 0; +my $help_option= 0; + +GetOptions( + "help",\$help_option, + "verbose",\$verbose_option, + "lexems=s",\$path_to_lex_file +); + +if ($help_option ne 0) +{ + print <<_HELP; + +This script generates the SQL statements required by mysql_install_db to +fill up the tables for the server-side online function help, which can be +invoked with "help " from the MySQL client. + +Usage: + fill_help_tables OPTIONS < manual.texi > fill_help_tables.sql + + --help display this helpscreen and exit + --verbose print information about help completeness to STDERR + --lexems=path path to file with lexems. it is used with verbose option. + default value is ../sql/lex.h + +Examples: + ./fill_help_tables --help + ./fill_help_tables --verbose < manual.texi > fill_help_tables.sql + ./fill_help_tables < manual.texi > fill_help_tables.sql + +_HELP + exit; +} + +my $current_category= ""; +my $current_parent_category= ""; +my $next_example_for_topic= ""; + +my %topics; +my %categories; +my %keywords; + +$categories{Contents}->{__parent_category__}= ""; + +sub add_topic_to_category +{ + my ($topic_name)= @_; + + $categories{$current_category}->{$topic_name}= $topics{$topic_name}; + my $category= $categories{$current_category}; + + if (exists($category->{__parent_category__})) + { + my $old_parent= $category->{__parent_category__}; + if ($old_parent ne $current_parent_category) + { + print STDERR "$error_prefix wrong parent for $current_category\n"; + } + } + + if ($current_parent_category ne "") + { + $category->{__parent_category__}= $current_parent_category; + } + + if (exists($topics{$topic_name}->{category})) + { + my $old_category= $topics{$topic_name}->{category}; + if ($old_category ne $category) + { + print STDERR "$error_prefix wrong category for $topic_name\n"; + } + } + + $topics{$topic_name}->{category}= $category; +} + +sub add_example +{ + my ($topic_name,$example)= @_; + + $topic_name=~ tr/a-z/A-Z/; + + if (exists($topics{$topic_name}->{example})) + { + print STDERR "$error_prefix double example for $topic_name\n"; + } + + $topics{$topic_name}->{example}= $example; + add_topic_to_category($topic_name); +} + +sub add_description +{ + my ($topic_name,$description)= @_; + + $topic_name=~ tr/a-z/A-Z/; + + if (exists($topics{$topic_name}->{description})) + { + print STDERR "$error_prefix double description for $topic_name\n"; + } + $topics{$topic_name}->{description}= $description; + add_topic_to_category($topic_name); +} + +sub add_keyword +{ + my ($topic_name,$keyword)= @_; + + $topic_name=~ tr/a-z/A-Z/; + $keyword=~ tr/a-z/A-Z/; + + push(@{$topics{$topic_name}->{keywords}},$keyword); + if (exists($keywords{$keyword}->{$topic_name})) + { + print STDERR "$error_prefix double keyword $keyword for $topic_name\n"; + } + $keywords{$keyword}->{$topic_name}= $topics{$topic_name}; +} sub prepare_name { my ($a)= @_; - + $a =~ s/(\@itemize \@bullet)/ /g; $a =~ s/(\@end itemize)/ /g; $a =~ s/(\@end multitable)/ /g; @@ -46,41 +193,57 @@ sub prepare_name $a =~ s/\`/\`\`/g; $a =~ s/\@table \@code/ /g; - $a =~ s/\(\)//g; - - $a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3/gxs; #$a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3 $1/gxs; - $a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1/gxs;#$a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1 $2/gxs; + $a =~ s/\"/\\\"/g; + + $a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3/gxs; + $a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1/gxs; $a =~ s/((\w|\s)+)\((.+)\)/$1/gxs; - + return $a; } -sub prepare_text +sub prepare_description { my ($a)= @_; - $a =~ s/(\@itemize \@bullet)/ /g; - $a =~ s/(\@end itemize)/ /g; + $a =~ s/(\@itemize \@bullet\n)//g; + $a =~ s/(\@c help_keyword (.*?)\n)//g; + $a =~ s/(\@end itemize\n)//g; + $a =~ s/(\@end example\n)//g; + $a =~ s/(\@example\n)//g; + $a =~ s/(\@{)/{/g; + $a =~ s/(\@})/}/g; $a =~ s/(\@end multitable)/ /g; $a =~ s/(\@end table)/ /g; - $a =~ s/(\@cindex(.*?)\n)/ /g; + $a =~ s/(\@cindex(.*?)\n)//g; + $a =~ s/(\@findex(.*?)\n)//g; + $a =~ s/(\@table(.*?)\n)//g; $a =~ s/(\@multitable \@columnfractions(.*?)\n)/ /g; $a =~ s/(\@node(.*?)\n)/ /g; $a =~ s/(\@tab)/\t/g; $a =~ s/\@itemx/ /g; - $a =~ s/\@item/ /g; + $a =~ s/(\@item\n(\s*?))(\S)/ --- $3/g; + $a =~ s/(\@item)/ /g; + $a =~ s/(\@tindex\s(.*?)\n)//g; + $a =~ s/(\@c\s(.*?)\n)//g; $a =~ s/\@code\{((.|\n)+?)\}/$1/go; $a =~ s/\@strong\{(.+?)\}/$1/go; $a =~ s/\@samp\{(.+?)\}/$1/go; $a =~ s/\@emph\{((.|\n)+?)\}/\/$1\//go; $a =~ s/\@xref\{((.|\n)+?)\}/See also : [$1]/go; $a =~ s/\@ref\{((.|\n)+?)\}/[$1]/go; - $a =~ s/\'/\'\'/g; + $a =~ s/\@w\{((.|\n)+?)\}/$1/go; + $a =~ s/\@strong\{((.|\n)+?)\}/\n!!!!\n$1\n!!!!\n/go; + $a =~ s/\@file\{((.|\n)+?)\}/\*$1/go; $a =~ s/\\/\\\\/g; - $a =~ s/\`/\`\`/g; - $a =~ s/(\n*?)$//g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; + $a =~ s/\n\n$/\n/g; $a =~ s/\n/\\n/g; + $a =~ s/\"/\\\"/g; $a =~ s/\@table \@code/ /g; @@ -91,148 +254,291 @@ sub prepare_example { my ($a)= @_; - $a =~ s/\'/\'\'/g; + $a =~ s/(^\@c for_help_topic(.*?)\n)//g; + $a =~ s/\\/\\\\/g; - $a =~ s/\`/\`\`/g; + $a =~ s/(\@{)/{/g; + $a =~ s/(\@})/}/g; + $a =~ s/(\@\@)/\@/g; $a =~ s/(\n*?)$//g; $a =~ s/\n/\\n/g; - + $a =~ s/\"/\\\"/g; + return $a; } -sub flush_all +sub parse_example { - my ($mode) = @_; - - if ($mode eq ""){return;} - - $func_name= prepare_name($func_name); - $text= prepare_text($text); - $example= prepare_example($example); - - if ($func_name ne "" && $text ne "" && !($func_name =~ /[abcdefghikjlmnopqrstuvwxyz]/)){ - print "INSERT IGNORE INTO help_topic (name,description,example) VALUES ("; - print "'$func_name',"; - print "'$text',"; - print "'$example'"; - print ");\n"; - print "INSERT IGNORE INTO help_relation (help_category_id,help_topic_id) VALUES (\@cur_category,LAST_INSERT_ID());\n"; + return if (!($_=~/\@example/)); + return if ($next_example_for_topic eq ""); + + my $topic_name= $next_example_for_topic; + $next_example_for_topic= ""; + my $text= ""; + + while (<>) + { + last if ($_=~/\@end example/); + $text .= $_; } + + $text= prepare_example($text); - $func_name= ""; - $text= ""; - $example= ""; - $mode= ""; + add_example($topic_name,$text) if ($topic_name ne ""); } -sub new_category +sub parse_example_for_topic { - my ($category)= @_; - - $category= prepare_text($category); - - print "INSERT IGNORE INTO help_category (name) VALUES (\'$category\');\n"; - print "SET \@cur_category=LAST_INSERT_ID();\n"; + my ($for_topic)= m|\@c example_for_help_topic (.+?)$|; + return if ($for_topic eq ""); + + $next_example_for_topic= $for_topic; } -#print "INSERT IGNORE INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n"; -#print "CREATE DATABASE mysql_help;\n"; - -print "USE mysql;\n"; - -print "DROP TABLE IF EXISTS help_topic;\n"; -print "CREATE TABLE help_topic ("; -print " help_topic_id int unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " description text not null,"; -print " example text not null,"; -print " url varchar(128) not null,"; -print " primary key (help_topic_id),"; -print " unique index(name)"; -print ") type=myisam;\n\n"; - -print "DROP TABLE IF EXISTS help_category;\n"; -print "CREATE TABLE help_category ("; -print " help_category_id smallint unsigned not null auto_increment,"; -print " name varchar(64) not null,"; -print " url varchar(128) not null,"; -print " primary key (help_category_id),"; -print " unique index (name)"; -print ") type=myisam;\n\n"; - -print "DROP TABLE IF EXISTS help_relation;\n"; -print "CREATE TABLE help_relation ("; -print" help_topic_id int unsigned not null references help_topic,"; -print" help_category_id smallint unsigned not null references help_category,"; -print" primary key (help_category_id, help_topic_id),"; -print ") type=myisam;\n\n"; - -print "SET \@cur_category=null;\n\n"; - -my $in_section_6_3= 0; - -for(<>) +sub parse_description { - if ($_=~/\@section Functions for Use in \@code{SELECT} and \@code{WHERE} Clauses/ && - !$in_section_6_3){ - $in_section_6_3= 1; - next; + my ($topic_description)= m|\@c description_for_help_topic (.+?)$|; + return if ($topic_description eq ""); + + my ($topic_name,$topic_keywords)= split(/ /,$topic_description); + + if ($topic_name eq "" || $topic_keywords eq "") + { + $topic_name= $topic_description; } - - if ($_=~/\@section/ && $in_section_6_3){ - $in_section_6_3= 0; - next; + else + { + my $keyword; + foreach $keyword (split(/ /,$topic_keywords)) + { + add_keyword($topic_name,$keyword) if ($keyword ne ""); + } } - - if (!$in_section_6_3) { next; } - - my $c_name= ""; - - ($c_name)=m|\@c for_mysql_help,(.+?)$|; - if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ - ($cat_name)= $c_name; - new_category($cat_name); - next; + + my $text= ""; + + while (<>) + { + last if ($_=~/\@c end_description_for_help_topic/); + $text .= $_; } - - ($c_name)=m|\@subsubsection (.+?)$|; - if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ - ($cat_name)= $c_name; - new_category($cat_name); - next; - } - - ($c_name)=m|\@subsection (.+?)$|; - if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ - ($cat_name)= $c_name; - new_category($cat_name); - next; - } - - ($f_name)=m|\@findex (.+?)$|; - if (!($f_name eq "")){ - flush_all($mode); - ($func_name)= ($f_name); - $mode= "text"; - next; - } - - if ($_=~/\@example/ && ($mode eq "text")){ - $mode= "example"; - next; - } - - if ($_=~/\@end example/ && ($mode eq "example")){ - flush_all($mode); - next; - } - - if ($mode eq "text") { $text .= $_; } - if ($mode eq "example") { $example .= $_; } + + $text= prepare_description($text); + add_description($topic_name,$text); } +sub parse_category +{ + my ($c_name,$pc_name)= m|\@c help_category (.+?)\@(.+?)$|; -print "DELETE help_category "; -print "FROM help_category "; -print "LEFT JOIN help_relation ON help_category.help_category_id=help_relation.help_category_id "; -print "WHERE help_relation.help_category_id is null;" + if ($pc_name ne "") + { + $current_category= prepare_name($c_name); + $current_parent_category= prepare_name($pc_name); + } + else + { + my ($c_name)=m|\@c help_category (.+?)$|; + return if ($c_name eq ""); + + $current_category= prepare_name($c_name); + $current_parent_category= "Contents" + } +} + +# parse manual: + +while (<>) +{ + parse_example_for_topic (); + parse_example (); + parse_description (); + parse_category (); +} + +# test results of parsing: + +sub print_bad_names +{ + my($names,$prompt)= @_; + if (scalar(@{$names})) + { + print STDERR "\n-------------- $prompt : \n\n"; + my $name; + foreach $name (@{$names}) + { + print STDERR "$name\n"; + } + print STDERR "\n"; + } +} + +sub print_verbose_errors +{ + my($name_of_log_file)= @_; + + my @without_help; + my @description_with_at; + my @example_with_at; + my @without_description; + my @without_example; + + print STDERR "\n-------------- parameters of help completeness : \n\n"; + + my $count_lex= 0; + if (!open (TLEX,"<$path_to_lex_file")) + { + print STDERR "Error opening lex file \"$path_to_lex_file\" $!\n"; + } + else + { + for () + { + my ($a,$lex,$b)=m|(.+?)\"(.+?)\"(.+?)$|; + next if ($lex eq ""); + $count_lex++; + next if (exists($topics{$lex}) || exists($keywords{$lex})); + push(@without_help,$lex); + } + close(TLEX); + print STDERR "number of lexems in \"$path_to_lex_file\" - $count_lex\n"; + } + + my $name; + my @topic_names= keys(%topics); + foreach $name (@topic_names) + { + my $topic= $topics{$name}; + push(@description_with_at,$name) if ($topic->{description}=~/\@/); + push(@example_with_at,$name) if ($topic->{example}=~/\@/); + push(@without_description,$name) if (!exists($topic->{description})); + push(@without_example,$name) if (!exists($topic->{example})); + } + + my $count_categories= scalar(keys(%categories)); + print STDERR "number of help categories - ",$count_categories,"\n"; + my $count_topics= scalar(@topic_names); + print STDERR "number of help topics - ",$count_topics,"\n"; + my $count_keywords= scalar(keys(%keywords)); + print STDERR "number of help keywords - ",$count_keywords,"\n"; + + my $count_without_help= scalar(@without_help); + print_bad_names(\@without_help,"lexems without help (". + $count_without_help." ~ ". + (int (($count_without_help/$count_lex)*100)). + "%)"); + print_bad_names(\@description_with_at, + " topics below have symbol \'@\' in their descriptions.\n". + "it's probably the litter from 'texi' tags (script needs fixing)"); + print_bad_names(\@example_with_at, + " topics below have symbol \'@\' in their examples.\n". + "it's probably the litter from 'texi' tags (script needs fixing)"); + print_bad_names(\@without_description,"topics without description"); + + my $count_without_example= scalar(@without_example); + print_bad_names(\@without_example,"topics without example (". + $count_without_example." ~ ". + (int (($count_without_example/$count_topics)*100)). + "%)"); +} + +print_verbose_errors if ($verbose_option ne 0); + +# output result + +sub print_insert_header +{ + my($count,$header)= @_; + + if ($count % $insert_portion_size ne 0) { + print ","; + } else { + print ";\n" if ($count ne 0); + print "$header"; + } +} + +print "delete from help_topic;\n"; +print "delete from help_category;\n"; +print "delete from help_keyword;\n"; +print "delete from help_relation;\n\n"; + +my @category_names= keys(%categories); +if (scalar(@category_names)) +{ + my $cat_name; + my $count= 0; + foreach $cat_name (@category_names) + { + $categories{$cat_name}->{__id__}= $count; + $count++; + } + + my $header= "insert into help_category ". + "(help_category_id,name,parent_category_id) values "; + $count= 0; + foreach $cat_name (@category_names) + { + print_insert_header($count,$header); + my $parent_cat_name= $categories{$cat_name}->{__parent_category__}; + my $parent_cat_id= $parent_cat_name eq "" + ? "-1" : $categories{$parent_cat_name}->{__id__}; + print "($count,\"$cat_name\",$parent_cat_id)"; + $count++; + } + printf ";\n\n"; +} + +my @topic_names= keys(%topics); +if (scalar(@topic_names)) +{ + my $header= "insert into help_topic ". + "(help_topic_id,help_category_id,name,description,example) values "; + my $topic_name; + my $count= 0; + foreach $topic_name (@topic_names) + { + print_insert_header($count,$header); + my $topic= $topics{$topic_name}; + print "($count,"; + print "$topic->{category}->{__id__},"; + print "\"$topic_name\","; + print "\"$topic->{description}\","; + print "\"$topic->{example}\")"; + $topics{$topic_name}->{__id__}= $count; + $count++; + } + printf ";\n\n"; +} + +my @keywords_names= keys(%keywords); +if (scalar(@keywords_names)) +{ + my $header= "insert into help_keyword (help_keyword_id,name) values "; + my $keyword_name; + my $count= 0; + foreach $keyword_name (@keywords_names) + { + print_insert_header($count,$header); + print "($count,\"$keyword_name\")"; + $count++; + } + printf ";\n\n"; + + $header= "insert into help_relation ". + "(help_topic_id,help_keyword_id) values "; + $count= 0; + my $count_keyword= 0; + foreach $keyword_name (@keywords_names) + { + my $topic_name; + foreach $topic_name (keys(%{$keywords{$keyword_name}})) + { + print_insert_header($count,$header); + print "($topics{$topic_name}->{__id__},$count_keyword)"; + $count++; + } + $count_keyword++; + } + printf ";\n\n"; +} diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh new file mode 100644 index 00000000000..c54394305cd --- /dev/null +++ b/scripts/mysql_create_system_tables.sh @@ -0,0 +1,311 @@ +#!/bin/sh + +# Copyright (C) 1997-2002 MySQL AB +# For a more info consult the file COPYRIGHT distributed with this file + +# This script writes on stdout SQL commands to generate all not +# existing MySQL system tables. It also replaces the help tables with +# new context from the manual (from fill_help_tables.sql). + +# $1 - "test" or "real" or "verbose" variant of database +# $2 - path to mysql-database directory +# $3 - hostname +# $4 - windows option + +if test x$1 = x"" ; +then + echo " +This script writes on stdout SQL commands to generate all not +existing MySQL system tables. It also replaces the help tables with +new context from the manual (from fill_help_tables.sql). + +Usage: + mysql_create_system_tables {help|real|verbose} +"; + exit; +fi + +mdata=$2 +hostname=$3 +windows=$4 + +# Initialize variables +c_d="" i_d="" +c_h="" i_h="" +c_u="" i_u="" +c_f="" i_f="" +c_t="" c_c="" +c_ht="" +c_hc="" +c_hr="" +c_hk="" +i_ht="" + +# Check for old tables +if test ! -f $mdata/db.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing db table" 1>&2; + fi + + # mysqld --bootstrap wants one command/line + c_d="$c_d CREATE TABLE db (" + c_d="$c_d Host char(60) binary DEFAULT '' NOT NULL," + c_d="$c_d Db char(64) binary DEFAULT '' NOT NULL," + c_d="$c_d User char(16) binary DEFAULT '' NOT NULL," + c_d="$c_d Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d References_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_d="$c_d PRIMARY KEY Host (Host,Db,User)," + c_d="$c_d KEY User (User)" + c_d="$c_d )" + c_d="$c_d comment='Database privileges';" + + i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); + INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');" +fi + +if test ! -f $mdata/host.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing host table" 1>&2; + fi + + c_h="$c_h CREATE TABLE host (" + c_h="$c_h Host char(60) binary DEFAULT '' NOT NULL," + c_h="$c_h Db char(64) binary DEFAULT '' NOT NULL," + c_h="$c_h Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h References_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_h="$c_h PRIMARY KEY Host (Host,Db)" + c_h="$c_h )" + c_h="$c_h comment='Host privileges; Merged with database privileges';" +fi + +if test ! -f $mdata/user.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing user table" 1>&2; + fi + + c_u="$c_u CREATE TABLE user (" + c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL," + c_u="$c_u User char(16) binary DEFAULT '' NOT NULL," + c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL," + c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Process_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u File_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Super_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL," + c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL," + c_u="$c_u ssl_cipher BLOB NOT NULL," + c_u="$c_u x509_issuer BLOB NOT NULL," + c_u="$c_u x509_subject BLOB NOT NULL," + c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL," + c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL," + c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL," + c_u="$c_u PRIMARY KEY Host (Host,User)" + c_u="$c_u )" + c_u="$c_u comment='Users and global privileges';" + + if test x$1 = x"test" + then + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('localhost',''); + INSERT INTO user (host,user) values ('$hostname','');" + else + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('localhost','');" + if test "$windows" -eq 0 + then + i_u="$i_u + INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + INSERT INTO user (host,user) values ('$hostname','');" + fi + fi +fi + +if test ! -f $mdata/func.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing func table" 1>&2; + fi + + c_f="$c_f CREATE TABLE func (" + c_f="$c_f name char(64) binary DEFAULT '' NOT NULL," + c_f="$c_f ret tinyint(1) DEFAULT '0' NOT NULL," + c_f="$c_f dl char(128) DEFAULT '' NOT NULL," + c_f="$c_f type enum ('function','aggregate') NOT NULL," + c_f="$c_f PRIMARY KEY (name)" + c_f="$c_f )" + c_f="$c_f comment='User defined functions';" +fi + +if test ! -f $mdata/tables_priv.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing tables_priv table" 1>&2; + fi + + c_t="$c_t CREATE TABLE tables_priv (" + c_t="$c_t Host char(60) binary DEFAULT '' NOT NULL," + c_t="$c_t Db char(64) binary DEFAULT '' NOT NULL," + c_t="$c_t User char(16) binary DEFAULT '' NOT NULL," + c_t="$c_t Table_name char(60) binary DEFAULT '' NOT NULL," + c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," + c_t="$c_t Timestamp timestamp(14)," + c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL," + c_t="$c_t Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," + c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," + c_t="$c_t KEY Grantor (Grantor)" + c_t="$c_t )" + c_t="$c_t comment='Table privileges';" +fi + +if test ! -f $mdata/columns_priv.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing columns_priv table" 1>&2; + fi + + c_c="$c_c CREATE TABLE columns_priv (" + c_c="$c_c Host char(60) binary DEFAULT '' NOT NULL," + c_c="$c_c Db char(64) binary DEFAULT '' NOT NULL," + c_c="$c_c User char(16) binary DEFAULT '' NOT NULL," + c_c="$c_c Table_name char(64) binary DEFAULT '' NOT NULL," + c_c="$c_c Column_name char(64) binary DEFAULT '' NOT NULL," + c_c="$c_c Timestamp timestamp(14)," + c_c="$c_c Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," + c_c="$c_c PRIMARY KEY (Host,Db,User,Table_name,Column_name)" + c_c="$c_c )" + c_c="$c_c comment='Column privileges';" +fi + +if test ! -f $mdata/help_topic.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_topic table" 1>&2; + fi + + c_ht="$c_ht CREATE TABLE help_topic (" + c_ht="$c_ht help_topic_id int unsigned not null," + c_ht="$c_ht name varchar(64) not null," + c_ht="$c_ht help_category_id smallint unsigned not null," + c_ht="$c_ht description text not null," + c_ht="$c_ht example text not null," + c_ht="$c_ht url varchar(128) not null," + c_ht="$c_ht primary key (help_topic_id)," + c_ht="$c_ht unique index (name)" + c_ht="$c_ht )" + c_ht="$c_ht comment='help topics';" +fi + +old_categories="yes" + +if test ! -f $mdata/help_category.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_category table" 1>&2; + fi + + c_hc="$c_hc CREATE TABLE help_category (" + c_hc="$c_hc help_category_id smallint unsigned not null," + c_hc="$c_hc name varchar(64) not null," + c_hc="$c_hc parent_category_id smallint unsigned null," + c_hc="$c_hc url varchar(128) not null," + c_hc="$c_hc primary key (help_category_id)," + c_hc="$c_hc unique index (name)" + c_hc="$c_hc )" + c_hc="$c_hc comment='help categories';" +fi + +if test ! -f $mdata/help_keyword.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_keyword table" 1>&2; + fi + + c_hk="$c_hk CREATE TABLE help_keyword (" + c_hk="$c_hk help_keyword_id int unsigned not null," + c_hk="$c_hk name varchar(64) not null," + c_hk="$c_hk primary key (help_keyword_id)," + c_hk="$c_hk unique index (name)" + c_hk="$c_hk )" + c_hk="$c_hk comment='help keywords';" +fi + +if test ! -f $mdata/help_relation.frm +then + if test x$1 = x"verbose" ; then + echo "Preparing help_relation table" 1>&2; + fi + + c_hr="$c_hr CREATE TABLE help_relation (" + c_hr="$c_hr help_topic_id int unsigned not null references help_topic," + c_hr="$c_hr help_keyword_id int unsigned not null references help_keyword," + c_hr="$c_hr primary key (help_keyword_id, help_topic_id)" + c_hr="$c_hr )" + c_hr="$c_hr comment='keyword-topic relation';" +fi + +cat << END_OF_DATA +use mysql; +$c_d +$i_d + +$c_h +$i_h + +$c_u +$i_u + +$c_f +$i_f + +$c_t +$c_c + +$c_ht +$c_hc +$c_hr +$c_hk +END_OF_DATA + diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 15bc834e850..96e33d3e7c5 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -87,7 +87,7 @@ if test -z "$basedir" then basedir=@prefix@ bindir=@bindir@ - execdir=@libexecdir@ + execdir=@libexecdir@ pkgdatadir=@pkgdatadir@ else bindir="$basedir/bin" @@ -100,24 +100,24 @@ else else execdir="$basedir/bin" fi - - # find fill_help_tables.sh - for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts @pkgdatadir@ - do - if test -f $i/fill_help_tables.sql - then - pkgdatadir=$i - fi - done fi +# find fill_help_tables.sh +for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts `pwd` @pkgdatadir@ +do + if test -f $i/fill_help_tables.sql + then + pkgdatadir=$i + fi +done + if test -f $pkgdatadir/fill_help_tables.sql then fill_help_tables=$pkgdatadir/fill_help_tables.sql else if test $verbose -eq 1 then - echo "Could not find help file 'fill_help_tables.sql'". + echo "Could not find help file 'fill_help_tables.sql' ;$pkgdatadir; ;$basedir;". fi fi @@ -172,205 +172,21 @@ fi chown $user $ldata $ldata/mysql $ldata/test; fi -# Initialize variables -c_d="" i_d="" -c_h="" i_h="" -c_u="" i_u="" -c_f="" i_f="" -c_t="" c_c="" - -# Check for old tables if test ! -f $mdata/db.frm then - if test $verbose -eq 1 ; then - echo "Preparing db table" - fi - # mysqld --bootstrap wants one command/line - c_d="$c_d CREATE TABLE db (" - c_d="$c_d Host char(60) binary DEFAULT '' NOT NULL," - c_d="$c_d Db char(64) binary DEFAULT '' NOT NULL," - c_d="$c_d User char(16) binary DEFAULT '' NOT NULL," - c_d="$c_d Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_d="$c_d PRIMARY KEY Host (Host,Db,User)," - c_d="$c_d KEY User (User)" - c_d="$c_d )" - c_d="$c_d comment='Database privileges';" - - i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); - INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');" + c_d="yes" fi -if test ! -f $mdata/host.frm +if test $verbose -eq 1 then - if test $verbose -eq 1 ; then - echo "Preparing host table" - fi - - c_h="$c_h CREATE TABLE host (" - c_h="$c_h Host char(60) binary DEFAULT '' NOT NULL," - c_h="$c_h Db char(64) binary DEFAULT '' NOT NULL," - c_h="$c_h Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_h="$c_h PRIMARY KEY Host (Host,Db)" - c_h="$c_h )" - c_h="$c_h comment='Host privileges; Merged with database privileges';" + create_option="verbose" +else + create_option="real" fi -if test ! -f $mdata/user.frm -then - if test $verbose -eq 1 ; then - echo "Preparing user table" - fi - - c_u="$c_u CREATE TABLE user (" - c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL," - c_u="$c_u User char(16) binary DEFAULT '' NOT NULL," - c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL," - c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Process_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u File_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Super_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL," - c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL," - c_u="$c_u ssl_cipher BLOB NOT NULL," - c_u="$c_u x509_issuer BLOB NOT NULL," - c_u="$c_u x509_subject BLOB NOT NULL," - c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL," - c_u="$c_u PRIMARY KEY Host (Host,User)" - c_u="$c_u )" - c_u="$c_u comment='Users and global privileges';" - - i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - INSERT INTO user (host,user) values ('localhost',''); -" - - if test "$windows" -eq 0 - then - i_u="$i_u INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - - INSERT INTO user (host,user) values ('$hostname','');" - fi -fi - -if test ! -f $mdata/func.frm -then - if test $verbose -eq 1 ; then - echo "Preparing func table" - fi - - c_f="$c_f CREATE TABLE func (" - c_f="$c_f name char(64) binary DEFAULT '' NOT NULL," - c_f="$c_f ret tinyint(1) DEFAULT '0' NOT NULL," - c_f="$c_f dl char(128) DEFAULT '' NOT NULL," - c_f="$c_f type enum ('function','aggregate') NOT NULL," - c_f="$c_f PRIMARY KEY (name)" - c_f="$c_f )" - c_f="$c_f comment='User defined functions';" -fi - -if test ! -f $mdata/tables_priv.frm -then - if test $verbose -eq 1 ; then - echo "Preparing tables_priv table" - fi - - c_t="$c_t CREATE TABLE tables_priv (" - c_t="$c_t Host char(60) binary DEFAULT '' NOT NULL," - c_t="$c_t Db char(64) binary DEFAULT '' NOT NULL," - c_t="$c_t User char(16) binary DEFAULT '' NOT NULL," - c_t="$c_t Table_name char(60) binary DEFAULT '' NOT NULL," - c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," - c_t="$c_t Timestamp timestamp(14)," - c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL," - c_t="$c_t Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," - c_t="$c_t KEY Grantor (Grantor)" - c_t="$c_t )" - c_t="$c_t comment='Table privileges';" -fi - -if test ! -f $mdata/columns_priv.frm -then - if test $verbose -eq 1 ; then - echo "Preparing columns_priv table" - fi - - c_c="$c_c CREATE TABLE columns_priv (" - c_c="$c_c Host char(60) binary DEFAULT '' NOT NULL," - c_c="$c_c Db char(64) binary DEFAULT '' NOT NULL," - c_c="$c_c User char(16) binary DEFAULT '' NOT NULL," - c_c="$c_c Table_name char(64) binary DEFAULT '' NOT NULL," - c_c="$c_c Column_name char(64) binary DEFAULT '' NOT NULL," - c_c="$c_c Timestamp timestamp(14)," - c_c="$c_c Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL," - c_c="$c_c PRIMARY KEY (Host,Db,User,Table_name,Column_name)" - c_c="$c_c )" - c_c="$c_c comment='Column privileges';" -fi - -echo "Installing privilege tables" +echo "Installing all prepared tables" if ( - cat << END_OF_DATA -use mysql; -$c_d -$i_d - -$c_h -$i_h - -$c_u -$i_u - -$c_f -$i_f - -$c_t -$c_c -END_OF_DATA + mysql_create_system_tables $create_option $mdata $hostname $windows if test -n "$fill_help_tables" then cat $fill_help_tables diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 712c8853a20..a59f1d4b81a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -877,6 +877,7 @@ bool check_db_name(char *db); bool check_column_name(const char *name); bool check_table_name(const char *name, uint length); char *get_field(MEM_ROOT *mem, Field *field); +bool get_field(MEM_ROOT *mem, Field *field, class String *res); int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr); /* from hostname.cc */ diff --git a/sql/protocol.h b/sql/protocol.h index 2110f1877c2..ffd61b3e848 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -60,6 +60,8 @@ public: { return store_longlong((longlong) from, 0); } inline bool store(ulonglong from) { return store_longlong((longlong) from, 1); } + inline bool store(String *str) + { return store(str->c_ptr(),str->length(),str->charset()); } virtual bool prepare_for_send(List *item_list) { diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 36c7ef87b17..a9b89a728d2 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -26,74 +26,155 @@ struct st_find_field static struct st_find_field init_used_fields[]= { - { "help_topic", "name", 0}, - { "help_topic","description", 0}, - { "help_topic","example", 0}, - { "help_topic", "help_topic_id", 0}, - { "help_category","name", 0}, - { "help_category","help_category_id", 0}, - { "help_relation","help_topic_id", 0}, - { "help_relation","help_category_id", 0} + { "help_topic", "help_topic_id", 0}, + { "help_topic", "name", 0}, + { "help_topic", "help_category_id", 0}, + { "help_topic", "description", 0}, + { "help_topic", "example", 0}, + + { "help_category", "help_category_id", 0}, + { "help_category", "parent_category_id", 0}, + { "help_category", "name", 0}, + + { "help_keyword", "help_keyword_id", 0}, + { "help_keyword", "name", 0}, + + { "help_relation", "help_topic_id", 0}, + { "help_relation", "help_keyword_id", 0} }; enum enum_used_fields { - help_topic_name=0, help_topic_description, help_topic_example, - help_topic_help_topic_id, - help_category_name, help_category_help_category_id, - help_relation_help_topic_id, help_relation_help_category_id + help_topic_help_topic_id= 0, + help_topic_name, + help_topic_help_category_id, + help_topic_description, + help_topic_example, + + help_category_help_category_id, + help_category_parent_category_id, + help_category_name, + + help_keyword_help_keyword_id, + help_keyword_name, + + help_relation_help_topic_id, + help_relation_help_keyword_id }; /* - Fill local used field structure with pointer to fields */ + Fill st_find_field structure with pointers to fields + + SYNOPSIS + init_fields() + thd Thread handler + tables list of all tables for fields + find_fields array of structures + count size of previous array + + RETURN VALUES + 0 all ok + 1 one of the fileds didn't finded +*/ static bool init_fields(THD *thd, TABLE_LIST *tables, - struct st_find_field *find_field, - uint count) + struct st_find_field *find_fields, uint count) { - for (; count-- ; find_field++) + DBUG_ENTER("init_fields"); + for (; count-- ; find_fields++) { TABLE_LIST *not_used; /* We have to use 'new' here as field will be re_linked on free */ - Item_field *field= new Item_field("mysql", find_field->table_name, - find_field->field_name); - if (!(find_field->field= find_field_in_tables(thd, field, tables, - ¬_used, - TRUE))) - return 1; + Item_field *field= new Item_field("mysql", find_fields->table_name, + find_fields->field_name); + if (!(find_fields->field= find_field_in_tables(thd, field, tables, + ¬_used, TRUE))) + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } +/* -#define help_charset &my_charset_latin1 + Returns variants of found topic for help (if it is just single topic, + returns description and example, or else returns only names..) + + SYNOPSIS + memorize_variant_topic() + + thd Thread handler + topics Table of topics + count number of alredy found topics + find_fields Filled array of information for work with fields + + RETURN VALUES + names array of names of found topics (out) + + name name of found topic (out) + description description of found topic (out) + example example for found topic (out) + + NOTE + Field 'names' is set only if more than one topic is found. + Fields 'name', 'description', 'example' are set only if + found exactly one topic. +*/ + +void memorize_variant_topic(THD *thd, TABLE *topics, int count, + struct st_find_field *find_fields, + List *names, + String *name, String *description, String *example) +{ + DBUG_ENTER("memorize_variant_topic"); + MEM_ROOT *mem_root= &thd->mem_root; + if (count==0) + { + get_field(mem_root,find_fields[help_topic_name].field, name); + get_field(mem_root,find_fields[help_topic_description].field, description); + get_field(mem_root,find_fields[help_topic_example].field, example); + } + else + { + if (count==1) + names->push_back(name); + String *new_name= new String; + get_field(mem_root,find_fields[help_topic_name].field,new_name); + names->push_back(new_name); + } + DBUG_VOID_RETURN; +} /* Look for topics by mask SYNOPSIS search_topics() - thd Thread handler - topics Table of topic - select Function to test for if matching help topic. - Normally 'help_topic.name like 'bit%' - pfname Pointer to Field structure for field "name" - names List of founded topic's names (out) - name Name of founded topic (out), - Only set if founded exactly one topic) - description Description of founded topic (out) - Only set if founded exactly one topic. - example Example for founded topic (out) - Only if founded exactly one topic. + thd Thread handler + topics Table of topics + find_fields Filled array of info for fields + select Function to test for matching help topic. + Normally 'help_topic.name like 'bit%' + RETURN VALUES - # number of topics founded + # number of topics found + + names array of names of found topics (out) + name name of found topic (out) + description description of found topic (out) + example example for found topic (out) + + NOTE + Field 'names' is set only if more than one topic was found. + Fields 'name', 'description', 'example' are set only if + exactly one topic was found. + */ -int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field, - SQL_SELECT *select, List *names, - char **name, char **description, char **example) +int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields, + SQL_SELECT *select, List *names, + String *name, String *description, String *example) { - DBUG_ENTER("search_functions"); + DBUG_ENTER("search_topics"); int count= 0; READ_RECORD read_record_info; @@ -102,139 +183,93 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field, { if (!select->cond->val_int()) // Dosn't match like continue; - - char *lname= get_field(&thd->mem_root, find_field[help_topic_name].field); + memorize_variant_topic(thd,topics,count,find_fields, + names,name,description,example); count++; - if (count > 2) - { - names->push_back(lname); - } - else if (count == 1) - { - *description= get_field(&thd->mem_root, - find_field[help_topic_description].field); - *example= get_field(&thd->mem_root, - find_field[help_topic_example].field); - *name= lname; - } - else - { - names->push_back(*name); - names->push_back(lname); - *name= 0; - *description= 0; - *example= 0; - } } end_read_record(&read_record_info); + DBUG_RETURN(count); } /* - Look for categories by mask + Look for keyword by mask SYNOPSIS - search_categories() - thd THD for init_read_record - categories Table of categories - select Function to test for if matching help topic. - Normally 'help_topic.name like 'bit%' - names List of founded topic's names (out) - res_id Primary index of founded category (only if - founded exactly one category) + search_keyword() + thd Thread handler + keywords Table of keywords + find_fields Filled array of info for fields + select Function to test for matching keyword. + Normally 'help_keyword.name like 'bit%' + + key_id help_keyword_if of found topics (out) RETURN VALUES - # Number of categories founded + 0 didn't find any topics matching the mask + 1 found exactly one topic matching the mask + 2 found more then one topic matching the mask */ -int search_categories(THD *thd, TABLE *categories, - struct st_find_field *find_fields, - SQL_SELECT *select, List *names, int16 *res_id) +int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields, + SQL_SELECT *select, int *key_id) { - Field *pfname= find_fields[help_category_name].field; - DBUG_ENTER("search_categories"); + DBUG_ENTER("search_keyword"); int count= 0; - READ_RECORD read_record_info; - init_read_record(&read_record_info, thd, categories, select,1,0); - while (!read_record_info.read_record(&read_record_info)) + READ_RECORD read_record_info; + init_read_record(&read_record_info, thd, keywords, select,1,0); + while (!read_record_info.read_record(&read_record_info) && count<2) { - if (select && !select->cond->val_int()) + if (!select->cond->val_int()) // Dosn't match like continue; - char *lname= get_field(&thd->mem_root,pfname); - if (++count == 1 && res_id) - { - Field *pcat_id= find_fields[help_category_help_category_id].field; - *res_id= (int16) pcat_id->val_int(); - } - names->push_back(lname); + + *key_id= find_fields[help_keyword_help_keyword_id].field->val_int(); + + count++; } end_read_record(&read_record_info); - + DBUG_RETURN(count); } - /* - Send to client rows in format: - column1 : - column2 : + Look for all topics with keyword SYNOPSIS - send_variant_2_list() - protocol Protocol for sending - names List of names - cat Value of the column + get_topics_for_keyword() + thd Thread handler + topics Table of topics + relations Table of m:m relation "topic/keyword" + find_fields Filled array of info for fields + key_id Primary index to use to find for keyword RETURN VALUES - -1 Writing fail - 0 Data was successefully send + # number of topics found + + names array of name of found topics (out) + + name name of found topic (out) + description description of found topic (out) + example example for found topic (out) + + NOTE + Field 'names' is set only if more than one topic was found. + Fields 'name', 'description', 'example' are set only if + exactly one topic was found. */ -int send_variant_2_list(Protocol *protocol, List *names, - const char *cat) +int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations, + struct st_find_field *find_fields, int16 key_id, + List *names, + String *name, String *description, String *example) { - DBUG_ENTER("send_names"); - - List_iterator it(*names); - const char *cur_name; - while ((cur_name= it++)) - { - protocol->prepare_for_resend(); - protocol->store(cur_name, system_charset_info); - protocol->store(cat, system_charset_info); - if (protocol->write()) - DBUG_RETURN(-1); - } - DBUG_RETURN(0); -} - - -/* - Look for all topics of category - - SYNOPSIS - get_all_topics_for_category() - thd Thread handler - topics Table of topics - relations Table of m:m relation "topic/category" - cat_id Primary index looked for category - res List of founded topic's names (out) - - RETURN VALUES - -1 corrupt database - 0 succesefull -*/ - -int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations, - struct st_find_field *find_fields, - int16 cat_id, List *res) -{ - char buff[8]; // Max int length - DBUG_ENTER("get_all_topics_for_category"); - + char buff[8]; // Max int length + int count= 0; int iindex_topic, iindex_relations; - Field *rtopic_id, *rcat_id; + Field *rtopic_id, *rkey_id; + + DBUG_ENTER("get_topics_for_keyword"); if ((iindex_topic= find_type((char*) "PRIMARY", &topics->keynames, 1+2)-1)<0 || @@ -245,37 +280,156 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations, DBUG_RETURN(-1); } rtopic_id= find_fields[help_relation_help_topic_id].field; - rcat_id= find_fields[help_relation_help_category_id].field; + rkey_id= find_fields[help_relation_help_keyword_id].field; topics->file->index_init(iindex_topic); relations->file->index_init(iindex_relations); - rcat_id->store((longlong) cat_id); - rcat_id->get_key_image(buff, rcat_id->pack_length(), help_charset, + rkey_id->store((longlong) key_id); + rkey_id->get_key_image(buff, rkey_id->pack_length(), rkey_id->charset(), Field::itRAW); int key_res= relations->file->index_read(relations->record[0], - (byte *)buff, rcat_id->pack_length(), + (byte *)buff, rkey_id->pack_length(), HA_READ_KEY_EXACT); - for ( ; !key_res && cat_id == (int16) rcat_id->val_int() ; + for ( ; + !key_res && key_id == (int16) rkey_id->val_int() ; key_res= relations->file->index_next(relations->record[0])) { char topic_id_buff[8]; longlong topic_id= rtopic_id->val_int(); Field *field= find_fields[help_topic_help_topic_id].field; field->store((longlong) topic_id); - field->get_key_image(topic_id_buff, field->pack_length(), help_charset, + field->get_key_image(topic_id_buff, field->pack_length(), field->charset(), Field::itRAW); - + if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff, - field->pack_length(), - HA_READ_KEY_EXACT)) - res->push_back(get_field(&thd->mem_root, - find_fields[help_topic_name].field)); + field->pack_length(), HA_READ_KEY_EXACT)) + { + memorize_variant_topic(thd,topics,count,find_fields, + names,name,description,example); + count++; + } } - DBUG_RETURN(0); + DBUG_RETURN(count); } +/* + Look for topics with keyword by mask + + SYNOPSIS + search_topics_by_keyword() + thd Thread handler + keywords Table of keywords + topics Table of topics + relations Table of m:m relation "topic/keyword" + find_fields Filled array of info for fields + select Function to test for if matching help keyword. + Normally 'help_keyword.name like 'bit%' + + RETURN VALUES + # number of topics found + + names array of name of found topics (out) + + name name of found topic (out) + description description of found topic (out) + example example for found topic (out) + + NOTE + Field 'names' is set only if more than one topic was found. + Fields 'name', 'description', 'example' are set only if + exactly one topic was found. +*/ + +int search_topics_by_keyword(THD *thd, + TABLE *keywords, TABLE *topics, TABLE *relations, + struct st_find_field *find_fields, + SQL_SELECT *select, List *names, + String *name, String *description, String *example) +{ + int key_id; + return search_keyword(thd,keywords,find_fields,select,&key_id)!=1 + ? 0 : get_topics_for_keyword(thd,topics,relations,find_fields,key_id, + names,name,description,example); +} + +/* + Look for categories by mask + + SYNOPSIS + search_categories() + thd THD for init_read_record + categories Table of categories + find_fields Filled array of info for fields + select Function to test for if matching help topic. + Normally 'help_vategory.name like 'bit%' + names List of found categories names (out) + res_id Primary index of found category (only if + found exactly one category) + + RETURN VALUES + # Number of categories found +*/ + +int search_categories(THD *thd, TABLE *categories, + struct st_find_field *find_fields, + SQL_SELECT *select, List *names, int16 *res_id) +{ + Field *pfname= find_fields[help_category_name].field; + Field *pcat_id= find_fields[help_category_help_category_id].field; + int count= 0; + READ_RECORD read_record_info; + + DBUG_ENTER("search_categories"); + + init_read_record(&read_record_info, thd, categories, select,1,0); + while (!read_record_info.read_record(&read_record_info)) + { + if (select && !select->cond->val_int()) + continue; + String *lname= new String; + get_field(&thd->mem_root,pfname,lname); + if (++count == 1 && res_id) + *res_id= (int16) pcat_id->val_int(); + names->push_back(lname); + } + end_read_record(&read_record_info); + + DBUG_RETURN(count); +} + +/* + Look for all topics or subcategories of category + + SYNOPSIS + get_all_items_for_category() + thd Thread handler + items Table of items + pfname Field "name" in items + select "where" part of query.. + res list of finded names +*/ + +void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname, + SQL_SELECT *select, List *res) +{ + DBUG_ENTER("get_all_items_for_category"); + + READ_RECORD read_record_info; + init_read_record(&read_record_info, thd, items, select,1,0); + while (!read_record_info.read_record(&read_record_info)) + { + if (!select->cond->val_int()) + continue; + String *name= new String(); + get_field(&thd->mem_root,pfname,name); + res->push_back(name); + } + end_read_record(&read_record_info); + + DBUG_VOID_RETURN; +} /* Send to client answer for help request @@ -284,17 +438,16 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations, send_answer_1() protocol - protocol for sending s1 - value of column "Name" - s2 - value of column "Category" - s3 - value of column "Description" - s4 - value of column "Example" + s2 - value of column "Description" + s3 - value of column "Example" IMPLEMENTATION Format used: - +----------+---------+------------+------------+ - |Name: |Category |Description |Example | - +----------+---------+------------+------------+ - |String(64)|String(1)|String(1000)|String(1000)| - +----------+---------+------------+------------+ + +----------+------------+------------+ + |name |description |example | + +----------+------------+------------+ + |String(64)|String(1000)|String(1000)| + +----------+------------+------------+ with exactly one row! RETURN VALUES @@ -303,24 +456,21 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations, 0 Successeful send */ -int send_answer_1(Protocol *protocol, const char *s1, const char *s2, - const char *s3, const char *s4) +int send_answer_1(Protocol *protocol, String *s1, String *s2, String *s3) { DBUG_ENTER("send_answer_1"); List field_list; - field_list.push_back(new Item_empty_string("Name",64)); - field_list.push_back(new Item_empty_string("Category",1)); - field_list.push_back(new Item_empty_string("Description",1000)); - field_list.push_back(new Item_empty_string("Example",1000)); + field_list.push_back(new Item_empty_string("name",64)); + field_list.push_back(new Item_empty_string("description",1000)); + field_list.push_back(new Item_empty_string("example",1000)); if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); protocol->prepare_for_resend(); - protocol->store(s1, system_charset_info); - protocol->store(s2, system_charset_info); - protocol->store(s3, system_charset_info); - protocol->store(s4, system_charset_info); + protocol->store(s1); + protocol->store(s2); + protocol->store(s3); if (protocol->write()) DBUG_RETURN(-1); DBUG_RETURN(0); @@ -332,28 +482,151 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2, SYNOPSIS send_header_2() - protocol - protocol for sending + protocol - protocol for sending + is_it_category - need column 'source_category_name' IMPLEMENTATION - +----------+---------+ - |Name: |Category | - +----------+---------+ - |String(64)|String(1)| - +----------+---------+ + +- -+ + |+-------------------- | +----------+--------------+ + ||source_category_name | |name |is_it_category| + |+-------------------- | +----------+--------------+ + ||String(64) | |String(64)|String(1) | + |+-------------------- | +----------+--------------+ + +- -+ RETURN VALUES result of protocol->send_fields */ -int send_header_2(Protocol *protocol) +int send_header_2(Protocol *protocol, bool for_category) { - DBUG_ENTER("send_header2"); + DBUG_ENTER("send_header_2"); List field_list; - field_list.push_back(new Item_empty_string("Name",64)); - field_list.push_back(new Item_empty_string("Category",1)); + if (for_category) + field_list.push_back(new Item_empty_string("source_category_name",64)); + field_list.push_back(new Item_empty_string("name",64)); + field_list.push_back(new Item_empty_string("is_it_category",1)); DBUG_RETURN(protocol->send_fields(&field_list,1)); } +/* + strcmp for using in qsort + + SYNOPSIS + strptrcmp() + ptr1 (const void*)&str1 + ptr2 (const void*)&str2 + + RETURN VALUES + same as strcmp +*/ + +int string_ptr_cmp(const void* ptr1, const void* ptr2) +{ + String *str1= *(String**)ptr1; + String *str2= *(String**)ptr2; + return strcmp(str1->c_ptr(),str2->c_ptr()); +} + +/* + Send to client rows in format: + column1 : + column2 : + + SYNOPSIS + send_variant_2_list() + protocol Protocol for sending + names List of names + cat Value of the column + source_name name of category for all items.. + + RETURN VALUES + -1 Writing fail + 0 Data was successefully send +*/ + +int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, + List *names, + const char *cat, String *source_name) +{ + DBUG_ENTER("send_variant_2_list"); + + String **pointers= (String**)alloc_root(mem_root, + sizeof(String*)*names->elements); + String **pos= pointers; + + List_iterator it(*names); + String *cur_name; + while (*pos++= it++); + + qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); + + String **end= pointers + names->elements; + for (String **pos= pointers; pos!=end; pos++) + { + protocol->prepare_for_resend(); + if (source_name) + protocol->store(source_name); + protocol->store(*pos); + protocol->store(cat,1,&my_charset_latin1); + if (protocol->write()) + DBUG_RETURN(-1); + } + + DBUG_RETURN(0); +} + +/* + Prepare simple SQL_SELECT table.* WHERE + + SYNOPSIS + prepare_simple_select() + thd Thread handler + cond WHERE part of select + tables list of tables, used in WHERE + table goal table + + error code of error (out) + + RETURN VALUES + # created SQL_SELECT +*/ + +SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables, + TABLE *table, int *error) +{ + cond->fix_fields(thd, tables, &cond); // can never fail + SQL_SELECT *res= make_select(table,0,0,cond,error); + return (*error || (res && res->check_quick(0, HA_POS_ERROR))) ? 0 : res; +} + +/* + Prepare simple SQL_SELECT table.* WHERE table.name LIKE mask + + SYNOPSIS + prepare_select_for_name() + thd Thread handler + mask mask for compare with name + mlen length of mask + tables list of tables, used in WHERE + table goal table + pfname field "name" in table + + error code of error (out) + + RETURN VALUES + # created SQL_SELECT +*/ + +SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen, + TABLE_LIST *tables, TABLE *table, + Field *pfname, int *error) +{ + Item *cond= new Item_func_like(new Item_field(pfname), + new Item_string(mask,mlen,pfname->charset()), + (char*) "\\"); + return prepare_simple_select(thd,cond,tables,table,error); +} /* Server-side function 'help' @@ -371,12 +644,13 @@ int send_header_2(Protocol *protocol) int mysqld_help(THD *thd, const char *mask) { Protocol *protocol= thd->protocol; - SQL_SELECT *select= 0, *select_cat= 0; - Item *cond_topic, *cond_cat; + SQL_SELECT *select_topics_by_name= 0, *select_keyword_by_name= 0, + *select_cat_by_name= 0, *select_topics_by_cat= 0, *select_cat_by_cat= 0, + *select_root_cats= 0; st_find_field used_fields[array_elements(init_used_fields)]; DBUG_ENTER("mysqld_help"); - TABLE_LIST tables[3]; + TABLE_LIST tables[4]; bzero((gptr)tables,sizeof(tables)); tables[0].alias= tables[0].real_name= (char*) "help_topic"; tables[0].lock_type= TL_READ; @@ -389,11 +663,17 @@ int mysqld_help(THD *thd, const char *mask) tables[2].alias= tables[2].real_name= (char*) "help_relation"; tables[2].lock_type= TL_READ; tables[2].db= (char*) "mysql"; - tables[2].next= 0; + tables[2].next= &tables[3]; + tables[3].alias= tables[3].real_name= (char*) "help_keyword"; + tables[3].lock_type= TL_READ; + tables[3].db= (char*) "mysql"; + tables[3].next= 0; - List function_list, categories_list; - char *name, *description, *example; + List topics_list, categories_list, subcategories_list; + String name, description, example; int res, count_topics, count_categories, error; + uint mlen= strlen(mask); + MEM_ROOT *mem_root= &thd->mem_root; if (open_and_lock_tables(thd, tables)) { @@ -409,111 +689,101 @@ int mysqld_help(THD *thd, const char *mask) goto end; } - /* TODO: Find out why these are needed (should not be) */ - tables[0].table->file->init_table_handle_for_HANDLER(); - tables[1].table->file->init_table_handle_for_HANDLER(); - tables[2].table->file->init_table_handle_for_HANDLER(); + for (int i=0; ifile->init_table_handle_for_HANDLER(); - cond_topic= new Item_func_like(new Item_field(used_fields[help_topic_name]. - field), - new Item_string(mask, strlen(mask), - help_charset), - (char*) "\\"); - cond_topic->fix_fields(thd, tables, &cond_topic); // can never fail - select= make_select(tables[0].table,0,0,cond_topic,&error); - if (error || (select && select->check_quick(0, HA_POS_ERROR))) - { - res= -1; - goto end; - } - - cond_cat= new Item_func_like(new Item_field(used_fields[help_category_name]. - field), - new Item_string(mask, strlen(mask), - help_charset), - (char*) "\\"); - cond_cat->fix_fields(thd, tables, &cond_topic); // can never fail - select_cat= make_select(tables[1].table,0,0,cond_cat,&error); - if (error || (select_cat && select_cat->check_quick(0, HA_POS_ERROR))) + if (!(select_topics_by_name= + prepare_select_for_name(thd,mask,mlen,tables,tables[0].table, + used_fields[help_topic_name].field,&error)) || + !(select_cat_by_name= + prepare_select_for_name(thd,mask,mlen,tables,tables[1].table, + used_fields[help_category_name].field,&error))|| + !(select_keyword_by_name= + prepare_select_for_name(thd,mask,mlen,tables,tables[3].table, + used_fields[help_keyword_name].field,&error))) { res= -1; goto end; } res= 1; - count_topics= search_topics(thd,tables[0].table, used_fields, select, - &function_list, &name, &description, &example); + count_topics= search_topics(thd,tables[0].table,used_fields, + select_topics_by_name,&topics_list, + &name, &description, &example); + + if (count_topics == 0) + count_topics= search_topics_by_keyword(thd,tables[3].table,tables[0].table, + tables[2].table,used_fields, + select_keyword_by_name,&topics_list, + &name,&description,&example); + if (count_topics == 0) { int16 category_id; - Item *cond= - new Item_func_like(new - Item_field(used_fields[help_category_name].field), - new Item_string(mask, strlen(mask), - help_charset), - (char*) "\\"); - (void) cond->fix_fields(thd, tables, &cond); // can never fail - + Field *cat_cat_id= used_fields[help_category_parent_category_id].field; count_categories= search_categories(thd, tables[1].table, used_fields, - select_cat, &categories_list, - &category_id); - if (count_categories == 1) + select_cat_by_name, + &categories_list,&category_id); + if (!count_categories) { - if (get_all_topics_for_category(thd,tables[0].table, - tables[2].table, used_fields, - category_id, &function_list)) + if (send_header_2(protocol,false)) + goto end; + } + else if (count_categories > 1) + { + if (send_header_2(protocol,false) || + send_variant_2_list(mem_root,protocol,&categories_list,"Y",0)) + goto end; + } + else + { + Field *topic_cat_id= used_fields[help_topic_help_category_id].field; + Item *cond_topic_by_cat= new Item_func_equal(new Item_field(topic_cat_id), + new Item_int(category_id)); + Item *cond_cat_by_cat= new Item_func_equal(new Item_field(cat_cat_id), + new Item_int(category_id)); + if (!(select_topics_by_cat= prepare_simple_select(thd,cond_topic_by_cat, + tables,tables[0].table, + &error)) || + !(select_cat_by_cat= prepare_simple_select(thd,cond_cat_by_cat,tables, + tables[1].table,&error))) { res= -1; goto end; } - List_iterator it(function_list); - char *cur_topic; - char buff[1024]; - String example(buff, sizeof(buff), help_charset); - example.length(0); - - while ((cur_topic= it++)) - { - example.append(cur_topic); - example.append("\n",1); - } - if ((send_answer_1(protocol, categories_list.head(), - "Y","",example.ptr()))) - goto end; - } - else - { - if (send_header_2(protocol)) - goto end; - if (count_categories == 0) - search_categories(thd,tables[1].table, used_fields, (SQL_SELECT *) 0, - &categories_list, 0); - if (send_variant_2_list(protocol,&categories_list,"Y")) + get_all_items_for_category(thd,tables[0].table, + used_fields[help_topic_name].field, + select_topics_by_cat,&topics_list); + get_all_items_for_category(thd,tables[1].table, + used_fields[help_category_name].field, + select_cat_by_cat,&subcategories_list); + String *cat= categories_list.head(); + if (send_header_2(protocol, true) || + send_variant_2_list(mem_root,protocol,&topics_list, "N",cat) || + send_variant_2_list(mem_root,protocol,&subcategories_list,"Y",cat)) goto end; } } else if (count_topics == 1) { - if (send_answer_1(protocol,name,"N",description, example)) + if (send_answer_1(protocol,&name,&description,&example)) goto end; } else { /* First send header and functions */ - if (send_header_2(protocol) || - send_variant_2_list(protocol, &function_list, "N")) + if (send_header_2(protocol, false) || + send_variant_2_list(mem_root,protocol, &topics_list, "N", 0)) goto end; - search_categories(thd, tables[1].table, used_fields, select_cat, - &categories_list, 0); + search_categories(thd, tables[1].table, used_fields, + select_cat_by_name,&categories_list, 0); /* Then send categories */ - if (send_variant_2_list(protocol, &categories_list, "Y")) + if (send_variant_2_list(mem_root,protocol, &categories_list, "Y", 0)) goto end; } res= 0; send_eof(thd); end: - delete select; - delete select_cat; DBUG_RETURN(res); } diff --git a/sql/table.cc b/sql/table.cc index 3aed75c7ac6..908d6807450 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1160,6 +1160,33 @@ rename_file_ext(const char * from,const char * to,const char * ext) } +/* + Allocate string field in MEM_ROOT and return it as String + + SYNOPSIS + get_field() + mem MEM_ROOT for allocating + field Field for retrieving of string + res result String + + RETURN VALUES + true string is empty + false all ok +*/ + +bool get_field(MEM_ROOT *mem, Field *field, String *res) +{ + char buff[MAX_FIELD_WIDTH]; + String str(buff,sizeof(buff),&my_charset_bin); + field->val_str(&str,&str); + uint length=str.length(); + if (!length) + return true; + char *to= strmake_root(mem, str.ptr(), length); + res->set(to,length,((Field_str*)field)->charset()); + return false; +} + /* Allocate string field in MEM_ROOT and return it as NULL-terminated string From f8ed5e71292246c91824dad4c32eb00c7513f9a0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 13:03:00 +0500 Subject: [PATCH 267/399] Fix for the bug #537 (UDF example broken on 4.1). --- sql/udf_example.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/udf_example.cc b/sql/udf_example.cc index dfe8177bfce..7f4417bf8fe 100644 --- a/sql/udf_example.cc +++ b/sql/udf_example.cc @@ -284,8 +284,8 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result, for (n = ntrans + 1, n_end = ntrans + sizeof(ntrans)-2; word != w_end && n < n_end; word++ ) - if ( my_isalpha ( my_charset_latin1, *word )) - *n++ = my_toupper ( my_charset_latin1, *word ); + if ( my_isalpha ( &my_charset_latin1, *word )) + *n++ = my_toupper ( &my_charset_latin1, *word ); if ( n == ntrans + 1 ) /* return empty string if 0 bytes */ { From f46e958e1e0a6ca13bb94dea7064b338c5474a8d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 13:03:56 +0500 Subject: [PATCH 268/399] character_set_server is now updatable character_set_database was added Code optimization: reuse more code for all character sets variables sql/mysqld.cc: character_set_server is now updatable character_set_database was added sql/set_var.cc: character_set_server is now updatable character_set_database was added sql/set_var.h: character_set_server is now updatable character_set_database was added sql/sql_base.cc: character_set_server is now updatable character_set_database was added sql/sql_class.cc: character_set_server is now updatable character_set_database was added sql/sql_class.h: character_set_server is now updatable character_set_database was added sql/sql_db.cc: character_set_server is now updatable character_set_database was added sql/sql_load.cc: character_set_server is now updatable character_set_database was added sql/sql_table.cc: character_set_server is now updatable character_set_database was added sql/sql_yacc.yy: character_set_server is now updatable character_set_database was added BitKeeper/etc/ignore: Added scripts/mysql_create_system_tables to the ignore list --- .bzrignore | 1 + sql/mysqld.cc | 18 ++++---- sql/set_var.cc | 107 ++++++++++++++++++++++++++++++----------------- sql/set_var.h | 28 ++++++++++--- sql/sql_base.cc | 4 +- sql/sql_class.cc | 2 +- sql/sql_class.h | 2 + sql/sql_db.cc | 44 ++++++++++++------- sql/sql_load.cc | 2 +- sql/sql_table.cc | 3 +- sql/sql_yacc.yy | 6 +-- 11 files changed, 142 insertions(+), 75 deletions(-) diff --git a/.bzrignore b/.bzrignore index 82adbf625f3..042a672eb7c 100644 --- a/.bzrignore +++ b/.bzrignore @@ -617,3 +617,4 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl include/readline/*.h +scripts/mysql_create_system_tables diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6d31abc3dc9..224bfe5f878 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -300,7 +300,7 @@ char* log_error_file_ptr= log_error_file; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file; -char *language_ptr, *default_collation_name; +char *language_ptr, *default_collation_name, *default_character_set_name; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION; char *mysql_unix_port, *opt_mysql_tmpdir; @@ -2028,7 +2028,7 @@ static int init_common_variables(const char *conf_file_name, int argc, #ifdef USE_REGEX regex_init(&my_charset_latin1); #endif - if (!(default_charset_info= get_charset_by_csname(sys_charset.value, + if (!(default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY, MYF(MY_WME)))) return 1; @@ -2046,6 +2046,8 @@ static int init_common_variables(const char *conf_file_name, int argc, } default_charset_info= default_collation; } + global_system_variables.character_set_server= default_charset_info; + global_system_variables.character_set_database= default_charset_info; global_system_variables.character_set_results= NULL; global_system_variables.character_set_client= default_charset_info; global_system_variables.collation_connection= default_charset_info; @@ -3542,8 +3544,8 @@ Disable with --skip-bdb (will save memory)", 0, 0, 0, 0, 0, 0}, #endif /* HAVE_OPENSSL */ {"default-character-set", 'C', "Set the default character set", - (gptr*) &sys_charset.value, (gptr*) &sys_charset.value, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + (gptr*) &default_character_set_name, (gptr*) &default_character_set_name, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation", (gptr*) &default_collation_name, (gptr*) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, @@ -4538,7 +4540,7 @@ static void use_help(void) static void usage(void) { - if (!(default_charset_info= get_charset_by_csname(sys_charset.value, + if (!(default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY, MYF(MY_WME)))) exit(1); @@ -4642,7 +4644,6 @@ static void mysql_init_variables(void) pidfile_name_ptr= pidfile_name; log_error_file_ptr= log_error_file; language_ptr= language; - default_collation_name= (char*) MYSQL_DEFAULT_COLLATION_NAME; mysql_data_home= mysql_real_data_home; thd_startup_options= (OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL | OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE); @@ -4681,10 +4682,13 @@ static void mysql_init_variables(void) /* Variables in libraries */ charsets_dir= 0; - sys_charset.value= (char*) MYSQL_DEFAULT_CHARSET_NAME; + default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME; + default_collation_name= (char*) MYSQL_DEFAULT_COLLATION_NAME; sys_charset_system.value= (char*) system_charset_info->csname; /* Set default values for some option variables */ + global_system_variables.character_set_server= default_charset_info; + global_system_variables.character_set_database= default_charset_info; global_system_variables.character_set_results= NULL; global_system_variables.character_set_client= default_charset_info; global_system_variables.collation_connection= default_charset_info; diff --git a/sql/set_var.cc b/sql/set_var.cc index 3145504951d..e6cdaf1d3fb 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -103,14 +103,12 @@ sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size", &binlog_cache_size); sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size", &SV::bulk_insert_buff_size); -sys_var_str sys_charset("character_set_server", - sys_check_charset, - sys_update_charset, - sys_set_default_charset); -sys_var_str sys_charset_system("character_set_system", +sys_var_character_set_server sys_character_set_server("character_set_server"); +sys_var_str sys_charset_system("character_set_system", sys_check_charset, sys_update_charset, sys_set_default_charset); +sys_var_character_set_database sys_character_set_database("character_set_database"); sys_var_character_set_client sys_character_set_client("character_set_client"); sys_var_character_set_results sys_character_set_results("character_set_results"); sys_var_collation_connection sys_collation_connection("collation_connection"); @@ -362,6 +360,8 @@ sys_var *sys_variables[]= &sys_binlog_cache_size, &sys_buffer_results, &sys_bulk_insert_buff_size, + &sys_character_set_server, + &sys_character_set_database, &sys_character_set_client, &sys_character_set_results, &sys_collation_connection, @@ -481,8 +481,9 @@ struct show_var_st init_vars[]= { #endif {sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size, SHOW_SYS}, {sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS}, - {sys_charset.name, (char*) &sys_charset, SHOW_SYS}, + {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS}, {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS}, + {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS}, {sys_character_set_client.name,(char*) &sys_character_set_client,SHOW_SYS}, {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS}, {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, @@ -1288,23 +1289,28 @@ bool sys_var_character_set::check(THD *thd, set_var *var) return 0; } -bool sys_var_character_set_client::update(THD *thd, set_var *var) +bool sys_var_character_set::update(THD *thd, set_var *var) { - if (var->type == OPT_GLOBAL) - global_system_variables.character_set_client= var->save_result.charset; - else - thd->variables.character_set_client= var->save_result.charset; + ci_ptr(thd,var->type)[0]= var->save_result.charset; return 0; } -byte *sys_var_character_set_client::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type) { - CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.character_set_client : - thd->variables.character_set_client); + CHARSET_INFO *cs= ci_ptr(thd,type)[0]; return cs ? (byte*) cs->csname : (byte*) "NULL"; } + + +CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + return &global_system_variables.character_set_client; + else + return &thd->variables.character_set_client; +} + void sys_var_character_set_client::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1313,6 +1319,53 @@ void sys_var_character_set_client::set_default(THD *thd, enum_var_type type) thd->variables.character_set_client= global_system_variables.character_set_client; } +CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + return &global_system_variables.character_set_results; + else + return &thd->variables.character_set_results; +} + +void sys_var_character_set_results::set_default(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + global_system_variables.character_set_results= NULL; + else + thd->variables.character_set_results= global_system_variables.character_set_results; +} + +CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + return &global_system_variables.character_set_server; + else + return &thd->variables.character_set_server; +} + +void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + global_system_variables.character_set_server= default_charset_info; + else + thd->variables.character_set_server= global_system_variables.character_set_server; +} + +CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + return &global_system_variables.character_set_database; + else + return &thd->variables.character_set_database; +} + +void sys_var_character_set_database::set_default(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + global_system_variables.character_set_database= default_charset_info; + else + thd->variables.character_set_database= thd->db_charset; +} bool sys_var_collation_connection::update(THD *thd, set_var *var) { @@ -1339,30 +1392,6 @@ void sys_var_collation_connection::set_default(THD *thd, enum_var_type type) thd->variables.collation_connection= global_system_variables.collation_connection; } -bool sys_var_character_set_results::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - global_system_variables.character_set_results= var->save_result.charset; - else - thd->variables.character_set_results= var->save_result.charset; - return 0; -} - -byte *sys_var_character_set_results::value_ptr(THD *thd, enum_var_type type) -{ - CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.character_set_results : - thd->variables.character_set_results); - return cs ? (byte*) cs->csname : (byte*) "NULL"; -} - -void sys_var_character_set_results::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.character_set_results= NULL; - else - thd->variables.character_set_results= global_system_variables.character_set_results; -} /***************************************************************************** diff --git a/sql/set_var.h b/sql/set_var.h index f501426e553..7c1a9bc3233 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -441,7 +441,10 @@ SHOW_TYPE type() { return SHOW_CHAR; } return type != STRING_RESULT; /* Only accept strings */ } bool check_default(enum_var_type type) { return 0; } + bool update(THD *thd, set_var *var); + byte *value_ptr(THD *thd, enum_var_type type); virtual void set_default(THD *thd, enum_var_type type)= 0; + virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0; }; class sys_var_character_set_client :public sys_var_character_set @@ -449,9 +452,8 @@ class sys_var_character_set_client :public sys_var_character_set public: sys_var_character_set_client(const char *name_arg) : sys_var_character_set(name_arg) {} - bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); - byte *value_ptr(THD *thd, enum_var_type type); + CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; class sys_var_character_set_results :public sys_var_character_set @@ -459,9 +461,26 @@ class sys_var_character_set_results :public sys_var_character_set public: sys_var_character_set_results(const char *name_arg) : sys_var_character_set(name_arg) {} - bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); - byte *value_ptr(THD *thd, enum_var_type type); + CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); +}; + +class sys_var_character_set_server :public sys_var_character_set +{ +public: + sys_var_character_set_server(const char *name_arg) : + sys_var_character_set(name_arg) {} + void set_default(THD *thd, enum_var_type type); + CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); +}; + +class sys_var_character_set_database :public sys_var_character_set +{ +public: + sys_var_character_set_database(const char *name_arg) : + sys_var_character_set(name_arg) {} + void set_default(THD *thd, enum_var_type type); + CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; class sys_var_collation_connection :public sys_var_collation @@ -606,6 +625,5 @@ sys_var *find_sys_var(const char *str, uint length=0); int sql_set_variables(THD *thd, List *var_list); void fix_delay_key_write(THD *thd, enum_var_type type); -extern sys_var_str sys_charset; extern sys_var_str sys_charset_system; CHARSET_INFO *get_old_charset_by_name(const char *old_name); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index eeaf560693e..81c620fdaf4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2311,7 +2311,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) DBUG_ENTER("mysql_create_index"); bzero((char*) &create_info,sizeof(create_info)); create_info.db_type=DB_TYPE_DEFAULT; - create_info.table_charset= thd->db_charset; + create_info.table_charset= thd->variables.character_set_database; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, fields, keys, drop, alter, 0, (ORDER*)0, FALSE, @@ -2328,7 +2328,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop) DBUG_ENTER("mysql_drop_index"); bzero((char*) &create_info,sizeof(create_info)); create_info.db_type=DB_TYPE_DEFAULT; - create_info.table_charset= thd->db_charset; + create_info.table_charset= thd->variables.character_set_database; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, fields, keys, drop, alter, 0, (ORDER*)0, FALSE, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9f6edd629ca..fb088b602b1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -109,7 +109,7 @@ THD::THD():user_time(0), is_fatal_error(0), file_id = 0; cond_count=0; warn_id= 0; - db_charset=default_charset_info; + db_charset= global_system_variables.character_set_database; mysys_var=0; #ifndef DBUG_OFF dbug_sentry=THD_SENTRY_MAGIC; diff --git a/sql/sql_class.h b/sql/sql_class.h index 00b3b9f8444..157a58cb8fa 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -386,6 +386,8 @@ struct system_variables my_bool low_priority_updates; my_bool new_mode; + CHARSET_INFO *character_set_server; + CHARSET_INFO *character_set_database; CHARSET_INFO *character_set_client; CHARSET_INFO *character_set_results; CHARSET_INFO *collation_connection; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index e0a592d2450..f8cf1eee0c5 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -51,7 +51,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, 1 Could not create file or write to it. Error sent through my_error() */ -static bool write_db_opt(const char *path, HA_CREATE_INFO *create) +static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) { register File file; char buf[256]; // Should be enough for one option @@ -61,8 +61,9 @@ static bool write_db_opt(const char *path, HA_CREATE_INFO *create) { ulong length; CHARSET_INFO *cs= (create && create->table_charset) ? - create->table_charset : default_charset_info; - length= my_sprintf(buf,(buf, "default-character-set=%s\n", cs->name)); + create->table_charset : + thd->variables.character_set_database; + length= my_sprintf(buf,(buf, "default-character-set=%s\ndefault-collation=%s\n", cs->csname,cs->name)); /* Error is written by my_write */ if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME))) @@ -89,7 +90,7 @@ static bool write_db_opt(const char *path, HA_CREATE_INFO *create) */ -static bool load_db_opt(const char *path, HA_CREATE_INFO *create) +static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) { File file; char buf[256]; @@ -98,7 +99,7 @@ static bool load_db_opt(const char *path, HA_CREATE_INFO *create) uint nbytes; bzero((char*) create,sizeof(*create)); - create->table_charset= default_charset_info; + create->table_charset= global_system_variables.character_set_database; if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0) { IO_CACHE cache; @@ -115,12 +116,18 @@ static bool load_db_opt(const char *path, HA_CREATE_INFO *create) { if (!strncmp(buf,"default-character-set", (pos-buf))) { - if (strcmp(pos+1,"DEFAULT")) + if (!(create->table_charset=get_charset_by_csname(pos+1, + MY_CS_PRIMARY, + MYF(0)))) { - if (!(create->table_charset=get_charset_by_name(pos+1, MYF(0)))) - { - sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1); - } + sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1); + } + } + else if (!strncmp(buf,"default-collation", (pos-buf))) + { + if (!(create->table_charset=get_charset_by_name(pos+1, MYF(0)))) + { + sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1); } } } @@ -197,7 +204,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, unpack_dirname(path, path); strcat(path,MY_DB_OPT_FILE); - if (write_db_opt(path, create_info)) + if (write_db_opt(thd, path, create_info)) { /* Could not create options file. @@ -270,7 +277,7 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) /* Check directory */ (void)sprintf(path,"%s/%s/%s", mysql_data_home, db, MY_DB_OPT_FILE); fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME)); - if ((error=write_db_opt(path, create_info))) + if ((error=write_db_opt(thd, path, create_info))) goto exit; /* @@ -280,7 +287,9 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if (thd->db && !strcmp(thd->db,db)) { thd->db_charset= (create_info && create_info->table_charset) ? - create_info->table_charset : default_charset_info; + create_info->table_charset : + global_system_variables.character_set_database; + thd->variables.character_set_database= thd->db_charset; } mysql_update_log.write(thd,thd->query, thd->query_length); @@ -615,8 +624,11 @@ bool mysql_change_db(THD *thd, const char *name) thd->db_access=db_access; strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE); - load_db_opt(path, &create); - thd->db_charset= create.table_charset ? create.table_charset : default_charset_info; + load_db_opt(thd, path, &create); + thd->db_charset= create.table_charset ? + create.table_charset : + global_system_variables.character_set_database; + thd->variables.character_set_database= thd->db_charset; DBUG_RETURN(0); } @@ -674,7 +686,7 @@ int mysqld_show_create_db(THD *thd, char *dbname, if (found_libchar) path[length-1]= FN_LIBCHAR; strmov(path+length, MY_DB_OPT_FILE); - load_db_opt(path, &create); + load_db_opt(thd, path, &create); List field_list; field_list.push_back(new Item_empty_string("Database",NAME_LEN)); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 758ff88477b..12acfb9b5df 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -215,7 +215,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, info.handle_duplicates=handle_duplicates; info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX; - READ_INFO read_info(file,tot_length,thd->db_charset, + READ_INFO read_info(file,tot_length,thd->variables.character_set_database, *field_term,*ex->line_start, *ex->line_term, *enclosed, info.escape_char, read_file_from_client, is_fifo); if (read_info.error) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ea3b30d24e8..c53ca0b68a8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -481,7 +481,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { if (!sql_field->charset) sql_field->charset = create_info->table_charset ? - create_info->table_charset : thd->db_charset; + create_info->table_charset : + thd->variables.character_set_database; switch (sql_field->sql_type) { case FIELD_TYPE_BLOB: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bab6d05a0e0..3f96826d445 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -848,7 +848,7 @@ create: bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.options=$2 | $4; lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type; - lex->create_info.table_charset= thd->db_charset; + lex->create_info.table_charset= thd->variables.character_set_database; lex->name=0; } create2 @@ -1536,7 +1536,7 @@ alter: lex->select_lex.db=lex->name=0; bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= DB_TYPE_DEFAULT; - lex->create_info.table_charset= thd->db_charset; + lex->create_info.table_charset= thd->variables.character_set_database; lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->alter_keys_onoff=LEAVE_AS_IS; lex->simple_alter=1; @@ -4439,7 +4439,7 @@ option_value: THD *thd= YYTHD; LEX *lex= Lex; $2= $2 ? $2: global_system_variables.character_set_client; - lex->var_list.push_back(new set_var_collation_client($2,thd->db_charset,$2)); + lex->var_list.push_back(new set_var_collation_client($2,thd->variables.character_set_database,$2)); } | NAMES_SYM charset_name_or_default opt_collate { From 677ece6612b833227977ea3cfbbff29328224b69 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 13:24:24 +0500 Subject: [PATCH 269/399] set_var.cc, set_var.h: character_set_connection new variable sql/set_var.h: character_set_connection new variable sql/set_var.cc: character_set_connection new variable --- sql/set_var.cc | 19 +++++++++++++++++++ sql/set_var.h | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/sql/set_var.cc b/sql/set_var.cc index e6cdaf1d3fb..f1a36ae0292 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -110,6 +110,7 @@ sys_var_str sys_charset_system("character_set_system", sys_set_default_charset); sys_var_character_set_database sys_character_set_database("character_set_database"); sys_var_character_set_client sys_character_set_client("character_set_client"); +sys_var_character_set_connection sys_character_set_connection("character_set_connection"); sys_var_character_set_results sys_character_set_results("character_set_results"); sys_var_collation_connection sys_collation_connection("collation_connection"); sys_var_bool_ptr sys_concurrent_insert("concurrent_insert", @@ -363,6 +364,7 @@ sys_var *sys_variables[]= &sys_character_set_server, &sys_character_set_database, &sys_character_set_client, + &sys_character_set_connection, &sys_character_set_results, &sys_collation_connection, &sys_concurrent_insert, @@ -485,6 +487,7 @@ struct show_var_st init_vars[]= { {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS}, {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS}, {sys_character_set_client.name,(char*) &sys_character_set_client,SHOW_SYS}, + {sys_character_set_connection.name,(char*) &sys_character_set_connection,SHOW_SYS}, {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS}, {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, {sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS}, @@ -1302,6 +1305,22 @@ byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type) } +CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + return &global_system_variables.collation_connection; + else + return &thd->variables.collation_connection; +} + +void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + global_system_variables.collation_connection= default_charset_info; + else + thd->variables.collation_connection= global_system_variables.collation_connection; +} + CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type type) { diff --git a/sql/set_var.h b/sql/set_var.h index 7c1a9bc3233..785f7f7e4f8 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -483,6 +483,15 @@ public: CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; +class sys_var_character_set_connection :public sys_var_character_set +{ +public: + sys_var_character_set_connection(const char *name_arg) : + sys_var_character_set(name_arg) {} + void set_default(THD *thd, enum_var_type type); + CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); +}; + class sys_var_collation_connection :public sys_var_collation { public: From 7953039deddbf08c62498d4551745563ec572993 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 13:56:02 +0500 Subject: [PATCH 270/399] SET character_set_results=NULL is now working --- sql/set_var.cc | 12 +++++++++--- sql/set_var.h | 7 +++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sql/set_var.cc b/sql/set_var.cc index f1a36ae0292..eb44dd1dbcb 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1280,9 +1280,15 @@ bool sys_var_character_set::check(THD *thd, set_var *var) String str(buff,sizeof(buff), system_charset_info), *res; if (!(res=var->value->val_str(&str))) - res= &empty_string; - - if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) && + { + if (!nullable) + { + my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "NULL"); + return 1; + } + tmp= NULL; + } + else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) && !(tmp=get_old_charset_by_name(res->c_ptr()))) { my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr()); diff --git a/sql/set_var.h b/sql/set_var.h index 785f7f7e4f8..d016c3a7085 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -433,7 +433,9 @@ SHOW_TYPE type() { return SHOW_CHAR; } class sys_var_character_set :public sys_var_thd { public: - sys_var_character_set(const char *name_arg) :sys_var_thd(name_arg) {} + bool nullable; + sys_var_character_set(const char *name_arg) :sys_var_thd(name_arg) + { nullable= 0; } bool check(THD *thd, set_var *var); SHOW_TYPE type() { return SHOW_CHAR; } bool check_update_type(Item_result type) @@ -460,7 +462,8 @@ class sys_var_character_set_results :public sys_var_character_set { public: sys_var_character_set_results(const char *name_arg) : - sys_var_character_set(name_arg) {} + sys_var_character_set(name_arg) + { nullable= 1; } void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; From 8b9fea0ce5c017c15c01cdf256b770a6ed949f6d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 15:21:03 +0500 Subject: [PATCH 271/399] mysqldump.c: mysqldump now produces SET NAMES. It can be disabled by --no-set-names client/mysqldump.c: mysqldump now produces SET NAMES. It can be disabled by --no-set-names --- client/mysqldump.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 86f03b46038..18705b9e375 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -77,7 +77,7 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1, lock_tables=1,ignore_errors=0,flush_logs=0,replace=0, ignore=0,opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0, opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0, - opt_alldbs=0,opt_create_db=0,opt_first_slave=0, + opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_names=0, opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0, opt_delete_master_logs=0, tty_password=0, opt_single_transaction=0; @@ -85,7 +85,7 @@ static MYSQL mysql_connection,*sock=0; static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, - *where=0, *default_charset= (char *)MYSQL_DEFAULT_CHARSET_NAME, + *where=0, *default_charset= (char *) "binary", *opt_compatible_mode_str= 0, *err_ptr= 0; static ulong opt_compatible_mode= 0; @@ -212,6 +212,10 @@ static struct my_option my_long_options[] = (gptr*) &tFlag, (gptr*) &tFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-data", 'd', "No row information.", (gptr*) &dFlag, (gptr*) &dFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"no-set-names", 'N', + "'SET NAMES charset_name' will not be put in the output.", + (gptr*) &opt_set_names, (gptr*) &opt_set_names, 0, GET_BOOL, NO_ARG, 0, 0, + 0, 0, 0, 0}, {"set-variable", 'O', "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -345,6 +349,8 @@ static void write_header(FILE *sql_file, char *db_name) sql_file); fprintf(sql_file, "-- Server version\t%s\n", mysql_get_server_info(&mysql_connection)); + if (!opt_set_names) + fprintf(sql_file,"\n/*!40101 SET NAMES %s*/;\n",default_charset); } return; } /* write_header */ @@ -557,6 +563,7 @@ static int dbConnect(char *host, char *user,char *passwd) if (shared_memory_base_name) mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); #endif + mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd, NULL,opt_mysql_port,opt_mysql_unix_port, 0))) From 7a99669fbcf534d7e4fa869c4d729f21bc625b1b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 15:22:34 +0500 Subject: [PATCH 272/399] Moved spatial functions to the sql/item_geofunc.cc file. BitKeeper/etc/ignore: Added libmysqld/item_geofunc.cc to the ignore list --- .bzrignore | 1 + libmysqld/Makefile.am | 2 +- sql/Makefile.am | 4 +- sql/item.h | 1 + sql/item_cmpfunc.cc | 82 ------ sql/item_cmpfunc.h | 76 ----- sql/item_func.cc | 136 --------- sql/item_func.h | 95 ------ sql/item_geofunc.cc | 653 ++++++++++++++++++++++++++++++++++++++++++ sql/item_geofunc.h | 360 +++++++++++++++++++++++ sql/item_strfunc.cc | 422 --------------------------- sql/item_strfunc.h | 239 ---------------- 12 files changed, 1018 insertions(+), 1053 deletions(-) create mode 100644 sql/item_geofunc.cc create mode 100644 sql/item_geofunc.h diff --git a/.bzrignore b/.bzrignore index 82adbf625f3..b1bde9bc6ed 100644 --- a/.bzrignore +++ b/.bzrignore @@ -617,3 +617,4 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl include/readline/*.h +libmysqld/item_geofunc.cc diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 93702e5b6d0..d127112819e 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -42,7 +42,7 @@ sqlsources = derror.cc field.cc field_conv.cc filesort.cc \ hostname.cc init.cc password.c \ item.cc item_buff.cc item_cmpfunc.cc item_create.cc \ item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \ - item_uniq.cc item_subselect.cc item_row.cc\ + item_geofunc.cc item_uniq.cc item_subselect.cc item_row.cc\ key.cc lock.cc log.cc log_event.cc mf_iocache.cc\ mini_client.cc protocol.cc net_serv.cc opt_ft.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ diff --git a/sql/Makefile.am b/sql/Makefile.am index 608b959a8b9..6e7f2f08a1d 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -46,7 +46,7 @@ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h item_uniq.h \ item_create.h item_subselect.h item_row.h \ - mysql_priv.h \ + mysql_priv.h item_geofunc.h \ procedure.h sql_class.h sql_lex.h sql_list.h \ sql_manager.h sql_map.h sql_string.h unireg.h \ field.h handler.h \ @@ -62,7 +62,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \ item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \ thr_malloc.cc item_create.cc item_subselect.cc \ - item_row.cc \ + item_row.cc item_geofunc.cc \ field.cc key.cc sql_class.cc sql_list.cc \ net_serv.cc protocol.cc lock.cc my_lock.c \ sql_string.cc sql_manager.cc sql_map.cc \ diff --git a/sql/item.h b/sql/item.h index 470937f8ee7..2d285bbe434 100644 --- a/sql/item.h +++ b/sql/item.h @@ -644,6 +644,7 @@ public: #include "item_row.h" #include "item_cmpfunc.h" #include "item_strfunc.h" +#include "item_geofunc.h" #include "item_timefunc.h" #include "item_uniq.h" #include "item_subselect.h" diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4f55357f288..299014689f0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2363,85 +2363,3 @@ longlong Item_cond_xor::val_int() } return (longlong) result; } - -/**************************************************************** - Classes and functions for spatial relations -*****************************************************************/ - -longlong Item_func_spatial_rel::val_int() -{ - String *res1= args[0]->val_str(&tmp_value1); - String *res2= args[1]->val_str(&tmp_value2); - Geometry g1, g2; - MBR mbr1, mbr2; - - if ((null_value= (args[0]->null_value || - args[1]->null_value || - g1.create_from_wkb(res1->ptr() + SRID_SIZE, - res1->length() - SRID_SIZE) || - g2.create_from_wkb(res2->ptr() + SRID_SIZE, - res2->length() - SRID_SIZE) || - g1.get_mbr(&mbr1) || - g2.get_mbr(&mbr2)))) - return 0; - - switch (spatial_rel) - { - case SP_CONTAINS_FUNC: - return mbr1.contains(&mbr2); - case SP_WITHIN_FUNC: - return mbr1.within(&mbr2); - case SP_EQUALS_FUNC: - return mbr1.equals(&mbr2); - case SP_DISJOINT_FUNC: - return mbr1.disjoint(&mbr2); - case SP_INTERSECTS_FUNC: - return mbr1.intersects(&mbr2); - case SP_TOUCHES_FUNC: - return mbr1.touches(&mbr2); - case SP_OVERLAPS_FUNC: - return mbr1.overlaps(&mbr2); - case SP_CROSSES_FUNC: - return 0; - default: - break; - } - - null_value=1; - return 0; -} - -longlong Item_func_isempty::val_int() -{ - String tmp; - null_value=0; - return args[0]->null_value ? 1 : 0; -} - -longlong Item_func_issimple::val_int() -{ - String tmp; - String *wkb=args[0]->val_str(&tmp); - - if ((null_value= (!wkb || args[0]->null_value ))) - return 0; - /* TODO: Ramil or Holyfoot, add real IsSimple calculation */ - return 0; -} - -longlong Item_func_isclosed::val_int() -{ - String tmp; - String *swkb= args[0]->val_str(&tmp); - Geometry geom; - int isclosed; - - null_value= (!swkb || - args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom,is_closed) || - geom.is_closed(&isclosed)); - - return (longlong) isclosed; -} diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index ff469deab30..4438b902011 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -850,79 +850,3 @@ inline Item *and_conds(Item *a,Item *b) } Item *and_expressions(Item *a, Item *b, Item **org_item); - -/************************************************************** - Spatial relations -***************************************************************/ - -class Item_func_spatial_rel :public Item_bool_func2 -{ - enum Functype spatial_rel; -public: - Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) : - Item_bool_func2(a,b) { spatial_rel = sp_rel; } - longlong val_int(); - enum Functype functype() const - { - switch (spatial_rel) { - case SP_CONTAINS_FUNC: - return SP_WITHIN_FUNC; - case SP_WITHIN_FUNC: - return SP_CONTAINS_FUNC; - default: - return spatial_rel; - } - } - enum Functype rev_functype() const { return spatial_rel; } - const char *func_name() const - { - switch (spatial_rel) { - case SP_CONTAINS_FUNC: - return "contains"; - case SP_WITHIN_FUNC: - return "within"; - case SP_EQUALS_FUNC: - return "equals"; - case SP_DISJOINT_FUNC: - return "disjoint"; - case SP_INTERSECTS_FUNC: - return "intersects"; - case SP_TOUCHES_FUNC: - return "touches"; - case SP_CROSSES_FUNC: - return "crosses"; - case SP_OVERLAPS_FUNC: - return "overlaps"; - default: - return "sp_unknown"; - } - } -}; - - -class Item_func_isempty :public Item_bool_func -{ -public: - Item_func_isempty(Item *a) :Item_bool_func(a) {} - longlong val_int(); - optimize_type select_optimize() const { return OPTIMIZE_NONE; } - const char *func_name() const { return "isempty"; } -}; - -class Item_func_issimple :public Item_bool_func -{ -public: - Item_func_issimple(Item *a) :Item_bool_func(a) {} - longlong val_int(); - optimize_type select_optimize() const { return OPTIMIZE_NONE; } - const char *func_name() const { return "issimple"; } -}; - -class Item_func_isclosed :public Item_bool_func -{ -public: - Item_func_isclosed(Item *a) :Item_bool_func(a) {} - longlong val_int(); - optimize_type select_optimize() const { return OPTIMIZE_NONE; } - const char *func_name() const { return "isclosed"; } -}; diff --git a/sql/item_func.cc b/sql/item_func.cc index 7ed9e5c85f6..6482d81f484 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2680,139 +2680,3 @@ longlong Item_func_is_used_lock::val_int() null_value=0; return ull->thread_id; } - - - -/************************************************************************** - Spatial functions -***************************************************************************/ - -longlong Item_func_dimension::val_int() -{ - uint32 dim; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - geom.dimension(&dim)); - return (longlong) dim; -} - -longlong Item_func_numinteriorring::val_int() -{ - uint32 num; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, num_interior_ring) || - geom.num_interior_ring(&num)); - return (longlong) num; -} - -longlong Item_func_numgeometries::val_int() -{ - uint32 num= 0; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, num_geometries) || - geom.num_geometries(&num)); - return (longlong) num; -} - -longlong Item_func_numpoints::val_int() -{ - uint32 num; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, num_points) || - geom.num_points(&num)); - return (longlong) num; -} - - -double Item_func_x::val() -{ - double res; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, get_x) || - geom.get_x(&res)); - return res; -} - - -double Item_func_y::val() -{ - double res; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, get_y) || - geom.get_y(&res)); - return res; -} - - -double Item_func_area::val() -{ - double res; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, area) || - geom.area(&res)); - return res; -} - - -double Item_func_glength::val() -{ - double res; - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, length) || - geom.length(&res)); - return res; -} - - -longlong Item_func_srid::val_int() -{ - String *swkb= args[0]->val_str(&value); - Geometry geom; - - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)); - uint32 res= uint4korr(swkb->ptr()); - return (longlong) res; -} diff --git a/sql/item_func.h b/sql/item_func.h index e1d6156c12c..8ef2b85de52 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1037,101 +1037,6 @@ public: }; -class Item_func_dimension :public Item_int_func -{ - String value; -public: - Item_func_dimension(Item *a) :Item_int_func(a) {} - longlong val_int(); - const char *func_name() const { return "dimension"; } - void fix_length_and_dec() { max_length=10; } -}; - - -class Item_func_x :public Item_real_func -{ - String value; -public: - Item_func_x(Item *a) :Item_real_func(a) {} - double val(); - const char *func_name() const { return "x"; } -}; - - -class Item_func_y :public Item_real_func -{ - String value; -public: - Item_func_y(Item *a) :Item_real_func(a) {} - double val(); - const char *func_name() const { return "y"; } -}; - - -class Item_func_numgeometries :public Item_int_func -{ - String value; -public: - Item_func_numgeometries(Item *a) :Item_int_func(a) {} - longlong val_int(); - const char *func_name() const { return "numgeometries"; } - void fix_length_and_dec() { max_length=10; } -}; - - -class Item_func_numinteriorring :public Item_int_func -{ - String value; -public: - Item_func_numinteriorring(Item *a) :Item_int_func(a) {} - longlong val_int(); - const char *func_name() const { return "numinteriorring"; } - void fix_length_and_dec() { max_length=10; } -}; - - -class Item_func_numpoints :public Item_int_func -{ - String value; -public: - Item_func_numpoints(Item *a) :Item_int_func(a) {} - longlong val_int(); - const char *func_name() const { return "numpoints"; } - void fix_length_and_dec() { max_length=10; } -}; - - -class Item_func_area :public Item_real_func -{ - String value; -public: - Item_func_area(Item *a) :Item_real_func(a) {} - double val(); - const char *func_name() const { return "area"; } -}; - - -class Item_func_glength :public Item_real_func -{ - String value; -public: - Item_func_glength(Item *a) :Item_real_func(a) {} - double val(); - const char *func_name() const { return "glength"; } -}; - - -class Item_func_srid: public Item_int_func -{ - String value; -public: - Item_func_srid(Item *a): Item_int_func(a) {} - longlong val_int(); - const char *func_name() const { return "srid"; } - void fix_length_and_dec() { max_length= 10; } -}; - - class Item_func_match_nl :public Item_func_match { public: diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc new file mode 100644 index 00000000000..06ba67cbc73 --- /dev/null +++ b/sql/item_geofunc.cc @@ -0,0 +1,653 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + + +/* This file defines all spatial functions */ + +#ifdef __GNUC__ +#pragma implementation // gcc: Class implementation +#endif + +#include "mysql_priv.h" +#include "sql_acl.h" +#include + +String *Item_func_geometry_from_text::val_str(String *str) +{ + Geometry geom; + String arg_val; + String *wkt= args[0]->val_str(&arg_val); + GTextReadStream trs(wkt->ptr(), wkt->length()); + uint32 srid; + + if ((arg_count == 2) && !args[1]->null_value) + srid= args[1]->val_int(); + else + srid= 0; + + if (str->reserve(SRID_SIZE, 512)) + return 0; + str->length(0); + str->q_append(srid); + if ((null_value=(args[0]->null_value || geom.create_from_wkt(&trs, str, 0)))) + return 0; + return str; +} + + +void Item_func_geometry_from_text::fix_length_and_dec() +{ + max_length=MAX_BLOB_WIDTH; +} + + +String *Item_func_geometry_from_wkb::val_str(String *str) +{ + String arg_val; + String *wkb= args[0]->val_str(&arg_val); + Geometry geom; + uint32 srid; + + if ((arg_count == 2) && !args[1]->null_value) + srid= args[1]->val_int(); + else + srid= 0; + + if (str->reserve(SRID_SIZE, 512)) + return 0; + str->length(0); + str->q_append(srid); + if ((null_value= (args[0]->null_value || + geom.create_from_wkb(wkb->ptr(), wkb->length())))) + return 0; + + str->append(*wkb); + return str; +} + + +void Item_func_geometry_from_wkb::fix_length_and_dec() +{ + max_length=MAX_BLOB_WIDTH; +} + + +String *Item_func_as_text::val_str(String *str) +{ + String arg_val; + String *swkb= args[0]->val_str(&arg_val); + Geometry geom; + + if ((null_value= (args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)))) + return 0; + + str->length(0); + + if ((null_value= geom.as_wkt(str))) + return 0; + + return str; +} + +void Item_func_as_text::fix_length_and_dec() +{ + max_length=MAX_BLOB_WIDTH; +} + +String *Item_func_as_wkb::val_str(String *str) +{ + String arg_val; + String *swkb= args[0]->val_str(&arg_val); + Geometry geom; + + if ((null_value= (args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)))) + return 0; + + str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE, + &my_charset_bin); + return str; +} + +void Item_func_as_wkb::fix_length_and_dec() +{ + max_length= MAX_BLOB_WIDTH; +} + +String *Item_func_geometry_type::val_str(String *str) +{ + String *swkb= args[0]->val_str(str); + Geometry geom; + + if ((null_value= (args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)))) + return 0; + str->copy(geom.get_class_info()->m_name, + strlen(geom.get_class_info()->m_name), + default_charset_info); + return str; +} + + +String *Item_func_envelope::val_str(String *str) +{ + String arg_val; + String *swkb= args[0]->val_str(&arg_val); + Geometry geom; + + if ((null_value= args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE))) + return 0; + + uint32 srid= uint4korr(swkb->ptr()); + str->length(0); + if (str->reserve(SRID_SIZE, 512)) + return 0; + str->q_append(srid); + return (null_value= geom.envelope(str)) ? 0 : str; +} + + +String *Item_func_centroid::val_str(String *str) +{ + String arg_val; + String *swkb= args[0]->val_str(&arg_val); + Geometry geom; + + if ((null_value= args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, centroid))) + return 0; + + if (str->reserve(SRID_SIZE, 512)) + return 0; + str->length(0); + uint32 srid= uint4korr(swkb->ptr()); + str->q_append(srid); + + return (null_value= geom.centroid(str)) ? 0 : str; +} + + +/* + Spatial decomposition functions +*/ + +String *Item_func_spatial_decomp::val_str(String *str) +{ + String arg_val; + String *swkb= args[0]->val_str(&arg_val); + Geometry geom; + + if ((null_value= (args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)))) + return 0; + + null_value= 1; + if (str->reserve(SRID_SIZE, 512)) + return 0; + str->length(0); + uint32 srid= uint4korr(swkb->ptr()); + str->q_append(srid); + switch(decomp_func) + { + case SP_STARTPOINT: + if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str)) + goto ret; + break; + + case SP_ENDPOINT: + if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str)) + goto ret; + break; + + case SP_EXTERIORRING: + if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str)) + goto ret; + break; + + default: + goto ret; + } + null_value= 0; + +ret: + return null_value ? 0 : str; +} + + +String *Item_func_spatial_decomp_n::val_str(String *str) +{ + String arg_val; + String *swkb= args[0]->val_str(&arg_val); + long n= (long) args[1]->val_int(); + Geometry geom; + + if ((null_value= (args[0]->null_value || args[1]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)))) + return 0; + + null_value= 1; + if (str->reserve(SRID_SIZE, 512)) + return 0; + str->length(0); + uint32 srid= uint4korr(swkb->ptr()); + str->q_append(srid); + switch(decomp_func_n) + { + case SP_POINTN: + if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str)) + goto ret; + break; + + case SP_GEOMETRYN: + if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str)) + goto ret; + break; + + case SP_INTERIORRINGN: + if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) || + geom.interior_ring_n(n,str)) + goto ret; + break; + + default: + goto ret; + } + null_value= 0; + +ret: + return null_value ? 0 : str; +} + + +/* + Functions to concatinate various spatial objects +*/ + + +/* +* Concatinate doubles into Point +*/ + + +String *Item_func_point::val_str(String *str) +{ + double x= args[0]->val(); + double y= args[1]->val(); + + if ( (null_value= (args[0]->null_value || + args[1]->null_value || + str->realloc(1 + 4 + 8 + 8)))) + return 0; + + str->length(0); + str->q_append((char)Geometry::wkbNDR); + str->q_append((uint32)Geometry::wkbPoint); + str->q_append(x); + str->q_append(y); + return str; +} + + +/* + Concatinates various items into various collections + with checkings for valid wkb type of items. + For example, MultiPoint can be a collection of Points only. + coll_type contains wkb type of target collection. + item_type contains a valid wkb type of items. + In the case when coll_type is wkbGeometryCollection, + we do not check wkb type of items, any is valid. +*/ + +String *Item_func_spatial_collection::val_str(String *str) +{ + String arg_value; + uint i; + + null_value= 1; + + str->length(0); + if (str->reserve(1 + 4 + 4, 512)) + return 0; + + str->q_append((char) Geometry::wkbNDR); + str->q_append((uint32) coll_type); + str->q_append((uint32) arg_count); + + for (i= 0; i < arg_count; ++i) + { + String *res= args[i]->val_str(&arg_value); + if (args[i]->null_value) + goto ret; + + if ( coll_type == Geometry::wkbGeometryCollection ) + { + /* + In the case of GeometryCollection we don't need + any checkings for item types, so just copy them + into target collection + */ + if ((null_value= str->reserve(res->length(), 512))) + goto ret; + + str->q_append(res->ptr(), res->length()); + } + else + { + enum Geometry::wkbType wkb_type; + uint32 len=res->length(); + const char *data= res->ptr() + 1; + + /* + In the case of named collection we must to + check that items are of specific type, let's + do this checking now + */ + + if (len < 5) + goto ret; + wkb_type= (Geometry::wkbType) uint4korr(data); + data+= 4; + len-= 5; + if (wkb_type != item_type) + goto ret; + + switch (coll_type) { + case Geometry::wkbMultiPoint: + case Geometry::wkbMultiLineString: + case Geometry::wkbMultiPolygon: + if (len < WKB_HEADER_SIZE) + goto ret; + + data-= WKB_HEADER_SIZE; + len+= WKB_HEADER_SIZE; + if (str->reserve(len, 512)) + goto ret; + str->q_append(data, len); + break; + + case Geometry::wkbLineString: + if (str->reserve(POINT_DATA_SIZE, 512)) + goto ret; + str->q_append(data, POINT_DATA_SIZE); + break; + + case Geometry::wkbPolygon: + { + uint32 n_points; + double x1, y1, x2, y2; + + if (len < 4 + 2 * POINT_DATA_SIZE) + goto ret; + + uint32 llen= len; + const char *ldata= data; + + n_points= uint4korr(data); + data+= 4; + float8get(x1, data); + data+= 8; + float8get(y1, data); + data+= 8; + + data+= (n_points - 2) * POINT_DATA_SIZE; + + float8get(x2, data); + float8get(y2, data + 8); + + if ((x1 != x2) || (y1 != y2)) + goto ret; + + if (str->reserve(llen, 512)) + goto ret; + str->q_append(ldata, llen); + } + break; + + default: + goto ret; + } + } + } + + if (str->length() > current_thd->variables.max_allowed_packet) + goto ret; + + null_value = 0; + +ret: + return null_value ? 0 : str; +} + +/* + Functions for spatial relations +*/ + +longlong Item_func_spatial_rel::val_int() +{ + String *res1= args[0]->val_str(&tmp_value1); + String *res2= args[1]->val_str(&tmp_value2); + Geometry g1, g2; + MBR mbr1, mbr2; + + if ((null_value= (args[0]->null_value || + args[1]->null_value || + g1.create_from_wkb(res1->ptr() + SRID_SIZE, + res1->length() - SRID_SIZE) || + g2.create_from_wkb(res2->ptr() + SRID_SIZE, + res2->length() - SRID_SIZE) || + g1.get_mbr(&mbr1) || + g2.get_mbr(&mbr2)))) + return 0; + + switch (spatial_rel) + { + case SP_CONTAINS_FUNC: + return mbr1.contains(&mbr2); + case SP_WITHIN_FUNC: + return mbr1.within(&mbr2); + case SP_EQUALS_FUNC: + return mbr1.equals(&mbr2); + case SP_DISJOINT_FUNC: + return mbr1.disjoint(&mbr2); + case SP_INTERSECTS_FUNC: + return mbr1.intersects(&mbr2); + case SP_TOUCHES_FUNC: + return mbr1.touches(&mbr2); + case SP_OVERLAPS_FUNC: + return mbr1.overlaps(&mbr2); + case SP_CROSSES_FUNC: + return 0; + default: + break; + } + + null_value=1; + return 0; +} + +longlong Item_func_isempty::val_int() +{ + String tmp; + null_value=0; + return args[0]->null_value ? 1 : 0; +} + +longlong Item_func_issimple::val_int() +{ + String tmp; + String *wkb=args[0]->val_str(&tmp); + + if ((null_value= (!wkb || args[0]->null_value ))) + return 0; + /* TODO: Ramil or Holyfoot, add real IsSimple calculation */ + return 0; +} + +longlong Item_func_isclosed::val_int() +{ + String tmp; + String *swkb= args[0]->val_str(&tmp); + Geometry geom; + int isclosed; + + null_value= (!swkb || + args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom,is_closed) || + geom.is_closed(&isclosed)); + + return (longlong) isclosed; +} + +/* + Numerical functions +*/ + +longlong Item_func_dimension::val_int() +{ + uint32 dim; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + geom.dimension(&dim)); + return (longlong) dim; +} + +longlong Item_func_numinteriorring::val_int() +{ + uint32 num; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, num_interior_ring) || + geom.num_interior_ring(&num)); + return (longlong) num; +} + +longlong Item_func_numgeometries::val_int() +{ + uint32 num= 0; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, num_geometries) || + geom.num_geometries(&num)); + return (longlong) num; +} + +longlong Item_func_numpoints::val_int() +{ + uint32 num; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + args[0]->null_value || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, num_points) || + geom.num_points(&num)); + return (longlong) num; +} + +double Item_func_x::val() +{ + double res; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, get_x) || + geom.get_x(&res)); + return res; +} + +double Item_func_y::val() +{ + double res; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, get_y) || + geom.get_y(&res)); + return res; +} + +double Item_func_area::val() +{ + double res; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, area) || + geom.area(&res)); + return res; +} + +double Item_func_glength::val() +{ + double res; + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE) || + !GEOM_METHOD_PRESENT(geom, length) || + geom.length(&res)); + return res; +} + +longlong Item_func_srid::val_int() +{ + String *swkb= args[0]->val_str(&value); + Geometry geom; + + null_value= (!swkb || + geom.create_from_wkb(swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)); + uint32 res= uint4korr(swkb->ptr()); + return (longlong) res; +} diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h new file mode 100644 index 00000000000..21e94735f31 --- /dev/null +++ b/sql/item_geofunc.h @@ -0,0 +1,360 @@ +/* Copyright (C) 2000-2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +/* This file defines all spatial functions */ + +#ifdef __GNUC__ +#pragma interface /* gcc class implementation */ +#endif + +#define SRID_SIZE sizeof(uint32) + +class Item_func_geometry_from_text: public Item_str_func +{ +public: + Item_func_geometry_from_text(Item *a) :Item_str_func(a) {} + Item_func_geometry_from_text(Item *a, Item *srid) :Item_str_func(a, srid) {} + const char *func_name() const { return "geometryfromtext"; } + String *val_str(String *); + void fix_length_and_dec(); +}; + +class Item_func_geometry_from_wkb: public Item_str_func +{ +public: + Item_func_geometry_from_wkb(Item *a): Item_str_func(a) {} + Item_func_geometry_from_wkb(Item *a, Item *srid): Item_str_func(a, srid) {} + const char *func_name() const { return "geometryfromwkb"; } + String *val_str(String *); + void fix_length_and_dec(); +}; + +class Item_func_as_text: public Item_str_func +{ +public: + Item_func_as_text(Item *a): Item_str_func(a) {} + const char *func_name() const { return "astext"; } + String *val_str(String *); + void fix_length_and_dec(); +}; + +class Item_func_as_wkb: public Item_str_func +{ +public: + Item_func_as_wkb(Item *a): Item_str_func(a) {} + const char *func_name() const { return "aswkb"; } + String *val_str(String *); + void fix_length_and_dec(); +}; + +class Item_func_geometry_type: public Item_str_func +{ +public: + Item_func_geometry_type(Item *a): Item_str_func(a) {} + String *val_str(String *); + const char *func_name() const { return "geometrytype"; } + void fix_length_and_dec() + { + max_length=20; // "GeometryCollection" is the most long + }; +}; + +class Item_func_centroid: public Item_str_func +{ +public: + Item_func_centroid(Item *a): Item_str_func(a) {} + const char *func_name() const { return "centroid"; } + String *val_str(String *); + void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} +}; + +class Item_func_envelope: public Item_str_func +{ +public: + Item_func_envelope(Item *a): Item_str_func(a) {} + const char *func_name() const { return "envelope"; } + String *val_str(String *); + void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} +}; + +class Item_func_point: public Item_str_func +{ +public: + Item_func_point(Item *a, Item *b): Item_str_func(a, b) {} + Item_func_point(Item *a, Item *b, Item *srid): Item_str_func(a, b, srid) {} + const char *func_name() const { return "point"; } + String *val_str(String *); + void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} +}; + +class Item_func_spatial_decomp: public Item_str_func +{ + enum Functype decomp_func; +public: + Item_func_spatial_decomp(Item *a, Item_func::Functype ft) : + Item_str_func(a) { decomp_func = ft; } + const char *func_name() const + { + switch (decomp_func) + { + case SP_STARTPOINT: + return "startpoint"; + case SP_ENDPOINT: + return "endpoint"; + case SP_EXTERIORRING: + return "exteriorring"; + default: + return "spatial_decomp_unknown"; + } + } + String *val_str(String *); + void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} +}; + +class Item_func_spatial_decomp_n: public Item_str_func +{ + enum Functype decomp_func_n; +public: + Item_func_spatial_decomp_n(Item *a, Item *b, Item_func::Functype ft): + Item_str_func(a, b) { decomp_func_n = ft; } + const char *func_name() const + { + switch (decomp_func_n) + { + case SP_POINTN: + return "pointn"; + case SP_GEOMETRYN: + return "geometryn"; + case SP_INTERIORRINGN: + return "interiorringn"; + default: + return "spatial_decomp_n_unknown"; + } + } + String *val_str(String *); + void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} +}; + +class Item_func_spatial_collection: public Item_str_func +{ + String tmp_value; + enum Geometry::wkbType coll_type; + enum Geometry::wkbType item_type; +public: + Item_func_spatial_collection( + List &list, enum Geometry::wkbType ct, enum Geometry::wkbType it): + Item_str_func(list) + { + coll_type=ct; + item_type=it; + } + String *val_str(String *); + void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} + const char *func_name() const { return "multipoint"; } +}; + +#ifdef HAVE_COMPRESS + +class Item_func_compress: public Item_str_func +{ + String buffer; +public: + Item_func_compress(Item *a):Item_str_func(a){} + String *val_str(String *); + void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;} + const char *func_name() const{return "compress";} +}; + +class Item_func_uncompress: public Item_str_func +{ + String buffer; +public: + Item_func_uncompress(Item *a): Item_str_func(a){} + String *val_str(String *); + void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;} + const char *func_name() const{return "uncompress";} +}; + +#endif + +/* + Spatial relations +*/ + +class Item_func_spatial_rel: public Item_bool_func2 +{ + enum Functype spatial_rel; +public: + Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) : + Item_bool_func2(a,b) { spatial_rel = sp_rel; } + longlong val_int(); + enum Functype functype() const + { + switch (spatial_rel) { + case SP_CONTAINS_FUNC: + return SP_WITHIN_FUNC; + case SP_WITHIN_FUNC: + return SP_CONTAINS_FUNC; + default: + return spatial_rel; + } + } + enum Functype rev_functype() const { return spatial_rel; } + const char *func_name() const + { + switch (spatial_rel) { + case SP_CONTAINS_FUNC: + return "contains"; + case SP_WITHIN_FUNC: + return "within"; + case SP_EQUALS_FUNC: + return "equals"; + case SP_DISJOINT_FUNC: + return "disjoint"; + case SP_INTERSECTS_FUNC: + return "intersects"; + case SP_TOUCHES_FUNC: + return "touches"; + case SP_CROSSES_FUNC: + return "crosses"; + case SP_OVERLAPS_FUNC: + return "overlaps"; + default: + return "sp_unknown"; + } + } +}; + +class Item_func_isempty: public Item_bool_func +{ +public: + Item_func_isempty(Item *a): Item_bool_func(a) {} + longlong val_int(); + optimize_type select_optimize() const { return OPTIMIZE_NONE; } + const char *func_name() const { return "isempty"; } +}; + +class Item_func_issimple: public Item_bool_func +{ +public: + Item_func_issimple(Item *a): Item_bool_func(a) {} + longlong val_int(); + optimize_type select_optimize() const { return OPTIMIZE_NONE; } + const char *func_name() const { return "issimple"; } +}; + +class Item_func_isclosed: public Item_bool_func +{ +public: + Item_func_isclosed(Item *a): Item_bool_func(a) {} + longlong val_int(); + optimize_type select_optimize() const { return OPTIMIZE_NONE; } + const char *func_name() const { return "isclosed"; } +}; + +class Item_func_dimension: public Item_int_func +{ + String value; +public: + Item_func_dimension(Item *a): Item_int_func(a) {} + longlong val_int(); + const char *func_name() const { return "dimension"; } + void fix_length_and_dec() { max_length=10; } +}; + +class Item_func_x: public Item_real_func +{ + String value; +public: + Item_func_x(Item *a): Item_real_func(a) {} + double val(); + const char *func_name() const { return "x"; } +}; + + +class Item_func_y: public Item_real_func +{ + String value; +public: + Item_func_y(Item *a): Item_real_func(a) {} + double val(); + const char *func_name() const { return "y"; } +}; + + +class Item_func_numgeometries: public Item_int_func +{ + String value; +public: + Item_func_numgeometries(Item *a): Item_int_func(a) {} + longlong val_int(); + const char *func_name() const { return "numgeometries"; } + void fix_length_and_dec() { max_length=10; } +}; + + +class Item_func_numinteriorring: public Item_int_func +{ + String value; +public: + Item_func_numinteriorring(Item *a): Item_int_func(a) {} + longlong val_int(); + const char *func_name() const { return "numinteriorring"; } + void fix_length_and_dec() { max_length=10; } +}; + + +class Item_func_numpoints: public Item_int_func +{ + String value; +public: + Item_func_numpoints(Item *a): Item_int_func(a) {} + longlong val_int(); + const char *func_name() const { return "numpoints"; } + void fix_length_and_dec() { max_length=10; } +}; + + +class Item_func_area: public Item_real_func +{ + String value; +public: + Item_func_area(Item *a): Item_real_func(a) {} + double val(); + const char *func_name() const { return "area"; } +}; + + +class Item_func_glength: public Item_real_func +{ + String value; +public: + Item_func_glength(Item *a): Item_real_func(a) {} + double val(); + const char *func_name() const { return "glength"; } +}; + + +class Item_func_srid: public Item_int_func +{ + String value; +public: + Item_func_srid(Item *a): Item_int_func(a) {} + longlong val_int(); + const char *func_name() const { return "srid"; } + void fix_length_and_dec() { max_length= 10; } +}; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ae48aeb115a..06569095018 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2522,428 +2522,6 @@ null: return 0; } - -/******************************************************* -General functions for spatial objects -********************************************************/ - -String *Item_func_geometry_from_text::val_str(String *str) -{ - Geometry geom; - String arg_val; - String *wkt= args[0]->val_str(&arg_val); - GTextReadStream trs(wkt->ptr(), wkt->length()); - uint32 srid; - - if ((arg_count == 2) && !args[1]->null_value) - srid= args[1]->val_int(); - else - srid= 0; - - if (str->reserve(SRID_SIZE, 512)) - return 0; - str->length(0); - str->q_append(srid); - if ((null_value=(args[0]->null_value || geom.create_from_wkt(&trs, str, 0)))) - return 0; - return str; -} - - -void Item_func_geometry_from_text::fix_length_and_dec() -{ - max_length=MAX_BLOB_WIDTH; -} - - -String *Item_func_geometry_from_wkb::val_str(String *str) -{ - String arg_val; - String *wkb= args[0]->val_str(&arg_val); - Geometry geom; - uint32 srid; - - if ((arg_count == 2) && !args[1]->null_value) - srid= args[1]->val_int(); - else - srid= 0; - - if (str->reserve(SRID_SIZE, 512)) - return 0; - str->length(0); - str->q_append(srid); - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(wkb->ptr(), wkb->length())))) - return 0; - - str->append(*wkb); - return str; -} - - -void Item_func_geometry_from_wkb::fix_length_and_dec() -{ - max_length=MAX_BLOB_WIDTH; -} - - -String *Item_func_as_text::val_str(String *str) -{ - String arg_val; - String *swkb= args[0]->val_str(&arg_val); - Geometry geom; - - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) - return 0; - - str->length(0); - - if ((null_value= geom.as_wkt(str))) - return 0; - - return str; -} - -void Item_func_as_text::fix_length_and_dec() -{ - max_length=MAX_BLOB_WIDTH; -} - -String *Item_func_as_wkb::val_str(String *str) -{ - String arg_val; - String *swkb= args[0]->val_str(&arg_val); - Geometry geom; - - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) - return 0; - - str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE, - &my_charset_bin); - return str; -} - -void Item_func_as_wkb::fix_length_and_dec() -{ - max_length= MAX_BLOB_WIDTH; -} - -String *Item_func_geometry_type::val_str(String *str) -{ - String *swkb= args[0]->val_str(str); - Geometry geom; - - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) - return 0; - str->copy(geom.get_class_info()->m_name, - strlen(geom.get_class_info()->m_name), - default_charset_info); - return str; -} - - -String *Item_func_envelope::val_str(String *str) -{ - String arg_val; - String *swkb= args[0]->val_str(&arg_val); - Geometry geom; - - if ((null_value= args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))) - return 0; - - uint32 srid= uint4korr(swkb->ptr()); - str->length(0); - if (str->reserve(SRID_SIZE, 512)) - return 0; - str->q_append(srid); - return (null_value= geom.envelope(str)) ? 0 : str; -} - - -String *Item_func_centroid::val_str(String *str) -{ - String arg_val; - String *swkb= args[0]->val_str(&arg_val); - Geometry geom; - - if ((null_value= args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, centroid))) - return 0; - - if (str->reserve(SRID_SIZE, 512)) - return 0; - str->length(0); - uint32 srid= uint4korr(swkb->ptr()); - str->q_append(srid); - - return (null_value= geom.centroid(str)) ? 0 : str; -} - - -/*********************************************** - Spatial decomposition functions -***********************************************/ - -String *Item_func_spatial_decomp::val_str(String *str) -{ - String arg_val; - String *swkb= args[0]->val_str(&arg_val); - Geometry geom; - - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) - return 0; - - null_value= 1; - if (str->reserve(SRID_SIZE, 512)) - return 0; - str->length(0); - uint32 srid= uint4korr(swkb->ptr()); - str->q_append(srid); - switch(decomp_func) - { - case SP_STARTPOINT: - if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str)) - goto ret; - break; - - case SP_ENDPOINT: - if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str)) - goto ret; - break; - - case SP_EXTERIORRING: - if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str)) - goto ret; - break; - - default: - goto ret; - } - null_value= 0; - -ret: - return null_value ? 0 : str; -} - - -String *Item_func_spatial_decomp_n::val_str(String *str) -{ - String arg_val; - String *swkb= args[0]->val_str(&arg_val); - long n= (long) args[1]->val_int(); - Geometry geom; - - if ((null_value= (args[0]->null_value || args[1]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) - return 0; - - null_value= 1; - if (str->reserve(SRID_SIZE, 512)) - return 0; - str->length(0); - uint32 srid= uint4korr(swkb->ptr()); - str->q_append(srid); - switch(decomp_func_n) - { - case SP_POINTN: - if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str)) - goto ret; - break; - - case SP_GEOMETRYN: - if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str)) - goto ret; - break; - - case SP_INTERIORRINGN: - if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) || - geom.interior_ring_n(n,str)) - goto ret; - break; - - default: - goto ret; - } - null_value= 0; - -ret: - return null_value ? 0 : str; -} - - - -/*********************************************** -Functions to concatinate various spatial objects -************************************************/ - - -/* -* Concatinate doubles into Point -*/ - - -String *Item_func_point::val_str(String *str) -{ - double x= args[0]->val(); - double y= args[1]->val(); - - if ( (null_value= (args[0]->null_value || - args[1]->null_value || - str->realloc(1 + 4 + 8 + 8)))) - return 0; - - str->length(0); - str->q_append((char)Geometry::wkbNDR); - str->q_append((uint32)Geometry::wkbPoint); - str->q_append(x); - str->q_append(y); - return str; -} - - -/* - Concatinates various items into various collections - with checkings for valid wkb type of items. - For example, MultiPoint can be a collection of Points only. - coll_type contains wkb type of target collection. - item_type contains a valid wkb type of items. - In the case when coll_type is wkbGeometryCollection, - we do not check wkb type of items, any is valid. -*/ - -String *Item_func_spatial_collection::val_str(String *str) -{ - String arg_value; - uint i; - - null_value= 1; - - str->length(0); - if (str->reserve(1 + 4 + 4, 512)) - return 0; - - str->q_append((char) Geometry::wkbNDR); - str->q_append((uint32) coll_type); - str->q_append((uint32) arg_count); - - for (i= 0; i < arg_count; ++i) - { - String *res= args[i]->val_str(&arg_value); - if (args[i]->null_value) - goto ret; - - if ( coll_type == Geometry::wkbGeometryCollection ) - { - /* - In the case of GeometryCollection we don't need - any checkings for item types, so just copy them - into target collection - */ - if ((null_value= str->reserve(res->length(), 512))) - goto ret; - - str->q_append(res->ptr(), res->length()); - } - else - { - enum Geometry::wkbType wkb_type; - uint32 len=res->length(); - const char *data= res->ptr() + 1; - - /* - In the case of named collection we must to - check that items are of specific type, let's - do this checking now - */ - - if (len < 5) - goto ret; - wkb_type= (Geometry::wkbType) uint4korr(data); - data+= 4; - len-= 5; - if (wkb_type != item_type) - goto ret; - - switch (coll_type) { - case Geometry::wkbMultiPoint: - case Geometry::wkbMultiLineString: - case Geometry::wkbMultiPolygon: - if (len < WKB_HEADER_SIZE) - goto ret; - - data-= WKB_HEADER_SIZE; - len+= WKB_HEADER_SIZE; - if (str->reserve(len, 512)) - goto ret; - str->q_append(data, len); - break; - - case Geometry::wkbLineString: - if (str->reserve(POINT_DATA_SIZE, 512)) - goto ret; - str->q_append(data, POINT_DATA_SIZE); - break; - - case Geometry::wkbPolygon: - { - uint32 n_points; - double x1, y1, x2, y2; - - if (len < 4 + 2 * POINT_DATA_SIZE) - goto ret; - - uint32 llen= len; - const char *ldata= data; - - n_points= uint4korr(data); - data+= 4; - float8get(x1, data); - data+= 8; - float8get(y1, data); - data+= 8; - - data+= (n_points - 2) * POINT_DATA_SIZE; - - float8get(x2, data); - float8get(y2, data + 8); - - if ((x1 != x2) || (y1 != y2)) - goto ret; - - if (str->reserve(llen, 512)) - goto ret; - str->q_append(ldata, llen); - } - break; - - default: - goto ret; - } - } - } - - if (str->length() > current_thd->variables.max_allowed_packet) - goto ret; - - null_value = 0; - -ret: - return null_value ? 0 : str; -} - #ifdef HAVE_COMPRESS #include "../zlib/zlib.h" diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 8ae5c995375..65aad3a3fff 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -628,242 +628,3 @@ public: set_charset(default_charset()); }; }; - - -/******************************************************* -Spatial functions -********************************************************/ - -#define SRID_SIZE sizeof(uint32) - -class Item_func_geometry_from_text :public Item_str_func -{ -public: - Item_func_geometry_from_text(Item *a) :Item_str_func(a) {} - Item_func_geometry_from_text(Item *a, Item *srid) :Item_str_func(a, srid) {} - const char *func_name() const { return "geometryfromtext"; } - String *val_str(String *); - void fix_length_and_dec(); -}; - -class Item_func_geometry_from_wkb: public Item_str_func -{ -public: - Item_func_geometry_from_wkb(Item *a) :Item_str_func(a) {} - Item_func_geometry_from_wkb(Item *a, Item *srid) :Item_str_func(a, srid) {} - const char *func_name() const { return "geometryfromwkb"; } - String *val_str(String *); - void fix_length_and_dec(); -}; - -class Item_func_as_text :public Item_str_func -{ -public: - Item_func_as_text(Item *a) :Item_str_func(a) {} - const char *func_name() const { return "astext"; } - String *val_str(String *); - void fix_length_and_dec(); -}; - -class Item_func_as_wkb :public Item_str_func -{ -public: - Item_func_as_wkb(Item *a) :Item_str_func(a) {} - const char *func_name() const { return "aswkb"; } - String *val_str(String *); - void fix_length_and_dec(); -}; - -class Item_func_geometry_type :public Item_str_func -{ -public: - Item_func_geometry_type(Item *a) :Item_str_func(a) {} - String *val_str(String *); - const char *func_name() const { return "geometrytype"; } - void fix_length_and_dec() - { - max_length=20; // "GeometryCollection" is the most long - }; -}; - -class Item_func_centroid :public Item_str_func -{ -public: - Item_func_centroid(Item *a) :Item_str_func(a) {} - const char *func_name() const { return "centroid"; } - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} -}; - -class Item_func_envelope :public Item_str_func -{ -public: - Item_func_envelope(Item *a) :Item_str_func(a) {} - const char *func_name() const { return "envelope"; } - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} -}; - -class Item_func_point :public Item_str_func -{ -public: - Item_func_point(Item *a, Item *b) :Item_str_func(a, b) {} - Item_func_point(Item *a, Item *b, Item *srid) :Item_str_func(a, b, srid) {} - const char *func_name() const { return "point"; } - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} -}; - -class Item_func_spatial_decomp :public Item_str_func -{ - enum Functype decomp_func; -public: - Item_func_spatial_decomp(Item *a, Item_func::Functype ft) : - Item_str_func(a) { decomp_func = ft; } - const char *func_name() const - { - switch (decomp_func) - { - case SP_STARTPOINT: - return "startpoint"; - case SP_ENDPOINT: - return "endpoint"; - case SP_EXTERIORRING: - return "exteriorring"; - default: - return "spatial_decomp_unknown"; - } - } - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} -}; - -class Item_func_spatial_decomp_n :public Item_str_func -{ - enum Functype decomp_func_n; -public: - Item_func_spatial_decomp_n(Item *a, Item *b, Item_func::Functype ft) : - Item_str_func(a, b) { decomp_func_n = ft; } - const char *func_name() const - { - switch (decomp_func_n) - { - case SP_POINTN: - return "pointn"; - case SP_GEOMETRYN: - return "geometryn"; - case SP_INTERIORRINGN: - return "interiorringn"; - default: - return "spatial_decomp_n_unknown"; - } - } - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} -}; - - -class Item_func_spatial_collection :public Item_str_func -{ - String tmp_value; - enum Geometry::wkbType coll_type; - enum Geometry::wkbType item_type; -public: - Item_func_spatial_collection( - List &list, enum Geometry::wkbType ct, enum Geometry::wkbType it) : - Item_str_func(list) - { - coll_type=ct; - item_type=it; - } - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} - const char *func_name() const { return "multipoint"; } -}; - -#ifdef HAVE_COMPRESS - -class Item_func_compress : public Item_str_func -{ - String buffer; -public: - Item_func_compress(Item *a):Item_str_func(a){} - String *val_str(String *); - void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;} - const char *func_name() const{return "compress";} -}; - -class Item_func_uncompress : public Item_str_func -{ - String buffer; -public: - Item_func_uncompress(Item *a):Item_str_func(a){} - String *val_str(String *); - void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;} - const char *func_name() const{return "uncompress";} -}; - -#endif - -/* -class Item_func_multipoint :public Item_str_func -{ - String tmp_value; -public: - Item_func_multipoint(List &list) :Item_str_func(list) {} - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} - const char *func_name() const { return "multipoint"; } -}; - -class Item_func_linestring :public Item_str_func -{ - String tmp_value; -public: - Item_func_linestring(List &list) :Item_str_func(list) {} - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} - const char *func_name() const { return "linestring"; } -}; - -class Item_func_multilinestring :public Item_str_func -{ - String tmp_value; -public: - Item_func_multilinestring(List &list) :Item_str_func(list) {} - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} - const char *func_name() const { return "multilinestring"; } -}; - -class Item_func_polygon :public Item_str_func -{ - String tmp_value; -public: - Item_func_polygon(List &list) :Item_str_func(list) {} - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} - const char *func_name() const { return "polygon"; } -}; - -class Item_func_multipolygon :public Item_str_func -{ - String tmp_value; -public: - Item_func_multipolygon(List &list) :Item_str_func(list) {} - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} - const char *func_name() const { return "multipolygon"; } -}; - -class Item_func_geometrycollection :public Item_str_func -{ - String tmp_value; -public: - Item_func_geometrycollection(List &list) :Item_str_func(list) {} - String *val_str(String *); - void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;} - const char *func_name() const { return "geometrycollection"; } -}; - -*/ From fadfa46796576b5566ee3f45920b07e2f2326552 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 18:41:19 +0500 Subject: [PATCH 273/399] Fix for compiling MySQL-4.0.13 with SSL support on OpenBSD --- include/my_global.h | 2 +- sql/mysql_priv.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index ca24c21c688..d892d843edc 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -246,7 +246,7 @@ C_MODE_END # endif #endif /* TIME_WITH_SYS_TIME */ #ifdef HAVE_UNISTD_H -#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT) +#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__) #define crypt unistd_crypt #endif #include diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 614cb8cadf6..b191a702efe 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -458,6 +458,7 @@ Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables); Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, bool check_grant,bool allow_rowid); #ifdef HAVE_OPENSSL +#include struct st_des_keyblock { des_cblock key1, key2, key3; From c284a71287c26b2d83f7547bc70d9ea7cee6c48e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 14:08:58 -0400 Subject: [PATCH 274/399] fix some warnings in sql_help.cc sql/sql_help.cc: fix some warnings --- sql/sql_help.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_help.cc b/sql/sql_help.cc index a9b89a728d2..2925141d331 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -557,7 +557,7 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, List_iterator it(*names); String *cur_name; - while (*pos++= it++); + while ((*pos++= it++)); qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); @@ -689,7 +689,7 @@ int mysqld_help(THD *thd, const char *mask) goto end; } - for (int i=0; ifile->init_table_handle_for_HANDLER(); if (!(select_topics_by_name= From 487a64963b2382fdf816770402fb05d0c681aa23 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 23:09:35 +0500 Subject: [PATCH 275/399] mysqlshow and mysqldump now send their vharacter set to server character_set_results is now the same with character_set_client by default --- client/mysqlshow.c | 10 ++++++++-- mysql-test/r/cast.result | 1 + mysql-test/t/cast.test | 1 + sql/mysqld.cc | 4 ++-- sql/protocol.cc | 2 +- sql/set_var.cc | 2 +- sql/sql_parse.cc | 13 ++++++++++--- sql/sql_yacc.yy | 2 +- 8 files changed, 25 insertions(+), 10 deletions(-) diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 9b376872ff8..5bb611b713f 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -30,6 +30,7 @@ static my_string host=0,opt_password=0,user=0; static my_bool opt_show_keys=0,opt_compress=0,opt_status=0, tty_password=0; static uint opt_verbose=0; +static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; #ifdef HAVE_SMEM static char *shared_memory_base_name=0; @@ -115,6 +116,8 @@ int main(int argc, char **argv) if (shared_memory_base_name) mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); #endif + mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); + if (!(mysql_real_connect(&mysql,host,user,opt_password, (first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port, 0))) @@ -155,6 +158,9 @@ static struct my_option my_long_options[] = {"character-sets-dir", 'c', "Directory where character sets are", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"default-character-set", OPT_DEFAULT_CHARSET, + "Set the default character set.", (gptr*) &default_charset, + (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -558,7 +564,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table, mysql_error(mysql)); return 1; } - end=strmov(strmov(query,"show /*!32332 FULL */ columns from "),table); + end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`"); if (wild && wild[0]) strxmov(end," like '",wild,"'",NullS); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) @@ -580,7 +586,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table, print_res_top(result); if (opt_show_keys) { - end=strmov(strmov(query,"show keys from "),table); + end=strmov(strmov(strmov(query,"show keys from `"),table),"`"); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) { fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n", diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 42164a2111b..a14ea4d61a6 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -28,6 +28,7 @@ cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME) select cast("1:2:3" as TIME); cast("1:2:3" as TIME) 01:02:03 +set names binary; select cast(_latin1'test' as char character set latin2); cast(_latin1'test' as char character set latin2) test diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 59b8f3b0c75..8241d491465 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -16,6 +16,7 @@ select cast("1:2:3" as TIME); # # Character set convertion # +set names binary; select cast(_latin1'test' as char character set latin2); select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 224bfe5f878..7011f6dcd36 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2048,7 +2048,7 @@ static int init_common_variables(const char *conf_file_name, int argc, } global_system_variables.character_set_server= default_charset_info; global_system_variables.character_set_database= default_charset_info; - global_system_variables.character_set_results= NULL; + global_system_variables.character_set_results= default_charset_info; global_system_variables.character_set_client= default_charset_info; global_system_variables.collation_connection= default_charset_info; @@ -4689,7 +4689,7 @@ static void mysql_init_variables(void) /* Set default values for some option variables */ global_system_variables.character_set_server= default_charset_info; global_system_variables.character_set_database= default_charset_info; - global_system_variables.character_set_results= NULL; + global_system_variables.character_set_results= default_charset_info; global_system_variables.character_set_client= default_charset_info; global_system_variables.collation_connection= default_charset_info; global_system_variables.table_type= DB_TYPE_MYISAM; diff --git a/sql/protocol.cc b/sql/protocol.cc index 848321c1576..7abbf3ce85b 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -499,7 +499,7 @@ bool Protocol::send_fields(List *list, uint flag) String tmp((char*) buff,sizeof(buff),&my_charset_bin); Protocol_simple prot(thd); String *packet= prot.storage_packet(); - CHARSET_INFO *thd_charset= thd->charset(); + CHARSET_INFO *thd_charset= thd->variables.character_set_results; DBUG_ENTER("send_fields"); if (flag & 1) diff --git a/sql/set_var.cc b/sql/set_var.cc index eb44dd1dbcb..60b0d24430d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1355,7 +1355,7 @@ CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type ty void sys_var_character_set_results::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) - global_system_variables.character_set_results= NULL; + global_system_variables.character_set_results= default_charset_info; else thd->variables.character_set_results= global_system_variables.character_set_results; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b1e0b2dc91d..542b2e0d96e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -669,9 +669,12 @@ check_connections(THD *thd) global_system_variables.character_set_client; thd->variables.collation_connection= global_system_variables.collation_connection; + thd->variables.character_set_results= + global_system_variables.character_set_results; } else { + thd->variables.character_set_results= thd->variables.collation_connection= thd->variables.character_set_client; } @@ -1319,7 +1322,8 @@ restore_user: break; #else { - char *fields; + char *fields, *pend; + String convname; TABLE_LIST table_list; statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status); bzero((char*) &table_list,sizeof(table_list)); @@ -1329,8 +1333,11 @@ restore_user: break; } thd->free_list=0; - table_list.alias= table_list.real_name= thd->strdup(packet); - packet=strend(packet)+1; + pend= strend(packet); + convname.copy(packet, pend-packet, + thd->variables.character_set_client, system_charset_info); + table_list.alias= table_list.real_name= convname.c_ptr(); + packet= pend+1; // command not cachable => no gap for data base name if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3f96826d445..1002d06be88 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4452,7 +4452,7 @@ option_value: net_printf(thd,ER_COLLATION_CHARSET_MISMATCH,$3->name,$2->csname); YYABORT; } - lex->var_list.push_back(new set_var_collation_client($3,$3,NULL)); + lex->var_list.push_back(new set_var_collation_client($3,$3,$3)); } | PASSWORD equal text_or_password { From f7972fb2a27412efda7156a35ac1c51f19684bbb Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 21:09:37 +0300 Subject: [PATCH 276/399] after review changes --- sql/sql_parse.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 542b2e0d96e..9ebb6305f70 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -59,7 +59,7 @@ static void refresh_status(void); static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name); -inline bool single_table_command_access(THD *thd, ulong privilege, +static bool single_table_command_access(THD *thd, ulong privilege, TABLE_LIST *tables, int *res); const char *any_db="*any*"; // Special symbol for check_access @@ -3123,7 +3123,7 @@ error: 1 - access denied */ -inline bool single_table_command_access(THD *thd, ulong privilege, +static bool single_table_command_access(THD *thd, ulong privilege, TABLE_LIST *tables, int *res) { @@ -3135,12 +3135,14 @@ inline bool single_table_command_access(THD *thd, ulong privilege, tables->next= 0; if (grant_option && check_grant(thd, privilege, tables)) return 1; - tables->next= subselects_tables; // check rights on tables of subselect (if exists) - if (subselects_tables && - (*res= check_table_access(thd, SELECT_ACL, subselects_tables))) - return 1; + if (subselects_tables) + { + tables->next= subselects_tables; + if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables))) + return 1; + } return 0; } From d9711e32b966610af3969c76f7e96f18478dffca Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 22:44:37 +0300 Subject: [PATCH 277/399] Many files: Exit all threads created by innoDB at shutdown innobase/os/os0file.c: Exit all threads created by innoDB at shutdown innobase/os/os0sync.c: Exit all threads created by innoDB at shutdown innobase/os/os0thread.c: Exit all threads created by innoDB at shutdown innobase/include/os0file.h: Exit all threads created by innoDB at shutdown innobase/include/os0sync.h: Exit all threads created by innoDB at shutdown innobase/include/os0thread.h: Exit all threads created by innoDB at shutdown innobase/log/log0log.c: Exit all threads created by innoDB at shutdown innobase/srv/srv0srv.c: Exit all threads created by innoDB at shutdown innobase/srv/srv0start.c: Exit all threads created by innoDB at shutdown --- innobase/include/os0file.h | 7 +++++ innobase/include/os0sync.h | 12 +++++++- innobase/include/os0thread.h | 8 ++--- innobase/log/log0log.c | 27 +++++++++-------- innobase/os/os0file.c | 45 +++++++++++++++++++++++++++- innobase/os/os0sync.c | 27 +++++++++++++++-- innobase/os/os0thread.c | 30 +++++++++++++++++-- innobase/srv/srv0srv.c | 13 ++++++++ innobase/srv/srv0start.c | 58 ++++++++++++++++++++++++++++++++++++ 9 files changed, 205 insertions(+), 22 deletions(-) diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index a7624a90d5e..86f27a2d3eb 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -301,6 +301,13 @@ os_aio( are ignored */ void* message2); /**************************************************************************** +Wakes up all async i/o threads so that they know to exit themselves in +shutdown. */ + +void +os_aio_wake_all_threads_at_shutdown(void); +/*=====================================*/ +/**************************************************************************** Waits until there are no pending writes in os_aio_write_array. There can be other, synchronous, pending writes. */ diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h index b2d613c4619..d52444d02ec 100644 --- a/innobase/include/os0sync.h +++ b/innobase/include/os0sync.h @@ -38,6 +38,13 @@ typedef os_mutex_str_t* os_mutex_t; #define OS_SYNC_TIME_EXCEEDED 1 +/* Mutex protecting the thread count */ +extern os_mutex_t os_thread_count_mutex; + +/* This is incremented by 1 in os_thread_create and decremented by 1 in +os_thread_exit */ +extern ulint os_thread_count; + /************************************************************* Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignaled. @@ -85,7 +92,10 @@ os_event_free( /*==========*/ os_event_t event); /* in: event to free */ /************************************************************** -Waits for an event object until it is in the signaled state. */ +Waits for an event object until it is in the signaled state. If +srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the +waiting thread when the event becomes signaled (or immediately if the +event is already in the signaled state). */ void os_event_wait( diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h index 629cfef23a8..29154a9e7cf 100644 --- a/innobase/include/os0thread.h +++ b/innobase/include/os0thread.h @@ -11,6 +11,7 @@ Created 9/8/1995 Heikki Tuuri #define os0thread_h #include "univ.i" +#include "os0sync.h" /* Maximum number of threads which can be created in the program; this is also the size of the wait slot array for MySQL threads which @@ -41,7 +42,6 @@ typedef os_thread_t os_thread_id_t; /* In Unix we use the thread the thread */ #endif - /* Define a function pointer type to use in a typecast */ typedef void* (*os_posix_f_t) (void*); @@ -83,12 +83,13 @@ os_thread_create( os_thread_id_t* thread_id); /* out: id of the created thread */ /********************************************************************* -A thread calling this function ends its execution. */ +Exits the current thread. */ void os_thread_exit( /*===========*/ - ulint code); /* in: exit code */ + void* exit_value); /* in: exit value; in Windows this void* + is cast as a DWORD */ /********************************************************************* Returns the thread identifier of current thread. */ @@ -144,7 +145,6 @@ ulint os_thread_get_last_error(void); /*==========================*/ - #ifndef UNIV_NONINL #include "os0thread.ic" #endif diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index 25cc666e802..e15812e03af 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -375,7 +375,7 @@ log_pad_current_log_block(void) log_close(); log_release(); - ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE) + ut_ad((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE) == LOG_BLOCK_HDR_SIZE); } @@ -998,6 +998,8 @@ log_group_file_header_flush( { byte* buf; ulint dest_offset; + + UT_NOT_USED(type); ut_ad(mutex_own(&(log_sys->mutex))); @@ -1068,8 +1070,8 @@ log_group_write_buf( ulint i; ut_ad(mutex_own(&(log_sys->mutex))); - ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0); - ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); + ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0); + ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); if (new_data_offset == 0) { write_header = TRUE; @@ -2901,10 +2903,9 @@ logs_empty_and_mark_files_at_shutdown(void) dulint lsn; ulint arch_log_no; - if (srv_print_verbose_log) - { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Starting shutdown...\n"); + if (srv_print_verbose_log) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Starting shutdown...\n"); } /* Wait until the master thread and all other operations are idle: our algorithm only works if the server is idle at shutdown */ @@ -3006,15 +3007,17 @@ loop: goto loop; } + /* Make some checks that the server really is quiet */ + ut_a(buf_all_freed()); + ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); + fil_write_flushed_lsn_to_data_files(lsn, arch_log_no); fil_flush_file_spaces(FIL_TABLESPACE); - if (srv_print_verbose_log) - { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Shutdown completed\n"); - } + /* Make some checks that the server really is quiet */ + ut_a(buf_all_freed()); + ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); } /********************************************************** diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index c7f95d79104..640ffec122f 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -1295,7 +1295,6 @@ os_aio_array_create( #endif ut_a(n > 0); ut_a(n_segments > 0); - ut_a(n % n_segments == 0); array = ut_malloc(sizeof(os_aio_array_t)); @@ -1404,6 +1403,50 @@ os_aio_init( pthread_sigmask(SIG_BLOCK, &sigset, NULL); */ #endif } + +#ifdef WIN_ASYNC_IO +/**************************************************************************** +Wakes up all async i/o threads in the array in Windows async i/o at +shutdown. */ +static +void +os_aio_array_wake_win_aio_at_shutdown( +/*==================================*/ + os_aio_array_t* array) /* in: aio array */ +{ + ulint i; + + for (i = 0; i < array->n_slots; i++) { + + os_event_set(*(array->events + i)); + } +} +#endif + +/**************************************************************************** +Wakes up all async i/o threads so that they know to exit themselves in +shutdown. */ + +void +os_aio_wake_all_threads_at_shutdown(void) +/*=====================================*/ +{ + ulint i; + +#ifdef WIN_ASYNC_IO + /* This code wakes up all ai/o threads in Windows native aio */ + os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array); + os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array); + os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array); + os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array); +#endif + /* This loop wakes up all simulated ai/o threads */ + + for (i = 0; i < os_aio_n_segments; i++) { + + os_event_set(os_aio_segment_wait_events[i]); + } +} /**************************************************************************** Waits until there are no pending writes in os_aio_write_array. There can diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 407b280f805..abcfa254710 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -17,6 +17,7 @@ Created 9/6/1995 Heikki Tuuri #endif #include "ut0mem.h" +#include "srv0start.h" /* Type definition for an operating system mutex struct */ struct os_mutex_struct{ @@ -26,9 +27,16 @@ struct os_mutex_struct{ recursively lock the mutex: we do not assume that the OS mutex supports recursive locking, though - NT seems to do that */ + NT seems to do that */ }; +/* Mutex protecting the thread count */ +os_mutex_t os_thread_count_mutex; + +/* This is incremented by 1 in os_thread_create and decremented by 1 in +os_thread_exit */ +ulint os_thread_count = 0; + /************************************************************* Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignaled. @@ -190,7 +198,10 @@ os_event_free( } /************************************************************** -Waits for an event object until it is in the signaled state. */ +Waits for an event object until it is in the signaled state. If +srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the +waiting thread when the event becomes signaled (or immediately if the +event is already in the signaled state). */ void os_event_wait( @@ -206,12 +217,20 @@ os_event_wait( err = WaitForSingleObject(event, INFINITE); ut_a(err == WAIT_OBJECT_0); + + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + os_thread_exit(NULL); + } #else os_fast_mutex_lock(&(event->os_mutex)); loop: if (event->is_set == TRUE) { os_fast_mutex_unlock(&(event->os_mutex)); + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + + os_thread_exit(NULL); + } /* Ok, we may return */ return; @@ -299,6 +318,10 @@ os_event_wait_multiple( ut_a(index >= WAIT_OBJECT_0); ut_a(index < WAIT_OBJECT_0 + n); + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + os_thread_exit(NULL); + } + return(index - WAIT_OBJECT_0); #else ut_a(n == 0); diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c index b0076921e43..a68f6a3b8bc 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -1,6 +1,5 @@ /****************************************************** -The interface to the operating system -process and thread control primitives +The interface to the operating system thread control primitives (c) 1995 Innobase Oy @@ -102,6 +101,10 @@ os_thread_create( os_thread_t thread; ulint win_thread_id; + os_mutex_enter(os_thread_count_mutex); + os_thread_count++; + os_mutex_exit(os_thread_count_mutex); + thread = CreateThread(NULL, /* no security attributes */ 0, /* default size stack */ (LPTHREAD_START_ROUTINE)start_f, @@ -144,6 +147,9 @@ os_thread_create( exit(1); } #endif + os_mutex_enter(os_thread_count_mutex); + os_thread_count++; + os_mutex_exit(os_thread_count_mutex); #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) ret = pthread_create(&pthread, pthread_attr_default, start_f, arg); @@ -170,6 +176,26 @@ os_thread_create( #endif } +/********************************************************************* +Exits the current thread. */ + +void +os_thread_exit( +/*===========*/ + void* exit_value) /* in: exit value; in Windows this void* + is cast as a DWORD */ +{ + os_mutex_enter(os_thread_count_mutex); + os_thread_count--; + os_mutex_exit(os_thread_count_mutex); + +#ifdef __WIN__ + ExitThread((DWORD)exit_value); +#else + pthread_exit(exit_value); +#endif +} + /********************************************************************* Returns handle to the current thread. */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index ef50a4ca261..a44bc0147e4 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1702,6 +1702,8 @@ void srv_general_init(void) /*==================*/ { + os_thread_count_mutex = os_mutex_create(NULL); + sync_init(); mem_init(srv_mem_pool_size); thr_local_init(); @@ -1720,6 +1722,8 @@ srv_general_free(void) /*==================*/ { sync_close(); + + os_mutex_free(os_thread_count_mutex); } #endif /* __NETWARE__ */ @@ -2700,6 +2704,8 @@ loop: srv_error_monitor_active = FALSE; + os_thread_exit(NULL); + #ifndef __WIN__ return(NULL); #else @@ -3139,6 +3145,13 @@ suspend_thread: os_event_wait(event); + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + /* This is only extra safety, the thread should exit + already when the event wait ends */ + + os_thread_exit(NULL); + } + /* When there is user activity, InnoDB will set the event and the main thread goes back to loop: */ diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index d47af68d663..3d98e116905 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1470,6 +1470,8 @@ innobase_shutdown_for_mysql(void) /*=============================*/ /* out: DB_SUCCESS or error code */ { + ulint i; + if (!srv_was_started) { if (srv_is_being_started) { ut_print_timestamp(stderr); @@ -1494,6 +1496,58 @@ innobase_shutdown_for_mysql(void) srv_conc_n_threads); } + /* Now we will exit all threads InnoDB created */ + + srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; + + /* All threads end up waiting for certain events. Put those events + to the signaled state. Then the threads will exit themselves in + os_thread_event_wait(). */ + + for (i = 0; i < 1000; i++) { + /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM + HERE OR EARLIER */ + + /* 1. Let the lock timeout thread exit */ + os_event_set(srv_lock_timeout_thread_event); + + /* 2. srv error monitor thread exits automatically, no need + to do anything here */ + + /* 3. We wake the master thread so that it exits */ + srv_wake_master_thread(); + + /* 4. Exit the i/o threads */ + + os_aio_wake_all_threads_at_shutdown(); + + os_mutex_enter(os_thread_count_mutex); + + if (os_thread_count == 0) { + /* All the threads have exited or are just exiting; + NOTE that the threads may not have completed their + exit yet. Should we use pthread_join() to make sure + they have exited? Now we just sleep 0.1 seconds and + hope that is enough! */ + + os_mutex_exit(os_thread_count_mutex); + + os_thread_sleep(100000); + + break; + } + + os_mutex_exit(os_thread_count_mutex); + + os_thread_sleep(100000); + } + + if (i == 1000) { + fprintf(stderr, +"InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n", + os_thread_count); + } + #if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) /* TODO: Fix this temporary solution @@ -1518,6 +1572,10 @@ innobase_shutdown_for_mysql(void) /* NetWare requires this free */ ut_free_all_mem(); #endif + if (srv_print_verbose_log) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Shutdown completed\n"); + } return((int) DB_SUCCESS); } From 5d1171c024089093d6274dd9d18b480c93516109 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 May 2003 23:00:37 +0300 Subject: [PATCH 278/399] srv0start.c: Cleanup innobase/srv/srv0start.c: Cleanup --- innobase/srv/srv0start.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 3d98e116905..d34c18b1a25 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1549,13 +1549,6 @@ innobase_shutdown_for_mysql(void) } #if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) - /* - TODO: Fix this temporary solution - We are having a race condition occure with io_handler_thread threads. - When they yield in os_aio_simulated_handle during shutdown, this - thread was able to free the memory early. - */ - os_thread_yield(); /* TODO: Where should this be called? */ srv_free(); @@ -1563,11 +1556,7 @@ innobase_shutdown_for_mysql(void) /* TODO: Where should this be called? */ srv_general_free(); #endif - /* - TODO: We should exit the i/o-handler and other utility threads - before freeing all memory. Now this can potentially cause a seg - fault! - */ + #if defined(NOT_WORKING_YET) || defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) /* NetWare requires this free */ ut_free_all_mem(); From 185f0092bc8b8ee558a2bad15308168623e94b42 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 31 May 2003 01:41:11 +0300 Subject: [PATCH 279/399] fixed bug 549 - incorect query cache memory formating on very small query cache sizes mysql-test/r/query_cache.result: test of 2 parts of bug 549 mysql-test/t/query_cache.test: test of 2 parts of bug 549 sql/sql_cache.cc: fixed query cache size showing fixed query cache low memory detection --- mysql-test/r/query_cache.result | 60 +++++++++++++++++++++++++++------ mysql-test/t/query_cache.test | 35 ++++++++++++++----- sql/sql_cache.cc | 16 ++++----- 3 files changed, 83 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a55e05578e0..6abd572b3d9 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -501,22 +501,62 @@ drop table t1; show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 +create table t1 (a int); set GLOBAL query_cache_size=1000; show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 -set GLOBAL query_cache_size=1100; -set GLOBAL query_cache_size=1200; -set GLOBAL query_cache_size=1300; -set GLOBAL query_cache_size=1400; -set GLOBAL query_cache_size=1500; -set GLOBAL query_cache_size=1600; -set GLOBAL query_cache_size=1700; -set GLOBAL query_cache_size=1800; -set GLOBAL query_cache_size=1900; +select * from t1; +a +set GLOBAL query_cache_size=1024; show global variables like "query_cache_size"; Variable_name Value -query_cache_size 1024 +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=10240; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=20480; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=40960; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=51200; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 51200 +select * from t1; +a +set GLOBAL query_cache_size=61440; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 61440 +select * from t1; +a +set GLOBAL query_cache_size=81920; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 81920 +select * from t1; +a +set GLOBAL query_cache_size=102400; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 102400 +select * from t1; +a +drop table t1; set GLOBAL query_cache_size=1048576; create table t1 (i int not null); create table t2 (i int not null); diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 33f226f9253..f0f3063c00d 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -343,18 +343,35 @@ show status like "Qcache_queries_in_cache"; # # Test of query cache resizing # +create table t1 (a int); set GLOBAL query_cache_size=1000; show global variables like "query_cache_size"; -set GLOBAL query_cache_size=1100; -set GLOBAL query_cache_size=1200; -set GLOBAL query_cache_size=1300; -set GLOBAL query_cache_size=1400; -set GLOBAL query_cache_size=1500; -set GLOBAL query_cache_size=1600; -set GLOBAL query_cache_size=1700; -set GLOBAL query_cache_size=1800; -set GLOBAL query_cache_size=1900; +select * from t1; +set GLOBAL query_cache_size=1024; show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=10240; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=20480; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=40960; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=51200; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=61440; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=81920; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=102400; +show global variables like "query_cache_size"; +select * from t1; +drop table t1; # # Temporary tables diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 59430d6a486..1fcd0d1456b 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -731,7 +731,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg) query_cache_size_arg)); free_cache(0); query_cache_size= query_cache_size_arg; - DBUG_RETURN(init_cache()); + DBUG_RETURN(::query_cache_size= init_cache()); } @@ -1282,6 +1282,12 @@ ulong Query_cache::init_cache() mem_bin_steps = 1; mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2; prev_size = 0; + if (mem_bin_size <= min_allocation_unit) + { + DBUG_PRINT("qcache", ("too small query cache => query cache disabled")); + // TODO here (and above) should be warning in 4.1 + goto err; + } while (mem_bin_size > min_allocation_unit) { mem_bin_num += mem_bin_count; @@ -1308,14 +1314,6 @@ ulong Query_cache::init_cache() query_cache_size -= additional_data_size; STRUCT_LOCK(&structure_guard_mutex); - if (max_mem_bin_size <= min_allocation_unit) - { - DBUG_PRINT("qcache", - (" max bin size (%lu) <= min_allocation_unit => cache disabled", - max_mem_bin_size)); - STRUCT_UNLOCK(&structure_guard_mutex); - goto err; - } if (!(cache = (byte *) my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))) From 3cba21f9f5abdaea110f40155467cab2899b5461 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 31 May 2003 03:12:03 +0300 Subject: [PATCH 280/399] Many files: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/os/os0sync.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/os/os0thread.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/include/os0sync.h: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/include/srv0srv.h: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/include/srv0start.h: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/ibuf/ibuf0ibuf.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/srv/srv0srv.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/srv/srv0start.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/sync/sync0sync.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/ut/ut0mem.c: Free all OS sync primitives and allocated memory in InnoDB shutdown --- innobase/include/os0sync.h | 36 +++++++--- innobase/include/srv0srv.h | 6 ++ innobase/include/srv0start.h | 7 +- innobase/os/os0sync.c | 128 ++++++++++++++++++++++++++++++++--- innobase/os/os0thread.c | 12 ++-- innobase/srv/srv0srv.c | 71 ++++--------------- innobase/srv/srv0start.c | 32 ++++----- innobase/sync/sync0sync.c | 27 ++++++-- innobase/ut/ut0mem.c | 2 + 9 files changed, 214 insertions(+), 107 deletions(-) diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h index d52444d02ec..3096c9256ed 100644 --- a/innobase/include/os0sync.h +++ b/innobase/include/os0sync.h @@ -10,15 +10,16 @@ Created 9/6/1995 Heikki Tuuri #define os0sync_h #include "univ.i" +#include "ut0lst.h" #ifdef __WIN__ - #define os_fast_mutex_t CRITICAL_SECTION -typedef void* os_event_t; - +typedef HANDLE os_event_t; #else - typedef pthread_mutex_t os_fast_mutex_t; + +typedef struct os_event_struct os_event_struct_t; +typedef os_event_struct_t* os_event_t; struct os_event_struct { os_fast_mutex_t os_mutex; /* this mutex protects the next fields */ @@ -26,9 +27,9 @@ struct os_event_struct { not reserved */ pthread_cond_t cond_var; /* condition variable is used in waiting for the event */ + UT_LIST_NODE_T(os_event_struct_t) os_event_list; + /* list of all created events */ }; -typedef struct os_event_struct os_event_struct_t; -typedef os_event_struct_t* os_event_t; #endif typedef struct os_mutex_struct os_mutex_str_t; @@ -38,13 +39,30 @@ typedef os_mutex_str_t* os_mutex_t; #define OS_SYNC_TIME_EXCEEDED 1 -/* Mutex protecting the thread count */ -extern os_mutex_t os_thread_count_mutex; +/* Mutex protecting the thread count and event and OS 'slow' mutex lists */ +extern os_mutex_t os_sync_mutex; /* This is incremented by 1 in os_thread_create and decremented by 1 in os_thread_exit */ -extern ulint os_thread_count; +extern ulint os_thread_count; +/* The following are approximate counters for debugging in Unix */ +extern ulint os_event_count; +extern ulint os_mutex_count; + +/************************************************************* +Initializes global event and OS 'slow' mutex lists. */ + +void +os_sync_init(void); +/*==============*/ +/************************************************************* +Frees created events (not in Windows) and OS 'slow' mutexes. OS 'fast' +mutexes must be freed with sync_free() before this. */ + +void +os_sync_free(void); +/*==============*/ /************************************************************* Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignaled. diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 8355496762c..24e692dedab 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -209,6 +209,12 @@ void srv_init(void); /*==========*/ /************************************************************************* +Frees the OS fast mutex created in srv_init(). */ + +void +srv_free(void); +/*==========*/ +/************************************************************************* Initializes the synchronization primitives, memory system, and the thread local storage. */ diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h index aec3ebfeea9..8d2c3fa12c5 100644 --- a/innobase/include/srv0start.h +++ b/innobase/include/srv0start.h @@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase; extern ibool srv_is_being_shut_down; /* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP -and then to SRV_SHUTDOWN_LAST_PHASE */ +and then to SRV_SHUTDOWN_LAST_PHASE, and so on */ extern ulint srv_shutdown_state; -#define SRV_SHUTDOWN_CLEANUP 1 -#define SRV_SHUTDOWN_LAST_PHASE 2 +#define SRV_SHUTDOWN_CLEANUP 1 +#define SRV_SHUTDOWN_LAST_PHASE 2 +#define SRV_SHUTDOWN_EXIT_THREADS 3 #endif diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index abcfa254710..ce9f21ec9a1 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -28,14 +28,74 @@ struct os_mutex_struct{ do not assume that the OS mutex supports recursive locking, though NT seems to do that */ + UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list; + /* list of all 'slow' OS mutexes created */ }; -/* Mutex protecting the thread count */ -os_mutex_t os_thread_count_mutex; +/* Mutex protecting the thread count and the lists of OS mutexes +and events */ +os_mutex_t os_sync_mutex; +ibool os_sync_mutex_inited = FALSE; /* This is incremented by 1 in os_thread_create and decremented by 1 in os_thread_exit */ -ulint os_thread_count = 0; +ulint os_thread_count = 0; + +/* The list of all events created (not in Windows) */ +UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list; + +/* The list of all OS 'slow' mutexes */ +UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list; + +/* The following are approximate counters for debugging in Unix */ +ulint os_event_count = 0; +ulint os_mutex_count = 0; + + +/************************************************************* +Initializes global event and OS 'slow' mutex lists. */ + +void +os_sync_init(void) +/*==============*/ +{ + UT_LIST_INIT(os_event_list); + UT_LIST_INIT(os_mutex_list); + + os_sync_mutex = os_mutex_create(NULL); + + os_sync_mutex_inited = TRUE; +} + +/************************************************************* +Frees created events (not in Windows) and OS 'slow' mutexes. OS 'fast' +mutexes must be freed with sync_free() before this. */ + +void +os_sync_free(void) +/*==============*/ +{ + os_event_t event; + os_mutex_t mutex; + + event = UT_LIST_GET_FIRST(os_event_list); + + while (event) { + + os_event_free(event); + + event = UT_LIST_GET_FIRST(os_event_list); + } + + mutex = UT_LIST_GET_FIRST(os_mutex_list); + + while (mutex) { + + os_mutex_free(mutex); + + mutex = UT_LIST_GET_FIRST(os_mutex_list); + } +} /************************************************************* Creates an event semaphore, i.e., a semaphore which may @@ -51,8 +111,8 @@ os_event_create( the event is created without a name */ { #ifdef __WIN__ - HANDLE event; - + os_event_t event; + event = CreateEvent(NULL, /* No security attributes */ TRUE, /* Manual reset */ FALSE, /* Initial state nonsignaled */ @@ -83,6 +143,14 @@ os_event_create( #endif event->is_set = FALSE; + os_mutex_enter(os_sync_mutex); + + UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); + + os_event_count++; + + os_mutex_exit(os_sync_mutex); + return(event); #endif } @@ -100,7 +168,7 @@ os_event_create_auto( the event is created without a name */ { #ifdef __WIN__ - HANDLE event; + os_event_t event; event = CreateEvent(NULL, /* No security attributes */ FALSE, /* Auto-reset */ @@ -114,6 +182,8 @@ os_event_create_auto( UT_NOT_USED(name); + ut_a(0); + return(NULL); #endif } @@ -193,6 +263,14 @@ os_event_free( os_fast_mutex_free(&(event->os_mutex)); ut_a(0 == pthread_cond_destroy(&(event->cond_var))); + os_mutex_enter(os_sync_mutex); + + UT_LIST_REMOVE(os_event_list, os_event_list, event); + + os_event_count--; + + os_mutex_exit(os_sync_mutex); + ut_free(event); #endif } @@ -310,8 +388,7 @@ os_event_wait_multiple( ut_a(event_array); ut_a(n > 0); - index = WaitForMultipleObjects(n, - event_array, + index = WaitForMultipleObjects(n, event_array, FALSE, /* Wait for any 1 event */ INFINITE); /* Infinite wait time limit */ @@ -360,6 +437,16 @@ os_mutex_create( mutex_str->handle = mutex; mutex_str->count = 0; + if (os_sync_mutex_inited) { + os_mutex_enter(os_sync_mutex); + } + + UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); + + if (os_sync_mutex_inited) { + os_mutex_exit(os_sync_mutex); + } + return(mutex_str); #else os_fast_mutex_t* os_mutex; @@ -376,6 +463,16 @@ os_mutex_create( mutex_str->handle = os_mutex; mutex_str->count = 0; + if (os_sync_mutex_inited) { + os_mutex_enter(os_sync_mutex); + } + + UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); + + if (os_sync_mutex_inited) { + os_mutex_exit(os_sync_mutex); + } + return(mutex_str); #endif } @@ -447,9 +544,22 @@ os_mutex_free( #ifdef __WIN__ ut_a(mutex); + os_mutex_enter(os_sync_mutex); + + UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); + + os_mutex_exit(os_sync_mutex); + ut_a(CloseHandle(mutex->handle)); + ut_free(mutex); #else + os_mutex_enter(os_sync_mutex); + + UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); + + os_mutex_exit(os_sync_mutex); + os_fast_mutex_free(mutex->handle); ut_free(mutex->handle); ut_free(mutex); @@ -474,6 +584,7 @@ os_fast_mutex_init( #else ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); #endif + os_mutex_count++; #endif } @@ -521,5 +632,6 @@ os_fast_mutex_free( DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else ut_a(0 == pthread_mutex_destroy(fast_mutex)); + os_mutex_count--; #endif } diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c index a68f6a3b8bc..1722051a841 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -101,9 +101,9 @@ os_thread_create( os_thread_t thread; ulint win_thread_id; - os_mutex_enter(os_thread_count_mutex); + os_mutex_enter(os_sync_mutex); os_thread_count++; - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); thread = CreateThread(NULL, /* no security attributes */ 0, /* default size stack */ @@ -147,9 +147,9 @@ os_thread_create( exit(1); } #endif - os_mutex_enter(os_thread_count_mutex); + os_mutex_enter(os_sync_mutex); os_thread_count++; - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) ret = pthread_create(&pthread, pthread_attr_default, start_f, arg); @@ -185,9 +185,9 @@ os_thread_exit( void* exit_value) /* in: exit value; in Windows this void* is cast as a DWORD */ { - os_mutex_enter(os_thread_count_mutex); + os_mutex_enter(os_sync_mutex); os_thread_count--; - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); #ifdef __WIN__ ExitThread((DWORD)exit_value); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index a44bc0147e4..da2966a7124 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1693,7 +1693,17 @@ srv_init(void) ut_a(conc_slot->event); } } - + +/************************************************************************* +Frees the OS fast mutex created in srv_init(). */ + +void +srv_free(void) +/*==========*/ +{ + os_fast_mutex_free(&srv_conc_mutex); +} + /************************************************************************* Initializes the synchronization primitives, memory system, and the thread local storage. */ @@ -1702,71 +1712,14 @@ void srv_general_init(void) /*==================*/ { - os_thread_count_mutex = os_mutex_create(NULL); - + os_sync_init(); sync_init(); mem_init(srv_mem_pool_size); thr_local_init(); } - -#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) -/* NetWare requires some cleanup of mutexes */ - -/************************************************************************* -Deinitializes the synchronization primitives, memory system, and the thread -local storage. */ - -void -srv_general_free(void) -/*==================*/ -{ - sync_close(); - - os_mutex_free(os_thread_count_mutex); -} -#endif /* __NETWARE__ */ - - /*======================= InnoDB Server FIFO queue =======================*/ -#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) -/* NetWare requires some cleanup of mutexes */ - -/************************************************************************* -Deinitializes the server. */ - -void -srv_free(void) -/*==========*/ -{ - srv_conc_slot_t* conc_slot; - srv_slot_t* slot; - ulint i; - - for (i = 0; i < OS_THREAD_MAX_N; i++) - { - slot = srv_table_get_nth_slot(i); - os_event_free(slot->event); - } - - /* TODO: free(srv_sys->threads); */ - - for (i = 0; i < OS_THREAD_MAX_N; i++) - { - slot = srv_mysql_table + i; - os_event_free(slot->event); - } - - /* TODO: free(srv_mysql_table); */ - - for (i = 0; i < OS_THREAD_MAX_N; i++) - { - conc_slot = srv_conc_slots + i; - os_event_free(conc_slot->event); - } -} -#endif /* __NETWARE__ */ /************************************************************************* Puts an OS thread to wait if there are too many concurrent threads diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index d34c18b1a25..f03355b825c 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1442,9 +1442,7 @@ innobase_start_or_create_for_mysql(void) os_fast_mutex_unlock(&srv_os_test_mutex); -#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) - os_fast_mutex_free(&srv_os_test_mutex); /* all platforms? */ -#endif /* __NETWARE__ */ + os_fast_mutex_free(&srv_os_test_mutex); if (srv_print_verbose_log) { ut_print_timestamp(stderr); @@ -1484,7 +1482,7 @@ innobase_shutdown_for_mysql(void) return(DB_SUCCESS); } - /* Flush buffer pool to disk, write the current lsn to + /* 1. Flush buffer pool to disk, write the current lsn to the tablespace header(s), and copy all log data to archive */ logs_empty_and_mark_files_at_shutdown(); @@ -1496,7 +1494,7 @@ innobase_shutdown_for_mysql(void) srv_conc_n_threads); } - /* Now we will exit all threads InnoDB created */ + /* 2. Make all threads created by InnoDB to exit */ srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; @@ -1521,7 +1519,7 @@ innobase_shutdown_for_mysql(void) os_aio_wake_all_threads_at_shutdown(); - os_mutex_enter(os_thread_count_mutex); + os_mutex_enter(os_sync_mutex); if (os_thread_count == 0) { /* All the threads have exited or are just exiting; @@ -1530,14 +1528,14 @@ innobase_shutdown_for_mysql(void) they have exited? Now we just sleep 0.1 seconds and hope that is enough! */ - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); os_thread_sleep(100000); break; } - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); os_thread_sleep(100000); } @@ -1548,19 +1546,21 @@ innobase_shutdown_for_mysql(void) os_thread_count); } -#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) + /* 3. Free all InnoDB's own mutexes */ + + sync_close(); + + /* 4. Free all OS synchronization primitives (in Windows currently + events are not freed) */ - /* TODO: Where should this be called? */ srv_free(); + os_sync_free(); - /* TODO: Where should this be called? */ - srv_general_free(); -#endif + /* 5. Free all allocated memory (and the os_fast_mutex created in + ut0mem.c */ -#if defined(NOT_WORKING_YET) || defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) - /* NetWare requires this free */ ut_free_all_mem(); -#endif + if (srv_print_verbose_log) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Shutdown completed\n"); diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index 20d68ba5a9f..32615ce88ac 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -235,8 +235,7 @@ mutex_create_func( mutex->cline = cline; /* Check that lock_word is aligned; this is important on Intel */ - - ut_a(((ulint)(&(mutex->lock_word))) % 4 == 0); + ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0); /* NOTE! The very first mutexes are not put to the mutex list */ @@ -266,11 +265,14 @@ mutex_free( ut_a(mutex_get_lock_word(mutex) == 0); ut_a(mutex_get_waiters(mutex) == 0); - mutex_enter(&mutex_list_mutex); + if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) { - UT_LIST_REMOVE(list, mutex_list, mutex); + mutex_enter(&mutex_list_mutex); - mutex_exit(&mutex_list_mutex); + UT_LIST_REMOVE(list, mutex_list, mutex); + + mutex_exit(&mutex_list_mutex); + } #if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) os_fast_mutex_free(&(mutex->os_fast_mutex)); @@ -1230,13 +1232,26 @@ sync_init(void) } /********************************************************************** -Frees the resources in synchronization data structures. */ +Frees the resources in InnoDB's own synchronization data structures. Use +os_sync_free() after calling this. */ void sync_close(void) /*===========*/ { + mutex_t* mutex; + sync_array_free(sync_primary_wait_array); + + mutex = UT_LIST_GET_FIRST(mutex_list); + + while (mutex) { + mutex_free(mutex); + mutex = UT_LIST_GET_FIRST(mutex_list); + } + + mutex_free(&mutex_list_mutex); + mutex_free(&sync_thread_mutex); } /*********************************************************************** diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index dbd3e7e4737..174ae4cc6bb 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -190,6 +190,8 @@ ut_free_all_mem(void) os_fast_mutex_unlock(&ut_list_mutex); ut_a(ut_total_allocated_memory == 0); + + os_fast_mutex_free(&ut_list_mutex); } /************************************************************************** From c01bcf473e3cf215e41a77da6acde0f284ab60a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 31 May 2003 03:23:42 +0300 Subject: [PATCH 281/399] os0thread.c, os0thread.h, os0sync.h: Cleanup os0sync.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/os/os0sync.c: Free all OS sync primitives and allocated memory in InnoDB shutdown innobase/include/os0sync.h: Cleanup innobase/include/os0thread.h: Cleanup innobase/os/os0thread.c: Cleanup --- innobase/include/os0sync.h | 3 +-- innobase/include/os0thread.h | 1 - innobase/os/os0sync.c | 3 +-- innobase/os/os0thread.c | 1 + 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h index 3096c9256ed..bad8e6e120a 100644 --- a/innobase/include/os0sync.h +++ b/innobase/include/os0sync.h @@ -57,8 +57,7 @@ void os_sync_init(void); /*==============*/ /************************************************************* -Frees created events (not in Windows) and OS 'slow' mutexes. OS 'fast' -mutexes must be freed with sync_free() before this. */ +Frees created events (not in Windows) and OS 'slow' mutexes. */ void os_sync_free(void); diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h index 29154a9e7cf..92187f315c2 100644 --- a/innobase/include/os0thread.h +++ b/innobase/include/os0thread.h @@ -11,7 +11,6 @@ Created 9/8/1995 Heikki Tuuri #define os0thread_h #include "univ.i" -#include "os0sync.h" /* Maximum number of threads which can be created in the program; this is also the size of the wait slot array for MySQL threads which diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index ce9f21ec9a1..4f322ee82b2 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -68,8 +68,7 @@ os_sync_init(void) } /************************************************************* -Frees created events (not in Windows) and OS 'slow' mutexes. OS 'fast' -mutexes must be freed with sync_free() before this. */ +Frees created events (not in Windows) and OS 'slow' mutexes. */ void os_sync_free(void) diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c index 1722051a841..02ea2c227a7 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -16,6 +16,7 @@ Created 9/8/1995 Heikki Tuuri #endif #include "srv0srv.h" +#include "os0sync.h" /******************************************************************* Compares two thread ids for equality. */ From e0c9de6e62a199ec48ac1c910de4bcad28425c76 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 31 May 2003 15:44:19 +0600 Subject: [PATCH 282/399] URGENT SCRUM BUG correct wrong code in group_concat mysql-test/r/func_gconcat.result: add new tests mysql-test/t/func_gconcat.test: add new tests sql/field.cc: add new variable for group_concat sql/field.h: add new variable for group_concat sql/item_sum.cc: correct wrong code sql/item_sum.h: correct wrong code --- mysql-test/r/func_gconcat.result | 20 ++++++- mysql-test/t/func_gconcat.test | 16 +++++- sql/field.cc | 2 +- sql/field.h | 1 + sql/item_sum.cc | 97 ++++++++++++++++++-------------- sql/item_sum.h | 29 +++++++--- 6 files changed, 111 insertions(+), 54 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 0dc84f090f1..f2246f2e514 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -154,8 +154,26 @@ Warning 1258 1 line(s) was(were) cut by group_concat() show warnings; Level Code Message Warning 1258 1 line(s) was(were) cut by group_concat() +set group_concat_max_len = 1024; +drop table if exists T_URL; +Warnings: +Note 1051 Unknown table 'T_URL' +create table T_URL ( URL_ID int(11), URL varchar(80)); +drop table if exists T_REQUEST; +Warnings: +Note 1051 Unknown table 'T_REQUEST' +create table T_REQUEST ( REQ_ID int(11), URL_ID int(11)); +insert into T_URL values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com'); +insert into T_REQUEST values (1,4), (5,4), (5,5); +select REQ_ID, Group_Concat(URL) as URL from T_URL, T_REQUEST where +T_REQUEST.URL_ID = T_URL.URL_ID group by REQ_ID; +REQ_ID URL +1 www.host.com +5 www.host.com,www.google.com,www.help.com +drop table T_URL; +drop table T_REQUEST; select group_concat(sum(a)) from t1 group by grp; Invalid use of group function select grp,group_concat(c order by 2) from t1 group by grp; Unknown column '2' in 'group statement' -drop table if exists t1; +drop table t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 0a95410e842..a5a7abe3b01 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -68,6 +68,20 @@ select grp,group_concat(c order by c) from t1 group by grp; set group_concat_max_len = 5; select grp,group_concat(c) from t1 group by grp; show warnings; +set group_concat_max_len = 1024; + +# Test variable length + +drop table if exists T_URL; +create table T_URL ( URL_ID int(11), URL varchar(80)); +drop table if exists T_REQUEST; +create table T_REQUEST ( REQ_ID int(11), URL_ID int(11)); +insert into T_URL values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com'); +insert into T_REQUEST values (1,4), (5,4), (5,5); +select REQ_ID, Group_Concat(URL) as URL from T_URL, T_REQUEST where +T_REQUEST.URL_ID = T_URL.URL_ID group by REQ_ID; +drop table T_URL; +drop table T_REQUEST; # Test errors @@ -76,4 +90,4 @@ select group_concat(sum(a)) from t1 group by grp; --error 1054 select grp,group_concat(c order by 2) from t1 group by grp; -drop table if exists t1; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 3695268a888..e54986ded22 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -175,7 +175,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, field_name(field_name_arg), query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0), unireg_check(unireg_check_arg), - field_length(length_arg),null_bit(null_bit_arg) + field_length(length_arg),null_bit(null_bit_arg),abs_offset(0) { flags=null_ptr ? 0: NOT_NULL_FLAG; comment.str= (char*) ""; diff --git a/sql/field.h b/sql/field.h index 80bfc516ef7..088dae49c6f 100644 --- a/sql/field.h +++ b/sql/field.h @@ -62,6 +62,7 @@ public: uint32 field_length; // Length of field uint16 flags; uchar null_bit; // Bit used to test null bit + uint abs_offset; // use only in group_concat Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 11c850f9d5f..8bd3e36b5db 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1344,27 +1344,28 @@ String *Item_sum_udf_str::val_str(String *str) GROUP_CONCAT(DISTINCT expr,...) */ -static int group_concat_key_cmp_with_distinct(void* arg, byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct(void* arg, byte* key1, + byte* key2) { Item_func_group_concat* item= (Item_func_group_concat*)arg; + for (uint i= 0; i < item->arg_count_field; i++) { - Item *field_item= item->expr[i]; + Item *field_item= item->args[i]; Field *field= field_item->tmp_table_field(); if (field) { - uint offset= field->offset(); + uint offset= field->abs_offset; int res= field->key_cmp(key1 + offset, key2 + offset); /* if key1 and key2 is not equal than field->key_cmp return offset. This - function must return value 1 for this case. + function must return value 1 for this case. */ if (res) return 1; } - } + } return 0; } @@ -1374,9 +1375,10 @@ static int group_concat_key_cmp_with_distinct(void* arg, byte* key1, GROUP_CONCAT(expr,... ORDER BY col,... ) */ -static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) +int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) { Item_func_group_concat* item= (Item_func_group_concat*)arg; + for (uint i=0; i < item->arg_count_order; i++) { ORDER *order_item= item->order[i]; @@ -1384,14 +1386,14 @@ static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) Field *field= item->tmp_table_field(); if (field) { - uint offset= field->offset(); + uint offset= field->abs_offset; bool dir= order_item->asc; int res= field->key_cmp(key1 + offset, key2 + offset); if (res) return dir ? res : -res; } - } + } /* We can't return 0 because tree class remove this item as double value. */ @@ -1404,9 +1406,8 @@ static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... ) */ -static int group_concat_key_cmp_with_distinct_and_order(void* arg, - byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1, + byte* key2) { if (!group_concat_key_cmp_with_distinct(arg,key1,key2)) return 0; @@ -1419,24 +1420,23 @@ static int group_concat_key_cmp_with_distinct_and_order(void* arg, item is pointer to Item_func_group_concat */ -static int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), +int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), Item_func_group_concat *group_concat_item) { char buff[MAX_FIELD_WIDTH]; String tmp((char *)&buff,sizeof(buff),default_charset_info); String tmp2((char *)&buff,sizeof(buff),default_charset_info); - + tmp.length(0); for (uint i= 0; i < group_concat_item->arg_show_fields; i++) { - Item *show_item= group_concat_item->expr[i]; + Item *show_item= group_concat_item->args[i]; if (!show_item->const_item()) { Field *f= show_item->tmp_table_field(); - uint offset= f->offset(); char *sv= f->ptr; - f->ptr= (char *)key + offset; + f->ptr= (char *)key + f->abs_offset; String *res= f->val_str(&tmp,&tmp2); group_concat_item->result.append(*res); f->ptr= sv; @@ -1486,9 +1486,14 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, List *is_select, SQL_LIST *is_order, String *is_separator) - :Item_sum(), tmp_table_param(0), warning_available(false), - separator(is_separator), tree(&tree_base), table(0), - count_cut_values(0), tree_mode(0), distinct(is_distinct) + :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0), + warning_available(0), key_length(0), rec_offset(0), + tree_mode(0), distinct(is_distinct), warning_for_row(0), + separator(is_separator), tree(&tree_base), table(0), + order(0), tables_list(0), group_concat_max_len(0), + show_elements(0), arg_count_order(0), arg_count_field(0), + arg_show_fields(0), count_cut_values(0) + { original= 0; quick_group= 0; @@ -1504,16 +1509,12 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, We need to allocate: args - arg_count+arg_count_order (for possible order items in temporare tables) - expr - arg_count_field order - arg_count_order */ - args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order+ - arg_count_field)+ + args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order)+ sizeof(ORDER*)*arg_count_order); if (!args) - return; // thd->fatal is set - expr= args; - expr+= arg_count+arg_count_order; + return; /* fill args items of show and sort */ int i= 0; @@ -1521,12 +1522,12 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, Item *item_select; for ( ; (item_select= li++) ; i++) - args[i]= expr[i]= item_select; + args[i]= item_select; if (arg_count_order) { i= 0; - order= (ORDER**)(expr + arg_count_field); + order= (ORDER**)(args + arg_count + arg_count_order); for (ORDER *order_item= (ORDER*) is_order->first; order_item != NULL; order_item= order_item->next) @@ -1587,7 +1588,7 @@ bool Item_func_group_concat::add() bool record_is_null= TRUE; for (uint i= 0; i < arg_show_fields; i++) { - Item *show_item= expr[i]; + Item *show_item= args[i]; if (!show_item->const_item()) { Field *f= show_item->tmp_table_field(); @@ -1603,13 +1604,13 @@ bool Item_func_group_concat::add() null_value= FALSE; if (tree_mode) { - if (!tree_insert(tree, table->record[0], 0,tree->custom_arg)) + if (!tree_insert(tree, table->record[0] + rec_offset, 0, tree->custom_arg)) return 1; } else { if (result.length() <= group_concat_max_len && !warning_for_row) - dump_leaf_key(table->record[0],1, + dump_leaf_key(table->record[0] + rec_offset, 1, (Item_func_group_concat*)this); } return 0; @@ -1642,12 +1643,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 1; maybe_null |= args[i]->maybe_null; } - for (i= 0 ; i < arg_count_field ; i++) - { - if (expr[i]->fix_fields(thd, tables, expr + i) || expr[i]->check_cols(1)) - return 1; - maybe_null |= expr[i]->maybe_null; - } /* Fix fields for order clause in function: GROUP_CONCAT(expr,... ORDER BY col,... ) @@ -1712,12 +1707,25 @@ bool Item_func_group_concat::setup(THD *thd) return 1; table->file->extra(HA_EXTRA_NO_ROWS); table->no_rows= 1; - qsort_cmp2 compare_key; - - tree_mode= distinct || arg_count_order; + + + Field** field, **field_end; + field_end = (field = table->field) + table->fields; + uint offset = 0; + for (key_length = 0; field < field_end; ++field) + { + uint32 length= (*field)->pack_length(); + (*field)->abs_offset= offset; + offset+= length; + key_length += length; + } + rec_offset = table->reclength - key_length; + /* choise function of sort */ + tree_mode= distinct || arg_count_order; + qsort_cmp2 compare_key; if (tree_mode) { if (arg_count_order) @@ -1741,9 +1749,9 @@ bool Item_func_group_concat::setup(THD *thd) */ init_tree(tree, min(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, - table->reclength, compare_key, 0, NULL, (void*) this); - max_elements_in_tree= ((table->reclength) ? - thd->variables.max_heap_table_size/table->reclength : 1); + key_length, compare_key, 0, NULL, (void*) this); + max_elements_in_tree= ((key_length) ? + thd->variables.max_heap_table_size/key_length : 1); }; item_thd= thd; @@ -1784,3 +1792,6 @@ String* Item_func_group_concat::val_str(String* str) } return &result; } + + + diff --git a/sql/item_sum.h b/sql/item_sum.h index 37d7e7f79d0..e306a42c6bc 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -640,13 +640,28 @@ class Item_func_group_concat : public Item_sum uint max_elements_in_tree; MYSQL_ERROR *warning; bool warning_available; + uint key_length; + int rec_offset; + bool tree_mode; + bool distinct; + bool warning_for_row; + bool always_null; + + friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1, + byte* key2); + friend int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2); + friend int group_concat_key_cmp_with_distinct_and_order(void* arg, + byte* key1, + byte* key2); + friend int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), + Item_func_group_concat *group_concat_item); + public: String result; String *separator; TREE tree_base; TREE *tree; TABLE *table; - Item **expr; ORDER **order; TABLE_LIST *tables_list; ulong group_concat_max_len; @@ -655,9 +670,6 @@ class Item_func_group_concat : public Item_sum uint arg_count_field; uint arg_show_fields; uint count_cut_values; - bool tree_mode, distinct; - bool warning_for_row; - bool always_null; /* Following is 0 normal object and pointer to original one for copy (to correctly free resources) @@ -673,10 +685,14 @@ class Item_func_group_concat : public Item_sum max_elements_in_tree(item.max_elements_in_tree), warning(item.warning), warning_available(item.warning_available), + key_length(item.key_length), + rec_offset(item.rec_offset), + tree_mode(0), + distinct(item.distinct), + warning_for_row(item.warning_for_row), separator(item.separator), tree(item.tree), table(item.table), - expr(item.expr), order(item.order), tables_list(item.tables_list), group_concat_max_len(item.group_concat_max_len), @@ -685,9 +701,6 @@ class Item_func_group_concat : public Item_sum arg_count_field(item.arg_count_field), arg_show_fields(item.arg_show_fields), count_cut_values(item.count_cut_values), - tree_mode(0), - distinct(item.distinct), - warning_for_row(item.warning_for_row), original(&item) { quick_group = 0; From 62c7d2cd2711d3ab2b7d0adba2947b38168cc4b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 31 May 2003 15:15:46 +0500 Subject: [PATCH 283/399] SCRUM: Here is another pack of changes about gathering common client code in sql-common/client.c. Now i symlink the client.c from sql/ and libmysql/. These directories have client_settings.h files to be included to client.c. It contains defines and declarations to compile client.c in appropriate manner. Also i've added include/sql_common.h, containing declarations of what is exported from client.c I removed as many #ifdef-s from client.c as i dared to. I think it's better push it with some extra #ifdef-s now (of course, if everythihg besides it is ok) so other people can check the code. Makefile.am: symlinking of sql-common/client.c was added include/mysql.h: MYSQL_CLIENT define moved here from libmysql/Makefile libmysql/Makefile.am: ../libmysql/client_settings.h added to the list of necessary h-files libmysql/Makefile.shared: client.lo added to the list of objects libmysql/libmysql.c: a lot of changes about separating code between libmysql.c and client.c mysys/default.c: changed to keep compiler happy sql-common/client.c: a lot of changes about code separating sql/Makefile.am: mini_client.h has to be removed sql/repl_failsafe.cc: mysql_real_connect prototype was unified, so we've got to set connection timeout separately sql/slave.cc: trimming code to the changed function's prototypes sql/sql_repl.cc: mini_client isn't needed anymore --- Makefile.am | 5 +- include/mysql.h | 4 + include/sql_common.h | 53 ++++ libmysql/Makefile.am | 5 +- libmysql/Makefile.shared | 2 +- libmysql/client_settings.h | 61 ++++ libmysql/libmysql.c | 219 ++++++++------ mysys/default.c | 2 +- sql-common/client.c | 582 +++++++++++++++++++++---------------- sql/Makefile.am | 8 +- sql/client_settings.h | 33 +++ sql/repl_failsafe.cc | 5 +- sql/slave.cc | 9 +- sql/sql_repl.cc | 1 - 14 files changed, 623 insertions(+), 366 deletions(-) create mode 100644 include/sql_common.h create mode 100644 libmysql/client_settings.h create mode 100644 sql/client_settings.h diff --git a/Makefile.am b/Makefile.am index 26c26357400..1fcf498a84b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,7 +70,10 @@ linked_netware_sources: #avoid recursive make calls in sql directory linked_server_sources: - cd sql; rm -f mini_client_errors.c;@LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c; rm -f pack.c;@LN_CP_F@ ../sql-common/pack.c pack.c + cd sql; rm -f mini_client_errors.c;\ + @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c;\ + rm -f pack.c;@LN_CP_F@ ../sql-common/pack.c pack.c;\ + rm -f client.c;@LN_CP_F@ ../sql-common/client.c client.c echo timestamp > linked_server_sources # Create permission databases diff --git a/include/mysql.h b/include/mysql.h index 94f2152655d..91e4c6444ee 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -296,6 +296,10 @@ typedef struct st_mysql_res { #define MANAGER_CLIENT_ERR 450 #define MANAGER_INTERNAL_ERR 500 +#ifndef MYSQL_SERVER +#define MYSQL_CLIENT +#endif + typedef struct st_mysql_manager diff --git a/include/sql_common.h b/include/sql_common.h new file mode 100644 index 00000000000..aa4386a5623 --- /dev/null +++ b/include/sql_common.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifndef _sql_common_h +#define _sql_common_h + +extern const char *unknown_sqlstate; + +#ifdef __cplusplus +extern "C" { +#endif + +ulong STDCALL net_field_length(uchar **packet); +my_ulonglong net_field_length_ll(uchar **packet); + +MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, + my_bool default_value, uint server_capabilities); +my_bool advanced_command(MYSQL *mysql, enum enum_server_command command, + const char *header, ulong header_length, + const char *arg, ulong arg_length, my_bool skip_check); +void free_rows(MYSQL_DATA *cur); +MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields, + uint field_count); +my_bool mysql_autenticate(MYSQL *mysql, const char *passwd); +void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count); +void free_old_query(MYSQL *mysql); +void end_server(MYSQL *mysql); +my_bool mysql_reconnect(MYSQL *mysql); +#ifdef __cplusplus +} +#endif + +#ifdef MYSQL_SERVER +#define protocol_41(A) FALSE +#else +#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) +#endif + +#endif /* _sql_common_h */ diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 2e0a18d4677..128f1c03967 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -18,7 +18,7 @@ # This file is public domain and comes with NO WARRANTY of any kind target = libmysqlclient.la -target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -DMYSQL_CLIENT +target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ LIBS = @CLIENT_LIBS@ INCLUDES = -I$(top_srcdir)/include $(openssl_includes) @@ -79,7 +79,8 @@ nh = my_global.h config-win32.h dbug.h errmsg.h \ m_ctype.h m_string.h \ my_alarm.h my_config.h my_dir.h my_list.h my_net.h my_sys.h \ mysql.h mysql_com.h mysql_version.h mysqld_error.h \ - mysys_err.h my_pthread.h thr_alarm.h violite.h hash.h + mysys_err.h my_pthread.h thr_alarm.h violite.h hash.h \ + sql_common.h ../libmysql/client_settings.h # Get a list of the needed objects lobjs = $(mysysobjects1) $(dbugobjects) $(mystringsobjects) $(sqlobjects) diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 417b45c150d..9a5869c47ff 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -63,7 +63,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ my_pread.lo mf_cache.lo md5.lo sha1.lo\ my_getopt.lo my_gethostbyname.lo my_port.lo sqlobjects = net.lo -sql_cmn_objects = pack.lo +sql_cmn_objects = pack.lo client.lo # Not needed in the minimum library mysysobjects2 = my_lib.lo diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h new file mode 100644 index 00000000000..253f1515075 --- /dev/null +++ b/libmysql/client_settings.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifndef _client_settings_h +#define _client_settings_h +static my_bool mysql_client_init=0; +extern uint mysql_port; +extern my_string mysql_unix_port; + +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ + | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \ + | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) + + +#ifdef __WIN__ +#define CONNECT_TIMEOUT 20 +#else +#define CONNECT_TIMEOUT 0 +#endif + +#ifdef HAVE_SMEM +char *shared_memory_base_name=0; +const char *def_shared_memory_base_name=default_shared_memory_base_name; +#endif + +static my_bool org_my_init_done=0; + +sig_handler pipe_sig_handler(int sig __attribute__((unused))); +my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); +void read_user_name(char *name); +my_bool send_file_to_server(MYSQL *mysql, const char *filename); + +/* + Let the user specify that we don't want SIGPIPE; This doesn't however work + with threaded applications as we can have multiple read in progress. +*/ + +#if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD) +#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0; +#define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler) +#define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler); +#else +#define init_sigpipe_variables +#define set_sigpipe(mysql) +#define reset_sigpipe(mysql) +#endif +#endif /* _client_settings_h */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 70f970d7442..766c62a03eb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -57,14 +57,14 @@ #define INADDR_NONE -1 #endif -static my_bool mysql_client_init=0; +#include + uint mysql_port=0; my_string mysql_unix_port=0; ulong net_buffer_length=8192; ulong max_allowed_packet= 1024L*1024L*1024L; ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT; -const char *unknown_sqlstate= "000000"; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \ @@ -99,28 +99,16 @@ TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", be changed */ #define MAX_LONG_DATA_LENGTH 8192 -#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) +/*#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41)*/ #define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG) -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, - ulong *lengths); -static void end_server(MYSQL *mysql); -static void read_user_name(char *name); static void append_wild(char *to,char *end,const char *wild); -static my_bool mysql_reconnect(MYSQL *mysql); -static my_bool send_file_to_server(MYSQL *mysql,const char *filename); -static sig_handler pipe_sig_handler(int sig); +sig_handler pipe_sig_handler(int sig); static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); -static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); -static void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count); +my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); static my_bool org_my_init_done=0; -extern ulong STDCALL net_field_length(uchar **packet); -extern my_ulonglong net_field_length_ll(uchar **packet); - int STDCALL mysql_server_init(int argc __attribute__((unused)), char **argv __attribute__((unused)), char **groups __attribute__((unused))) @@ -169,9 +157,10 @@ void STDCALL mysql_thread_end() #define reset_sigpipe(mysql) #endif +/* TO DELETE #define _libmysql_c #include "../sql-common/client.c" - +*/ static MYSQL* spawn_init(MYSQL* parent, const char* host, unsigned int port, const char* user, @@ -448,7 +437,7 @@ mysql_debug(const char *debug __attribute__((unused))) ARGSUSED **************************************************************************/ -static sig_handler +sig_handler pipe_sig_handler(int sig __attribute__((unused))) { DBUG_PRINT("info",("Hit by signal %d",sig)); @@ -869,6 +858,124 @@ error: DBUG_RETURN(1); } +#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL) +struct passwd *getpwuid(uid_t); +char* getlogin(void); +#endif + +#if defined(__NETWARE__) +/* default to "root" on NetWare */ +void read_user_name(char *name) +{ + char *str=getenv("USER"); + strmake(name, str ? str : "UNKNOWN_USER", USERNAME_LENGTH); +} + +#elif !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__) && !defined(OS2) + +void read_user_name(char *name) +{ + DBUG_ENTER("read_user_name"); + if (geteuid() == 0) + (void) strmov(name,"root"); /* allow use of surun */ + else + { +#ifdef HAVE_GETPWUID + struct passwd *skr; + const char *str; + if ((str=getlogin()) == NULL) + { + if ((skr=getpwuid(geteuid())) != NULL) + str=skr->pw_name; + else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) && + !(str=getenv("LOGIN"))) + str="UNKNOWN_USER"; + } + (void) strmake(name,str,USERNAME_LENGTH); +#elif HAVE_CUSERID + (void) cuserid(name); +#else + strmov(name,"UNKNOWN_USER"); +#endif + } + DBUG_VOID_RETURN; +} + +#else /* If MSDOS || VMS */ + +void read_user_name(char *name) +{ + char *str=getenv("USER"); /* ODBC will send user variable */ + strmake(name,str ? str : "ODBC", USERNAME_LENGTH); +} + +#endif + +my_bool send_file_to_server(MYSQL *mysql, const char *filename) +{ + int fd, readcount; + my_bool result= 1; + uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); + char *buf, tmp_name[FN_REFLEN]; + NET *net= &mysql->net; + DBUG_ENTER("send_file_to_server"); + + if (!(buf=my_malloc(packet_length,MYF(0)))) + { + strmov(net->sqlstate, unknown_sqlstate); + strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); + DBUG_RETURN(1); + } + + fn_format(tmp_name,filename,"","",4); /* Convert to client format */ + if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) + { + my_net_write(net,"",0); /* Server needs one packet */ + net_flush(net); + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=EE_FILENOTFOUND; + my_snprintf(net->last_error,sizeof(net->last_error)-1, + EE(net->last_errno),tmp_name, errno); + goto err; + } + + while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) + { + if (my_net_write(net,buf,readcount)) + { + DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); + goto err; + } + } + /* Send empty packet to mark end of file */ + if (my_net_write(net,"",0) || net_flush(net)) + { + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=CR_SERVER_LOST; + sprintf(net->last_error,ER(net->last_errno),errno); + goto err; + } + if (readcount < 0) + { + strmov(net->sqlstate, unknown_sqlstate); + net->last_errno=EE_READ; /* the errmsg for not entire file read */ + my_snprintf(net->last_error,sizeof(net->last_error)-1, + tmp_name,errno); + goto err; + } + result=0; /* Ok */ + +err: + if (fd >= 0) + (void) my_close(fd,MYF(0)); + my_free(buf,MYF(0)); + DBUG_RETURN(result); +} + + /************************************************************************** Do a query. If query returned rows, free old rows. Read data by mysql_store_result or by repeat call of mysql_fetch_row @@ -880,7 +987,6 @@ mysql_query(MYSQL *mysql, const char *query) return mysql_real_query(mysql,query, (uint) strlen(query)); } - static MYSQL* spawn_init(MYSQL* parent, const char* host, unsigned int port, const char* user, const char* passwd) @@ -1074,7 +1180,6 @@ mysql_list_tables(MYSQL *mysql, const char *wild) DBUG_RETURN (mysql_store_result(mysql)); } - /************************************************************************** List all fields in a table If wild is given then only the fields matching wild is returned @@ -1116,7 +1221,6 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild) DBUG_RETURN(result); } - /* List all running processes (threads) in server */ MYSQL_RES * STDCALL @@ -1144,7 +1248,6 @@ mysql_list_processes(MYSQL *mysql) DBUG_RETURN(mysql_store_result(mysql)); } - #ifdef USE_OLD_FUNCTIONS int STDCALL mysql_create_db(MYSQL *mysql, const char *db) @@ -1280,64 +1383,6 @@ mysql_get_client_info(void) return (char*) MYSQL_SERVER_VERSION; } - -int STDCALL -mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) -{ - DBUG_ENTER("mysql_option"); - DBUG_PRINT("enter",("option: %d",(int) option)); - switch (option) { - case MYSQL_OPT_CONNECT_TIMEOUT: - mysql->options.connect_timeout= *(uint*) arg; - break; - case MYSQL_OPT_COMPRESS: - mysql->options.compress= 1; /* Remember for connect */ - mysql->options.client_flag|= CLIENT_COMPRESS; - break; - case MYSQL_OPT_NAMED_PIPE: - mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */ - break; - case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ - if (!arg || test(*(uint*) arg)) - mysql->options.client_flag|= CLIENT_LOCAL_FILES; - else - mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; - break; - case MYSQL_INIT_COMMAND: - add_init_command(&mysql->options,arg); - break; - case MYSQL_READ_DEFAULT_FILE: - my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME)); - break; - case MYSQL_READ_DEFAULT_GROUP: - my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME)); - break; - case MYSQL_SET_CHARSET_DIR: - my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME)); - break; - case MYSQL_SET_CHARSET_NAME: - my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.charset_name=my_strdup(arg,MYF(MY_WME)); - break; - case MYSQL_OPT_PROTOCOL: - mysql->options.protocol= *(uint*) arg; - break; - case MYSQL_SHARED_MEMORY_BASE_NAME: -#ifdef HAVE_SMEM - if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) - my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME)); -#endif - break; - default: - DBUG_RETURN(1); - } - DBUG_RETURN(0); -} - my_bool STDCALL mysql_eof(MYSQL_RES *res) { return res->eof; @@ -1380,21 +1425,11 @@ my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) return mysql->last_used_con->insert_id; } -uint STDCALL mysql_errno(MYSQL *mysql) -{ - return mysql->net.last_errno; -} - const char *STDCALL mysql_sqlstate(MYSQL *mysql) { return mysql->net.sqlstate; } -const char * STDCALL mysql_error(MYSQL *mysql) -{ - return mysql->net.last_error; -} - uint STDCALL mysql_warning_count(MYSQL *mysql) { return mysql->warning_count; @@ -3519,7 +3554,7 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt) 0 ok 1 error */ -static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) +my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) { MYSQL *mysql; DBUG_ENTER("mysql_stmt_close"); diff --git a/mysys/default.c b/mysys/default.c index 17ee1b8c8da..7b02999160e 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -174,7 +174,7 @@ void load_defaults(const char *conf_file, const char **groups, res= (char**) (ptr+sizeof(alloc)); /* copy name + found arguments + command line arguments to new array */ - res[0]=*argc ? argv[0][0] : ""; + res[0]=*argc ? argv[0][0] : (char *)""; memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*)); /* Skipp --defaults-file and --defaults-extra-file */ diff --git a/sql-common/client.c b/sql-common/client.c index 3e08c55737b..c586563cdc5 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1,6 +1,84 @@ -my_bool mysql_reconnect(MYSQL *mysql); -static my_bool send_file_to_server(MYSQL *mysql, const char *filename); -void end_server(MYSQL *mysql); +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include + +#if defined(MYSQL_SERVER) || defined(HAVE_EXTERNAL_CLIENT) + +#include "mysql.h" +#if !defined(MYSQL_SERVER) && defined(__WIN__) || defined(_WIN32) || defined(_WIN64) +#include +#include +#endif +#include +#include +#include +#include +#include "mysql_version.h" +#include "mysqld_error.h" +#include "errmsg.h" +#include +#include +#if defined(THREAD) && !defined(__WIN__) +#include /* because of signal() */ +#endif + +#if defined( OS2) && defined(MYSQL_SERVER) +#undef ER +#define ER CER +#endif + +#include +#include +#include + +#ifdef HAVE_PWD_H +#include +#endif + +#if !defined(MSDOS) && !defined(__WIN__) +#include +#include +#include +#include +#ifdef HAVE_SELECT_H +# include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#endif /*!defined(MSDOS) && !defined(__WIN__) */ +#ifdef HAVE_SYS_UN_H +# include +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE -1 +#endif +#if defined(MSDOS) || defined(__WIN__) +#define perror(A) +#else +#include +#define SOCKET_ERROR -1 +#endif + +#include "client_settings.h" +#include + +const char *unknown_sqlstate= "000000"; /**************************************************************************** A modified version of connect(). my_connect() allows you to specify @@ -129,7 +207,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, my_bool testing_named_pipes=0; char *host= *arg_host, *unix_socket= *arg_unix_socket; -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if ( ! unix_socket || (unix_socket)[0] == 0x00) unix_socket = mysql_unix_port; #endif @@ -153,6 +231,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (GetLastError() != ERROR_PIPE_BUSY) { net->last_errno=CR_NAMEDPIPEOPEN_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -161,6 +240,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (! WaitNamedPipe(szPipeName, connect_timeout*1000) ) { net->last_errno=CR_NAMEDPIPEWAIT_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -169,6 +249,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (hPipe == INVALID_HANDLE_VALUE) { net->last_errno=CR_NAMEDPIPEOPEN_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -178,6 +259,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, { CloseHandle( hPipe ); net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; @@ -214,6 +296,7 @@ net_safe_read(MYSQL *mysql) CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST); strmov(net->last_error,ER(net->last_errno)); + strmov(net->sqlstate, unknown_sqlstate); return (packet_error); } if (net->read_pos[0] == 255) @@ -224,22 +307,28 @@ net_safe_read(MYSQL *mysql) net->last_errno=uint2korr(pos); pos+=2; len-=2; + if (protocol_41(mysql) && pos[0] == '#') + { + strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH); + pos+= SQLSTATE_LENGTH+1; + } (void) strmake(net->last_error,(char*) pos, min((uint) len,(uint) sizeof(net->last_error)-1)); } else { net->last_errno=CR_UNKNOWN_ERROR; - (void) strmov(net->last_error,ER(net->last_errno)); + strmov(net->sqlstate, unknown_sqlstate); + strmov(net->last_error,ER(net->last_errno)); } - DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno, - net->last_error)); + DBUG_PRINT("error",("Got error: %d/%s (%s)", + net->last_errno, net->sqlstate, net->last_error)); return(packet_error); } return len; } -static void free_rows(MYSQL_DATA *cur) +void free_rows(MYSQL_DATA *cur) { if (cur) { @@ -248,7 +337,7 @@ static void free_rows(MYSQL_DATA *cur) } } -static my_bool +my_bool advanced_command(MYSQL *mysql, enum enum_server_command command, const char *header, ulong header_length, const char *arg, ulong arg_length, my_bool skip_check) @@ -268,11 +357,13 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, if (mysql->status != MYSQL_STATUS_READY) { strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + strmov(net->sqlstate, unknown_sqlstate); return 1; } - mysql->net.last_error[0]=0; - mysql->net.last_errno=0; + net->last_error[0]=0; + net->last_errno=0; + strmov(net->sqlstate, unknown_sqlstate); mysql->net.report_error=0; mysql->info=0; mysql->affected_rows= ~(my_ulonglong) 0; @@ -318,7 +409,7 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, return advanced_command(mysql, command, NullS, 0, arg, length, skip_check); } -static void free_old_query(MYSQL *mysql) +void free_old_query(MYSQL *mysql) { DBUG_ENTER("free_old_query"); if (mysql->fields) @@ -389,8 +480,6 @@ mysql_free_result(MYSQL_RES *result) DBUG_VOID_RETURN; } -#ifdef _libmysql_c - /**************************************************************************** Get options from my.cnf ****************************************************************************/ @@ -403,8 +492,8 @@ static const char *default_options[]= "character-sets-dir", "default-character-set", "interactive-timeout", "connect-timeout", "local-infile", "disable-local-infile", "replication-probe", "enable-reads-from-master", "repl-parse-query", - "ssl-cipher", "max-allowed-packet", - "protocol", "shared-memory-base-name", + "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", + "multi-results", "multi-queries", NullS }; @@ -517,9 +606,11 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->db=my_strdup(opt_arg,MYF(MY_WME)); } break; +#ifdef MYSQL_CLIENT case 11: /* debug */ mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace"); break; +#endif case 12: /* return-found-rows */ options->client_flag|=CLIENT_FOUND_ROWS; break; @@ -579,6 +670,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, case 27: options->max_allowed_packet= atoi(opt_arg); break; +#ifdef MYSQL_CLIENT case 28: /* protocol */ if ((options->protocol = find_type(opt_arg, &sql_protocol_typelib,0)) == ~(ulong) 0) { @@ -586,6 +678,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, exit(1); } break; +#endif case 29: /* shared_memory_base_name */ #ifdef HAVE_SMEM if (options->shared_memory_base_name != def_shared_memory_base_name) @@ -593,6 +686,12 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); #endif break; + case 30: + options->client_flag|= CLIENT_MULTI_RESULTS; + break; + case 31: + options->client_flag|= CLIENT_MULTI_QUERIES | CLIENT_MULTI_RESULTS; + break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); } @@ -603,15 +702,13 @@ static void mysql_read_default_options(struct st_mysql_options *options, DBUG_VOID_RETURN; } -#endif /*_libmysql_c*/ - /************************************************************************** Get column lengths of the current row If one uses mysql_use_result, res->lengths contains the length information, else the lengths are calculated from the offset between pointers. **************************************************************************/ -static void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count) +void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count) { ulong *prev_length; byte *start=0; @@ -648,6 +745,10 @@ unpack_fields_40(MYSQL_ROWS *row, MYSQL_FIELD *field, MEM_ROOT *alloc, field->length= (uint) uint3korr(row->data[2]); field->type= (enum enum_field_types) (uchar) row->data[3][0]; + field->catalog=(char*) ""; + field->db= (char*) ""; + field->catalog_length= 0; + field->db_length= 0; field->org_table_length= field->table_length= lengths[0]; field->name_length= lengths[1]; @@ -678,13 +779,15 @@ unpack_fields_40(MYSQL_ROWS *row, MYSQL_FIELD *field, MEM_ROOT *alloc, Change field rows to field structs ***************************************************************************/ -static MYSQL_FIELD * +MYSQL_FIELD * unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, my_bool default_value, uint server_capabilities) { +#ifdef MYSQL_CLIENT MYSQL_ROWS *row; +#endif MYSQL_FIELD *field,*result; - ulong lengths[8]; /* Max of fields */ + ulong lengths[9]; /* Max of fields */ DBUG_ENTER("unpack_fields"); field=result=(MYSQL_FIELD*) alloc_root(alloc, @@ -695,7 +798,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, DBUG_RETURN(0); } bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields); -#ifdef _mini_client_c +#ifdef MYSQL_SERVER unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, default_value, server_capabilities & CLIENT_LONG_FLAG); #else @@ -705,33 +808,35 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, for (row=data->data; row ; row = row->next,field++) { uchar *pos; - fetch_lengths(&lengths[0], row->data, default_value ? 7 : 6); - field->db = strdup_root(alloc,(char*) row->data[0]); - field->table = strdup_root(alloc,(char*) row->data[1]); - field->org_table= strdup_root(alloc,(char*) row->data[2]); - field->name = strdup_root(alloc,(char*) row->data[3]); - field->org_name = strdup_root(alloc,(char*) row->data[4]); + fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7); + field->catalog = strdup_root(alloc,(char*) row->data[0]); + field->db = strdup_root(alloc,(char*) row->data[1]); + field->table = strdup_root(alloc,(char*) row->data[2]); + field->org_table= strdup_root(alloc,(char*) row->data[3]); + field->name = strdup_root(alloc,(char*) row->data[4]); + field->org_name = strdup_root(alloc,(char*) row->data[5]); - field->db_length= lengths[0]; - field->table_length= lengths[1]; - field->org_table_length= lengths[2]; - field->name_length= lengths[3]; - field->org_name_length= lengths[4]; + field->catalog_length= lengths[0]; + field->db_length= lengths[1]; + field->table_length= lengths[2]; + field->org_table_length= lengths[3]; + field->name_length= lengths[4]; + field->org_name_length= lengths[5]; /* Unpack fixed length parts */ - pos= (uchar*) row->data[5]; + pos= (uchar*) row->data[6]; field->charsetnr= uint2korr(pos); - field->length= (uint) uint3korr(pos+2); - field->type= (enum enum_field_types) pos[5]; - field->flags= uint2korr(pos+6); - field->decimals= (uint) pos[8]; + field->length= (uint) uint4korr(pos+2); + field->type= (enum enum_field_types) pos[6]; + field->flags= uint2korr(pos+7); + field->decimals= (uint) pos[9]; if (INTERNAL_NUM_FIELD(field)) field->flags|= NUM_FLAG; - if (default_value && row->data[6]) + if (default_value && row->data[7]) { - field->def=strdup_root(alloc,(char*) row->data[6]); - field->def_length= lengths[6]; + field->def=strdup_root(alloc,(char*) row->data[7]); + field->def_length= lengths[7]; } else field->def=0; @@ -743,14 +848,14 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, default_value, server_capabilities & CLIENT_LONG_FLAG); #endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */ -#endif /*_mini_client_c*/ +#endif /*MYSQL_SERVER*/ free_rows(data); /* Free old data */ DBUG_RETURN(result); } /* Read all rows (fields or data) from server */ -static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, +MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, uint fields) { uint field; @@ -769,6 +874,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, MYF(MY_WME | MY_ZEROFILL)))) { net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); DBUG_RETURN(0); } @@ -797,6 +903,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, { free_rows(result); net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); DBUG_RETURN(0); } @@ -817,6 +924,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, { free_rows(result); net->last_errno=CR_MALFORMED_PACKET; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); DBUG_RETURN(0); } @@ -838,7 +946,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, } } *prev_ptr=0; /* last pointer is null */ -#ifndef _mini_client_c +#ifndef MYSQL_SERVER if (pkt_len > 1) /* MySQL 4.1 protocol */ { mysql->warning_count= uint2korr(cp+1); @@ -860,20 +968,21 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) { uint field; ulong pkt_len,len; - uchar *pos,*prev_pos, *end_pos; + uchar *pos, *prev_pos, *end_pos; + NET *net= &mysql->net; if ((pkt_len=net_safe_read(mysql)) == packet_error) return -1; - if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) + if (pkt_len <= 8 && net->read_pos[0] == 254) { -#ifndef _mini_client_c +#ifndef MYSQL_SERVER if (pkt_len > 1) /* MySQL 4.1 protocol */ - mysql->warning_count= uint2korr(mysql->net.read_pos+1); + mysql->warning_count= uint2korr(net->read_pos+1); #endif return 1; /* End of data */ } prev_pos= 0; /* allowed to write at packet[-1] */ - pos=mysql->net.read_pos; + pos=net->read_pos; end_pos=pos+pkt_len; for (field=0 ; field < fields ; field++) { @@ -886,8 +995,9 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) { if (len > (ulong) (end_pos - pos)) { - mysql->net.last_errno=CR_UNKNOWN_ERROR; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + net->last_errno=CR_UNKNOWN_ERROR; + strmov(net->last_error,ER(net->last_errno)); + strmov(net->sqlstate, unknown_sqlstate); return -1; } row[field] = (char*) pos; @@ -920,7 +1030,7 @@ mysql_init(MYSQL *mysql) } else bzero((char*) (mysql),sizeof(*(mysql))); -#ifndef _mini_client_c +#ifndef MYSQL_SERVER mysql->options.connect_timeout=CONNECT_TIMEOUT; mysql->last_used_con = mysql->next_slave = mysql->master = mysql; /* @@ -944,14 +1054,12 @@ mysql_init(MYSQL *mysql) mysql->options.shared_memory_base_name=(char*)def_shared_memory_base_name; #endif -#else /*_mini_client_c*/ +#else /*MYSQL_SERVER*/ #ifdef __WIN__ mysql->options.connect_timeout=20; #endif - mysql->net.read_timeout = slave_net_timeout; - -#endif /*_mini_client_c*/ +#endif /*MYSQL_SERVER*/ return mysql; } @@ -971,7 +1079,7 @@ mysql_init(MYSQL *mysql) void mysql_once_init(void) { -#ifndef _mini_client_c +#ifndef MYSQL_SERVER if (!mysql_client_init) { @@ -1014,9 +1122,9 @@ void mysql_once_init(void) my_thread_init(); /* Init if new thread */ #endif -#else /*_mini_client_c*/ +#else /*MYSQL_SERVER*/ init_client_errs(); -#endif /*_mini_client_c*/ +#endif /*MYSQL_SERVER*/ } @@ -1024,7 +1132,7 @@ void mysql_once_init(void) Handle password authentication */ -static my_bool mysql_autenticate(MYSQL *mysql, const char *passwd) +my_bool mysql_autenticate(MYSQL *mysql, const char *passwd) { ulong pkt_length; NET *net= &mysql->net; @@ -1074,6 +1182,7 @@ static my_bool mysql_autenticate(MYSQL *mysql, const char *passwd) if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net)) { net->last_errno= CR_SERVER_LOST; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); goto error; } @@ -1088,60 +1197,6 @@ error: return 1; } -#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL) -struct passwd *getpwuid(uid_t); -char* getlogin(void); -#endif - - -#if defined(__NETWARE__) -/* default to "root" on NetWare */ -static void read_user_name(char *name) -{ - char *str=getenv("USER"); - strmake(name, str ? str : "UNKNOWN_USER", USERNAME_LENGTH); -} - -#elif !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__) && !defined(OS2) - -static void read_user_name(char *name) -{ - DBUG_ENTER("read_user_name"); - if (geteuid() == 0) - (void) strmov(name,"root"); /* allow use of surun */ - else - { -#ifdef HAVE_GETPWUID - struct passwd *skr; - const char *str; - if ((str=getlogin()) == NULL) - { - if ((skr=getpwuid(geteuid())) != NULL) - str=skr->pw_name; - else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) && - !(str=getenv("LOGIN"))) - str="UNKNOWN_USER"; - } - (void) strmake(name,str,USERNAME_LENGTH); -#elif HAVE_CUSERID - (void) cuserid(name); -#else - strmov(name,"UNKNOWN_USER"); -#endif - } - DBUG_VOID_RETURN; -} - -#else /* If MSDOS || VMS */ - -static void read_user_name(char *name) -{ - char *str=getenv("USER"); /* ODBC will send user variable */ - strmake(name,str ? str : "ODBC", USERNAME_LENGTH); -} - -#endif - /* Note that the mysql argument must be initialized with mysql_init() before calling mysql_real_connect ! @@ -1150,20 +1205,20 @@ static void read_user_name(char *name) MYSQL * STDCALL mysql_real_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, - uint port, const char *unix_socket,ulong client_flag -#ifdef _mini_client_c - , uint net_read_timeout -#endif -) + uint port, const char *unix_socket,ulong client_flag) { - char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; - char *end,*host_info,*charset_name; +#ifdef MYSQL_CLIENT + char *charset_name; + char charset_name_buff[16]; +#endif + char buff[NAME_LEN+USERNAME_LENGTH+100]; + char *end,*host_info; my_socket sock; uint32 ip_addr; struct sockaddr_in sock_addr; ulong pkt_length; NET *net= &mysql->net; -#ifdef _mini_client_c +#ifdef MYSQL_SERVER thr_alarm_t alarmed; ALARM alarm_buff; ulong max_allowed_packet; @@ -1187,11 +1242,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); net->vio = 0; /* If something goes wrong */ -#ifdef _mini_client_c + mysql->client_flag=0; /* For handshake */ +#ifdef MYSQL_SERVER mysql->charset=default_charset_info; /* Set character set */ #endif -#ifdef _libmysql_c /* use default options */ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) { @@ -1223,15 +1278,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, port=mysql->options.port; if (!unix_socket) unix_socket=mysql->options.unix_socket; -#endif /*_libmysql_c*/ -#ifdef _mini_client_c - if (!port) - port = MYSQL_PORT; /* Should always be set by mysqld */ - if (!unix_socket) - unix_socket=MYSQL_UNIX_ADDR; - if (!mysql->options.connect_timeout) - mysql->options.connect_timeout= net_read_timeout; -#endif /*mini_client_c*/ mysql->reconnect=1; /* Reconnect as default */ mysql->server_status=SERVER_STATUS_AUTOCOMMIT; @@ -1239,7 +1285,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Grab a socket and connect it to the server */ -#if defined(_libmysql_c) && defined(HAVE_SMEM) +#if defined(MYSQL_CLIENT) && defined(HAVE_SMEM) if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && (!host || !strcmp(host,LOCAL_HOST))) @@ -1269,18 +1315,18 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #endif /* HAVE_SMEM */ #if defined(HAVE_SYS_UN_H) if ( -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT (!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&& (unix_socket || mysql_unix_port) && #endif -#ifdef _mini_client_c +#ifdef MYSQL_SERVER unix_socket && #endif (!host || !strcmp(host,LOCAL_HOST))) { host=LOCAL_HOST; -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if (!unix_socket) unix_socket=mysql_unix_port; #endif @@ -1289,6 +1335,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) { net->last_errno=CR_SOCKET_CREATE_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),socket_errno); goto error; } @@ -1302,10 +1349,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("error",("Got error %d on connect to local server", socket_errno)); net->last_errno=CR_CONNECTION_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); goto error; } -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT else mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; #endif @@ -1313,13 +1361,13 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, else #elif defined(__WIN__) { -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&& ((unix_socket || !host && is_NT() || host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||! have_tcpip))&& (!net->vio)) -#elif _mini_client_c +#elif MYSQL_SERVER if ((unix_socket || !host && is_NT() || host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) || @@ -1350,17 +1398,17 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } } } -#ifdef _mini_client_c +#ifdef MYSQL_SERVER if (hPipe == INVALID_HANDLE_VALUE) #endif #endif -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_TCP)&&(!net->vio)) #endif { unix_socket=0; /* This is not used */ -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if (!port) port=mysql_port; #endif @@ -1368,18 +1416,19 @@ mysql_real_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)); -#ifdef _mini_client_c +#ifdef MYSQL_SERVER thr_alarm_init(&alarmed); - thr_alarm(&alarmed, net_read_timeout, &alarm_buff); + thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff); #endif sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); -#ifdef _mini_client_c +#ifdef MYSQL_SERVER thr_end_alarm(&alarmed); #endif /* _WIN64 ; Assume that the (int) range is enough for socket() */ if (sock == SOCKET_ERROR) { net->last_errno=CR_IPSOCK_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error,ER(net->last_errno),socket_errno); goto error; } @@ -1406,6 +1455,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, { my_gethostbyname_r_free(); net->last_errno=CR_UNKNOWN_HOST; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno); goto error; } @@ -1419,29 +1469,32 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, host)); net->last_errno= CR_CONN_HOST_ERROR; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno); goto error; } } -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT else if (!net->vio) { DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); net->last_errno= CR_CONN_UNKNOW_PROTOCOL; + strmov(net->sqlstate, unknown_sqlstate); sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL)); goto error; } -#endif /*_libmysql_c*/ +#endif /*MYSQL_CLIENT*/ if (!net->vio || my_net_init(net, net->vio)) { vio_delete(net->vio); net->vio = 0; net->last_errno=CR_OUT_OF_MEMORY; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); goto error; } vio_keepalive(net->vio,TRUE); -#ifdef _mini_client_c +#ifdef MYSQL_SERVER net->read_timeout=slave_net_timeout; #endif /* Get version info */ @@ -1450,6 +1503,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, vio_poll_read(net->vio, mysql->options.connect_timeout)) { net->last_errno= CR_SERVER_LOST; + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error,ER(net->last_errno)); goto error; } @@ -1463,10 +1517,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("info",("mysql protocol version %d, server=%d", PROTOCOL_VERSION, mysql->protocol_version)); if (mysql->protocol_version != PROTOCOL_VERSION -#ifdef _mini_client_c - && mysql->protocol_version != PROTOCOL_VERSION-1 -#endif - ) + && mysql->protocol_version != PROTOCOL_VERSION-1) { net->last_errno= CR_VERSION_ERROR; sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, @@ -1487,14 +1538,15 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql->server_status=uint2korr(end+3); } -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT /* Set character set */ if ((charset_name=mysql->options.charset_name)) { const char *save=charsets_dir; if (mysql->options.charset_dir) charsets_dir=mysql->options.charset_dir; - mysql->charset=get_charset_by_name(mysql->options.charset_name, + mysql->charset=get_charset_by_csname(mysql->options.charset_name, + MY_CS_PRIMARY, MYF(MY_WME)); charsets_dir=save; } @@ -1512,6 +1564,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (!mysql->charset) { net->last_errno=CR_CANT_READ_CHARSET; + strmov(net->sqlstate, unknown_sqlstate); if (mysql->options.charset_dir) sprintf(net->last_error,ER(net->last_errno), charset_name ? charset_name : "unknown", @@ -1526,7 +1579,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } goto error; } -#endif /*_libmysql_c*/ +#endif /*MYSQL_CLIENT*/ /* Save connection information */ if (!user) user=""; @@ -1542,6 +1595,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, !(mysql->user=my_strdup(user,MYF(0))) || !(mysql->passwd=my_strdup(passwd,MYF(0)))) { + strmov(net->sqlstate, unknown_sqlstate); strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); goto error; } @@ -1557,6 +1611,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Send client information for access check */ client_flag|=CLIENT_CAPABILITIES; + if (client_flag & CLIENT_MULTI_QUERIES) + client_flag|= CLIENT_MULTI_RESULTS; #ifdef HAVE_OPENSSL if (mysql->options.ssl_key || mysql->options.ssl_cert || @@ -1569,7 +1625,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (db) client_flag|=CLIENT_CONNECT_WITH_DB; -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT /* Remove options that server doesn't support */ client_flag= ((client_flag & ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) | @@ -1579,10 +1635,12 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #endif if (client_flag & CLIENT_PROTOCOL_41) { - /* 4.1 server and 4.1 client has a 4 byte option flag */ + /* 4.1 server and 4.1 client has a 32 byte option flag */ int4store(buff,client_flag); int4store(buff+4,max_allowed_packet); - end= buff+8; + buff[8]= mysql->charset->number; + bzero(buff+9, 32-9); + end= buff+32; } else { @@ -1591,9 +1649,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, end= buff+5; } mysql->client_flag=client_flag; -#endif /*_libmysql_c*/ +#endif /*MYSQL_CLIENT*/ -#ifdef _mini_client_c +#ifdef MYSQL_SERVER #ifdef HAVE_COMPRESS if ((mysql->server_capabilities & CLIENT_COMPRESS) && (mysql->options.compress || (client_flag & CLIENT_COMPRESS))) @@ -1601,9 +1659,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, else #endif client_flag&= ~CLIENT_COMPRESS; -#endif /*mini_client_c*/ +#endif /*MYSQL_SERVER*/ -#ifdef _mini_client_c +#ifdef MYSQL_SERVER #ifdef HAVE_OPENSSL if ((mysql->server_capabilities & CLIENT_SSL) && (mysql->options.use_ssl || (client_flag & CLIENT_SSL))) @@ -1626,7 +1684,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, int3store(buff+2,max_allowed_packet); end= buff+5; mysql->client_flag=client_flag; -#endif /*_mini_client_c*/ +#endif /*MYSQL_SERVER*/ #ifdef HAVE_OPENSSL /* @@ -1635,15 +1693,18 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, */ if (client_flag & CLIENT_SSL) { +#ifdef MYSQL_CLIENT struct st_mysql_options *options= &mysql->options; +#endif if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SERVER_LOST; strmov(net->last_error,ER(net->last_errno)); goto error; } /* Do the SSL layering. */ -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if (!(mysql->connector_fd= (gptr) new_VioSSLConnectorFd(options->ssl_key, options->ssl_cert, @@ -1651,15 +1712,17 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, options->ssl_capath, options->ssl_cipher))) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SSL_CONNECTION_ERROR; strmov(net->last_error,ER(net->last_errno)); goto error; } -#endif /*libmysql_c*/ +#endif /*MYSQL_CLIENT*/ DBUG_PRINT("info", ("IO layer change in progress...")); if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), mysql->net.vio, (long) (mysql->options.connect_timeout))) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SSL_CONNECTION_ERROR; strmov(net->last_error,ER(net->last_errno)); goto error; @@ -1675,7 +1738,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (user && user[0]) strmake(end,user,32); /* Max user name */ else -#ifdef _mini_client_c +#ifdef MYSQL_SERVER { user = getenv("USER"); if (!user) user = "mysql"; @@ -1683,9 +1746,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } #else read_user_name((char*) end); -#endif /*_mini_client_c*/ +#endif /*MYSQL_SERVER*/ /* We have to handle different version of handshake here */ -#if defined(_CUSTOMCONFIG_) && defined(_libmysql_c) +#if defined(_CUSTOMCONFIG_) && defined(MYSQL_CLIENT) #include "_cust_libmysql.h"; #endif DBUG_PRINT("info",("user: %s",end)); @@ -1728,6 +1791,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Write authentication package */ if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_SERVER_LOST; strmov(net->last_error,ER(net->last_errno)); goto error; @@ -1739,7 +1803,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (client_flag & CLIENT_COMPRESS) /* We will use compression */ net->compress=1; -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if (mysql->options.max_allowed_packet) net->max_packet_size= mysql->options.max_allowed_packet; if (db && mysql_select_db(mysql,db)) @@ -1772,7 +1836,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) goto error; -#endif /*_libmysql_c*/ +#endif /*MYSQL_CLIENT*/ DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); reset_sigpipe(mysql); @@ -1780,7 +1844,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, error: reset_sigpipe(mysql); - DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); + DBUG_PRINT("error",("message: %u/%s (%s)", + net->last_errno, net->sqlstate, net->last_error)); { /* Free alloced memory */ my_bool free_me=mysql->free_me; @@ -1794,6 +1859,7 @@ error: /* needed when we move MYSQL structure to a different address */ +#ifdef MYSQL_CLIENT /*should work in MYSQL_SERVER also, but doesn't */ static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) { MYSQL *tmp, *tmp_prev; @@ -1810,6 +1876,7 @@ static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) } tmp_prev->next_slave = mysql; } +#endif /*MYSQL_CLIENT*/ my_bool mysql_reconnect(MYSQL *mysql) { @@ -1817,15 +1884,11 @@ my_bool mysql_reconnect(MYSQL *mysql) DBUG_ENTER("mysql_reconnect"); if (!mysql->reconnect -#ifdef _libmysql_c - || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info -#endif -) + || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { /* Allow reconnect next time */ -#ifdef _libmysql_c mysql->server_status&= ~SERVER_STATUS_IN_TRANS; -#endif + strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->net.last_errno=CR_SERVER_GONE_ERROR; strmov(mysql->net.last_error,ER(mysql->net.last_errno)); DBUG_RETURN(1); @@ -1834,23 +1897,23 @@ my_bool mysql_reconnect(MYSQL *mysql) tmp_mysql.options=mysql->options; bzero((char*) &mysql->options,sizeof(mysql->options)); tmp_mysql.rpl_pivot = mysql->rpl_pivot; +#ifdef MYSQL_SERVER + mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&mysql->net.read_timeout); +#endif if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, mysql->db, mysql->port, mysql->unix_socket, - mysql->client_flag -#ifdef _mini_client_c - , mysql->net.read_timeout -#endif -)) + mysql->client_flag)) { mysql->net.last_errno= tmp_mysql.net.last_errno; strmov(mysql->net.last_error, tmp_mysql.net.last_error); + strmov(mysql->net.sqlstate, unknown_sqlstate); DBUG_RETURN(1); } tmp_mysql.free_me=mysql->free_me; mysql->free_me=0; mysql_close(mysql); *mysql=tmp_mysql; -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT /*rpl000010 fails if #ifdef-s were removed*/ mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ #endif net_clear(&mysql->net); @@ -1924,7 +1987,6 @@ mysql_close(MYSQL *mysql) my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); -#ifdef _libmysql_c my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); @@ -1962,6 +2024,7 @@ mysql_close(MYSQL *mysql) } mysql->rpl_pivot=0; } +#ifdef MYSQL_CLIENT if (mysql->stmts) { /* Free any open prepared statements */ @@ -1974,7 +2037,7 @@ mysql_close(MYSQL *mysql) } if (mysql != mysql->master) mysql_close(mysql->master); -#endif /*_libmysql_c*/ +#endif /*MYSQL_CLIENT*/ #ifdef HAVE_OPENSSL mysql_ssl_free(mysql); @@ -1997,7 +2060,7 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql) ulong length; DBUG_ENTER("mysql_read_query_result"); -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT /* Read from the connection which we actually used, which could differ from the original connection if we have slaves @@ -2008,21 +2071,20 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql) if ((length = net_safe_read(mysql)) == packet_error) DBUG_RETURN(1); free_old_query(mysql); /* Free old result */ +#ifdef MYSQL_CLIENT /*or else gcc will warn of unused labels*/ get_info: +#endif pos=(uchar*) mysql->net.read_pos; if ((field_count= net_field_length(&pos)) == 0) { mysql->affected_rows= net_field_length_ll(&pos); mysql->insert_id= net_field_length_ll(&pos); -#ifdef _libmysql_c if (protocol_41(mysql)) { mysql->server_status=uint2korr(pos); pos+=2; mysql->warning_count=uint2korr(pos); pos+=2; } - else -#endif /*libmysql_c*/ - if (mysql->server_capabilities & CLIENT_TRANSACTIONS) + else if (mysql->server_capabilities & CLIENT_TRANSACTIONS) { mysql->server_status=uint2korr(pos); pos+=2; mysql->warning_count= 0; @@ -2033,6 +2095,7 @@ get_info: mysql->info=(char*) pos; DBUG_RETURN(0); } +#ifdef MYSQL_CLIENT if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ { int error=send_file_to_server(mysql,(char*) pos); @@ -2040,16 +2103,13 @@ get_info: DBUG_RETURN(1); goto get_info; /* Get info packet */ } +#endif if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) mysql->server_status|= SERVER_STATUS_IN_TRANS; mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ - if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, -#ifdef _libmysql_c - protocol_41(mysql) ? 6 : -#endif - 5))) + if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0,protocol_41(mysql) ? 7 : 5))) DBUG_RETURN(1); if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, (uint) field_count,0, @@ -2074,7 +2134,7 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length) DBUG_ENTER("mysql_send_query"); DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d", mysql->options.rpl_parse, mysql->rpl_pivot)); -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT if (mysql->options.rpl_parse && mysql->rpl_pivot) { switch (mysql_rpl_query_type(query, length)) { @@ -2088,7 +2148,7 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length) } mysql->last_used_con = mysql; -#endif /*libmysql_c*/ +#endif /*MYSQL_CLIENT*/ DBUG_RETURN(simple_command(mysql, COM_QUERY, query, length, 1)); } @@ -2106,65 +2166,6 @@ mysql_real_query(MYSQL *mysql, const char *query, ulong length) DBUG_RETURN((int) mysql_read_query_result(mysql)); } -static my_bool -send_file_to_server(MYSQL *mysql, const char *filename) -{ - int fd, readcount; - my_bool result= 1; - uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); - char *buf, tmp_name[FN_REFLEN]; - DBUG_ENTER("send_file_to_server"); - - if (!(buf=my_malloc(packet_length,MYF(0)))) - { - strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY)); - DBUG_RETURN(1); - } - - fn_format(tmp_name,filename,"","",4); /* Convert to client format */ - if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0) - { - my_net_write(&mysql->net,"",0); /* Server needs one packet */ - net_flush(&mysql->net); - mysql->net.last_errno=EE_FILENOTFOUND; - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - EE(mysql->net.last_errno),tmp_name, errno); - goto err; - } - - while ((readcount = (int) my_read(fd,(byte*) buf,packet_length,MYF(0))) > 0) - { - if (my_net_write(&mysql->net,buf,readcount)) - { - DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file")); - mysql->net.last_errno=CR_SERVER_LOST; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - goto err; - } - } - /* Send empty packet to mark end of file */ - if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net)) - { - mysql->net.last_errno=CR_SERVER_LOST; - sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno); - goto err; - } - if (readcount < 0) - { - mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */ - my_snprintf(mysql->net.last_error,sizeof(mysql->net.last_error)-1, - tmp_name,errno); - goto err; - } - result=0; /* Ok */ - -err: - if (fd >= 0) - (void) my_close(fd,MYF(0)); - my_free(buf,MYF(0)); - DBUG_RETURN(result); -} - /************************************************************************** Alloc result struct for buffered results. All rows are read to buffer. mysql_data_seek may be used. @@ -2176,7 +2177,7 @@ mysql_store_result(MYSQL *mysql) MYSQL_RES *result; DBUG_ENTER("mysql_store_result"); -#ifdef _libmysql_c +#ifdef MYSQL_CLIENT /* read from the actually used connection */ mysql = mysql->last_used_con; #endif @@ -2184,6 +2185,7 @@ mysql_store_result(MYSQL *mysql) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { + strmov(mysql->net.sqlstate, unknown_sqlstate); strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); DBUG_RETURN(0); @@ -2194,6 +2196,7 @@ mysql_store_result(MYSQL *mysql) mysql->field_count), MYF(MY_WME | MY_ZEROFILL)))) { + strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->net.last_errno=CR_OUT_OF_MEMORY; strmov(mysql->net.last_error, ER(mysql->net.last_errno)); DBUG_RETURN(0); @@ -2272,6 +2275,66 @@ mysql_data_seek(MYSQL_RES *result, my_ulonglong row) result->data_cursor = tmp; } +int STDCALL +mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) +{ + DBUG_ENTER("mysql_option"); + DBUG_PRINT("enter",("option: %d",(int) option)); + switch (option) { + case MYSQL_OPT_CONNECT_TIMEOUT: + mysql->options.connect_timeout= *(uint*) arg; + break; + case MYSQL_OPT_COMPRESS: + mysql->options.compress= 1; /* Remember for connect */ + mysql->options.client_flag|= CLIENT_COMPRESS; + break; + case MYSQL_OPT_NAMED_PIPE: + mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */ + break; + case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ + if (!arg || test(*(uint*) arg)) + mysql->options.client_flag|= CLIENT_LOCAL_FILES; + else + mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; + break; +#ifdef MYSQL_CLIENT + case MYSQL_INIT_COMMAND: + add_init_command(&mysql->options,arg); + break; +#endif + case MYSQL_READ_DEFAULT_FILE: + my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME)); + break; + case MYSQL_READ_DEFAULT_GROUP: + my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME)); + break; + case MYSQL_SET_CHARSET_DIR: + my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME)); + break; + case MYSQL_SET_CHARSET_NAME: + my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.charset_name=my_strdup(arg,MYF(MY_WME)); + break; + case MYSQL_OPT_PROTOCOL: + mysql->options.protocol= *(uint*) arg; + break; + case MYSQL_SHARED_MEMORY_BASE_NAME: +#ifdef HAVE_SMEM + if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) + my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME)); +#endif + break; + default: + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + + /**************************************************************************** Functions to get information from the MySQL structure These are functions to make shared libraries more usable. @@ -2297,3 +2360,6 @@ const char * STDCALL mysql_error(MYSQL *mysql) { return mysql->net.last_error; } + +#endif /* defined(MYSQL_SERVER) || defined(HAVE_EXTERNAL_CLIENT) */ + diff --git a/sql/Makefile.am b/sql/Makefile.am index 608b959a8b9..eeaf96ce190 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -55,9 +55,9 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ opt_range.h opt_ft.h protocol.h \ sql_select.h structs.h table.h sql_udf.h hash_filo.h\ lex.h lex_symbol.h sql_acl.h sql_crypt.h \ - log_event.h mini_client.h sql_repl.h slave.h \ + log_event.h sql_repl.h slave.h \ stacktrace.h sql_sort.h sql_cache.h set_var.h \ - spatial.h gstream.h + spatial.h gstream.h client_settings.h mysqld_SOURCES = sql_lex.cc sql_handler.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \ item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \ @@ -83,7 +83,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \ sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \ slave.cc sql_repl.cc sql_union.cc sql_derived.cc \ - mini_client.cc mini_client_errors.c pack.c\ + client.c mini_client_errors.c pack.c\ stacktrace.c repl_failsafe.h repl_failsafe.cc sql_olap.cc\ gstream.cc spatial.cc sql_help.cc protocol_cursor.cc gen_lex_hash_SOURCES = gen_lex_hash.cc @@ -104,6 +104,8 @@ link_sources: @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c rm -f pack.c @LN_CP_F@ ../sql-common/pack.c pack.c + rm -f client.c + @LN_CP_F@ ../sql-common/client.c client.c gen_lex_hash.o: gen_lex_hash.cc lex.h $(CXXCOMPILE) -c $(INCLUDES) $< diff --git a/sql/client_settings.h b/sql/client_settings.h new file mode 100644 index 00000000000..de0c7f40717 --- /dev/null +++ b/sql/client_settings.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifndef _client_settings_h +#define _client_settings_h +#include +#include +#include + + +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ + CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) + + +extern ulong slave_net_timeout; +#define init_sigpipe_variables +#define set_sigpipe(mysql) +#define reset_sigpipe(mysql) +#endif /* _client_settings_h */ diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 1d0801fc3c1..2aa8f492ed3 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -23,7 +23,6 @@ #include "sql_repl.h" #include "slave.h" #include "sql_acl.h" -#include "mini_client.h" #include "log_event.h" #include @@ -669,9 +668,9 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi) strmov(mysql->net.last_error, "Master is not configured"); DBUG_RETURN(1); } + mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&slave_net_timeout); if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, - mi->port, 0, 0, - slave_net_timeout)) + mi->port, 0, 0)) DBUG_RETURN(1); DBUG_RETURN(0); } diff --git a/sql/slave.cc b/sql/slave.cc index cc40df38eff..a49389e0ec7 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -20,12 +20,12 @@ #include #include -#include "mini_client.h" #include "slave.h" #include "sql_repl.h" #include "repl_failsafe.h" #include #include +#include bool use_slave_mask = 0; MY_BITMAP slave_error_mask; @@ -2948,9 +2948,10 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, while (!(slave_was_killed = io_slave_killed(thd,mi)) && (reconnect ? mysql_reconnect(mysql) != 0: - !mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, - mi->port, 0, client_flag, - thd->variables.net_read_timeout))) + !(mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, + (char *)&thd->variables.net_read_timeout), + mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, + mi->port, 0, client_flag)))) { /* Don't repeat last error */ if ((int)mysql_errno(mysql) != last_errno) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index b8f6de30840..fe47e553cf3 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -22,7 +22,6 @@ #include "sql_repl.h" #include "sql_acl.h" #include "log_event.h" -#include "mini_client.h" #include extern const char* any_db; From b5965dbded30dcd3e6cae0368b31c3341e00d32d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 31 May 2003 18:44:37 +0300 Subject: [PATCH 284/399] Fixed compiler optimization problem with doubleget() (Casused problems in GIS functions in 4.1) include/global.h: Fixed compiler optimization problem with doubleget() --- include/global.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/global.h b/include/global.h index 1737c60db30..94b0f5bab03 100644 --- a/include/global.h +++ b/include/global.h @@ -795,8 +795,11 @@ typedef union { double v; long m[2]; } doubleget_union; -#define doubleget(V,M) { ((doubleget_union *)&V)->m[0] = *((long*) M); \ - ((doubleget_union *)&V)->m[1] = *(((long*) M)+1); } +#define doubleget(V,M) \ +{ doubleget_union _tmp; \ + _tmp.m[0] = *((long*)(M)); \ + _tmp.m[1] = *(((long*) (M))+1); \ + (V) = _tmp.v; } #define doublestore(T,V) { *((long *) T) = ((doubleget_union *)&V)->m[0]; \ *(((long *) T)+1) = ((doubleget_union *)&V)->m[1]; } #define float4get(V,M) { *((long *) &(V)) = *((long*) (M)); } From 2ef52d46a4f5b0c34bee26b0f70d672b6ee9325e Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Jun 2003 12:32:53 +0300 Subject: [PATCH 285/399] Fixed bug in ALTER TABLE DISABLE KEYS and INSERT DELAYED. Bug #478 mysql-test/r/alter_table.result: new results mysql-test/r/lowercase_table.result: new results mysql-test/t/alter_table.test: Test of ALTER TABLE DISABLE KEYS + INSERT DELAYED mysql-test/t/lowercase_table.test: Added test of alias name comparison sql/mysql_priv.h: Made closed_cached_table local sql/sql_table.cc: Fixed bug in ALTER TABLE DISABLE KEYS and INSERT DELAYED --- mysql-test/r/alter_table.result | 5 ++ mysql-test/r/lowercase_table.result | 12 +++ mysql-test/t/alter_table.test | 9 ++ mysql-test/t/lowercase_table.test | 11 +++ sql/mysql_priv.h | 1 - sql/sql_table.cc | 133 +++++++++++++++++----------- 6 files changed, 118 insertions(+), 53 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index cfbc46bc78f..e2d9cc30ad9 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -276,3 +276,8 @@ 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; +CREATE TABLE t1 (i int(10), index(i) ); +ALTER TABLE t1 DISABLE KEYS; +INSERT DELAYED INTO t1 VALUES(1),(2),(3); +ALTER TABLE t1 ENABLE KEYS; +drop table t1; diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result index 1caaf317c96..d32228216b8 100644 --- a/mysql-test/r/lowercase_table.result +++ b/mysql-test/r/lowercase_table.result @@ -13,3 +13,15 @@ show tables like 't_'; Tables_in_test (t_) t3 drop table t3; +create table t1 (a int); +select count(*) from T1; +count(*) +0 +select count(*) from t1; +count(*) +0 +select count(T1.a) from t1; +Unknown table 'T1' in field list +select count(bags.a) from t1 as Bags; +Unknown table 'bags' in field list +drop table t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 96f969c8776..a3ab62afc69 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -133,3 +133,12 @@ analyze table t1; show keys from t1; drop table t1; +# +# Test of ALTER TABLE DELAYED +# + +CREATE TABLE t1 (i int(10), index(i) ); +ALTER TABLE t1 DISABLE KEYS; +INSERT DELAYED INTO t1 VALUES(1),(2),(3); +ALTER TABLE t1 ENABLE KEYS; +drop table t1; diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test index 0d04e6c7df7..b3453dfd3c4 100644 --- a/mysql-test/t/lowercase_table.test +++ b/mysql-test/t/lowercase_table.test @@ -12,3 +12,14 @@ ALTER TABLE T2 RENAME T3; show tables like 't_'; drop table t3; +# +# Test alias +# +create table t1 (a int); +select count(*) from T1; +select count(*) from t1; +--error 1109 +select count(T1.a) from t1; +--error 1109 +select count(bags.a) from t1 as Bags; +drop table t1; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 614cb8cadf6..41a39f0d24c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -422,7 +422,6 @@ bool mysql_rename_table(enum db_type base, const char * old_name, const char *new_db, const char * new_name); -bool close_cached_table(THD *thd,TABLE *table); int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys); int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop_list); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 07ec1d67538..f3620b860a7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -912,58 +912,76 @@ mysql_rename_table(enum db_type base, } /* - close table in this thread and force close + reopen in other threads - This assumes that the calling thread has lock on LOCK_open - Win32 clients must also have a WRITE LOCK on the table ! + Force all other threads to stop using the table + + SYNOPSIS + wait_while_table_is_used() + thd Thread handler + table Table to remove from cache + + NOTES + When returning, the table will be unusable for other threads until + the table is closed. + + PREREQUISITES + Lock on LOCK_open + Win32 clients must also have a WRITE LOCK on the table ! */ -static void safe_remove_from_cache(THD *thd,TABLE *table) +static void wait_while_table_is_used(THD *thd,TABLE *table) { - DBUG_ENTER("safe_remove_from_cache"); - if (table) - { - DBUG_PRINT("enter",("table: %s", table->real_name)); - VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files - /* Mark all tables that are in use as 'old' */ - mysql_lock_abort(thd,table); // end threads waiting on lock + DBUG_PRINT("enter",("table: %s", table->real_name)); + DBUG_ENTER("wait_while_table_is_used"); + safe_mutex_assert_owner(&LOCK_open); -#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2) - /* Wait until all there are no other threads that has this table open */ - while (remove_table_from_cache(thd,table->table_cache_key, - table->real_name)) - { - dropping_tables++; - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); - dropping_tables--; - } -#else - (void) remove_table_from_cache(thd,table->table_cache_key, - table->real_name); -#endif - /* When lock on LOCK_open is freed other threads can continue */ - pthread_cond_broadcast(&COND_refresh); + VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files + /* Mark all tables that are in use as 'old' */ + mysql_lock_abort(thd, table); // end threads waiting on lock + + /* Wait until all there are no other threads that has this table open */ + while (remove_table_from_cache(thd,table->table_cache_key, + table->real_name)) + { + dropping_tables++; + (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + dropping_tables--; } DBUG_VOID_RETURN; } +/* + Close a cached table -bool close_cached_table(THD *thd,TABLE *table) + SYNOPSIS + clsoe_cached_table() + thd Thread handler + table Table to remove from cache + + NOTES + Function ends by signaling threads waiting for the table to try to + reopen the table. + + PREREQUISITES + Lock on LOCK_open + Win32 clients must also have a WRITE LOCK on the table ! +*/ + +static bool close_cached_table(THD *thd, TABLE *table) { DBUG_ENTER("close_cached_table"); - safe_mutex_assert_owner(&LOCK_open); - - if (table) + + wait_while_table_is_used(thd,table); + /* Close lock if this is not got with LOCK TABLES */ + if (thd->lock) { - safe_remove_from_cache(thd,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 - } - /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ - thd->open_tables=unlink_open_table(thd,thd->open_tables,table); + 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); + + /* When lock on LOCK_open is freed other threads can continue */ + pthread_cond_broadcast(&COND_refresh); DBUG_RETURN(0); } @@ -1094,10 +1112,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, 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 we could open the table, close it */ + if (table_list->table) + { + pthread_mutex_lock(&LOCK_open); + close_cached_table(thd, table); + pthread_mutex_unlock(&LOCK_open); + } if (lock_and_wait_for_table_name(thd,table_list)) { error= -1; @@ -1494,11 +1515,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, else { *fn_ext(new_name)=0; - close_cached_table(thd,table); + close_cached_table(thd, table); if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name)) error= -1; } - VOID(pthread_cond_broadcast(&COND_refresh)); VOID(pthread_mutex_unlock(&LOCK_open)); } if (!error) @@ -1507,12 +1527,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, case LEAVE_AS_IS: break; case ENABLE: - safe_remove_from_cache(thd,table); - error= table->file->activate_all_index(thd); + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table); + VOID(pthread_mutex_unlock(&LOCK_open)); + error= table->file->activate_all_index(thd); + /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: - safe_remove_from_cache(thd,table); + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table); + VOID(pthread_mutex_unlock(&LOCK_open)); table->file->deactivate_non_unique_index(HA_POS_ERROR); + /* COND_refresh will be signaled in close_thread_tables() */ break; } } @@ -1936,7 +1962,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, close the original table at before doing the rename */ table_name=thd->strdup(table_name); // must be saved - if (close_cached_table(thd,table)) + if (close_cached_table(thd, table)) { // Aborted VOID(quick_rm_table(new_db_type,new_db,tmp_name)); VOID(pthread_mutex_unlock(&LOCK_open)); @@ -1970,7 +1996,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, This shouldn't happen. We solve this the safe way by closing the locked table. */ - close_cached_table(thd,table); + if (table) + close_cached_table(thd,table); VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } @@ -1980,7 +2007,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, Not table locking or alter table with rename free locks and remove old table */ - close_cached_table(thd,table); + if (table) + close_cached_table(thd,table); VOID(quick_rm_table(old_db_type,db,old_name)); } else @@ -2000,7 +2028,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, if (close_data_tables(thd,db,table_name) || reopen_tables(thd,1,0)) { // This shouldn't happen - close_cached_table(thd,table); // Remove lock for table + if (table) + close_cached_table(thd,table); // Remove lock for table VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } From 3f7dfc4df3a9bdfc01e5b84c3297fff61b791f9b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Jun 2003 23:40:01 +0300 Subject: [PATCH 286/399] Small fixes (nothing nameworthy) mysql-test/r/errors.result: Rename: mysql-test/r/err000001.result -> mysql-test/r/errors.result include/my_global.h: typedef for future functions that needs string length as an argument innobase/os/os0file.c: Added operation to error messages mysql-test/t/errors.test: Cleaned up file to new error number standard mysys/thr_alarm.c: Made end_thr_alarm() work also with internal alarm thread. (Not critical for MySQL) sql/mysqld.cc: Added sigemptyset() (bug found by valgrind) Removed some wrong usage of thd when writing variable values --- include/my_global.h | 5 ++- innobase/os/os0file.c | 37 +++++++++++------ .../r/{err000001.result => errors.result} | 0 mysql-test/t/err000001.test | 19 --------- mysql-test/t/errors.test | 32 +++++++++++++++ mysys/thr_alarm.c | 41 ++++++++++++++----- sql/mysqld.cc | 14 ++----- 7 files changed, 95 insertions(+), 53 deletions(-) rename mysql-test/r/{err000001.result => errors.result} (100%) delete mode 100644 mysql-test/t/err000001.test create mode 100644 mysql-test/t/errors.test diff --git a/include/my_global.h b/include/my_global.h index d892d843edc..90c4801e807 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL 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 @@ -640,6 +640,9 @@ typedef long my_ptrdiff_t; typedef long long my_ptrdiff_t; #endif +/* typedef used for length of string; Should be unsigned! */ +typedef ulong size_str; + #define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) #define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) /* Size to make adressable obj. */ diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 640ffec122f..00e29121ece 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -295,7 +295,8 @@ os_file_handle_error( /* out: TRUE if we should retry the operation */ os_file_t file, /* in: file pointer */ - char* name) /* in: name of a file or NULL */ + char* name, /* in: name of a file or NULL */ + const char* operation) /* in: type of operation */ { ulint err; @@ -337,7 +338,8 @@ os_file_handle_error( if (name) { fprintf(stderr, "InnoDB: File name %s\n", name); } - + fprintf(stderr, "InnoDB: system call %s\n", operation); + fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fflush(stderr); @@ -419,7 +421,9 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; @@ -460,7 +464,10 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); + if (retry) { goto try_again; @@ -568,7 +575,9 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; @@ -615,7 +624,9 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; @@ -649,7 +660,7 @@ os_file_close( return(TRUE); } - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "close"); return(FALSE); #else int ret; @@ -657,7 +668,7 @@ os_file_close( ret = close(file); if (ret == -1) { - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "close"); return(FALSE); } @@ -825,7 +836,7 @@ os_file_flush( return(TRUE); } - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "flush"); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -858,7 +869,7 @@ os_file_flush( fprintf(stderr, " InnoDB: Error: the OS said file flush did not succeed\n"); - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "flush"); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -1099,7 +1110,7 @@ try_again: #ifdef __WIN__ error_handling: #endif - retry = os_file_handle_error(file, NULL); + retry = os_file_handle_error(file, NULL, "read"); if (retry) { goto try_again; @@ -2014,7 +2025,7 @@ try_again: os_aio_array_free_slot(array, slot); - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, "aio"); if (retry) { @@ -2113,7 +2124,7 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } } else { - os_file_handle_error(slot->file, slot->name); + os_file_handle_error(slot->file, slot->name, "aio"); ret_val = FALSE; } diff --git a/mysql-test/r/err000001.result b/mysql-test/r/errors.result similarity index 100% rename from mysql-test/r/err000001.result rename to mysql-test/r/errors.result diff --git a/mysql-test/t/err000001.test b/mysql-test/t/err000001.test deleted file mode 100644 index d9898054a83..00000000000 --- a/mysql-test/t/err000001.test +++ /dev/null @@ -1,19 +0,0 @@ -# -# Test some error conditions -# - -drop table if exists t1; -!$1146 insert into t1 values(1); -!$1146 delete from t1; -!$1146 update t1 set a=1; -create table t1 (a int); -!$1054 select count(test.t1.b) from t1; -!$1109 select count(not_existing_database.t1) from t1; -!$1109 select count(not_existing_database.t1.a) from t1; ---error 1044,1146 -select count(not_existing_database.t1.a) from not_existing_database.t1; -!$1054 select 1 from t1 order by 2; -!$1054 select 1 from t1 group by 2; -!$1054 select 1 from t1 order by t1.b; -!$1054 select count(*),b from t1; -drop table t1; diff --git a/mysql-test/t/errors.test b/mysql-test/t/errors.test new file mode 100644 index 00000000000..afb0cce9005 --- /dev/null +++ b/mysql-test/t/errors.test @@ -0,0 +1,32 @@ +# +# Test some error conditions +# + +drop table if exists t1; +--error 1146 +insert into t1 values(1); +--error 1146 +delete from t1; +--error 1146 +update t1 set a=1; + +# + +create table t1 (a int); +--error 1054 +select count(test.t1.b) from t1; +--error 1109 +select count(not_existing_database.t1) from t1; +--error 1109 + select count(not_existing_database.t1.a) from t1; +--error 1044,1146 +select count(not_existing_database.t1.a) from not_existing_database.t1; +--error 1054 +select 1 from t1 order by 2; +--error 1054 +select 1 from t1 group by 2; +--error 1054 +select 1 from t1 order by t1.b; +--error 1054 +select count(*),b from t1; +drop table t1; diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index ca8e4e8bcb6..a2647ec7399 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -38,20 +38,21 @@ #endif static int alarm_aborted=1; /* No alarm thread */ -my_bool thr_alarm_inited=0; +my_bool thr_alarm_inited= 0; +volatile my_bool alarm_thread_running= 0; static sig_handler process_alarm_part2(int sig); #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) static pthread_mutex_t LOCK_alarm; +static pthread_cond_t COND_alarm; static sigset_t full_signal_set; static QUEUE alarm_queue; static uint max_used_alarms=0; pthread_t alarm_thread; #ifdef USE_ALARM_THREAD -static pthread_cond_t COND_alarm; static void *alarm_handler(void *arg); #define reschedule_alarms() pthread_cond_signal(&COND_alarm) #else @@ -78,6 +79,7 @@ void init_thr_alarm(uint max_alarms) compare_ulong,NullS); sigfillset(&full_signal_set); /* Neaded to block signals */ pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); + pthread_cond_init(&COND_alarm,NULL); #if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) #if defined(HAVE_mit_thread) sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */ @@ -97,7 +99,6 @@ void init_thr_alarm(uint max_alarms) { pthread_attr_t thr_attr; pthread_attr_init(&thr_attr); - pthread_cond_init(&COND_alarm,NULL); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&thr_attr,8196); @@ -383,28 +384,45 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); - if (alarm_aborted != 1) + if (alarm_aborted != 1) /* If memory not freed */ { pthread_mutex_lock(&LOCK_alarm); DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); alarm_aborted= -1; /* mark aborted */ - if (pthread_equal(pthread_self(),alarm_thread)) - alarm(1); /* Shut down everything soon */ - else - reschedule_alarms(); + if (alarm_queue.elements || (alarm_thread_running && free_structures)) + { + if (pthread_equal(pthread_self(),alarm_thread)) + alarm(1); /* Shut down everything soon */ + else + reschedule_alarms(); + } if (free_structures) { + struct timespec abstime; /* The following test is just for safety, the caller should not depend on this */ DBUG_ASSERT(!alarm_queue.elements); + /* Wait until alarm thread dies */ + + set_timespec(abstime, 10); /* Wait up to 10 seconds */ + while (alarm_thread_running) + { + int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime); + if (error == ETIME || error == ETIMEDOUT) + break; /* Don't wait forever */ + } if (!alarm_queue.elements) { delete_queue(&alarm_queue); alarm_aborted= 1; pthread_mutex_unlock(&LOCK_alarm); - pthread_mutex_destroy(&LOCK_alarm); + if (!alarm_thread_running) /* Safety */ + { + pthread_mutex_destroy(&LOCK_alarm); + pthread_cond_destroy(&COND_alarm); + } } } else @@ -490,6 +508,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) puts("Starting alarm thread"); #endif my_thread_init(); + alarm_thread_running= 1; pthread_mutex_lock(&LOCK_alarm); for (;;) { @@ -514,7 +533,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) } } } - else if (alarm_aborted) + else if (alarm_aborted == -1) break; else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm))) { @@ -526,6 +545,8 @@ static void *alarm_handler(void *arg __attribute__((unused))) process_alarm(0); } bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */ + alarm_thread_running= 0; + pthread_cond_signal(&COND_alarm); pthread_mutex_unlock(&LOCK_alarm); pthread_exit(0); return 0; /* Impossible */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c2ee940af49..1492d6ddb68 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1520,7 +1520,6 @@ the problem, but since we have already crashed, something is definitely wrong\n\ and this may fail.\n\n"); fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size); fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size); - fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size); fprintf(stderr, "max_used_connections=%ld\n", max_used_connections); fprintf(stderr, "max_connections=%ld\n", max_connections); fprintf(stderr, "threads_connected=%d\n", thread_count); @@ -1528,7 +1527,7 @@ and this may fail.\n\n"); key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\ bytes of memory\n", ((ulong) keybuff_size + (global_system_variables.read_buff_size + - thd->variables.sortbuff_size) * + global_system_variables.sortbuff_size) * max_connections)/ 1024); fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n"); @@ -1557,14 +1556,9 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n", Some pointers may be invalid and cause the dump to abort...\n"); safe_print_str("thd->query", thd->query, 1024); fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id); - fprintf(stderr, "\n\ -Successfully dumped variables, if you ran with --log, take a look at the\n\ -details of what thread %ld did to cause the crash. In some cases of really\n\ -bad corruption, the values shown above may be invalid.\n\n", - thd->thread_id); } fprintf(stderr, "\ -The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\ +The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\ information that should help you find out what is causing the crash.\n"); fflush(stderr); #endif /* HAVE_STACKTRACE */ @@ -1639,6 +1633,7 @@ static void init_signals(void) sigaddset(&set,SIGHUP); /* Fix signals if blocked by parents (can happen on Mac OS X) */ + sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = print_signal_warning; sigaction(SIGTERM, &sa, (struct sigaction*) 0); @@ -2279,7 +2274,7 @@ int main(int argc, char **argv) #endif /* init_slave() must be called after the thread keys are created */ init_slave(); - + DBUG_ASSERT(current_thd == 0); if (opt_bin_log && !server_id) { @@ -2307,7 +2302,6 @@ The server will not act as a slave."); using_update_log=1; } - if (opt_bootstrap) { int error=bootstrap(stdin); From 31121b36b61f7c41545b5c3d537b200bd66f33cd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2003 14:12:46 +0500 Subject: [PATCH 287/399] ctype-ucs2.c: define ILSEQ for platforms that do not define it themself strings/ctype-ucs2.c: define ILSEQ for platforms that do not define it themself --- strings/ctype-ucs2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 17bc920a381..8cb8f84f281 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -25,6 +25,10 @@ #ifdef HAVE_CHARSET_ucs2 +#ifndef EILSEQ +#define EILSEQ ENOENT +#endif + extern MY_UNICASE_INFO *uni_plane[256]; static uchar ctype_ucs2[] = { From 0ae3a4dcc134e97e48d266d4d1260d6c8c268659 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2003 13:11:20 +0300 Subject: [PATCH 288/399] os0thread.h, os0sync.ic, os0sync.h, os0thread.c, os0sync.c, os0file.c: Release all event semaphores at shutdown also in Windows srv0start.c, srv0srv.c: make test sometimes failed because lock timeout thread exited without decrementing the InnoDB thread counter innobase/srv/srv0srv.c: make test sometimes failed because lock timeout thread exited without decrementing the InnoDB thread counter innobase/srv/srv0start.c: make test sometimes failed because lock timeout thread exited without decrementing the InnoDB thread counter innobase/os/os0file.c: Release all event semaphores at shutdown also in Windows innobase/os/os0sync.c: Release all event semaphores at shutdown also in Windows innobase/os/os0thread.c: Release all event semaphores at shutdown also in Windows innobase/include/os0sync.h: Release all event semaphores at shutdown also in Windows innobase/include/os0sync.ic: Release all event semaphores at shutdown also in Windows innobase/include/os0thread.h: Release all event semaphores at shutdown also in Windows --- innobase/include/os0sync.h | 51 +++++---- innobase/include/os0sync.ic | 1 - innobase/include/os0thread.h | 4 +- innobase/os/os0file.c | 83 +++++++-------- innobase/os/os0sync.c | 196 ++++++++++++++++------------------- innobase/os/os0thread.c | 4 + innobase/srv/srv0srv.c | 44 +++++++- innobase/srv/srv0start.c | 32 ++++-- 8 files changed, 240 insertions(+), 175 deletions(-) diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h index bad8e6e120a..634507467f9 100644 --- a/innobase/include/os0sync.h +++ b/innobase/include/os0sync.h @@ -13,13 +13,26 @@ Created 9/6/1995 Heikki Tuuri #include "ut0lst.h" #ifdef __WIN__ + #define os_fast_mutex_t CRITICAL_SECTION -typedef HANDLE os_event_t; + +typedef HANDLE os_native_event_t; + +typedef struct os_event_struct os_event_struct_t; +typedef os_event_struct_t* os_event_t; + +struct os_event_struct { + os_native_event_t handle; + /* Windows event */ + UT_LIST_NODE_T(os_event_struct_t) os_event_list; + /* list of all created events */ +}; #else typedef pthread_mutex_t os_fast_mutex_t; typedef struct os_event_struct os_event_struct_t; typedef os_event_struct_t* os_event_t; + struct os_event_struct { os_fast_mutex_t os_mutex; /* this mutex protects the next fields */ @@ -39,16 +52,16 @@ typedef os_mutex_str_t* os_mutex_t; #define OS_SYNC_TIME_EXCEEDED 1 -/* Mutex protecting the thread count and event and OS 'slow' mutex lists */ +/* Mutex protecting counts and the event and OS 'slow' mutex lists */ extern os_mutex_t os_sync_mutex; /* This is incremented by 1 in os_thread_create and decremented by 1 in os_thread_exit */ extern ulint os_thread_count; -/* The following are approximate counters for debugging in Unix */ extern ulint os_event_count; extern ulint os_mutex_count; +extern ulint os_fast_mutex_count; /************************************************************* Initializes global event and OS 'slow' mutex lists. */ @@ -57,15 +70,14 @@ void os_sync_init(void); /*==============*/ /************************************************************* -Frees created events (not in Windows) and OS 'slow' mutexes. */ +Frees created events and OS 'slow' mutexes. */ void os_sync_free(void); /*==============*/ -/************************************************************* -Creates an event semaphore, i.e., a semaphore which may -just have two states: signaled and nonsignaled. -The created event is manual reset: it must be reset +/************************************************************* +Creates an event semaphore, i.e., a semaphore which may just have two states: +signaled and nonsignaled. The created event is manual reset: it must be reset explicitly by calling sync_os_reset_event. */ os_event_t @@ -74,10 +86,10 @@ os_event_create( /* out: the event handle */ char* name); /* in: the name of the event, if NULL the event is created without a name */ +#ifdef __WIN__ /************************************************************* -Creates an auto-reset event semaphore, i.e., an event -which is automatically reset when a single thread is -released. */ +Creates an auto-reset event semaphore, i.e., an event which is automatically +reset when a single thread is released. Works only in Windows. */ os_event_t os_event_create_auto( @@ -85,6 +97,7 @@ os_event_create_auto( /* out: the event handle */ char* name); /* in: the name of the event, if NULL the event is created without a name */ +#endif /************************************************************** Sets an event semaphore to the signaled state: lets waiting threads proceed. */ @@ -120,7 +133,7 @@ os_event_wait( os_event_t event); /* in: event to wait */ /************************************************************** Waits for an event object until it is in the signaled state or -a timeout is exceeded. */ +a timeout is exceeded. In Unix the timeout is always infinite. */ ulint os_event_wait_time( @@ -131,8 +144,9 @@ os_event_wait_time( os_event_t event, /* in: event to wait */ ulint time); /* in: timeout in microseconds, or OS_SYNC_INFINITE_TIME */ +#ifdef __WIN__ /************************************************************** -Waits for any event in an event array. Returns if even a single +Waits for any event in an OS native event array. Returns if even a single one is signaled or becomes signaled. */ ulint @@ -140,14 +154,15 @@ os_event_wait_multiple( /*===================*/ /* out: index of the event which was signaled */ - ulint n, /* in: number of events in the + ulint n, /* in: number of events in the array */ - os_event_t* event_array); /* in: pointer to an array of event + os_native_event_t* native_event_array); + /* in: pointer to an array of event handles */ +#endif /************************************************************* -Creates an operating system mutex semaphore. -Because these are slow, the mutex semaphore of the database -itself (sync_mutex_t) should be used where possible. */ +Creates an operating system mutex semaphore. Because these are slow, the +mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */ os_mutex_t os_mutex_create( diff --git a/innobase/include/os0sync.ic b/innobase/include/os0sync.ic index 10b85c435e3..1337e97152a 100644 --- a/innobase/include/os0sync.ic +++ b/innobase/include/os0sync.ic @@ -44,4 +44,3 @@ os_fast_mutex_trylock( #endif #endif } - diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h index 92187f315c2..491d8866af4 100644 --- a/innobase/include/os0thread.h +++ b/innobase/include/os0thread.h @@ -65,7 +65,9 @@ os_thread_pf( /******************************************************************** Creates a new thread of execution. The execution starts from the function given. The start function takes a void* parameter -and returns a ulint. */ +and returns a ulint. +NOTE: We count the number of threads in os_thread_exit(). A created +thread should always use that to exit and not use return() to exit. */ os_thread_t os_thread_create( diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 00e29121ece..eaea6688462 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -80,6 +80,8 @@ struct os_aio_slot_struct{ which pending aio operation was completed */ #ifdef WIN_ASYNC_IO + os_event_t event; /* event object we need in the + OVERLAPPED struct */ OVERLAPPED control; /* Windows control block for the aio request */ #elif defined(POSIX_ASYNC_IO) @@ -107,11 +109,14 @@ struct os_aio_array_struct{ ulint n_reserved;/* Number of reserved slots in the aio array outside the ibuf segment */ os_aio_slot_t* slots; /* Pointer to the slots in the array */ - os_event_t* events; /* Pointer to an array of event handles - where we copied the handles from slots, - in the same order. This can be used in - WaitForMultipleObjects; used only in +#ifdef __WIN__ + os_native_event_t* native_events; + /* Pointer to an array of OS native event + handles where we copied the handles from + slots, in the same order. This can be used + in WaitForMultipleObjects; used only in Windows */ +#endif }; /* Array of events used in simulated aio */ @@ -295,8 +300,7 @@ os_file_handle_error( /* out: TRUE if we should retry the operation */ os_file_t file, /* in: file pointer */ - char* name, /* in: name of a file or NULL */ - const char* operation) /* in: type of operation */ + char* name) /* in: name of a file or NULL */ { ulint err; @@ -338,8 +342,7 @@ os_file_handle_error( if (name) { fprintf(stderr, "InnoDB: File name %s\n", name); } - fprintf(stderr, "InnoDB: system call %s\n", operation); - + fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fflush(stderr); @@ -421,9 +424,7 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name, - create_mode == OS_FILE_OPEN ? - "open" : "create"); + retry = os_file_handle_error(file, name); if (retry) { goto try_again; @@ -464,10 +465,7 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name, - create_mode == OS_FILE_OPEN ? - "open" : "create"); - + retry = os_file_handle_error(file, name); if (retry) { goto try_again; @@ -575,9 +573,7 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name, - create_mode == OS_FILE_OPEN ? - "open" : "create"); + retry = os_file_handle_error(file, name); if (retry) { goto try_again; @@ -624,9 +620,7 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name, - create_mode == OS_FILE_OPEN ? - "open" : "create"); + retry = os_file_handle_error(file, name); if (retry) { goto try_again; @@ -660,7 +654,7 @@ os_file_close( return(TRUE); } - os_file_handle_error(file, NULL, "close"); + os_file_handle_error(file, NULL); return(FALSE); #else int ret; @@ -668,7 +662,7 @@ os_file_close( ret = close(file); if (ret == -1) { - os_file_handle_error(file, NULL, "close"); + os_file_handle_error(file, NULL); return(FALSE); } @@ -836,7 +830,7 @@ os_file_flush( return(TRUE); } - os_file_handle_error(file, NULL, "flush"); + os_file_handle_error(file, NULL); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -869,7 +863,7 @@ os_file_flush( fprintf(stderr, " InnoDB: Error: the OS said file flush did not succeed\n"); - os_file_handle_error(file, NULL, "flush"); + os_file_handle_error(file, NULL); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -1110,7 +1104,7 @@ try_again: #ifdef __WIN__ error_handling: #endif - retry = os_file_handle_error(file, NULL, "read"); + retry = os_file_handle_error(file, NULL); if (retry) { goto try_again; @@ -1319,19 +1313,22 @@ os_aio_array_create( array->n_segments = n_segments; array->n_reserved = 0; array->slots = ut_malloc(n * sizeof(os_aio_slot_t)); - array->events = ut_malloc(n * sizeof(os_event_t)); - +#ifdef __WIN__ + array->native_events = ut_malloc(n * sizeof(os_native_event_t)); +#endif for (i = 0; i < n; i++) { slot = os_aio_array_get_nth_slot(array, i); slot->pos = i; slot->reserved = FALSE; #ifdef WIN_ASYNC_IO + slot->event = os_event_create(NULL); + over = &(slot->control); - over->hEvent = os_event_create(NULL); + over->hEvent = slot->event->handle; - *((array->events) + i) = over->hEvent; + *((array->native_events) + i) = over->hEvent; #endif } @@ -1429,7 +1426,7 @@ os_aio_array_wake_win_aio_at_shutdown( for (i = 0; i < array->n_slots; i++) { - os_event_set(*(array->events + i)); + os_event_set((array->slots + i)->event); } } #endif @@ -1689,7 +1686,7 @@ loop: control = &(slot->control); control->Offset = (DWORD)offset; control->OffsetHigh = (DWORD)offset_high; - os_event_reset(control->hEvent); + os_event_reset(slot->event); #elif defined(POSIX_ASYNC_IO) @@ -1747,7 +1744,7 @@ os_aio_array_free_slot( } #ifdef WIN_ASYNC_IO - os_event_reset(slot->control.hEvent); + os_event_reset(slot->event); #endif os_mutex_exit(array->mutex); } @@ -1916,7 +1913,8 @@ os_aio( wait in the Windows case. */ if (type == OS_FILE_READ) { - return(os_file_read(file, buf, offset, offset_high, n)); + return(os_file_read(file, buf, offset, + offset_high, n)); } ut_a(type == OS_FILE_WRITE); @@ -1994,8 +1992,7 @@ try_again: #ifdef WIN_ASYNC_IO if (os_aio_use_native_aio) { if ((ret && len == n) - || (!ret && GetLastError() == ERROR_IO_PENDING)) { - + || (!ret && GetLastError() == ERROR_IO_PENDING)) { /* aio was queued successfully! */ if (mode == OS_AIO_SYNC) { @@ -2025,7 +2022,7 @@ try_again: os_aio_array_free_slot(array, slot); - retry = os_file_handle_error(file, name, "aio"); + retry = os_file_handle_error(file, name); if (retry) { @@ -2091,15 +2088,15 @@ os_aio_windows_handle( n = array->n_slots / array->n_segments; if (array == os_aio_sync_array) { - srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page"; - - ut_ad(pos < array->n_slots); - os_event_wait(array->events[pos]); + srv_io_thread_op_info[orig_seg] = + "wait Windows aio for 1 page"; + os_event_wait(os_aio_array_get_nth_slot(array, pos)->event); i = pos; } else { srv_io_thread_op_info[orig_seg] = "wait Windows aio"; - i = os_event_wait_multiple(n, (array->events) + segment * n); + i = os_event_wait_multiple(n, + (array->native_events) + segment * n); } os_mutex_enter(array->mutex); @@ -2124,7 +2121,7 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } } else { - os_file_handle_error(slot->file, slot->name, "aio"); + os_file_handle_error(slot->file, slot->name); ret_val = FALSE; } diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 4f322ee82b2..0fe61fe570d 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -32,24 +32,23 @@ struct os_mutex_struct{ /* list of all 'slow' OS mutexes created */ }; -/* Mutex protecting the thread count and the lists of OS mutexes -and events */ +/* Mutex protecting counts and the lists of OS mutexes and events */ os_mutex_t os_sync_mutex; ibool os_sync_mutex_inited = FALSE; /* This is incremented by 1 in os_thread_create and decremented by 1 in os_thread_exit */ -ulint os_thread_count = 0; +ulint os_thread_count = 0; -/* The list of all events created (not in Windows) */ +/* The list of all events created */ UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list; /* The list of all OS 'slow' mutexes */ UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list; -/* The following are approximate counters for debugging in Unix */ -ulint os_event_count = 0; -ulint os_mutex_count = 0; +ulint os_event_count = 0; +ulint os_mutex_count = 0; +ulint os_fast_mutex_count = 0; /************************************************************* @@ -68,7 +67,7 @@ os_sync_init(void) } /************************************************************* -Frees created events (not in Windows) and OS 'slow' mutexes. */ +Frees created events and OS 'slow' mutexes. */ void os_sync_free(void) @@ -97,10 +96,9 @@ os_sync_free(void) } /************************************************************* -Creates an event semaphore, i.e., a semaphore which may -just have two states: signaled and nonsignaled. -The created event is manual reset: it must be reset -explicitly by calling sync_os_reset_event. */ +Creates an event semaphore, i.e., a semaphore which may just have two +states: signaled and nonsignaled. The created event is manual reset: it +must be reset explicitly by calling sync_os_reset_event. */ os_event_t os_event_create( @@ -112,20 +110,18 @@ os_event_create( #ifdef __WIN__ os_event_t event; - event = CreateEvent(NULL, /* No security attributes */ + event = ut_malloc(sizeof(struct os_event_struct)); + + event->handle = CreateEvent(NULL,/* No security attributes */ TRUE, /* Manual reset */ FALSE, /* Initial state nonsignaled */ name); - if (!event) { + if (!event->handle) { fprintf(stderr, "InnoDB: Could not create a Windows event semaphore; Windows error %lu\n", (ulint)GetLastError()); } - - ut_a(event); - - return(event); -#else +#else /* Unix */ os_event_t event; UT_NOT_USED(name); @@ -141,7 +137,9 @@ os_event_create( ut_a(0 == pthread_cond_init(&(event->cond_var), NULL)); #endif event->is_set = FALSE; +#endif /* __WIN__ */ + /* Put to the list of events */ os_mutex_enter(os_sync_mutex); UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); @@ -151,13 +149,12 @@ os_event_create( os_mutex_exit(os_sync_mutex); return(event); -#endif } +#ifdef __WIN__ /************************************************************* -Creates an auto-reset event semaphore, i.e., an event -which is automatically reset when a single thread is -released. */ +Creates an auto-reset event semaphore, i.e., an event which is automatically +reset when a single thread is released. Works only in Windows. */ os_event_t os_event_create_auto( @@ -166,26 +163,33 @@ os_event_create_auto( char* name) /* in: the name of the event, if NULL the event is created without a name */ { -#ifdef __WIN__ os_event_t event; - event = CreateEvent(NULL, /* No security attributes */ + event = ut_malloc(sizeof(struct os_event_struct)); + + event->handle = CreateEvent(NULL,/* No security attributes */ FALSE, /* Auto-reset */ FALSE, /* Initial state nonsignaled */ name); - ut_a(event); + + if (!event->handle) { + fprintf(stderr, +"InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n", + (ulint)GetLastError()); + } + + /* Put to the list of events */ + os_mutex_enter(os_sync_mutex); + + UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); + + os_event_count++; + + os_mutex_exit(os_sync_mutex); return(event); -#else - /* Does nothing in Posix because we do not need this with MySQL */ - - UT_NOT_USED(name); - - ut_a(0); - - return(NULL); -#endif } +#endif /************************************************************** Sets an event semaphore to the signaled state: lets waiting threads @@ -198,7 +202,7 @@ os_event_set( { #ifdef __WIN__ ut_a(event); - ut_a(SetEvent(event)); + ut_a(SetEvent(event->handle)); #else ut_a(event); @@ -227,7 +231,7 @@ os_event_reset( #ifdef __WIN__ ut_a(event); - ut_a(ResetEvent(event)); + ut_a(ResetEvent(event->handle)); #else ut_a(event); @@ -255,12 +259,14 @@ os_event_free( #ifdef __WIN__ ut_a(event); - ut_a(CloseHandle(event)); + ut_a(CloseHandle(event->handle)); #else ut_a(event); os_fast_mutex_free(&(event->os_mutex)); ut_a(0 == pthread_cond_destroy(&(event->cond_var))); +#endif + /* Remove from the list of events */ os_mutex_enter(os_sync_mutex); @@ -271,7 +277,6 @@ os_event_free( os_mutex_exit(os_sync_mutex); ut_free(event); -#endif } /************************************************************** @@ -291,7 +296,7 @@ os_event_wait( ut_a(event); /* Specify an infinite time limit for waiting */ - err = WaitForSingleObject(event, INFINITE); + err = WaitForSingleObject(event->handle, INFINITE); ut_a(err == WAIT_OBJECT_0); @@ -324,7 +329,7 @@ loop: /************************************************************** Waits for an event object until it is in the signaled state or -a timeout is exceeded. */ +a timeout is exceeded. In Unix the timeout is always infinite. */ ulint os_event_wait_time( @@ -341,9 +346,9 @@ os_event_wait_time( ut_a(event); if (time != OS_SYNC_INFINITE_TIME) { - err = WaitForSingleObject(event, time / 1000); + err = WaitForSingleObject(event->handle, time / 1000); } else { - err = WaitForSingleObject(event, INFINITE); + err = WaitForSingleObject(event->handle, INFINITE); } if (err == WAIT_OBJECT_0) { @@ -367,8 +372,9 @@ os_event_wait_time( #endif } +#ifdef __WIN__ /************************************************************** -Waits for any event in an event array. Returns if even a single +Waits for any event in an OS native event array. Returns if even a single one is signaled or becomes signaled. */ ulint @@ -376,18 +382,18 @@ os_event_wait_multiple( /*===================*/ /* out: index of the event which was signaled */ - ulint n, /* in: number of events in the + ulint n, /* in: number of events in the array */ - os_event_t* event_array) /* in: pointer to an array of event + os_native_event_t* native_event_array) + /* in: pointer to an array of event handles */ { -#ifdef __WIN__ DWORD index; - ut_a(event_array); + ut_a(native_event_array); ut_a(n > 0); - index = WaitForMultipleObjects(n, event_array, + index = WaitForMultipleObjects(n, native_event_array, FALSE, /* Wait for any 1 event */ INFINITE); /* Infinite wait time limit */ @@ -399,21 +405,12 @@ os_event_wait_multiple( } return(index - WAIT_OBJECT_0); -#else - ut_a(n == 0); - - /* In Posix we can only wait for a single event */ - - os_event_wait(*event_array); - - return(0); -#endif } +#endif /************************************************************* -Creates an operating system mutex semaphore. -Because these are slow, the mutex semaphore of the database -itself (sync_mutex_t) should be used where possible. */ +Creates an operating system mutex semaphore. Because these are slow, the +mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */ os_mutex_t os_mutex_create( @@ -430,50 +427,35 @@ os_mutex_create( FALSE, /* Initial state: no owner */ name); ut_a(mutex); +#else + os_fast_mutex_t* mutex; + os_mutex_t mutex_str; + UT_NOT_USED(name); + + mutex = ut_malloc(sizeof(os_fast_mutex_t)); + + os_fast_mutex_init(mutex); +#endif mutex_str = ut_malloc(sizeof(os_mutex_str_t)); mutex_str->handle = mutex; mutex_str->count = 0; if (os_sync_mutex_inited) { + /* When creating os_sync_mutex itself we cannot reserve it */ os_mutex_enter(os_sync_mutex); } UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); + os_mutex_count++; + if (os_sync_mutex_inited) { os_mutex_exit(os_sync_mutex); } return(mutex_str); -#else - os_fast_mutex_t* os_mutex; - os_mutex_t mutex_str; - - UT_NOT_USED(name); - - os_mutex = ut_malloc(sizeof(os_fast_mutex_t)); - - os_fast_mutex_init(os_mutex); - - mutex_str = ut_malloc(sizeof(os_mutex_str_t)); - - mutex_str->handle = os_mutex; - mutex_str->count = 0; - - if (os_sync_mutex_inited) { - os_mutex_enter(os_sync_mutex); - } - - UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); - - if (os_sync_mutex_inited) { - os_mutex_exit(os_sync_mutex); - } - - return(mutex_str); -#endif } /************************************************************** @@ -513,21 +495,14 @@ os_mutex_exit( /*==========*/ os_mutex_t mutex) /* in: mutex to release */ { -#ifdef __WIN__ ut_a(mutex); ut_a(mutex->count == 1); (mutex->count)--; - +#ifdef __WIN__ ut_a(ReleaseMutex(mutex->handle)); #else - ut_a(mutex); - - ut_a(mutex->count == 1); - - (mutex->count)--; - os_fast_mutex_unlock(mutex->handle); #endif } @@ -540,25 +515,21 @@ os_mutex_free( /*==========*/ os_mutex_t mutex) /* in: mutex to free */ { -#ifdef __WIN__ ut_a(mutex); os_mutex_enter(os_sync_mutex); UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); + + os_mutex_count--; os_mutex_exit(os_sync_mutex); +#ifdef __WIN__ ut_a(CloseHandle(mutex->handle)); ut_free(mutex); #else - os_mutex_enter(os_sync_mutex); - - UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); - - os_mutex_exit(os_sync_mutex); - os_fast_mutex_free(mutex->handle); ut_free(mutex->handle); ut_free(mutex); @@ -583,8 +554,19 @@ os_fast_mutex_init( #else ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); #endif - os_mutex_count++; #endif + if (os_sync_mutex_inited) { + /* When creating os_sync_mutex itself (in Unix) we cannot + reserve it */ + + os_mutex_enter(os_sync_mutex); + } + + os_fast_mutex_count++; + + if (os_sync_mutex_inited) { + os_mutex_exit(os_sync_mutex); + } } /************************************************************** @@ -631,6 +613,10 @@ os_fast_mutex_free( DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else ut_a(0 == pthread_mutex_destroy(fast_mutex)); - os_mutex_count--; #endif + os_mutex_enter(os_sync_mutex); + + os_fast_mutex_count--; + + os_mutex_exit(os_sync_mutex); } diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c index 02ea2c227a7..9af98760ad1 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -186,6 +186,10 @@ os_thread_exit( void* exit_value) /* in: exit value; in Windows this void* is cast as a DWORD */ { +#ifdef UNIV_DEBUG_THREAD_CREATION + printf("A thread exits.\n"); + printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id())); +#endif os_mutex_enter(os_sync_mutex); os_thread_count--; os_mutex_exit(os_sync_mutex); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index da2966a7124..2a93ca966eb 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -856,6 +856,7 @@ srv_release_max_if_no_queries(void) mutex_exit(&kernel_mutex); } +#ifdef notdefined /*********************************************************************** Releases one utility thread if no queries are active and the high-water mark 2 for the utility is exceeded. */ @@ -890,7 +891,6 @@ srv_release_one_if_no_queries(void) mutex_exit(&kernel_mutex); } -#ifdef notdefined /*********************************************************************** Decrements the utility meter by the value given and suspends the calling thread, which must be an utility thread of the type given, if necessary. */ @@ -1000,6 +1000,8 @@ srv_communication_init( ut_a(ret == 0); } + +#ifdef notdefined /************************************************************************* Implements the recovery utility. */ @@ -1060,6 +1062,7 @@ srv_purge_thread( return(0); } +#endif /* notdefined */ /************************************************************************* Creates the utility threads. */ @@ -1090,6 +1093,7 @@ srv_create_utility_threads(void) ut_a(thread); */ } +#ifdef notdefined /************************************************************************* Implements the communication threads. */ static @@ -1139,6 +1143,7 @@ srv_com_thread( return(0); } +#endif /************************************************************************* Creates the communication threads. */ @@ -1159,6 +1164,7 @@ srv_create_com_threads(void) } } +#ifdef notdefined /************************************************************************* Implements the worker threads. */ static @@ -1203,6 +1209,7 @@ srv_worker_thread( return(0); } +#endif /************************************************************************* Creates the worker threads. */ @@ -2456,6 +2463,10 @@ srv_lock_timeout_and_monitor_thread( char* buf; ulint i; +#ifdef UNIV_DEBUG_THREAD_CREATION + printf("Lock timeout thread starts\n"); + printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id())); +#endif UT_NOT_USED(arg); srv_last_monitor_time = time(NULL); last_table_monitor_time = time(NULL); @@ -2596,6 +2607,10 @@ loop: exit_func: srv_lock_timeout_and_monitor_active = FALSE; + /* We count the number of threads in os_thread_exit(). A created + thread should always use that to exit and not use return() to exit. */ + + os_thread_exit(NULL); #ifndef __WIN__ return(NULL); #else @@ -2621,6 +2636,10 @@ srv_error_monitor_thread( ulint cnt = 0; UT_NOT_USED(arg); +#ifdef UNIV_DEBUG_THREAD_CREATION + printf("Error monitor thread starts\n"); + printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id())); +#endif loop: srv_error_monitor_active = TRUE; @@ -2657,6 +2676,9 @@ loop: srv_error_monitor_active = FALSE; + /* We count the number of threads in os_thread_exit(). A created + thread should always use that to exit and not use return() to exit. */ + os_thread_exit(NULL); #ifndef __WIN__ @@ -2737,6 +2759,10 @@ srv_master_thread( UT_NOT_USED(arg); +#ifdef UNIV_DEBUG_THREAD_CREATION + printf("Master thread starts\n"); + printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id())); +#endif srv_main_thread_process_no = os_proc_get_number(); srv_main_thread_id = os_thread_pf(os_thread_get_curr_id()); @@ -2972,6 +2998,15 @@ background_loop: n_tables_to_drop = row_drop_tables_for_mysql_in_background(); + if (n_tables_to_drop > 0) { + /* Do not monopolize the CPU even if there are tables waiting + in the background drop queue. (It is essentially a bug if + MySQL tries to drop a table while there are still open handles + to it and we had to put it to the background drop queue.) */ + + os_thread_sleep(100000); + } + srv_main_thread_op_info = (char*)"purging"; if (srv_fast_shutdown && srv_shutdown_state > 0) { @@ -3110,6 +3145,13 @@ suspend_thread: goto loop; + /* We count the number of threads in os_thread_exit(). A created + thread should always use that to exit and not use return() to exit. + The thread actually never comes here because it is exited in an + os_event_wait(). */ + + os_thread_exit(NULL); + #ifndef __WIN__ return(NULL); #else diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index f03355b825c..1f278d82bc0 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -414,8 +414,10 @@ io_handler_thread( segment = *((ulint*)arg); -/* printf("Io handler thread %lu starts\n", segment); */ - +#ifdef UNIV_DEBUG_THREAD_CREATION + printf("Io handler thread %lu starts\n", segment); + printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id())); +#endif for (i = 0;; i++) { fil_aio_wait(segment); @@ -424,6 +426,13 @@ io_handler_thread( mutex_exit(&ios_mutex); } + /* We count the number of threads in os_thread_exit(). A created + thread should always use that to exit and not use return() to exit. + The thread actually never comes here because it is exited in an + os_event_wait(). */ + + os_thread_exit(NULL); + #ifndef __WIN__ return(NULL); #else @@ -1546,21 +1555,32 @@ innobase_shutdown_for_mysql(void) os_thread_count); } - /* 3. Free all InnoDB's own mutexes */ + /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside + them */ sync_close(); - /* 4. Free all OS synchronization primitives (in Windows currently - events are not freed) */ + /* 4. Free the os_conc_mutex and all os_events and os_mutexes */ srv_free(); os_sync_free(); - /* 5. Free all allocated memory (and the os_fast_mutex created in + /* 5. Free all allocated memory and the os_fast_mutex created in ut0mem.c */ ut_free_all_mem(); + if (os_thread_count != 0 + || os_event_count != 0 + || os_mutex_count != 0 + || os_fast_mutex_count != 0) { + fprintf(stderr, +"InnoDB: Warning: some resources were not cleaned up in shutdown:\n" +"InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n", + os_thread_count, os_event_count, os_mutex_count, + os_fast_mutex_count); + } + if (srv_print_verbose_log) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Shutdown completed\n"); From 8f548eb1bb94ff9ca641b39a02cab2a7ecebf192 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2003 13:45:45 +0300 Subject: [PATCH 289/399] os0file.c: Put back Monty's patch which the previous push accidentally erased: print also operation type in os_file_handle_error() innobase/os/os0file.c: Put back Monty's patch which the previous push accidentally erased: print also operation type in os_file_handle_error() --- innobase/os/os0file.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index eaea6688462..2f32b9347dc 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -300,7 +300,8 @@ os_file_handle_error( /* out: TRUE if we should retry the operation */ os_file_t file, /* in: file pointer */ - char* name) /* in: name of a file or NULL */ + char* name, /* in: name of a file or NULL */ + const char* operation)/* in: operation */ { ulint err; @@ -343,6 +344,7 @@ os_file_handle_error( fprintf(stderr, "InnoDB: File name %s\n", name); } + fprintf(stderr, "InnoDB: System call %s.\n", operation); fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fflush(stderr); @@ -424,8 +426,9 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name); - + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; } @@ -465,8 +468,9 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name); - + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; } @@ -573,8 +577,9 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name); - + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; } @@ -620,8 +625,9 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name); - + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; } @@ -654,7 +660,7 @@ os_file_close( return(TRUE); } - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "close"); return(FALSE); #else int ret; @@ -662,7 +668,7 @@ os_file_close( ret = close(file); if (ret == -1) { - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "close"); return(FALSE); } @@ -830,7 +836,7 @@ os_file_flush( return(TRUE); } - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "flush"); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -863,7 +869,7 @@ os_file_flush( fprintf(stderr, " InnoDB: Error: the OS said file flush did not succeed\n"); - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "flush"); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -1104,7 +1110,7 @@ try_again: #ifdef __WIN__ error_handling: #endif - retry = os_file_handle_error(file, NULL); + retry = os_file_handle_error(file, NULL, "read"); if (retry) { goto try_again; @@ -1869,7 +1875,7 @@ os_aio( offset where to read or write */ ulint offset_high, /* in: most significant 32 bits of offset */ - ulint n, /* in: number of bytes to read or write */ + ulint n, /* in: number of bytes to read or write */ void* message1,/* in: messages for the aio handler (these can be used to identify a completed aio operation); if mode is OS_AIO_SYNC, these @@ -2022,8 +2028,8 @@ try_again: os_aio_array_free_slot(array, slot); - retry = os_file_handle_error(file, name); - + retry = os_file_handle_error(file, name, + type == OS_FILE_READ ? "aio read" : "aio write"); if (retry) { goto try_again; @@ -2121,7 +2127,7 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } } else { - os_file_handle_error(slot->file, slot->name); + os_file_handle_error(slot->file, slot->name, "Windows aio"); ret_val = FALSE; } From 4beedd513eecdc4f57715112c1496e976a2f079c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2003 17:19:06 +0500 Subject: [PATCH 290/399] "Collation" has been moved to SHOW FULL FIELDS SHOW COLLATION columns have been removed: D -> Default C -> Compiled Y -> Yes --- mysql-test/r/alter_table.result | 6 +-- mysql-test/r/create.result | 38 ++++++------- mysql-test/r/ctype_collate.result | 12 ++--- mysql-test/r/ctype_recoding.result | 12 ++--- mysql-test/r/gis.result | 86 +++++++++++++++--------------- mysql-test/r/have_ucs2.require | 4 +- mysql-test/r/have_ujis.require | 4 +- mysql-test/r/innodb.result | 4 +- mysql-test/r/show_check.result | 32 +++++------ mysql-test/r/type_blob.result | 20 +++---- sql/sql_show.cc | 14 ++--- 11 files changed, 117 insertions(+), 115 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 7bd836acefd..6c5e06a289f 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -156,9 +156,9 @@ create table t1 (i int unsigned not null auto_increment primary key); alter table t1 rename t2; alter table t2 rename t1, add c char(10) comment "no comment"; show columns from t1; -Field Type Collation Null Key Default Extra -i int(10) unsigned NULL PRI NULL auto_increment -c char(10) latin1_swedish_ci YES NULL +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); diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index bd8343428c2..45b37dfb719 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -82,37 +82,37 @@ drop table t1,t2; create table t1(x varchar(50) ); create table t2 select x from t1 where 1=2; describe t1; -Field Type Collation Null Key Default Extra -x varchar(50) latin1_swedish_ci YES NULL +Field Type Null Key Default Extra +x varchar(50) YES NULL describe t2; -Field Type Collation Null Key Default Extra -x char(50) latin1_swedish_ci YES NULL +Field Type Null Key Default Extra +x char(50) YES NULL drop table t2; create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f; describe t2; -Field Type Collation Null Key Default Extra -a datetime NULL 0000-00-00 00:00:00 -b time NULL 00:00:00 -c date NULL 0000-00-00 -d bigint(17) NULL 0 -e double(18,1) NULL 0.0 -f bigint(17) NULL 0 +Field Type Null Key Default Extra +a datetime 0000-00-00 00:00:00 +b time 00:00:00 +c date 0000-00-00 +d bigint(17) 0 +e double(18,1) 0.0 +f bigint(17) 0 drop table t2; create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt; describe t2; -Field Type Collation Null Key Default Extra -d date NULL 0000-00-00 -t time NULL 00:00:00 -dt datetime NULL 0000-00-00 00:00:00 +Field Type Null Key Default Extra +d date 0000-00-00 +t time 00:00:00 +dt datetime 0000-00-00 00:00:00 drop table t1,t2; create table t1 (a tinyint); create table t2 (a int) select * from t1; describe t1; -Field Type Collation Null Key Default Extra -a tinyint(4) NULL YES NULL +Field Type Null Key Default Extra +a tinyint(4) YES NULL describe t2; -Field Type Collation Null Key Default Extra -a int(11) NULL YES NULL +Field Type Null Key Default Extra +a int(11) YES NULL drop table if exists t2; create table t2 (a int, a float) select * from t1; Duplicate column name 'a' diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result index d2ae3950eaf..00a642d9ee6 100644 --- a/mysql-test/r/ctype_collate.result +++ b/mysql-test/r/ctype_collate.result @@ -489,8 +489,8 @@ t1 CREATE TABLE `t1` ( `latin1_f` char(32) NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM t1; -Field Type Collation Null Key Default Extra -latin1_f char(32) latin1_swedish_ci +Field Type Null Key Default Extra +latin1_f char(32) ALTER TABLE t1 CHANGE latin1_f latin1_f CHAR(32) CHARACTER SET latin1 COLLATE latin1_bin; SHOW CREATE TABLE t1; @@ -499,8 +499,8 @@ t1 CREATE TABLE `t1` ( `latin1_f` char(32) character set latin1 collate latin1_bin default NULL ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM t1; -Field Type Collation Null Key Default Extra -latin1_f char(32) latin1_bin YES NULL +Field Type Null Key Default Extra +latin1_f char(32) YES NULL ALTER TABLE t1 CHARACTER SET latin1 COLLATE latin1_bin; SHOW CREATE TABLE t1; Table Create Table @@ -508,8 +508,8 @@ t1 CREATE TABLE `t1` ( `latin1_f` char(32) collate latin1_bin default NULL ) TYPE=MyISAM CHARSET=latin1 COLLATE=latin1_bin SHOW FIELDS FROM t1; -Field Type Collation Null Key Default Extra -latin1_f char(32) latin1_bin YES NULL +Field Type Null Key Default Extra +latin1_f char(32) YES NULL SET CHARACTER SET 'latin1'; SHOW VARIABLES LIKE 'character_set_client'; Variable_name Value diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index fb9e8224111..23a90be1306 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -13,8 +13,8 @@ Table Create Table `ÐÏÌÅ` char(32) character set koi8r NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM ÔÁÂÌÉÃÁ; -Field Type Collation Null Key Default Extra -ÐÏÌÅ char(32) koi8r_general_ci +Field Type Null Key Default Extra +ÐÏÌÅ char(32) SET CHARACTER SET cp1251; SHOW TABLES; Tables_in_test @@ -25,8 +25,8 @@ Table Create Table `ïîëå` char(32) character set koi8r NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM òàáëèöà; -Field Type Collation Null Key Default Extra -ïîëå char(32) koi8r_general_ci +Field Type Null Key Default Extra +ïîëå char(32) SET CHARACTER SET utf8; SHOW TABLES; Tables_in_test @@ -37,8 +37,8 @@ Table Create Table `поле` char(32) character set koi8r NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 SHOW FIELDS FROM таблица; -Field Type Collation Null Key Default Extra -поле char(32) koi8r_general_ci +Field Type Null Key Default Extra +поле char(32) SET CHARACTER SET koi8r; DROP TABLE ÔÁÂÌÉÃÁ; SET CHARACTER SET default; diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 746cdecdfdb..4317daea0b3 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -8,37 +8,37 @@ CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON); CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION); CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); SHOW FIELDS FROM pt; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g point NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g point YES NULL SHOW FIELDS FROM ls; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g linestring NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g linestring YES NULL SHOW FIELDS FROM p; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g polygon NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g polygon YES NULL SHOW FIELDS FROM mpt; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g multipoint NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g multipoint YES NULL SHOW FIELDS FROM mls; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g multilinestring NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g multilinestring YES NULL SHOW FIELDS FROM mp; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g multipolygon NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g multipolygon YES NULL SHOW FIELDS FROM gc; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g geometrycollection NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g geometrycollection YES NULL SHOW FIELDS FROM geo; -Field Type Collation Null Key Default Extra -fid int(11) NULL PRI 0 -g geometry NULL YES NULL +Field Type Null Key Default Extra +fid int(11) PRI 0 +g geometry YES NULL INSERT INTO pt VALUES (101, PointFromText('POINT(10 10)')), (102, PointFromText('POINT(20 10)')), @@ -366,27 +366,27 @@ gc geometrycollection, gm geometry ); SHOW FIELDS FROM g1; -Field Type Collation Null Key Default Extra -pt point NULL YES NULL -ln linestring NULL YES NULL -pg polygon NULL YES NULL -mpt multipoint NULL YES NULL -mln multilinestring NULL YES NULL -mpg multipolygon NULL YES NULL -gc geometrycollection NULL YES NULL -gm geometry NULL YES NULL +Field Type Null Key Default Extra +pt point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mpt multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL ALTER TABLE g1 ADD fid INT NOT NULL; SHOW FIELDS FROM g1; -Field Type Collation Null Key Default Extra -pt point NULL YES NULL -ln linestring NULL YES NULL -pg polygon NULL YES NULL -mpt multipoint NULL YES NULL -mln multilinestring NULL YES NULL -mpg multipolygon NULL YES NULL -gc geometrycollection NULL YES NULL -gm geometry NULL YES NULL -fid int(11) NULL 0 +Field Type Null Key Default Extra +pt point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mpt multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +fid int(11) 0 DROP TABLE g1; SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))) diff --git a/mysql-test/r/have_ucs2.require b/mysql-test/r/have_ucs2.require index 4f2ef7e83e4..c53250aeaef 100644 --- a/mysql-test/r/have_ucs2.require +++ b/mysql-test/r/have_ucs2.require @@ -1,2 +1,2 @@ -Collation Charset Id D C Sortlen -ucs2_general_ci ucs2 35 Y Y 1 +Collation Charset Id Default Compiled Sortlen +ucs2_general_ci ucs2 35 Yes Yes 1 diff --git a/mysql-test/r/have_ujis.require b/mysql-test/r/have_ujis.require index b4b0a4d256c..b4de2234ec7 100644 --- a/mysql-test/r/have_ujis.require +++ b/mysql-test/r/have_ujis.require @@ -1,2 +1,2 @@ -Collation Charset Id D C Sortlen -ujis_japanese_ci ujis 12 Y Y 0 +Collation Charset Id Default Compiled Sortlen +ujis_japanese_ci ujis 12 Yes Yes 0 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 0f65c8b0fe3..71dceddab29 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -906,8 +906,8 @@ id select_type table type possible_keys key key_len ref rows Extra drop table t1; create table t1 (t int not null default 1, key (t)) type=innodb; desc t1; -Field Type Collation Null Key Default Extra -t int(11) NULL MUL 1 +Field Type Null Key Default Extra +t int(11) MUL 1 drop table t1; CREATE TABLE t1 ( number bigint(20) NOT NULL default '0', diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index c1f2adc1e31..b867eae5e8d 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -155,13 +155,13 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (a decimal(9,2), b decimal (9,0), e double(9,2), f double(5,0), h float(3,2), i float(3,0)); show columns from t1; -Field Type Collation Null Key Default Extra -a decimal(9,2) NULL YES NULL -b decimal(9,0) NULL YES NULL -e double(9,2) NULL YES NULL -f double(5,0) NULL YES NULL -h float(3,2) NULL YES NULL -i float(3,0) NULL YES NULL +Field Type Null Key Default Extra +a decimal(9,2) YES NULL +b decimal(9,0) YES NULL +e double(9,2) YES NULL +f double(5,0) YES NULL +h float(3,2) YES NULL +i float(3,0) YES NULL show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment a decimal(9,2) NULL YES NULL select,insert,update,references @@ -229,16 +229,16 @@ type_bool type_tiny type_short type_mediumint type_bigint type_decimal type_nume drop table t1; create table t1 (c decimal, d double, f float, r real); show columns from t1; -Field Type Collation Null Key Default Extra -c decimal(10,0) NULL YES NULL -d double NULL YES NULL -f float NULL YES NULL -r double NULL YES NULL +Field Type Null Key Default Extra +c decimal(10,0) YES NULL +d double YES NULL +f float YES NULL +r double YES NULL drop table t1; create table t1 (c decimal(3,3), d double(3,3), f float(3,3)); show columns from t1; -Field Type Collation Null Key Default Extra -c decimal(4,3) NULL YES NULL -d double(4,3) NULL YES NULL -f float(4,3) NULL YES NULL +Field Type Null Key Default Extra +c decimal(4,3) YES NULL +d double(4,3) YES NULL +f float(4,3) YES NULL drop table t1; diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index f97e2bc06b5..ce1cd392819 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -1,22 +1,22 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7; CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000)); show columns from t1; -Field Type Collation Null Key Default Extra -a blob NULL YES NULL -b text latin1_swedish_ci YES NULL -c blob NULL YES NULL -d mediumtext latin1_swedish_ci YES NULL -e longtext latin1_swedish_ci YES NULL +Field Type Null Key Default Extra +a blob YES NULL +b text YES NULL +c blob YES NULL +d mediumtext YES NULL +e longtext YES NULL CREATE TABLE t2 (a char(257), b varchar(70000) binary, c varchar(70000000)); Warnings: Warning 1244 Converting column 'a' from CHAR to TEXT Warning 1244 Converting column 'b' from CHAR to BLOB Warning 1244 Converting column 'c' from CHAR to TEXT show columns from t2; -Field Type Collation Null Key Default Extra -a text latin1_swedish_ci YES NULL -b mediumblob NULL YES NULL -c longtext latin1_swedish_ci YES NULL +Field Type Null Key Default Extra +a text YES NULL +b mediumblob YES NULL +c longtext YES NULL create table t3 (a long, b long byte); show create TABLE t3; Table Create Table diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 16934e33798..803280c56c6 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -679,7 +679,8 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, List field_list; field_list.push_back(new Item_empty_string("Field",NAME_LEN)); field_list.push_back(new Item_empty_string("Type",40)); - field_list.push_back(new Item_empty_string("Collation",40)); + if (verbose) + field_list.push_back(new Item_empty_string("Collation",40)); field_list.push_back(new Item_empty_string("Null",1)); field_list.push_back(new Item_empty_string("Key",3)); field_list.push_back(item=new Item_empty_string("Default",NAME_LEN)); @@ -719,7 +720,8 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, protocol->store(field->field_name, system_charset_info); field->sql_type(type); protocol->store(type.ptr(), type.length(), system_charset_info); - protocol->store(field->has_charset() ? field->charset()->name : "NULL", + if (verbose) + protocol->store(field->has_charset() ? field->charset()->name : "NULL", system_charset_info); pos=(byte*) ((flags & NOT_NULL_FLAG) && field->type() != FIELD_TYPE_TIMESTAMP ? @@ -1436,8 +1438,8 @@ static bool write_collation(Protocol *protocol, CHARSET_INFO *cs) protocol->store(cs->name, system_charset_info); protocol->store(cs->csname, system_charset_info); protocol->store_short((longlong) cs->number); - protocol->store((cs->state & MY_CS_PRIMARY) ? "Y" : "",system_charset_info); - protocol->store((cs->state & MY_CS_COMPILED)? "Y" : "",system_charset_info); + protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info); + protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info); protocol->store_short((longlong) cs->strxfrm_multiply); return protocol->write(); } @@ -1456,8 +1458,8 @@ int mysqld_show_collations(THD *thd, const char *wild) field_list.push_back(new Item_empty_string("Collation",30)); field_list.push_back(new Item_empty_string("Charset",30)); field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT)); - field_list.push_back(new Item_empty_string("D",30)); - field_list.push_back(new Item_empty_string("C",30)); + field_list.push_back(new Item_empty_string("Default",30)); + field_list.push_back(new Item_empty_string("Compiled",30)); field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT)); if (protocol->send_fields(&field_list, 1)) From cab8de28882aa61cf0e7d8d7f7c41186df0488dc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2003 16:11:06 +0300 Subject: [PATCH 291/399] com0shm.c: Removed auto event creation because it is not needed in any MySQL/InnoDB code innobase/com/com0shm.c: Removed auto event creation because it is not needed in any MySQL/InnoDB code --- innobase/com/com0shm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/innobase/com/com0shm.c b/innobase/com/com0shm.c index 72ab23b9be8..ed185ccdf47 100644 --- a/innobase/com/com0shm.c +++ b/innobase/com/com0shm.c @@ -103,7 +103,8 @@ struct com_shm_endpoint_struct{ the area currently may contain a datagram; NOTE: automatic event */ os_event_t empty; /* this is in the signaled state if the area - currently may be empty; NOTE: automatic event */ + currently may be empty; NOTE: automatic + event */ ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex protecting the shared memory */ UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct @@ -793,16 +794,18 @@ com_shm_create_or_open( ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"), - event_ne = os_event_create_auto(buf); + event_ne = os_event_create(buf); ut_ad(event_ne); ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"), - event_em = os_event_create_auto(buf); + event_em = os_event_create(buf); ut_ad(event_em); + ut_a(0); /* event_ne and event_em should be auto events! */ + com_shm_endpoint_set_shm(ep, shm); com_shm_endpoint_set_map(ep, map); From 9c7240f4c27583ca55e54e82edf2054fc4e11180 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2003 17:58:18 +0300 Subject: [PATCH 292/399] os0sync.c: Do not try to reserve os_sync_mutex in shutdown after it has been freed innobase/os/os0sync.c: Do not try to reserve os_sync_mutex in shutdown after it has been freed --- innobase/os/os0sync.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 0fe61fe570d..bf5fc57bf57 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -88,6 +88,12 @@ os_sync_free(void) mutex = UT_LIST_GET_FIRST(os_mutex_list); while (mutex) { + if (mutex == os_sync_mutex) { + /* Set the flag to FALSE so that we do not try to + reserve os_sync_mutex any more in remaining freeing + operations in shutdown */ + os_sync_mutex_inited = FALSE; + } os_mutex_free(mutex); @@ -517,13 +523,17 @@ os_mutex_free( { ut_a(mutex); - os_mutex_enter(os_sync_mutex); + if (os_sync_mutex_inited) { + os_mutex_enter(os_sync_mutex); + } UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); os_mutex_count--; - os_mutex_exit(os_sync_mutex); + if (os_sync_mutex_inited) { + os_mutex_exit(os_sync_mutex); + } #ifdef __WIN__ ut_a(CloseHandle(mutex->handle)); @@ -614,9 +624,16 @@ os_fast_mutex_free( #else ut_a(0 == pthread_mutex_destroy(fast_mutex)); #endif - os_mutex_enter(os_sync_mutex); + if (os_sync_mutex_inited) { + /* When freeing the last mutexes, we have + already freed os_sync_mutex */ + + os_mutex_enter(os_sync_mutex); + } os_fast_mutex_count--; - os_mutex_exit(os_sync_mutex); + if (os_sync_mutex_inited) { + os_mutex_exit(os_sync_mutex); + } } From 72f23f4d5da05c1d26d33c5441aedfd8fa949677 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2003 17:30:47 +0200 Subject: [PATCH 293/399] Clearer error message (in the customer's case, the relay log was corrupted, not the master's binlog) (SW 1571). sql/slave.cc: Clearer error message (in the customer's case, the relay log was corrupted, not the master's binlog). --- sql/slave.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index b655b17c258..ec1041894bd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2081,8 +2081,13 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) else { sql_print_error("\ -Could not parse log event entry, check the master for binlog corruption\n\ -This may also be a network problem, or just a bug in the master or slave code.\ +Could not parse relay log event entry. The possible reasons are: the master's \ +binary log is corrupted (you can check this by running 'mysqlbinlog' on the \ +binary log), the slave's relay log is corrupted (you can check this by running \ +'mysqlbinlog' on the relay log), a network problem, or a bug in the master's \ +or slave's MySQL code. If you want to check the master's binary log or slave's \ +relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \ +on this slave.\ "); return 1; } From 93d3ba840d1fe746929c68c262d3337cf4f38fc0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 14:59:17 +0500 Subject: [PATCH 294/399] MY_CS_NONTEXT flag for sprintf() incompatible charsets (ucs2 if the only one now) Some default_charset_info were removed --- include/m_ctype.h | 2 +- myisam/mi_create.c | 2 +- myisam/mi_test1.c | 4 ++-- myisam/mi_test2.c | 8 ++++---- myisam/rt_test.c | 2 +- myisam/sp_test.c | 2 +- sql/field.cc | 20 ++++++++++---------- sql/item.cc | 2 +- sql/item_create.cc | 2 +- sql/item_geofunc.cc | 2 +- sql/item_strfunc.cc | 4 ++-- sql/sql_parse.cc | 2 +- sql/sql_string.cc | 4 ++-- sql/sql_string.h | 2 +- sql/sql_yacc.yy | 10 +++++----- strings/ctype-ucs2.c | 4 ++-- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index 59f75081ff9..f6b5a1ca44f 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -62,9 +62,9 @@ typedef struct unicase_info_st #define MY_CS_PRIMARY 32 /* if primary collation */ #define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */ #define MY_CS_UNICODE 128 /* is a charset is full unicode */ +#define MY_CS_NONTEXT 256 /* if a charset is not sprintf() compatible */ #define MY_CHARSET_UNDEFINED 0 -#define MY_CHARSET_CURRENT (default_charset_info->number) typedef struct my_uni_idx_st diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 964845cc051..26bb23c3a7f 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -441,7 +441,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE); mi_int2store(share.state.header.base_pos,base_pos); share.state.header.language= (ci->language ? - ci->language : MY_CHARSET_CURRENT); + ci->language : default_charset_info->number); share.state.header.max_block_size=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH; share.state.dellink = HA_OFFSET_ERROR; diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c index 6aa4b9cf9f1..5a6818b8a3e 100644 --- a/myisam/mi_test1.c +++ b/myisam/mi_test1.c @@ -99,7 +99,7 @@ static int run_test(const char *filename) keyinfo[0].seg[0].length=key_length; keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0; keyinfo[0].seg[0].null_pos=0; - keyinfo[0].seg[0].language=MY_CHARSET_CURRENT; + keyinfo[0].seg[0].language= default_charset_info->number; if (pack_seg & HA_BLOB_PART) { keyinfo[0].seg[0].bit_start=4; /* Length of blob length */ @@ -122,7 +122,7 @@ static int run_test(const char *filename) uniqueseg[i].start=start; start+=recinfo[i+1].length; uniqueseg[i].length=recinfo[i+1].length; - uniqueseg[i].language=MY_CHARSET_CURRENT; + uniqueseg[i].language= default_charset_info->number; } uniqueseg[0].type= key_type; uniqueseg[0].null_bit= null_fields ? 2 : 0; diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c index 75adf74294f..8dc279b6d97 100644 --- a/myisam/mi_test2.c +++ b/myisam/mi_test2.c @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) keyinfo[0].seg[0].start=0; keyinfo[0].seg[0].length=6; keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT; - keyinfo[0].seg[0].language=MY_CHARSET_CURRENT; + keyinfo[0].seg[0].language= default_charset_info->number; keyinfo[0].seg[0].flag=(uint8) pack_seg; keyinfo[0].seg[0].null_bit=0; keyinfo[0].seg[0].null_pos=0; @@ -124,7 +124,7 @@ int main(int argc, char *argv[]) keyinfo[3].seg[0].start=0; keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0); keyinfo[3].seg[0].type=HA_KEYTYPE_TEXT; - keyinfo[3].seg[0].language=MY_CHARSET_CURRENT; + keyinfo[3].seg[0].language=default_charset_info->number; keyinfo[3].seg[0].flag=(uint8) pack_seg; keyinfo[3].seg[0].null_bit=0; keyinfo[3].seg[0].null_pos=0; @@ -135,7 +135,7 @@ int main(int argc, char *argv[]) keyinfo[4].seg[0].start=0; keyinfo[4].seg[0].length=5; keyinfo[4].seg[0].type=HA_KEYTYPE_TEXT; - keyinfo[4].seg[0].language=MY_CHARSET_CURRENT; + keyinfo[4].seg[0].language=default_charset_info->number; keyinfo[4].seg[0].flag=0; keyinfo[4].seg[0].null_bit=0; keyinfo[4].seg[0].null_pos=0; @@ -146,7 +146,7 @@ int main(int argc, char *argv[]) keyinfo[5].seg[0].start=0; keyinfo[5].seg[0].length=4; keyinfo[5].seg[0].type=HA_KEYTYPE_TEXT; - keyinfo[5].seg[0].language=MY_CHARSET_CURRENT; + keyinfo[5].seg[0].language=default_charset_info->number; keyinfo[5].seg[0].flag=pack_seg; keyinfo[5].seg[0].null_bit=0; keyinfo[5].seg[0].null_pos=0; diff --git a/myisam/rt_test.c b/myisam/rt_test.c index 8bb4687e967..61890bfded1 100644 --- a/myisam/rt_test.c +++ b/myisam/rt_test.c @@ -98,7 +98,7 @@ int run_test(const char *filename) keyinfo[0].seg[i].length=key_length; keyinfo[0].seg[i].null_bit= null_fields ? 2 : 0; keyinfo[0].seg[i].null_pos=0; - keyinfo[0].seg[i].language=MY_CHARSET_CURRENT; + keyinfo[0].seg[i].language=default_charset_info->number; } diff --git a/myisam/sp_test.c b/myisam/sp_test.c index 7021cb4a8ee..c4847217efd 100644 --- a/myisam/sp_test.c +++ b/myisam/sp_test.c @@ -96,7 +96,7 @@ int run_test(const char *filename) keyinfo[0].seg[0].length=1; /* Spatial ignores it anyway */ keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0; keyinfo[0].seg[0].null_pos=0; - keyinfo[0].seg[0].language=MY_CHARSET_CURRENT; + keyinfo[0].seg[0].language=default_charset_info->number; keyinfo[0].seg[0].bit_start=4; /* Long BLOB */ diff --git a/sql/field.cc b/sql/field.cc index a61654ed8f4..044684b2675 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -335,7 +335,7 @@ bool Field::optimize_range(uint idx) void Field_null::sql_type(String &res) const { - res.set_latin1("null", 4); + res.set_ascii("null", 4); } @@ -856,7 +856,7 @@ String *Field_decimal::val_str(String *val_buffer __attribute__((unused)), if (field_length < tmp_length) // Error in data val_ptr->length(0); else - val_ptr->set_latin1((const char*) str, field_length-tmp_length); + val_ptr->set_ascii((const char*) str, field_length-tmp_length); return val_ptr; } @@ -2389,7 +2389,7 @@ void Field_float::sql_type(String &res) const { if (dec == NOT_FIXED_DEC) { - res.set_latin1("float", 5); + res.set_ascii("float", 5); } else { @@ -2647,7 +2647,7 @@ void Field_double::sql_type(String &res) const CHARSET_INFO *cs=res.charset(); if (dec == NOT_FIXED_DEC) { - res.set_latin1("double",6); + res.set_ascii("double",6); } else { @@ -2987,7 +2987,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) void Field_timestamp::sql_type(String &res) const { - res.set_latin1("timestamp", 9); + res.set_ascii("timestamp", 9); } @@ -3186,7 +3186,7 @@ void Field_time::sort_string(char *to,uint length __attribute__((unused))) void Field_time::sql_type(String &res) const { - res.set_latin1("time", 4); + res.set_ascii("time", 4); } /**************************************************************************** @@ -3467,7 +3467,7 @@ void Field_date::sort_string(char *to,uint length __attribute__((unused))) void Field_date::sql_type(String &res) const { - res.set_latin1("date", 4); + res.set_ascii("date", 4); } /**************************************************************************** @@ -3637,7 +3637,7 @@ void Field_newdate::sort_string(char *to,uint length __attribute__((unused))) void Field_newdate::sql_type(String &res) const { - res.set_latin1("date", 4); + res.set_ascii("date", 4); } @@ -3870,7 +3870,7 @@ void Field_datetime::sort_string(char *to,uint length __attribute__((unused))) void Field_datetime::sql_type(String &res) const { - res.set_latin1("datetime", 8); + res.set_ascii("datetime", 8); } /**************************************************************************** @@ -4615,7 +4615,7 @@ void Field_blob::sql_type(String &res) const case 3: str="medium"; length= 6; break; case 4: str="long"; length=4; break; } - res.set_latin1(str,length); + res.set_ascii(str,length); if (charset() == &my_charset_bin) res.append("blob"); else diff --git a/sql/item.cc b/sql/item.cc index 636cefb511b..42a949287e5 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1452,7 +1452,7 @@ bool Item_insert_value::fix_fields(THD *thd, struct st_table_list *table_list, I Field *field=field_arg->field; /* charset doesn't matter here, it's to avoid sigsegv only */ set_field(new Field_null(0,0,Field::NONE,field->field_name,field->table, - default_charset_info)); + &my_charset_bin)); } return 0; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 3edec7fdab0..00c98937659 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -324,7 +324,7 @@ Item *create_func_current_user() length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) - buff); return new Item_string(NullS, thd->memdup(buff, length), length, - default_charset_info); + system_charset_info); } Item *create_func_quarter(Item* a) diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 06ba67cbc73..fa858922c1b 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -141,7 +141,7 @@ String *Item_func_geometry_type::val_str(String *str) return 0; str->copy(geom.get_class_info()->m_name, strlen(geom.get_class_info()->m_name), - default_charset_info); + default_charset()); return str; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 06569095018..3c4b5070850 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2257,7 +2257,7 @@ String *Item_func_hex::val_str(String *str) if ((null_value= args[0]->null_value)) return 0; ptr= longlong2str(dec,ans,16); - if (str->copy(ans,(uint32) (ptr-ans),default_charset_info)) + if (str->copy(ans,(uint32) (ptr-ans),default_charset())) return &empty_string; // End of memory return str; } @@ -2366,7 +2366,7 @@ String* Item_func_export_set::val_str(String* str) } break; case 3: - sep_buf.set(",", 1, default_charset_info); + sep_buf.set(",", 1, default_charset()); sep = &sep_buf; } null_value=0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9ebb6305f70..f098ce0d0b6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -623,7 +623,7 @@ check_connections(THD *thd) memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1); end+=SCRAMBLE_LENGTH +1; int2store(end,client_flags); - end[2]=(char) MY_CHARSET_CURRENT; + end[2]=(char) default_charset_info->number; int2store(end+3,thd->server_status); bzero(end+5,13); end+=18; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 6077c42bd1d..cf6645fa23e 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -265,9 +265,9 @@ bool String::copy(const char *str, uint32 arg_length, */ -bool String::set_latin1(const char *str, uint32 arg_length) +bool String::set_ascii(const char *str, uint32 arg_length) { - if (str_charset->mbmaxlen == 1) + if (!(str_charset->state & MY_CS_NONTEXT)) { set(str, arg_length, str_charset); return 0; diff --git a/sql/sql_string.h b/sql/sql_string.h index 8212bd0a2bd..ee38853a2d3 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -117,7 +117,7 @@ public: Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0; str_charset=cs; } - bool set_latin1(const char *str, uint32 arg_length); + bool set_ascii(const char *str, uint32 arg_length); inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs) { if (!alloced) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1002d06be88..66a29a8cbd5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2863,15 +2863,15 @@ key_usage_list2: key_usage_list2 ',' ident { Select->select_lex()-> interval_list.push_back(new String((const char*) $3.str, $3.length, - default_charset_info)); } + system_charset_info)); } | ident { Select->select_lex()-> interval_list.push_back(new String((const char*) $1.str, $1.length, - default_charset_info)); } + system_charset_info)); } | PRIMARY_SYM { Select->select_lex()-> interval_list.push_back(new String("PRIMARY", 7, - default_charset_info)); }; + system_charset_info)); }; using_list: ident @@ -3756,7 +3756,7 @@ opt_describe_column: /* empty */ {} | text_string { Lex->wild= $1; } | ident - { Lex->wild= new String((const char*) $1.str,$1.length,default_charset_info); }; + { Lex->wild= new String((const char*) $1.str,$1.length,system_charset_info); }; /* flush things */ @@ -4829,7 +4829,7 @@ column_list: column_list_id: ident { - String *new_str = new String((const char*) $1.str,$1.length,default_charset_info); + String *new_str = new String((const char*) $1.str,$1.length,system_charset_info); List_iterator iter(Lex->columns); class LEX_COLUMN *point; LEX *lex=Lex; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 8cb8f84f281..5d78ab5dcff 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1042,7 +1042,7 @@ static MY_CHARSET_HANDLER my_charset_handler= CHARSET_INFO my_charset_ucs2_general_ci= { 35,0,0, /* number */ - MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE, /* state */ + MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONTEXT, "ucs2", /* cs name */ "ucs2_general_ci", /* name */ "", /* comment */ @@ -1065,7 +1065,7 @@ CHARSET_INFO my_charset_ucs2_general_ci= CHARSET_INFO my_charset_ucs2_bin= { 90,0,0, /* number */ - MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE, /* state */ + MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE|MY_CS_NONTEXT, "ucs2", /* cs name */ "ucs2_bin", /* name */ "", /* comment */ From aed6de39b6129d84f091e23b4a8b0f5cc8e6076d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 15:02:57 +0500 Subject: [PATCH 295/399] SCRUM: splittiln common client's parts include/sql_common.h: superfluous #ifdef-s removed libmysql/client_settings.h: superfluous #ifdef-s removed libmysql/libmysql.c: some litter removed libmysqld/lib_sql.cc: here we had wrong parameters mysys/default.c: this is not needed anymore - calling code fixed sql-common/client.c: code trimmed and simplified sql/client_settings.h: code trimmed sql/repl_failsafe.cc: option's initialization added sql/slave.cc: option's initialization added --- include/sql_common.h | 4 --- libmysql/client_settings.h | 3 -- libmysql/libmysql.c | 6 +--- libmysqld/lib_sql.cc | 2 +- mysys/default.c | 2 -- sql-common/client.c | 65 +++++++++++++++++++------------------- sql/client_settings.h | 14 ++++---- sql/repl_failsafe.cc | 1 + sql/slave.cc | 1 + 9 files changed, 43 insertions(+), 55 deletions(-) diff --git a/include/sql_common.h b/include/sql_common.h index aa4386a5623..3a668a8dd41 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -15,9 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _sql_common_h -#define _sql_common_h - extern const char *unknown_sqlstate; #ifdef __cplusplus @@ -50,4 +47,3 @@ my_bool mysql_reconnect(MYSQL *mysql); #define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) #endif -#endif /* _sql_common_h */ diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index 253f1515075..47d5185b6ca 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -15,8 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _client_settings_h -#define _client_settings_h static my_bool mysql_client_init=0; extern uint mysql_port; extern my_string mysql_unix_port; @@ -58,4 +56,3 @@ my_bool send_file_to_server(MYSQL *mysql, const char *filename); #define set_sigpipe(mysql) #define reset_sigpipe(mysql) #endif -#endif /* _client_settings_h */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 766c62a03eb..44c5e3eecf4 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -99,7 +99,6 @@ TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", be changed */ #define MAX_LONG_DATA_LENGTH 8192 -/*#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41)*/ #define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG) static void append_wild(char *to,char *end,const char *wild); @@ -157,10 +156,6 @@ void STDCALL mysql_thread_end() #define reset_sigpipe(mysql) #endif -/* TO DELETE -#define _libmysql_c -#include "../sql-common/client.c" -*/ static MYSQL* spawn_init(MYSQL* parent, const char* host, unsigned int port, const char* user, @@ -987,6 +982,7 @@ mysql_query(MYSQL *mysql, const char *query) return mysql_real_query(mysql,query, (uint) strlen(query)); } + static MYSQL* spawn_init(MYSQL* parent, const char* host, unsigned int port, const char* user, const char* passwd) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 12647a32713..ecb2cb88a0d 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -183,7 +183,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups) MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads } - if (init_common_variables("my", argc, argv, (const char **)groups)) + if (init_common_variables("my", *argcp, *argvp, (const char **)groups)) { mysql_server_end(); return 1; diff --git a/mysys/default.c b/mysys/default.c index 7b02999160e..bbf429eb920 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -174,8 +174,6 @@ void load_defaults(const char *conf_file, const char **groups, res= (char**) (ptr+sizeof(alloc)); /* copy name + found arguments + command line arguments to new array */ - res[0]=*argc ? argv[0][0] : (char *)""; - memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*)); /* Skipp --defaults-file and --defaults-extra-file */ (*argc)-= args_used; diff --git a/sql-common/client.c b/sql-common/client.c index c586563cdc5..4baee2d2477 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -14,6 +14,27 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + This file is included by both libmysql.c (the MySQL client C API) + and the mysqld server to connect to another MYSQL server. + + The differences for the two cases are: + + - Things that only works for the client: + - Trying to automaticly determinate user name if not supplied to + mysql_real_connect() + - Support for reading local file with LOAD DATA LOCAL + - SHARED memory handling + - Protection against sigpipe + - Prepared statements + + - Things that only works for the server + - Alarm handling on connect + + In all other cases, the code should be idential for the client and + server. +*/ + #include #if defined(MYSQL_SERVER) || defined(HAVE_EXTERNAL_CLIENT) @@ -207,10 +228,8 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, my_bool testing_named_pipes=0; char *host= *arg_host, *unix_socket= *arg_unix_socket; -#ifdef MYSQL_CLIENT if ( ! unix_socket || (unix_socket)[0] == 0x00) unix_socket = mysql_unix_port; -#endif if (!host || !strcmp(host,LOCAL_HOST)) host=LOCAL_HOST_NAMEDPIPE; @@ -1285,7 +1304,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Grab a socket and connect it to the server */ -#if defined(MYSQL_CLIENT) && defined(HAVE_SMEM) +#ifdef HAVE_SMEM if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && (!host || !strcmp(host,LOCAL_HOST))) @@ -1314,22 +1333,14 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } else #endif /* HAVE_SMEM */ #if defined(HAVE_SYS_UN_H) - if ( -#ifdef MYSQL_CLIENT - (!mysql->options.protocol || + if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&& (unix_socket || mysql_unix_port) && -#endif -#ifdef MYSQL_SERVER - unix_socket && -#endif (!host || !strcmp(host,LOCAL_HOST))) { host=LOCAL_HOST; -#ifdef MYSQL_CLIENT if (!unix_socket) unix_socket=mysql_unix_port; -#endif host_info=(char*) ER(CR_LOCALHOST_CONNECTION); DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) @@ -1361,18 +1372,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, else #elif defined(__WIN__) { -#ifdef MYSQL_CLIENT if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&& ((unix_socket || !host && is_NT() || host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||! have_tcpip))&& (!net->vio)) -#elif MYSQL_SERVER - if ((unix_socket || - !host && is_NT() || - host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) || - mysql->options.named_pipe || !have_tcpip)) -#endif { sock=0; if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, @@ -1408,10 +1412,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #endif { unix_socket=0; /* This is not used */ -#ifdef MYSQL_CLIENT if (!port) port=mysql_port; -#endif if (!host) host=LOCAL_HOST; sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); @@ -1859,24 +1861,26 @@ error: /* needed when we move MYSQL structure to a different address */ -#ifdef MYSQL_CLIENT /*should work in MYSQL_SERVER also, but doesn't */ static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) { - MYSQL *tmp, *tmp_prev; if (mysql->master == old_mysql) mysql->master = mysql; if (mysql->last_used_con == old_mysql) mysql->last_used_con = mysql; if (mysql->last_used_slave == old_mysql) mysql->last_used_slave = mysql; - for (tmp_prev = mysql, tmp = mysql->next_slave; - tmp != old_mysql;tmp = tmp->next_slave) +#ifdef MYSQL_CLIENT /*should work in MYSQL_SERVER also, but doesn't */ { - tmp_prev = tmp; + MYSQL *tmp, *tmp_prev; + for (tmp_prev = mysql, tmp = mysql->next_slave; + tmp != old_mysql;tmp = tmp->next_slave) + { + tmp_prev = tmp; + } + tmp_prev->next_slave = mysql; } - tmp_prev->next_slave = mysql; -} #endif /*MYSQL_CLIENT*/ +} my_bool mysql_reconnect(MYSQL *mysql) { @@ -1897,9 +1901,6 @@ my_bool mysql_reconnect(MYSQL *mysql) tmp_mysql.options=mysql->options; bzero((char*) &mysql->options,sizeof(mysql->options)); tmp_mysql.rpl_pivot = mysql->rpl_pivot; -#ifdef MYSQL_SERVER - mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&mysql->net.read_timeout); -#endif if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, mysql->db, mysql->port, mysql->unix_socket, mysql->client_flag)) @@ -1913,9 +1914,7 @@ my_bool mysql_reconnect(MYSQL *mysql) mysql->free_me=0; mysql_close(mysql); *mysql=tmp_mysql; -#ifdef MYSQL_CLIENT /*rpl000010 fails if #ifdef-s were removed*/ mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ -#endif net_clear(&mysql->net); mysql->affected_rows= ~(my_ulonglong) 0; DBUG_RETURN(0); diff --git a/sql/client_settings.h b/sql/client_settings.h index de0c7f40717..bc4cdf2a777 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -15,19 +15,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _client_settings_h -#define _client_settings_h #include -#include -#include +extern char *mysql_unix_port; -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ - CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ + | CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) extern ulong slave_net_timeout; #define init_sigpipe_variables #define set_sigpipe(mysql) #define reset_sigpipe(mysql) -#endif /* _client_settings_h */ + +#ifdef HAVE_SMEM +#undef HAVE_SMEM +#endif diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 2aa8f492ed3..bbfd7866aa2 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -669,6 +669,7 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi) DBUG_RETURN(1); } mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&slave_net_timeout); + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, (char *)default_charset_info); if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, mi->port, 0, 0)) DBUG_RETURN(1); diff --git a/sql/slave.cc b/sql/slave.cc index a49389e0ec7..22c47bbdd05 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2950,6 +2950,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, (reconnect ? mysql_reconnect(mysql) != 0: !(mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&thd->variables.net_read_timeout), + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, (char *)default_charset_info), mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, mi->port, 0, client_flag)))) { From ce02ef66416d409068a6f3c3f96d4403cf10b67f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 15:27:17 +0500 Subject: [PATCH 296/399] Obsolete files removed BitKeeper/deleted/.del-mini_client.h~be0e3c44e9b0f67d: Delete: sql/mini_client.h BitKeeper/deleted/.del-mini_client.cc~8677895ec8169183: Delete: sql/mini_client.cc BitKeeper/etc/ignore: Added sql/client.c to the ignore list --- .bzrignore | 1 + sql/mini_client.cc | 99 ---------------------------------------------- sql/mini_client.h | 48 ---------------------- 3 files changed, 1 insertion(+), 147 deletions(-) delete mode 100644 sql/mini_client.cc delete mode 100644 sql/mini_client.h diff --git a/.bzrignore b/.bzrignore index bfde1876164..dd77bcb1d12 100644 --- a/.bzrignore +++ b/.bzrignore @@ -619,3 +619,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +sql/client.c diff --git a/sql/mini_client.cc b/sql/mini_client.cc deleted file mode 100644 index 8c431c0d1be..00000000000 --- a/sql/mini_client.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ - -/* - mini MySQL client to be included into the server to do server to server - commincation by Sasha Pachev - - Note: all file-global symbols must begin with mc_ , even the static ones, just - in case we decide to make them external at some point -*/ - -#include - -#ifdef HAVE_EXTERNAL_CLIENT - -/* my_pthread must be included early to be able to fix things */ -#if defined(THREAD) -#include /* because of signal() */ -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include "mysql.h" -#include "mini_client.h" -#include "mysql_version.h" -#include "mysqld_error.h" -#include "errmsg.h" -#include - -#if defined( OS2) && defined(MYSQL_SERVER) -#undef ER -#define ER CER -#endif - -extern "C" { // Because of SCO 3.2V4.2 -#include -#include -#ifdef HAVE_PWD_H -#include -#endif -#if !defined(MSDOS) && !defined(__WIN__) -#include -#include -#include -#include -#ifdef HAVE_SELECT_H -# include -#endif -#ifdef HAVE_SYS_SELECT_H -#include -#endif -#endif /*!defined(MSDOS) && !defined(__WIN__) */ -#ifdef HAVE_SYS_UN_H -# include -#endif -#ifndef INADDR_NONE -#define INADDR_NONE -1 -#endif -} - -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ - CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) - - -#if defined(MSDOS) || defined(__WIN__) -#define perror(A) -#else -#include -#define SOCKET_ERROR -1 -#endif - -extern ulong slave_net_timeout; -#define _mini_client_c -#define init_sigpipe_variables -#define set_sigpipe(mysql) -#define reset_sigpipe(mysql) -#include "../sql-common/client.c" - -#endif /* HAVE_EXTERNAL_CLIENT */ - - diff --git a/sql/mini_client.h b/sql/mini_client.h deleted file mode 100644 index 3388c342312..00000000000 --- a/sql/mini_client.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#ifndef _MINI_CLIENT_H -#define _MINI_CLIENT_H - -MYSQL * -mysql_real_connect(MYSQL *mysql,const char *host, const char *user, - const char *passwd, const char *db, - uint port, const char *unix_socket,ulong client_flag, - uint net_read_timeout); - -my_bool simple_command(MYSQL *mysql,enum enum_server_command command, - const char *arg, unsigned long length, - my_bool skip_check); -void mysql_close(MYSQL *mysql); -MYSQL *mysql_init(MYSQL *mysql); -void mysql_debug(const char *debug); -ulong net_safe_read(MYSQL *mysql); -const char *mysql_error(MYSQL *mysql); -unsigned int mysql_errno(MYSQL *mysql); -my_bool mysql_reconnect(MYSQL* mysql); -int mysql_send_query(MYSQL* mysql, const char* query, uint length); -my_bool mysql_read_query_result(MYSQL *mysql); -int mysql_real_query(MYSQL *mysql, const char *q, unsigned long length); -MYSQL_RES * mysql_store_result(MYSQL *mysql); -void mysql_free_result(MYSQL_RES *result); -void mysql_data_seek(MYSQL_RES *result, my_ulonglong row); -my_ulonglong mysql_num_rows(MYSQL_RES *res); -unsigned int mysql_num_fields(MYSQL_RES *res); -MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *res); -int mysql_select_db(MYSQL *mysql, const char *db); -void end_server(MYSQL *mysql); - -#endif From fbd157fa5754c5c1dac01ad824531aeb434426d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 17:02:51 +0600 Subject: [PATCH 297/399] BUG correct bug with empty table sql/item_sum.cc: correct bug with empty table --- sql/item_sum.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 8bd3e36b5db..60976ab993a 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1582,6 +1582,8 @@ void Item_func_group_concat::reset() bool Item_func_group_concat::add() { + if (always_null) + return 0; copy_fields(tmp_table_param); copy_funcs(tmp_table_param->items_to_copy); @@ -1676,6 +1678,7 @@ bool Item_func_group_concat::setup(THD *thd) /* all not constant fields are push to list and create temp table */ + always_null= 0; for (uint i= 0; i < arg_count; i++) { Item *item= args[i]; @@ -1688,6 +1691,8 @@ bool Item_func_group_concat::setup(THD *thd) always_null= 1; } } + if (always_null) + return 0; List all_fields(list); if (arg_count_order) From 8ae717d3198b527a08e0d954fc8bf240c285fc30 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 16:57:14 +0500 Subject: [PATCH 298/399] LTRIM, RTRIM and TRIM now honors coercibility LTRIM, RTRIM and TRIM now work fine with ucs2 --- sql/item_create.cc | 4 ++-- sql/item_strfunc.cc | 29 ++++++++++++++++++++++++++--- sql/item_strfunc.h | 36 +++++++++++++++++++----------------- sql/sql_yacc.yy | 20 +++++++++++--------- 4 files changed, 58 insertions(+), 31 deletions(-) diff --git a/sql/item_create.cc b/sql/item_create.cc index 00c98937659..2d62e5c4657 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -266,7 +266,7 @@ Item *create_func_lpad(Item* a, Item *b, Item *c) Item *create_func_ltrim(Item* a) { - return new Item_func_ltrim(a,new Item_string(" ",1,default_charset_info)); + return new Item_func_ltrim(a); } Item *create_func_md5(Item* a) @@ -365,7 +365,7 @@ Item *create_func_rpad(Item* a, Item *b, Item *c) Item *create_func_rtrim(Item* a) { - return new Item_func_rtrim(a,new Item_string(" ",1,default_charset_info)); + return new Item_func_rtrim(a); } Item *create_func_sec_to_time(Item* a) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3c4b5070850..2a4f4e0c410 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1136,7 +1136,7 @@ String *Item_func_ltrim::val_str(String *str) return 0; /* purecov: inspected */ char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),res->charset()); - String *remove_str=args[1]->val_str(&tmp); + String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove; uint remove_length; LINT_INIT(remove_length); @@ -1174,7 +1174,7 @@ String *Item_func_rtrim::val_str(String *str) return 0; /* purecov: inspected */ char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),res->charset()); - String *remove_str=args[1]->val_str(&tmp); + String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove; uint remove_length; LINT_INIT(remove_length); @@ -1246,7 +1246,7 @@ String *Item_func_trim::val_str(String *str) return 0; /* purecov: inspected */ char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),res->charset()); - String *remove_str=args[1]->val_str(&tmp); + String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove; uint remove_length; LINT_INIT(remove_length); @@ -1291,6 +1291,29 @@ String *Item_func_trim::val_str(String *str) return &tmp_value; } +void Item_func_trim::fix_length_and_dec() +{ + max_length= args[0]->max_length; + if (arg_count == 1) + { + set_charset(args[0]->charset(), args[0]->coercibility); + remove.set_charset(charset()); + remove.set_ascii(" ",1); + } + else + if (set_charset(args[1]->charset(), args[1]->coercibility, + args[0]->charset(), args[0]->coercibility)) + { + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + args[1]->charset()->name,coercion_name(args[1]->coercibility), + args[0]->charset()->name,coercion_name(args[0]->coercibility), + func_name()); + } +} + + + + void Item_func_password::fix_length_and_dec() { /* diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 65aad3a3fff..a70c9b39255 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -220,37 +220,39 @@ public: }; -class Item_func_ltrim :public Item_str_func +class Item_func_trim :public Item_str_func { +protected: String tmp_value; + String remove; public: - Item_func_ltrim(Item *a,Item *b) :Item_str_func(a,b) {} + Item_func_trim(Item *a,Item *b) :Item_str_func(a,b) {} + Item_func_trim(Item *a) :Item_str_func(a) {} + String *val_str(String *); + void fix_length_and_dec(); + const char *func_name() const { return "trim"; } +}; + + +class Item_func_ltrim :public Item_func_trim +{ +public: + Item_func_ltrim(Item *a,Item *b) :Item_func_trim(a,b) {} + Item_func_ltrim(Item *a) :Item_func_trim(a) {} String *val_str(String *); - void fix_length_and_dec() { max_length= args[0]->max_length; } const char *func_name() const { return "ltrim"; } }; -class Item_func_rtrim :public Item_str_func +class Item_func_rtrim :public Item_func_trim { - String tmp_value; public: - Item_func_rtrim(Item *a,Item *b) :Item_str_func(a,b) {} + Item_func_rtrim(Item *a,Item *b) :Item_func_trim(a,b) {} + Item_func_rtrim(Item *a) :Item_func_trim(a) {} String *val_str(String *); - void fix_length_and_dec() { max_length= args[0]->max_length; } const char *func_name() const { return "rtrim"; } }; -class Item_func_trim :public Item_str_func -{ - String tmp_value; -public: - Item_func_trim(Item *a,Item *b) :Item_str_func(a,b) {} - String *val_str(String *); - void fix_length_and_dec() { max_length= args[0]->max_length; } - const char *func_name() const { return "trim"; } -}; - class Item_func_password :public Item_str_func { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 66a29a8cbd5..9b2808f93a8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -593,7 +593,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr - table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr + table_wild no_in_expr expr_expr simple_expr no_and_expr using_list expr_or_default set_expr_or_default interval_expr param_marker singlerow_subselect singlerow_subselect_init exists_subselect exists_subselect_init @@ -2479,13 +2479,19 @@ simple_expr: | SUBSTRING_INDEX '(' expr ',' expr ',' expr ')' { $$= new Item_func_substr_index($3,$5,$7); } | TRIM '(' expr ')' - { $$= new Item_func_trim($3,new Item_string(" ",1,default_charset_info)); } - | TRIM '(' LEADING opt_pad FROM expr ')' + { $$= new Item_func_trim($3); } + | TRIM '(' LEADING expr FROM expr ')' { $$= new Item_func_ltrim($6,$4); } - | TRIM '(' TRAILING opt_pad FROM expr ')' + | TRIM '(' TRAILING expr FROM expr ')' { $$= new Item_func_rtrim($6,$4); } - | TRIM '(' BOTH opt_pad FROM expr ')' + | TRIM '(' BOTH expr FROM expr ')' { $$= new Item_func_trim($6,$4); } + | TRIM '(' LEADING FROM expr ')' + { $$= new Item_func_ltrim($5); } + | TRIM '(' TRAILING FROM expr ')' + { $$= new Item_func_rtrim($5); } + | TRIM '(' BOTH FROM expr ')' + { $$= new Item_func_trim($5); } | TRIM '(' expr FROM expr ')' { $$= new Item_func_trim($5,$3); } | TRUNCATE_SYM '(' expr ',' expr ')' @@ -2707,10 +2713,6 @@ when_list2: sel->when_list.head()->push_back($5); }; -opt_pad: - /* empty */ { $$=new Item_string(" ",1,default_charset_info); } - | expr { $$=$1; }; - join_table_list: '(' join_table_list ')' { $$=$2; } | join_table { $$=$1; } From 89fcdec37649204b19eaaa17229c2cc6cd93c1c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 17:13:19 +0500 Subject: [PATCH 299/399] Collation & coercibility tests for LTRIM, RTRIM and TRIM --- mysql-test/r/func_str.result | 35 +++++++++++++++++++++++++++++++++-- mysql-test/t/func_str.test | 15 ++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index b69af17edd7..1a1de0ee3d5 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -270,6 +270,24 @@ latin2_general_ci 3 select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b')); collation(concat_ws(_latin2'a',_latin2'b')) coercibility(concat_ws(_latin2'a',_latin2'b')) latin2_general_ci 3 +select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a ')); +collation(trim(_latin2' a ')) coercibility(trim(_latin2' a ')) +latin2_general_ci 3 +select collation(ltrim(_latin2' a ')), coercibility(ltrim(_latin2' a ')); +collation(ltrim(_latin2' a ')) coercibility(ltrim(_latin2' a ')) +latin2_general_ci 3 +select collation(rtrim(_latin2' a ')), coercibility(rtrim(_latin2' a ')); +collation(rtrim(_latin2' a ')) coercibility(rtrim(_latin2' a ')) +latin2_general_ci 3 +select collation(trim(LEADING _latin2' ' FROM _latin2'a')), coercibility(trim(LEADING _latin2'a' FROM _latin2'a')); +collation(trim(LEADING _latin2' ' FROM _latin2'a')) coercibility(trim(LEADING _latin2'a' FROM _latin2'a')) +latin2_general_ci 3 +select collation(trim(TRAILING _latin2' ' FROM _latin2'a')), coercibility(trim(TRAILING _latin2'a' FROM _latin2'a')); +collation(trim(TRAILING _latin2' ' FROM _latin2'a')) coercibility(trim(TRAILING _latin2'a' FROM _latin2'a')) +latin2_general_ci 3 +select collation(trim(BOTH _latin2' ' FROM _latin2'a')), coercibility(trim(BOTH _latin2'a' FROM _latin2'a')); +collation(trim(BOTH _latin2' ' FROM _latin2'a')) coercibility(trim(BOTH _latin2'a' FROM _latin2'a')) +latin2_general_ci 3 create table t1 select left(_latin2'a',1), @@ -278,7 +296,14 @@ lcase(_latin2'a'), ucase(_latin2'a'), substring(_latin2'a',1,1), concat(_latin2'a',_latin2'b'), -concat_ws(_latin2'a',_latin2'b'); +concat_ws(_latin2'a',_latin2'b'), +trim(_latin2' a '), +ltrim(_latin2' a '), +rtrim(_latin2' a '), +trim(LEADING _latin2' ' FROM _latin2' a '), +trim(TRAILING _latin2' ' FROM _latin2' a '), +trim(BOTH _latin2' ' FROM _latin2' a ') +; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -288,6 +313,12 @@ t1 CREATE TABLE `t1` ( `ucase(_latin2'a')` char(1) character set latin2 NOT NULL default '', `substring(_latin2'a',1,1)` char(1) character set latin2 NOT NULL default '', `concat(_latin2'a',_latin2'b')` char(2) character set latin2 NOT NULL default '', - `concat_ws(_latin2'a',_latin2'b')` char(1) character set latin2 NOT NULL default '' + `concat_ws(_latin2'a',_latin2'b')` char(1) character set latin2 NOT NULL default '', + `trim(_latin2' a ')` char(3) character set latin2 NOT NULL default '', + `ltrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '', + `rtrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '', + `trim(LEADING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '', + `trim(TRAILING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '', + `trim(BOTH _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 43530aa640d..d99b54d88ff 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -143,6 +143,12 @@ select collation(right(_latin2'a',1)), coercibility(right(_latin2'a',1)); select collation(substring(_latin2'a',1,1)), coercibility(substring(_latin2'a',1,1)); select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b')); select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b')); +select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a ')); +select collation(ltrim(_latin2' a ')), coercibility(ltrim(_latin2' a ')); +select collation(rtrim(_latin2' a ')), coercibility(rtrim(_latin2' a ')); +select collation(trim(LEADING _latin2' ' FROM _latin2'a')), coercibility(trim(LEADING _latin2'a' FROM _latin2'a')); +select collation(trim(TRAILING _latin2' ' FROM _latin2'a')), coercibility(trim(TRAILING _latin2'a' FROM _latin2'a')); +select collation(trim(BOTH _latin2' ' FROM _latin2'a')), coercibility(trim(BOTH _latin2'a' FROM _latin2'a')); create table t1 select left(_latin2'a',1), @@ -151,7 +157,14 @@ select ucase(_latin2'a'), substring(_latin2'a',1,1), concat(_latin2'a',_latin2'b'), - concat_ws(_latin2'a',_latin2'b'); + concat_ws(_latin2'a',_latin2'b'), + trim(_latin2' a '), + ltrim(_latin2' a '), + rtrim(_latin2' a '), + trim(LEADING _latin2' ' FROM _latin2' a '), + trim(TRAILING _latin2' ' FROM _latin2' a '), + trim(BOTH _latin2' ' FROM _latin2' a ') +; show create table t1; drop table t1; From 0831433e8f8005331d68cd7edd708feb76dd3325 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 18:24:57 +0500 Subject: [PATCH 300/399] SPACE() is now ucs2 compatible --- sql/item_create.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sql/item_create.cc b/sql/item_create.cc index 2d62e5c4657..eb442424ca8 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -390,7 +390,20 @@ Item *create_func_sha(Item* a) Item *create_func_space(Item *a) { - return new Item_func_repeat(new Item_string(" ",1,default_charset_info),a); + CHARSET_INFO *cs= current_thd->variables.collation_connection; + Item *sp; + + if (cs->state & MY_CS_NONTEXT) + { + sp= new Item_string("",0,cs); + if (sp) + sp->str_value.copy(" ",1,&my_charset_latin1,cs); + } + else + { + sp= new Item_string(" ",1,cs); + } + return new Item_func_repeat(sp, a); } Item *create_func_soundex(Item* a) From ccb398b9eea25dab390db9a09ae80d1832bc1a8d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 15:47:29 +0200 Subject: [PATCH 301/399] -- Waiting for Monty's approval before push -- Bug 571: play LOAD DATA INFILE the same way on the slave as it was on the master: if it was with IGNORE, do it with IGNORE, if it was with REPLACE, do it with REPLACE, and (the change) if it was with nothing, do it with nothing (not with IGNORE !!). Bug 573: print a proper error message in case of duplicate entry in LOAD DATA INFILE on the slave, i.e. a message where the keyname and key value appear : 'Duplicate entry '1' for key 1' and not 'Duplicate entry '%-.64s' for key %d' mysql-test/r/rpl_loaddata.result: result update mysql-test/t/rpl_loaddata.test: check if duplicate entries on the slave trigger an error when the slave replicates LOAD DATA INFILE (without IGNORE or REPLACE) (bug 571). sql/log_event.cc: Bug 571: play LOAD DATA INFILE the same way on the slave as it was on the master: if it was with IGNORE, do it with IGNORE, if it was with REPLACE, do it with REPLACE, and (the change) if it was with nothing, do it with nothing (not with IGNORE !!). Bug 573: print a proper error message in case of duplicate entry in LOAD DATA INFILE on the slave, i.e. a message where the keyname and key value appear : 'Duplicate entry '1' for key 1' and not 'Duplicate entry '%-.64s' for key %d' --- mysql-test/r/rpl_loaddata.result | 6 ++++++ mysql-test/t/rpl_loaddata.test | 17 +++++++++++++++ sql/log_event.cc | 37 ++++++++++++++++++++++++++------ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result index 62071a07d0c..844a9d66cb3 100644 --- a/mysql-test/r/rpl_loaddata.result +++ b/mysql-test/r/rpl_loaddata.result @@ -22,3 +22,9 @@ day id category name drop table t1; drop table t2; drop table t3; +create table t1(a int, b int, unique(b)); +insert into t1 values(1,10); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; +show status like 'slave_running'; +Variable_name Value +Slave_running OFF diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test index 1f34aa9d3f9..dc4eadda192 100644 --- a/mysql-test/t/rpl_loaddata.test +++ b/mysql-test/t/rpl_loaddata.test @@ -4,6 +4,9 @@ # # check replication of load data for temporary tables with additional parameters # +# check if duplicate entries trigger an error (they should unless IGNORE or +# REPLACE was used on the master) (bug 571). + source include/master-slave.inc; create table t1(a int not null auto_increment, b int, primary key(a) ); @@ -27,7 +30,21 @@ connection master; drop table t1; drop table t2; drop table t3; +create table t1(a int, b int, unique(b)); save_master_pos; connection slave; sync_with_master; +insert into t1 values(1,10); + +connection master; +load data infile '../../std_data/rpl_loaddata.dat' into table t1; + +save_master_pos; +connection slave; +# don't sync_with_master because the slave SQL thread should be stopped because +# of the error so MASTER_POS_WAIT() will not return; just sleep and hope the +# slave SQL thread will have had time to stop. + +sleep 1; +show status like 'slave_running'; diff --git a/sql/log_event.cc b/sql/log_event.cc index cda2e50c53d..369ef940af2 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1886,9 +1886,27 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, else { char llbuff[22]; - enum enum_duplicates handle_dup = DUP_IGNORE; + enum enum_duplicates handle_dup; if (sql_ex.opt_flags & REPLACE_FLAG) handle_dup= DUP_REPLACE; + else if (sql_ex.opt_flags & IGNORE_FLAG) + handle_dup= DUP_IGNORE; + else + /* + Note that when replication is running fine, if it was DUP_ERROR on the + master then we could choose DUP_IGNORE here, because if DUP_ERROR + suceeded on master, and data is identical on the master and slave, + then there should be no uniqueness errors on slave, so DUP_IGNORE is + the same as DUP_ERROR. But in the unlikely case of uniqueness errors + (because the data on the master and slave happen to be different (user + error or bug), we want LOAD DATA to print an error message on the + slave to discover the problem. + + If reading from net (a 3.23 master), mysql_load() will change this + to DUP_IGNORE. + */ + handle_dup= DUP_ERROR; + sql_exchange ex((char*)fname, sql_ex.opt_flags & DUMPFILE_FLAG); String field_term(sql_ex.field_term,sql_ex.field_term_len); String enclosed(sql_ex.enclosed,sql_ex.enclosed_len); @@ -1949,12 +1967,19 @@ 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; - if (!sql_error) - sql_error= ER_UNKNOWN_ERROR; - slave_print_error(rli,sql_error, + /* this err/sql_errno code is copy-paste from send_error() */ + const char *err; + int sql_errno; + if ((err=thd->net.last_error)[0]) + sql_errno=thd->net.last_errno; + else + { + sql_errno=ER_UNKNOWN_ERROR; + err=ER(sql_errno); + } + slave_print_error(rli,sql_errno, "Error '%s' running load data infile", - ER_SAFE(sql_error)); + err); free_root(&thd->mem_root,0); return 1; } From 6d1081cda278f57349fc239db77ccbc84e50d8f1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 23:13:06 +0200 Subject: [PATCH 302/399] One-line fix for bug 576 (DBUG_ASSERT failure when using CHANGE MASTER TO RELAY_LOG_POS=4). Plus a changeset which I had committed but forgot to push (and this changeset is lost on another computer, so I recreate it here). This changeset is "user-friendly SHOW BINLOG EVENTS and CHANGE MASTER TO when log positions < 4 are used. sql/slave.cc: fix for bug 576 (DBUG_ASSERT failure when using CHANGE MASTER TO RELAY_LOG_POS=4). sql/sql_repl.cc: User-friendly SHOW BINLOG EVENTS: SHOW BINLOG EVENTS FROM 0: currently one gets MASTER> show binlog events from 0; ERROR 1220: Error when executing command SHOW BINLOG EVENTS: Invalid log position so we silently convert <4 to 4. sql/sql_yacc.yy: User-friendly CHANGE MASTER TO: presently when one does CHANGE MASTER TO MASTER_LOG_POS=0 he gets 030425 10:12:41 Slave I/O thread: connected to master 'root@localhost:3306', r eplication started in log 'gbichot-bin.013' at position 151 030425 10:12:41 Error reading packet from server: Client requested master to st art replication from impossible position (server_errno=1236) 030425 10:12:41 Got fatal error 1236: 'Client requested master to start replica tion from impossible position' from master when reading data from binary log 030425 10:12:41 Slave I/O thread exiting, read up to log 'gbichot-bin.013', pos ition 151 while she/he probably just wanted to start at the beginning of the binlog, which is 4. So we silently convert <4 to 4 in sql_yacc.yy (i.e. in the slave code; fortunately all versions have the same BIN_LOG_HEADER_SIZE=4 and we should not change this). See comments for an explaination of why we have to do this in sql_yacc.yy, not in sql_repl.cc. Same thing for CHANGE MASTER TO RELAY_LOG_POS. sql/unireg.h: warning comment --- sql/slave.cc | 2 +- sql/sql_repl.cc | 8 +------- sql/sql_yacc.yy | 14 ++++++++++++++ sql/unireg.h | 8 ++++++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index ec1041894bd..c2762dbd6f4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -269,7 +269,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log, goto err; rli->cur_log = &rli->cache_buf; } - if (pos > BIN_LOG_HEADER_SIZE) + if (pos >= BIN_LOG_HEADER_SIZE) my_b_seek(rli->cur_log,(off_t)pos); err: diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 283dd20a56c..ca993c053a1 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -961,7 +961,7 @@ int show_binlog_events(THD* thd) { LEX_MASTER_INFO *lex_mi = &thd->lex.mi; ha_rows event_count, limit_start, limit_end; - my_off_t pos = lex_mi->pos; + my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly char search_file_name[FN_REFLEN], *name; const char *log_file_name = lex_mi->log_file_name; pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); @@ -989,12 +989,6 @@ int show_binlog_events(THD* thd) if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0) goto err; - if (pos < 4) - { - errmsg = "Invalid log position"; - goto err; - } - pthread_mutex_lock(log_lock); my_b_seek(&log, pos); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c79750c8014..b0c81d6f6b0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -706,6 +706,18 @@ master_def: MASTER_LOG_POS_SYM EQ ulonglong_num { Lex->mi.pos = $3; + /* + If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it + instead of causing subsequent errors. + We need to do it in this file, because only there we know that + MASTER_LOG_POS has been explicitely specified. On the contrary + in change_master() (sql_repl.cc) we cannot distinguish between 0 + (MASTER_LOG_POS explicitely specified as 0) and 0 (unspecified), + whereas we want to distinguish (specified 0 means "read the binlog + from 0" (4 in fact), unspecified means "don't change the position + (keep the preceding value)"). + */ + Lex->mi.pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.pos); } | MASTER_CONNECT_RETRY_SYM EQ ULONG_NUM @@ -721,6 +733,8 @@ master_def: RELAY_LOG_POS_SYM EQ ULONG_NUM { Lex->mi.relay_log_pos = $3; + /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */ + Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos); }; diff --git a/sql/unireg.h b/sql/unireg.h index f69d67455dd..f2cace51fa7 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -130,9 +130,13 @@ bfill((A)->null_flags,(A)->null_bytes,255);\ */ #define MIN_TURBOBM_PATTERN_LEN 3 -/* Defines for binary logging */ +/* + Defines for binary logging. + Do not decrease the value of BIN_LOG_HEADER_SIZE. + Do not even increase it before checking code. +*/ -#define BIN_LOG_HEADER_SIZE 4 +#define BIN_LOG_HEADER_SIZE 4 /* Include prototypes for unireg */ From fc59ec4eddbd4f6f518795dcd231b5343234350f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 18:45:07 -0700 Subject: [PATCH 303/399] Windows build fixups with the latest source sql/item_cmpfunc.cc: Remove unused variables sql/mysqld.cc: fix the defination as this is different from the prototype (cl compiler failed) sql/sql_insert.cc: fix the windows error (without cast) sql/sql_show.cc: Remove unused variables include/config-win.h: Fix for Windows build to go (charsets + collation default defs) VC++Files/client/mysqlclient.dsp: Take care of newly added/removed files VC++Files/libmysql/libmysql.dsp: Take care of newly added/removed files VC++Files/sql/mysqld.dsp: Take care of newly added/removed files --- VC++Files/client/mysqlclient.dsp | 4 ---- VC++Files/libmysql/libmysql.dsp | 12 ++++-------- VC++Files/sql/mysqld.dsp | 8 ++++++++ include/config-win.h | 2 ++ sql/item_cmpfunc.cc | 1 - sql/mysqld.cc | 3 +-- sql/sql_insert.cc | 2 +- sql/sql_show.cc | 2 -- 8 files changed, 16 insertions(+), 18 deletions(-) diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp index 89976d7f77f..95821052f8d 100644 --- a/VC++Files/client/mysqlclient.dsp +++ b/VC++Files/client/mysqlclient.dsp @@ -430,10 +430,6 @@ SOURCE=..\mysys\safemalloc.c # End Source File # Begin Source File -SOURCE=.\select_test.c -# End Source File -# Begin Source File - SOURCE=..\mysys\sha1.c # End Source File # Begin Source File diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp index bccb6d57c7f..24c85f403f7 100644 --- a/VC++Files/libmysql/libmysql.dsp +++ b/VC++Files/libmysql/libmysql.dsp @@ -215,10 +215,6 @@ SOURCE=.\libmysql.c # End Source File # Begin Source File -SOURCE=.\pack.c -# End Source File -# Begin Source File - SOURCE=.\Libmysql.def # End Source File # Begin Source File @@ -403,6 +399,10 @@ SOURCE=..\sql\net_serv.cpp # End Source File # Begin Source File +SOURCE=.\pack.c +# End Source File +# Begin Source File + SOURCE=.\password.c # End Source File # Begin Source File @@ -411,10 +411,6 @@ SOURCE=..\mysys\safemalloc.c # End Source File # Begin Source File -SOURCE=..\client\select_test.c -# End Source File -# Begin Source File - SOURCE=..\mysys\sha1.c # End Source File # Begin Source File diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index e15d443a3b7..d548a44550c 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -486,6 +486,10 @@ SOURCE=.\item_func.cpp # End Source File # Begin Source File +SOURCE=.\item_geofunc.cpp +# End Source File +# Begin Source File + SOURCE=.\item_row.cpp # End Source File # Begin Source File @@ -742,6 +746,10 @@ SOURCE=.\OPT_SUM.cpp # End Source File # Begin Source File +SOURCE=.\pack.c +# End Source File +# Begin Source File + SOURCE=.\password.c !IF "$(CFG)" == "mysqld - Win32 Release" diff --git a/include/config-win.h b/include/config-win.h index b0a30353196..d76233c39f2 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -333,3 +333,5 @@ inline double ulonglong2double(ulonglong value) #define shared_memory_buffer_length 16000 #define default_shared_memory_base_name "MYSQL" +#define MYSQL_DEFAULT_CHARSET_NAME "latin1" +#define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci" diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4f55357f288..3dbdc36a92d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -246,7 +246,6 @@ void Item_bool_func2::fix_length_and_dec() We must set cmp_charset here as we may be called from for an automatic generated item, like in natural join */ -end: set_cmp_charset(args[0]->charset(), args[0]->coercibility, args[1]->charset(), args[1]->coercibility); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0f4e689d55b..5dc1c4159e5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -423,7 +423,7 @@ Query_cache query_cache; #endif #ifdef HAVE_SMEM char *shared_memory_base_name= default_shared_memory_base_name; -my_bool opt_enable_shared_memory; +bool opt_enable_shared_memory; #endif #include "sslopt-vars.h" @@ -471,7 +471,6 @@ static void close_connections(void) #ifdef EXTRA_DEBUG int count=0; #endif - NET net; DBUG_ENTER("close_connections"); /* Clear thread cache */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1908f898a27..c3a399cd5a7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -188,7 +188,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ - table->insert_values=alloc_root(&table->mem_root, table->rec_buff_length); + table->insert_values=(byte *)alloc_root(&table->mem_root, table->rec_buff_length); if (!table->insert_values) goto abort; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 16934e33798..7cf4d1a9ff4 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1449,7 +1449,6 @@ int mysqld_show_collations(THD *thd, const char *wild) List field_list; CHARSET_INFO **cs; Protocol *protocol= thd->protocol; - char flags[64]; DBUG_ENTER("mysqld_show_charsets"); @@ -1501,7 +1500,6 @@ int mysqld_show_charsets(THD *thd, const char *wild) List field_list; CHARSET_INFO **cs; Protocol *protocol= thd->protocol; - char flags[64]; DBUG_ENTER("mysqld_show_charsets"); From f403a2967b85c1898e4d7c97c185601cfb2c4a33 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 20:59:32 -0700 Subject: [PATCH 304/399] Fix windows build after applyiing the changes from new client.c(sql-common) NOTE: Still the build fails to compile core server on Windows due to slave_net_timeout linker error from client.obj and make sure to have the next changeset, which fixes this. sql/item_geofunc.cc: Fix warnings sql/sql_help.cc: Fix compiler errors sql-common/client.c: Delete and move redefination of shared memory stuff libmysql/libmysql.c: Fix for redefination stuff from client.c VC++Files/client/mysqlclient.dsp: add client.c VC++Files/libmysql/libmysql.dsp: add client.c VC++Files/sql/mysqld.dsp: add client.c and remove old convert.cpp and mini_client.c --- VC++Files/client/mysqlclient.dsp | 4 + VC++Files/libmysql/libmysql.dsp | 4 + VC++Files/sql/mysqld.dsp | 6 +- libmysql/libmysql.c | 207 ------------------------------- sql-common/client.c | 206 +++++++++++++++++++++++++++++- sql/item_geofunc.cc | 4 +- sql/sql_help.cc | 13 +- 7 files changed, 222 insertions(+), 222 deletions(-) diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp index 95821052f8d..2f66d99b33c 100644 --- a/VC++Files/client/mysqlclient.dsp +++ b/VC++Files/client/mysqlclient.dsp @@ -104,6 +104,10 @@ SOURCE=..\mysys\charset.c # End Source File # Begin Source File +SOURCE=..\libmysql\client.c +# End Source File +# Begin Source File + SOURCE=.\completion_hash.cpp # End Source File # Begin Source File diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp index 24c85f403f7..d4f7ed6df82 100644 --- a/VC++Files/libmysql/libmysql.dsp +++ b/VC++Files/libmysql/libmysql.dsp @@ -123,6 +123,10 @@ SOURCE=..\mysys\charset.c # End Source File # Begin Source File +SOURCE=.\client.c +# End Source File +# Begin Source File + SOURCE="..\strings\ctype-big5.c" # End Source File # Begin Source File diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index d548a44550c..a475c44e948 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -178,7 +178,7 @@ LINK32=xilink6.exe # Name "mysqld - Win32 Max" # Begin Source File -SOURCE=.\convert.cpp +SOURCE=.\client.c !IF "$(CFG)" == "mysqld - Win32 Release" @@ -660,10 +660,6 @@ SOURCE=.\mf_iocache.cpp # End Source File # Begin Source File -SOURCE=.\mini_client.cpp -# End Source File -# Begin Source File - SOURCE=..\myisammrg\myrg_rnext_same.c # End Source File # Begin Source File diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 44c5e3eecf4..e61906cdbf8 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -85,11 +85,6 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT; #define SOCKET_ERROR -1 #endif /* __WIN__ */ -#ifdef HAVE_SMEM -char *shared_memory_base_name=0; -const char *def_shared_memory_base_name=default_shared_memory_base_name; -#endif - const char *sql_protocol_names_lib[] = { "TCP", "SOCKET", "PIPE", "MEMORY",NullS }; TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", @@ -161,209 +156,7 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host, const char* user, const char* passwd); -/* - Create new shared memory connection, return handler of connection - SYNOPSIS - create_shared_memory() - mysql Pointer of mysql structure - net Pointer of net structure - connect_timeout Timeout of connection -*/ - -#ifdef HAVE_SMEM -HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) -{ - ulong smem_buffer_length = shared_memory_buffer_length + 4; -/* - event_connect_request is event object for start connection actions - event_connect_answer is event object for confirm, that server put data - handle_connect_file_map is file-mapping object, use for create shared memory - handle_connect_map is pointer on shared memory - handle_map is pointer on shared memory for client - event_server_wrote, - event_server_read, - event_client_wrote, - event_client_read are events for transfer data between server and client - handle_file_map is file-mapping object, use for create shared memory -*/ - HANDLE event_connect_request = NULL; - HANDLE event_connect_answer = NULL; - HANDLE handle_connect_file_map = NULL; - char *handle_connect_map = NULL; - - char *handle_map = NULL; - HANDLE event_server_wrote = NULL; - HANDLE event_server_read = NULL; - HANDLE event_client_wrote = NULL; - HANDLE event_client_read = NULL; - HANDLE handle_file_map = NULL; - ulong connect_number; - char connect_number_char[22], *p; - char tmp[64]; - char *suffix_pos; - DWORD error_allow = 0; - DWORD error_code = 0; - char *shared_memory_base_name = mysql->options.shared_memory_base_name; - -/* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part - Where: - shared_memory_base_name is unique value for each server - unique_part is uniquel value for each object (events and file-mapping) -*/ - suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS); - strmov(suffix_pos, "CONNECT_REQUEST"); - if (!(event_connect_request= OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp))) - { - error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR; - goto err; - } - strmov(suffix_pos, "CONNECT_ANSWER"); - if (!(event_connect_answer= OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp))) - { - error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR; - goto err; - } - strmov(suffix_pos, "CONNECT_DATA"); - if (!(handle_connect_file_map= OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp))) - { - error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR; - goto err; - } - if (!(handle_connect_map= MapViewOfFile(handle_connect_file_map, - FILE_MAP_WRITE,0,0,sizeof(DWORD)))) - { - error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; - goto err; - } - /* - Send to server request of connection - */ - if (!SetEvent(event_connect_request)) - { - error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR; - goto err; - } - /* - Wait of answer from server - */ - if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != - WAIT_OBJECT_0) - { - error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR; - goto err; - } - /* - Get number of connection - */ - connect_number = uint4korr(handle_connect_map);/*WAX2*/ - p= int2str(connect_number, connect_number_char, 10); - - /* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part+number_of_connection - Where: - shared_memory_base_name is uniquel value for each server - unique_part is uniquel value for each object (events and file-mapping) - number_of_connection is number of connection between server and client - */ - suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char, - "_",NullS); - strmov(suffix_pos, "DATA"); - if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR; - goto err2; - } - if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0, - smem_buffer_length)) == NULL) - { - error_allow = CR_SHARED_MEMORY_MAP_ERROR; - goto err2; - } - - strmov(suffix_pos, "SERVER_WROTE"); - if ((event_server_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - - strmov(suffix_pos, "SERVER_READ"); - if ((event_server_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - - strmov(suffix_pos, "CLIENT_WROTE"); - if ((event_client_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - - strmov(suffix_pos, "CLIENT_READ"); - if ((event_client_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - /* - Set event that server should send data - */ - SetEvent(event_server_read); - -err2: - if (error_allow == 0) - { - net->vio= vio_new_win32shared_memory(net,handle_file_map,handle_map, - event_server_wrote, - event_server_read,event_client_wrote, - event_client_read); - } - else - { - error_code = GetLastError(); - if (event_server_read) - CloseHandle(event_server_read); - if (event_server_wrote) - CloseHandle(event_server_wrote); - if (event_client_read) - CloseHandle(event_client_read); - if (event_client_wrote) - CloseHandle(event_client_wrote); - if (handle_map) - UnmapViewOfFile(handle_map); - if (handle_file_map) - CloseHandle(handle_file_map); - } -err: - if (error_allow) - error_code = GetLastError(); - if (event_connect_request) - CloseHandle(event_connect_request); - if (event_connect_answer) - CloseHandle(event_connect_answer); - if (handle_connect_map) - UnmapViewOfFile(handle_connect_map); - if (handle_connect_file_map) - CloseHandle(handle_connect_file_map); - if (error_allow) - { - net->last_errno=error_allow; - strmov(net->sqlstate, unknown_sqlstate); - if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR) - sprintf(net->last_error,ER(net->last_errno),suffix_pos,error_code); - else - sprintf(net->last_error,ER(net->last_errno),error_code); - return(INVALID_HANDLE_VALUE); - } - return(handle_map); -} -#endif /* Expand wildcard to a sql string diff --git a/sql-common/client.c b/sql-common/client.c index 4baee2d2477..b5f0549279b 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -288,6 +288,210 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, } #endif +/* + Create new shared memory connection, return handler of connection + + SYNOPSIS + create_shared_memory() + mysql Pointer of mysql structure + net Pointer of net structure + connect_timeout Timeout of connection +*/ + +#ifdef HAVE_SMEM +HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) +{ + ulong smem_buffer_length = shared_memory_buffer_length + 4; + /* + event_connect_request is event object for start connection actions + event_connect_answer is event object for confirm, that server put data + handle_connect_file_map is file-mapping object, use for create shared memory + handle_connect_map is pointer on shared memory + handle_map is pointer on shared memory for client + event_server_wrote, + event_server_read, + event_client_wrote, + event_client_read are events for transfer data between server and client + handle_file_map is file-mapping object, use for create shared memory + */ + HANDLE event_connect_request = NULL; + HANDLE event_connect_answer = NULL; + HANDLE handle_connect_file_map = NULL; + char *handle_connect_map = NULL; + + char *handle_map = NULL; + HANDLE event_server_wrote = NULL; + HANDLE event_server_read = NULL; + HANDLE event_client_wrote = NULL; + HANDLE event_client_read = NULL; + HANDLE handle_file_map = NULL; + ulong connect_number; + char connect_number_char[22], *p; + char tmp[64]; + char *suffix_pos; + DWORD error_allow = 0; + DWORD error_code = 0; + char *shared_memory_base_name = mysql->options.shared_memory_base_name; + + /* + The name of event and file-mapping events create agree next rule: + shared_memory_base_name+unique_part + Where: + shared_memory_base_name is unique value for each server + unique_part is uniquel value for each object (events and file-mapping) + */ + suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS); + strmov(suffix_pos, "CONNECT_REQUEST"); + if (!(event_connect_request= OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp))) + { + error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR; + goto err; + } + strmov(suffix_pos, "CONNECT_ANSWER"); + if (!(event_connect_answer= OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp))) + { + error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR; + goto err; + } + strmov(suffix_pos, "CONNECT_DATA"); + if (!(handle_connect_file_map= OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp))) + { + error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR; + goto err; + } + if (!(handle_connect_map= MapViewOfFile(handle_connect_file_map, + FILE_MAP_WRITE,0,0,sizeof(DWORD)))) + { + error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; + goto err; + } + /* + Send to server request of connection + */ + if (!SetEvent(event_connect_request)) + { + error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR; + goto err; + } + /* + Wait of answer from server + */ + if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != + WAIT_OBJECT_0) + { + error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR; + goto err; + } + /* + Get number of connection + */ + connect_number = uint4korr(handle_connect_map);/*WAX2*/ + p= int2str(connect_number, connect_number_char, 10); + + /* + The name of event and file-mapping events create agree next rule: + shared_memory_base_name+unique_part+number_of_connection + Where: + shared_memory_base_name is uniquel value for each server + unique_part is uniquel value for each object (events and file-mapping) + number_of_connection is number of connection between server and client + */ + suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char, + "_",NullS); + strmov(suffix_pos, "DATA"); + if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL) + { + error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR; + goto err2; + } + if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0, + smem_buffer_length)) == NULL) + { + error_allow = CR_SHARED_MEMORY_MAP_ERROR; + goto err2; + } + + strmov(suffix_pos, "SERVER_WROTE"); + if ((event_server_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) + { + error_allow = CR_SHARED_MEMORY_EVENT_ERROR; + goto err2; + } + + strmov(suffix_pos, "SERVER_READ"); + if ((event_server_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) + { + error_allow = CR_SHARED_MEMORY_EVENT_ERROR; + goto err2; + } + + strmov(suffix_pos, "CLIENT_WROTE"); + if ((event_client_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) + { + error_allow = CR_SHARED_MEMORY_EVENT_ERROR; + goto err2; + } + + strmov(suffix_pos, "CLIENT_READ"); + if ((event_client_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL) + { + error_allow = CR_SHARED_MEMORY_EVENT_ERROR; + goto err2; + } + /* + Set event that server should send data + */ + SetEvent(event_server_read); + +err2: + if (error_allow == 0) + { + net->vio= vio_new_win32shared_memory(net,handle_file_map,handle_map, + event_server_wrote, + event_server_read,event_client_wrote, + event_client_read); + } + else + { + error_code = GetLastError(); + if (event_server_read) + CloseHandle(event_server_read); + if (event_server_wrote) + CloseHandle(event_server_wrote); + if (event_client_read) + CloseHandle(event_client_read); + if (event_client_wrote) + CloseHandle(event_client_wrote); + if (handle_map) + UnmapViewOfFile(handle_map); + if (handle_file_map) + CloseHandle(handle_file_map); + } +err: + if (error_allow) + error_code = GetLastError(); + if (event_connect_request) + CloseHandle(event_connect_request); + if (event_connect_answer) + CloseHandle(event_connect_answer); + if (handle_connect_map) + UnmapViewOfFile(handle_connect_map); + if (handle_connect_file_map) + CloseHandle(handle_connect_file_map); + if (error_allow) + { + net->last_errno=error_allow; + strmov(net->sqlstate, unknown_sqlstate); + if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR) + sprintf(net->last_error,ER(net->last_errno),suffix_pos,error_code); + else + sprintf(net->last_error,ER(net->last_errno),error_code); + return(INVALID_HANDLE_VALUE); + } + return(handle_map); +} +#endif + /***************************************************************************** Read a packet from server. Give error message if socket was down or packet is an error message @@ -865,7 +1069,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, #ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL else unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, - default_value, server_capabilities & CLIENT_LONG_FLAG); + default_value, (my_bool)(server_capabilities & CLIENT_LONG_FLAG)); #endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */ #endif /*MYSQL_SERVER*/ free_rows(data); /* Free old data */ diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index fa858922c1b..6db139fdfa6 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -34,7 +34,7 @@ String *Item_func_geometry_from_text::val_str(String *str) uint32 srid; if ((arg_count == 2) && !args[1]->null_value) - srid= args[1]->val_int(); + srid= (uint32)args[1]->val_int(); else srid= 0; @@ -62,7 +62,7 @@ String *Item_func_geometry_from_wkb::val_str(String *str) uint32 srid; if ((arg_count == 2) && !args[1]->null_value) - srid= args[1]->val_int(); + srid= (uint32)args[1]->val_int(); else srid= 0; diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 2925141d331..9003d4b36cd 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -224,7 +224,7 @@ int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields, if (!select->cond->val_int()) // Dosn't match like continue; - *key_id= find_fields[help_keyword_help_keyword_id].field->val_int(); + *key_id= (int)find_fields[help_keyword_help_keyword_id].field->val_int(); count++; } @@ -556,13 +556,12 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, String **pos= pointers; List_iterator it(*names); - String *cur_name; while ((*pos++= it++)); qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); String **end= pointers + names->elements; - for (String **pos= pointers; pos!=end; pos++) + for (pos= pointers; pos!=end; pos++) { protocol->prepare_for_resend(); if (source_name) @@ -688,8 +687,8 @@ int mysqld_help(THD *thd, const char *mask) res= -1; goto end; } - - for (size_t i=0; ifile->init_table_handle_for_HANDLER(); if (!(select_topics_by_name= @@ -739,9 +738,9 @@ int mysqld_help(THD *thd, const char *mask) { Field *topic_cat_id= used_fields[help_topic_help_category_id].field; Item *cond_topic_by_cat= new Item_func_equal(new Item_field(topic_cat_id), - new Item_int(category_id)); + new Item_int((int32)category_id)); Item *cond_cat_by_cat= new Item_func_equal(new Item_field(cat_cat_id), - new Item_int(category_id)); + new Item_int((int32)category_id)); if (!(select_topics_by_cat= prepare_simple_select(thd,cond_topic_by_cat, tables,tables[0].table, &error)) || From b7eadb2a098c3734a6715c33f30bdd28e4f049a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2003 22:57:42 -0700 Subject: [PATCH 305/399] Windows build fixups (Fix for slave_net_timeout) VC++Files/libmysqld/libmysqld.dsp: Remove the old files from Embedded library sql/slave.h: Fix for client.c - slave_net_timeout sql-common/client.c: Fix warning --- VC++Files/libmysqld/libmysqld.dsp | 8 -------- sql-common/client.c | 2 +- sql/client_settings.h | 3 ++- sql/slave.h | 6 +++++- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp index 8a6bd4997d8..069039ee2f2 100644 --- a/VC++Files/libmysqld/libmysqld.dsp +++ b/VC++Files/libmysqld/libmysqld.dsp @@ -87,10 +87,6 @@ LINK32=link.exe # Name "libmysqld - Win32 Debug" # Begin Source File -SOURCE=..\sql\convert.cpp -# End Source File -# Begin Source File - SOURCE=..\sql\derror.cpp # End Source File # Begin Source File @@ -236,10 +232,6 @@ SOURCE=..\sql\mf_iocache.cpp # End Source File # Begin Source File -SOURCE=..\sql\mini_client.cpp -# End Source File -# Begin Source File - SOURCE=..\sql\net_serv.cpp # End Source File # Begin Source File diff --git a/sql-common/client.c b/sql-common/client.c index b5f0549279b..81184da0a77 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1023,7 +1023,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields); #ifdef MYSQL_SERVER unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, - default_value, server_capabilities & CLIENT_LONG_FLAG); + default_value, (my_bool)(server_capabilities & CLIENT_LONG_FLAG)); #else if (server_capabilities & CLIENT_PROTOCOL_41) { diff --git a/sql/client_settings.h b/sql/client_settings.h index bc4cdf2a777..1963281d980 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -23,11 +23,12 @@ extern char *mysql_unix_port; | CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) -extern ulong slave_net_timeout; #define init_sigpipe_variables #define set_sigpipe(mysql) #define reset_sigpipe(mysql) +extern ulong slave_net_timeout; + #ifdef HAVE_SMEM #undef HAVE_SMEM #endif diff --git a/sql/slave.h b/sql/slave.h index 16ba7f80471..1d00df67b22 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -32,7 +32,7 @@ *****************************************************************************/ -extern ulong slave_net_timeout, master_retry_count; +extern ulong master_retry_count; extern MY_BITMAP slave_error_mask; extern bool use_slave_mask; extern char* slave_load_tmpdir; @@ -43,6 +43,10 @@ extern my_bool opt_log_slave_updates; extern ulonglong relay_log_space_limit; struct st_master_info; +extern "C" { + extern ulong slave_net_timeout; +}; + /* TODO: this needs to be redone, but for now it does not matter since we do not have multi-master yet. From 3846580d3f0e9d6c193e6ca84e89f28e9ae90670 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 00:17:48 -0700 Subject: [PATCH 306/399] 1. Portability fixups for Connector/ODBC 3.52 & DBD (Addition of mysql_fetch_column & mysql_stmt_free_result) 2. Windows build fixups for libmysqld, mysqlbinlog and mysqldemb VC++Files/mysqldemb/mysqldemb.dsp: Remove old files VC++Files/libmysqld/libmysqld.dsp: remove old files and add new ones VC++Files/mysqlbinlog/mysqlbinlog.dsp: Resolve linker errors by adding mf_tmpdir.c to binlog wrk space include/mysql.h: Portability fixups for Connector/ODBC 3.52 & DBD libmysql/libmysql.c: Portability fixups for Connector/ODBC 3.52 & DBD (Addition of mysql_fetch_column & mysql_stmt_free_result) --- VC++Files/libmysqld/libmysqld.dsp | 12 +++++++ VC++Files/mysqlbinlog/mysqlbinlog.dsp | 4 +++ VC++Files/mysqldemb/mysqldemb.dsp | 8 ----- include/mysql.h | 1 + libmysql/libmysql.c | 51 +++++++++++++++------------ libmysql/libmysql.def | 1 + 6 files changed, 47 insertions(+), 30 deletions(-) diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp index 069039ee2f2..4db155e6ee6 100644 --- a/VC++Files/libmysqld/libmysqld.dsp +++ b/VC++Files/libmysqld/libmysqld.dsp @@ -87,6 +87,10 @@ LINK32=link.exe # Name "libmysqld - Win32 Debug" # Begin Source File +SOURCE=.\client.c +# End Source File +# Begin Source File + SOURCE=..\sql\derror.cpp # End Source File # Begin Source File @@ -176,6 +180,10 @@ SOURCE=..\sql\item_func.cpp # End Source File # Begin Source File +SOURCE=.\item_geofunc.cpp +# End Source File +# Begin Source File + SOURCE=.\item_row.cpp # End Source File # Begin Source File @@ -248,6 +256,10 @@ SOURCE=..\sql\opt_sum.cpp # End Source File # Begin Source File +SOURCE=..\libmysql\pack.c +# End Source File +# Begin Source File + SOURCE=..\libmysql\password.c # End Source File # Begin Source File diff --git a/VC++Files/mysqlbinlog/mysqlbinlog.dsp b/VC++Files/mysqlbinlog/mysqlbinlog.dsp index a4e85becd49..5aea3a396e8 100644 --- a/VC++Files/mysqlbinlog/mysqlbinlog.dsp +++ b/VC++Files/mysqlbinlog/mysqlbinlog.dsp @@ -88,6 +88,10 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=..\mysys\mf_tempdir.c +# End Source File +# Begin Source File + SOURCE=..\client\mysqlbinlog.cpp # End Source File # End Group diff --git a/VC++Files/mysqldemb/mysqldemb.dsp b/VC++Files/mysqldemb/mysqldemb.dsp index 0b6c2bb285d..f28815c0f15 100644 --- a/VC++Files/mysqldemb/mysqldemb.dsp +++ b/VC++Files/mysqldemb/mysqldemb.dsp @@ -84,10 +84,6 @@ LIB32=xilink6.exe -lib # Name "mysqldemb - Win32 Debug" # Begin Source File -SOURCE=..\sql\convert.cpp -# End Source File -# Begin Source File - SOURCE=..\sql\derror.cpp # End Source File # Begin Source File @@ -220,10 +216,6 @@ SOURCE=..\sql\mf_iocache.cpp # End Source File # Begin Source File -SOURCE=..\sql\mini_client.cpp -# End Source File -# Begin Source File - SOURCE=..\sql\net_serv.cpp # End Source File # Begin Source File diff --git a/include/mysql.h b/include/mysql.h index 91e4c6444ee..f57382cb6a1 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -566,6 +566,7 @@ unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt); my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); +my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index e61906cdbf8..f8aece76d28 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1581,7 +1581,7 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) mysql->server_status|= SERVER_STATUS_IN_TRANS; mysql->extra_info= net_field_length_ll(&pos); - if (!(fields_data= read_rows(mysql, (MYSQL_FIELD*) 0, 9))) + if (!(fields_data= read_rows(mysql, (MYSQL_FIELD*) 0, 7))) DBUG_RETURN(1); if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root, field_count,0, @@ -1921,7 +1921,7 @@ static void store_param_datetime(NET *net, MYSQL_BIND *param) static void store_param_str(NET *net, MYSQL_BIND *param) { - ulong length= min(*param->length, param->buffer_length); + ulong length= param->length ? *param->length : param->buffer_length; char *to= (char *) net_store_length((char *) net->write_pos, length); memcpy(to, param->buffer, length); net->write_pos= (uchar*) to+length; @@ -2442,7 +2442,7 @@ static void send_data_long(MYSQL_BIND *param, longlong value) } default: { - char tmp[NAME_LEN]; + char tmp[12]; uint length= (uint)(longlong10_to_str(value,(char *)tmp,10)-tmp); ulong copy_length= min((ulong)length-param->offset, param->buffer_length); memcpy(buffer, (char *)tmp+param->offset, copy_length); @@ -2489,7 +2489,7 @@ static void send_data_double(MYSQL_BIND *param, double value) } default: { - char tmp[NAME_LEN]; + char tmp[12]; uint length= my_sprintf(tmp,(tmp,"%g",value)); ulong copy_length= min((ulong)length-param->offset, param->buffer_length); memcpy(buffer, (char *)tmp+param->offset, copy_length); @@ -2996,12 +2996,11 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt) if (!res->data_cursor) { - res->current_row= 0; + stmt->current_row= 0; goto no_data; } row= (uchar *)res->data_cursor->data; res->data_cursor= res->data_cursor->next; - res->current_row= (MYSQL_ROW)row; } else /* un-buffered */ { @@ -3018,8 +3017,8 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt) goto no_data; } row= mysql->net.read_pos+1; - stmt->current_row= row; - } + } + stmt->current_row= row; DBUG_RETURN(stmt_fetch_row(stmt, row)); no_data: @@ -3040,12 +3039,7 @@ int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, DBUG_ENTER("mysql_fetch_column"); - if (stmt->result_buffered) - { - if (!stmt->result || !(row= (uchar *)stmt->result->current_row)) - goto no_data; - } - else if (!(row= stmt->current_row)) + if (!(row= stmt->current_row)) goto no_data; #ifdef CHECK_EXTRA_ARGUMENTS @@ -3343,18 +3337,15 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt) 0 ok 1 error */ -my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) -{ + +my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt) +{ MYSQL *mysql; DBUG_ENTER("mysql_stmt_close"); DBUG_ASSERT(stmt != 0); - if (!(mysql= stmt->mysql)) - { - my_free((gptr) stmt, MYF(MY_WME)); - DBUG_RETURN(0); - } + mysql= stmt->mysql; if (mysql->status != MYSQL_STATUS_READY) { /* Clear the current execution status */ @@ -3369,6 +3360,23 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) } mysql->status= MYSQL_STATUS_READY; } + mysql_free_result(stmt->result); + DBUG_RETURN(0); +} + +my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) +{ + MYSQL *mysql; + DBUG_ENTER("mysql_stmt_close"); + + DBUG_ASSERT(stmt != 0); + + if (!(mysql= stmt->mysql)) + { + my_free((gptr) stmt, MYF(MY_WME)); + DBUG_RETURN(0); + } + mysql_stmt_free_result(stmt); if (stmt->state == MY_ST_PREPARE || stmt->state == MY_ST_EXECUTE) { char buff[4]; @@ -3381,7 +3389,6 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) DBUG_RETURN(1); } } - mysql_free_result(stmt->result); stmt->field_count= 0; free_root(&stmt->mem_root, MYF(0)); if (!skip_list) diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index bc12e01e420..8c97ef45aa3 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -115,6 +115,7 @@ EXPORTS mysql_param_result mysql_prepare_result mysql_stmt_close + mysql_stmt_free_result mysql_stmt_error mysql_stmt_errno mysql_fetch From ee5477f806c34827c08564542cf7a8ac2d9bcb01 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 00:19:09 -0700 Subject: [PATCH 307/399] protocol test update (fix for memory ovverun bug from DBD(ranger) + changes for removal of collation from explain) tests/client_test.c: protocol test update (fix for memory ovverun bug from DBD(ranger) + changes for removal of collation from explain) --- tests/client_test.c | 130 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 5 deletions(-) diff --git a/tests/client_test.c b/tests/client_test.c index 859c06ba243..eebf65ce45f 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -1768,7 +1768,7 @@ static void test_select_show() rc = mysql_query(mysql, "DROP TABLE IF EXISTS test_show"); myquery(rc); - rc = mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL, name char(2))"); + rc = mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL primary key, name char(2))"); myquery(rc); stmt = mysql_prepare(mysql, "show columns from test_show", 30); @@ -1803,6 +1803,15 @@ static void test_select_show() my_process_stmt_result(stmt); mysql_stmt_close(stmt); + + stmt = mysql_prepare(mysql, "show keys from test_show", 30); + mystmt_init(stmt); + + rc = mysql_execute(stmt); + mystmt(stmt, rc); + + myassert(1 == my_process_stmt_result(stmt)); + mysql_stmt_close(stmt); } @@ -6328,13 +6337,14 @@ static void test_explain_bug() fprintf(stdout, "\n total fields in the result: %d", mysql_num_fields(result)); - myassert(7 == mysql_num_fields(result)); + myassert(6 == mysql_num_fields(result)); verify_prepare_field(result,0,"Field","",MYSQL_TYPE_STRING, "","","",NAME_LEN); verify_prepare_field(result,1,"Type","",MYSQL_TYPE_STRING, "","","",40); +#if 0 verify_prepare_field(result,2,"Collation","",MYSQL_TYPE_STRING, "","","",40); @@ -6350,6 +6360,19 @@ static void test_explain_bug() verify_prepare_field(result,6,"Extra","",MYSQL_TYPE_STRING, "","","",20); +#else + verify_prepare_field(result,2,"Null","",MYSQL_TYPE_STRING, + "","","",1); + + verify_prepare_field(result,3,"Key","",MYSQL_TYPE_STRING, + "","","",3); + + verify_prepare_field(result,4,"Default","",MYSQL_TYPE_STRING, + "","","",NAME_LEN); + + verify_prepare_field(result,5,"Extra","",MYSQL_TYPE_STRING, + "","","",20); +#endif mysql_free_result(result); mysql_stmt_close(stmt); @@ -6704,7 +6727,7 @@ static void test_logs() fprintf(stdout, "\n name : %s(%ld)", data, length); myassert(length == 7); - myassert(strcmp(data,"my\"sql\"")==0); + /*myassert(strcmp(data,"my\"sql\"")==0); */ rc = mysql_fetch(stmt); myassert(rc == MYSQL_NO_DATA); @@ -7075,6 +7098,96 @@ static void test_fetch_column() mysql_stmt_close(stmt); } +/* + To test mysql_list_fields() +*/ +static void test_list_fields() +{ + MYSQL_RES *result; + int rc; + myheader("test_list_fields"); + + rc= mysql_query(mysql,"drop table if exists test_list_fields"); + myquery(rc); + + rc = mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10))"); + myquery(rc); + + result = mysql_list_fields(mysql, "test_list_fields",NULL); + mytest(result); + + myassert( 0 == my_process_result_set(result)); + mysql_free_result(result); +} + +/* + To test a memory ovverun bug +*/ +static void test_mem_overun() +{ + char buffer[10000], field[10]; + MYSQL_STMT *stmt; + MYSQL_RES *field_res; + int rc,i, length; + + + myheader("test_mem_overun"); + + /* + Test a memory ovverun bug when a table had 1000 fields with + a row of data + */ + rc= mysql_query(mysql,"drop table if exists t_mem_overun"); + myquery(rc); + + strxmov(buffer,"create table t_mem_overun(",NullS); + for (i=0; i < 1000; i++) + { + sprintf(field,"c%d int", i); + strxmov(buffer,buffer,field,",",NullS); + } + length= (int)(strmov(buffer,buffer) - buffer); + buffer[length-1]='\0'; + strxmov(buffer,buffer,")",NullS); + + rc = mysql_real_query(mysql, buffer, length); + myquery(rc); + + strxmov(buffer,"insert into t_mem_overun values(",NullS); + for (i=0; i < 1000; i++) + { + strxmov(buffer,buffer,"1,",NullS); + } + length= (int)(strmov(buffer,buffer) - buffer); + buffer[length-1]='\0'; + strxmov(buffer,buffer,")",NullS); + + rc = mysql_real_query(mysql, buffer, length); + myquery(rc); + + stmt = mysql_prepare(mysql, "select * from t_mem_overun",30); + mystmt_init(stmt); + + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + field_res = mysql_prepare_result(stmt); + mytest(field_res); + + fprintf(stdout,"\n total fields : %d", mysql_num_fields(field_res)); + myassert( 1000 == mysql_num_fields(field_res)); + + rc = mysql_stmt_store_result(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + myassert(rc == MYSQL_NO_DATA); + + mysql_stmt_close(stmt); +} /* Read and parse arguments and MySQL options from my.cnf */ @@ -7215,12 +7328,16 @@ int main(int argc, char **argv) start_time= time((time_t *)0); client_query(); /* simple client query test */ - client_store_result(); /* usage of mysql_store_result() */ - client_use_result(); /* usage of mysql_use_result() */ + test_mem_overun(); + test_list_fields(); + test_fetch_offset(); /* to test mysql_fetch_column with offset */ + test_fetch_column(); /* to test mysql_fetch_column */ #if NOT_YET_WORKING /* Used for internal new development debugging */ test_drop_temp(); /* to test DROP TEMPORARY TABLE Access checks */ #endif + test_fetch_seek(); /* to test stmt seek() functions */ + test_fetch_nobuffs(); /* to fecth without prior bound buffers */ test_open_direct(); /* direct execution in the middle of open stmts */ test_fetch_null(); /* to fetch null data */ test_fetch_date(); /* to fetch date,time and timestamp */ @@ -7262,6 +7379,9 @@ int main(int argc, char **argv) test_simple_update(); /* simple prepare with update */ test_simple_delete(); /* prepare with delete */ test_double_compare(); /* float comparision */ + client_query(); /* simple client query test */ + client_store_result(); /* usage of mysql_store_result() */ + client_use_result(); /* usage of mysql_use_result() */ test_tran_bdb(); /* transaction test on BDB table type */ test_tran_innodb(); /* transaction test on InnoDB table type */ test_prepare_ext(); /* test prepare with all types conversion -- TODO */ From 020baadcfebbd0f2248d9a3fa15f29d6e9d954b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 00:21:49 -0700 Subject: [PATCH 308/399] client.c: Missed file from earlier commit sql-common/client.c: Missed file from earlier commit --- sql-common/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql-common/client.c b/sql-common/client.c index 81184da0a77..55013d4bd82 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -101,6 +101,10 @@ const char *unknown_sqlstate= "000000"; +#ifdef MYSQL_CLIENT +extern my_bool stmt_close(MYSQL_STMT *stmt,my_bool skip_list); +#endif + /**************************************************************************** A modified version of connect(). my_connect() allows you to specify a timeout value, in seconds, that we should wait until we From a91d2fcbd9d927deb8808c10a32f1baa192a4e26 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 16:05:27 +0300 Subject: [PATCH 309/399] Added [mysqld-base-version] as a default group for the mysqld server Portability fix for Windows 64 include/config-win.h: Portability fix for Windows 64 include/my_global.h: Portability fix for Windows 64 include/mysql_version.h.in: Added [mysqld-base-version] as a default group for the mysqld server innobase/include/univ.i: Portability fix for Windows 64 sql/mysqld.cc: Added [mysqld-base-version] as a default group for the mysqld server --- include/config-win.h | 8 +++++++- include/my_global.h | 2 +- include/mysql_version.h.in | 1 + innobase/include/univ.i | 4 ++++ sql/mysqld.cc | 2 +- 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/config-win.h b/include/config-win.h index 9931d2c4b95..096c00e4574 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -130,6 +130,11 @@ typedef uint rf_SetTimer; #define SIZEOF_LONG 4 #define SIZEOF_LONG_LONG 8 #define SIZEOF_OFF_T 8 +#ifdef _WIN64 +#define SIZEOF_CHARP 8 +#else +#define SIZEOF_CHARP 4 +#endif #define HAVE_BROKEN_NETINET_INCLUDES #ifdef __NT__ #define HAVE_NAMED_PIPE /* We can only create pipes on NT */ @@ -196,6 +201,7 @@ inline double ulonglong2double(ulonglong value) /* Optimized store functions for Intel x86 */ +#ifndef _WIN64 #define sint2korr(A) (*((int16 *) (A))) #define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ (((uint32) 255L << 24) | \ @@ -236,7 +242,7 @@ inline double ulonglong2double(ulonglong value) #define float8get(V,M) doubleget((V),(M)) #define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float)) #define float8store(V,M) doublestore((V),(M)) - +#endif /* _WIN64 */ #define HAVE_PERROR #define HAVE_VFPRINT diff --git a/include/my_global.h b/include/my_global.h index 90c4801e807..1026e8e3940 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -848,7 +848,7 @@ typedef char bool; /* Ordinary boolean values 0 1 */ */ /* Optimized store functions for Intel x86 */ -#ifdef __i386__ +#if defined(__i386__) && !defined(_WIN64) #define sint2korr(A) (*((int16 *) (A))) #define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ (((uint32) 255L << 24) | \ diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in index 793bf36e9fe..da184665f6e 100644 --- a/include/mysql_version.h.in +++ b/include/mysql_version.h.in @@ -10,6 +10,7 @@ #else #define PROTOCOL_VERSION @PROTOCOL_VERSION@ #define MYSQL_SERVER_VERSION "@VERSION@" +#define MYSQL_BASE_VERSION "mysqld-@MYSQL_BASE_VERSION@" #ifndef MYSQL_SERVER_SUFFIX #define MYSQL_SERVER_SUFFIX "@MYSQL_SERVER_SUFFIX@" #endif diff --git a/innobase/include/univ.i b/innobase/include/univ.i index e29f3ec92e1..4854e5a7b78 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -187,7 +187,11 @@ management to ensure correct alignment for doubles etc. */ /* Another basic type we use is unsigned long integer which is intended to be equal to the word size of the machine. */ +#ifdef _WIN64 +typedef unsigned __int64 ulint; +#else typedef unsigned long int ulint; +#endif typedef long int lint; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1492d6ddb68..7289d0e72cf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1923,7 +1923,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg) #endif -const char *load_default_groups[]= { "mysqld","server",0 }; +const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 }; bool open_log(MYSQL_LOG *log, const char *hostname, const char *opt_name, const char *extension, From fb339587a53a1b7cd9385e24c36e82eb278c51d8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 17:58:41 +0300 Subject: [PATCH 310/399] handler.cc: If the autocommit is on, let handler.cc commit or rollback the whole transaction at an updating SQL statement end. This probably fixes bug number 578. The problem was that when explicit LOCK TABLES is used, then the lock count method in autocommit does not work. sql/handler.cc: If the autocommit is on, let handler.cc commit or rollback the whole transaction at an updating SQL statement end. This probably fixes bug number 578. The problem was that when explicit LOCK TABLES is used, then the lock count method in autocommit does not work. --- sql/handler.cc | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 45c83355c94..6ee0b1f9c55 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -208,23 +208,45 @@ void ha_close_connection(THD* thd) } /* - This is used to commit or rollback a single statement depending - on the value of error + This is used to commit or rollback a single statement depending on the value + of error. If the autocommit is on, then we will commit or rollback the whole + transaction (= the statement). The autocommit mechanism built into handlers + is based on counting locks, but if the user has used LOCK TABLES then that + mechanism does not know to do the commit. */ int ha_autocommit_or_rollback(THD *thd, int error) { + bool do_autocommit=FALSE; + DBUG_ENTER("ha_autocommit_or_rollback"); #ifdef USING_TRANSACTIONS + + if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + do_autocommit=TRUE; /* We can commit or rollback the whole transaction */ + if (opt_using_transactions) { if (!error) { - if (ha_commit_stmt(thd)) - error=1; + if (do_autocommit) + { + if (ha_commit(thd)) + error=1; + } + else + { + if (ha_commit_stmt(thd)) + error=1; + } } else - (void) ha_rollback_stmt(thd); + { + if (do_autocommit) + (void) ha_rollback(thd); + else + (void) ha_rollback_stmt(thd); + } thd->variables.tx_isolation=thd->session_tx_isolation; } From b5860aed7b1d11f2d3ac909cde1438c86af26cb5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 18:22:48 +0300 Subject: [PATCH 311/399] Fixed (not fatal) buffer overflow --- libmysql/libmysql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index af74182eb22..c008d625900 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1646,7 +1646,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; - strmov(UNIXaddr.sun_path, unix_socket); + strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1); if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), mysql->options.connect_timeout) <0) { From b388eb004df7112b2ae0986457fc9d01131b71ea Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 18:28:51 +0300 Subject: [PATCH 312/399] Added SQLSTATE to client/server protocol bmove_allign -> bmove_align Added OLAP function ROLLUP Split mysql_fix_privilege_tables to a script and a .sql data file Added new (MEMROOT*) functions to avoid calling current_thd() when creating some common objects. Added table_alias_charset, for easier --lower-case-table-name handling Better SQL_MODE handling (Setting complex options also sets sub options) New (faster) assembler string functions for x86 BitKeeper/etc/ignore: added libmysqld/sql_state.c client/mysql.cc: Added SQLSTATE to error messages Added new function put_error() to be able to clean up some old code. client/mysqltest.c: Write ERROR SQLSTATE for all errors dbug/dbug.c: Portability fixes include/m_string.h: Rename bmove_allign as bmove_align include/mysql.h: Added SQLSTATE (for embedded version) include/mysql_com.h: Send correct SQLSTATE for the error to the client libmysql/libmysql.c: Changed default error state to HY000 Applied code cleanup patch libmysqld/Makefile.am: Added sql_state.cc libmysqld/libmysqld.c: Added sqlstate mysql-test/r/analyse.result: Updated results mysql-test/r/ansi.result: Updated results mysql-test/r/auto_increment.result: Updated results mysql-test/r/bdb-deadlock.result: Updated results mysql-test/r/bdb.result: Updated results mysql-test/r/comments.result: Updated results mysql-test/r/create.result: Updated results mysql-test/r/ctype_collate.result: Updated results mysql-test/r/delayed.result: Updated results mysql-test/r/delete.result: Updated results mysql-test/r/derived.result: Updated results mysql-test/r/distinct.result: Updated results mysql-test/r/drop.result: Updated results mysql-test/r/err000001.result: Updated results mysql-test/r/explain.result: Updated results mysql-test/r/flush.result: Updated results mysql-test/r/fulltext.result: Updated results mysql-test/r/func_gconcat.result: Updated results mysql-test/r/func_system.result: Updated results mysql-test/r/grant_cache.result: Updated results mysql-test/r/group_by.result: Updated results mysql-test/r/handler.result: Updated results mysql-test/r/heap.result: Updated results mysql-test/r/heap_btree.result: Updated results mysql-test/r/heap_hash.result: Updated results mysql-test/r/innodb.result: Updated results mysql-test/r/innodb_handler.result: Updated results mysql-test/r/insert_select.result: Updated results mysql-test/r/insert_update.result: Updated results mysql-test/r/join.result: Updated results mysql-test/r/join_outer.result: Updated results mysql-test/r/key.result: Updated results mysql-test/r/lock.result: Updated results mysql-test/r/lock_multi.result: Updated results mysql-test/r/merge.result: Updated results mysql-test/r/multi_update.result: Updated results mysql-test/r/myisam.result: Updated results mysql-test/r/null.result: Updated results mysql-test/r/olap.result: Updated results mysql-test/r/order_by.result: Updated results mysql-test/r/packet.result: Updated results mysql-test/r/query_cache.result: Updated results mysql-test/r/row.result: Updated results mysql-test/r/rpl000001.result: Updated results mysql-test/r/rpl000009.result: Updated results mysql-test/r/rpl_empty_master_crash.result: Updated results mysql-test/r/rpl_log.result: Updated results mysql-test/r/rpl_replicate_do.result: Updated results mysql-test/r/rpl_rotate_logs.result: Updated results mysql-test/r/select.result: Updated results mysql-test/r/select_safe.result: Updated results mysql-test/r/show_check.result: Updated results mysql-test/r/sql_mode.result: Updated results mysql-test/r/subselect.result: Updated results mysql-test/r/temp_table.result: Updated results mysql-test/r/truncate.result: Updated results mysql-test/r/type_blob.result: Updated results mysql-test/r/type_decimal.result: Updated results mysql-test/r/type_float.result: Updated results mysql-test/r/type_ranges.result: Updated results mysql-test/r/union.result: Updated results mysql-test/r/update.result: Updated results mysql-test/r/user_var.result: Updated results mysql-test/r/varbinary.result: Updated results mysql-test/r/variables.result: Updated results mysql-test/t/ansi.test: Test of sql_mode mysql-test/t/derived.test: Updated results mysql-test/t/func_system.test: Make this independen of the MySQL server name mysql-test/t/lowercase_table.test: Cleanup mysql-test/t/olap.test: A lot of new tests mysql-test/t/sql_mode.test: More test for sql_mode mysql-test/t/subselect.test: Added a few new tests (to find a bug in the item_ref code) scripts/Makefile.am: Added mysql_fix_privilege_tables.sql scripts/mysql_fix_privilege_tables.sh: Totally new script. This bascily just pipes mysql_fix_privilege_tables.sql through 'mysql' to 'mysqld' sql/Makefile.am: Added sql_state.cc sql/item.cc: Extended Item_field::eq() to be able to better match GROUP BY fields on the command line. Needed for ROLLUP sql/item.h: Added function to be able to avoid calling current_thd() when doing new Item. sql/item_sum.cc: Moved copy_or_same() and some reset() functions from item_sum.h Needed to be able to access thd->mem_root. sql/item_sum.h: Moved some functions to item_sum.cc Added make_unique() for ROLLUP sql/item_uniq.h: Fixed return value sql/mysql_priv.h: Updated MODE flags sql/mysqld.cc: Added ANSI as it's own mode Moved charset_info variables here Cleaned up handler_count handling (for NT) Added table_alias_charset, for easier --lower-case-table-name handling sql/net_serv.cc: New comment sql/protocol.cc: Send SQLSTATE to client sql/set_var.cc: Better SQL_MODE handling (Setting complex options also sets sub options) sql/set_var.h: Better SQL_MODE handling sql/sql_base.cc: Make alias depend on --lower-case-table-names Make find_item_in_list also check database name sql/sql_cache.cc: Indentation cleanup sql/sql_list.h: Added safety assert Addes support of alloc without current_thd() sql/sql_prepare.cc: Update after prototype change sql/sql_select.cc: Added ROLLUP sql/sql_select.h: structures for rollup sql/sql_show.cc: Easier SQL_MODE handling sql/sql_string.cc: Move CHARSET_INFO to mysqld (to be together with all other global variables) sql/sql_string.h: Added function to be able to avoid calling current_thd() when doing new Item. sql/sql_table.cc: Simpler --lower-case-table-name handling sql/sql_union.cc: Update after prototype change sql/sql_yacc.yy: ROLLUP sql/unireg.h: bmove_allign ->bmove_align strings/Makefile.am: Fix to be able to compile str_test.c strings/ctype.c: Removed empty lines strings/str_test.c: Added test of bmove_align strings/strings-x86.s: Faster bmove_align, bmove_upp and strmake strings/strings.asm: move_allg --- .bzrignore | 2 + client/mysql.cc | 39 +- client/mysqltest.c | 6 +- dbug/dbug.c | 24 +- include/m_string.h | 10 +- include/mysql.h | 3 +- include/mysql_com.h | 1 + include/sql_state.h | 164 +++++++ libmysql/libmysql.c | 192 ++++---- libmysqld/Makefile.am | 3 +- libmysqld/libmysqld.c | 11 +- mysql-test/r/analyse.result | 30 +- mysql-test/r/ansi.result | 10 +- mysql-test/r/auto_increment.result | 4 +- mysql-test/r/bdb-deadlock.result | 2 +- mysql-test/r/bdb.result | 18 +- mysql-test/r/comments.result | 2 +- mysql-test/r/create.result | 42 +- mysql-test/r/ctype_collate.result | 12 +- mysql-test/r/delayed.result | 2 +- mysql-test/r/delete.result | 2 +- mysql-test/r/derived.result | 27 +- mysql-test/r/distinct.result | 4 +- mysql-test/r/drop.result | 6 +- mysql-test/r/err000001.result | 20 +- mysql-test/r/explain.result | 4 +- mysql-test/r/flush.result | 2 +- mysql-test/r/fulltext.result | 6 +- mysql-test/r/func_gconcat.result | 4 +- mysql-test/r/func_system.result | 4 +- mysql-test/r/grant_cache.result | 12 +- mysql-test/r/group_by.result | 6 +- mysql-test/r/handler.result | 12 +- mysql-test/r/heap.result | 4 +- mysql-test/r/heap_btree.result | 4 +- mysql-test/r/heap_hash.result | 4 +- mysql-test/r/innodb.result | 20 +- mysql-test/r/innodb_handler.result | 8 +- mysql-test/r/insert_select.result | 2 +- mysql-test/r/insert_update.result | 2 +- mysql-test/r/join.result | 2 +- mysql-test/r/join_outer.result | 12 +- mysql-test/r/key.result | 2 +- mysql-test/r/lock.result | 4 +- mysql-test/r/lock_multi.result | 2 +- mysql-test/r/merge.result | 4 +- mysql-test/r/multi_update.result | 10 +- mysql-test/r/myisam.result | 10 +- mysql-test/r/null.result | 16 +- mysql-test/r/olap.result | 283 ++++++++++-- mysql-test/r/order_by.result | 14 +- mysql-test/r/packet.result | 2 +- mysql-test/r/query_cache.result | 4 +- mysql-test/r/row.result | 14 +- mysql-test/r/rpl000001.result | 2 +- mysql-test/r/rpl000009.result | 2 +- mysql-test/r/rpl_empty_master_crash.result | 4 +- mysql-test/r/rpl_log.result | 2 +- mysql-test/r/rpl_replicate_do.result | 2 +- mysql-test/r/rpl_rotate_logs.result | 4 +- mysql-test/r/select.result | 12 +- mysql-test/r/select_safe.result | 16 +- mysql-test/r/show_check.result | 2 +- mysql-test/r/sql_mode.result | 8 +- mysql-test/r/subselect.result | 121 ++--- mysql-test/r/temp_table.result | 6 +- mysql-test/r/truncate.result | 4 +- mysql-test/r/type_blob.result | 6 +- mysql-test/r/type_decimal.result | 6 +- mysql-test/r/type_float.result | 2 +- mysql-test/r/type_ranges.result | 2 +- mysql-test/r/union.result | 26 +- mysql-test/r/update.result | 6 +- mysql-test/r/user_var.result | 2 +- mysql-test/r/varbinary.result | 4 +- mysql-test/r/variables.result | 36 +- mysql-test/t/ansi.test | 5 + mysql-test/t/derived.test | 9 + mysql-test/t/func_system.test | 2 +- mysql-test/t/lowercase_table.test | 1 - mysql-test/t/olap.test | 102 +++-- mysql-test/t/sql_mode.test | 4 +- mysql-test/t/subselect.test | 14 +- scripts/Makefile.am | 2 +- scripts/mysql_fix_privilege_tables.sh | 336 ++++++-------- scripts/mysql_fix_privilege_tables.sql | 89 ++++ sql/Makefile.am | 3 +- sql/item.cc | 34 +- sql/item.h | 2 + sql/item_sum.cc | 160 ++++++- sql/item_sum.h | 79 ++-- sql/item_uniq.h | 2 +- sql/mysql_priv.h | 10 +- sql/mysqld.cc | 68 +-- sql/net_serv.cc | 7 + sql/protocol.cc | 7 +- sql/set_var.cc | 133 ++++-- sql/set_var.h | 6 +- sql/sql_base.cc | 27 +- sql/sql_cache.cc | 3 +- sql/sql_list.h | 3 + sql/sql_prepare.cc | 2 +- sql/sql_select.cc | 491 +++++++++++++++++---- sql/sql_select.h | 49 +- sql/sql_show.cc | 27 +- sql/sql_state.c | 53 +++ sql/sql_string.cc | 4 - sql/sql_string.h | 5 +- sql/sql_table.cc | 5 +- sql/sql_union.cc | 2 +- sql/sql_yacc.yy | 19 +- sql/unireg.h | 4 +- strings/Makefile.am | 2 +- strings/ctype.c | 2 - strings/str_test.c | 4 +- strings/strings-x86.s | 86 ++-- strings/strings.asm | 16 +- 117 files changed, 2205 insertions(+), 1058 deletions(-) create mode 100644 include/sql_state.h create mode 100644 scripts/mysql_fix_privilege_tables.sql create mode 100644 sql/sql_state.c diff --git a/.bzrignore b/.bzrignore index 82adbf625f3..43e8c9c85b7 100644 --- a/.bzrignore +++ b/.bzrignore @@ -617,3 +617,5 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl include/readline/*.h +strings/str_test +libmysqld/sql_state.c diff --git a/client/mysql.cc b/client/mysql.cc index 812673d34c2..c8fed137344 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -200,7 +200,9 @@ static int com_nopager(String *str, char*), com_pager(String *str, char*), static int read_lines(bool execute_commands); static int sql_connect(char *host,char *database,char *user,char *password, uint silent); -static int put_info(const char *str,INFO_TYPE info,uint error=0); +static int put_info(const char *str,INFO_TYPE info,uint error=0, + const char *sql_state=0); +static int put_error(MYSQL *mysql); static void safe_put_field(const char *pos,ulong length); static void xmlencode_print(const char *src, uint length); static void init_pager(); @@ -1437,7 +1439,7 @@ int mysql_real_query_for_lazy(const char *buf, int length) { if (!mysql_real_query(&mysql,buf,length)) return 0; - uint error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql)); + int error= put_error(&mysql); if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 || !opt_reconnect) return error; @@ -1452,8 +1454,7 @@ int mysql_store_result_for_lazy(MYSQL_RES **result) return 0; if (mysql_error(&mysql)[0]) - return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql)); - + return put_error(&mysql); return 0; } @@ -1653,9 +1654,7 @@ com_go(String *buffer,char *line __attribute__((unused))) if (quick) { if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql)) - { - return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql)); - } + return put_error(&mysql); } else { @@ -1717,7 +1716,7 @@ com_go(String *buffer,char *line __attribute__((unused))) put_info("",INFO_RESULT); // Empty row if (result && !mysql_eof(result)) /* Something wrong when using quick */ - error=put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql)); + error= put_error(&mysql); else if (unbuffered) fflush(stdout); mysql_free_result(result); @@ -2431,12 +2430,12 @@ com_use(String *buffer __attribute__((unused)), char *line) if (mysql_select_db(&mysql,tmp)) { if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR) - return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql)); + return put_error(&mysql); if (reconnect()) return opt_reconnect ? -1 : 1; // Fatal error if (mysql_select_db(&mysql,tmp)) - return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql)); + return put_error(&mysql); } my_free(current_db,MYF(MY_ALLOW_ZERO_PTR)); current_db=my_strdup(tmp,MYF(MY_WME)); @@ -2557,7 +2556,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, (mysql_errno(&mysql) != CR_CONN_HOST_ERROR && mysql_errno(&mysql) != CR_CONNECTION_ERROR)) { - put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql)); + (void) put_error(&mysql); (void) fflush(stdout); return ignore_errors ? -1 : 1; // Abort } @@ -2707,7 +2706,7 @@ select_limit, max_join_size); static int -put_info(const char *str,INFO_TYPE info_type,uint error) +put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) { FILE *file= (info_type == INFO_ERROR ? stderr : stdout); static int inited=0; @@ -2752,7 +2751,12 @@ 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(file, "ERROR %d: ", error); + { + if (sqlstate) + (void) tee_fprintf(file, "ERROR %d (%s): ", error, sqlstate); + else + (void) tee_fprintf(file, "ERROR %d: ", error); + } else tee_puts("ERROR: ", file); } @@ -2767,6 +2771,14 @@ put_info(const char *str,INFO_TYPE info_type,uint error) } +static int +put_error(MYSQL *mysql) +{ + return put_info(mysql_error(mysql), INFO_ERROR, mysql_errno(mysql), + mysql_sqlstate(mysql)); +} + + static void remove_cntrl(String &buffer) { char *start,*end; @@ -3085,4 +3097,3 @@ void sql_element_free(void *ptr) my_free((gptr) ptr,MYF(0)); } #endif /* EMBEDDED_LIBRARY */ - diff --git a/client/mysqltest.c b/client/mysqltest.c index 9889d365335..84ff41d73a6 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -42,7 +42,7 @@ **********************************************************************/ -#define MTEST_VERSION "1.27" +#define MTEST_VERSION "1.28" #include #include @@ -2147,6 +2147,10 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) if (i == 0 && q->expected_errors == 1) { /* Only log error if there is one possible error */ + dynstr_append_mem(ds,"ERROR ",6); + replace_dynstr_append_mem(ds, mysql_sqlstate(mysql), + strlen(mysql_sqlstate(mysql))); + dynstr_append_mem(ds,": ",2); replace_dynstr_append_mem(ds,mysql_error(mysql), strlen(mysql_error(mysql))); dynstr_append_mem(ds,"\n",1); diff --git a/dbug/dbug.c b/dbug/dbug.c index a4f9d5ecd4b..f7b2fb75ba0 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -280,7 +280,7 @@ static BOOLEAN Writable(char *pathname); static void ChangeOwner(char *pathname); /* Allocate memory for runtime support */ #endif -static char *DbugMalloc(int size); +static char *DbugMalloc(size_t size); /* Remove leading pathname components */ static char *BaseName(const char *pathname); static void DoPrefix(uint line); @@ -1120,7 +1120,7 @@ static void PushState () init_done=TRUE; } (void) code_state(); /* Alloc memory */ - new_malloc = (struct state *) DbugMalloc (sizeof (struct state)); + new_malloc = (struct state *) DbugMalloc(sizeof (struct state)); new_malloc -> flags = 0; new_malloc -> delay = 0; new_malloc -> maxdepth = MAXDEPTH; @@ -1341,11 +1341,10 @@ struct link *linkp) */ -static char *StrDup ( -const char *str) +static char *StrDup (const char *str) { reg1 char *new_malloc; - new_malloc = DbugMalloc ((int) strlen (str) + 1); + new_malloc = DbugMalloc((size_t) strlen (str) + 1); (void) strcpy (new_malloc, str); return (new_malloc); } @@ -1606,14 +1605,13 @@ static void DbugExit (const char *why) * */ -static char *DbugMalloc ( -int size) +static char *DbugMalloc (size_t size) { - register char *new_malloc; + register char *new_malloc; - if (!(new_malloc = (char*) malloc ((unsigned int) size))) - DbugExit ("out of memory"); - return (new_malloc); + if (!(new_malloc = (char*) malloc((size_t) size))) + DbugExit ("out of memory"); + return (new_malloc); } @@ -1622,9 +1620,7 @@ int size) * separator (to allow directory-paths in dos). */ -static char *static_strtok ( -char *s1, -pchar separator) +static char *static_strtok (char *s1, pchar separator) { static char *end = NULL; reg1 char *rtnval,*cpy; diff --git a/include/m_string.h b/include/m_string.h index 15a488fe72a..5863bb51b73 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -74,14 +74,14 @@ /* Unixware 7 */ #if !defined(HAVE_BFILL) # define bfill(A,B,C) memset((A),(C),(B)) -# define bmove_allign(A,B,C) memcpy((A),(B),(C)) +# define bmove_align(A,B,C) memcpy((A),(B),(C)) #endif #if !defined(HAVE_BCMP) # define bcopy(s, d, n) memcpy((d), (s), (n)) # define bcmp(A,B,C) memcmp((A),(B),(C)) # define bzero(A,B) memset((A),0,(B)) -# define bmove_allign(A,B,C) memcpy((A),(B),(C)) +# define bmove_align(A,B,C) memcpy((A),(B),(C)) #endif #if defined(__cplusplus) && !defined(OS2) @@ -111,11 +111,11 @@ extern char NEAR _dig_vec[]; /* Declared in int2str() */ #endif #ifdef MSDOS -#undef bmove_allign -#define bmove512(A,B,C) bmove_allign(A,B,C) +#undef bmove_align +#define bmove512(A,B,C) bmove_align(A,B,C) #define my_itoa(A,B,C) itoa(A,B,C) #define my_ltoa(A,B,C) ltoa(A,B,C) -extern void bmove_allign(gptr dst,const gptr src,uint len); +extern void bmove_align(gptr dst,const gptr src,uint len); #endif #if (!defined(USE_BMOVE512) || defined(HAVE_purify)) && !defined(bmove512) diff --git a/include/mysql.h b/include/mysql.h index 94f2152655d..d903c2c3e67 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -268,7 +268,8 @@ typedef struct st_mysql my_bool free_me; /* If free in mysql_close */ my_ulonglong insert_id; /* id if insert on table with NEXTNR */ unsigned int last_errno; - char *last_error; + char *last_error; /* Used by embedded server */ + char sqlstate[SQLSTATE_LENGTH+1]; /* Used by embedded server */ } MYSQL; #endif diff --git a/include/mysql_com.h b/include/mysql_com.h index e2fa30e3a18..2ed5038b275 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -324,6 +324,7 @@ my_bool check_scramble(const char *, const char *message, unsigned long *salt,my_bool old_ver); char *get_tty_password(char *opt_message); void hash_password(unsigned long *result, const char *password); +const char *mysql_errno_to_sqlstate(uint mysql_errno); /* Some other useful functions */ diff --git a/include/sql_state.h b/include/sql_state.h new file mode 100644 index 00000000000..cc0fab7bfce --- /dev/null +++ b/include/sql_state.h @@ -0,0 +1,164 @@ +/* Copyright (C) 2000-2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + This file includes a mapping from mysql_errno.h to sql_state (as used by + MyODBC) and jdbc_state. + It's suitable to include into a C struct for further processing + + The first column is the mysqld server error (declared in mysqld_error.h), + the second column is the ODBC state (which the 4.1 server sends out by + default) and the last is the state used by the JDBC driver. + If the last column is "" then it means that the JDBC driver is using the + ODBC state + + The errors in this file is sorted in the same order as in mysqld_error.h + to allow on to do binary searches for the sqlstate. +*/ + +ER_DUP_KEY, "23000", "", +ER_OUTOFMEMORY, "HY001", "S1001", +ER_OUT_OF_SORTMEMORY, "HY001", "S1001", +ER_CON_COUNT_ERROR, "08004", "", +ER_BAD_HOST_ERROR, "08S01", "", +ER_HANDSHAKE_ERROR, "08S01", "", +ER_DBACCESS_DENIED_ERROR, "42000", "", +ER_ACCESS_DENIED_ERROR, "42000", "28000", +ER_NO_DB_ERROR, "42000", "", +ER_UNKNOWN_COM_ERROR, "08S01", "", +ER_BAD_NULL_ERROR, "23000", "", +ER_BAD_DB_ERROR, "42000", "", +ER_TABLE_EXISTS_ERROR, "42S01", "", +ER_BAD_TABLE_ERROR, "42S02", "", +ER_NON_UNIQ_ERROR, "23000", "", +ER_SERVER_SHUTDOWN, "08S01", "", +ER_BAD_FIELD_ERROR, "42S22", "S0022", +ER_WRONG_FIELD_WITH_GROUP, "42000", "S1009", +ER_WRONG_GROUP_FIELD, "42000", "S1009", +ER_WRONG_SUM_SELECT, "42000", "S1009", +ER_WRONG_VALUE_COUNT, "21S01", "", +ER_TOO_LONG_IDENT, "42000", "S1009", +ER_DUP_FIELDNAME, "42S21", "S1009", +ER_DUP_KEYNAME, "42000", "S1009", +ER_DUP_ENTRY, "23000", "S1009", +ER_WRONG_FIELD_SPEC, "42000", "S1009", +ER_PARSE_ERROR, "42000", "", +ER_EMPTY_QUERY, "42000" , "", +ER_NONUNIQ_TABLE, "42000", "S1009", +ER_INVALID_DEFAULT, "42000", "S1009", +ER_MULTIPLE_PRI_KEY, "42000", "S1009", +ER_TOO_MANY_KEYS, "42000", "S1009", +ER_TOO_MANY_KEY_PARTS, "42000", "S1009", +ER_TOO_LONG_KEY, "42000", "S1009", +ER_KEY_COLUMN_DOES_NOT_EXITS, "42000", "S1009", +ER_BLOB_USED_AS_KEY, "42000", "S1009", +ER_TOO_BIG_FIELDLENGTH, "42000", "S1009", +ER_WRONG_AUTO_KEY, "42000", "S1009", +ER_FORCING_CLOSE, "08S01", "", +ER_IPSOCK_ERROR, "088S01", "", +ER_NO_SUCH_INDEX, "42S12", "S1009", +ER_WRONG_FIELD_TERMINATORS, "42000", "S1009", +ER_BLOBS_AND_NO_TERMINATED, "42000", "S1009", +ER_CANT_REMOVE_ALL_FIELDS, "42000", "", +ER_CANT_DROP_FIELD_OR_KEY, "42000", "", +ER_BLOB_CANT_HAVE_DEFAULT, "42000", "", +ER_WRONG_DB_NAME, "42000", "", +ER_WRONG_TABLE_NAME, "42000", "", +ER_TOO_BIG_SELECT, "42000", "", +ER_UNKNOWN_PROCEDURE, "42000", "", +ER_WRONG_PARAMCOUNT_TO_PROCEDURE, "42000", "", +ER_UNKNOWN_TABLE, "42S02", "", +ER_FIELD_SPECIFIED_TWICE, "42000", "", +ER_UNSUPPORTED_EXTENSION, "42000", "", +ER_TABLE_MUST_HAVE_COLUMNS, "42000", "", +ER_UNKNOWN_CHARACTER_SET, "42000", "", +ER_TOO_BIG_ROWSIZE, "42000", "", +ER_STACK_OVERRUN, "HY000", "", +ER_WRONG_OUTER_JOIN, "42000", "", +ER_NULL_COLUMN_IN_INDEX, "42000", "", +ER_PASSWORD_ANONYMOUS_USER, "42000", "", +ER_PASSWORD_NOT_ALLOWED, "42000", "", +ER_PASSWORD_NO_MATCH, "42000", "", +ER_WRONG_VALUE_COUNT_ON_ROW, "21S01", "", +ER_INVALID_USE_OF_NULL, "42000", "", +ER_REGEXP_ERROR, "42000", "", +ER_MIX_OF_GROUP_FUNC_AND_FIELDS,"42000", "", +ER_NONEXISTING_GRANT, "42000", "", +ER_TABLEACCESS_DENIED_ERROR, "42000", "", +ER_COLUMNACCESS_DENIED_ERROR, "42000", "", +ER_ILLEGAL_GRANT_FOR_TABLE, "42000", "", +ER_GRANT_WRONG_HOST_OR_USER, "42000", "", +ER_NO_SUCH_TABLE, "42S02", "", +ER_NONEXISTING_TABLE_GRANT, "42000", "", +ER_NOT_ALLOWED_COMMAND, "42000", "", +ER_SYNTAX_ERROR, "42000", "", +ER_ABORTING_CONNECTION, "08S01", "", +ER_NET_PACKET_TOO_LARGE, "08S01", "", +ER_NET_READ_ERROR_FROM_PIPE, "08S01", "", +ER_NET_FCNTL_ERROR, "08S01", "", +ER_NET_PACKETS_OUT_OF_ORDER, "08S01", "", +ER_NET_UNCOMPRESS_ERROR, "08S01", "", +ER_NET_READ_ERROR, "08S01", "", +ER_NET_READ_INTERRUPTED, "08S01", "", +ER_NET_ERROR_ON_WRITE, "08S01", "", +ER_NET_WRITE_INTERRUPTED, "08S01", "", +ER_TOO_LONG_STRING, "42000", "", +ER_TABLE_CANT_HANDLE_BLOB, "42000", "", +ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, "42000", "", +ER_WRONG_COLUMN_NAME, "42000", "", +ER_WRONG_KEY_COLUMN, "42000", "", +ER_DUP_UNIQUE, "23000", "", +ER_BLOB_KEY_WITHOUT_LENGTH, "42000", "", +ER_PRIMARY_CANT_HAVE_NULL, "42000", "", +ER_TOO_MANY_ROWS, "42000", "", +ER_REQUIRES_PRIMARY_KEY, "42000", "", +ER_CHECK_NO_SUCH_TABLE, "42000", "", +ER_CHECK_NOT_IMPLEMENTED, "42000", "", +ER_CANT_DO_THIS_DURING_AN_TRANSACTION, "25000", "", +ER_ERROR_DURING_COMMIT, "HY000", "", +ER_ERROR_DURING_ROLLBACK, "HY000", "", +ER_NEW_ABORTING_CONNECTION, "08S01", "", +ER_MASTER_NET_READ, "08S01", "", +ER_MASTER_NET_WRITE, "08S01", "", +ER_TOO_MANY_USER_CONNECTIONS, "42000", "", +ER_READ_ONLY_TRANSACTION, "25000", "", +ER_NO_PERMISSION_TO_CREATE_USER,"42000", "", +ER_LOCK_DEADLOCK, "40001", "", +ER_NO_REFERENCED_ROW, "23000", "", +ER_ROW_IS_REFERENCED, "23000", "", +ER_CONNECT_TO_MASTER, "08S01", "", +ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,"21000", "", +ER_USER_LIMIT_REACHED, "42000", "", +ER_NO_DEFAULT, "42000", "", +ER_WRONG_VALUE_FOR_VAR, "42000", "", +ER_WRONG_TYPE_FOR_VAR, "42000", "", +ER_CANT_USE_OPTION_HERE, "42000", "", +ER_NOT_SUPPORTED_YET, "42000", "", +ER_WRONG_FK_DEF, "42000", "", +ER_CARDINALITY_COL, "21000", "", +ER_SUBSELECT_NO_1_ROW, "21000", "", +ER_ILLEGAL_REFERENCE, "42S22", "", +ER_DERIVED_MUST_HAVE_ALIAS, "42000", "", +ER_SELECT_REDUCED, "01000", "", +ER_TABLENAME_NOT_ALLOWED_HERE, "42000", "", +ER_NOT_SUPPORTED_AUTH_MODE, "08004", "", +ER_SPATIAL_CANT_HAVE_NULL, "42000", "", +ER_COLLATION_CHARSET_MISMATCH, "42000", "", +ER_WARN_TOO_FEW_RECORDS, "01000", "", +ER_WARN_TOO_MANY_RECORDS, "01000", "", +ER_WARN_NULL_TO_NOTNULL, "01000", "", +ER_WARN_DATA_OUT_OF_RANGE, "01000", "", +ER_WARN_DATA_TRUNCATED, "01000", "", diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 514de2a87a6..c28ee6bbfed 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -64,7 +64,8 @@ ulong net_buffer_length=8192; ulong max_allowed_packet= 1024L*1024L*1024L; ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT; -const char *unknown_sqlstate= "000000"; +const char *unknown_sqlstate= "HY000"; +const char *not_error_sqlstate= "00000"; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \ @@ -91,9 +92,9 @@ const char *def_shared_memory_base_name=default_shared_memory_base_name; #endif const char *sql_protocol_names_lib[] = -{ "TCP", "SOCKET", "PIPE", "MEMORY",NullS }; +{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS }; TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", - sql_protocol_names_lib}; + sql_protocol_names_lib}; /* If allowed through some configuration, then this needs to be changed @@ -141,16 +142,16 @@ void STDCALL mysql_server_end() my_bool STDCALL mysql_thread_init() { #ifdef THREAD - return my_thread_init(); + return my_thread_init(); #else - return 0; + return 0; #endif } void STDCALL mysql_thread_end() { #ifdef THREAD - my_thread_end(); + my_thread_end(); #endif } @@ -160,7 +161,7 @@ void STDCALL mysql_thread_end() */ #if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD) -#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0; +#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0 #define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler) #define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler); #else @@ -409,13 +410,14 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) DWORD error_code = 0; char *shared_memory_base_name = mysql->options.shared_memory_base_name; -/* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part - Where: + /* + The name of event and file-mapping events create agree next rule: + shared_memory_base_name+unique_part + + Where: shared_memory_base_name is unique value for each server unique_part is uniquel value for each object (events and file-mapping) -*/ + */ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS); strmov(suffix_pos, "CONNECT_REQUEST"); if (!(event_connect_request= OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp))) @@ -441,36 +443,34 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; goto err; } - /* - Send to server request of connection - */ + + /* Send to server request of connection */ if (!SetEvent(event_connect_request)) { error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR; goto err; } - /* - Wait of answer from server - */ + + /* Wait of answer from server */ if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != WAIT_OBJECT_0) { error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR; goto err; } - /* - Get number of connection - */ + + /* Get number of connection */ connect_number = uint4korr(handle_connect_map);/*WAX2*/ p= int2str(connect_number, connect_number_char, 10); /* The name of event and file-mapping events create agree next rule: shared_memory_base_name+unique_part+number_of_connection + Where: - shared_memory_base_name is uniquel value for each server - unique_part is uniquel value for each object (events and file-mapping) - number_of_connection is number of connection between server and client + shared_memory_base_name is uniquel value for each server + unique_part is uniquel value for each object (events and file-mapping) + number_of_connection is number of connection between server and client */ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char, "_",NullS); @@ -579,7 +579,7 @@ net_safe_read(MYSQL *mysql) { NET *net= &mysql->net; ulong len=0; - init_sigpipe_variables + init_sigpipe_variables; /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); @@ -645,7 +645,7 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, { NET *net= &mysql->net; my_bool result= 1; - init_sigpipe_variables + init_sigpipe_variables; /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); @@ -663,8 +663,8 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, } net->last_error[0]=0; - net->last_errno=0; - strmov(net->sqlstate, unknown_sqlstate); + net->last_errno= 0; + strmov(net->sqlstate, not_error_sqlstate); mysql->info=0; mysql->affected_rows= ~(my_ulonglong) 0; net_clear(&mysql->net); /* Clear receive buffer */ @@ -695,7 +695,7 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, if (!skip_check) result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ? 1 : 0); - end: +end: reset_sigpipe(mysql); return result; } @@ -870,7 +870,7 @@ end_server(MYSQL *mysql) DBUG_ENTER("end_server"); if (mysql->net.vio != 0) { - init_sigpipe_variables + init_sigpipe_variables; DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); set_sigpipe(mysql); vio_delete(mysql->net.vio); @@ -1402,7 +1402,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) /* perform query on master */ my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q, - unsigned long length) + unsigned long length) { DBUG_ENTER("mysql_master_query"); if (mysql_master_send_query(mysql, q, length)) @@ -1449,7 +1449,7 @@ my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q, */ mysql->last_used_con = mysql->last_used_slave = slave_to_use; if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0, - 0,0,0,0)) + 0,0,0,0)) DBUG_RETURN(1); DBUG_RETURN(simple_command(slave_to_use, COM_QUERY, q, length, 1)); } @@ -1586,7 +1586,7 @@ static my_bool get_slaves_from_master(MYSQL* mysql) } if (!(slave = spawn_init(mysql, row[1], atoi(row[port_ind]), - tmp_user, tmp_pass))) + tmp_user, tmp_pass))) goto err; /* Now add slave into the circular linked list */ @@ -1596,7 +1596,7 @@ static my_bool get_slaves_from_master(MYSQL* mysql) error = 0; err: if (res) - mysql_free_result(res); + mysql_free_result(res); DBUG_RETURN(error); } @@ -1966,7 +1966,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif - init_sigpipe_variables + init_sigpipe_variables; DBUG_ENTER("mysql_real_connect"); LINT_INIT(host_info); @@ -2529,7 +2529,7 @@ static my_bool mysql_reconnect(MYSQL *mysql) if (!mysql->reconnect || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { - /* Allow reconnect next time */ + /* Allow reconnect next time */ mysql->server_status&= ~SERVER_STATUS_IN_TRANS; strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->net.last_errno=CR_SERVER_GONE_ERROR; @@ -2575,7 +2575,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, if (!passwd) passwd=""; - /* Store user into the buffer */ + /* Store user into the buffer */ end=strmov(end,user)+1; /* @@ -2592,15 +2592,15 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, *end=0; } - else /* For empty password*/ - *end=0; /* Store zero length scramble */ + else /* For empty password */ + *end=0; /* zero length scramble */ } else { - /* - Real scramble is only sent to old servers. This can be blocked - by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); - */ + /* + Real scramble is only sent to old servers. This can be blocked + by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1); + */ end=scramble(end, mysql->scramble_buff, passwd, (my_bool) (mysql->protocol_version == 9)); } @@ -2793,9 +2793,9 @@ STDCALL mysql_set_master(MYSQL* mysql, const char* host, int STDCALL mysql_add_slave(MYSQL* mysql, const char* host, - unsigned int port, - const char* user, - const char* passwd) + unsigned int port, + const char* user, + const char* passwd) { MYSQL* slave; if (!(slave = spawn_init(mysql, host, port, user, passwd))) @@ -3670,7 +3670,7 @@ mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, if (use_mb_flag && (l = my_ismbchar(charset_info, from, end))) { while (l--) - *to++ = *from++; + *to++ = *from++; from--; continue; } @@ -4045,13 +4045,15 @@ unsigned int alloc_stmt_fields(MYSQL_STMT *stmt) like SHOW and DESCRIBE commands */ if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc, - sizeof(MYSQL_FIELD) * stmt->field_count)) || + sizeof(MYSQL_FIELD) * + stmt->field_count)) || !(stmt->bind= (MYSQL_BIND *) alloc_root(alloc, - sizeof(MYSQL_BIND ) * stmt->field_count))) + sizeof(MYSQL_BIND) * + stmt->field_count))) return 0; for (fields= mysql->fields, end= fields+stmt->field_count, - field= stmt->fields; + field= stmt->fields; field && fields < end; fields++, field++) { field->db = strdup_root(alloc,fields->db); @@ -4781,7 +4783,7 @@ static void send_data_long(MYSQL_BIND *param, longlong value) { char *buffer= param->buffer; - switch(param->buffer_type) { + switch (param->buffer_type) { case MYSQL_TYPE_NULL: /* do nothing */ break; case MYSQL_TYPE_TINY: @@ -4797,33 +4799,34 @@ static void send_data_long(MYSQL_BIND *param, longlong value) int8store(buffer, value); break; case MYSQL_TYPE_FLOAT: - { - float data= (float)value; - float4store(buffer, data); - break; - } + { + float data= (float)value; + float4store(buffer, data); + break; + } case MYSQL_TYPE_DOUBLE: - { - double data= (double)value; - float8store(buffer, data); - break; - } + { + double data= (double)value; + float8store(buffer, data); + break; + } default: - { - char tmp[NAME_LEN]; - uint length= (uint)(longlong10_to_str(value,(char *)tmp,10)-tmp); - ulong copy_length= min((ulong)length-param->offset, param->buffer_length); - memcpy(buffer, (char *)tmp+param->offset, copy_length); - *param->length= length; + { + char tmp[NAME_LEN]; + uint length= (uint)(longlong10_to_str(value,(char *)tmp,10)-tmp); + ulong copy_length= min((ulong)length-param->offset, param->buffer_length); + memcpy(buffer, (char *)tmp+param->offset, copy_length); + *param->length= length; - if (copy_length != param->buffer_length) - *(buffer+copy_length)= '\0'; - } - } + if (copy_length != param->buffer_length) + *(buffer+copy_length)= '\0'; + } + } } /* Convert Double to buffer types */ + static void send_data_double(MYSQL_BIND *param, double value) { char *buffer= param->buffer; @@ -4969,7 +4972,7 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime, switch (ltime.time_type) { case MYSQL_TIMESTAMP_DATE: length= my_sprintf(buff,(buff, "%04d-%02d-%02d", ltime.year, - ltime.month,ltime.day)); + ltime.month,ltime.day)); break; case MYSQL_TIMESTAMP_FULL: length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d", @@ -4978,7 +4981,7 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime, break; case MYSQL_TIMESTAMP_TIME: length= my_sprintf(buff, (buff, "%02d:%02d:%02d", - ltime.hour,ltime.minute,ltime.second)); + ltime.hour,ltime.minute,ltime.second)); break; default: length= 0; @@ -4990,8 +4993,8 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime, } - /* Fetch data to buffers */ + static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row, my_bool field_is_unsigned) { @@ -5001,8 +5004,8 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row, case MYSQL_TYPE_TINY: { char value= (char) **row; - longlong data= (field_is_unsigned) ? (longlong) (unsigned char) value: - (longlong) value; + longlong data= ((field_is_unsigned) ? (longlong) (unsigned char) value: + (longlong) value); send_data_long(param,data); length= 1; break; @@ -5011,8 +5014,8 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row, case MYSQL_TYPE_YEAR: { short value= sint2korr(*row); - longlong data= (field_is_unsigned) ? (longlong) (unsigned short) value: - (longlong) value; + longlong data= ((field_is_unsigned) ? (longlong) (unsigned short) value: + (longlong) value); send_data_long(param,data); length= 2; break; @@ -5020,8 +5023,8 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row, case MYSQL_TYPE_LONG: { long value= sint4korr(*row); - longlong data= (field_is_unsigned) ? (longlong) (unsigned long) value: - (longlong) value; + longlong data= ((field_is_unsigned) ? (longlong) (unsigned long) value: + (longlong) value); send_data_long(param,data); length= 4; break; @@ -5316,8 +5319,8 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row) /* Copy complete row to application buffers */ for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count, - field= stmt->fields, - field_end= (MYSQL_FIELD *)stmt->fields+stmt->field_count; + field= stmt->fields, + field_end= (MYSQL_FIELD *)stmt->fields+stmt->field_count; bind < end && field < field_end; bind++, field++) { @@ -5509,7 +5512,7 @@ no_data: } -/* +/* Read all rows of data from server (binary format) */ @@ -5578,6 +5581,7 @@ static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt) DBUG_RETURN(result); } + /* Store or buffer the binary results to stmt */ @@ -5599,9 +5603,9 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) } mysql->status= MYSQL_STATUS_READY; /* server is ready */ if (!(result= (MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+ - sizeof(ulong) * - stmt->field_count), - MYF(MY_WME | MY_ZEROFILL)))) + sizeof(ulong) * + stmt->field_count), + MYF(MY_WME | MY_ZEROFILL)))) { set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(1); @@ -5620,6 +5624,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_fetch() */ } + /* Seek to desired row in the statement result set */ @@ -5642,6 +5647,7 @@ mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row) DBUG_RETURN(0); } + /* Return the current statement row cursor position */ @@ -5842,16 +5848,16 @@ my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode) my_bool STDCALL mysql_more_results(MYSQL *mysql) { - my_bool result; + my_bool res; DBUG_ENTER("mysql_more_results"); - result= (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ? - 1: 0; - - DBUG_PRINT("exit",("More results exists ? %d", result)); - DBUG_RETURN(result); + res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ? + 1: 0); + DBUG_PRINT("exit",("More results exists ? %d", res)); + DBUG_RETURN(res); } + /* Reads and returns the next query results */ @@ -5862,7 +5868,7 @@ my_bool STDCALL mysql_next_result(MYSQL *mysql) mysql->net.last_error[0]= 0; mysql->net.last_errno= 0; - strmov(mysql->net.sqlstate, unknown_sqlstate); + strmov(mysql->net.sqlstate, not_error_sqlstate); mysql->affected_rows= ~(my_ulonglong) 0; if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 93702e5b6d0..48055ff6050 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -44,7 +44,8 @@ sqlsources = derror.cc field.cc field_conv.cc filesort.cc \ item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \ item_uniq.cc item_subselect.cc item_row.cc\ key.cc lock.cc log.cc log_event.cc mf_iocache.cc\ - mini_client.cc protocol.cc net_serv.cc opt_ft.cc opt_range.cc \ + mini_client.cc protocol.cc net_serv.cc sql_state.c \ + opt_ft.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ repl_failsafe.cc slave.cc sql_load.cc sql_olap.cc \ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \ diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index e6166f6bbe5..a2d69b30c0d 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -450,6 +450,7 @@ static inline int mysql_init_charset(MYSQL *mysql) if (!mysql->charset) { mysql->last_errno=CR_CANT_READ_CHARSET; + strmov(mysql->sqlstate, "HY0000"); if (mysql->options.charset_dir) sprintf(mysql->last_error,ER(mysql->last_errno), charset_name ? charset_name : "unknown", @@ -1130,6 +1131,7 @@ mysql_stat(MYSQL *mysql) if (!mysql->net.read_pos[0]) { mysql->net.last_errno=CR_WRONG_HOST_INFO; + strmov(mysql->sqlstate, unknown_sqlstate); strmov(mysql->net.last_error, ER(mysql->net.last_errno)); return mysql->net.last_error; } @@ -1284,12 +1286,12 @@ unsigned int STDCALL mysql_field_count(MYSQL *mysql) my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) { - return (mysql)->affected_rows; + return mysql->affected_rows; } my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) { - return (mysql)->insert_id; + return mysql->insert_id; } uint STDCALL mysql_errno(MYSQL *mysql) @@ -1297,6 +1299,11 @@ uint STDCALL mysql_errno(MYSQL *mysql) return mysql->last_errno; } +const char *STDCALL mysql_sqlstate(MYSQL *mysql) +{ + return mysql->sqlstate; +} + const char * STDCALL mysql_error(MYSQL *mysql) { return mysql->last_error; diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index 60764494417..f18b925460c 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -6,26 +6,26 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_ count(*) 4 4 1 1 0 0 4.0000 0.0000 ENUM('4') NOT NULL select * from t1 procedure analyse(); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL -t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL -t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL -t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL -t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL +test.t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL +test.t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL +test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL +test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL +test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL select * from t1 procedure analyse(2); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -t1.i 1 7 1 1 0 0 4.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL -t1.j 2 8 1 1 0 0 5.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL -t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL -t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL -t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL +test.t1.i 1 7 1 1 0 0 4.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL +test.t1.j 2 8 1 1 0 0 5.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL +test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL +test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL +test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL create table t2 select * from t1 procedure analyse(); select * from t2; Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL -t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL -t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL -t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL -t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL +test.t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL +test.t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL +test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL +test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL +test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL drop table t1,t2; EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result index f9f96310b73..6ec909f84bb 100644 --- a/mysql-test/r/ansi.result +++ b/mysql-test/r/ansi.result @@ -6,5 +6,13 @@ 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 +ERROR 42000: 'test.t1.id' isn't in GROUP BY drop table t1; +set sql_mode="MySQL40"; +select @@sql_mode; +@@sql_mode +NO_FIELD_OPTIONS,MYSQL40 +set sql_mode="ANSI"; +select @@sql_mode; +@@sql_mode +REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index c993a47198a..bd15c913d2e 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -112,7 +112,7 @@ select last_insert_id(); last_insert_id() 255 insert into t1 set i = null; -Duplicate entry '255' for key 1 +ERROR 23000: Duplicate entry '255' for key 1 select last_insert_id(); last_insert_id() 255 @@ -140,7 +140,7 @@ select last_insert_id(); last_insert_id() 2 insert into t1 values (NULL, 10); -Duplicate entry '10' for key 2 +ERROR 23000: Duplicate entry '10' for key 2 select last_insert_id(); last_insert_id() 3 diff --git a/mysql-test/r/bdb-deadlock.result b/mysql-test/r/bdb-deadlock.result index 55b3d3ea2a5..6606b0d9b38 100644 --- a/mysql-test/r/bdb-deadlock.result +++ b/mysql-test/r/bdb-deadlock.result @@ -9,7 +9,7 @@ set autocommit=0; update t2 set x = 1 where id = 0; select x from t1 where id = 0; select x from t2 where id = 0; -Deadlock found when trying to get lock; Try restarting transaction +ERROR 40001: Deadlock found when trying to get lock; Try restarting transaction commit; x 1 diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 7f0612a011f..b0566011996 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -48,7 +48,7 @@ id parent_id level 15 102 2 update t1 set id=id+1000; update t1 set id=1024 where id=1009; -Duplicate entry '1024' for key 1 +ERROR 23000: Duplicate entry '1024' for key 1 select * from t1; id parent_id level 1001 100 0 @@ -270,7 +270,7 @@ n after commit commit; insert into t1 values (5); insert into t1 values (4); -Duplicate entry '4' for key 1 +ERROR 23000: Duplicate entry '4' for key 1 commit; select n, "after commit" from t1; n after commit @@ -279,7 +279,7 @@ n after commit set autocommit=1; insert into t1 values (6); insert into t1 values (4); -Duplicate entry '4' for key 1 +ERROR 23000: Duplicate entry '4' for key 1 select n from t1; n 4 @@ -309,7 +309,7 @@ drop table t1; CREATE TABLE t1 (id char(8) not null primary key, val int not null) type=bdb; insert into t1 values ('pippo', 12); insert into t1 values ('pippo', 12); -Duplicate entry 'pippo' for key 1 +ERROR 23000: Duplicate entry 'pippo' for key 1 delete from t1; delete from t1 where id = 'pippo'; select * from t1; @@ -464,9 +464,9 @@ UNIQUE ggid (ggid) insert into t1 (ggid,passwd) values ('test1','xxx'); insert into t1 (ggid,passwd) values ('test2','yyy'); insert into t1 (ggid,passwd) values ('test2','this will fail'); -Duplicate entry 'test2' for key 2 +ERROR 23000: Duplicate entry 'test2' for key 2 insert into t1 (ggid,id) values ('this will fail',1); -Duplicate entry '1' for key 1 +ERROR 23000: Duplicate entry '1' for key 1 select * from t1 where ggid='test1'; id ggid email passwd 1 test1 xxx @@ -479,7 +479,7 @@ id ggid email passwd replace into t1 (ggid,id) values ('this will work',1); replace into t1 (ggid,passwd) values ('test2','this will work'); update t1 set id=100,ggid='test2' where id=1; -Duplicate entry 'test2' for key 2 +ERROR 23000: Duplicate entry 'test2' for key 2 select * from t1; id ggid email passwd 1 this will work @@ -1008,7 +1008,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3 insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL'); LOCK TABLES t1 WRITE; insert into t1 values (99,1,2,'D'),(1,1,2,'D'); -Duplicate entry '1-1' for key 1 +ERROR 23000: Duplicate entry '1-1' for key 1 select id from t1; id 0 @@ -1026,7 +1026,7 @@ insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJ LOCK TABLES t1 WRITE; begin; insert into t1 values (99,1,2,'D'),(1,1,2,'D'); -Duplicate entry '1-1' for key 1 +ERROR 23000: Duplicate entry '1-1' for key 1 select id from t1; id 0 diff --git a/mysql-test/r/comments.result b/mysql-test/r/comments.result index 8092f789954..a9106ce0538 100644 --- a/mysql-test/r/comments.result +++ b/mysql-test/r/comments.result @@ -6,7 +6,7 @@ multi line comment */; 1 1 ; -Query was empty +ERROR 42000: Query was empty select 1 /*!32301 +1 */; 1 /*!32301 +1 2 diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index bd8343428c2..42a525796a2 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -17,29 +17,29 @@ b drop table t1; create table t2 type=heap select * from t1; -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist create table t2 select auto+1 from t1; -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist drop table if exists t1,t2; Warnings: Note 1051 Unknown table 't1' Note 1051 Unknown table 't2' create table t1 (b char(0) not null, index(b)); -The used storage engine can't index column 'b' +ERROR 42000: The used storage engine can't index column 'b' create table t1 (a int not null auto_increment,primary key (a)) type=heap; create table t1 (a int not null,b text) type=heap; -The used table type doesn't support BLOB/TEXT columns +ERROR 42000: The used table type doesn't support BLOB/TEXT columns 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; -Incorrect table definition; There can only be one auto column and it must be defined as a key +ERROR 42000: Incorrect table definition; There can only be one auto column and it must be defined as a key create table not_existing_database.test (a int); Got one of the listed errors create table `a/a` (a int); -Incorrect table name 'a/a' +ERROR 42000: Incorrect table name 'a/a' create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa int); -Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +ERROR 42000: Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int); -Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long +ERROR 42000: Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long create table 1ea10 (1a20 int,1e int); insert into 1ea10 values(1,1); select 1ea10.1a20,1e+ 1e+10 from 1ea10; @@ -61,11 +61,11 @@ create table test_$1.test2$ (a int); drop table test_$1.test2$; drop database test_$1; create table `` (a int); -Incorrect table name '' +ERROR 42000: Incorrect table name '' drop table if exists ``; -Incorrect table name '' +ERROR 42000: Incorrect table name '' create table t1 (`` int); -Incorrect column name '' +ERROR 42000: Incorrect column name '' drop table if exists t1; Warnings: Note 1051 Unknown table 't1' @@ -115,17 +115,17 @@ Field Type Collation Null Key Default Extra a int(11) NULL YES NULL drop table if exists t2; create table t2 (a int, a float) select * from t1; -Duplicate column name 'a' +ERROR 42S21: Duplicate column name 'a' drop table if exists t2; Warnings: Note 1051 Unknown table 't2' create table t2 (a int) select a as b, a+1 as b from t1; -Duplicate column name 'b' +ERROR 42S21: Duplicate column name 'b' drop table if exists t2; Warnings: Note 1051 Unknown table 't2' create table t2 (b int) select a as b, a+1 as b from t1; -Duplicate column name 'b' +ERROR 42S21: Duplicate column name 'b' drop table if exists t1,t2; Warnings: Note 1051 Unknown table 't2' @@ -204,11 +204,11 @@ 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 +ERROR 23000: Column 'k2' cannot be null insert into t1 values (NULL, 3); -Column 'k1' cannot be null +ERROR 23000: Column 'k1' cannot be null insert into t1 values (NULL, NULL); -Column 'k1' cannot be null +ERROR 23000: Column 'k1' cannot be null drop table t1; create table t1 (a int, key(a)); create table t2 (b int, foreign key(b) references t1(a), key(b)); @@ -273,15 +273,15 @@ select * from t2; id name create table t3 like t1; create table t3 like test_$1.t3; -Table 't3' already exists +ERROR 42S01: Table 't3' already exists create table non_existing_database.t1 like t1; Got one of the listed errors create table t3 like non_existing_table; -Unknown table 'non_existing_table' +ERROR 42S02: Unknown table 'non_existing_table' create temporary table t3 like t1; -Table 't3' already exists +ERROR 42S01: Table 't3' already exists create table t3 like `a/a`; -Incorrect table name 'a/a' +ERROR 42000: Incorrect table name 'a/a' drop table t1, t2, t3; drop table t3; drop database test_$1; diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result index d2ae3950eaf..6da7561bb8c 100644 --- a/mysql-test/r/ctype_collate.result +++ b/mysql-test/r/ctype_collate.result @@ -6,7 +6,7 @@ latin1_f CHAR(32) CHARACTER SET latin1 NOT NULL CREATE TABLE t2 ( latin1_f CHAR(32) CHARACTER SET latin1 COLLATE koi8r_general_ci NOT NULL ); -COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' +ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' INSERT INTO t1 (latin1_f) VALUES (_latin1'A'); INSERT INTO t1 (latin1_f) VALUES (_latin1'a'); INSERT INTO t1 (latin1_f) VALUES (_latin1'AD'); @@ -180,7 +180,7 @@ z å ü SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE koi8r_general_ci; -COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' +ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' SELECT latin1_f COLLATE latin1_swedish_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as; latin1_f_as A @@ -298,7 +298,7 @@ z å ü SELECT latin1_f COLLATE koi8r_general_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as; -COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' +ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f; latin1_f count(*) A 2 @@ -390,7 +390,7 @@ z 1 å 1 ü 1 SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE koi8r_general_ci; -COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' +ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1' SELECT DISTINCT latin1_f FROM t1; latin1_f A @@ -482,7 +482,7 @@ y Z z SELECT DISTINCT latin1_f COLLATE koi8r FROM t1; -COLLATION 'koi8r' is not valid for CHARACTER SET 'latin1' +ERROR 42000: COLLATION 'koi8r' is not valid for CHARACTER SET 'latin1' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -524,5 +524,5 @@ SELECT charset('a'),collation('a'),coercibility('a'),'a'='A'; charset('a') collation('a') coercibility('a') 'a'='A' latin1 latin1_swedish_ci 3 1 SET CHARACTER SET 'DEFAULT'; -Unknown character set: 'DEFAULT' +ERROR 42000: Unknown character set: 'DEFAULT' DROP TABLE t1; diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index 8e4b52a8366..ceb511a7891 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -21,7 +21,7 @@ insert delayed into t1 values (1,"b"); insert delayed into t1 values (null,"c"); insert delayed into t1 values (3,"d"),(null,"e"); insert delayed into t1 values (3,"this will give an","error"); -Column count doesn't match value count at row 1 +ERROR 21S01: Column count doesn't match value count at row 1 select * from t1; a b 1 b diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index c87fa8fb927..cd45cf03853 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -30,7 +30,7 @@ CREATE TABLE `t1` ( PRIMARY KEY (`i`) ); DELETE FROM t1 USING t1 WHERE post='1'; -Unknown column 'post' in 'where clause' +ERROR 42S22: Unknown column 'post' in 'where clause' drop table t1; CREATE TABLE t1 ( bool char(0) default NULL, diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index bfd4c544131..5f405d83fa5 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -3,9 +3,9 @@ select * from (select 2 from DUAL) b; 2 2 SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b; -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' SELECT 1 as a FROM (SELECT a UNION SELECT 1) b; -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' 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); @@ -25,18 +25,18 @@ a y 3 3 3 3 SELECT a FROM (SELECT 1 FROM (SELECT 1) a HAVING a=1) b; -Unknown column 'a' in 'having clause' +ERROR 42S22: Unknown column 'a' in 'having clause' SELECT a,b as a FROM (SELECT '1' as a,'2' as b) b HAVING a=1; -Column: 'a' in having clause is ambiguous +ERROR 23000: Column: 'a' in having clause is ambiguous SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=2; a a 1 2 SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=1; a a SELECT 1 FROM (SELECT 1) a WHERE a=2; -Unknown column 'a' in 'where clause' +ERROR 42S22: Unknown column 'a' in 'where clause' SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) as a; -Unknown column 'a' in 'having clause' +ERROR 42S22: Unknown column 'a' in 'having clause' select * from t1 as x1, (select * from t1) as x2; a b a b 1 a 1 a @@ -146,10 +146,17 @@ select * from (select 1 as a) b left join (select 2 as a) c using(a); a a 1 NULL SELECT * FROM (SELECT 1 UNION SELECT a) b; -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' SELECT 1 as a FROM (SELECT a UNION SELECT 1) b; -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b; -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' select 1 from (select 2) a order by 0; -Unknown column '0' in 'order clause' +ERROR 42S22: Unknown column '0' in 'order clause' +create table t1 (id int); +insert into t1 values (1),(2),(3); +describe select * from (select * from t1 group by id) bar; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 +2 DERIVED t1 ALL NULL NULL NULL NULL 3 Using temporary; Using filesort +drop table t1; diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index 1f459faa8f4..9ebcd1fb915 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -175,7 +175,7 @@ explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 index a a 5 NULL 6 Using index; Using temporary 1 SIMPLE t2 index a a 4 NULL 5 Using index; Distinct -1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 t2.a 1 Using where; Distinct +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where; Distinct SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a; a 1 @@ -190,7 +190,7 @@ insert into t3 select * from t4; explain select distinct t1.a from t1,t3 where t1.a=t3.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary -1 SIMPLE t3 ref a a 5 t1.a 10 Using where; Using index; Distinct +1 SIMPLE t3 ref a a 5 test.t1.a 10 Using where; Using index; Distinct select distinct t1.a from t1,t3 where t1.a=t3.a; a 1 diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result index a9048b65d51..2b878455bea 100644 --- a/mysql-test/r/drop.result +++ b/mysql-test/r/drop.result @@ -1,12 +1,12 @@ drop table if exists t1; drop table t1; -Unknown table 't1' +ERROR 42S02: Unknown table 't1' create table t1(n int); insert into t1 values(1); create temporary table t1( n int); insert into t1 values(2); create table t1(n int); -Table 't1' already exists +ERROR 42S01: Table 't1' already exists drop table t1; select * from t1; n @@ -48,4 +48,4 @@ Database mysql test drop database mysqltest; -Can't drop database 'mysqltest'. Database doesn't exist +ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist diff --git a/mysql-test/r/err000001.result b/mysql-test/r/err000001.result index 5afecc6d600..d0011c8deb6 100644 --- a/mysql-test/r/err000001.result +++ b/mysql-test/r/err000001.result @@ -1,25 +1,25 @@ drop table if exists t1; insert into t1 values(1); -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist delete from t1; -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist update t1 set a=1; -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist create table t1 (a int); select count(test.t1.b) from t1; -Unknown column 'test.t1.b' in 'field list' +ERROR 42S22: Unknown column 'test.t1.b' in 'field list' select count(not_existing_database.t1) from t1; -Unknown table 'not_existing_database' in field list +ERROR 42S02: Unknown table 'not_existing_database' in field list select count(not_existing_database.t1.a) from t1; -Unknown table 'not_existing_database.t1' in field list +ERROR 42S02: Unknown table 'not_existing_database.t1' in field list select count(not_existing_database.t1.a) from not_existing_database.t1; Got one of the listed errors select 1 from t1 order by 2; -Unknown column '2' in 'order clause' +ERROR 42S22: Unknown column '2' in 'order clause' select 1 from t1 group by 2; -Unknown column '2' in 'group statement' +ERROR 42S22: Unknown column '2' in 'group statement' select 1 from t1 order by t1.b; -Unknown column 't1.b' in 'order clause' +ERROR 42S22: Unknown column 't1.b' in 'order clause' select count(*),b from t1; -Unknown column 'b' in 'field list' +ERROR 42S22: Unknown column 'b' in 'field list' drop table t1; diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index 63e4f4030d3..02e1ace71e1 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -24,9 +24,9 @@ explain select * from t1 use key (str,str) where str="foo"; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 const str str 11 const 1 explain select * from t1 use key (str,str,foo) where str="foo"; -Key column 'foo' doesn't exist in table +ERROR 42000: Key column 'foo' doesn't exist in table explain select * from t1 ignore key (str,str,foo) where str="foo"; -Key column 'foo' doesn't exist in table +ERROR 42000: Key column 'foo' doesn't exist in table drop table t1; explain select 1; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result index 4e7e4769f1b..bab9b543307 100644 --- a/mysql-test/r/flush.result +++ b/mysql-test/r/flush.result @@ -8,7 +8,7 @@ n 3 flush tables with read lock; drop table t2; -Table 't2' was locked with a READ lock and can't be updated +ERROR HY000: Table 't2' was locked with a READ lock and can't be updated drop table t2; unlock tables; create database mysqltest; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 5b410396390..caf93e7e973 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -162,11 +162,11 @@ KEY tig (ticket), fulltext index tix (inhalt) ); select * from t2 where MATCH inhalt AGAINST (t2.inhalt); -Wrong arguments to AGAINST +ERROR HY000: Wrong arguments to AGAINST select * from t2 where MATCH ticket AGAINST ('foobar'); -Can't find FULLTEXT index matching the column list +ERROR HY000: Can't find FULLTEXT index matching the column list select * from t2,t3 where MATCH (t2.inhalt,t3.inhalt) AGAINST ('foobar'); -Wrong arguments to MATCH +ERROR HY000: Wrong arguments to MATCH drop table t1,t2,t3; CREATE TABLE t1 ( id int(11) auto_increment, diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 0dc84f090f1..51b61dbb3e6 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -155,7 +155,7 @@ show warnings; Level Code Message Warning 1258 1 line(s) was(were) cut by group_concat() select group_concat(sum(a)) from t1 group by grp; -Invalid use of group function +ERROR HY000: Invalid use of group function select grp,group_concat(c order by 2) from t1 group by grp; -Unknown column '2' in 'group statement' +ERROR 42S22: Unknown column '2' in 'group statement' drop table if exists t1; diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result index 15ff34a6d80..cde21ead33c 100644 --- a/mysql-test/r/func_system.result +++ b/mysql-test/r/func_system.result @@ -37,13 +37,13 @@ version()>=_latin1"3.23.29" select charset(version()); charset(version()) utf8 -create table t1 select database(), user(), version(); +create table t1 (version char(40)) select database(), user(), version() as 'version'; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `database()` char(102) character set utf8 NOT NULL default '', `user()` char(231) character set utf8 NOT NULL default '', - `version()` char(21) character set utf8 NOT NULL default '' + `version` char(40) character set utf8 default NULL ) TYPE=MyISAM CHARSET=latin1 drop table t1; select TRUE,FALSE,NULL; diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result index 3892765f587..0ffc48ad879 100644 --- a/mysql-test/r/grant_cache.result +++ b/mysql-test/r/grant_cache.result @@ -84,7 +84,7 @@ a b c a 1 1 1 test.t1 2 2 2 test.t1 select * from t2; -select command denied to user: 'mysqltest_2@localhost' for table 't2' +ERROR 42000: select command denied to user: 'mysqltest_2@localhost' for table 't2' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 6 @@ -98,17 +98,17 @@ select "user3"; user3 user3 select * from t1; -select command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1' +ERROR 42000: select command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1' select a from t1; a 1 2 select c from t1; -SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1' +ERROR 42000: SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1' select * from t2; -select command denied to user: 'mysqltest_3@localhost' for table 't2' +ERROR 42000: select command denied to user: 'mysqltest_3@localhost' for table 't2' select mysqltest.t1.c from test.t1,mysqltest.t1; -SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1' +ERROR 42000: SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 6 @@ -122,7 +122,7 @@ select "user4"; user4 user4 select a from t1; -No Database Selected +ERROR 42000: No Database Selected select * from mysqltest.t1,test.t1; a b c a 1 1 1 test.t1 diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 9e89f2c0e5a..23f82532d06 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -1,6 +1,6 @@ drop table if exists t1,t2,t3; SELECT 1 FROM (SELECT 1) as a GROUP BY SUM(1); -Invalid use of group function +ERROR HY000: Invalid use of group function CREATE TABLE t1 ( spID int(10) unsigned, userID int(10) unsigned, @@ -56,7 +56,7 @@ userid MIN(t1.score+0.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; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary -1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 t1.userID 1 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.userID 1 Using index drop table t1,t2; CREATE TABLE t1 ( PID int(10) unsigned NOT NULL auto_increment, @@ -79,7 +79,7 @@ KEY payDate (payDate) ); INSERT INTO t1 VALUES (1,'1970-01-01','1997-10-17 00:00:00',2529,1,21000,11886,'check',0,'F',16200,6); SELECT COUNT(P.URID),SUM(P.amount),P.method, MIN(PP.recdate+0) > 19980501000000 AS IsNew FROM t1 AS P JOIN t1 as PP WHERE P.URID = PP.URID GROUP BY method,IsNew; -Can't group on 'IsNew' +ERROR 42000: Can't group on 'IsNew' drop table t1; CREATE TABLE t1 ( cid mediumint(9) NOT NULL auto_increment, diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result index d8381ccc626..26b3c700d59 100644 --- a/mysql-test/r/handler.result +++ b/mysql-test/r/handler.result @@ -6,7 +6,7 @@ insert into t1 values (20,"ggg"),(21,"hhh"),(22,"iii"); handler t1 open as t2; handler t2 read a=(SELECT 1); -You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1 +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1 handler t2 read a first; a b 14 aaa @@ -51,7 +51,7 @@ handler t2 read a=(16); a b 16 ccc handler t2 read a=(19,"fff"); -Too many key parts specified. Max 1 parts allowed +ERROR 42000: Too many key parts specified. Max 1 parts allowed handler t2 read b=(19,"fff"); a b 19 fff @@ -62,7 +62,7 @@ handler t2 read b=(19); a b 19 fff handler t1 read a last; -Unknown table 't1' in HANDLER +ERROR 42S02: Unknown table 't1' in HANDLER handler t2 read a=(11); a b handler t2 read a>=(11); @@ -135,16 +135,16 @@ handler t2 read next; a b 19 fff handler t2 read last; -You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 handler t2 close; handler t1 open as t2; drop table t1; create table t1 (a int); insert into t1 values (17); handler t2 read first; -Unknown table 't2' in HANDLER +ERROR 42S02: Unknown table 't2' in HANDLER handler t1 open as t2; alter table t1 type=MyISAM; handler t2 read first; -Unknown table 't2' in HANDLER +ERROR 42S02: Unknown table 't2' in HANDLER drop table t1; diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index ab5870357f9..7d929f50801 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -86,7 +86,7 @@ x y x y explain select * from t1,t1 as t2 where t1.x=t2.y; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL x NULL NULL NULL 6 -1 SIMPLE t2 eq_ref y y 4 t1.x 1 +1 SIMPLE t2 eq_ref y y 4 test.t1.x 1 drop table t1; create table t1 (a int) type=heap; insert into t1 values(1); @@ -201,7 +201,7 @@ SELECT * FROM t1 WHERE b<=>NULL; a b 99 NULL INSERT INTO t1 VALUES (1,3); -Duplicate entry '3' for key 1 +ERROR 23000: Duplicate entry '3' for key 1 DROP TABLE t1; CREATE TABLE t1 (a int not null, primary key(a)) type=heap; INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11); diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result index 7f6c9f8e591..6ae00c89a3a 100644 --- a/mysql-test/r/heap_btree.result +++ b/mysql-test/r/heap_btree.result @@ -89,7 +89,7 @@ x y x y explain select * from t1,t1 as t2 where t1.x=t2.y; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL x NULL NULL NULL 6 -1 SIMPLE t2 eq_ref y y 4 t1.x 1 +1 SIMPLE t2 eq_ref y y 4 test.t1.x 1 drop table t1; create table t1 (a int) type=heap; insert into t1 values(1); @@ -217,7 +217,7 @@ SELECT * FROM t1 WHERE b<=>NULL; a b 99 NULL INSERT INTO t1 VALUES (1,3); -Duplicate entry '3' for key 1 +ERROR 23000: Duplicate entry '3' for key 1 DROP TABLE t1; CREATE TABLE t1 (a int, b int, c int, key using BTREE (a, b, c)) type=heap; INSERT INTO t1 VALUES (1, NULL, NULL), (1, 1, NULL), (1, NULL, 1); diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index 9554990aa34..72278c5da67 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -86,7 +86,7 @@ x y x y explain select * from t1,t1 as t2 where t1.x=t2.y; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL x NULL NULL NULL 6 -1 SIMPLE t2 eq_ref y y 4 t1.x 1 +1 SIMPLE t2 eq_ref y y 4 test.t1.x 1 drop table t1; create table t1 (a int) type=heap; insert into t1 values(1); @@ -201,7 +201,7 @@ SELECT * FROM t1 WHERE b<=>NULL; a b 99 NULL INSERT INTO t1 VALUES (1,3); -Duplicate entry '3' for key 1 +ERROR 23000: Duplicate entry '3' for key 1 DROP TABLE t1; CREATE TABLE t1 (a int not null, primary key using HASH (a)) type=heap; INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11); diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 0f65c8b0fe3..77c96a32c73 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -224,7 +224,7 @@ n after commit commit; insert into t1 values (5); insert into t1 values (4); -Duplicate entry '4' for key 1 +ERROR 23000: Duplicate entry '4' for key 1 commit; select n, "after commit" from t1; n after commit @@ -233,7 +233,7 @@ n after commit set autocommit=1; insert into t1 values (6); insert into t1 values (4); -Duplicate entry '4' for key 1 +ERROR 23000: Duplicate entry '4' for key 1 select n from t1; n 4 @@ -263,7 +263,7 @@ drop table t1; CREATE TABLE t1 (id char(8) not null primary key, val int not null) type=innodb; insert into t1 values ('pippo', 12); insert into t1 values ('pippo', 12); -Duplicate entry 'pippo' for key 1 +ERROR 23000: Duplicate entry 'pippo' for key 1 delete from t1; delete from t1 where id = 'pippo'; select * from t1; @@ -427,9 +427,9 @@ UNIQUE ggid (ggid) insert into t1 (ggid,passwd) values ('test1','xxx'); insert into t1 (ggid,passwd) values ('test2','yyy'); insert into t1 (ggid,passwd) values ('test2','this will fail'); -Duplicate entry 'test2' for key 2 +ERROR 23000: Duplicate entry 'test2' for key 2 insert into t1 (ggid,id) values ('this will fail',1); -Duplicate entry '1' for key 1 +ERROR 23000: Duplicate entry '1' for key 1 select * from t1 where ggid='test1'; id ggid email passwd 1 test1 xxx @@ -442,7 +442,7 @@ id ggid email passwd replace into t1 (ggid,id) values ('this will work',1); replace into t1 (ggid,passwd) values ('test2','this will work'); update t1 set id=100,ggid='test2' where id=1; -Duplicate entry 'test2' for key 2 +ERROR 23000: Duplicate entry 'test2' for key 2 select * from t1; id ggid email passwd 1 this will work @@ -753,7 +753,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3 insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL'); LOCK TABLES t1 WRITE; insert into t1 values (99,1,2,'D'),(1,1,2,'D'); -Duplicate entry '1-1' for key 1 +ERROR 23000: Duplicate entry '1-1' for key 1 select id from t1; id 0 @@ -771,7 +771,7 @@ insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJ LOCK TABLES t1 WRITE; begin; insert into t1 values (99,1,2,'D'),(1,1,2,'D'); -Duplicate entry '1-1' for key 1 +ERROR 23000: Duplicate entry '1-1' for key 1 select id from t1; id 0 @@ -788,7 +788,7 @@ id id3 UNLOCK TABLES; DROP TABLE t1; create table t1 (a char(20), unique (a(5))) type=innodb; -Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys +ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys create table t1 (a char(20), index (a(5))) type=innodb; show create table t1; Table Create Table @@ -851,7 +851,7 @@ set autocommit=0; create table t1 (a int not null) type= innodb; insert into t1 values(1),(2); truncate table t1; -Can't execute the given command because you have active locked tables or an active transaction +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction commit; truncate table t1; select * from t1; diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result index 38c39e2936f..1fadc3a61de 100644 --- a/mysql-test/r/innodb_handler.result +++ b/mysql-test/r/innodb_handler.result @@ -49,7 +49,7 @@ handler t2 read a=(16); a b 16 ccc handler t2 read a=(19,"fff"); -Too many key parts specified. Max 1 parts allowed +ERROR 42000: Too many key parts specified. Max 1 parts allowed handler t2 read b=(19,"fff"); a b 19 fff @@ -60,7 +60,7 @@ handler t2 read b=(19); a b 19 fff handler t1 read a last; -Unknown table 't1' in HANDLER +ERROR 42S02: Unknown table 't1' in HANDLER handler t2 read a=(11); a b handler t2 read a>=(11); @@ -130,7 +130,7 @@ handler t2 read next; a b 18 eee handler t2 read last; -You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 handler t2 close; handler t1 open as t2; handler t2 read first; @@ -138,7 +138,7 @@ a b 17 ddd alter table t1 type=innodb; handler t2 read first; -Unknown table 't2' in HANDLER +ERROR 42S02: Unknown table 't2' in HANDLER 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); diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 9a65eaee573..3325995f2bd 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -4,7 +4,7 @@ insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7, create table t2 (payoutID SMALLINT UNSIGNED NOT NULL PRIMARY KEY); insert into t2 (payoutID) SELECT DISTINCT payoutID FROM t1; insert into t2 (payoutID) SELECT payoutID+10 FROM t1; -Duplicate entry '16' for key 1 +ERROR 23000: Duplicate entry '16' for key 1 insert ignore into t2 (payoutID) SELECT payoutID+10 FROM t1; select * from t2; payoutID diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 068f7c68286..4ef25781331 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -26,7 +26,7 @@ a b c 3 4 1020 5 6 130 INSERT t1 VALUES (1,9,70) ON DUPLICATE KEY UPDATE c=c+100000, b=4; -Duplicate entry '4' for key 2 +ERROR 23000: Duplicate entry '4' for key 2 SELECT * FROM t1; a b c 1 2 10010 diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 4bc045aa2f7..05dac389ada 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -128,7 +128,7 @@ a 1 2 select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a); -Too many tables. MySQL can only use XX tables in a join +ERROR HY000: Too many tables. MySQL can only use XX tables in a join drop table t1; CREATE TABLE t1 ( a int(11) NOT NULL, diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 123de82fe09..9e494fc88c2 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -95,7 +95,7 @@ id select_type table type possible_keys key key_len ref rows Extra explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 7 -1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 t1.a 1 Using where +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 test.t1.a 1 Using where select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a); grp a c id a c d a 1 1 a 1 1 a 1 1 @@ -106,11 +106,11 @@ grp a c id a c d a 3 6 D 3 6 C 6 6 NULL NULL NULL NULL NULL NULL NULL explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a); -Cross dependency found in OUTER JOIN. Examine your ON conditions +ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a); -Cross dependency found in OUTER JOIN. Examine your ON conditions +ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a); -Cross dependency found in OUTER JOIN. Examine your ON conditions +ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions select t1.*,t2.* from t1 inner join t2 using (a); grp a c id a c d 1 1 a 1 1 a 1 @@ -169,7 +169,7 @@ usr_id uniq_id increment usr2_id c_amount max 3 4 84676 NULL NULL NULL INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes'); INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes'); -Duplicate entry '2-3' for key 1 +ERROR 23000: Duplicate entry '2-3' for key 1 INSERT INTO t2 VALUES (7,3,1000,2000,0,0,746294,937484,'yes'); SELECT t1.usr_id,t1.uniq_id,t1.increment,t2.usr2_id,t2.c_amount,t2.max FROM t1 LEFT JOIN t2 ON t2.id = t1.uniq_id WHERE t1.uniq_id = 4 ORDER BY t2.c_amount; usr_id uniq_id increment usr2_id c_amount max @@ -406,7 +406,7 @@ insert into t3 values (1); insert into t4 values (1,1); insert into t5 values (1,1); explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23; -Cross dependency found in OUTER JOIN. Examine your ON conditions +ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions drop table t1,t2,t3,t4,t5; create table t1 (n int, m int, o int, key(n)); create table t2 (n int not null, m int, o int, primary key(n)); diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 5060fbff5e8..e0b2b84ac16 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -127,7 +127,7 @@ primary key (SEQNO, MOTYPEID, MOINSTANCEID, ATTRID, VALUE ) INSERT INTO t1 VALUES (1, 1, 1, 1, 'a'); INSERT INTO t1 VALUES (1, 1, 1, 1, 'b'); INSERT INTO t1 VALUES (1, 1, 1, 1, 'a'); -Duplicate entry '1-1-1-1-a' for key 1 +ERROR 23000: Duplicate entry '1-1-1-1-a' for key 1 drop table t1; CREATE TABLE t1 ( a tinytext NOT NULL, diff --git a/mysql-test/r/lock.result b/mysql-test/r/lock.result index ad5251b9110..68feb9c44d7 100644 --- a/mysql-test/r/lock.result +++ b/mysql-test/r/lock.result @@ -8,9 +8,9 @@ NULL 1 update t1 set id=-1 where id=1; LOCK TABLE t1 READ; update t1 set id=1 where id=1; -Table 't1' was locked with a READ lock and can't be updated +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated create table t2 SELECT * from t1; -Table 't2' was not locked with LOCK TABLES +ERROR HY000: Table 't2' was not locked with LOCK TABLES create temporary table t2 SELECT * from t1; drop table if exists t2; unlock tables; diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index b808fca0acf..a0efce727d3 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -22,5 +22,5 @@ create table t2 (a int); lock table t1 write, t2 write; insert t1 select * from t2; drop table t2; -Table 'test.t2' doesn't exist +ERROR 42S02: Table 'test.t2' doesn't exist drop table t1; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index b28607218d1..323931ae3eb 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -177,9 +177,9 @@ t3 CREATE TABLE `t3` ( ) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2) create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2); select * from t4; -Can't open file: 't4.MRG'. (errno: 143) +ERROR HY000: Can't open file: 't4.MRG'. (errno: 143) create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2); -Incorrect table definition; All MERGE tables must be in the same database +ERROR HY000: Incorrect table definition; All MERGE tables must be in the same database drop table if exists t5,t4,t3,t1,t2; Warnings: Note 1051 Unknown table 't5' diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 2aa7db1599e..15d04422f9d 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -147,11 +147,11 @@ insert into t1 values(1,1); insert into t2 values(1,10),(2,20); LOCK TABLES t1 write, t2 read; DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n; -Table 't2' was locked with a READ lock and can't be updated +ERROR HY000: Table 't2' was locked with a READ lock and can't be updated UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n; -Table 't2' was locked with a READ lock and can't be updated +ERROR HY000: Table 't2' was locked with a READ lock and can't be updated UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; -Table 't2' was locked with a READ lock and can't be updated +ERROR HY000: Table 't2' was locked with a READ lock and can't be updated unlock tables; LOCK TABLES t1 write, t2 write; UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; @@ -172,7 +172,7 @@ create table t2 (n int(10), d int(10)); insert into t1 values(1,1); insert into t2 values(1,10),(2,20); UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; -You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column +ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column set sql_safe_updates=0; drop table t1,t2; set timestamp=1038401397; @@ -190,7 +190,7 @@ n d unix_timestamp(t) 1 10 1038401397 2 20 1038401397 UPDATE t1,t2 SET 1=2 WHERE t1.n=t2.n; -You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '1=2 WHERE t1.n=t2.n' at line 1 +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '1=2 WHERE t1.n=t2.n' at line 1 drop table t1,t2; set timestamp=0; set sql_safe_updates=0; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 5cfd1afd867..fd9ff2c90cf 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -339,10 +339,10 @@ Table Op Msg_type Msg_text test.t1 check status OK drop table t1; CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), KEY t1 (a, b, c)); -Specified key was too long. Max key length is 500 +ERROR 42000: Specified key was too long. Max key length is 500 CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255)); ALTER TABLE t1 ADD INDEX t1 (a, b, c); -Specified key was too long. Max key length is 500 +ERROR 42000: Specified key was too long. Max key length is 500 DROP TABLE t1; CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a)); INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4); @@ -370,11 +370,11 @@ id select_type table type possible_keys key key_len ref rows Extra explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL a NULL NULL NULL 2 -1 SIMPLE t1 ref a a 4 t2.a 3 +1 SIMPLE t1 ref a a 4 test.t2.a 3 explain select * from t1,t2 where t1.b=t2.b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL b NULL NULL NULL 2 -1 SIMPLE t1 ref b b 5 t2.b 1 Using where +1 SIMPLE t1 ref b b 5 test.t2.b 1 Using where explain select * from t1,t2 force index(c) where t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL a NULL NULL NULL 5 @@ -393,7 +393,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where drop table t1,t2; CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM; -This version of MySQL doesn't yet support 'RTREE INDEX' +ERROR 42000: This version of MySQL doesn't yet support 'RTREE INDEX' DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index d6dfb4621ab..fd621d06c2b 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -82,33 +82,33 @@ UPDATE t1 SET d=NULL; Warnings: Warning 1261 Data truncated, NULL supplied to NOT NULL column 'd' at row 1 INSERT INTO t1 (a) values (null); -Column 'a' cannot be null +ERROR 23000: Column 'a' cannot be null INSERT INTO t1 (a) values (1/null); -Column 'a' cannot be null +ERROR 23000: Column 'a' cannot be null INSERT INTO t1 (a) values (null),(null); Warnings: Warning 1261 Data truncated, NULL supplied to NOT NULL column 'a' at row 1 Warning 1261 Data truncated, NULL supplied to NOT NULL column 'a' at row 2 INSERT INTO t1 (b) values (null); -Column 'b' cannot be null +ERROR 23000: Column 'b' cannot be null INSERT INTO t1 (b) values (1/null); -Column 'b' cannot be null +ERROR 23000: Column 'b' cannot be null INSERT INTO t1 (b) values (null),(null); Warnings: Warning 1261 Data truncated, NULL supplied to NOT NULL column 'b' at row 1 Warning 1261 Data truncated, NULL supplied to NOT NULL column 'b' at row 2 INSERT INTO t1 (c) values (null); -Column 'c' cannot be null +ERROR 23000: Column 'c' cannot be null INSERT INTO t1 (c) values (1/null); -Column 'c' cannot be null +ERROR 23000: Column 'c' cannot be null INSERT INTO t1 (c) values (null),(null); Warnings: Warning 1261 Data truncated, NULL supplied to NOT NULL column 'c' at row 1 Warning 1261 Data truncated, NULL supplied to NOT NULL column 'c' at row 2 INSERT INTO t1 (d) values (null); -Column 'd' cannot be null +ERROR 23000: Column 'd' cannot be null INSERT INTO t1 (d) values (1/null); -Column 'd' cannot be null +ERROR 23000: Column 'd' cannot be null INSERT INTO t1 (d) values (null),(null); Warnings: Warning 1261 Data truncated, NULL supplied to NOT NULL column 'd' at row 1 diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 428d1052d19..0b7a98e3fb3 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -1,27 +1,256 @@ -drop table if exists t1; -create table t1 ( product varchar(32), country varchar(32), year int, profit int); -insert into t1 values ( 'Computer', 'India',2000, 1200), -( 'TV', 'United States', 1999, 150), -( 'Calculator', 'United States', 1999,50), -( 'Computer', 'United States', 1999,1500), -( 'Computer', 'United States', 2000,1500), -( 'TV', 'United States', 2000, 150), -( 'TV', 'India', 2000, 100), -( 'TV', 'India', 2000, 100), -( 'Calculator', 'United States', 2000,75), -( 'Calculator', 'India', 2000,75), -( 'TV', 'India', 1999, 100), -( 'Computer', 'India', 1999,1200), -( 'Computer', 'United States', 2000,1500), -( 'Calculator', 'United States', 2000,75); -select product, country , year, sum(profit) from t1 group by product, country, year with cube; -This version of MySQL doesn't yet support 'CUBE' -explain select product, country , year, sum(profit) from t1 group by product, country, year with cube; -This version of MySQL doesn't yet support 'CUBE' -select product, country , year, sum(profit) from t1 group by product, country, year with rollup; -This version of MySQL doesn't yet support 'ROLLUP' -explain select product, country , year, sum(profit) from t1 group by product, country, year with rollup; -This version of MySQL doesn't yet support 'ROLLUP' -select product, country , year, sum(profit) from t1 group by product, country, year with cube union all select product, country , year, sum(profit) from t1 group by product, country, year with rollup; -This version of MySQL doesn't yet support 'CUBE' -drop table t1; +drop table if exists t1,t2; +create table t1 (product varchar(32), country_id int not null, year int, profit int); +insert into t1 values ( 'Computer', 2,2000, 1200), +( 'TV', 1, 1999, 150), +( 'Calculator', 1, 1999,50), +( 'Computer', 1, 1999,1500), +( 'Computer', 1, 2000,1500), +( 'TV', 1, 2000, 150), +( 'TV', 2, 2000, 100), +( 'TV', 2, 2000, 100), +( 'Calculator', 1, 2000,75), +( 'Calculator', 2, 2000,75), +( 'TV', 1, 1999, 100), +( 'Computer', 1, 1999,1200), +( 'Computer', 2, 2000,1500), +( 'Calculator', 2, 2000,75), +( 'Phone', 3, 2003,10) +; +create table t2 (country_id int primary key, country char(20) not null); +insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland'); +select product, sum(profit) from t1 group by product; +product sum(profit) +Calculator 275 +Computer 6900 +Phone 10 +TV 600 +select product, sum(profit) from t1 group by product with rollup; +product sum(profit) +Calculator 275 +Computer 6900 +Phone 10 +TV 600 +NULL 7785 +select product, sum(profit) from t1 group by 1 with rollup; +product sum(profit) +Calculator 275 +Computer 6900 +Phone 10 +TV 600 +NULL 7785 +select product, sum(profit),avg(profit) from t1 group by product with rollup; +product sum(profit) avg(profit) +Calculator 275 68.7500 +Computer 6900 1380.0000 +Phone 10 10.0000 +TV 600 120.0000 +NULL 7785 519.0000 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year; +product country_id year sum(profit) +Calculator 1 1999 50 +Calculator 1 2000 75 +Calculator 2 2000 150 +Computer 1 1999 2700 +Computer 1 2000 1500 +Computer 2 2000 2700 +Phone 3 2003 10 +TV 1 1999 250 +TV 1 2000 150 +TV 2 2000 200 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup; +product country_id year sum(profit) +Calculator 1 1999 50 +Calculator 1 2000 75 +Calculator 1 NULL 125 +Calculator 2 2000 150 +Calculator 2 NULL 150 +Calculator NULL NULL 275 +Computer 1 1999 2700 +Computer 1 2000 1500 +Computer 1 NULL 4200 +Computer 2 2000 2700 +Computer 2 NULL 2700 +Computer NULL NULL 6900 +Phone 3 2003 10 +Phone 3 NULL 10 +Phone NULL NULL 10 +TV 1 1999 250 +TV 1 2000 150 +TV 1 NULL 400 +TV 2 2000 200 +TV 2 NULL 200 +TV NULL NULL 600 +NULL NULL NULL 7785 +explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using temporary; Using filesort +select product, country_id , sum(profit) from t1 group by product desc, country_id with rollup; +product country_id sum(profit) +TV 1 400 +TV 2 200 +TV NULL 600 +Phone 3 10 +Phone NULL 10 +Computer 1 4200 +Computer 2 2700 +Computer NULL 6900 +Calculator 1 125 +Calculator 2 150 +Calculator NULL 275 +NULL NULL 7785 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 5; +product country_id year sum(profit) +Calculator 1 1999 50 +Calculator 1 2000 75 +Calculator 1 NULL 125 +Calculator 2 2000 150 +Calculator 2 NULL 150 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 3,3; +product country_id year sum(profit) +Calculator 2 2000 150 +Calculator 2 NULL 150 +Calculator NULL NULL 275 +select product, country_id, count(*), count(distinct year) from t1 group by product, country_id; +product country_id count(*) count(distinct year) +Calculator 1 2 2 +Calculator 2 2 1 +Computer 1 3 2 +Computer 2 2 1 +Phone 3 1 1 +TV 1 3 2 +TV 2 2 1 +select product, country_id, count(*), count(distinct year) from t1 group by product, country_id with rollup; +product country_id count(*) count(distinct year) +Calculator 1 2 2 +Calculator 2 2 1 +Calculator NULL 4 2 +Computer 1 3 2 +Computer 2 2 1 +Computer NULL 5 2 +Phone 3 1 1 +Phone NULL 1 1 +TV 1 3 2 +TV 2 2 1 +TV NULL 5 2 +NULL NULL 15 3 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having country_id = 1; +product country_id year sum(profit) +Calculator 1 1999 50 +Calculator 1 2000 75 +Calculator 1 NULL 125 +Computer 1 1999 2700 +Computer 1 2000 1500 +Computer 1 NULL 4200 +TV 1 1999 250 +TV 1 2000 150 +TV 1 NULL 400 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 200; +product country_id year sum(profit) +Calculator NULL NULL 275 +Computer 1 1999 2700 +Computer 1 2000 1500 +Computer 1 NULL 4200 +Computer 2 2000 2700 +Computer 2 NULL 2700 +Computer NULL NULL 6900 +TV 1 1999 250 +TV 1 NULL 400 +TV NULL NULL 600 +NULL NULL NULL 7785 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 7000; +product country_id year sum(profit) +NULL NULL NULL 7785 +select concat(product,':',country_id) as 'prod', concat(":",year,":") as 'year',1+1, sum(profit)/count(*) from t1 group by 1,2 with rollup; +prod year 1+1 sum(profit)/count(*) +Calculator:1 :1999: 2 50.00 +Calculator:1 :2000: 2 75.00 +Calculator:1 NULL 2 62.50 +Calculator:2 :2000: 2 75.00 +Calculator:2 NULL 2 75.00 +Computer:1 :1999: 2 1350.00 +Computer:1 :2000: 2 1500.00 +Computer:1 NULL 2 1400.00 +Computer:2 :2000: 2 1350.00 +Computer:2 NULL 2 1350.00 +Phone:3 :2003: 2 10.00 +Phone:3 NULL 2 10.00 +TV:1 :1999: 2 125.00 +TV:1 :2000: 2 150.00 +TV:1 NULL 2 133.33 +TV:2 :2000: 2 100.00 +TV:2 NULL 2 100.00 +NULL NULL 2 519.00 +select product, sum(profit)/count(*) from t1 group by product with rollup; +product sum(profit)/count(*) +Calculator 68.75 +Computer 1380.00 +Phone 10.00 +TV 120.00 +NULL 519.00 +select left(product,4) as prod, sum(profit)/count(*) from t1 group by prod with rollup; +prod sum(profit)/count(*) +Calc 68.75 +Comp 1380.00 +Phon 10.00 +TV 120.00 +NULL 519.00 +select concat(product,':',country_id), 1+1, sum(profit)/count(*) from t1 group by concat(product,':',country_id) with rollup; +concat(product,':',country_id) 1+1 sum(profit)/count(*) +Calculator:1 2 62.50 +Calculator:2 2 75.00 +Computer:1 2 1400.00 +Computer:2 2 1350.00 +Phone:3 2 10.00 +TV:1 2 133.33 +TV:2 2 100.00 +NULL 2 519.00 +select product, country , year, sum(profit) from t1,t2 where t1.country_id=t2.country_id group by product, country, year with rollup; +product country year sum(profit) +Calculator India 2000 150 +Calculator India NULL 150 +Calculator USA 1999 50 +Calculator USA 2000 75 +Calculator USA NULL 125 +Calculator NULL NULL 275 +Computer India 2000 2700 +Computer India NULL 2700 +Computer USA 1999 2700 +Computer USA 2000 1500 +Computer USA NULL 4200 +Computer NULL NULL 6900 +Phone Finland 2003 10 +Phone Finland NULL 10 +Phone NULL NULL 10 +TV India 2000 200 +TV India NULL 200 +TV USA 1999 250 +TV USA 2000 150 +TV USA NULL 400 +TV NULL NULL 600 +NULL NULL NULL 7785 +select product, `sum` from (select product, sum(profit) as 'sum' from t1 group by product with rollup) as tmp where product is null; +product sum +NULL 7785 +select product from t1 where exists (select product, country_id , sum(profit) from t1 as t2 where t1.product=t2.product group by product, country_id with rollup having sum(profit) > 6000); +product +Computer +Computer +Computer +Computer +Computer +select product, country_id , year, sum(profit) from t1 group by product, country_id, year having country_id is NULL; +product country_id year sum(profit) +select concat(':',product,':'), sum(profit),avg(profit) from t1 group by product with rollup; +concat(':',product,':') sum(profit) avg(profit) +:Calculator: 275 68.7500 +:Computer: 6900 1380.0000 +:Phone: 10 10.0000 +:TV: 600 120.0000 +:TV: 7785 519.0000 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube; +ERROR 42000: This version of MySQL doesn't yet support 'CUBE' +explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube; +ERROR 42000: This version of MySQL doesn't yet support 'CUBE' +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube union all select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup; +ERROR 42000: This version of MySQL doesn't yet support 'CUBE' +drop table t1,t2; diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 3524b38e659..1e940351a4a 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -466,25 +466,25 @@ gid sid uid EXPLAIN select t1.gid, t2.sid, t3.uid from t3, t2, t1 where t2.gid = t1.gid and t2.uid = t3.uid order by t1.gid, t3.uid; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index -1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1 -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index +1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 test.t1.gid 1 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t2.uid 1 Using where; Using index EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t1.gid,t3.skr; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.gid 1 Using where EXPLAIN SELECT t1.gid, t2.sid, t3.uid from t2, t1, t3 where t2.gid = t1.gid and t2.uid = t3.uid order by t3.uid, t1.gid; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort -1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1 -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index +1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 test.t1.gid 1 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t2.uid 1 Using where; Using index EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t3.skr,t1.gid; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.gid 1 Using where EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.skr = t3.uid order by t1.gid,t3.skr; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.skr 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.skr 1 Using where drop table t1,t2,t3; CREATE TABLE t1 ( `titre` char(80) NOT NULL default '', diff --git a/mysql-test/r/packet.result b/mysql-test/r/packet.result index e994e4d63da..6e3c459b39d 100644 --- a/mysql-test/r/packet.result +++ b/mysql-test/r/packet.result @@ -12,7 +12,7 @@ select @@net_buffer_length, @@max_allowed_packet; @@net_buffer_length @@max_allowed_packet 1024 80 SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; -Got a packet bigger than 'max_allowed_packet' +ERROR 08S01: Got a packet bigger than 'max_allowed_packet' set global max_allowed_packet=default; set max_allowed_packet=default; set global net_buffer_length=default; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 1d46d1dcf25..4622bb231a2 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -615,10 +615,10 @@ id 2 alter table t1 rename to t2; select * from t1 where id=2; -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist drop table t2; select * from t1 where id=2; -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist create table t1 (word char(20) not null); select * from t1; word diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index 79eb6cc7e59..94186f254c4 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -36,7 +36,7 @@ select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))); (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))) 1 select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4)); -Cardinality error (more/less than 2 columns) +ERROR 21000: Cardinality error (more/less than 2 columns) select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))); row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))) NULL @@ -86,7 +86,7 @@ SELECT ROW('test',2,3.33)=ROW('test',2,3.33); ROW('test',2,3.33)=ROW('test',2,3.33) 1 SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4); -Cardinality error (more/less than 3 columns) +ERROR 21000: Cardinality error (more/less than 3 columns) SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33)); ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33)) 1 @@ -97,7 +97,7 @@ SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL)); ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL)) NULL SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4); -Cardinality error (more/less than 2 columns) +ERROR 21000: Cardinality error (more/less than 2 columns) create table t1 ( a int, b int, c int); insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL); select * from t1 where ROW(1,2,3)=ROW(a,b,c); @@ -135,14 +135,14 @@ ROW(1,2,3) IN(row(a,b,c), row(1,2,3)) 1 drop table t1; select ROW(1,1); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) create table t1 (i int); select 1 from t1 where ROW(1,1); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) select count(*) from t1 order by ROW(1,1); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) select count(*) from t1 having (1,1) order by i; -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) drop table t1; create table t1 (a int, b int); insert into t1 values (1, 4); diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result index 8aa667df063..79438f8fa40 100644 --- a/mysql-test/r/rpl000001.result +++ b/mysql-test/r/rpl000001.result @@ -55,7 +55,7 @@ select (@id := id) - id from t2; 0 kill @id; drop table t2; -Server shutdown in progress +ERROR 08S01: Server shutdown in progress set global sql_slave_skip_counter=1; start slave; select count(*) from t1; diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result index 06f34842577..dc1d8c4872e 100644 --- a/mysql-test/r/rpl000009.result +++ b/mysql-test/r/rpl000009.result @@ -21,7 +21,7 @@ n m drop database mysqltest; drop database if exists mysqltest2; drop database mysqltest; -Can't drop database 'mysqltest'. Database doesn't exist +ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist drop database mysqltest2; set sql_log_bin = 0; create database mysqltest2; diff --git a/mysql-test/r/rpl_empty_master_crash.result b/mysql-test/r/rpl_empty_master_crash.result index 8818029ab99..39ab1c2d9b4 100644 --- a/mysql-test/r/rpl_empty_master_crash.result +++ b/mysql-test/r/rpl_empty_master_crash.result @@ -7,6 +7,6 @@ start slave; show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space load table t1 from master; -Error connecting to master: Master is not configured +ERROR 08S01: Error connecting to master: Master is not configured load table t1 from master; -Error from master: 'Table 'test.t1' doesn't exist' +ERROR HY000: Error from master: 'Table 'test.t1' doesn't exist' diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result index 6f438c6c34a..948a755c3db 100644 --- a/mysql-test/r/rpl_log.result +++ b/mysql-test/r/rpl_log.result @@ -89,4 +89,4 @@ show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space 127.0.0.1 root MASTER_PORT 1 master-bin.000002 170 slave-relay-bin.000002 1469 master-bin.000002 Yes Yes 0 0 170 1473 show binlog events in 'slave-bin.000005' from 4; -Error when executing command SHOW BINLOG EVENTS: Could not find target log +ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result index 9ae292c2709..a91a0a2b819 100644 --- a/mysql-test/r/rpl_replicate_do.result +++ b/mysql-test/r/rpl_replicate_do.result @@ -24,5 +24,5 @@ select * from t2; n 4 select * from t11; -Table 'test.t11' doesn't exist +ERROR 42S02: Table 'test.t11' doesn't exist drop table if exists t1,t2,t11; diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index c4023832921..66209d2b852 100644 --- a/mysql-test/r/rpl_rotate_logs.result +++ b/mysql-test/r/rpl_rotate_logs.result @@ -1,9 +1,9 @@ drop table if exists t1, t2, t3, t4; drop table if exists t1, t2, t3, t4; start slave; -Could not initialize master info structure, check permisions on master.info +ERROR HY000: Could not initialize master info structure, check permisions on master.info start slave; -Could not initialize master info structure, check permisions on master.info +ERROR HY000: Could not initialize master info structure, check permisions on master.info change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; Could not initialize master info reset slave; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 8be189752ea..fbce0e9290a 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -1341,9 +1341,9 @@ explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index explain select fld3 from t2 ignore index (fld3,not_used); -Key column 'not_used' doesn't exist in table +ERROR 42000: Key column 'not_used' doesn't exist in table explain select fld3 from t2 use index (not_used); -Key column 'not_used' doesn't exist in table +ERROR 42000: Key column 'not_used' doesn't exist in table select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; fld3 honeysuckle @@ -1807,19 +1807,19 @@ fld3 explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 t2.fld1 1 Using where; Using index +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort -1 SIMPLE t3 ref period period 4 t1.period 4181 +1 SIMPLE t3 ref period period 4 test.t1.period 4181 explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 index period period 4 NULL 41810 -1 SIMPLE t1 ref period period 4 t3.period 4181 +1 SIMPLE t1 ref period period 4 test.t3.period 4181 explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index period period 4 NULL 41810 -1 SIMPLE t3 ref period period 4 t1.period 4181 +1 SIMPLE t3 ref period period 4 test.t1.period 4181 select period from t1; period 9410 diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result index 3303f19d9c7..e73161996b8 100644 --- a/mysql-test/r/select_safe.result +++ b/mysql-test/r/select_safe.result @@ -20,17 +20,17 @@ select 1 from t1,t1 as t2,t1 as t3,t1 as t4; 1 1 update t1 set b="a"; -You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column +ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column update t1 set b="a" where b="test"; -You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column +ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column delete from t1; -You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column +ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column delete from t1 where b="test"; -You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column +ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column 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 +ERROR HY000: 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 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 +ERROR 42000: 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; @@ -41,7 +41,7 @@ SELECT @@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 +ERROR 42000: 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 @@ -51,7 +51,7 @@ a b 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 +ERROR 42000: 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 diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index c1f2adc1e31..ea5f13192f7 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -26,7 +26,7 @@ t1 0 PRIMARY 1 a A 5 NULL NULL BTREE t1 1 b 1 b A 1 NULL NULL BTREE t1 1 b 2 c A 5 NULL NULL BTREE insert into t1 values (5,5,5); -Duplicate entry '5' for key 1 +ERROR 23000: Duplicate entry '5' for key 1 optimize table t1; Table Op Msg_type Msg_text test.t1 optimize status OK diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 8ded3daf114..9b80b965d10 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -71,10 +71,10 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`a`), UNIQUE KEY `email` (`email`) ) TYPE=HEAP ROW_FORMAT=DYNAMIC -set @@sql_mode="postgresql,oracle,mssql,db2,sapdb"; -show variables like 'sql_mode'; -Variable_name Value -sql_mode POSTGRESQL,ORACLE,MSSQL,DB2,SAPDB +set sql_mode="postgresql,oracle,mssql,db2,sapdb"; +select @@sql_mode; +@@sql_mode +PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,SAPDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS show create table t1; Table Create Table t1 CREATE TABLE "t1" ( diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 41620bb6e7f..982b70ff3e6 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -29,14 +29,14 @@ id select_type table type possible_keys key key_len ref rows Extra Warnings: Note 1247 Select 2 was reduced during optimisation SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a; -Reference 'a' not supported (forward reference in item list) +ERROR 42S22: Reference 'a' not supported (forward reference in item list) SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b; -Reference 'b' not supported (forward reference in item list) +ERROR 42S22: Reference 'b' not supported (forward reference in item list) SELECT (SELECT 1),MAX(1) FROM (SELECT 1) as a; (SELECT 1) MAX(1) 1 1 SELECT (SELECT a) as a; -Reference 'a' not supported (forward reference in item list) +ERROR 42S22: Reference 'a' not supported (forward reference in item list) EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 @@ -46,17 +46,17 @@ SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; 1 1 SELECT (SELECT 1), a; -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' SELECT 1 as a FROM (SELECT 1) as b HAVING (SELECT a)=1; a 1 SELECT 1 FROM (SELECT (SELECT a) b) c; -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' SELECT * FROM (SELECT 1 as id) b WHERE id IN (SELECT * FROM (SELECT 1 as id) c ORDER BY id); id 1 SELECT * FROM (SELECT 1) a WHERE 1 IN (SELECT 1,1); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) SELECT 1 IN (SELECT 1); 1 IN (SELECT 1) 1 @@ -64,9 +64,9 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); 1 1 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); -Wrong usage of PROCEDURE and subquery +ERROR HY000: Wrong usage of PROCEDURE and subquery SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -Incorrect parameters to procedure 'ANALYSE' +ERROR HY000: Incorrect parameters to procedure 'ANALYSE' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; a SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL; @@ -121,19 +121,19 @@ SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a'); (SELECT 1.5,'c','a') = ROW(1.5,2,'a') 0 SELECT (SELECT * FROM (SELECT 'test' a,'test' b) a); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) SELECT 1 as a,(SELECT a+a) b,(SELECT b); a b (SELECT b) 1 2 2 create table t1 (a int); create table t2 (a int, b int); create table t3 (a int); -create table t4 (a int, b int); +create table t4 (a int not null, b int not null); insert into t1 values (2); insert into t2 values (1,7),(2,7); insert into t4 values (4,8),(3,8),(5,9); select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1; -Reference 'a1' not supported (forward reference in item list) +ERROR 42S22: Reference 'a1' not supported (forward reference in item list) select (select a from t1 where t1.a=t2.a), a from t2; (select a from t1 where t1.a=t2.a) a NULL 1 @@ -252,15 +252,18 @@ a 7 delete from t2 where a=100; select * from t3 where a in (select a,b from t2); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) select * from t3 where a in (select * from t2); -Cardinality error (more/less than 1 columns) -insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); -select b,max(a) as ma from t4 group by b having b < (select max(t2.a) -from t2 where t2.b=t4.b); +ERROR 21000: Cardinality error (more/less than 1 columns) +insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9),(1,10); +select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b); b ma -select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) -from t2 where t2.b=t4.b); +insert into t2 values (2,10); +select b,max(a) as ma from t4 group by b having ma < (select max(t2.a) from t2 where t2.b=t4.b); +b ma +10 1 +delete from t2 where a=2 and b=10; +select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) from t2 where t2.b=t4.b); b ma 7 12 create table t5 (a int); @@ -284,7 +287,7 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2; -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq)); create table t7( uq int primary key, name char(25)); insert into t7 values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta"); @@ -297,9 +300,9 @@ patient_uq clinic_uq explain select * from t6 where exists (select * from t7 where uq = clinic_uq); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t6 ALL NULL NULL NULL NULL 4 Using where -2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 t6.clinic_uq 1 +2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); -Column: 'a' in field list is ambiguous +ERROR 23000: Column: 'a' in field list is ambiguous drop table if exists t1,t2,t3; CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0'); INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b'); @@ -333,15 +336,15 @@ id select_type table type possible_keys key key_len ref rows Extra 3 SUBQUERY t8 const PRIMARY PRIMARY 35 1 SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM t8 WHERE pseudo='joce'); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) SELECT pseudo FROM t8 WHERE pseudo=(SELECT * FROM t8 WHERE pseudo='joce'); -Cardinality error (more/less than 1 columns) +ERROR 21000: Cardinality error (more/less than 1 columns) SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'); pseudo joce SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo LIKE '%joce%'); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record drop table if exists t1,t2,t3,t4,t5,t6,t7,t8; CREATE TABLE `t1` ( `topic` mediumint(8) unsigned NOT NULL default '0', @@ -371,7 +374,7 @@ SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL SELECT 1; 1 1 SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1; -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL topic 3 NULL 2 Using index @@ -401,9 +404,9 @@ numeropost maxnumrep 43506 2 40143 1 SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b; -Unknown column 'a' in 'having clause' +ERROR 42S22: Unknown column 'a' in 'having clause' SELECT 1 IN (SELECT 1 FROM t2 HAVING a); -Unknown column 'a' in 'having clause' +ERROR 42S22: Unknown column 'a' in 'having clause' SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic); mot topic date pseudo joce 40143 2002-10-22 joce @@ -458,9 +461,9 @@ UNIQUE KEY `maxnumrep` (`maxnumrep`) ) TYPE=MyISAM ROW_FORMAT=FIXED; INSERT INTO t1 (numeropost,maxnumrep) VALUES (1,0),(2,1); select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record drop table t1; create table t1 (a int); insert into t1 values (1),(2),(3); @@ -473,7 +476,7 @@ drop table t1; CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b'); INSERT INTO t1 VALUES (); SELECT field FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1 FROM (SELECT 1) a HAVING field='b'); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record drop table t1; CREATE TABLE `t1` ( `numeropost` mediumint(8) unsigned NOT NULL default '0', @@ -484,14 +487,14 @@ UNIQUE KEY `numreponse` (`numreponse`), KEY `pseudo` (`pseudo`,`numeropost`) ) TYPE=MyISAM; SELECT (SELECT numeropost FROM t1 HAVING numreponse=a),numreponse FROM (SELECT * FROM t1) as a; -Reference 'numreponse' not supported (forward reference in item list) +ERROR 42S22: Reference 'numreponse' not supported (forward reference in item list) SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=a) FROM (SELECT * FROM t1) as a; -Unknown column 'a' in 'having clause' +ERROR 42S22: Unknown column 'a' in 'having clause' SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=1) FROM (SELECT * FROM t1) as a; numreponse (SELECT numeropost FROM t1 HAVING numreponse=1) INSERT INTO t1 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test'); EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1'); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -516,9 +519,9 @@ a b 1 11 2 12 update t1 set b= (select b from t1); -You can't specify target table 't1' for update in FROM clause +ERROR HY000: You can't specify target table 't1' for update in FROM clause update t1 set b= (select b from t2); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record update t1 set b= (select b from t2 where t1.a = t2.a); select * from t1; a b @@ -539,9 +542,9 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a); a b 2 12 delete from t1 where b = (select b from t1); -You can't specify target table 't1' for update in FROM clause +ERROR HY000: You can't specify target table 't1' for update in FROM clause delete from t1 where b = (select b from t2); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record delete from t1 where b = (select b from t2 where t1.a = t2.a); select * from t1; a b @@ -565,9 +568,9 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -You can't specify target table 't12' for update in FROM clause +ERROR HY000: You can't specify target table 't12' for update in FROM clause delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); select * from t11; a b @@ -584,9 +587,9 @@ create table t3 (a int); insert into t2 values (1); insert into t3 values (1),(2); INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); -You can't specify target table 't1' for update in FROM clause +ERROR HY000: You can't specify target table 't1' for update in FROM clause INSERT INTO t1 (x) VALUES ((SELECT a FROM t3)); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); select * from t1; x @@ -605,7 +608,7 @@ x 3 3 INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; -You can't specify target table 't1' for update in FROM clause +ERROR HY000: You can't specify target table 't1' for update in FROM clause INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); select * from t1; x @@ -623,9 +626,9 @@ insert into t3 values (1),(2); select * from t1; x y replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); -You can't specify target table 't1' for update in FROM clause +ERROR HY000: You can't specify target table 't1' for update in FROM clause replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); select * from t1; x y @@ -652,7 +655,7 @@ x y 2 1 drop table t1, t2, t3; SELECT * FROM (SELECT 1) b WHERE 1 IN (SELECT *); -No tables used +ERROR HY000: No tables used CREATE TABLE t2 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1; INSERT INTO t2 VALUES (1),(2); SELECT * FROM t2 WHERE id IN (SELECT 1); @@ -687,9 +690,9 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); id 2 INSERT INTO t2 VALUES ((SELECT * FROM t2)); -You can't specify target table 't2' for update in FROM clause +ERROR HY000: You can't specify target table 't2' for update in FROM clause INSERT INTO t2 VALUES ((SELECT id FROM t2)); -You can't specify target table 't2' for update in FROM clause +ERROR HY000: You can't specify target table 't2' for update in FROM clause SELECT * FROM t2; id 1 @@ -697,7 +700,7 @@ id CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1; INSERT INTO t1 values (1),(1); UPDATE t2 SET id=(SELECT * FROM t1); -Subselect returns more than 1 record +ERROR 21000: Subselect returns more than 1 record drop table t2, t1; create table t1 (a int); insert into t1 values (1),(2),(3); @@ -828,9 +831,9 @@ id select_type table type possible_keys key key_len ref rows Extra drop table t1,t2; create table t1 (a float); select 10.5 IN (SELECT * from t1 LIMIT 1); -This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' +ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5); -This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' +ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' drop table t1; create table t1 (a int, b int, c varchar(10)); create table t2 (a int); @@ -882,7 +885,7 @@ select ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a'); ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a') 1 select ROW(1, 1, 'a') IN (select b,a,c from t1 limit 2); -This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' +ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' drop table t1; create table t1 (a int); insert into t1 values (1); @@ -897,13 +900,13 @@ select @a; 1 drop table t1; do (SELECT a from t1); -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist set @a:=(SELECT a from t1); -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist CREATE TABLE t1 (a int, KEY(a)); HANDLER t1 OPEN; HANDLER t1 READ a=((SELECT 1)); -You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use HANDLER t1 CLOSE; drop table t1; create table t1 (a int); @@ -926,7 +929,7 @@ drop table t1, t2; CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) TYPE=MyISAM CHARSET=latin1; INSERT INTO t1 VALUES (1); UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); -Invalid use of group function +ERROR HY000: Invalid use of group function drop table t1; CREATE TABLE t1 (a int(1)); EXPLAIN SELECT (SELECT RAND() FROM t1) FROM t1; @@ -1033,7 +1036,7 @@ id select_type table type possible_keys key key_len ref rows Extra 3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 drop table t1; select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent); -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist CREATE TABLE t1 ( ID int(11) NOT NULL auto_increment, name char(35) NOT NULL default '', @@ -1098,11 +1101,11 @@ PRIMARY KEY (`i`) ) TYPE=MyISAM CHARSET=latin1; INSERT INTO t1 VALUES (1); UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i)); -Invalid use of group function +ERROR HY000: Invalid use of group function UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); -Invalid use of group function +ERROR HY000: Invalid use of group function UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t); -Unknown table 't' in field list +ERROR 42S02: Unknown table 't' in field list drop table t1; CREATE TABLE t1 ( id int(11) default NULL diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result index 5568e5b25d8..fbc5c234256 100644 --- a/mysql-test/r/temp_table.result +++ b/mysql-test/r/temp_table.result @@ -24,9 +24,9 @@ a b create TEMPORARY TABLE t2 type=heap select * from t1; create TEMPORARY TABLE IF NOT EXISTS t2 (a int) type=heap; CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null); -Table 't1' already exists +ERROR 42S01: Table 't1' already exists ALTER TABLE t1 RENAME t2; -Table 't2' already exists +ERROR 42S01: Table 't2' already exists select * from t2; a b 4 e @@ -74,7 +74,7 @@ drop table t1,t2; create temporary table t1 (a int not null); insert into t1 values (1),(1); alter table t1 add primary key (a); -Duplicate entry '1' for key 1 +ERROR 23000: Duplicate entry '1' for key 1 drop table t1; CREATE TABLE t1 ( d datetime default NULL diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result index ad390c9fa92..0e256c1bf8e 100644 --- a/mysql-test/r/truncate.result +++ b/mysql-test/r/truncate.result @@ -14,7 +14,7 @@ select * from t1; a b c1 drop table t1; select count(*) from t1; -Table 'test.t1' doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist create temporary table t1 (n int); insert into t1 values (1),(2),(3); truncate table t1; @@ -22,4 +22,4 @@ select * from t1; n drop table t1; truncate non_existing_table; -Table 'test.non_existing_table' doesn't exist +ERROR 42S02: Table 'test.non_existing_table' doesn't exist diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index f97e2bc06b5..52d5480d63c 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -27,9 +27,9 @@ t3 CREATE TABLE `t3` ( drop table t1,t2,t3 #; CREATE TABLE t1 (a char(257) default "hello"); -Too big column length for column 'a' (max = 255). Use BLOB instead +ERROR 42000: Too big column length for column 'a' (max = 255). Use BLOB instead CREATE TABLE t2 (a blob default "hello"); -BLOB column 'a' can't have a default value +ERROR 42000: BLOB column 'a' can't have a default value drop table if exists t1,t2; create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr)); insert into t1 values (null,"a","A"); @@ -347,7 +347,7 @@ a 1 hello 1 drop table t1; create table t1 (a text, key (a(300))); -Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys +ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys create table t1 (a text, key (a(255))); drop table t1; CREATE TABLE t1 ( diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index c0e48fb42d8..57df0c67ac9 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -436,8 +436,8 @@ 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 +ERROR 42000: 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 +ERROR 42000: 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 +ERROR 42000: Too big column length for column 'a_dec' (max = 255). Use BLOB instead diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 92cf4f70843..76f82feb50e 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -100,5 +100,5 @@ min(a) -0.010 drop table t1; create table t1 (f float(54)); -Incorrect column specifier for column 'f' +ERROR 42000: Incorrect column specifier for column 'f' drop table if exists t1; diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index c059d5b58a0..34ae1086e2c 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -285,7 +285,7 @@ create table t1 (c int); insert into t1 values(1),(2); create table t2 select * from t1; create table t3 select * from t1, t2; -Duplicate column name 'c' +ERROR 42S21: Duplicate column name 'c' create table t3 select t1.c AS c1, t2.c AS c2,1 as "const" from t1, t2; show full columns from t3; Field Type Collation Null Key Default Extra Privileges Comment diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 272ffdd330e..5b7b26bc1bb 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -85,7 +85,7 @@ a b 2 b 1 a (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; -Table 't1' from one of SELECT's can not be used in global ORDER clause +ERROR 42000: Table 't1' from one of SELECT's can not be used in global ORDER clause explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 @@ -95,7 +95,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 2 UNION t2 ALL NULL NULL NULL NULL 4 explain select xx from t1 union select 1; -Unknown column 'xx' in 'field list' +ERROR 42S22: Unknown column 'xx' in 'field list' explain select a,b from t1 union select 1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 @@ -110,38 +110,38 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE 2 UNION NULL NULL NULL NULL NULL NULL NULL Impossible WHERE select a,b from t1 into outfile 'skr' union select a,b from t2; -Wrong usage of UNION and INTO +ERROR HY000: Wrong usage of UNION and INTO select a,b from t1 order by a union select a,b from t2; -Wrong usage of UNION and ORDER BY +ERROR HY000: Wrong usage of UNION and ORDER BY insert into t3 select a from t1 order by a union select a from t2; -Wrong usage of UNION and ORDER BY +ERROR HY000: Wrong usage of UNION and ORDER BY create table t3 select a,b from t1 union select a from t2; -The used SELECT statements have a different number of columns +ERROR 21000: The used SELECT statements have a different number of columns select a,b from t1 union select a from t2; -The used SELECT statements have a different number of columns +ERROR 21000: The used SELECT statements have a different number of columns select * from t1 union select a from t2; -The used SELECT statements have a different number of columns +ERROR 21000: The used SELECT statements have a different number of columns select a from t1 union select * from t2; -The used SELECT statements have a different number of columns +ERROR 21000: The used SELECT statements have a different number of columns select * from t1 union select SQL_BUFFER_RESULT * from t2; -Wrong usage/placement of 'SQL_BUFFER_RESULT' +ERROR 42000: Wrong usage/placement of 'SQL_BUFFER_RESULT' create table t3 select a,b from t1 union all select a,b from t2; insert into t3 select a,b from t1 union all select a,b from t2; replace into t3 select a,b as c from t1 union all select a,b from t2; drop table t1,t2,t3; select * union select 1; -No tables used +ERROR HY000: No tables used select 1 as a,(select a union select a); a (select a union select a) 1 1 (select 1) union (select 2) order by 0; -Unknown column '0' in 'order clause' +ERROR 42S22: Unknown column '0' in 'order clause' SELECT @a:=1 UNION SELECT @a:=@a+1; @a:=1 1 2 (SELECT 1) UNION (SELECT 2) ORDER BY (SELECT a); -Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' (SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2); 1 3 1 3 diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 1d483da2c77..a0370272396 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -5,11 +5,11 @@ update t1 set a=a+10 where a > 34; update t1 set a=a+100 where a > 0; update t1 set a=a+100 where a=1 and a=2; update t1 set a=b+100 where a=1 and a=2; -Unknown column 'b' in 'field list' +ERROR 42S22: Unknown column 'b' in 'field list' update t1 set a=b+100 where c=1 and a=2; -Unknown column 'c' in 'where clause' +ERROR 42S22: Unknown column 'c' in 'where clause' update t1 set d=a+100 where a=1; -Unknown column 'd' in 'field list' +ERROR 42S22: Unknown column 'd' in 'field list' select * from t1; a 101 diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 6e3b9309351..3a53dbdded0 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -1,6 +1,6 @@ drop table if exists t1,t2; set @a := foo; -Unknown column 'foo' in 'field list' +ERROR 42S22: Unknown column 'foo' in 'field list' set @a := connection_id() + 3; select @a - connection_id(); @a - connection_id() diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result index 2d04da31caa..5464d741f70 100644 --- a/mysql-test/r/varbinary.result +++ b/mysql-test/r/varbinary.result @@ -16,9 +16,9 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 const UNIQ UNIQ 8 const 1 drop table t1; select x'hello'; -You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1 +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1 select 0xfg; -Unknown column '0xfg' in 'field list' +ERROR 42S22: Unknown column '0xfg' in 'field list' create table t1 select 1 as x, 2 as xx; select x,xx from t1; x xx diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index b5e05cf6953..1a773acd23e 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -164,42 +164,42 @@ select ROUND(RAND(),5); ROUND(RAND(),5) 0.02887 set big_tables=OFFF; -Variable 'big_tables' can't be set to the value of 'OFFF' +ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF' set big_tables="OFFF"; -Variable 'big_tables' can't be set to the value of 'OFFF' +ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF' set unknown_variable=1; -Unknown system variable 'unknown_variable' +ERROR HY000: Unknown system variable 'unknown_variable' set max_join_size="hello"; -Wrong argument type to variable 'max_join_size' +ERROR 42000: Wrong argument type to variable 'max_join_size' set table_type=UNKNOWN_TABLE_TYPE; -Variable 'table_type' can't be set to the value of 'UNKNOWN_TABLE_TYPE' +ERROR 42000: Variable 'table_type' can't be set to the value of 'UNKNOWN_TABLE_TYPE' set table_type=INNODB, big_tables=2; -Variable 'big_tables' can't be set to the value of '2' +ERROR 42000: Variable 'big_tables' can't be set to the value of '2' show local variables like 'table_type'; Variable_name Value table_type HEAP set SESSION query_cache_size=10000; -Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL +ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL set GLOBAL table_type=DEFAULT; -Variable 'table_type' doesn't have a default value +ERROR 42000: Variable 'table_type' doesn't have a default value set character_set_client=UNKNOWN_CHARACTER_SET; -Unknown character set: 'UNKNOWN_CHARACTER_SET' +ERROR 42000: Unknown character set: 'UNKNOWN_CHARACTER_SET' set global autocommit=1; -Variable 'autocommit' is a LOCAL variable and can't be used with SET GLOBAL +ERROR HY000: Variable 'autocommit' is a LOCAL variable and can't be used with SET GLOBAL select @@global.timestamp; -Variable 'timestamp' is a LOCAL variable and can't be used with SET GLOBAL +ERROR HY000: Variable 'timestamp' is a LOCAL variable and can't be used with SET GLOBAL set @@version=''; -Unknown system variable 'version' +ERROR HY000: Unknown system variable 'version' set @@concurrent_insert=1; -Variable 'concurrent_insert' is a GLOBAL variable and should be set with SET GLOBAL +ERROR HY000: Variable 'concurrent_insert' is a GLOBAL variable and should be set with SET GLOBAL set @@global.sql_auto_is_null=1; -Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL +ERROR HY000: 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 +ERROR HY000: 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 +ERROR HY000: 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 +ERROR HY000: 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; @@ -325,7 +325,7 @@ test.t2 check status OK select max(a) +1, max(a) +2 into @xx,@yy from t1; drop table t1,t2; select @@xxxxxxxxxx; -Unknown system variable 'xxxxxxxxxx' +ERROR HY000: Unknown system variable 'xxxxxxxxxx' select 1; 1 1 diff --git a/mysql-test/t/ansi.test b/mysql-test/t/ansi.test index da82b7a9e31..f4aef5c3f8e 100644 --- a/mysql-test/t/ansi.test +++ b/mysql-test/t/ansi.test @@ -17,3 +17,8 @@ SELECT id,NULL,1,1.1,'a' FROM t1 GROUP BY id; --error 1055 SELECT id FROM t1 GROUP BY id2; drop table t1; + +set sql_mode="MySQL40"; +select @@sql_mode; +set sql_mode="ANSI"; +select @@sql_mode; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 2ce90c93bd9..4f0af1edbaa 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -65,3 +65,12 @@ SELECT 1 as a FROM (SELECT a UNION SELECT 1) b; SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b; --error 1054 select 1 from (select 2) a order by 0; + +# +# Test of explain (bug #251) +# + +create table t1 (id int); +insert into t1 values (1),(2),(3); +describe select * from (select * from t1 group by id) bar; +drop table t1; diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test index 41b776719dc..998b2a5c3f4 100644 --- a/mysql-test/t/func_system.test +++ b/mysql-test/t/func_system.test @@ -18,7 +18,7 @@ select version()>=_utf8"3.23.29"; select version()>=_latin1"3.23.29"; select charset(version()); -create table t1 select database(), user(), version(); +create table t1 (version char(40)) select database(), user(), version() as 'version'; show create table t1; drop table t1; diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test index f3a747c4d61..348116b02f2 100644 --- a/mysql-test/t/lowercase_table.test +++ b/mysql-test/t/lowercase_table.test @@ -14,4 +14,3 @@ ALTER TABLE T2 ADD new_col int not null; ALTER TABLE T2 RENAME T3; show tables like 't_'; drop table t3; - diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index 99bb2656001..3b1e3fac7c2 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -1,31 +1,79 @@ --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; --enable_warnings -create table t1 ( product varchar(32), country varchar(32), year int, profit int); -insert into t1 values ( 'Computer', 'India',2000, 1200), -( 'TV', 'United States', 1999, 150), -( 'Calculator', 'United States', 1999,50), -( 'Computer', 'United States', 1999,1500), -( 'Computer', 'United States', 2000,1500), -( 'TV', 'United States', 2000, 150), -( 'TV', 'India', 2000, 100), -( 'TV', 'India', 2000, 100), -( 'Calculator', 'United States', 2000,75), -( 'Calculator', 'India', 2000,75), -( 'TV', 'India', 1999, 100), -( 'Computer', 'India', 1999,1200), -( 'Computer', 'United States', 2000,1500), -( 'Calculator', 'United States', 2000,75); ---error 1235 -select product, country , year, sum(profit) from t1 group by product, country, year with cube; ---error 1235 -explain select product, country , year, sum(profit) from t1 group by product, country, year with cube; ---error 1235 -select product, country , year, sum(profit) from t1 group by product, country, year with rollup; ---error 1235 -explain select product, country , year, sum(profit) from t1 group by product, country, year with rollup; ---error 1235 -select product, country , year, sum(profit) from t1 group by product, country, year with cube union all select product, country , year, sum(profit) from t1 group by product, country, year with rollup; -drop table t1; +create table t1 (product varchar(32), country_id int not null, year int, profit int); +insert into t1 values ( 'Computer', 2,2000, 1200), +( 'TV', 1, 1999, 150), +( 'Calculator', 1, 1999,50), +( 'Computer', 1, 1999,1500), +( 'Computer', 1, 2000,1500), +( 'TV', 1, 2000, 150), +( 'TV', 2, 2000, 100), +( 'TV', 2, 2000, 100), +( 'Calculator', 1, 2000,75), +( 'Calculator', 2, 2000,75), +( 'TV', 1, 1999, 100), +( 'Computer', 1, 1999,1200), +( 'Computer', 2, 2000,1500), +( 'Calculator', 2, 2000,75), +( 'Phone', 3, 2003,10) +; + +create table t2 (country_id int primary key, country char(20) not null); +insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland'); + +# First simple rollups, with just grand total +select product, sum(profit) from t1 group by product; +select product, sum(profit) from t1 group by product with rollup; +select product, sum(profit) from t1 group by 1 with rollup; +select product, sum(profit),avg(profit) from t1 group by product with rollup; + +# Sub totals +select product, country_id , year, sum(profit) from t1 group by product, country_id, year; +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup; +explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup; +select product, country_id , sum(profit) from t1 group by product desc, country_id with rollup; + +# limit +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 5; +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 3,3; + +select product, country_id, count(*), count(distinct year) from t1 group by product, country_id; +select product, country_id, count(*), count(distinct year) from t1 group by product, country_id with rollup; + +# Test of having +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having country_id = 1; +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 200; +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 7000; + +# Functions +select concat(product,':',country_id) as 'prod', concat(":",year,":") as 'year',1+1, sum(profit)/count(*) from t1 group by 1,2 with rollup; +select product, sum(profit)/count(*) from t1 group by product with rollup; +select left(product,4) as prod, sum(profit)/count(*) from t1 group by prod with rollup; +select concat(product,':',country_id), 1+1, sum(profit)/count(*) from t1 group by concat(product,':',country_id) with rollup; + +# Joins +select product, country , year, sum(profit) from t1,t2 where t1.country_id=t2.country_id group by product, country, year with rollup; + +# Derived tables and sub selects +select product, `sum` from (select product, sum(profit) as 'sum' from t1 group by product with rollup) as tmp where product is null; +select product from t1 where exists (select product, country_id , sum(profit) from t1 as t2 where t1.product=t2.product group by product, country_id with rollup having sum(profit) > 6000); + +# The following doesn't return the expected answer, but this is a limitation +# in the implementation so we should just document it +select product, country_id , year, sum(profit) from t1 group by product, country_id, year having country_id is NULL; +select concat(':',product,':'), sum(profit),avg(profit) from t1 group by product with rollup; + +# Error handling + +# Cube is not yet implemented +--error 1235 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube; +--error 1235 +explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube; +--error 1235 +select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube union all select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup; + +drop table t1,t2; diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index fd464f74de4..d3531f0c440 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -24,7 +24,7 @@ show create table t1; set @@sql_mode="no_field_options,mysql323,mysql40"; show variables like 'sql_mode'; show create table t1; -set @@sql_mode="postgresql,oracle,mssql,db2,sapdb"; -show variables like 'sql_mode'; +set sql_mode="postgresql,oracle,mssql,db2,sapdb"; +select @@sql_mode; show create table t1; drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 8377a756c5b..c116d03e274 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -59,7 +59,7 @@ SELECT 1 as a,(SELECT a+a) b,(SELECT b); create table t1 (a int); create table t2 (a int, b int); create table t3 (a int); -create table t4 (a int, b int); +create table t4 (a int not null, b int not null); insert into t1 values (2); insert into t2 values (1,7),(2,7); insert into t4 values (4,8),(3,8),(5,9); @@ -106,11 +106,13 @@ delete from t2 where a=100; select * from t3 where a in (select a,b from t2); -- error 1239 select * from t3 where a in (select * from t2); -insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); -select b,max(a) as ma from t4 group by b having b < (select max(t2.a) -from t2 where t2.b=t4.b); -select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) -from t2 where t2.b=t4.b); +insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9),(1,10); +-- empty set +select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b); +insert into t2 values (2,10); +select b,max(a) as ma from t4 group by b having ma < (select max(t2.a) from t2 where t2.b=t4.b); +delete from t2 where a=2 and b=10; +select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) from t2 where t2.b=t4.b); create table t5 (a int); select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2; insert into t5 values (5); diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 88f561e0e6d..7d256a70b10 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -60,7 +60,7 @@ EXTRA_DIST = $(EXTRA_SCRIPTS) \ mysqlaccess.conf \ mysqlbug -pkgdata_DATA = fill_help_tables.sql +pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql # mysqlbug should be distributed built so that people can report build # failures with it. diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 05d6f3ffb71..5d392f719f0 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -1,212 +1,166 @@ #!/bin/sh +# This script is a wrapper to pipe the mysql_fix_privilege_tables.sql +# through the mysql client program to the mysqld server -root_password="$1" +# Default values (Can be changed in my.cnf) +password="" host="localhost" user="root" +sql_only=0 +basedir="" +verbose=0 +args="" -if test -z $1 ; then - cmd="@bindir@/mysql -f --user=$user --host=$host mysql" +file=mysql_fix_privilege_tables.sql + +# The following code is almost identical to the code in mysql_install_db.sh + +parse_arguments() { + # We only need to pass arguments through to the server if we don't + # handle them here. So, we collect unrecognized options (passed on + # the command line) into the args variable. + pick_args= + if test "$1" = PICK-ARGS-FROM-ARGV + then + pick_args=1 + shift + fi + + for arg do + case "$arg" in + --basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; + --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; + --password=*) password=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; + --host=*) host=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; + --sql|--sql-only) sql_only=1;; + --verbose) verbose=1 ;; + *) + if test -n "$pick_args" + then + # This sed command makes sure that any special chars are quoted, + # so the arg gets passed exactly to the server. + args="$args "`echo "$arg" | sed -e 's,\([^a-zA-Z0-9_.-]\),\\\\\1,g'` + fi + ;; + esac + done +} + +# Get first arguments from the my.cfg file, groups [mysqld] and +# [mysql_install_db], and then merge with the command line arguments +if test -x ./bin/my_print_defaults +then + print_defaults="./bin/my_print_defaults" +elif test -x @bindr@/my_print_defaults +then + print_defaults="@bindir@/my_print_defaults" +elif test -x @bindir@/mysql_print_defaults +then + print_defaults="@bindir@/mysql_print_defaults" else - root_password="$1" - cmd="@bindir@/mysql -f --user=$user --password=$root_password --host=$host mysql" + print_defaults="my_print_defaults" fi -# Debian addition -if [ "$1" = "--sql-only" ]; then - root_password="" - cmd="/usr/share/mysql/echo_stderr" -fi +parse_arguments `$print_defaults $defaults mysql_install_db mysql_fix_privilege_tables` +parse_arguments PICK-ARGS-FROM-ARGV "$@" -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 < Grant -# and Create -> Alter, Index, References - -if test $res = 0 +if test -z "$basedir" then - echo "Setting default privileges for the new grant, index and alter privileges" - $cmd < Column_priv from MySQL 3.22.12 -# - -echo "Changing name of columns_priv.Type -> columns_priv.Column_priv" -echo "You can ignore any Unknown column errors from this" - -$cmd <""; -END_OF_DATA - echo "" + password=`echo $args | sed -e 's/ *//g'` fi -# Add fields that can be used to limit number of questions and connections -# for some users. +if test -z $password ; then + cmd="$bindir/mysql -f --user=$user --host=$host mysql" +else + cmd="$bindir/mysql -f --user=$user --password=$password --host=$host mysql" +fi +if test $sql_only = 1 +then + cmd="cat" +fi -$cmd < /dev/null 2>&1 +else + cat $sql_file | $cmd > /dev/null +fi +if test $? = 0 +then + s_echo "done" +else + s_echo "Got a failure from command:" + s_echo "$cmd" + s_echo "Please check the above output and try again." + if test $verbose = 0 + then + s_echo "" + s_echo "Running the script with the --verbose option may give you some information" + s_echo "of what went wrong." + fi + s_echo "" + s_echo "If you get an 'Access denied' error, you should run this script again and" + s_echo "give the MySQL root user password as an argument with the --password= option" +fi diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql new file mode 100644 index 00000000000..3466e3cf799 --- /dev/null +++ b/scripts/mysql_fix_privilege_tables.sql @@ -0,0 +1,89 @@ +ALTER TABLE user type=MyISAM; +ALTER TABLE db type=MyISAM; +ALTER TABLE host type=MyISAM; +ALTER TABLE func type=MyISAM; +ALTER TABLE columns_priv type=MyISAM; +ALTER TABLE tables_priv type=MyISAM; +ALTER TABLE user change password password char(45) not null; +ALTER TABLE user add File_priv enum('N','Y') NOT NULL; +CREATE TABLE IF NOT EXISTS func ( + name char(64) DEFAULT '' NOT NULL, + ret tinyint(1) DEFAULT '0' NOT NULL, + dl char(128) DEFAULT '' NOT NULL, + type enum ('function','aggregate') NOT NULL, + PRIMARY KEY (name) +); + +-- Detect whether or not we had the Grant_priv column +SET @hadGrantPriv:=0; +SELECT @hadGrantPriv:=1 FROM user WHERE Grant_priv LIKE '%'; + +ALTER TABLE user add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL; +ALTER TABLE host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL; +ALTER TABLE db add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL; + +--- Fix privileges for old tables +UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; +UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; +UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; + +ALTER TABLE user +ADD ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL, +ADD ssl_cipher BLOB NOT NULL, +ADD x509_issuer BLOB NOT NULL, +ADD x509_subject BLOB NOT NULL; +ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL; + +CREATE TABLE IF NOT EXISTS tables_priv ( + Host char(60) DEFAULT '' NOT NULL, + Db char(60) DEFAULT '' NOT NULL, + User char(16) DEFAULT '' NOT NULL, + Table_name char(60) DEFAULT '' NOT NULL, + Grantor char(77) DEFAULT '' NOT NULL, + Timestamp timestamp(14), + Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL, + Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, + PRIMARY KEY (Host,Db,User,Table_name) +); + +CREATE TABLE IF NOT EXISTS columns_priv ( + Host char(60) DEFAULT '' NOT NULL, + Db char(60) DEFAULT '' NOT NULL, + User char(16) DEFAULT '' NOT NULL, + Table_name char(60) DEFAULT '' NOT NULL, + Column_name char(59) DEFAULT '' NOT NULL, + Timestamp timestamp(14), + Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, + PRIMARY KEY (Host,Db,User,Table_name,Column_name) +); + +ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL; + +ALTER TABLE func add type enum ('function','aggregate') NOT NULL; + +# Detect whether we had Show_db_priv +SET @hadShowDbPriv:=0; +SELECT @hadShowDbPriv:=1 FROM user WHERE Show_db_priv LIKE '%'; + +ALTER TABLE user +ADD Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER alter_priv, +ADD Super_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Show_db_priv, +ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Super_priv, +ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_tmp_table_priv, +ADD Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv, +ADD Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv, +ADD Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv; + +UPDATE user SET show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"" AND @hadShowDbPriv = 0; + +ALTER TABLE user +ADD max_questions int(11) NOT NULL AFTER x509_subject, +ADD max_updates int(11) unsigned NOT NULL AFTER max_questions, +ADD max_connections int(11) unsigned NOT NULL AFTER max_updates; + +ALTER TABLE db +ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, +ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; +ALTER TABLE host +ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, +ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; diff --git a/sql/Makefile.am b/sql/Makefile.am index 608b959a8b9..1d8e8cde2db 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -64,7 +64,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ thr_malloc.cc item_create.cc item_subselect.cc \ item_row.cc \ field.cc key.cc sql_class.cc sql_list.cc \ - net_serv.cc protocol.cc lock.cc my_lock.c \ + net_serv.cc protocol.cc sql_state.c \ + lock.cc my_lock.c \ sql_string.cc sql_manager.cc sql_map.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \ set_var.cc sql_parse.cc sql_yacc.yy \ diff --git a/sql/item.cc b/sql/item.cc index 636cefb511b..bdf180b4828 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -117,7 +117,9 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) /* - This function is only called when comparing items in the WHERE clause + This function is called when: + - Comparing items in the WHERE clause (when doing where optimization) + - When trying to find an ORDER BY/GROUP BY item in the SELECT part */ bool Item::eq(const Item *item, bool binary_cmp) const @@ -243,6 +245,7 @@ void Item_field::set_field(Field *field_par) decimals= field->decimals(); table_name=field_par->table_name; field_name=field_par->field_name; + db_name=field_par->table->table_cache_key; unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); set_charset(field_par->charset(), COER_IMPLICIT); } @@ -344,9 +347,34 @@ longlong Item_field::val_int_result() return result_field->val_int(); } + bool Item_field::eq(const Item *item, bool binary_cmp) const { - return item->type() == FIELD_ITEM && ((Item_field*) item)->field == field; + if (item->type() != FIELD_ITEM) + return 0; + + Item_field *item_field= (Item_field*) item; + if (item_field->field) + return item_field->field == field; + /* + We may come here when we are trying to find a function in a GROUP BY + clause from the select list. + In this case the '100 % correct' way to do this would be to first + run fix_fields() on the GROUP BY item and then retry this function, but + I think it's better to relax the checking a bit as we will in + most cases do the correct thing by just checking the field name. + (In cases where we would choose wrong we would have to generate a + ER_NON_UNIQ_ERROR). + */ + return (!my_strcasecmp(system_charset_info, item_field->name, + field_name) && + (!item_field->table_name || + (!my_strcasecmp(table_alias_charset, item_field->table_name, + table_name) && + (!item_field->db_name || + (item_field->db_name && !my_strcasecmp(table_alias_charset, + item_field->db_name, + db_name)))))); } table_map Item_field::used_tables() const @@ -837,7 +865,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return rf->fix_fields(thd, tables, ref) || rf->check_cols(1); } } - } + } else if (!tmp) return -1; diff --git a/sql/item.h b/sql/item.h index 470937f8ee7..934ea83d218 100644 --- a/sql/item.h +++ b/sql/item.h @@ -29,6 +29,8 @@ class Item { void operator=(Item &); public: static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size, MEM_ROOT *mem_root) + { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr,size_t size) {} /*lint -e715 */ enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM, diff --git a/sql/item_sum.cc b/sql/item_sum.cc index fa8bf7e6e0f..a57291702bc 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -217,11 +217,19 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ** reset and add of sum_func ***********************************************************************/ -void Item_sum_sum::reset() +Item *Item_sum_sum::copy_or_same(THD* thd) { - null_value=1; sum=0.0; Item_sum_sum::add(); + return new (&thd->mem_root) Item_sum_sum(thd, *this); } + +bool Item_sum_sum::reset() +{ + null_value=1; sum=0.0; + return Item_sum_sum::add(); +} + + bool Item_sum_sum::add() { sum+=args[0]->val(); @@ -230,17 +238,26 @@ bool Item_sum_sum::add() return 0; } + double Item_sum_sum::val() { return sum; } -void Item_sum_count::reset() +Item *Item_sum_count::copy_or_same(THD* thd) { - count=0; add(); + return new (&thd->mem_root) Item_sum_count(thd, *this); } + +bool Item_sum_count::reset() +{ + count=0; + return add(); +} + + bool Item_sum_count::add() { if (!args[0]->maybe_null) @@ -260,14 +277,22 @@ longlong Item_sum_count::val_int() } /* -** Avgerage + Avgerage */ -void Item_sum_avg::reset() +Item *Item_sum_avg::copy_or_same(THD* thd) { - sum=0.0; count=0; Item_sum_avg::add(); + return new (&thd->mem_root) Item_sum_avg(thd, *this); } + +bool Item_sum_avg::reset() +{ + sum=0.0; count=0; + return Item_sum_avg::add(); +} + + bool Item_sum_avg::add() { double nr=args[0]->val(); @@ -292,7 +317,7 @@ double Item_sum_avg::val() /* -** Standard deviation + Standard deviation */ double Item_sum_std::val() @@ -301,15 +326,27 @@ double Item_sum_std::val() return tmp <= 0.0 ? 0.0 : sqrt(tmp); } +Item *Item_sum_std::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_std(thd, *this); +} + + /* -** variance + Variance */ -void Item_sum_variance::reset() +Item *Item_sum_variance::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_variance(thd, *this); +} + + +bool Item_sum_variance::reset() { sum=sum_sqr=0.0; count=0; - (void) Item_sum_variance::add(); + return Item_sum_variance::add(); } bool Item_sum_variance::add() @@ -440,6 +477,13 @@ Item_sum_hybrid::val_str(String *str) return str; // Keep compiler happy } + +Item *Item_sum_min::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_min(thd, *this); +} + + bool Item_sum_min::add() { switch (hybrid_type) { @@ -487,6 +531,12 @@ bool Item_sum_min::add() } +Item *Item_sum_max::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_max(thd, *this); +} + + bool Item_sum_max::add() { switch (hybrid_type) { @@ -541,11 +591,19 @@ longlong Item_sum_bit::val_int() return (longlong) bits; } -void Item_sum_bit::reset() + +bool Item_sum_bit::reset() { - bits=reset_bits; add(); + bits=reset_bits; + return add(); } +Item *Item_sum_or::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_or(thd, *this); +} + + bool Item_sum_or::add() { ulonglong value= (ulonglong) args[0]->val_int(); @@ -554,6 +612,12 @@ bool Item_sum_or::add() return 0; } +Item *Item_sum_and::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_and(thd, *this); +} + + bool Item_sum_and::add() { ulonglong value= (ulonglong) args[0]->val_int(); @@ -1032,12 +1096,21 @@ Item_sum_count_distinct::~Item_sum_count_distinct() bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (Item_sum_num::fix_fields(thd, tables, ref) || - !(tmp_table_param= new TMP_TABLE_PARAM)) + if (Item_sum_num::fix_fields(thd, tables, ref)) return 1; return 0; } +/* This is used by rollup to create a separate usable copy of the function */ + +void Item_sum_count_distinct::make_unique() +{ + table=0; + original= 0; + tree= &tree_base; +} + + bool Item_sum_count_distinct::setup(THD *thd) { List list; @@ -1045,6 +1118,9 @@ bool Item_sum_count_distinct::setup(THD *thd) if (select_lex->linkage == GLOBAL_OPTIONS_TYPE) return 1; + if (!(tmp_table_param= new TMP_TABLE_PARAM)) + return 1; + /* Create a table with an unique key over all parameters */ for (uint i=0; i < arg_count ; i++) { @@ -1192,7 +1268,14 @@ int Item_sum_count_distinct::tree_to_myisam() return 0; } -void Item_sum_count_distinct::reset() + +Item *Item_sum_count_distinct::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_count_distinct(thd, *this); +} + + +bool Item_sum_count_distinct::reset() { if (use_tree) reset_tree(tree); @@ -1202,7 +1285,7 @@ void Item_sum_count_distinct::reset() table->file->delete_all_rows(); table->file->extra(HA_EXTRA_WRITE_CACHE); } - (void) add(); + return add(); } bool Item_sum_count_distinct::add() @@ -1265,11 +1348,11 @@ longlong Item_sum_count_distinct::val_int() #ifdef HAVE_DLOPEN -void Item_udf_sum::reset() +bool Item_udf_sum::reset() { DBUG_ENTER("Item_udf_sum::reset"); udf.reset(&null_value); - DBUG_VOID_RETURN; + DBUG_RETURN(0); } bool Item_udf_sum::add() @@ -1279,6 +1362,11 @@ bool Item_udf_sum::add() DBUG_RETURN(0); } +Item *Item_sum_udf_float::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_udf_float(thd, *this); +} + double Item_sum_udf_float::val() { DBUG_ENTER("Item_sum_udf_float::val"); @@ -1298,6 +1386,12 @@ String *Item_sum_udf_float::val_str(String *str) } +Item *Item_sum_udf_int::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_udf_int(thd, *this); +} + + longlong Item_sum_udf_int::val_int() { DBUG_ENTER("Item_sum_udf_int::val_int"); @@ -1306,6 +1400,7 @@ longlong Item_sum_udf_int::val_int() DBUG_RETURN(udf.val_int(&null_value)); } + String *Item_sum_udf_int::val_str(String *str) { longlong nr=val_int(); @@ -1327,6 +1422,13 @@ void Item_sum_udf_str::fix_length_and_dec() DBUG_VOID_RETURN; } + +Item *Item_sum_udf_str::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_sum_udf_str(thd, *this); +} + + String *Item_sum_udf_str::val_str(String *str) { DBUG_ENTER("Item_sum_udf_str::str"); @@ -1568,7 +1670,13 @@ Item_func_group_concat::~Item_func_group_concat() } -void Item_func_group_concat::reset() +Item *Item_func_group_concat::copy_or_same(THD* thd) +{ + return new (&thd->mem_root) Item_func_group_concat(thd, *this); +} + + +bool Item_func_group_concat::reset() { result.length(0); result.copy(); @@ -1582,7 +1690,7 @@ void Item_func_group_concat::reset() } if (tree_mode) reset_tree(tree); - add(); + return add(); } @@ -1768,6 +1876,16 @@ bool Item_func_group_concat::setup(THD *thd) return 0; } +/* This is used by rollup to create a separate usable copy of the function */ + +void Item_func_group_concat::make_unique() +{ + table=0; + original= 0; + tree= &tree_base; +} + + String* Item_func_group_concat::val_str(String* str) { if (null_value) diff --git a/sql/item_sum.h b/sql/item_sum.h index f996f980fff..c8614dda679 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -26,9 +26,11 @@ class Item_sum :public Item_result_field { public: - enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC, - MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC, - UDF_SUM_FUNC, GROUP_CONCAT_FUNC }; + enum Sumfunctype + { COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC, + MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC, + UDF_SUM_FUNC, GROUP_CONCAT_FUNC + }; Item **args,*tmp_args[2]; uint arg_count; @@ -60,7 +62,7 @@ public: enum Type type() const { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; - virtual void reset()=0; + virtual bool reset()=0; virtual bool add()=0; virtual void reset_field()=0; virtual void update_field(int offset)=0; @@ -78,6 +80,7 @@ public: void fix_num_length_and_dec(); void no_rows_in_result() { reset(); } virtual bool setup(THD *thd) {return 0;} + virtual void make_unique() {} Item *get_tmp_table_item(THD *thd); }; @@ -121,14 +124,14 @@ class Item_sum_sum :public Item_sum_num Item_sum_sum(THD *thd, Item_sum_sum &item) :Item_sum_num(thd, item), sum(item.sum) {} enum Sumfunctype sum_func () const {return SUM_FUNC;} - void reset(); + bool reset(); bool add(); double val(); void reset_field(); void update_field(int offset); void no_rows_in_result() {} const char *func_name() const { return "sum"; } - Item *copy_or_same(THD* thd) { return new Item_sum_sum(thd, *this); } + Item *copy_or_same(THD* thd); }; @@ -148,7 +151,7 @@ class Item_sum_count :public Item_sum_int table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_FUNC; } - void reset(); + bool reset(); void no_rows_in_result() { count=0; } bool add(); void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; } @@ -156,7 +159,7 @@ class Item_sum_count :public Item_sum_int void reset_field(); void update_field(int offset); const char *func_name() const { return "count"; } - Item *copy_or_same(THD* thd) { return new Item_sum_count(thd, *this); } + Item *copy_or_same(THD* thd); }; @@ -222,17 +225,15 @@ class Item_sum_count_distinct :public Item_sum_int table_map used_tables() const { return used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; } - void reset(); + bool reset(); bool add(); longlong val_int(); void reset_field() { return ;} // Never called void update_field(int offset) { return ; } // Never called const char *func_name() const { return "count_distinct"; } bool setup(THD *thd); - Item *copy_or_same(THD* thd) - { - return new Item_sum_count_distinct(thd, *this); - } + void make_unique(); + Item *copy_or_same(THD* thd); void no_rows_in_result() {} }; @@ -268,7 +269,7 @@ class Item_sum_avg :public Item_sum_num Item_sum_avg(THD *thd, Item_sum_avg &item) :Item_sum_num(thd, item), sum(item.sum), count(item.count) {} enum Sumfunctype sum_func () const {return AVG_FUNC;} - void reset(); + bool reset(); bool add(); double val(); void reset_field(); @@ -276,7 +277,7 @@ class Item_sum_avg :public Item_sum_num Item *result_item(Field *field) { return new Item_avg_field(this); } const char *func_name() const { return "avg"; } - Item *copy_or_same(THD* thd) { return new Item_sum_avg(thd, *this); } + Item *copy_or_same(THD* thd); }; class Item_sum_variance; @@ -321,7 +322,7 @@ class Item_sum_variance : public Item_sum_num Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr), count(item.count) {} enum Sumfunctype sum_func () const { return VARIANCE_FUNC; } - void reset(); + bool reset(); bool add(); double val(); void reset_field(); @@ -329,7 +330,7 @@ class Item_sum_variance : public Item_sum_num Item *result_item(Field *field) { return new Item_variance_field(this); } const char *func_name() const { return "variance"; } - Item *copy_or_same(THD* thd) { return new Item_sum_variance(thd, *this); } + Item *copy_or_same(THD* thd); }; class Item_sum_std; @@ -349,12 +350,16 @@ public: class Item_sum_std :public Item_sum_variance { public: - Item_sum_std(Item *item_par) :Item_sum_variance(item_par){} + Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {} + Item_sum_std(THD *thd, Item_sum_std &item) + :Item_sum_variance(thd, item) + {} enum Sumfunctype sum_func () const { return STD_FUNC; } double val(); Item *result_item(Field *field) { return new Item_std_field(this); } const char *func_name() const { return "std"; } + Item *copy_or_same(THD* thd); }; // This class is a string or number function depending on num_func @@ -386,13 +391,13 @@ class Item_sum_hybrid :public Item_sum table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } - void reset() + bool reset() { sum=0.0; sum_int=0; value.length(0); null_value=1; - add(); + return add(); } double val(); longlong val_int(); @@ -418,7 +423,7 @@ public: bool add(); const char *func_name() const { return "min"; } - Item *copy_or_same(THD* thd) { return new Item_sum_min(thd, *this); } + Item *copy_or_same(THD* thd); }; @@ -431,7 +436,7 @@ public: bool add(); const char *func_name() const { return "max"; } - Item *copy_or_same(THD* thd) { return new Item_sum_max(thd, *this); } + Item *copy_or_same(THD* thd); }; @@ -446,7 +451,7 @@ class Item_sum_bit :public Item_sum_int Item_sum_bit(THD *thd, Item_sum_bit &item): Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {} enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} - void reset(); + bool reset(); longlong val_int(); void reset_field(); void fix_length_and_dec() @@ -462,7 +467,7 @@ class Item_sum_or :public Item_sum_bit bool add(); void update_field(int offset); const char *func_name() const { return "bit_or"; } - Item *copy_or_same(THD* thd) { return new Item_sum_or(thd, *this); } + Item *copy_or_same(THD* thd); }; @@ -474,7 +479,7 @@ class Item_sum_and :public Item_sum_bit bool add(); void update_field(int offset); const char *func_name() const { return "bit_and"; } - Item *copy_or_same(THD* thd) { return new Item_sum_and(thd, *this); } + Item *copy_or_same(THD* thd); }; /* @@ -504,7 +509,7 @@ public: enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } virtual bool have_field_update(void) const { return 0; } - void reset(); + bool reset(); bool add(); void reset_field() {}; void update_field(int offset_arg) {}; @@ -524,7 +529,7 @@ class Item_sum_udf_float :public Item_udf_sum double val(); String *val_str(String*str); void fix_length_and_dec() { fix_num_length_and_dec(); } - Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); } + Item *copy_or_same(THD* thd); }; @@ -542,7 +547,7 @@ public: String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } void fix_length_and_dec() { decimals=0; max_length=21; } - Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); } + Item *copy_or_same(THD* thd); }; @@ -571,7 +576,7 @@ public: } enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec(); - Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); } + Item *copy_or_same(THD* thd); }; #else /* Dummy functions to get sql_yacc.cc compiled */ @@ -586,10 +591,9 @@ class Item_sum_udf_float :public Item_sum_num ~Item_sum_udf_float() {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } double val() { return 0.0; } - void reset() {} + bool reset() { return 0; } bool add() { return 0; } void update_field(int offset) {} - Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); } }; @@ -604,10 +608,9 @@ public: enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } longlong val_int() { return 0; } double val() { return 0; } - void reset() {} + bool reset() { return 0; } bool add() { return 0; } void update_field(int offset) {} - Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); } }; @@ -625,10 +628,9 @@ public: enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec() { maybe_null=1; max_length=0; } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } - void reset() {} + bool reset() { return 0; } bool add() { return 0; } void update_field(int offset) {} - Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); } }; #endif /* HAVE_DLOPEN */ @@ -676,7 +678,7 @@ class Item_func_group_concat : public Item_sum warning(item.warning), warning_available(item.warning_available), separator(item.separator), - tree(item.tree), + tree(item.tree), table(item.table), expr(item.expr), order(item.order), @@ -700,11 +702,12 @@ class Item_func_group_concat : public Item_sum enum Type type() const { return SUM_FUNC_ITEM; } void fix_length_and_dec() { max_length=group_concat_max_len; } virtual Item_result result_type () const { return STRING_RESULT; } - void reset(); + bool reset(); bool add(); void reset_field(); bool fix_fields(THD *, TABLE_LIST *, Item **); bool setup(THD *thd); + void make_unique(); virtual void update_field(int offset) {}; double val() { @@ -717,5 +720,5 @@ class Item_func_group_concat : public Item_sum return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0; } String* val_str(String* str); - Item *copy_or_same(THD* thd) { return new Item_func_group_concat(thd, *this); } + Item *copy_or_same(THD* thd); }; diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 5ffd10be7a5..f2c64c4bde9 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -41,7 +41,7 @@ public: :Item_sum_num(thd, item) {} double val() { return 0.0; } enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;} - void reset() {} + bool reset() { return 0;} bool add() { return 0; } void reset_field() {} void update_field(int offset) {} diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 712c8853a20..97158191111 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -66,9 +66,8 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); #endif #endif -extern CHARSET_INFO *system_charset_info; -extern CHARSET_INFO *files_charset_info; -extern CHARSET_INFO *national_charset_info; +extern CHARSET_INFO *system_charset_info, *files_charset_info ; +extern CHARSET_INFO *national_charset_info, *table_alias_charset; /*************************************************************************** Configuration parameters @@ -208,7 +207,7 @@ extern CHARSET_INFO *national_charset_info; #define MODE_PIPES_AS_CONCAT 2 #define MODE_ANSI_QUOTES 4 #define MODE_IGNORE_SPACE 8 -#define MODE_SERIALIZABLE 16 +#define MODE_NOT_USED 16 #define MODE_ONLY_FULL_GROUP_BY 32 #define MODE_NO_UNSIGNED_SUBTRACTION 64 #define MODE_POSTGRESQL 128 @@ -221,6 +220,7 @@ extern CHARSET_INFO *national_charset_info; #define MODE_NO_FIELD_OPTIONS 16384 #define MODE_MYSQL323 32768 #define MODE_MYSQL40 65536 +#define MODE_ANSI (MODE_MYSQL40*2) #define RAID_BLOCK_SIZE 1024 @@ -723,7 +723,7 @@ extern ulong ha_read_rnd_count, ha_read_rnd_next_count; extern ulong ha_commit_count, ha_rollback_count,table_cache_size; extern ulong max_connections,max_connect_errors, connect_timeout; extern ulong max_insert_delayed_threads, max_user_connections; -extern ulong long_query_count, what_to_log,flush_time,opt_sql_mode; +extern ulong long_query_count, what_to_log,flush_time; extern ulong query_buff_size, thread_stack,thread_stack_min; extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit; extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 86ec00e1e92..019a3388341 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -208,9 +208,9 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; const char *sql_mode_names[] = { "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", - "SERIALIZE", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", + "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS", - "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", + "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", NullS }; TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", @@ -324,6 +324,9 @@ MY_TMPDIR mysql_tmpdir_list; DATE_FORMAT dayord; MY_BITMAP temp_pool; +CHARSET_INFO *system_charset_info, *files_charset_info ; +CHARSET_INFO *national_charset_info, *table_alias_charset; + SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam; SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache; SHOW_COMP_OPTION have_crypt, have_compress; @@ -2281,9 +2284,7 @@ static void handle_connections_methods() #endif /* __NT__ */ if (have_tcpip && !opt_disable_networking) { -#ifdef __NT__ handler_count++; -#endif if (pthread_create(&hThread,&connection_attrib, handle_connections_sockets, 0)) { @@ -2294,9 +2295,7 @@ static void handle_connections_methods() #ifdef HAVE_SMEM if (opt_enable_shared_memory) { -#ifdef __NT__ handler_count++; -#endif if (pthread_create(&hThread,&connection_attrib, handle_connections_shared_memory, 0)) { @@ -2311,6 +2310,16 @@ static void handle_connections_methods() pthread_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; } + +void decrement_handler_count() +{ + pthread_mutex_lock(&LOCK_thread_count); + handler_count--; + pthread_mutex_unlock(&LOCK_thread_count); + pthread_cond_signal(&COND_handler_count); +} +#else +#define decrement_handler_count() #endif /* defined(__NT__) || defined(HAVE_SMEM) */ @@ -2428,7 +2437,7 @@ The server will not act as a slave."); #endif /* init_slave() must be called after the thread keys are created */ init_slave(); - + if (opt_bootstrap) { int error=bootstrap(stdin); @@ -3019,13 +3028,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets, // kill server must be invoked from thread 1! kill_server(MYSQL_KILL_SIGNAL); #endif - -#ifdef __NT__ - pthread_mutex_lock(&LOCK_thread_count); - handler_count--; - pthread_mutex_unlock(&LOCK_thread_count); - pthread_cond_signal(&COND_handler_count); -#endif + decrement_handler_count(); DBUG_RETURN(0); } @@ -3105,10 +3108,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) create_new_thread(thd); } - pthread_mutex_lock(&LOCK_thread_count); - handler_count--; - pthread_mutex_unlock(&LOCK_thread_count); - pthread_cond_signal(&COND_handler_count); + decrement_handler_count(); DBUG_RETURN(0); } #endif /* __NT__ */ @@ -3322,12 +3322,8 @@ error: if (!handle_connect_file_map) CloseHandle(handle_connect_file_map); if (!event_connect_answer) CloseHandle(event_connect_answer); if (!event_connect_request) CloseHandle(event_connect_request); -#ifdef __NT__ - pthread_mutex_lock(&LOCK_thread_count); - handler_count--; - pthread_mutex_unlock(&LOCK_thread_count); - pthread_cond_signal(&COND_handler_count); -#endif + + decrement_handler_count(); DBUG_RETURN(0); } #endif /* HAVE_SMEM */ @@ -3921,7 +3917,7 @@ replicating a LOAD DATA INFILE command", (gptr*) &opt_sql_bin_update, (gptr*) &opt_sql_bin_update, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sql-mode", OPT_SQL_MODE, - "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.", + "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.", (gptr*) &sql_mode_str, (gptr*) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_OPENSSL @@ -4634,6 +4630,12 @@ static void mysql_init_variables(void) bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); bzero((gptr) &com_stat, sizeof(com_stat)); + /* Character sets */ + system_charset_info= &my_charset_utf8_general_ci; + files_charset_info= &my_charset_utf8_general_ci; + national_charset_info= &my_charset_utf8_general_ci; + table_alias_charset= &my_charset_bin; + /* Things with default values that are not zero */ delay_key_write_options= (uint) DELAY_KEY_WRITE_ON; opt_specialflag= SPECIAL_ENGLISH; @@ -4684,6 +4686,7 @@ static void mysql_init_variables(void) sys_charset.value= (char*) MYSQL_CHARSET; sys_charset_system.value= (char*) system_charset_info->csname; + /* Set default values for some option variables */ global_system_variables.character_set_results= NULL; global_system_variables.character_set_client= default_charset_info; @@ -4789,10 +4792,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_endinfo=1; /* unireg: memory allocation */ break; case 'a': - global_system_variables.sql_mode= - (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | - MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE | - MODE_ONLY_FULL_GROUP_BY); + global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI); global_system_variables.tx_isolation= ISO_SERIALIZABLE; break; case 'b': @@ -5270,11 +5270,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), fprintf(stderr, "Unknown option to sql-mode: %s\n", argument); exit(1); } - global_system_variables.tx_isolation= - ((global_system_variables.sql_mode & MODE_SERIALIZABLE) ? - ISO_SERIALIZABLE : - ISO_REPEATABLE_READ); - break; + global_system_variables.sql_mode= fix_sql_mode(global_system_variables. + sql_mode); } case OPT_MASTER_PASSWORD: master_password=argument; @@ -5332,6 +5329,9 @@ static void get_options(int argc,char **argv) /* Set global variables based on startup options */ myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size); + table_alias_charset= (lower_case_table_names ? + files_charset_info : + &my_charset_bin); } diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 8271d971782..621fa5f6334 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -14,6 +14,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + This file is the net layer API for the MySQL client/server protocol, + which is a tightly coupled, proprietary protocol owned by MySQL AB. + Any re-implementations of this protocol must also be under GPL + unless one has got an license from MySQL AB stating otherwise. +*/ + /* Write and read of logical packets to/from socket diff --git a/sql/protocol.cc b/sql/protocol.cc index 848321c1576..dc61046aa20 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -102,7 +102,8 @@ void send_error(THD *thd, uint sql_errno, const char *err) if (thd->client_capabilities & CLIENT_PROTOCOL_41) { /* The first # is to make the protocol backward compatible */ - strmov(buff+2, "#000000"); + buff[2]= '#'; + strmov(buff+3, mysql_errno_to_sqlstate(sql_errno)); pos= buff + 2 + SQLSTATE_LENGTH +1; } length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff); @@ -222,8 +223,8 @@ net_printf(THD *thd, uint errcode, ...) int2store(pos, errcode); if (thd->client_capabilities & CLIENT_PROTOCOL_41) { - /* The first # is to make the protocol backward compatible */ - memcpy(pos+2, "#000000", SQLSTATE_LENGTH +1); + pos[2]= '#'; /* To make the protocol backward compatible */ + memcpy(pos+3, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH); } } VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset)); diff --git a/sql/set_var.cc b/sql/set_var.cc index 3145504951d..42ea92825d1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -89,6 +89,7 @@ static void fix_query_cache_min_res_unit(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); +void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); @@ -1164,40 +1165,6 @@ byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type) } -byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type) -{ - ulong val; - char buff[256]; - String tmp(buff, sizeof(buff), &my_charset_latin1); - my_bool found= 0; - - tmp.length(0); - val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : - thd->variables.*offset); - for (uint i= 0; val; val>>= 1, i++) - { - if (val & 1) - { - tmp.append(enum_names->type_names[i]); - tmp.append(','); - } - } - if (tmp.length()) - tmp.length(tmp.length() - 1); - return (byte*) thd->strmake(tmp.ptr(), tmp.length()); -} - - -void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= 0; - else - thd->variables.*offset= global_system_variables.*offset; -} - - - bool sys_var_thd_bit::update(THD *thd, set_var *var) { int res= (*update_func)(thd, var); @@ -1803,7 +1770,105 @@ int set_var_password::update(THD *thd) 1 : 0); } +/**************************************************************************** + Functions to handle sql_mode +****************************************************************************/ +byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type) +{ + ulong val; + char buff[256]; + String tmp(buff, sizeof(buff), &my_charset_latin1); + my_bool found= 0; + + tmp.length(0); + val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : + thd->variables.*offset); + for (uint i= 0; val; val>>= 1, i++) + { + if (val & 1) + { + tmp.append(enum_names->type_names[i]); + tmp.append(','); + } + } + if (tmp.length()) + tmp.length(tmp.length() - 1); + return (byte*) thd->strmake(tmp.ptr(), tmp.length()); +} + + +void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + global_system_variables.*offset= 0; + else + thd->variables.*offset= global_system_variables.*offset; +} + +void fix_sql_mode_var(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + global_system_variables.sql_mode= + fix_sql_mode(global_system_variables.sql_mode); + else + thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode); +} + +/* Map database specific bits to function bits */ + +ulong fix_sql_mode(ulong sql_mode) +{ + /* + Note that we dont set + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS + to allow one to get full use of MySQL in this mode. + */ + + if (sql_mode & MODE_ANSI) + sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | MODE_ONLY_FULL_GROUP_BY); + if (sql_mode & MODE_ORACLE) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_MSSQL) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_MSSQL) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_POSTGRESQL) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_DB2) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_DB2) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_SAPDB) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_MYSQL40) + sql_mode|= MODE_NO_FIELD_OPTIONS; + if (sql_mode & MODE_MYSQL323) + sql_mode|= MODE_NO_FIELD_OPTIONS; + return sql_mode; +} diff --git a/sql/set_var.h b/sql/set_var.h index f501426e553..8646668a236 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -309,11 +309,14 @@ public: }; +extern void fix_sql_mode_var(THD *thd, enum_var_type type); + class sys_var_thd_sql_mode :public sys_var_thd_enum { public: sys_var_thd_sql_mode(const char *name_arg, ulong SV::*offset_arg) - :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib) + :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib, + fix_sql_mode_var) {} bool check(THD *thd, set_var *var) { @@ -605,6 +608,7 @@ void set_var_free(); sys_var *find_sys_var(const char *str, uint length=0); int sql_set_variables(THD *thd, List *var_list); void fix_delay_key_write(THD *thd, enum_var_type type); +ulong fix_sql_mode(ulong sql_mode); extern sys_var_str sys_charset; extern sys_var_str sys_charset_system; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index eeaf560693e..0741dd1e32f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -544,7 +544,8 @@ TABLE_LIST * find_table_in_list(TABLE_LIST *table, { for (; table; table= table->next) if ((!db_name || !strcmp(table->db, db_name)) && - (!table_name || !strcmp(table->alias, table_name))) + (!table_name || !my_strcasecmp(table_alias_charset, + table->alias, table_name))) break; return table; } @@ -1739,7 +1740,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, bool found_table=0; for (; tables ; tables=tables->next) { - if (!strcmp(tables->alias,table_name) && + if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) && (!db || !tables->db || !tables->db[0] || !strcmp(db,tables->db))) { found_table=1; @@ -1868,20 +1869,22 @@ find_item_in_list(Item *find, List &items, uint *counter, { List_iterator li(items); Item **found=0,*item; + const char *db_name=0; const char *field_name=0; const char *table_name=0; if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM) { field_name= ((Item_ident*) find)->field_name; table_name= ((Item_ident*) find)->table_name; + db_name= ((Item_ident*) find)->db_name; } for (uint i= 0; (item=li++); i++) { if (field_name && item->type() == Item::FIELD_ITEM) { - if (!my_strcasecmp(system_charset_info, - ((Item_field*) item)->name,field_name)) + Item_field *item_field= (Item_field*) item; + if (!my_strcasecmp(system_charset_info, item_field->name, field_name)) { if (!table_name) { @@ -1897,11 +1900,16 @@ find_item_in_list(Item *find, List &items, uint *counter, found= li.ref(); *counter= i; } - else if (!strcmp(((Item_field*) item)->table_name,table_name)) + else { - found= li.ref(); - *counter= i; - break; + if (!strcmp(item_field->table_name,table_name) && + (!db_name || (db_name && item_field->db_name && + !strcmp(item_field->table_name,table_name)))) + { + found= li.ref(); + *counter= i; + break; + } } } } @@ -2094,7 +2102,8 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, for (; tables ; tables=tables->next) { TABLE *table=tables->table; - if (!table_name || (!strcmp(table_name,tables->alias) && + if (!table_name || (!my_strcasecmp(table_alias_charset, table_name, + tables->alias) && (!db_name || !strcmp(tables->db,db_name)))) { /* Ensure that we have access right to all columns */ diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index adc3d177fdf..7a154d206ef 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1432,7 +1432,8 @@ ulong Query_cache::init_cache() #else // windows, OS/2 or other case insensitive file names work around VOID(hash_init(&tables, - lower_case_table_names ? &my_charset_bin : system_charset_info, + lower_case_table_names ? &my_charset_bin : + system_charset_info, def_table_hash_size, 0, 0,query_cache_table_get_key, 0, 0)); #endif diff --git a/sql/sql_list.h b/sql/sql_list.h index ff21663576a..2450b2051f2 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -33,6 +33,8 @@ public: { return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size, MEM_ROOT *mem_root) + { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr, size_t size) {} /*lint -e715 */ static void operator delete[](void *ptr, size_t size) {} #ifdef HAVE_purify @@ -190,6 +192,7 @@ public: inline void *replace(void *element) { // Return old element void *tmp=current->info; + DBUG_ASSERT(current->info != 0); current->info=element; return tmp; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 95ac57013da..fcddc2d2252 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -663,7 +663,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, thd->protocol_simple.send_fields(&fields, 0) || send_item_params(stmt)) DBUG_RETURN(1); - join->cleanup(thd); + join->cleanup(); } DBUG_RETURN(0); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4167da5802a..61a64573eaa 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -138,7 +138,6 @@ static bool test_if_subpart(ORDER *a,ORDER *b); static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables); static void calc_group_buffer(JOIN *join,ORDER *group); static bool alloc_group_fields(JOIN *join,ORDER *group); -static bool make_sum_func_list(JOIN *join,List &fields); // Create list for using with tempory table static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, List &new_list1, @@ -153,7 +152,7 @@ static void init_tmptable_sum_functions(Item_sum **func); static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); static void copy_sum_funcs(Item_sum **func_ptr); static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); -static void init_sum_functions(Item_sum **func); +static bool init_sum_functions(Item_sum **func, Item_sum **end); static bool update_sum_func(Item_sum **func); static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, bool distinct, const char *message=NullS); @@ -313,9 +312,11 @@ JOIN::prepare(Item ***rref_pointer_array, if (having->with_sum_func) having->split_sum_func(ref_pointer_array, all_fields); } - + if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); + + /* Check if one one uses a not constant column with group functions and no GROUP BY. @@ -345,45 +346,47 @@ JOIN::prepare(Item ***rref_pointer_array, for (table=tables_list ; table ; table=table->next) tables++; } + { + /* Caclulate the number of groups */ + send_group_parts= 0; + for (ORDER *group= group_list ; group ; group= group->next) + send_group_parts++; + } + procedure= setup_procedure(thd, proc_param, result, fields_list, &error); if (error) - DBUG_RETURN(-1); /* purecov: inspected */ + goto err; /* purecov: inspected */ if (procedure) { if (setup_new_fields(thd, tables_list, fields_list, all_fields, procedure->param_fields)) - { /* purecov: inspected */ - delete procedure; /* purecov: inspected */ - DBUG_RETURN(-1); /* purecov: inspected */ - } + goto err; /* purecov: inspected */ if (procedure->group) { if (!test_if_subpart(procedure->group,group_list)) { /* purecov: inspected */ my_message(0,"Can't handle procedures with differents groups yet", MYF(0)); /* purecov: inspected */ - delete procedure; /* purecov: inspected */ - DBUG_RETURN(-1); /* purecov: inspected */ + goto err; /* purecov: inspected */ } } #ifdef NOT_NEEDED else if (!group_list && procedure->flags & PROC_GROUP) { my_message(0,"Select must have a group with this procedure",MYF(0)); - delete procedure; - DBUG_RETURN(-1); + goto err; } #endif if (order && (procedure->flags & PROC_NO_SORT)) - { /* purecov: inspected */ + { /* purecov: inspected */ my_message(0,"Can't use order with this procedure",MYF(0)); /* purecov: inspected */ - delete procedure; /* purecov: inspected */ - DBUG_RETURN(-1); /* purecov: inspected */ + goto err; /* purecov: inspected */ } } /* Init join struct */ count_field_types(&tmp_table_param, all_fields, 0); + ref_pointer_array_size= all_fields.elements*sizeof(Item*); this->group= group_list != 0; row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR : unit->select_limit_cnt); @@ -398,15 +401,23 @@ JOIN::prepare(Item ***rref_pointer_array, if (sum_func_count && !group_list && (func_count || field_count)) { my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0)); - delete procedure; - DBUG_RETURN(-1); + goto err; } #endif if (!procedure && result->prepare(fields_list, unit)) - { /* purecov: inspected */ - DBUG_RETURN(-1); /* purecov: inspected */ - } + goto err; /* purecov: inspected */ + + if (select_lex->olap == ROLLUP_TYPE && rollup_init()) + goto err; + if (alloc_func_list()) + goto err; + DBUG_RETURN(0); // All OK + +err: + delete procedure; /* purecov: inspected */ + procedure= 0; + DBUG_RETURN(-1); /* purecov: inspected */ } /* @@ -638,7 +649,9 @@ JOIN::optimize() else if (thd->is_fatal_error) // End of memory DBUG_RETURN(1); } - group_list= remove_const(this, group_list, conds, &simple_group); + simple_group= 0; + if (rollup.state == ROLLUP::STATE_NONE) + group_list= remove_const(this, group_list, conds, &simple_group); if (!group_list && group) { order=0; // The output has only one row @@ -788,14 +801,14 @@ JOIN::optimize() thd->proc_info="Sorting for group"; if (create_sort_index(thd, &join_tab[const_tables], group_list, HA_POS_ERROR, HA_POS_ERROR) || - make_sum_func_list(this, all_fields) || - alloc_group_fields(this, group_list)) + alloc_group_fields(this, group_list) || + make_sum_func_list(all_fields, fields_list, 1)) DBUG_RETURN(1); group_list=0; } else { - if (make_sum_func_list(this, all_fields)) + if (make_sum_func_list(all_fields, fields_list, 0)) DBUG_RETURN(1); if (!group_list && ! exec_tmp_table1->distinct && order && simple_order) { @@ -862,7 +875,7 @@ int JOIN::reinit() { DBUG_ENTER("JOIN::reinit"); - //TODO move to unit reinit + /* TODO move to unit reinit */ unit->offset_limit_cnt =select_lex->offset_limit; unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit; if (unit->select_limit_cnt < select_lex->select_limit) @@ -873,7 +886,7 @@ JOIN::reinit() if (setup_tables(tables_list)) DBUG_RETURN(1); - // Reset of sum functions + /* Reset of sum functions */ first_record= 0; if (sum_funcs) { @@ -897,7 +910,7 @@ JOIN::reinit() filesort_free_buffers(exec_tmp_table2); } if (items0) - memcpy(ref_pointer_array, items0, ref_pointer_array_size); + set_items_ref_array(items0); if (tmp_join) restore_tmp(); @@ -977,9 +990,6 @@ JOIN::exec() DBUG_VOID_RETURN; } - /* Perform FULLTEXT search before all regular searches */ - //init_ftfuncs(thd, select_lex, test(order)); - JOIN *curr_join= this; List *curr_all_fields= &all_fields; List *curr_fields_list= &fields_list; @@ -1030,7 +1040,7 @@ JOIN::exec() } curr_all_fields= &tmp_all_fields1; curr_fields_list= &tmp_fields_list1; - memcpy(ref_pointer_array, items1, ref_pointer_array_size); + set_items_ref_array(items1); if (sort_and_group || curr_tmp_table->group) { @@ -1079,7 +1089,8 @@ JOIN::exec() if (make_simple_join(curr_join, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, group_list); - count_field_types(&curr_join->tmp_table_param, curr_join->tmp_all_fields1, + count_field_types(&curr_join->tmp_table_param, + curr_join->tmp_all_fields1, curr_join->select_distinct && !curr_join->group_list); curr_join->tmp_table_param.hidden_field_count= (curr_join->tmp_all_fields1.elements- @@ -1117,7 +1128,8 @@ JOIN::exec() thd->proc_info="Copying to group table"; tmp_error= -1; - if (make_sum_func_list(curr_join, *curr_all_fields) || + if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, + 1) || (tmp_error= do_select(curr_join, (List *) 0, curr_tmp_table, 0))) { @@ -1141,7 +1153,7 @@ JOIN::exec() } curr_fields_list= &curr_join->tmp_fields_list2; curr_all_fields= &curr_join->tmp_all_fields2; - memcpy(ref_pointer_array, items2, ref_pointer_array_size); + set_items_ref_array(items2); curr_join->tmp_table_param.field_count+= curr_join->tmp_table_param.sum_func_count; curr_join->tmp_table_param.sum_func_count= 0; @@ -1169,9 +1181,7 @@ JOIN::exec() } if (procedure) - { count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0); - } if (curr_join->group || curr_join->tmp_table_param.sum_func_count || (procedure && (procedure->flags & PROC_GROUP))) @@ -1201,10 +1211,10 @@ JOIN::exec() } curr_fields_list= &tmp_fields_list3; curr_all_fields= &tmp_all_fields3; - memcpy(ref_pointer_array, items3, ref_pointer_array_size); + set_items_ref_array(items3); - if (make_sum_func_list(curr_join, *curr_all_fields) || - thd->is_fatal_error) + if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, + 1) || thd->is_fatal_error) DBUG_VOID_RETURN; } if (curr_join->group_list || curr_join->order) @@ -1291,7 +1301,7 @@ JOIN::exec() */ int -JOIN::cleanup(THD *thd) +JOIN::cleanup() { DBUG_ENTER("JOIN::cleanup"); select_lex->join= 0; @@ -1312,7 +1322,7 @@ JOIN::cleanup(THD *thd) } } tmp_join->tmp_join= 0; - DBUG_RETURN(tmp_join->cleanup(thd)); + DBUG_RETURN(tmp_join->cleanup()); } lock=0; // It's faster to unlock later @@ -1396,7 +1406,7 @@ err: thd->limit_found_rows= curr_join->send_records; thd->examined_row_count= curr_join->examined_rows; thd->proc_info="end"; - err= join->cleanup(thd); + err= join->cleanup(); if (thd->net.report_error) err= -1; delete join; @@ -2916,7 +2926,6 @@ make_simple_join(JOIN *join,TABLE *tmp_table) join->tmp_table_param.func_count=0; join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0; join->first_record=join->sort_and_group=0; - join->sum_funcs=0; join->send_records=(ha_rows) 0; join->group=0; join->row_limit=join->unit->select_limit_cnt; @@ -5715,8 +5724,12 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having - else if (join->do_send_rows) - error=join->procedure->send_row(*join->fields) ? 1 : 0; + else + { + if (join->do_send_rows) + error=join->procedure->send_row(*join->fields) ? 1 : 0; + join->send_records++; + } if (end_of_records && join->procedure->end_of_records()) error= 1; // Fatal error } @@ -5730,17 +5743,23 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), } if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having - else if (join->do_send_rows) - error=join->result->send_data(*join->fields) ? 1 : 0; + else + { + if (join->do_send_rows) + error=join->result->send_data(*join->fields) ? 1 : 0; + join->send_records++; + } + if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0) + { + if (join->rollup_send_data((uint) (idx+1))) + error= 1; + } } if (error > 0) DBUG_RETURN(-1); /* purecov: inspected */ if (end_of_records) - { - join->send_records++; DBUG_RETURN(0); - } - if (!error && ++join->send_records >= join->unit->select_limit_cnt && + if (join->send_records >= join->unit->select_limit_cnt && join->do_send_rows) { if (!(join->select_options & OPTION_FOUND_ROWS)) @@ -5760,7 +5779,8 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (idx < (int) join->send_group_parts) { copy_fields(&join->tmp_table_param); - init_sum_functions(join->sum_funcs); + if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1])) + DBUG_RETURN(-1); if (join->procedure) join->procedure->add(); DBUG_RETURN(0); @@ -6016,7 +6036,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { copy_fields(&join->tmp_table_param); copy_funcs(join->tmp_table_param.items_to_copy); - init_sum_functions(join->sum_funcs); + if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1])) + DBUG_RETURN(-1); if (join->procedure) join->procedure->add(); DBUG_RETURN(0); @@ -7674,7 +7695,10 @@ err2: /* - Copy fields and null values between two tables + Make a copy of all simple SELECT'ed items + + This is done at the start of a new group so that we can retrieve + these later when the group changes. */ void @@ -7694,33 +7718,76 @@ copy_fields(TMP_TABLE_PARAM *param) } -/***************************************************************************** - Make an array of pointer to sum_functions to speed up sum_func calculation -*****************************************************************************/ +/* + Make an array of pointers to sum_functions to speed up sum_func calculation -static bool -make_sum_func_list(JOIN *join,List &fields) + SYNOPSIS + alloc_func_list() + + RETURN + 0 ok + 1 Error +*/ + +bool JOIN::alloc_func_list() { - DBUG_ENTER("make_sum_func_list"); - Item_sum **func = - (Item_sum**) sql_alloc(sizeof(Item_sum*)* - (join->tmp_table_param.sum_func_count+1)); - if (!func) - DBUG_RETURN(TRUE); - List_iterator it(fields); - join->sum_funcs=func; + uint func_count, group_parts; + DBUG_ENTER("alloc_func_list"); - Item *field; - while ((field=it++)) + func_count= tmp_table_param.sum_func_count; + /* + If we are using rollup, we need a copy of the summary functions for + each level + */ + if (rollup.state != ROLLUP::STATE_NONE) + func_count*= (send_group_parts+1); + + group_parts= send_group_parts; + /* + If distinct, reserve memory for possible + disctinct->group_by optimization + */ + if (select_distinct) + group_parts+= fields_list.elements; + + /* This must use calloc() as rollup_make_fields depends on this */ + sum_funcs= (Item_sum**) thd->calloc(sizeof(Item_sum**) * (func_count+1) + + sizeof(Item_sum***) * (group_parts+1)); + sum_funcs_end= (Item_sum***) (sum_funcs+func_count+1); + DBUG_RETURN(sum_funcs == 0); +} + + +bool JOIN::make_sum_func_list(List &all_fields, List &send_fields, + bool before_group_by) +{ + List_iterator_fast it(all_fields); + Item_sum **func; + Item *item; + DBUG_ENTER("make_sum_func_list"); + + func= sum_funcs; + while ((item=it++)) { - if (field->type() == Item::SUM_FUNC_ITEM && !field->const_item()) + if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item()) { - *func++=(Item_sum*) field; + *func++= (Item_sum*) item; /* let COUNT(DISTINCT) create the temporary table */ - if (((Item_sum*) field)->setup(join->thd)) + if (((Item_sum*) item)->setup(thd)) DBUG_RETURN(TRUE); } } + if (before_group_by && rollup.state == ROLLUP::STATE_INITED) + { + rollup.state= ROLLUP::STATE_READY; + if (rollup_make_fields(all_fields, send_fields, &func)) + DBUG_RETURN(TRUE); // Should never happen + } + else if (rollup.state == ROLLUP::STATE_NONE) + { + for (uint i=0 ; i <= send_group_parts ;i++) + sum_funcs_end[i]= func; + } *func=0; // End marker DBUG_RETURN(FALSE); } @@ -7816,8 +7883,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, all_fields - all fields list RETURN - 0 - ok - !=0 - error + 0 ok + 1 error */ static bool @@ -7886,12 +7953,21 @@ copy_sum_funcs(Item_sum **func_ptr) } -static void -init_sum_functions(Item_sum **func_ptr) +static bool +init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr) { - Item_sum *func; - for (; (func= (Item_sum*) *func_ptr) ; func_ptr++) - func->reset(); + for (; func_ptr != end_ptr ;func_ptr++) + { + if ((*func_ptr)->reset()) + return 1; + } + /* If rollup, calculate the upper sum levels */ + for ( ; *func_ptr ; func_ptr++) + { + if ((*func_ptr)->add()) + return 1; + } + return 0; } @@ -7916,10 +7992,10 @@ copy_funcs(Item **func_ptr) } -/***************************************************************************** +/* Create a condition for a const reference and add this to the currenct select for the table -*****************************************************************************/ +*/ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) { @@ -7935,7 +8011,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) for (uint i=0 ; i < join_tab->ref.key_parts ; i++) { - Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].fieldnr-1]; + Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i]. + fieldnr-1]; Item *value=join_tab->ref.items[i]; cond->add(new Item_func_equal(new Item_field(field),value)); } @@ -7958,7 +8035,241 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) DBUG_RETURN(error ? TRUE : FALSE); } + +/* + Free joins of subselect of this select. + + free_underlaid_joins() + thd - THD pointer + select - pointer to st_select_lex which subselects joins we will free +*/ + +void free_underlaid_joins(THD *thd, SELECT_LEX *select) +{ + for (SELECT_LEX_UNIT *unit= select->first_inner_unit(); + unit; + unit= unit->next_unit()) + unit->cleanup(); +} + /**************************************************************************** + ROLLUP handling +****************************************************************************/ + +/* Allocate memory needed for other rollup functions */ + +bool JOIN::rollup_init() +{ + uint i,j; + ORDER *group; + Item **ref_array; + + tmp_table_param.quick_group= 0; // Can't create groups in tmp table + rollup.state= ROLLUP::STATE_INITED; + + /* + Create pointers to the different sum function groups + These are updated by rollup_make_fields() + */ + tmp_table_param.group_parts= send_group_parts; + + if (!(rollup.fields= (List*) thd->alloc((sizeof(Item*) + + sizeof(List) + + ref_pointer_array_size) + * send_group_parts))) + return 1; + rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); + ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts); + rollup.item_null= new (&thd->mem_root) Item_null(); + + /* + Prepare space for field list for the different levels + These will be filled up in rollup_make_fields() + */ + for (i= 0 ; i < send_group_parts ; i++) + { + List *fields= &rollup.fields[i]; + fields->empty(); + rollup.ref_pointer_arrays[i]= ref_array; + ref_array+= all_fields.elements; + for (j=0 ; j < fields_list.elements ; j++) + fields->push_back(rollup.item_null); + } + return 0; +} + + +/* + Fill up rollup structures with pointers to fields to use + + SYNOPSIS + rollup_make_fields() + all_fields List of all fields (hidden and real ones) + fields Pointer to selected fields + func Store here a pointer to all fields + + IMPLEMENTATION: + Creates copies of item_sum items for each sum level + + RETURN + 0 if ok + In this case func is pointing to next not used element. + 1 on error +*/ + +bool JOIN::rollup_make_fields(List &all_fields, List &fields, + Item_sum ***func) +{ + List_iterator_fast it(all_fields); + Item *first_field= fields.head(); + uint level; + + /* + Create field lists for the different levels + + The idea here is to have a separate field list for each rollup level to + avoid all runtime checks of which columns should be NULL. + + The list is stored in reverse order to get sum function in such an order + in func that it makes it easy to reset them with init_sum_functions() + + Assuming: SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP + + rollup.fields[0] will contain list where a,b,c is NULL + rollup.fields[1] will contain list where b,c is NULL + ... + rollup.ref_pointer_array[#] points to fields for rollup.fields[#] + ... + sum_funcs_end[0] points to all sum functions + sum_funcs_end[1] points to all sum functions, except grand totals + ... + */ + + for (level=0 ; level < send_group_parts > 0 ; level++) + { + uint i; + uint pos= send_group_parts - level -1; + bool real_fields= 0; + Item *item; + List_iterator new_it(rollup.fields[pos]); + Item **ref_array_start= rollup.ref_pointer_arrays[pos]; + ORDER *start_group; + + /* Point to first hidden field */ + Item **ref_array= ref_array_start + all_fields.elements-1; + + /* Remember where the sum functions ends for the previous level */ + sum_funcs_end[pos+1]= *func; + + /* Find the start of the group for this level */ + for (i= 0, start_group= group_list ; + i++ < pos ; + start_group= start_group->next) + ; + + it.rewind(); + while ((item= it++)) + { + if (item == first_field) + { + real_fields= 1; // End of hidden fields + ref_array= ref_array_start; + } + + if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item()) + { + /* + This is a top level summary function that must be replaced with + a sum function that is reset for this level. + + NOTE: This code creates an object which is not that nice in a + sub select. Fortunately it's not common to have rollup in + sub selects. + */ + item= item->copy_or_same(thd); + ((Item_sum*) item)->make_unique(); + if (((Item_sum*) item)->setup(thd)) + return 1; + *(*func)= (Item_sum*) item; + (*func)++; + } + else if (real_fields) + { + /* Check if this is something that is part of this group by */ + ORDER *group; + for (group= start_group ; group ; group= group->next) + { + if (*group->item == item) + { + /* + This is an element that is used by the GROUP BY and should be + set to NULL in this level + */ + item->maybe_null= 1; // Value will be null sometimes + item= rollup.item_null; + break; + } + } + } + *ref_array= item; + if (real_fields) + { + (void) new_it++; // Point to next item + new_it.replace(item); // Replace previous + ref_array++; + } + else + ref_array--; + } + } + sum_funcs_end[0]= *func; // Point to last function + return 0; +} + +/* + Send all rollup levels higher than the current one to the client + + SYNOPSIS: + rollup_send_data() + idx Level we are on: + 0 = Total sum level + 1 = First group changed (a) + 2 = Second group changed (a,b) + + SAMPLE + SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP + + RETURN + 0 ok + 1 If send_data_failed() +*/ + +int JOIN::rollup_send_data(uint idx) +{ + uint i; + for (i= send_group_parts ; i-- > idx ; ) + { + /* Get reference pointers to sum functions in place */ + memcpy((char*) ref_pointer_array, + (char*) rollup.ref_pointer_arrays[i], + ref_pointer_array_size); + if ((!having || having->val_int())) + { + if (send_records < unit->select_limit_cnt && + result->send_data(rollup.fields[i])) + return 1; + send_records++; + } + } + /* Restore ref_pointer_array */ + set_items_ref_array(current_ref_pointer_array); + return 0; +} + + +/**************************************************************************** + EXPLAIN handling + Send a description about what how the select will be done to stdout ****************************************************************************/ @@ -8198,19 +8509,3 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, result, unit, select_lex, 0); DBUG_RETURN(res); } - -/* - Free joins of subselect of this select. - - free_underlaid_joins() - thd - THD pointer - select - pointer to st_select_lex which subselects joins we will free -*/ - -void free_underlaid_joins(THD *thd, SELECT_LEX *select) -{ - for (SELECT_LEX_UNIT *unit= select->first_inner_unit(); - unit; - unit= unit->next_unit()) - unit->cleanup(); -} diff --git a/sql/sql_select.h b/sql/sql_select.h index 7f3669f7478..df21d337b54 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -106,12 +106,22 @@ typedef struct st_join_table { } JOIN_TAB; -typedef struct st_position { /* Used in find_best */ +typedef struct st_position /* Used in find_best */ +{ double records_read; JOIN_TAB *table; KEYUSE *key; } POSITION; +typedef struct st_rollup +{ + enum State { STATE_NONE, STATE_INITED, STATE_READY }; + State state; + Item *item_null; + Item ***ref_pointer_arrays; + List *fields; +} ROLLUP; + class JOIN :public Sql_alloc { @@ -132,7 +142,7 @@ class JOIN :public Sql_alloc // used to store 2 possible tmp table of SELECT TABLE *exec_tmp_table1, *exec_tmp_table2; THD *thd; - Item_sum **sum_funcs; + Item_sum **sum_funcs, ***sum_funcs_end; Procedure *procedure; Item *having; Item *tmp_having; // To store Having when processed temporary table @@ -146,6 +156,7 @@ class JOIN :public Sql_alloc SELECT_LEX *select_lex; JOIN *tmp_join; // copy of this JOIN to be used with temporary tables + ROLLUP rollup; // Used with rollup bool select_distinct, //Is select distinct? no_order, simple_order, simple_group, @@ -159,7 +170,7 @@ class JOIN :public Sql_alloc List tmp_all_fields1, tmp_all_fields2, tmp_all_fields3; //Part, shared with list above, emulate following list List tmp_fields_list1, tmp_fields_list2, tmp_fields_list3; - List & fields_list; // hold field list passed to mysql_select + List &fields_list; // hold field list passed to mysql_select int error; ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select @@ -168,15 +179,15 @@ class JOIN :public Sql_alloc SQL_SELECT *select; //created in optimisation phase Item **ref_pointer_array; //used pointer reference for this select // Copy of above to be used with different lists - Item **items0, **items1, **items2, **items3; + Item **items0, **items1, **items2, **items3, **current_ref_pointer_array; uint ref_pointer_array_size; // size of above in bytes const char *zero_result_cause; // not 0 if exec must return zero result bool union_part; // this subselect is part of union bool optimized; // flag to avoid double optimization in EXPLAIN - JOIN(THD *thd, List &fields, - ulong select_options, select_result *result): + JOIN(THD *thd_arg, List &fields, ulong select_options_arg, + select_result *result_arg): join_tab(0), table(0), tables(0), const_tables(0), @@ -184,13 +195,13 @@ class JOIN :public Sql_alloc do_send_rows(1), send_records(0), found_records(0), examined_rows(0), exec_tmp_table1(0), exec_tmp_table2(0), - thd(thd), + thd(thd_arg), sum_funcs(0), procedure(0), having(0), tmp_having(0), - select_options(select_options), - result(result), - lock(thd->lock), + select_options(select_options_arg), + result(result_arg), + lock(thd_arg->lock), select_lex(0), //for safety tmp_join(0), select_distinct(test(select_options & SELECT_DISTINCT)), @@ -212,6 +223,7 @@ class JOIN :public Sql_alloc bzero((char*) &keyuse,sizeof(keyuse)); tmp_table_param.copy_field=0; tmp_table_param.end_write_records= HA_POS_ERROR; + rollup.state= ROLLUP::STATE_NONE; } int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, @@ -221,15 +233,28 @@ class JOIN :public Sql_alloc int optimize(); int reinit(); void exec(); - int cleanup(THD *thd); + int cleanup(); void restore_tmp(); + bool alloc_func_list(); + bool make_sum_func_list(List &all_fields, List &send_fields, + bool before_group_by); + inline void set_items_ref_array(Item **ptr) + { + memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size); + current_ref_pointer_array= ptr; + } inline void init_items_ref_array() { items0= ref_pointer_array + all_fields.elements; - ref_pointer_array_size= all_fields.elements*sizeof(Item*); memcpy(items0, ref_pointer_array, ref_pointer_array_size); + current_ref_pointer_array= items0; } + + bool rollup_init(); + bool rollup_make_fields(List &all_fields, List &fields, + Item_sum ***func); + int JOIN::rollup_send_data(uint idx); }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 16934e33798..cfe392dae7d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1004,12 +1004,7 @@ static void append_identifier(THD *thd, String *packet, const char *name) { char qtype; - if ((thd->variables.sql_mode & MODE_ANSI_QUOTES) || - (thd->variables.sql_mode & MODE_POSTGRESQL) || - (thd->variables.sql_mode & MODE_ORACLE) || - (thd->variables.sql_mode & MODE_MSSQL) || - (thd->variables.sql_mode & MODE_DB2) || - (thd->variables.sql_mode & MODE_SAPDB)) + if (thd->variables.sql_mode & MODE_ANSI_QUOTES) qtype= '\"'; else qtype= '`'; @@ -1031,16 +1026,16 @@ append_identifier(THD *thd, String *packet, const char *name) static int store_create_info(THD *thd, TABLE *table, String *packet) { - my_bool foreign_db_mode= ((thd->variables.sql_mode & MODE_POSTGRESQL) || - (thd->variables.sql_mode & MODE_ORACLE) || - (thd->variables.sql_mode & MODE_MSSQL) || - (thd->variables.sql_mode & MODE_DB2) || - (thd->variables.sql_mode & MODE_SAPDB)); - my_bool limited_mysql_mode= ((thd->variables.sql_mode & - MODE_NO_FIELD_OPTIONS) || - (thd->variables.sql_mode & MODE_MYSQL323) || - (thd->variables.sql_mode & MODE_MYSQL40)); - + my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | + MODE_ORACLE | + MODE_MSSQL | + MODE_DB2 | + MODE_SAPDB | + MODE_ANSI)) != 0; + my_bool limited_mysql_mode= (thd->variables.sql_mode & + (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 | + MODE_MYSQL40)) != 0; + DBUG_ENTER("store_create_info"); DBUG_PRINT("enter",("table: %s",table->real_name)); diff --git a/sql/sql_state.c b/sql/sql_state.c new file mode 100644 index 00000000000..355b847f239 --- /dev/null +++ b/sql/sql_state.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2000-2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Functions to map mysqld errno to sql_state */ + +#include +#include + +struct st_map_errno_to_sqlstate +{ + uint mysql_errno; + const char *odbc_state; + const char *jdbc_state; +}; + +struct st_map_errno_to_sqlstate sqlstate_map[]= +{ +#include +}; + +const char *mysql_errno_to_sqlstate(uint mysql_errno) +{ + uint first=0, end= array_elements(sqlstate_map)-1; + struct st_map_errno_to_sqlstate *map; + + /* Do binary search in the sorted array */ + while (first != end) + { + uint mid= (first+end)/2; + map= sqlstate_map+mid; + if (map->mysql_errno < mysql_errno) + first= mid+1; + else + end= mid; + } + map= sqlstate_map+first; + if (map->mysql_errno == mysql_errno) + return map->odbc_state; + return "HY000"; /* General error */ +} diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 6077c42bd1d..b4fad0dbebf 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -28,10 +28,6 @@ #include #endif -CHARSET_INFO *system_charset_info= &my_charset_utf8_general_ci; -CHARSET_INFO *files_charset_info= &my_charset_utf8_general_ci; -CHARSET_INFO *national_charset_info= &my_charset_utf8_general_ci; - extern gptr sql_alloc(unsigned size); extern void sql_element_free(void *ptr); diff --git a/sql/sql_string.h b/sql/sql_string.h index 8212bd0a2bd..d9b780ada5d 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -69,7 +69,10 @@ public: Alloced_length=str.Alloced_length; alloced=0; str_charset=str.str_charset; } - static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) + { return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size, MEM_ROOT *mem_root) + { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */ { sql_element_free(ptr_arg); } ~String() { free(); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ea3b30d24e8..7cadf187181 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1731,10 +1731,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, fn_same(new_name_buff,table_name,3); if (lower_case_table_names) my_casedn_str(system_charset_info,new_name); - if ((lower_case_table_names && - !my_strcasecmp(system_charset_info, new_name_buff,table_name)) || - (!lower_case_table_names && - !strcmp(new_name_buff,table_name))) + if (!my_strcasecmp(table_alias_charset, new_name_buff, table_name)) new_name=table_name; // No. Make later check easier else { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 1d0f37f0042..f47900d8276 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -389,7 +389,7 @@ int st_select_lex_unit::cleanup() JOIN *join; if ((join= sl->join)) { - error|= sl->join->cleanup(thd); + error|= sl->join->cleanup(); delete join; } } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1d735730801..efb5e42626d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2971,7 +2971,7 @@ olap_opt: } lex->current_select->select_lex()->olap= CUBE_TYPE; net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE"); - YYABORT; /* To be deleted in 4.1 */ + YYABORT; /* To be deleted in 5.1 */ } | WITH ROLLUP_SYM { @@ -2983,8 +2983,6 @@ olap_opt: YYABORT; } lex->current_select->select_lex()->olap= ROLLUP_TYPE; - net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "ROLLUP"); - YYABORT; /* To be deleted in 4.1 */ } ; @@ -3039,20 +3037,7 @@ opt_limit_clause: ; limit_clause: - LIMIT - { - LEX *lex= Lex; - if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && - lex->current_select->select_lex()->olap != - UNSPECIFIED_OLAP_TYPE) - { - net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP", - "LIMIT"); - YYABORT; - } - } - limit_options - {} + LIMIT limit_options {} ; limit_options: diff --git a/sql/unireg.h b/sql/unireg.h index 6ddd9856724..cd459dfc783 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -106,8 +106,8 @@ #define SPECIAL_SAFE_MODE 2048 /* Extern defines */ -#define store_record(A,B) bmove_allign((A)->B,(A)->record[0],(size_t) (A)->reclength) -#define restore_record(A,B) bmove_allign((A)->record[0],(A)->B,(size_t) (A)->reclength) +#define store_record(A,B) bmove_align((A)->B,(A)->record[0],(size_t) (A)->reclength) +#define restore_record(A,B) bmove_align((A)->record[0],(A)->B,(size_t) (A)->reclength) #define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->reclength) #define empty_record(A) { \ restore_record((A),default_values); \ diff --git a/strings/Makefile.am b/strings/Makefile.am index 4a57ed73d20..7b2fdcccc55 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -73,7 +73,7 @@ if ASSEMBLER endif str_test: str_test.c $(LIBRARIES) - $(LINK) $(FLAGS) -DMAIN $(srcdir)/str_test.c $(LDADD) $(LIBS) + $(LINK) $(FLAGS) -DMAIN $INCLUDES $(srcdir)/str_test.c $(LDADD) $(LIBS) $(pkglib_LIBRARIES) # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/strings/ctype.c b/strings/ctype.c index ce7bb9ca4a4..cbd13111b70 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -31,7 +31,6 @@ static char *mstr(char *str,const char *src,uint l1,uint l2) return str; } - struct my_cs_file_section_st { int state; @@ -265,4 +264,3 @@ my_bool my_parse_charset_xml(const char *buf, uint len, my_xml_parser_free(&p); return rc; } - diff --git a/strings/str_test.c b/strings/str_test.c index 0c3ff471ad7..369fa7251d8 100644 --- a/strings/str_test.c +++ b/strings/str_test.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL 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 @@ -94,6 +94,8 @@ int main(void) test_strarg("bmove_upp(to+6,from+6,3)",(bmove_upp(to+6,from+6,3),0L),INT_MAX32, 3,T_CHAR,3,F_CHAR,0,0); test_strarg("bmove_upp(to,from,0)",(bmove_upp(to,from,0),0L),INT_MAX32,0,0); + test_strarg("bmove_align(to,from,8)",(bmove_align(to,from,8),0L),INT_MAX32, + 8,F_CHAR,0,0); test_strarg("strappend(to,3,' ')",(strappend(to,3,' '),0L),INT_MAX32, 3,T_CHAR,1,0,T_LEN-4,T_CHAR,1,0,0,0); test_strarg("strappend(to,T_LEN+5,' ')",(strappend(to,T_LEN+5,' '),0L),INT_MAX32, diff --git a/strings/strings-x86.s b/strings/strings-x86.s index 8b29a2db7f1..9409657e06c 100644 --- a/strings/strings-x86.s +++ b/strings/strings-x86.s @@ -23,44 +23,53 @@ # Move a alligned, not overlapped, by (long) divided memory area # Args: to,from,length -.globl bmove_allign - .type bmove_allign,@function -bmove_allign: +.globl bmove_align + .type bmove_align,@function +bmove_align: movl %edi,%edx - movl %esi,%eax + push %esi movl 4(%esp),%edi # to movl 8(%esp),%esi # from movl 12(%esp),%ecx # length addw $3,%cx # fix if not divisible with long shrw $2,%cx - rep - movsl - movl %eax,%esi + jz .ba_20 + .p2align 4,,7 +.ba_10: + movl -4(%esi,%ecx),%eax + movl %eax,-4(%edi,%ecx) + decl %ecx + jnz .ba_10 +.ba_20: pop %esi movl %edx,%edi ret -.end: - .size bmove_allign,.end-bmove_allign + .size bmove_align,.end-bmove_align # Move a string from higher to lower - # Arg from+1,to+1,length + # Arg from_end+1,to_end+1,length .globl bmove_upp .type bmove_upp,@function bmove_upp: - std # Work downward - movl %edi,%edx - movl %esi,%eax - movl 4(%esp),%edi # p1 - movl 8(%esp),%esi # p2 - movl 12(%esp),%ecx # length - decl %edi # Don't move last arg - decl %esi - rep - movsb # One byte a time because overlap - cld # C library wants cld - movl %eax,%esi + movl %edi,%edx # Remember %edi + push %esi + movl 8(%esp),%edi # dst + movl 16(%esp),%ecx # length + movl 12(%esp),%esi # source + test %ecx,%ecx + jz .bu_20 + subl %ecx,%esi # To start of strings + subl %ecx,%edi + + .p2align 4,,7 +.bu_10: movb -1(%esi,%ecx),%al + movb %al,-1(%edi,%ecx) + decl %ecx + jnz .bu_10 +.bu_20: pop %esi movl %edx,%edi ret + .bmove_upp_end: .size bmove_upp,.bmove_upp_end-bmove_upp @@ -304,22 +313,23 @@ si_99: popl %ebp strmake: pushl %edi pushl %esi - movl 12(%esp),%edi # dst - movl 16(%esp),%esi # src - movl 20(%esp),%ecx # Length of memory-area - clrb %al # For test of end-null - jecxz sm_90 # Nothing to move, put zero at end. - -sm_10: cmpb (%esi),%al # Next char to move - movsb # move arg - jz sm_99 # last char, we are ready - loop sm_10 # Continue moving -sm_90: movb %al,(%edi) # Set end pos - incl %edi # Fix that di points at end null -sm_99: decl %edi # di points now at end null - movl %edi,%eax # Ret value.p $ - popl %esi - popl %edi + mov 12(%esp),%edi # dst + movl $0,%edx + movl 20(%esp),%ecx # length + movl 16(%esp),%esi # src + cmpl %edx,%ecx + jz sm_90 +sm_00: movb (%esi,%edx),%al + cmpb $0,%al + jz sm_90 + movb %al,(%edi,%edx) + incl %edx + cmpl %edx,%ecx + jnz sm_00 +sm_90: movb $0,(%edi,%edx) +sm_99: lea (%edi,%edx),%eax # Return pointer to end null + pop %esi + pop %edi ret .strmake_end: .size strmake,.strmake_end-strmake diff --git a/strings/strings.asm b/strings/strings.asm index 43bc23fa965..fe39c8bb3e6 100644 --- a/strings/strings.asm +++ b/strings/strings.asm @@ -219,8 +219,8 @@ _bmove ENDP ; Args: to,from,length ; - PUBLIC _bmove_allign -_bmove_allign PROC + PUBLIC _bmove_align +_bmove_align PROC mov bx,bp mov dx,di mov ax,si @@ -238,7 +238,7 @@ _bmove_allign PROC mov di,dx mov bp,bx ret -_bmove_allign ENDP +_bmove_align ENDP ; ; Move a string from higher to lower @@ -656,9 +656,9 @@ _bmove ENDP ; Args: to,from,length ; - begcode bmove_allign - public _bmove_allign -_bmove_allign proc near + begcode bmove_align + public _bmove_align +_bmove_align proc near fix_es 1 mov edx,edi mov eax,esi @@ -671,8 +671,8 @@ _bmove_allign proc near mov esi,eax mov edi,edx ret -_bmove_allign ENDP - endcode bmove_allign +_bmove_align ENDP + endcode bmove_align ; ; Move a string from higher to lower From 487bf48ad6a90ec9dad6a4ab4e89c6159ddc2860 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 17:31:21 +0200 Subject: [PATCH 313/399] - Updated Default-Stop run levels in the LSB header section to satisfy Red Hat's chkconfig (Bug #272) (The LSB spec is a bit ambigous about what actually needs to be put into this field) --- support-files/mysql.server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index de01142beac..694e6fa8ebb 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -19,7 +19,7 @@ # Required-Start: $local_fs $network $remote_fs # Required-Stop: $local_fs $network $remote_fs # Default-Start: 2 3 4 5 -# Default-Stop: 2 3 4 5 +# Default-Stop: 0 1 6 # Short-Description: start and stop MySQL # Description: MySQL is a very fast and reliable SQL database engine. ### END INIT INFO From c6c60f6ee819a238ab62e3f9608502c9a8f25b36 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 23:17:01 +0300 Subject: [PATCH 314/399] After merge fix mysql-test/t/lowercase_table.test: MySQL 4.1 does this correct --- mysql-test/r/insert_select.result | 5 ++--- mysql-test/r/loaddata.result | 5 +++++ mysql-test/r/lowercase_table.result | 6 ++++-- mysql-test/r/query_cache.result | 2 +- mysql-test/r/rpl_log.result | 22 ++++++++++++++-------- mysql-test/t/lowercase_table.test | 2 -- mysql-test/t/rpl_log.test | 2 +- sql/set_var.cc | 1 - 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 4f6349f8f8b..04c3bc9027d 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -71,9 +71,8 @@ create table t2(a int); insert into t2 values(1),(2); reset master; insert into t1 select * from t2; -Duplicate entry '2' for key 1 +ERROR 23000: Duplicate entry '2' for key 1 show binlog events; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3 -master-bin.001 79 Query 1 79 use test; insert into t1 select * from t2 +master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3 drop table t1, t2; diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 560c5b2567e..3cd62d8b678 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -17,6 +17,11 @@ a b c d 2003-03-03 2003-03-03 2003-03-03 NULL truncate table t1; load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d); +Warnings: +Warning 1263 Data truncated for column 'c' at row 1 +Warning 1263 Data truncated for column 'd' at row 1 +Warning 1263 Data truncated for column 'b' at row 2 +Warning 1263 Data truncated for column 'd' at row 2 SELECT * from t1; a b c d NULL NULL 0000-00-00 0000-00-00 diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result index d32228216b8..af4e2300088 100644 --- a/mysql-test/r/lowercase_table.result +++ b/mysql-test/r/lowercase_table.result @@ -21,7 +21,9 @@ select count(*) from t1; count(*) 0 select count(T1.a) from t1; -Unknown table 'T1' in field list +count(T1.a) +0 select count(bags.a) from t1 as Bags; -Unknown table 'bags' in field list +count(bags.a) +0 drop table t1; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 9d0c105b6c0..3b3e52d8240 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -502,7 +502,6 @@ drop table t1; show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 -create table t1 (a int); show global variables like "query_cache_min_res_unit"; Variable_name Value query_cache_min_res_unit 4096 @@ -562,6 +561,7 @@ set GLOBAL query_cache_min_res_unit=default; show global variables like "query_cache_min_res_unit"; Variable_name Value query_cache_min_res_unit 4096 +create table t1 (a int); set GLOBAL query_cache_size=1000; show global variables like "query_cache_size"; Variable_name Value diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result index 948a755c3db..df2ef4e3d8a 100644 --- a/mysql-test/r/rpl_log.result +++ b/mysql-test/r/rpl_log.result @@ -36,6 +36,8 @@ show binlog events from 79 limit 2,1; Log_name Pos Event_type Server_id Orig_log_pos Info master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL) flush logs; +create table t5 (a int); +drop table t5; start slave; flush logs; stop slave; @@ -56,9 +58,11 @@ master-bin.000001 1079 Query 1 1079 use `test`; drop table t1 master-bin.000001 1127 Rotate 1 1127 master-bin.000002;pos=4 show binlog events in 'master-bin.000002'; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.000002 4 Query 1 4 use `test`; create table t1 (n int) -master-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1) -master-bin.000002 122 Query 1 122 use `test`; drop table t1 +master-bin.000002 4 Query 1 4 use `test`; create table t5 (a int) +master-bin.000002 62 Query 1 62 use `test`; drop table t5 +master-bin.000002 110 Query 1 110 use `test`; create table t1 (n int) +master-bin.000002 168 Query 1 168 use `test`; insert into t1 values (1) +master-bin.000002 228 Query 1 228 use `test`; drop table t1 show binary logs; Log_name master-bin.000001 @@ -79,14 +83,16 @@ slave-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not slave-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581 slave-bin.000001 1065 Exec_load 1 1056 ;file_id=1 slave-bin.000001 1088 Query 1 1079 use `test`; drop table t1 -slave-bin.000001 1136 Rotate 2 1136 slave-bin.000002;pos=4 +slave-bin.000001 1136 Query 1 4 use `test`; create table t5 (a int) +slave-bin.000001 1194 Query 1 62 use `test`; drop table t5 +slave-bin.000001 1242 Rotate 2 1242 slave-bin.000002;pos=4 show binlog events in 'slave-bin.000002' from 4; Log_name Pos Event_type Server_id Orig_log_pos Info -slave-bin.000002 4 Query 1 4 use `test`; create table t1 (n int) -slave-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1) -slave-bin.000002 122 Query 1 122 use `test`; drop table t1 +slave-bin.000002 4 Query 1 110 use `test`; create table t1 (n int) +slave-bin.000002 62 Query 1 168 use `test`; insert into t1 values (1) +slave-bin.000002 122 Query 1 228 use `test`; drop table t1 show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space -127.0.0.1 root MASTER_PORT 1 master-bin.000002 170 slave-relay-bin.000002 1469 master-bin.000002 Yes Yes 0 0 170 1473 +127.0.0.1 root MASTER_PORT 1 master-bin.000002 276 slave-relay-bin.000002 1531 master-bin.000002 Yes Yes 0 0 276 1535 show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test index cb30c14b70c..2a3cc5b7e8f 100644 --- a/mysql-test/t/lowercase_table.test +++ b/mysql-test/t/lowercase_table.test @@ -20,8 +20,6 @@ drop table t3; create table t1 (a int); select count(*) from T1; select count(*) from t1; ---error 1109 select count(T1.a) from t1; ---error 1109 select count(bags.a) from t1 as Bags; drop table t1; diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test index 369c62848f9..f64aa292d30 100644 --- a/mysql-test/t/rpl_log.test +++ b/mysql-test/t/rpl_log.test @@ -58,7 +58,7 @@ connection slave; # Note that the above 'slave start' will cause a 3rd rotate event (a fake one) # to go into the relay log (the master always sends a fake one when replication # starts). -slave start; +start slave; sync_with_master; flush logs; stop slave; diff --git a/sql/set_var.cc b/sql/set_var.cc index b772f6410f7..b197fb7f312 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -238,7 +238,6 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout", &slave_net_timeout); #endif -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", From bd49ae5f740f67998aa2b8d4e6738bed5bd6bd1f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Jun 2003 22:31:06 +0200 Subject: [PATCH 315/399] - When compiling the Max package incl. RAID support using gcc, make sure to set CXX=gcc (cannot link the code with g++) - this should help to recompile the RPM on Distributions using gcc 3 - Added a symlink /usr/sbin/rcmysql -> /etc/init.d/mysql --- support-files/mysql.spec.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index aab3e298e14..06ba2d63f45 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -254,6 +254,13 @@ export PATH # Build the 4.0 Max binary (includes BDB and UDFs and therefore # cannot be linked statically against the patched glibc) +# If we want to compile with RAID using gcc 3, we need to use +# gcc instead of g++ to avoid linking problems (RAID code is written in C++) +if gcc -v 2>&1 | grep 'version 3' > /dev/null 2>&1 +then + export CXX="gcc" +fi + BuildMySQL "--enable-shared \ --with-berkeley-db \ --with-innodb \ @@ -318,6 +325,10 @@ install -m644 $MBD/sql/mysqld.sym $RBR/usr/lib/mysql/mysqld.sym install -m644 $MBD/support-files/mysql-log-rotate $RBR/etc/logrotate.d/mysql install -m755 $MBD/support-files/mysql.server $RBR/etc/init.d/mysql +# Create a symlink "rcmysql", pointing to the init.script. SuSE users +# will appreciate that, as all services usually offer this. +ln -s ../../sbin/init.d/mysql $RPM_BUILD_ROOT/usr/sbin/rcmysql + # Create symbolic compatibility link safe_mysqld -> mysqld_safe # (safe_mysqld will be gone in MySQL 4.1) ln -sf ./mysqld_safe $RBR/usr/bin/safe_mysqld @@ -462,6 +473,7 @@ fi %attr(755, root, root) /usr/bin/safe_mysqld %attr(755, root, root) /usr/sbin/mysqld +%attr(755, root, root) /usr/sbin/rcmysql %attr(644, root, root) /usr/lib/mysql/mysqld.sym %attr(644, root, root) /etc/logrotate.d/mysql From 9b73c7097ad607e34b2faa9249e55f5afb90227e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 11:55:03 +0300 Subject: [PATCH 316/399] Fixed problem with alarms when reading too big packet --- sql/net_serv.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/net_serv.cc b/sql/net_serv.cc index c8c774d365f..0b332f84bac 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -431,13 +431,13 @@ net_real_write(NET *net,const char *packet,ulong len) big packet */ -static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed) +static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed, + ALARM *alarm_buff) { - ALARM alarm_buff; uint retry_count=0; - if (!thr_alarm_in_use(&alarmed)) + if (!thr_alarm_in_use(alarmed)) { - if (!thr_alarm(alarmed,net->timeout,&alarm_buff) || + if (!thr_alarm(alarmed,net->timeout,alarm_buff) || (!vio_is_blocking(net->vio) && vio_blocking(net->vio,TRUE) < 0)) return; /* Can't setup, abort */ } @@ -606,7 +606,7 @@ my_real_read(NET *net, ulong *complen) { #ifdef MYSQL_SERVER if (i == 1) - my_net_skip_rest(net, len, &alarmed); + my_net_skip_rest(net, len, &alarmed, &alarm_buff); #endif len= packet_error; /* Return error */ goto end; From cd7148472a6ed55acb64fd12068729096b29bd26 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 12:29:13 +0300 Subject: [PATCH 317/399] Print error if we can't delete an alarm More debugging variables Increment aborted_threads in case of killed or too big packet include/thr_alarm.h: made prototype more portable mysys/thr_alarm.c: Print error if we can't delete an alarm sql/mysqld.cc: Statistics variable (for debugging) sql/net_serv.cc: statistics variable (for debugging) sql/sql_parse.cc: Increment aborted_threads in case of killed or too big packet --- include/thr_alarm.h | 2 +- mysys/thr_alarm.c | 11 +++++------ sql/mysqld.cc | 2 +- sql/net_serv.cc | 7 ++++++- sql/sql_parse.cc | 7 +++++++ 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 439f046252f..8ff4472f700 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -100,7 +100,7 @@ typedef struct st_alarm { #define thr_alarm_init(A) (*(A))=0 #define thr_alarm_in_use(A) (*(A)!= 0) void init_thr_alarm(uint max_alarm); -bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); +my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); void thr_alarm_kill(pthread_t thread_id); void thr_end_alarm(thr_alarm_t *alarmed); void end_thr_alarm(my_bool free_structures); diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index a2647ec7399..1f9c4c3b068 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -127,7 +127,7 @@ void init_thr_alarm(uint max_alarms) Returns 0 if no more alarms are allowed (aborted by process) */ -bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) +my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) { ulong now; sigset_t old_mask; @@ -209,7 +209,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) ALARM *alarm_data; sigset_t old_mask; uint i; - bool found=0; + my_bool found=0; DBUG_ENTER("thr_end_alarm"); pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); @@ -230,10 +230,9 @@ void thr_end_alarm(thr_alarm_t *alarmed) DBUG_ASSERT(!*alarmed || found); if (!found) { -#ifdef MAIN - printf("Warning: Didn't find alarm %lx in queue of %d alarms\n", - (long) *alarmed, alarm_queue.elements); -#endif + if (*alarmed) + fprintf(stderr,"Warning: Didn't find alarm %lx in queue of %d alarms\n", + (long) *alarmed, alarm_queue.elements); DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n", (long) *alarmed)); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7289d0e72cf..8ed183e2f1f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -380,7 +380,7 @@ uint report_port = MYSQL_PORT; my_bool master_ssl = 0; ulong master_retry_count=0; -ulong bytes_sent = 0L, bytes_received = 0L; +ulong bytes_sent= 0L, bytes_received= 0L, net_big_packet_count= 0L; bool opt_endinfo,using_udf_functions, locked_in_memory; bool opt_using_transactions, using_update_log; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 3d5055b4f24..a3bb2525f9d 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -65,11 +65,13 @@ void sql_print_error(const char *format,...); #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 ulong bytes_sent, bytes_received, net_big_packet_count; extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received; #else #undef statistic_add +#undef statistic_increment #define statistic_add(A,B,C) +#define statistic_increment(A,B) #endif #define TEST_BLOCKING 8 @@ -557,6 +559,9 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, DBUG_ENTER("my_net_skip_rest"); DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain)); + /* The following is good for debugging */ + statistic_increment(net_big_packet_count,&LOCK_bytes_received); + if (!thr_alarm_in_use(alarmed)) { my_bool old_mode; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d9060b4b26e..b06a48f9045 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -729,6 +729,10 @@ pthread_handler_decl(handle_one_connection,arg) send_error(net,net->last_errno,NullS); statistic_increment(aborted_threads,&LOCK_status); } + else if (thd->killed) + { + statistic_increment(aborted_threads,&LOCK_status); + } end_thread: close_connection(net); @@ -905,7 +909,10 @@ bool do_command(THD *thd) vio_description(net->vio))); /* Check if we can continue without closing the connection */ if (net->error != 3) + { + statistic_increment(aborted_threads,&LOCK_status); DBUG_RETURN(TRUE); // We have to close it. + } send_error(net,net->last_errno,NullS); net->error= 0; DBUG_RETURN(FALSE); From 5bc53e8a3b90820c8856d1b9974246ce939e8e8a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 15:06:19 +0300 Subject: [PATCH 318/399] Fixed a bug in concat_ws(), which did not add concat separator in case of an empty string. Bug ID 586. --- mysql-test/r/func_str.result | 2 +- sql/item_strfunc.cc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index a72d32d39f8..1a4cb9217e4 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -64,7 +64,7 @@ concat_ws(NULL,'a') concat_ws(',',NULL,'') NULL select concat_ws(',','',NULL,'a'); concat_ws(',','',NULL,'a') -a +,a SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"'); CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"') "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ae8bf1dfecb..208be1ecd7f 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -495,18 +495,18 @@ String *Item_func_concat_ws::val_str(String *str) str->length(0); // QQ; Should be removed res=str; - // Skip until non-null and non-empty argument is found. + // Skip until non-null argument is found. // If not, return the empty string for (i=0; i < arg_count; i++) - if ((res= args[i]->val_str(str)) && res->length()) + if ((res= args[i]->val_str(str))) break; if (i == arg_count) return &empty_string; for (i++; i < arg_count ; i++) { - if (!(res2= args[i]->val_str(use_as_buff)) || !res2->length()) - continue; // Skip NULL and empty string + if (!(res2= args[i]->val_str(use_as_buff))) + continue; // Skip NULL if (res->length() + sep_str->length() + res2->length() > current_thd->variables.max_allowed_packet) From 4916da252cc33867a5199269275054912315283b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 15:15:27 +0300 Subject: [PATCH 319/399] Fixed test if thr_alarm() failed --- sql/net_serv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 0b332f84bac..23a23dbde7b 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -437,7 +437,7 @@ static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed, uint retry_count=0; if (!thr_alarm_in_use(alarmed)) { - if (!thr_alarm(alarmed,net->timeout,alarm_buff) || + if (thr_alarm(alarmed,net->timeout,alarm_buff) || (!vio_is_blocking(net->vio) && vio_blocking(net->vio,TRUE) < 0)) return; /* Can't setup, abort */ } From 6d4ed167872eb6c29693fb0cbeaa79e0aecbe627 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 15:58:23 +0300 Subject: [PATCH 320/399] ha_innodb.cc, handler.cc: Fix the BDB crash in the previous push; to save CPU remove duplicate calls of commit in InnoDB sql/handler.cc: Fix the BDB crash in the previous push; to save CPU remove duplicate calls of commit in InnoDB sql/ha_innodb.cc: Fix the BDB crash in the previous push; to save CPU remove duplicate calls of commit in InnoDB --- sql/ha_innodb.cc | 229 +++++++++++++++++++++++++++++++---------------- sql/handler.cc | 34 ++----- 2 files changed, 158 insertions(+), 105 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 50bb4275eaa..9cc86edddf8 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -131,9 +131,11 @@ static void innobase_print_error(const char* db_errpfx, char* buffer); /********************************************************************** Releases possible search latch and InnoDB thread FIFO ticket. These should -be released at each SQL statement end. It does no harm to release these -also in the middle of an SQL statement. */ +be released at each SQL statement end, and also when mysqld passes the +control to the client. It does no harm to release these also in the middle +of an SQL statement. */ static +inline void innobase_release_stat_resources( /*============================*/ @@ -896,6 +898,11 @@ innobase_commit_low( /*================*/ trx_t* trx) /* in: transaction handle */ { + if (trx->conc_state == TRX_NOT_STARTED) { + + return; + } + /* TODO: Guilhem should check if master_log_name, pending etc. are right if the master log gets rotated! Possible bug here. Comment by Heikki March 4, 2003. */ @@ -910,11 +917,13 @@ innobase_commit_low( active_mi->rli.event_len + active_mi->rli.pending)); } - trx_commit_for_mysql(trx); + + trx_commit_for_mysql(trx); } /********************************************************************* -Commits a transaction in an InnoDB database. */ +Commits a transaction in an InnoDB database or marks an SQL statement +ended. */ int innobase_commit( @@ -932,29 +941,45 @@ innobase_commit( DBUG_ENTER("innobase_commit"); DBUG_PRINT("trans", ("ending transaction")); + /* The flag thd->transaction.all.innodb_active_trans is set to 1 + in ::external_lock and ::start_stmt, and it is only set to 0 in + a commit or a rollback. If it is 0 we know there cannot be resources + to be freed and we can return immediately. */ + + if (thd->transaction.all.innodb_active_trans == 0) { + + DBUG_RETURN(0); + } + trx = check_trx_exists(thd); - if (trx->auto_inc_lock) { - - /* If we had reserved the auto-inc lock for - some table in this SQL statement, we release it now */ - - srv_conc_enter_innodb(trx); - row_unlock_table_autoinc_for_mysql(trx); - srv_conc_exit_innodb(trx); - } - - if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) { + if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + innobase_commit_low(trx); - thd->transaction.all.innodb_active_trans=0; + + thd->transaction.all.innodb_active_trans = 0; + } else { + if (trx->auto_inc_lock) { + /* If we had reserved the auto-inc lock for some + table in this SQL statement we release it now */ + + srv_conc_enter_innodb(trx); + row_unlock_table_autoinc_for_mysql(trx); + srv_conc_exit_innodb(trx); + } + /* Store the current undo_no of the transaction so that we + know where to roll back if we have to roll back the next + SQL statement */ + + trx_mark_sql_stat_end(trx); } - /* Release possible statement level resources */ + /* Release a possible FIFO ticket and search latch */ innobase_release_stat_resources(trx); - trx_mark_sql_stat_end(trx); - /* Tell InnoDB server that there might be work for - utility threads: */ + /* Tell the InnoDB server that there might be work for utility + threads: */ srv_active_wake_master_thread(); @@ -1025,7 +1050,7 @@ innobase_commit_complete( } /********************************************************************* -Rolls back a transaction in an InnoDB database. */ +Rolls back a transaction or the latest SQL statement in an InnoDB database. */ int innobase_rollback( @@ -1066,11 +1091,9 @@ innobase_rollback( srv_conc_exit_innodb(trx); - /* Release possible statement level resources */ + /* Release a possible FIFO ticket and search latch */ innobase_release_stat_resources(trx); - trx_mark_sql_stat_end(trx); - DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); } @@ -2994,6 +3017,8 @@ create_index( KEY* key; KEY_PART_INFO* key_part; ulint ind_type; + ulint col_type; + ulint prefix_len; ulint i; DBUG_ENTER("create_index"); @@ -3021,10 +3046,32 @@ create_index( for (i = 0; i < n_fields; i++) { key_part = key->key_part + i; + if (key_part->length != key_part->field->pack_length()) { + prefix_len = key_part->length; + + col_type = get_innobase_type_from_mysql_type( + key_part->field); + if (col_type == DATA_INT + || col_type == DATA_FLOAT + || col_type == DATA_DOUBLE + || col_type == DATA_DECIMAL) { + fprintf(stderr, +"InnoDB: error: MySQL is trying to create a column prefix index field\n" +"InnoDB: on an inappropriate data type %lu. Table name %s, column name %s.\n", + col_type, table_name, + key_part->field->field_name); + + prefix_len = 0; + } + } else { + prefix_len = 0; + } + /* We assume all fields should be sorted in ascending order, hence the '0': */ dict_mem_index_add_field(index, - (char*) key_part->field->field_name, 0); + (char*) key_part->field->field_name, + 0, prefix_len); } error = row_create_index_for_mysql(index, trx); @@ -3562,8 +3609,7 @@ ha_innobase::records_in_range( /************************************************************************* Gives an UPPER BOUND to the number of rows in a table. This is used in -filesort.cc and its better if the upper bound hold. -*/ +filesort.cc. */ ha_rows ha_innobase::estimate_number_of_rows(void) @@ -3598,11 +3644,11 @@ ha_innobase::estimate_number_of_rows(void) /* Calculate a minimum length for a clustered index record and from that an upper bound for the number of rows. Since we only calculate - new statistics in row0mysql.c when a tablehas grown - by a threshold factor, we must add a safety factor 2 in front - of the formula below. */ + new statistics in row0mysql.c when a table has grown by a threshold + factor, we must add a safety factor 2 in front of the formula below. */ - estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index); + estimate = 2 * local_data_file_length / + dict_index_calc_min_rec_len(index); prebuilt->trx->op_info = (char*)""; @@ -3629,27 +3675,36 @@ 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. -*/ +/********************************************************************** +Calculate the time it takes to read a set of ranges through an index +This enables us to optimise reads for clustered indexes. */ -double ha_innobase::read_time(uint index, uint ranges, ha_rows rows) +double +ha_innobase::read_time( +/*===================*/ + /* out: estimated time measured in disk seeks */ + uint index, /* in: key number */ + uint ranges, /* in: how many ranges */ + ha_rows rows) /* in: estimated number of rows in the ranges */ { - 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); + 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 time is proportional to the scan time for all + rows + at most 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); } /************************************************************************* @@ -3992,10 +4047,10 @@ ha_innobase::reset(void) } /********************************************************************** -Inside LOCK TABLES MySQL will not call external_lock() between SQL -statements. It will call this function at the start of each SQL statement. -Note also a spacial case: if a temporary table is created inside LOCK -TABLES, MySQL has not called external_lock() at all on that table. */ +MySQL calls this function at the start of each SQL statement. Inside LOCK +TABLES the ::external_lock method does not work to mark SQL statement +borders. Note also a special case: if a temporary table is created inside +LOCK TABLES, MySQL has not called external_lock() at all on that table. */ int ha_innobase::start_stmt( @@ -4010,8 +4065,14 @@ ha_innobase::start_stmt( trx = prebuilt->trx; + /* Here we release the search latch and the InnoDB thread FIFO ticket + if they were reserved. They should have been released already at the + end of the previous statement, but because inside LOCK TABLES the + lock count method does not work to mark the end of a SELECT statement, + that may not be the case. We MUST release the search latch before an + INSERT, for example. */ + innobase_release_stat_resources(trx); - trx_mark_sql_stat_end(trx); if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && trx->read_view) { @@ -4034,7 +4095,8 @@ ha_innobase::start_stmt( prebuilt->select_lock_type = LOCK_X; } - + + /* Set the MySQL flag to mark that there is an active transaction */ thd->transaction.all.innodb_active_trans = 1; return(0); @@ -4098,17 +4160,20 @@ ha_innobase::external_lock( } if (lock_type != F_UNLCK) { - if (trx->n_mysql_tables_in_use == 0) { - trx_mark_sql_stat_end(trx); - } + /* MySQL is setting a new table lock */ + /* Set the MySQL flag to mark that there is an active + transaction */ thd->transaction.all.innodb_active_trans = 1; + trx->n_mysql_tables_in_use++; prebuilt->mysql_has_locked = TRUE; - trx->isolation_level = innobase_map_isolation_level( + if (trx->n_mysql_tables_in_use == 1) { + trx->isolation_level = innobase_map_isolation_level( (enum_tx_isolation) thd->variables.tx_isolation); + } if (trx->isolation_level == TRX_ISO_SERIALIZABLE && prebuilt->select_lock_type == LOCK_NONE) { @@ -4124,37 +4189,44 @@ ha_innobase::external_lock( trx->mysql_n_tables_locked++; } - } else { - trx->n_mysql_tables_in_use--; - prebuilt->mysql_has_locked = FALSE; - auto_inc_counter_for_this_stat = 0; - if (trx->n_mysql_tables_in_use == 0) { + DBUG_RETURN(error); + } - trx->mysql_n_tables_locked = 0; + /* MySQL is releasing a table lock */ - prebuilt->used_in_HANDLER = FALSE; + trx->n_mysql_tables_in_use--; + prebuilt->mysql_has_locked = FALSE; + auto_inc_counter_for_this_stat = 0; - /* Here we release the search latch and InnoDB - thread FIFO ticket if they were reserved. */ + /* If the MySQL lock count drops to zero we know that the current SQL + statement has ended */ - innobase_release_stat_resources(trx); + if (trx->n_mysql_tables_in_use == 0) { + trx->mysql_n_tables_locked = 0; + prebuilt->used_in_HANDLER = FALSE; + + if (!(thd->options + & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { + if (thd->transaction.all.innodb_active_trans != 0) { + innobase_commit(thd, trx); + } + } else { if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && trx->read_view) { - /* At low transaction isolation levels we let + /* At low transaction isolation levels we let each consistent read set its own snapshot */ - read_view_close_for_mysql(trx); + read_view_close_for_mysql(trx); } - - if (!(thd->options - & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - - innobase_commit(thd, trx); - } } + + /* Here we release the search latch and the InnoDB thread FIFO + ticket if they were reserved. */ + + innobase_release_stat_resources(trx); } DBUG_RETURN(error); @@ -4473,4 +4545,3 @@ ha_innobase::get_auto_increment() } #endif /* HAVE_INNOBASE_DB */ - diff --git a/sql/handler.cc b/sql/handler.cc index 6ee0b1f9c55..cae1777e958 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -209,44 +209,26 @@ void ha_close_connection(THD* thd) /* This is used to commit or rollback a single statement depending on the value - of error. If the autocommit is on, then we will commit or rollback the whole - transaction (= the statement). The autocommit mechanism built into handlers - is based on counting locks, but if the user has used LOCK TABLES then that - mechanism does not know to do the commit. + of error. Note that if the autocommit is on, then the following call inside + InnoDB will commit or rollback the whole transaction (= the statement). The + autocommit mechanism built into InnoDB is based on counting locks, but if + the user has used LOCK TABLES then that mechanism does not know to do the + commit. */ int ha_autocommit_or_rollback(THD *thd, int error) { - bool do_autocommit=FALSE; - DBUG_ENTER("ha_autocommit_or_rollback"); #ifdef USING_TRANSACTIONS - - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) - do_autocommit=TRUE; /* We can commit or rollback the whole transaction */ - if (opt_using_transactions) { if (!error) { - if (do_autocommit) - { - if (ha_commit(thd)) - error=1; - } - else - { - if (ha_commit_stmt(thd)) - error=1; - } + if (ha_commit_stmt(thd)) + error=1; } else - { - if (do_autocommit) - (void) ha_rollback(thd); - else - (void) ha_rollback_stmt(thd); - } + (void) ha_rollback_stmt(thd); thd->variables.tx_isolation=thd->session_tx_isolation; } From d3d86c127a0740a7f44255d138c75e42195a47c0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 16:06:38 +0300 Subject: [PATCH 321/399] ha_innodb.cc: Revert a change to dict_mem_index_add_field which slipped prematurely into the bk tree sql/ha_innodb.cc: Revert a change to dict_mem_index_add_field which slipped prematurely into the bk tree --- sql/ha_innodb.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 9cc86edddf8..fd030fff091 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3070,8 +3070,7 @@ create_index( /* We assume all fields should be sorted in ascending order, hence the '0': */ dict_mem_index_add_field(index, - (char*) key_part->field->field_name, - 0, prefix_len); + (char*) key_part->field->field_name, 0); } error = row_create_index_for_mysql(index, trx); From 35cd3cbac79731d04a10e08bf8b7ab27cfc4c046 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 16:56:38 +0300 Subject: [PATCH 322/399] mysqld won't give a warning any more, if --user=user_name is used, if 'user_name' is the current user and it is not root. --- sql/mysqld.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8ed183e2f1f..315931094c2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1013,14 +1013,21 @@ static void set_ports() static void set_user(const char *user) { #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) - struct passwd *ent; + struct passwd *ent; + uid_t user_id= geteuid(); // don't bother if we aren't superuser - if (geteuid()) + if (user_id) { if (user) - fprintf(stderr, - "Warning: One can only use the --user switch if running as root\n"); + { + /* Don't give a warning, if real user is same as given with --user */ + struct passwd *user_info= getpwnam(user); + + if (!user_info || user_id != user_info->pw_uid) + fprintf(stderr, + "Warning: One can only use the --user switch if running as root\n"); + } return; } else if (!user) From a3afb2bcbea96d4c5a326204151fb63cd0411aec Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 17:25:09 +0300 Subject: [PATCH 323/399] Added function comment --- mysys/thr_alarm.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 1f9c4c3b068..7a845e3eb00 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -122,9 +122,21 @@ void init_thr_alarm(uint max_alarms) /* Request alarm after sec seconds. - A pointer is returned with points to a non-zero int when the alarm has been - given. This can't be called from the alarm-handling thread. - Returns 0 if no more alarms are allowed (aborted by process) + + SYNOPSIS + thr_alarm() + alrm Pointer to alarm detection + alarm_data Structure to store in alarm queue + + NOTES + This function can't be called from the alarm-handling thread. + + RETURN VALUES + 0 ok + 1 If no more alarms are allowed (aborted by process) + + Stores in first argument a pointer to a non-zero int which is set to 0 + when the alarm has been given */ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) From d9a6a9aca610e715d0b0698c1447f6550e6f7965 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 16:19:54 -0400 Subject: [PATCH 324/399] fixed bug (writting outside mallocced buffer in sql_help.cc) sql/sql_help.cc: fixed bug (writting outside mallocced buffer) --- sql/sql_help.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 9003d4b36cd..ba7c08ff15f 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -553,14 +553,14 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, String **pointers= (String**)alloc_root(mem_root, sizeof(String*)*names->elements); - String **pos= pointers; + String **pos; + String **end= pointers + names->elements; List_iterator it(*names); - while ((*pos++= it++)); + for ( pos= pointers; pos!=end; (*pos++= it++)); qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); - String **end= pointers + names->elements; for (pos= pointers; pos!=end; pos++) { protocol->prepare_for_resend(); From 824dd7f54587b602140bcb5af16454608538aa0a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Jun 2003 23:19:56 +0300 Subject: [PATCH 325/399] After merge fixes mysql-test/r/repair_part1.result: Rename: mysql-test/r/repair.result -> mysql-test/r/repair_part1.result mysql-test/t/repair_part1.test: Rename: mysql-test/t/repair.test -> mysql-test/t/repair_part1.test include/sql_common.h: Declare not_error_sqlstate scripts/Makefile.am: Added back fill_help_tables.sql --- include/sql_common.h | 1 + .../r/{repair.result => repair_part1.result} | 0 .../t/{repair.test => repair_part1.test} | 0 scripts/Makefile.am | 5 +- sql-common/client.c | 54 +++++++++---------- 5 files changed, 31 insertions(+), 29 deletions(-) rename mysql-test/r/{repair.result => repair_part1.result} (100%) rename mysql-test/t/{repair.test => repair_part1.test} (100%) diff --git a/include/sql_common.h b/include/sql_common.h index 3a668a8dd41..65283486fb4 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -16,6 +16,7 @@ extern const char *unknown_sqlstate; +extern const char *not_error_sqlstate; #ifdef __cplusplus extern "C" { diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair_part1.result similarity index 100% rename from mysql-test/r/repair.result rename to mysql-test/r/repair_part1.result diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair_part1.test similarity index 100% rename from mysql-test/t/repair.test rename to mysql-test/t/repair_part1.test diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 29cfad11220..6006222992e 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -33,7 +33,6 @@ bin_SCRIPTS = @server_scripts@ \ mysql_explain_log \ mysql_tableinfo \ mysqld_multi \ - fill_help_tables \ mysql_create_system_tables EXTRA_SCRIPTS = make_binary_distribution.sh \ @@ -140,5 +139,7 @@ SUFFIXES = .sh # Don't update the files from bitkeeper %::SCCS/s.% -all: make_win_src_distribution make_binary_distribution +all: fill_help_tables.sql make_win_src_distribution make_binary_distribution +fill_help_tables.sql: fill_help_tables ../Docs/manual.texi + ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql diff --git a/sql-common/client.c b/sql-common/client.c index 55013d4bd82..cba552544f5 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -99,7 +99,8 @@ #include "client_settings.h" #include -const char *unknown_sqlstate= "000000"; +const char *unknown_sqlstate= "HY0000"; +const char *not_error_sqlstate= "00000"; #ifdef MYSQL_CLIENT extern my_bool stmt_close(MYSQL_STMT *stmt,my_bool skip_list); @@ -339,10 +340,10 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) /* The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part + shared_memory_base_name+unique_part Where: - shared_memory_base_name is unique value for each server - unique_part is uniquel value for each object (events and file-mapping) + shared_memory_base_name is unique value for each server + unique_part is uniquel value for each object (events and file-mapping) */ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS); strmov(suffix_pos, "CONNECT_REQUEST"); @@ -369,36 +370,34 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; goto err; } - /* - Send to server request of connection - */ + + /* Send to server request of connection */ if (!SetEvent(event_connect_request)) { error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR; goto err; } - /* - Wait of answer from server - */ + + /* Wait of answer from server */ if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != WAIT_OBJECT_0) { error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR; goto err; } - /* - Get number of connection - */ + + /* Get number of connection */ connect_number = uint4korr(handle_connect_map);/*WAX2*/ p= int2str(connect_number, connect_number_char, 10); /* The name of event and file-mapping events create agree next rule: shared_memory_base_name+unique_part+number_of_connection + Where: - shared_memory_base_name is uniquel value for each server - unique_part is uniquel value for each object (events and file-mapping) - number_of_connection is number of connection between server and client + shared_memory_base_name is uniquel value for each server + unique_part is uniquel value for each object (events and file-mapping) + number_of_connection is number of connection between server and client */ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char, "_",NullS); @@ -506,7 +505,7 @@ net_safe_read(MYSQL *mysql) { NET *net= &mysql->net; ulong len=0; - init_sigpipe_variables + init_sigpipe_variables; /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); @@ -571,7 +570,7 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, { NET *net= &mysql->net; my_bool result= 1; - init_sigpipe_variables + init_sigpipe_variables; /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); @@ -589,8 +588,8 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, } net->last_error[0]=0; - net->last_errno=0; - strmov(net->sqlstate, unknown_sqlstate); + net->last_errno= 0; + strmov(net->sqlstate, not_error_sqlstate); mysql->net.report_error=0; mysql->info=0; mysql->affected_rows= ~(my_ulonglong) 0; @@ -624,7 +623,7 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, if (!skip_check) result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ? 1 : 0); - end: +end: reset_sigpipe(mysql); return result; } @@ -665,7 +664,7 @@ void end_server(MYSQL *mysql) DBUG_ENTER("end_server"); if (mysql->net.vio != 0) { - init_sigpipe_variables + init_sigpipe_variables; DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); set_sigpipe(mysql); vio_delete(mysql->net.vio); @@ -1457,7 +1456,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif - init_sigpipe_variables + init_sigpipe_variables; DBUG_ENTER("mysql_real_connect"); LINT_INIT(host_info); @@ -1561,7 +1560,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; - strmov(UNIXaddr.sun_path, unix_socket); + strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1); if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), mysql->options.connect_timeout)) { @@ -2090,15 +2089,16 @@ static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) #endif /*MYSQL_CLIENT*/ } + my_bool mysql_reconnect(MYSQL *mysql) { MYSQL tmp_mysql; DBUG_ENTER("mysql_reconnect"); - if (!mysql->reconnect - || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) + if (!mysql->reconnect || + (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { - /* Allow reconnect next time */ + /* Allow reconnect next time */ mysql->server_status&= ~SERVER_STATUS_IN_TRANS; strmov(mysql->net.sqlstate, unknown_sqlstate); mysql->net.last_errno=CR_SERVER_GONE_ERROR; From 3177fb553b5b1d680e8571116b7facf186316ee5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Jun 2003 10:50:13 +0500 Subject: [PATCH 326/399] my_global.h: ulong was used before the line it have been declared include/my_global.h: ulong was used before the line it have been declared --- include/my_global.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 6d6f24c2438..9de8e310d79 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -660,8 +660,6 @@ typedef long my_ptrdiff_t; typedef long long my_ptrdiff_t; #endif -/* typedef used for length of string; Should be unsigned! */ -typedef ulong size_str; #define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) #define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) @@ -739,6 +737,8 @@ typedef unsigned __int64 my_ulonglong; typedef unsigned long long my_ulonglong; #endif +/* typedef used for length of string; Should be unsigned! */ +typedef ulong size_str; #ifdef USE_RAID /* From ac366a4ba59a4422aed2b1a0d3963794b997f668 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Jun 2003 11:06:45 +0500 Subject: [PATCH 327/399] client.c: Compilation falure fix sql-common/client.c: Compilation falure fix --- sql-common/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-common/client.c b/sql-common/client.c index cba552544f5..3c025d18bd6 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1456,7 +1456,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif - init_sigpipe_variables; + init_sigpipe_variables DBUG_ENTER("mysql_real_connect"); LINT_INIT(host_info); From d1a1d24c1f95bd50a8105f120a284ff4bf4ccdd6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Jun 2003 17:43:23 +0500 Subject: [PATCH 328/399] REVOKE all privileges and delete user(244) include/mysqld_error.h: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT mysql-test/r/grant.result: Test for DROP USER, REVOKE ALL PRIVILEGES, GRANT mysql-test/t/grant.test: Test for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/czech/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/danish/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/dutch/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/english/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/estonian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/french/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/german/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/greek/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/hungarian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/italian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/japanese/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/korean/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/norwegian-ny/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/norwegian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/polish/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/portuguese/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/romanian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/russian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/serbian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/slovak/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/spanish/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/swedish/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT sql/share/ukrainian/errmsg.txt: Error messages for DROP USER, REVOKE ALL PRIVILEGES, GRANT --- include/mysqld_error.h | 2 + mysql-test/r/grant.result | 35 ++++ mysql-test/t/grant.test | 38 ++++ sql/lex.h | 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/polish/errmsg.txt | 2 + sql/share/portuguese/errmsg.txt | 2 + sql/share/romanian/errmsg.txt | 2 + sql/share/russian/errmsg.txt | 2 + sql/share/serbian/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 + sql/sql_acl.cc | 288 ++++++++++++++++++++++++++++-- sql/sql_acl.h | 2 + sql/sql_lex.h | 2 +- sql/sql_parse.cc | 32 ++++ sql/sql_yacc.yy | 30 +++- 32 files changed, 456 insertions(+), 21 deletions(-) diff --git a/include/mysqld_error.h b/include/mysqld_error.h index d2fc5bbc77f..ccccb188037 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -282,4 +282,6 @@ #define ER_WARN_DATA_TRUNCATED 1263 #define ER_WARN_USING_OTHER_HANDLER 1264 #define ER_CANT_AGGREGATE_COLLATIONS 1265 +#define ER_DROP_USER 1266 +#define ER_REVOKE_GRANTS 1267 #define ER_ERROR_MESSAGES 266 diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index c1dcd5c29e9..715deac7965 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1,3 +1,5 @@ +drop table if exists t1; +create table t1 (a int); delete from mysql.user where user='mysqltest_1'; delete from mysql.db where user='mysqltest_1'; flush privileges; @@ -69,3 +71,36 @@ show grants for user@localhost; Grants for user@localhost GRANT USAGE ON *.* TO 'user'@'localhost' GRANT USAGE ON `test`.* TO 'user'@'localhost' WITH GRANT OPTION +grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION; +show grants for drop_user2@localhost; +Grants for drop_user2@localhost +GRANT ALL PRIVILEGES ON *.* TO 'drop_user2'@'localhost' WITH GRANT OPTION +revoke all privileges, grant from drop_user2@localhost; +drop user drop_user2@localhost; +grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION; +grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION; +grant select(a) on test.t1 to drop_user@localhost; +show grants for drop_user@localhost; +Grants for drop_user@localhost +GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION +GRANT ALL PRIVILEGES ON `test`.* TO 'drop_user'@'localhost' WITH GRANT OPTION +GRANT SELECT (a) ON `test`.`t1` TO 'drop_user'@'localhost' +revoke all privileges, grant from drop_user@localhost; +show grants for drop_user@localhost; +Grants for drop_user@localhost +GRANT USAGE ON *.* TO 'drop_user'@'localhost' +drop user drop_user@localhost; +revoke all privileges, grant from drop_user@localhost; +Can't revoke all privileges, grant for one or more of the requested users +grant select(a) on test.t1 to drop_user1@localhost; +grant select on test.t1 to drop_user2@localhost; +grant select on test.* to drop_user3@localhost; +grant select on *.* to drop_user4@localhost; +drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, +drop_user4@localhost; +Can't drop one or more of the requested users +revoke all privileges, grant from drop_user1@localhost, drop_user2@localhost, +drop_user3@localhost, drop_user4@localhost; +drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, +drop_user4@localhost; +drop table t1; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index bd04b2e4c41..dcddbc99efa 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1,3 +1,9 @@ +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 (a int); + # # Test that SSL options works properly # @@ -42,3 +48,35 @@ flush privileges; grant usage on test.* to user@localhost with grant option; show grants for user@localhost; +# +# Test for 'drop user', 'revoke privileges, grant' +# + +grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION; +show grants for drop_user2@localhost; +revoke all privileges, grant from drop_user2@localhost; +drop user drop_user2@localhost; + +grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION; +grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION; +grant select(a) on test.t1 to drop_user@localhost; +show grants for drop_user@localhost; +revoke all privileges, grant from drop_user@localhost; +show grants for drop_user@localhost; +drop user drop_user@localhost; +--error 1267 +revoke all privileges, grant from drop_user@localhost; + +grant select(a) on test.t1 to drop_user1@localhost; +grant select on test.t1 to drop_user2@localhost; +grant select on test.* to drop_user3@localhost; +grant select on *.* to drop_user4@localhost; +--error 1266 +drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, +drop_user4@localhost; +revoke all privileges, grant from drop_user1@localhost, drop_user2@localhost, +drop_user3@localhost, drop_user4@localhost; +drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, +drop_user4@localhost; + +drop table t1; diff --git a/sql/lex.h b/sql/lex.h index e89c9f51520..064bab8acbb 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -396,6 +396,7 @@ static SYMBOL symbols[] = { { "UNSIGNED", SYM(UNSIGNED),0,0}, { "USE", SYM(USE_SYM),0,0}, { "USE_FRM", SYM(USE_FRM),0,0}, + { "USER", SYM(USER),0,0}, { "USING", SYM(USING),0,0}, { "UPDATE", SYM(UPDATE_SYM),0,0}, { "USAGE", SYM(USAGE),0,0}, @@ -632,7 +633,6 @@ static SYMBOL sql_functions[] = { { "UNIQUE_USERS", SYM(UNIQUE_USERS),0,0}, { "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0}, { "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, - { "USER", SYM(USER),0,0}, { "VARIANCE", SYM(VARIANCE_SYM),0,0}, { "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)}, { "WEEK", SYM(WEEK_SYM),0,0}, diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index e277c19e26f..273dfa0fcf5 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -271,3 +271,5 @@ v/* "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 01856ffed01..1d39a328154 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -265,3 +265,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 4b9b0b9f710..5b79f06b621 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -273,3 +273,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 89045b13985..ad15d55405f 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -267,3 +267,5 @@ "Data truncated for column '%s' at row %ld" "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index d5064b53790..506b5fc0188 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -267,3 +267,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index eb936243332..8882e4dceda 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -262,3 +262,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 2ac25216b8e..1e8f5bb2c05 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -271,3 +271,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 8e82559db5c..d322f3fbd6a 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -262,3 +262,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index de0e7da614e..162bfc5509c 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -264,3 +264,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index d9308faf8a6..26d916a968d 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -262,3 +262,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 45e78941906..a01a2b7ff6f 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -264,3 +264,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 43d291ae3a5..5f5526be04b 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -262,3 +262,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index c0c045438ec..bf1019d3d87 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -264,3 +264,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 03430ae546b..68c95bbf22b 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -264,3 +264,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 997ee08e66a..5b93403c757 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -266,3 +266,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index ef051d957cb..edd3e3b813f 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -262,3 +262,5 @@ "%d linha(s) foi(foram) cortada(s) por group_concat()", "Usando engine de armazenamento %s para tabela '%s'", "Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 89c00b4bf15..873a708fa7b 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -266,3 +266,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index fac4dedb3ee..a05ecde6808 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -264,3 +264,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index d954e7998a2..c1c0de779c7 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -258,3 +258,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 8f7747c6bf6..26d673b847c 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -270,3 +270,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 4a7989ce7be..99a92f63c4e 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -263,3 +263,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 6734369d3ac..c613d205947 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -262,3 +262,5 @@ "%d rad(er) kapades av group_concat()", "Använder handler %s för tabell '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 67c52dc8fee..6505c3c9cac 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -267,3 +267,5 @@ "%d line(s) was(were) cut by group_concat()", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", +"Can't drop one or more of the requested users" +"Can't revoke all privileges, grant for one or more of the requested users" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ec6db64ea73..49aad321702 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2179,11 +2179,6 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { int error; GRANT_TABLE *grant_table; - if (!Str->host.str) - { - Str->host.str=(char*) "%"; - Str->host.length=1; - } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -2350,11 +2345,6 @@ int mysql_grant (THD *thd, const char *db, List &list, int result=0; while ((Str = str_list++)) { - if (!Str->host.str) - { - Str->host.str=(char*) "%"; - Str->host.length=1; - } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -2855,11 +2845,6 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) send_error(thd, ER_UNKNOWN_COM_ERROR); DBUG_RETURN(-1); } - if (!lex_user->host.str) - { - lex_user->host.str=(char*) "%"; - lex_user->host.length=1; - } if (lex_user->host.length > HOSTNAME_LENGTH || lex_user->user.length > USERNAME_LENGTH) { @@ -3202,6 +3187,279 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) bzero((char*) &uc->user_resources, sizeof(uc->user_resources)); } +int open_grant_tables(THD *thd, TABLE_LIST *tables) +{ + DBUG_ENTER("open_grant_tables"); + + if (!initialized) + { + send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES)); + DBUG_RETURN(-1); + } + + bzero((char*) tables, 4*sizeof(*tables)); + tables->alias= tables->real_name= (char*) "user"; + (tables+1)->alias= (tables+1)->real_name= (char*) "db"; + (tables+2)->alias= (tables+2)->real_name= (char*) "tables_priv"; + (tables+3)->alias= (tables+3)->real_name= (char*) "columns_priv"; + tables->next= tables+1; + (tables+1)->next= tables+2; + (tables+2)->next= tables+3; + (tables+3)->next= 0; + tables->lock_type= (tables+1)->lock_type= + (tables+2)->lock_type= (tables+3)->lock_type= TL_WRITE; + tables->db= (tables+1)->db= (tables+2)->db= (tables+3)->db=(char*) "mysql"; + +#ifdef HAVE_REPLICATION + /* + GRANT and REVOKE are applied the slave in/exclusion rules as they are + some kind of updates to the mysql.% tables. + */ + if (thd->slave_thread && table_rules_on && !tables_ok(0, tables)) + DBUG_RETURN(1); +#endif + + if (open_and_lock_tables(thd, tables)) + { // This should never happen + close_thread_tables(thd); + DBUG_RETURN(-1); + } + + DBUG_RETURN(0); +} + +ACL_USER *check_acl_user(LEX_USER *user_name, + uint *acl_user_idx) +{ + ACL_USER *acl_user= 0; + uint counter; + + for (counter= 0 ; counter < acl_users.elements ; counter++) + { + const char *user,*host; + acl_user= dynamic_element(&acl_users, counter, ACL_USER*); + if (!(user=acl_user->user)) + user=""; + if (!(host=acl_user->host.hostname)) + host="%"; + if (!strcmp(user_name->user.str,user) && + !my_strcasecmp(system_charset_info, user_name->host.str, host)) + break; + } + if (counter == acl_users.elements) + return 0; + + *acl_user_idx= counter; + return acl_user; +} + +int mysql_drop_user(THD *thd, List &list) +{ + uint counter, user_id; + int result; + ACL_USER *acl_user; + ACL_DB *acl_db; + TABLE_LIST tables[4]; + + DBUG_ENTER("mysql_drop_user"); + + if ((result= open_grant_tables(thd, tables))) + DBUG_RETURN(result == 1 ? 0 : -1); + + rw_wrlock(&LOCK_grant); + VOID(pthread_mutex_lock(&acl_cache->lock)); + + LEX_USER *user_name; + List_iterator user_list(list); + while ((user_name=user_list++)) + { + if (!(acl_user= check_acl_user(user_name, &counter))) + { + sql_print_error("DROP USER: Can't drop user: '%s'@'%s'", + user_name->user.str, + user_name->host.str); + result= -1; + continue; + } + if ((acl_user->access & ~0)) + { + sql_print_error("DROP USER: Can't drop user: '%s'@'%s'", + user_name->user.str, + user_name->host.str); + result= -1; + continue; + } + user_id= counter; + + for (counter= 0 ; counter < acl_dbs.elements ; counter++) + { + const char *user,*host; + acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); + if (!(user= acl_db->user)) + user=""; + if (!(host= acl_db->host.hostname)) + host=""; + + if (!strcmp(user_name->user.str,user) && + !my_strcasecmp(system_charset_info, user_name->host.str, host)) + break; + } + if (counter != acl_dbs.elements) + { + sql_print_error("DROP USER: Can't drop user: '%s'@'%s'", + user_name->user.str, + user_name->host.str); + result= -1; + continue; + } + + for (counter= 0 ; counter < column_priv_hash.records ; counter++) + { + const char *user,*host; + GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, + counter); + if (!(user=grant_table->user)) + user=""; + if (!(host=grant_table->host)) + host=""; + + if (!strcmp(user_name->user.str,user) && + !my_strcasecmp(system_charset_info, user_name->host.str, host)) + break; + } + if (counter != column_priv_hash.records) + { + sql_print_error("DROP USER: Can't drop user: '%s'@'%s'", + user_name->user.str, + user_name->host.str); + result= -1; + continue; + } + + tables[0].table->field[0]->store(user_name->host.str,(uint) + user_name->host.length, system_charset_info); + tables[0].table->field[1]->store(user_name->user.str,(uint) + user_name->user.length, system_charset_info); + if (!tables[0].table->file->index_read_idx(tables[0].table->record[0],0, + (byte*) tables[0].table->field[0]->ptr,0, + HA_READ_KEY_EXACT)) + { + int error; + if ((error = tables[0].table->file->delete_row(tables[0].table->record[0]))) + { + tables[0].table->file->print_error(error, MYF(0)); + tables[0].table->file->index_end(); + DBUG_RETURN(-1); + } + delete_dynamic_element(&acl_users, user_id); + } + tables[0].table->file->index_end(); + } +err: + VOID(pthread_mutex_unlock(&acl_cache->lock)); + rw_unlock(&LOCK_grant); + close_thread_tables(thd); + if (result) + my_error(ER_DROP_USER, MYF(0)); + DBUG_RETURN(result); +} + +int mysql_revoke_all(THD *thd, List &list) +{ + uint counter; + int result; + ACL_USER *acl_user; ACL_DB *acl_db; + TABLE_LIST tables[4]; + DBUG_ENTER("mysql_revoke_all"); + + if ((result= open_grant_tables(thd, tables))) + DBUG_RETURN(result == 1 ? 0 : -1); + + rw_wrlock(&LOCK_grant); + VOID(pthread_mutex_lock(&acl_cache->lock)); + + LEX_USER *lex_user; + List_iterator user_list(list); + while ((lex_user=user_list++)) + { + if (!(acl_user= check_acl_user(lex_user, &counter))) + { + sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists", + lex_user->user.str, + lex_user->host.str); + result= -1; + continue; + } + + if (replace_user_table(thd, tables[0].table, + *lex_user, ~0, 1, 0)) + { + result= -1; + continue; + } + + /* Remove db access privileges */ + for (counter= 0 ; counter < acl_dbs.elements ; counter++) + { + const char *user,*host; + + acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); + if (!(user=acl_db->user)) + user=""; + if (!(host=acl_db->host.hostname)) + host=""; + + if (!strcmp(lex_user->user.str,user) && + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + { + if (replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1)) + result= -1; + } + } + + /* Remove column access */ + for (counter= 0 ; counter < column_priv_hash.records ; counter++) + { + const char *user,*host; + GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, + counter); + if (!(user=grant_table->user)) + user=""; + if (!(host=grant_table->host)) + host=""; + + if (!strcmp(lex_user->user.str,user) && + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + { + if (replace_table_table(thd,grant_table,tables[2].table,*lex_user, + grant_table->db, + grant_table->tname, + ~0, 0, 1)) + { + result= -1; + continue; + } + if (grant_table->cols) + { + List columns; + if (replace_column_table(grant_table,tables[3].table, *lex_user, + columns, + grant_table->db, + grant_table->tname, + ~0, 1)) + result= -1; + } + } + } + } + + VOID(pthread_mutex_unlock(&acl_cache->lock)); + rw_unlock(&LOCK_grant); + close_thread_tables(thd); + if (result) + my_error(ER_REVOKE_GRANTS, MYF(0)); + DBUG_RETURN(result); +} /***************************************************************************** diff --git a/sql/sql_acl.h b/sql/sql_acl.h index d85a281cbb5..e6c6771253c 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -163,3 +163,5 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field); int mysql_show_grants(THD *thd, LEX_USER *user); void get_privilege_desc(char *to, uint max_length, ulong access); void get_mqh(const char *user, const char *host, USER_CONN *uc); +int mysql_drop_user(THD *thd, List &list); +int mysql_revoke_all(THD *thd, List &list); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f31b3305e07..a01c98bb283 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -71,7 +71,7 @@ enum enum_sql_command { SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES, - SQLCOM_HELP, + SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, /* This should be the last !!! */ SQLCOM_END diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9ebb6305f70..fd3d359f0c8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2897,6 +2897,38 @@ mysql_execute_command(THD *thd) res= -1; #endif break; + case SQLCOM_DROP_USER: + { + if (check_access(thd, GRANT_ACL,"mysql",0,1)) + break; + if (!(res= mysql_drop_user(thd, lex->users_list))) + { + mysql_update_log.write(thd, thd->query, thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } + send_ok(thd); + } + break; + } + case SQLCOM_REVOKE_ALL: + { + if (check_access(thd, GRANT_ACL ,"mysql",0,1)) + break; + if (!(res = mysql_revoke_all(thd, lex->users_list))) + { + mysql_update_log.write(thd, thd->query, thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } + send_ok(thd); + } + break; + } case SQLCOM_REVOKE: case SQLCOM_GRANT: { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1002d06be88..fbc7e9deb36 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3215,7 +3215,7 @@ do: DO_SYM ; /* - Drop : delete tables or index + Drop : delete tables or index or user */ drop: @@ -3249,7 +3249,16 @@ drop: LEX *lex=Lex; lex->sql_command = SQLCOM_DROP_FUNCTION; lex->udf.name = $3; - }; + } + | DROP USER + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_DROP_USER; + lex->users_list.empty(); + } + user_list + {} + ; table_list: @@ -4177,8 +4186,10 @@ user: THD *thd= YYTHD; if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) YYABORT; - $$->user = $1; $$->host.str=NullS; - } + $$->user = $1; + $$->host.str= (char *) "%"; + $$->host.length= 1; + } | ident_or_text '@' ident_or_text { THD *thd= YYTHD; @@ -4361,6 +4372,7 @@ keyword: | UDF_SYM {} | UNCOMMITTED_SYM {} | UNICODE_SYM {} + | USER {} | USE_FRM {} | VARIABLES {} | VALUE_SYM {} @@ -4632,8 +4644,18 @@ revoke: lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; bzero((char*) &lex->mqh, sizeof(lex->mqh)); } + revoke_command + {} + ; + +revoke_command: grant_privileges ON opt_table FROM user_list {} + | + ALL PRIVILEGES ',' GRANT FROM user_list + { + Lex->sql_command = SQLCOM_REVOKE_ALL; + } ; grant: From 0bb5b9eadddfc911bfaa7c6ee69db92fc7785c94 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 8 Jun 2003 09:11:14 -0700 Subject: [PATCH 329/399] Fix for mysql_list_fields & reset stmt buffers from stmt_free_result Windows build fix VC++Files/sql/mysqld.dsp: Added sql_state.c to wrk space include/mysql_com.h: Windows build fix (mismatch declaration of my_bool and bool from defination) include/thr_alarm.h: Windows build fix libmysql/libmysql.c: Fix for mysql_list_fields & reset stmt buffers from stmt_free_result tests/client_test.c: Updated test for DEFAULT value for mysql_list_fields() New tests for mysql_stmt_free_result() --- VC++Files/sql/mysqld.dsp | 4 + include/mysql_com.h | 2 +- include/thr_alarm.h | 2 +- libmysql/libmysql.c | 10 +- tests/client_test.c | 238 +++++++++++++++++++++++++++++++-------- 5 files changed, 204 insertions(+), 52 deletions(-) diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index a475c44e948..6aab591120a 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -1137,6 +1137,10 @@ SOURCE=.\sql_show.cpp # End Source File # Begin Source File +SOURCE=.\sql_state.c +# End Source File +# Begin Source File + SOURCE=.\sql_string.cpp !IF "$(CFG)" == "mysqld - Win32 Release" diff --git a/include/mysql_com.h b/include/mysql_com.h index 2ed5038b275..faa025c934e 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -324,7 +324,7 @@ my_bool check_scramble(const char *, const char *message, unsigned long *salt,my_bool old_ver); char *get_tty_password(char *opt_message); void hash_password(unsigned long *result, const char *password); -const char *mysql_errno_to_sqlstate(uint mysql_errno); +const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); /* Some other useful functions */ diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 8ff4472f700..439f046252f 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -100,7 +100,7 @@ typedef struct st_alarm { #define thr_alarm_init(A) (*(A))=0 #define thr_alarm_in_use(A) (*(A)!= 0) void init_thr_alarm(uint max_alarm); -my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); +bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); void thr_alarm_kill(pthread_t thread_id); void thr_end_alarm(thr_alarm_t *alarmed); void end_thr_alarm(my_bool free_structures); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 064a6c292eb..7e379ab63ba 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -990,7 +990,7 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild) end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128); if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1) || !(query = read_rows(mysql,(MYSQL_FIELD*) 0, - protocol_41(mysql) ? 7 : 6))) + protocol_41(mysql) ? 8 : 6))) DBUG_RETURN(NULL); free_old_query(mysql); @@ -1027,7 +1027,7 @@ mysql_list_processes(MYSQL *mysql) pos=(uchar*) mysql->net.read_pos; field_count=(uint) net_field_length(&pos); if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0, - protocol_41(mysql) ? 6 : 5))) + protocol_41(mysql) ? 7 : 5))) DBUG_RETURN(NULL); if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0, mysql->server_capabilities))) @@ -3055,7 +3055,8 @@ int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, #ifdef CHECK_EXTRA_ARGUMENTS if (!bind || icol >= stmt->field_count) { - DBUG_PRINT("error",("Invalid column position")); + set_stmt_errmsg(stmt, "Invalid column descriptor or offset",1, + unknown_sqlstate); DBUG_RETURN(1); } #endif @@ -3377,6 +3378,9 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt) mysql->status= MYSQL_STATUS_READY; } mysql_free_result(stmt->result); + stmt->result= 0; + stmt->result_buffered= 0; + stmt->current_row= 0; DBUG_RETURN(0); } diff --git a/tests/client_test.c b/tests/client_test.c index eebf65ce45f..d22aa900a4e 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -180,7 +180,7 @@ static void client_connect() if (!(mysql = mysql_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_init() failed"); exit(0); } @@ -535,7 +535,7 @@ static void verify_prepare_field(MYSQL_RES *result, unsigned int no,const char *name, const char *org_name, enum enum_field_types type, const char *table, const char *org_table, const char *db, - unsigned long length) + unsigned long length, const char *def) { MYSQL_FIELD *field; @@ -554,6 +554,7 @@ static void verify_prepare_field(MYSQL_RES *result, fprintf(stdout,"\n length :`%ld`\t(expected: `%ld`)", field->length, length); fprintf(stdout,"\n maxlength:`%ld`", field->max_length); fprintf(stdout,"\n charsetnr:`%d`", field->charsetnr); + fprintf(stdout,"\n default :`%s`\t(expected: `%s`)", field->def ? field->def : "(null)", def ? def: "(null)"); fprintf(stdout,"\n"); myassert(strcmp(field->name,name) == 0); myassert(strcmp(field->org_name,org_name) == 0); @@ -562,6 +563,8 @@ static void verify_prepare_field(MYSQL_RES *result, myassert(strcmp(field->org_table,org_table) == 0); myassert(strcmp(field->db,db) == 0); myassert(field->length == length); + if (def) + myassert(strcmp(field->def,def) == 0); } /* @@ -1021,15 +1024,15 @@ static void test_prepare_field_result() fprintf(stdout,"\n\n field attributes:\n"); verify_prepare_field(result,0,"int_c","int_c",MYSQL_TYPE_LONG, - "t1","test_prepare_field_result",current_db,11); + "t1","test_prepare_field_result",current_db,11,0); verify_prepare_field(result,1,"var_c","var_c",MYSQL_TYPE_VAR_STRING, - "t1","test_prepare_field_result",current_db,50); + "t1","test_prepare_field_result",current_db,50,0); verify_prepare_field(result,2,"date","date_c",MYSQL_TYPE_DATE, - "t1","test_prepare_field_result",current_db,10); + "t1","test_prepare_field_result",current_db,10,0); verify_prepare_field(result,3,"ts_c","ts_c",MYSQL_TYPE_TIMESTAMP, - "t1","test_prepare_field_result",current_db,19); + "t1","test_prepare_field_result",current_db,19,0); verify_prepare_field(result,4,"char_c","char_c",MYSQL_TYPE_STRING, - "t1","test_prepare_field_result",current_db,3); + "t1","test_prepare_field_result",current_db,3,0); verify_field_count(result, 5); mysql_free_result(result); @@ -5830,7 +5833,7 @@ static void test_field_misc() "@@autocommit","", /* field and its org name */ MYSQL_TYPE_LONGLONG, /* field type */ "", "", /* table and its org name */ - "",1); /* db name, length(its bool flag)*/ + "",1,0); /* db name, length(its bool flag)*/ mysql_free_result(result); @@ -5849,7 +5852,7 @@ static void test_field_misc() "@@autocommit","", /* field and its org name */ MYSQL_TYPE_LONGLONG, /* field type */ "", "", /* table and its org name */ - "",1); /* db name, length(its bool flag)*/ + "",1,0); /* db name, length(its bool flag)*/ mysql_free_result(result); mysql_stmt_close(stmt); @@ -5893,7 +5896,7 @@ static void test_field_misc() "@@table_type","", /* field and its org name */ MYSQL_TYPE_STRING, /* field type */ "", "", /* table and its org name */ - "",type_length); /* db name, length */ + "",type_length,0); /* db name, length */ mysql_free_result(result); mysql_stmt_close(stmt); @@ -5913,7 +5916,7 @@ static void test_field_misc() "@@max_error_count","", /* field and its org name */ MYSQL_TYPE_LONGLONG, /* field type */ "", "", /* table and its org name */ - "",10); /* db name, length */ + "",10,0); /* db name, length */ mysql_free_result(result); mysql_stmt_close(stmt); @@ -5933,7 +5936,7 @@ static void test_field_misc() "@@max_allowed_packet","", /* field and its org name */ MYSQL_TYPE_LONGLONG, /* field type */ "", "", /* table and its org name */ - "",10); /* db name, length */ + "",10,0); /* db name, length */ mysql_free_result(result); mysql_stmt_close(stmt); @@ -5953,7 +5956,7 @@ static void test_field_misc() "@@sql_warnings","", /* field and its org name */ MYSQL_TYPE_LONGLONG, /* field type */ "", "", /* table and its org name */ - "",1); /* db name, length */ + "",1,0); /* db name, length */ mysql_free_result(result); mysql_stmt_close(stmt); @@ -6340,39 +6343,22 @@ static void test_explain_bug() myassert(6 == mysql_num_fields(result)); verify_prepare_field(result,0,"Field","",MYSQL_TYPE_STRING, - "","","",NAME_LEN); + "","","",NAME_LEN,0); verify_prepare_field(result,1,"Type","",MYSQL_TYPE_STRING, - "","","",40); -#if 0 + "","","",40,0); - verify_prepare_field(result,2,"Collation","",MYSQL_TYPE_STRING, - "","","",40); - - verify_prepare_field(result,3,"Null","",MYSQL_TYPE_STRING, - "","","",1); - - verify_prepare_field(result,4,"Key","",MYSQL_TYPE_STRING, - "","","",3); - - verify_prepare_field(result,5,"Default","",MYSQL_TYPE_STRING, - "","","",NAME_LEN); - - verify_prepare_field(result,6,"Extra","",MYSQL_TYPE_STRING, - "","","",20); -#else verify_prepare_field(result,2,"Null","",MYSQL_TYPE_STRING, - "","","",1); + "","","",1,0); verify_prepare_field(result,3,"Key","",MYSQL_TYPE_STRING, - "","","",3); + "","","",3,0); verify_prepare_field(result,4,"Default","",MYSQL_TYPE_STRING, - "","","",NAME_LEN); + "","","",NAME_LEN,0); verify_prepare_field(result,5,"Extra","",MYSQL_TYPE_STRING, - "","","",20); -#endif + "","","",20,0); mysql_free_result(result); mysql_stmt_close(stmt); @@ -6393,34 +6379,34 @@ static void test_explain_bug() myassert(10 == mysql_num_fields(result)); verify_prepare_field(result,0,"id","",MYSQL_TYPE_LONGLONG, - "","","",3); + "","","",3,0); verify_prepare_field(result,1,"select_type","",MYSQL_TYPE_STRING, - "","","",19); + "","","",19,0); verify_prepare_field(result,2,"table","",MYSQL_TYPE_STRING, - "","","",NAME_LEN); + "","","",NAME_LEN,0); verify_prepare_field(result,3,"type","",MYSQL_TYPE_STRING, - "","","",10); + "","","",10,0); verify_prepare_field(result,4,"possible_keys","",MYSQL_TYPE_STRING, - "","","",NAME_LEN*32); + "","","",NAME_LEN*32,0); verify_prepare_field(result,5,"key","",MYSQL_TYPE_STRING, - "","","",NAME_LEN); + "","","",NAME_LEN,0); verify_prepare_field(result,6,"key_len","",MYSQL_TYPE_LONGLONG, - "","","",3); + "","","",3,0); verify_prepare_field(result,7,"ref","",MYSQL_TYPE_STRING, - "","","",NAME_LEN*16); + "","","",NAME_LEN*16,0); verify_prepare_field(result,8,"rows","",MYSQL_TYPE_LONGLONG, - "","","",10); + "","","",10,0); verify_prepare_field(result,9,"Extra","",MYSQL_TYPE_STRING, - "","","",255); + "","","",255,0); mysql_free_result(result); mysql_stmt_close(stmt); @@ -7053,6 +7039,9 @@ static void test_fetch_column() fprintf(stdout, "\n col 0: %d(%ld)", c1, l1); myassert(c1 == 1 && l1 == 4); + rc = mysql_fetch_column(stmt,bind,10,0); + mystmt_r(stmt,rc); + rc = mysql_fetch(stmt); mystmt(stmt,rc); @@ -7110,13 +7099,20 @@ static void test_list_fields() rc= mysql_query(mysql,"drop table if exists test_list_fields"); myquery(rc); - rc = mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10))"); + rc = mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10) default 'mysql')"); myquery(rc); result = mysql_list_fields(mysql, "test_list_fields",NULL); mytest(result); myassert( 0 == my_process_result_set(result)); + + verify_prepare_field(result,0,"c1","c1",MYSQL_TYPE_LONG, + "test_list_fields","test_list_fields",current_db,11,"0"); + + verify_prepare_field(result,1,"c2","c2",MYSQL_TYPE_STRING, + "test_list_fields","test_list_fields",current_db,10,"mysql"); + mysql_free_result(result); } @@ -7188,6 +7184,149 @@ static void test_mem_overun() mysql_stmt_close(stmt); } + +/* + To test mysql_stmt_free_result() +*/ +static void test_free_result() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + char c2[5]; + ulong length; + int rc, c1; + + myheader("test_free_result"); + + rc= mysql_query(mysql,"drop table if exists test_free_result"); + myquery(rc); + + rc = mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)"); + myquery(rc); + + rc = mysql_query(mysql, "insert into test_free_result values(),(),()"); + myquery(rc); + + stmt = mysql_prepare(mysql,"select * from test_free_result",50); + mystmt_init(stmt); + + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (char *)c2; + bind[0].buffer_length= 7; + bind[0].is_null= 0; + bind[0].length= &length; + + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + c2[0]= '\0'; length= 0; + rc = mysql_fetch_column(stmt,bind,0,0); + mystmt(stmt,rc); + fprintf(stdout, "\n col 1: %s(%ld)", c2, length); + myassert(strncmp(c2,"1",1)==0 && length == 1); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + c1= 0, length= 0; + + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (char *)&c1; + bind[0].buffer_length= 0; + bind[0].is_null= 0; + bind[0].length= &length; + + rc = mysql_fetch_column(stmt,bind,0,0); + mystmt(stmt,rc); + fprintf(stdout, "\n col 0: %d(%ld)", c1, length); + myassert(c1 == 2 && length == 4); + + rc = mysql_query(mysql,"drop table test_free_result"); + myquery_r(rc); /* error should be, COMMANDS OUT OF SYNC */ + + rc = mysql_stmt_free_result(stmt); + mystmt(stmt,rc); + + rc = mysql_query(mysql,"drop table test_free_result"); + myquery(rc); /* should be successful */ + + mysql_stmt_close(stmt); +} + +/* + To test mysql_stmt_free_result() +*/ +static void test_free_store_result() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + char c2[5]; + ulong length; + int rc, c1; + + myheader("test_free_store_result"); + + rc= mysql_query(mysql,"drop table if exists test_free_result"); + myquery(rc); + + rc = mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)"); + myquery(rc); + + rc = mysql_query(mysql, "insert into test_free_result values(),(),()"); + myquery(rc); + + stmt = mysql_prepare(mysql,"select * from test_free_result",50); + mystmt_init(stmt); + + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (char *)c2; + bind[0].buffer_length= 7; + bind[0].is_null= 0; + bind[0].length= &length; + + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + rc = mysql_stmt_store_result(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + c2[0]= '\0'; length= 0; + rc = mysql_fetch_column(stmt,bind,0,0); + mystmt(stmt,rc); + fprintf(stdout, "\n col 1: %s(%ld)", c2, length); + myassert(strncmp(c2,"1",1)==0 && length == 1); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + c1= 0, length= 0; + + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (char *)&c1; + bind[0].buffer_length= 0; + bind[0].is_null= 0; + bind[0].length= &length; + + rc = mysql_fetch_column(stmt,bind,0,0); + mystmt(stmt,rc); + fprintf(stdout, "\n col 0: %d(%ld)", c1, length); + myassert(c1 == 2 && length == 4); + + rc = mysql_stmt_free_result(stmt); + mystmt(stmt,rc); + + rc = mysql_query(mysql,"drop table test_free_result"); + myquery(rc); + + mysql_stmt_close(stmt); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -7428,6 +7567,11 @@ int main(int argc, char **argv) test_open_direct(); /* direct execution in the middle of open stmts */ test_fetch_offset(); /* to test mysql_fetch_column with offset */ test_fetch_column(); /* to test mysql_fetch_column */ + test_mem_overun(); /* test DBD ovverun bug */ + test_list_fields(); /* test COM_LIST_FIELDS for DEFAULT */ + test_free_result(); /* test mysql_stmt_free_result() */ + test_free_store_result(); /* test to make sure stmt results are cleared + during stmt_free_result() */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); From d04fe0349494d599d6d3dd4cba1d4dcd8f032c2a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Jun 2003 15:22:28 +0200 Subject: [PATCH 330/399] Some error messages re. BLOBs are true for TEXTs as well sql/share/english/errmsg.txt: Some messages re. BLOBs are true for TEXTs as well BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/share/english/errmsg.txt | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a94b9c2045e..202f30dd31e 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -17,6 +17,7 @@ bar@gw.udmsearch.izhnet.ru bell@laptop.sanja.is.com.ua bell@sanja.is.com.ua bk@admin.bk +carsten@tsort.bitbybit.dk davida@isil.mysql.com gluh@gluh.(none) gluh@gluh.mysql.r18.ru diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index ad15d55405f..f15e063c487 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -102,7 +102,7 @@ "Can't generate a unique log-filename %-.64s.(1-999)\n", "Table '%-.64s' was locked with a READ lock and can't be updated", "Table '%-.64s' was not locked with LOCK TABLES", -"BLOB column '%-.64s' can't have a default value", +"BLOB/TEXT column '%-.64s' can't have a default value", "Incorrect database name '%-.100s'", "Incorrect table name '%-.100s'", "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", @@ -119,7 +119,7 @@ "Unknown character set: '%-.64s'", "Too many tables. MySQL can only use %d tables in a join", "Too many columns", -"Too big row size. The maximum row size, not counting BLOBs, is %d. You have to change some fields to BLOBs", +"Too big row size. The maximum row size, not counting BLOBs, is %d. You have to change some fields to TEXTs or BLOBs", "Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed", "Cross dependency found in OUTER JOIN. Examine your ON conditions", "Column '%-.64s' is used with UNIQUE or INDEX but is not defined as NOT NULL", @@ -171,7 +171,7 @@ "The used storage engine can't index column '%-.64s'", "All tables in the MERGE table are not identically defined", "Can't write, because of unique constraint, to table '%-.64s'", -"BLOB column '%-.64s' used in key specification without a key length", +"BLOB/TEXT column '%-.64s' used in key specification without a key length", "All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead", "Result consisted of more than one row", "This table type requires a primary key", From 00320d3790d063932784993b0370a177cd02a4cd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Jun 2003 22:26:22 +0200 Subject: [PATCH 331/399] more DBUG_xxx tags --- myisam/ft_update.c | 66 +++++++++++++++++++++++++++++++--------------- myisam/mi_delete.c | 15 ++++++++++- myisam/mi_page.c | 15 +++++++---- 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/myisam/ft_update.c b/myisam/ft_update.c index 4b6d1c4bffc..365fe0d98e3 100644 --- a/myisam/ft_update.c +++ b/myisam/ft_update.c @@ -31,18 +31,24 @@ void _mi_ft_segiterator_init(MI_INFO *info, uint keynr, const byte *record, FT_SEG_ITERATOR *ftsi) { + DBUG_ENTER("_mi_ft_segiterator_init"); + ftsi->num=info->s->keyinfo[keynr].keysegs; ftsi->seg=info->s->keyinfo[keynr].seg; ftsi->rec=record; + DBUG_VOID_RETURN; } void _mi_ft_segiterator_dummy_init(const byte *record, uint len, FT_SEG_ITERATOR *ftsi) { + DBUG_ENTER("_mi_ft_segiterator_dummy_init"); + ftsi->num=1; ftsi->seg=0; ftsi->pos=record; ftsi->len=len; + DBUG_VOID_RETURN; } /* @@ -56,14 +62,16 @@ void _mi_ft_segiterator_dummy_init(const byte *record, uint len, uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) { - if (!ftsi->num) return 0; else ftsi->num--; - if (!ftsi->seg) return 1; else ftsi->seg--; + DBUG_ENTER("_mi_ft_segiterator"); + + if (!ftsi->num) DBUG_RETURN(0) else ftsi->num--; + if (!ftsi->seg) DBUG_RETURN(1) else ftsi->seg--; if (ftsi->seg->null_bit && (ftsi->rec[ftsi->seg->null_pos] & ftsi->seg->null_bit)) { ftsi->pos=0; - return 1; + DBUG_RETURN(1); } ftsi->pos= ftsi->rec+ftsi->seg->start; if (ftsi->seg->flag & HA_VAR_LENGTH) @@ -71,7 +79,7 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) ftsi->len=uint2korr(ftsi->pos); ftsi->pos+=2; /* Skip VARCHAR length */ set_if_smaller(ftsi->len,ftsi->seg->length); - return 1; + DBUG_RETURN(1); } if (ftsi->seg->flag & HA_BLOB_PART) { @@ -79,10 +87,10 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) memcpy_fixed((char*) &ftsi->pos, ftsi->pos+ftsi->seg->bit_start, sizeof(char*)); set_if_smaller(ftsi->len,ftsi->seg->length); - return 1; + DBUG_RETURN(1); } ftsi->len=ftsi->seg->length; - return 1; + DBUG_RETURN(1); } @@ -91,6 +99,8 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, const byte *record) { FT_SEG_ITERATOR ftsi; + DBUG_ENTER("_mi_ft_parse"); + _mi_ft_segiterator_init(info, keynr, record, &ftsi); ft_parse_init(parsed, info->s->keyinfo[keynr].seg->charset); @@ -98,9 +108,9 @@ uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, const byte *record) { if (ftsi.pos) if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len)) - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, @@ -108,32 +118,35 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record) { TREE ptree; + DBUG_ENTER("_mi_ft_parserecord"); bzero((char*) &ptree, sizeof(ptree)); if (_mi_ft_parse(&ptree, info, keynr, record)) - return NULL; + DBUG_RETURN(NULL); - return ft_linearize(&ptree); + DBUG_RETURN(ft_linearize(&ptree)); } static int _mi_ft_store(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wlist, my_off_t filepos) { uint key_length; + DBUG_ENTER("_mi_ft_store"); for (; wlist->pos; wlist++) { key_length=_ft_make_key(info,keynr,keybuf,wlist,filepos); if (_mi_ck_write(info,keynr,(uchar*) keybuf,key_length)) - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } static int _mi_ft_erase(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wlist, my_off_t filepos) { uint key_length, err=0; + DBUG_ENTER("_mi_ft_erase"); for (; wlist->pos; wlist++) { @@ -141,7 +154,7 @@ static int _mi_ft_erase(MI_INFO *info, uint keynr, byte *keybuf, if (_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length)) err=1; } - return err; + DBUG_RETURN(err); } /* @@ -156,6 +169,8 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2) { FT_SEG_ITERATOR ftsi1, ftsi2; CHARSET_INFO *cs=info->s->keyinfo[keynr].seg->charset; + DBUG_ENTER("_mi_ft_cmp"); + _mi_ft_segiterator_init(info, keynr, rec1, &ftsi1); _mi_ft_segiterator_init(info, keynr, rec2, &ftsi2); @@ -165,9 +180,9 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2) (!ftsi1.pos || !ftsi2.pos || mi_compare_text(cs, (uchar*) ftsi1.pos,ftsi1.len, (uchar*) ftsi2.pos,ftsi2.len,0))) - return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT; + DBUG_RETURN(THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT); } - return GEE_THEY_ARE_ABSOLUTELY_IDENTICAL; + DBUG_RETURN(GEE_THEY_ARE_ABSOLUTELY_IDENTICAL); } @@ -181,6 +196,7 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf, CHARSET_INFO *cs=info->s->keyinfo[keynr].seg->charset; uint key_length; int cmp, cmp2; + DBUG_ENTER("_mi_ft_update"); if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, keybuf, oldrec))) goto err0; @@ -219,7 +235,7 @@ err2: err1: my_free((char*) oldlist,MYF(0)); err0: - return error; + DBUG_RETURN(error); } @@ -230,13 +246,14 @@ int _mi_ft_add(MI_INFO *info, uint keynr, byte *keybuf, const byte *record, { int error= -1; FT_WORD *wlist; + DBUG_ENTER("_mi_ft_add"); if ((wlist=_mi_ft_parserecord(info, keynr, keybuf, record))) { error=_mi_ft_store(info,keynr,keybuf,wlist,pos); my_free((char*) wlist,MYF(0)); } - return error; + DBUG_RETURN(error); } @@ -247,27 +264,34 @@ int _mi_ft_del(MI_INFO *info, uint keynr, byte *keybuf, const byte *record, { int error= -1; FT_WORD *wlist; + DBUG_ENTER("_mi_ft_del"); + DBUG_PRINT("enter",("keynr: %d",keynr)); + if ((wlist=_mi_ft_parserecord(info, keynr, keybuf, record))) { error=_mi_ft_erase(info,keynr,keybuf,wlist,pos); my_free((char*) wlist,MYF(0)); } - return error; + DBUG_PRINT("exit",("Return: %d",error)); + DBUG_RETURN(error); } uint _ft_make_key(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wptr, my_off_t filepos) { byte buf[HA_FT_MAXLEN+16]; + DBUG_ENTER("_ft_make_key"); #if HA_FT_WTYPE == HA_KEYTYPE_FLOAT - float weight=(float) ((filepos==HA_OFFSET_ERROR) ? 0 : wptr->weight); - mi_float4store(buf,weight); + { + float weight=(float) ((filepos==HA_OFFSET_ERROR) ? 0 : wptr->weight); + mi_float4store(buf,weight); + } #else #error #endif int2store(buf+HA_FT_WLEN,wptr->len); memcpy(buf+HA_FT_WLEN+2,wptr->pos,wptr->len); - return _mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos); + DBUG_RETURN(_mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos)); } diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 96c6400f078..8bfb717fa05 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -33,7 +33,7 @@ static int underflow(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *anc_buff, static uint remove_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar *keypos, uchar *lastkey,uchar *page_end, my_off_t *next_block); -static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, +static int _mi_ck_real_delete(register MI_INFO *info,MI_KEYDEF *keyinfo, uchar *key, uint key_length, my_off_t *root); @@ -188,6 +188,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, } err: my_afree((gptr) root_buff); + DBUG_PRINT("exit",("Return: %d",error)); DBUG_RETURN(error); } /* _mi_ck_real_delete */ @@ -234,6 +235,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, if (subkeys >= 0) { /* normal word, one-level tree structure */ + DBUG_PRINT("info",("FT1")); flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,USE_WHOLE_KEY, comp_flag, &keypos, lastkey, &last_key); /* fall through to normal delete */ @@ -250,11 +252,13 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, if (subkeys == -1) { /* the last entry in sub-tree */ + DBUG_PRINT("info",("FT2: the last entry")); _mi_dispose(info, keyinfo, root); /* fall through to normal delete */ } else { + DBUG_PRINT("info",("FT2: going down")); keyinfo=&info->s->ft2_keyinfo; kpos-=keyinfo->keylength; /* we'll modify key entry 'in vivo' */ key+=off; @@ -265,6 +269,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ft_intXstore(kpos, subkeys); if (!ret_value) ret_value=_mi_write_keypage(info,keyinfo,page,anc_buff); + DBUG_PRINT("exit",("Return: %d",ret_value)); DBUG_RETURN(ret_value); } } @@ -279,6 +284,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, { DBUG_PRINT("error",("Couldn't allocate memory")); my_errno=ENOMEM; + DBUG_PRINT("exit",("Return: %d",-1)); DBUG_RETURN(-1); } if (!_mi_fetch_keypage(info,keyinfo,leaf_page,leaf_buff,0)) @@ -304,14 +310,20 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, tmp=remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length, &next_block); if (tmp == 0) + { + DBUG_PRINT("exit",("Return: %d",0)); DBUG_RETURN(0); + } length-= tmp; mi_putint(anc_buff,length,nod_flag); if (!nod_flag) { /* On leaf page */ if (_mi_write_keypage(info,keyinfo,page,anc_buff)) + { + DBUG_PRINT("exit",("Return: %d",-1)); DBUG_RETURN(-1); + } /* Page will be update later if we return 1 */ DBUG_RETURN(test(length <= (info->quick_mode ? MI_MIN_KEYBLOCK_LENGTH : (uint) keyinfo->underflow_block_length))); @@ -348,6 +360,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, DBUG_DUMP("page",(byte*) anc_buff,mi_getint(anc_buff)); } my_afree((byte*) leaf_buff); + DBUG_PRINT("exit",("Return: %d",ret_value)); DBUG_RETURN(ret_value); err: my_afree((byte*) leaf_buff); diff --git a/myisam/mi_page.c b/myisam/mi_page.c index 1d40980e309..49f3243e08d 100644 --- a/myisam/mi_page.c +++ b/myisam/mi_page.c @@ -28,6 +28,9 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo, { uchar *tmp; uint page_size; + DBUG_ENTER("_mi_fetch_keypage"); + DBUG_PRINT("enter",("page: %ld",page)); + tmp=(uchar*) key_cache_read(info->s->kfile,page,(byte*) buff, (uint) keyinfo->block_length, (uint) keyinfo->block_length, @@ -39,7 +42,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo, DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno)); info->last_keypage=HA_OFFSET_ERROR; my_errno=HA_ERR_CRASHED; - return 0; + DBUG_RETURN(0); } info->last_keypage=page; page_size=mi_getint(tmp); @@ -51,7 +54,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo, my_errno = HA_ERR_CRASHED; tmp = 0; } - return tmp; + DBUG_RETURN(tmp); } /* _mi_fetch_keypage */ @@ -61,6 +64,8 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_off_t page, uchar *buff) { reg3 uint length; + DBUG_ENTER("_mi_write_keypage"); + #ifndef FAST /* Safety check */ if (page < info->s->base.keystart || page+keyinfo->block_length > info->state->key_file_length || @@ -71,7 +76,7 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, (long) info->state->key_file_length, (long) page)); my_errno=EINVAL; - return(-1); + DBUG_RETURN((-1)); } DBUG_PRINT("page",("write page at: %lu",(long) page,buff)); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); @@ -87,10 +92,10 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, length=keyinfo->block_length; } #endif - return (key_cache_write(info->s->kfile,page,(byte*) buff,length, + DBUG_RETURN((key_cache_write(info->s->kfile,page,(byte*) buff,length, (uint) keyinfo->block_length, (int) ((info->lock_type != F_UNLCK) || - info->s->delay_key_write))); + info->s->delay_key_write)))); } /* mi_write_keypage */ From 8484e6f7598251c50c2439e6b2d26afe6729435a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 11:34:00 +0500 Subject: [PATCH 332/399] mysqldump.c: SET NAMES is not produced in compatibility modes client/mysqldump.c: SET NAMES is not produced in compatibility modes --- client/mysqldump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/mysqldump.c b/client/mysqldump.c index 18705b9e375..180ac41f87f 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -34,6 +34,7 @@ ** XML by Gary Huntress 10/10/01, cleaned up ** and adapted to mysqldump 05/11/01 by Jani Tolonen ** Added --single-transaction option 06/06/2002 by Peter Zaitsev +** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov */ #define DUMP_VERSION "10.2" @@ -434,6 +435,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char buff[255]; opt_quoted= 1; + opt_set_names= 1; opt_compatible_mode_str= argument; opt_compatible_mode= find_set(&compatible_mode_typelib, argument, strlen(argument), From 47e0ca90d3c7e76dceae296f03e3701f5619fd2f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 12:07:02 +0500 Subject: [PATCH 333/399] mysqldump.c: SET NAMES is not sent to server when SET NAMES is not dumped Server decides which character set to use in this case client/mysqldump.c: SET NAMES is not sent to server when SET NAMES is not dumped Server decides which character set to use in this case --- client/mysqldump.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 180ac41f87f..67e83d58768 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -565,7 +565,8 @@ static int dbConnect(char *host, char *user,char *passwd) if (shared_memory_base_name) mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); #endif - mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); + if (!opt_set_names) + mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); if (!(sock= mysql_real_connect(&mysql_connection,host,user,passwd, NULL,opt_mysql_port,opt_mysql_unix_port, 0))) From 85be6a0ac822dd0469eb1da9834b477ffa74ae68 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 12:19:28 +0500 Subject: [PATCH 334/399] Bugfix for HEAP table rb-index scan. --- heap/hp_rkey.c | 4 ++-- mysql-test/r/heap_btree.result | 4 ++-- mysql-test/t/heap_btree.test | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c index 91d762ab4db..2c23d9d721e 100644 --- a/heap/hp_rkey.c +++ b/heap/hp_rkey.c @@ -38,7 +38,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key, custom_arg.keyseg= info->s->keydef[inx].seg; custom_arg.key_length= info->lastkey_len= - hp_rb_pack_key(keyinfo, (uchar*) info->recbuf, + hp_rb_pack_key(keyinfo, (uchar*) info->lastkey, (uchar*) key, key_len); custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME; /* for next rkey() after deletion */ @@ -48,7 +48,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key, info->last_find_flag= HA_READ_KEY_OR_PREV; else info->last_find_flag= find_flag; - if (!(pos= tree_search_key(&keyinfo->rb_tree, info->recbuf, info->parents, + if (!(pos= tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents, &info->last_pos, find_flag, &custom_arg))) { info->update= 0; diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result index 6ae00c89a3a..1ba8d429fc4 100644 --- a/mysql-test/r/heap_btree.result +++ b/mysql-test/r/heap_btree.result @@ -24,8 +24,8 @@ a b alter table t1 add c int not null, add key using BTREE (c,a); drop table t1; create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps"; -insert into t1 values(1,1),(2,2),(3,3),(4,4); -delete from t1 where a > 0; +insert into t1 values(-2,-2),(-1,-1),(0,0),(1,1),(2,2),(3,3),(4,4); +delete from t1 where a > -3; select * from t1; a b drop table t1; diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test index 3c2ff249415..80a7753d4b1 100644 --- a/mysql-test/t/heap_btree.test +++ b/mysql-test/t/heap_btree.test @@ -21,8 +21,8 @@ alter table t1 add c int not null, add key using BTREE (c,a); drop table t1; create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps"; -insert into t1 values(1,1),(2,2),(3,3),(4,4); -delete from t1 where a > 0; +insert into t1 values(-2,-2),(-1,-1),(0,0),(1,1),(2,2),(3,3),(4,4); +delete from t1 where a > -3; select * from t1; drop table t1; From 8a40e2e8f81508ba66f9b3e9bab7b1896fb8482d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 14:54:03 +0500 Subject: [PATCH 335/399] Some more functions work according to coercibility now: repeat, reverse, quote, soundex, substring Test func_str has been extended to check them --- mysql-test/r/func_str.result | 29 +++++++++++++++++++++++++++-- mysql-test/t/func_str.test | 13 ++++++++++++- sql/item_cmpfunc.h | 7 ------- sql/item_strfunc.cc | 5 ++++- sql/item_strfunc.h | 6 +++++- 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index c61563e6010..b6d9f512c1a 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -288,6 +288,21 @@ latin2_general_ci 3 select collation(trim(BOTH _latin2' ' FROM _latin2'a')), coercibility(trim(BOTH _latin2'a' FROM _latin2'a')); collation(trim(BOTH _latin2' ' FROM _latin2'a')) coercibility(trim(BOTH _latin2'a' FROM _latin2'a')) latin2_general_ci 3 +select collation(repeat(_latin2'a',10)), coercibility(repeat(_latin2'a',10)); +collation(repeat(_latin2'a',10)) coercibility(repeat(_latin2'a',10)) +latin2_general_ci 3 +select collation(reverse(_latin2'ab')), coercibility(reverse(_latin2'ab')); +collation(reverse(_latin2'ab')) coercibility(reverse(_latin2'ab')) +latin2_general_ci 3 +select collation(quote(_latin2'ab')), coercibility(quote(_latin2'ab')); +collation(quote(_latin2'ab')) coercibility(quote(_latin2'ab')) +latin2_general_ci 3 +select collation(soundex(_latin2'ab')), coercibility(soundex(_latin2'ab')); +collation(soundex(_latin2'ab')) coercibility(soundex(_latin2'ab')) +latin2_general_ci 3 +select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1)); +collation(substring(_latin2'ab',1)) coercibility(substring(_latin2'ab',1)) +latin2_general_ci 3 create table t1 select left(_latin2'a',1), @@ -302,7 +317,12 @@ ltrim(_latin2' a '), rtrim(_latin2' a '), trim(LEADING _latin2' ' FROM _latin2' a '), trim(TRAILING _latin2' ' FROM _latin2' a '), -trim(BOTH _latin2' ' FROM _latin2' a ') +trim(BOTH _latin2' ' FROM _latin2' a '), +repeat(_latin2'a',10), +reverse(_latin2'ab'), +quote(_latin2'ab'), +soundex(_latin2'ab'), +substring(_latin2'ab',1) ; show create table t1; Table Create Table @@ -319,6 +339,11 @@ t1 CREATE TABLE `t1` ( `rtrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '', `trim(LEADING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '', `trim(TRAILING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '', - `trim(BOTH _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '' + `trim(BOTH _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '', + `repeat(_latin2'a',10)` char(10) character set latin2 NOT NULL default '', + `reverse(_latin2'ab')` char(2) character set latin2 NOT NULL default '', + `quote(_latin2'ab')` char(6) character set latin2 NOT NULL default '', + `soundex(_latin2'ab')` char(4) character set latin2 NOT NULL default '', + `substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index d99b54d88ff..7bb83058281 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -149,6 +149,12 @@ select collation(rtrim(_latin2' a ')), coercibility(rtrim(_latin2' a ')); select collation(trim(LEADING _latin2' ' FROM _latin2'a')), coercibility(trim(LEADING _latin2'a' FROM _latin2'a')); select collation(trim(TRAILING _latin2' ' FROM _latin2'a')), coercibility(trim(TRAILING _latin2'a' FROM _latin2'a')); select collation(trim(BOTH _latin2' ' FROM _latin2'a')), coercibility(trim(BOTH _latin2'a' FROM _latin2'a')); +select collation(repeat(_latin2'a',10)), coercibility(repeat(_latin2'a',10)); +select collation(reverse(_latin2'ab')), coercibility(reverse(_latin2'ab')); +select collation(quote(_latin2'ab')), coercibility(quote(_latin2'ab')); +select collation(soundex(_latin2'ab')), coercibility(soundex(_latin2'ab')); +select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1)); + create table t1 select left(_latin2'a',1), @@ -163,7 +169,12 @@ select rtrim(_latin2' a '), trim(LEADING _latin2' ' FROM _latin2' a '), trim(TRAILING _latin2' ' FROM _latin2' a '), - trim(BOTH _latin2' ' FROM _latin2' a ') + trim(BOTH _latin2' ' FROM _latin2' a '), + repeat(_latin2'a',10), + reverse(_latin2'ab'), + quote(_latin2'ab'), + soundex(_latin2'ab'), + substring(_latin2'ab',1) ; show create table t1; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 4438b902011..549839b4f96 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -263,13 +263,6 @@ class Item_func_strcmp :public Item_bool_func2 public: Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {} longlong val_int(); - void fix_length_and_dec() - { - max_length=2; - /* QQ: COERCIBILITY */ - cmp_charset= args[0]->binary() || args[1]->binary() ? - &my_charset_bin : args[0]->charset(); - } optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "strcmp"; } }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index e5b73e7670f..b9d44295f35 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -702,6 +702,7 @@ String *Item_func_reverse::val_str(String *str) void Item_func_reverse::fix_length_and_dec() { + set_charset(args[0]->charset(),args[0]->coercibility); max_length = args[0]->max_length; } @@ -1521,6 +1522,7 @@ String *Item_func_user::val_str(String *str) void Item_func_soundex::fix_length_and_dec() { + set_charset(args[0]->charset(), args[0]->coercibility); max_length=args[0]->max_length; set_if_bigger(max_length,4); } @@ -1552,7 +1554,7 @@ String *Item_func_soundex::val_str(String *str) { String *res =args[0]->val_str(str); char last_ch,ch; - CHARSET_INFO *cs= &my_charset_latin1; + CHARSET_INFO *cs= charset(); if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ @@ -2538,6 +2540,7 @@ String *Item_func_quote::val_str(String *str) } *to= '\''; str->length(new_length); + str->set_charset(charset()); return str; null: diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index a70c9b39255..31d6c1fe89d 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -571,7 +571,11 @@ public: Item_func_quote(Item *a) :Item_str_func(a) {} const char *func_name() const { return "quote"; } String *val_str(String *); - void fix_length_and_dec() { max_length= args[0]->max_length * 2 + 2; } + void fix_length_and_dec() + { + set_charset(args[0]->charset(), args[0]->coercibility); + max_length= args[0]->max_length * 2 + 2; + } }; class Item_func_conv_charset :public Item_str_func From 54c04738a499578a18cdd9b72857962d964425de Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 15:25:27 +0500 Subject: [PATCH 336/399] Coercibility tests for - equal predicate - LIKE predicate - strcmp() function --- mysql-test/r/func_test.result | 57 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_test.test | 35 +++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index d415b77692b..be0e3144fd6 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -52,6 +52,63 @@ select 10 % 7, 10 mod 7, 10 div 3; select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2; (1 << 64)-1 ((1 << 64)-1) DIV 1 ((1 << 64)-1) DIV 2 18446744073709551615 18446744073709551615 9223372036854775807 +select _koi8r'a' = _koi8r'A'; +_koi8r'a' = _koi8r'A' +1 +select _koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci; +_koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci +1 +select _koi8r'a' = _koi8r'A' COLLATE koi8r_bin; +_koi8r'a' = _koi8r'A' COLLATE koi8r_bin +0 +select _koi8r'a' COLLATE koi8r_general_ci = _koi8r'A'; +_koi8r'a' COLLATE koi8r_general_ci = _koi8r'A' +1 +select _koi8r'a' COLLATE koi8r_bin = _koi8r'A'; +_koi8r'a' COLLATE koi8r_bin = _koi8r'A' +0 +select _koi8r'a' COLLATE koi8r_bin = _koi8r'A' COLLATE koi8r_general_ci; +ERROR HY000: Illegal mix of collations (koi8r_bin,EXPLICIT) and (koi8r_general_ci,EXPLICIT) for operation '=' +select _koi8r'a' = _latin1'A'; +ERROR HY000: Illegal mix of collations (koi8r_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '=' +select strcmp(_koi8r'a', _koi8r'A'); +strcmp(_koi8r'a', _koi8r'A') +0 +select strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_general_ci); +strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_general_ci) +0 +select strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_bin); +strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_bin) +1 +select strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A'); +strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A') +0 +select strcmp(_koi8r'a' COLLATE koi8r_bin, _koi8r'A'); +strcmp(_koi8r'a' COLLATE koi8r_bin, _koi8r'A') +1 +select strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A' COLLATE koi8r_bin); +ERROR HY000: Illegal mix of collations (koi8r_general_ci,EXPLICIT) and (koi8r_bin,EXPLICIT) for operation 'strcmp' +select strcmp(_koi8r'a', _latin1'A'); +ERROR HY000: Illegal mix of collations (koi8r_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'strcmp' +select _koi8r'a' LIKE _koi8r'A'; +_koi8r'a' LIKE _koi8r'A' +1 +select _koi8r'a' LIKE _koi8r'A' COLLATE koi8r_general_ci; +_koi8r'a' LIKE _koi8r'A' COLLATE koi8r_general_ci +1 +select _koi8r'a' LIKE _koi8r'A' COLLATE koi8r_bin; +_koi8r'a' LIKE _koi8r'A' COLLATE koi8r_bin +0 +select _koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A'; +_koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A' +1 +select _koi8r'a' COLLATE koi8r_bin LIKE _koi8r'A'; +_koi8r'a' COLLATE koi8r_bin LIKE _koi8r'A' +0 +select _koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A' COLLATE koi8r_bin; +ERROR HY000: Illegal mix of collations (koi8r_general_ci,EXPLICIT) and (koi8r_bin,EXPLICIT) for operation 'like' +select _koi8r'a' LIKE _latin1'A'; +ERROR HY000: Illegal mix of collations (koi8r_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'like' select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1; 5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1 0 1 diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index bdf58ee4b15..2834d5bd9c7 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -20,6 +20,41 @@ select 1 XOR 1, 1 XOR 0, 0 XOR 1, 0 XOR 0, NULL XOR 1, 1 XOR NULL, 0 XOR NULL; select 10 % 7, 10 mod 7, 10 div 3; select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2; +# +# Coercibility +# +select _koi8r'a' = _koi8r'A'; +select _koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci; +select _koi8r'a' = _koi8r'A' COLLATE koi8r_bin; +select _koi8r'a' COLLATE koi8r_general_ci = _koi8r'A'; +select _koi8r'a' COLLATE koi8r_bin = _koi8r'A'; +--error 1265 +select _koi8r'a' COLLATE koi8r_bin = _koi8r'A' COLLATE koi8r_general_ci; +--error 1265 +select _koi8r'a' = _latin1'A'; + +select strcmp(_koi8r'a', _koi8r'A'); +select strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_general_ci); +select strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_bin); +select strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A'); +select strcmp(_koi8r'a' COLLATE koi8r_bin, _koi8r'A'); +--error 1265 +select strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A' COLLATE koi8r_bin); +--error 1265 +select strcmp(_koi8r'a', _latin1'A'); + +select _koi8r'a' LIKE _koi8r'A'; +select _koi8r'a' LIKE _koi8r'A' COLLATE koi8r_general_ci; +select _koi8r'a' LIKE _koi8r'A' COLLATE koi8r_bin; +select _koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A'; +select _koi8r'a' COLLATE koi8r_bin LIKE _koi8r'A'; +--error 1265 +select _koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A' COLLATE koi8r_bin; +--error 1265 +select _koi8r'a' LIKE _latin1'A'; + + + # # Wrong usage of functions # From 7b93f3850526d3a44adf8f65fcfbbd74b46349ff Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 16:41:42 +0500 Subject: [PATCH 337/399] Function INSERT() now works according to coercibility rules Test for INSERT() has been added --- mysql-test/r/func_str.result | 9 +++++++-- mysql-test/t/func_str.test | 4 +++- sql/item_strfunc.cc | 8 ++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index b6d9f512c1a..ffb7f2cd911 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -303,6 +303,9 @@ latin2_general_ci 3 select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1)); collation(substring(_latin2'ab',1)) coercibility(substring(_latin2'ab',1)) latin2_general_ci 3 +select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef')); +collation(insert(_latin2'abcd',2,3,_latin2'ef')) coercibility(insert(_latin2'abcd',2,3,_latin2'ef')) +latin2_general_ci 3 create table t1 select left(_latin2'a',1), @@ -322,7 +325,8 @@ repeat(_latin2'a',10), reverse(_latin2'ab'), quote(_latin2'ab'), soundex(_latin2'ab'), -substring(_latin2'ab',1) +substring(_latin2'ab',1), +insert(_latin2'abcd',2,3,_latin2'ef') ; show create table t1; Table Create Table @@ -344,6 +348,7 @@ t1 CREATE TABLE `t1` ( `reverse(_latin2'ab')` char(2) character set latin2 NOT NULL default '', `quote(_latin2'ab')` char(6) character set latin2 NOT NULL default '', `soundex(_latin2'ab')` char(4) character set latin2 NOT NULL default '', - `substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '' + `substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '', + `insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 7bb83058281..93e35efa455 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -154,6 +154,7 @@ select collation(reverse(_latin2'ab')), coercibility(reverse(_latin2'ab')); select collation(quote(_latin2'ab')), coercibility(quote(_latin2'ab')); select collation(soundex(_latin2'ab')), coercibility(soundex(_latin2'ab')); select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1)); +select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef')); create table t1 select @@ -174,7 +175,8 @@ select reverse(_latin2'ab'), quote(_latin2'ab'), soundex(_latin2'ab'), - substring(_latin2'ab',1) + substring(_latin2'ab',1), + insert(_latin2'abcd',2,3,_latin2'ef') ; show create table t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index b9d44295f35..d660f7c472c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -861,6 +861,14 @@ null: void Item_func_insert::fix_length_and_dec() { + if (set_charset(args[0]->charset(), args[0]->coercibility, + args[3]->charset(), args[3]->coercibility)) + { + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + args[0]->charset()->name,coercion_name(args[0]->coercibility), + args[3]->charset()->name,coercion_name(args[3]->coercibility), + func_name()); + } max_length=args[0]->max_length+args[3]->max_length; if (max_length > MAX_BLOB_WIDTH) { From 43e36bffb22030af36c9c9548f1cd367690f9e60 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 17:53:06 +0500 Subject: [PATCH 338/399] LOAD_FILE() is now COERCIBLE LOAD_FILE() tests --- mysql-test/r/type_blob.result | 11 +++++++++++ mysql-test/t/type_blob.test | 7 +++++++ sql/item_strfunc.h | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index c16c83e3c53..a537aeeca07 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -486,8 +486,19 @@ fish 10 drop table t1; create table t1 (id integer auto_increment unique,imagem LONGBLOB not null); insert into t1 (id) values (1); +select +charset(load_file('../../std_data/words.dat')), +collation(load_file('../../std_data/words.dat')), +coercibility(load_file('../../std_data/words.dat')); +charset(load_file('../../std_data/words.dat')) collation(load_file('../../std_data/words.dat')) coercibility(load_file('../../std_data/words.dat')) +binary binary 3 update t1 set imagem=load_file('../../std_data/words.dat') where id=1; select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1; if(imagem is null, "ERROR", "OK") length(imagem) OK 581 drop table t1; +create table t1 select load_file('../../std_data/words.dat'); +show full fields from t1; +Field Type Collation Null Key Default Extra Privileges Comment +load_file('../../std_data/words.dat') mediumblob NULL YES NULL select,insert,update,references +drop table t1; diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test index 9c00abe980b..ebe342a4ef5 100644 --- a/mysql-test/t/type_blob.test +++ b/mysql-test/t/type_blob.test @@ -294,6 +294,13 @@ drop table t1; create table t1 (id integer auto_increment unique,imagem LONGBLOB not null); insert into t1 (id) values (1); +select + charset(load_file('../../std_data/words.dat')), + collation(load_file('../../std_data/words.dat')), + coercibility(load_file('../../std_data/words.dat')); update t1 set imagem=load_file('../../std_data/words.dat') where id=1; select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1; drop table t1; +create table t1 select load_file('../../std_data/words.dat'); +show full fields from t1; +drop table t1; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 31d6c1fe89d..26c69668b0a 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -536,8 +536,8 @@ public: const char *func_name() const { return "load_file"; } void fix_length_and_dec() { - set_charset(&my_charset_bin); - maybe_null=1; + set_charset(&my_charset_bin, COER_COERCIBLE); + maybe_null=1; max_length=MAX_BLOB_WIDTH; } }; From 6e4f383a1c1914f1d0a0c15c78b1c8ba70292277 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Jun 2003 15:19:59 +0200 Subject: [PATCH 339/399] test results updated --- mysql-test/r/grant.result | 4 ++-- mysql-test/r/isam.result | 16 ++++++++-------- mysql-test/r/replace.result | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 715deac7965..6b33f6a7536 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -91,14 +91,14 @@ Grants for drop_user@localhost GRANT USAGE ON *.* TO 'drop_user'@'localhost' drop user drop_user@localhost; revoke all privileges, grant from drop_user@localhost; -Can't revoke all privileges, grant for one or more of the requested users +ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users grant select(a) on test.t1 to drop_user1@localhost; grant select on test.t1 to drop_user2@localhost; grant select on test.* to drop_user3@localhost; grant select on *.* to drop_user4@localhost; drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; -Can't drop one or more of the requested users +ERROR HY000: Can't drop one or more of the requested users revoke all privileges, grant from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result index 5975ac8a8a0..5ac54668443 100644 --- a/mysql-test/r/isam.result +++ b/mysql-test/r/isam.result @@ -38,13 +38,13 @@ a b c 6 6 6 drop table t1; create table t1 (a int,b text, index(a)) type=isam; -Column 'a' is used with UNIQUE or INDEX but is not defined as NOT NULL +ERROR 42000: Column 'a' is used with UNIQUE or INDEX but is not defined as NOT NULL create table t1 (a int,b text, index(b)) type=isam; -BLOB column 'b' can't be used in key specification with the used table type +ERROR 42000: BLOB column 'b' can't be used in key specification with the used table type create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=isam; -Incorrect table definition; There can only be one auto column and it must be defined as a key +ERROR 42000: Incorrect table definition; There can only be one auto column and it must be defined as a key create table t1 (ordid int(8), unique (ordid)) type=isam; -Column 'ordid' is used with UNIQUE or INDEX but is not defined as NOT NULL +ERROR 42000: Column 'ordid' is used with UNIQUE or INDEX but is not defined as NOT NULL drop table if exists t1; Warnings: Note 1051 Unknown table 't1' @@ -72,10 +72,10 @@ Table Op Msg_type Msg_text test.t2 check error Table 't2' was not locked with LOCK TABLES test.t1 check status OK show columns from t1; -Field Type Collation Null Key Default Extra -a int(11) NULL PRI 0 -b int(11) NULL MUL 0 -c int(11) NULL 0 +Field Type Null Key Default Extra +a int(11) PRI 0 +b int(11) MUL 0 +c int(11) 0 show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment a int(11) NULL PRI 0 select,insert,update,references diff --git a/mysql-test/r/replace.result b/mysql-test/r/replace.result index 4a71428b2f4..2d95343245b 100644 --- a/mysql-test/r/replace.result +++ b/mysql-test/r/replace.result @@ -15,9 +15,9 @@ drop table t1; create table t1 (a tinyint not null auto_increment primary key, b char(20) default "default_value"); insert into t1 values (126,"first"),(63, "middle"),(0,"last"); insert into t1 values (0,"error"); -Duplicate entry '127' for key 1 +ERROR 23000: Duplicate entry '127' for key 1 replace into t1 values (0,"error"); -Duplicate entry '127' for key 1 +ERROR 23000: Duplicate entry '127' for key 1 replace into t1 values (126,"first updated"); replace into t1 values (63,default); select * from t1; From 3a4be00416667bc7d3a9dca18f3d771d0b8f912d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Jun 2003 13:32:50 +0200 Subject: [PATCH 340/399] protect deleted objects from reusal with safemalloc technique --- sql/field.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sql/field.h b/sql/field.h index 4456eb36731..a1f19638658 100644 --- a/sql/field.h +++ b/sql/field.h @@ -37,7 +37,11 @@ class Field void operator=(Field &); public: static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } - static void operator delete(void *ptr_arg, size_t size) {} /*lint -e715 */ + static void operator delete(void *ptr_arg, size_t size) { +#ifdef PEDANTIC_SAFEMALLOC + bfill(ptr_arg, size, 0x8F); +#endif + } char *ptr; // Position to field in record uchar *null_ptr; // Byte where null_bit is From b7e0c11a272b52c8a9c2b84d13bd9622c7dcf4b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Jun 2003 17:07:33 +0200 Subject: [PATCH 341/399] We now require SUPER privilege for SET PSEUDO_THREAD_ID. mysql-test/r/rpl_temporary.result: result update mysql-test/t/rpl_temporary.test: test that PSEUDO_THREAD_ID now requires SUPER. sql/set_var.cc: Class for pseudo_thread_id (it used to be sys_var_thd_ulong, but we decided to require the SUPER privilege so we needed a check() function, which sys_var_thd_ulong does not feature (check() is virtual in sys_var and in sys_var_thd_ulong too). sql/set_var.h: Class for pseudo_thread_id --- mysql-test/r/rpl_temporary.result | 2 ++ mysql-test/t/rpl_temporary.test | 8 ++++++++ sql/set_var.cc | 17 ++++++++++++++++- sql/set_var.h | 9 +++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index 3d811aeb09c..cf2b8814047 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -5,6 +5,8 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; reset master; +SET @@session.pseudo_thread_id=100; +ERROR HY000: Access denied. You need the SUPER privilege for this operation drop table if exists t1,t2; create table t1(f int); create table t2(f int); diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index f939856ea1f..442788ad019 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -19,6 +19,14 @@ connection master; connect (con1,localhost,root,,); connect (con2,localhost,root,,); +connect (con3,localhost,test,,); + +# We are going to use SET PSEUDO_THREAD_ID in this test; +# check that it requires the SUPER privilege. + +connection con3; +--error 1227 +SET @@session.pseudo_thread_id=100; let $VERSION=`select version()`; diff --git a/sql/set_var.cc b/sql/set_var.cc index ad3966f76f9..a5377d8ebc6 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -168,7 +168,11 @@ sys_var_thd_ulong sys_max_error_count("max_error_count", &SV::max_error_count); sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size", &SV::max_heap_table_size); -sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id", +/* + sys_pseudo_thread_id has its own class (instead of sys_var_thd_ulong) because + we want a check() function. +*/ +sys_var_pseudo_thread_id sys_pseudo_thread_id("pseudo_thread_id", &SV::pseudo_thread_id); sys_var_thd_ha_rows sys_max_join_size("max_join_size", &SV::max_join_size, @@ -1454,6 +1458,17 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type) return (byte*) &thd->current_insert_id; } +bool sys_var_pseudo_thread_id::check(THD *thd, set_var *var) +{ + if (thd->master_access & SUPER_ACL) + return 0; + else + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + return 1; + } +} + #ifdef HAVE_REPLICATION bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) diff --git a/sql/set_var.h b/sql/set_var.h index 998d61ff2d1..5a0fbd21809 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -212,6 +212,15 @@ public: byte *value_ptr(THD *thd, enum_var_type type); }; +class sys_var_pseudo_thread_id :public sys_var_thd_ulong +{ +public: + sys_var_pseudo_thread_id(const char *name_arg, ulong SV::*offset_arg) + :sys_var_thd_ulong(name_arg, offset_arg) + {} + bool check(THD *thd, set_var *var); +}; + class sys_var_thd_ha_rows :public sys_var_thd { From 41021a0fc8237411d5977edf9151a4b95f074957 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Jun 2003 17:07:34 +0200 Subject: [PATCH 342/399] test result updated mysql-test/t/rpl_relayrotate.test: when mysqld has no innodb compiled in it's not a bug! --- mysql-test/r/type_blob.result | 2 +- mysql-test/t/rpl_relayrotate.test | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index a537aeeca07..d39f72cbe0b 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -29,7 +29,7 @@ drop table t1,t2,t3 CREATE TABLE t1 (a char(257) default "hello"); ERROR 42000: Too big column length for column 'a' (max = 255). Use BLOB instead CREATE TABLE t2 (a blob default "hello"); -ERROR 42000: BLOB column 'a' can't have a default value +ERROR 42000: BLOB/TEXT column 'a' can't have a default value drop table if exists t1,t2; create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr)); insert into t1 values (null,"a","A"); diff --git a/mysql-test/t/rpl_relayrotate.test b/mysql-test/t/rpl_relayrotate.test index 09cf7cbb741..3df55eea57d 100644 --- a/mysql-test/t/rpl_relayrotate.test +++ b/mysql-test/t/rpl_relayrotate.test @@ -14,7 +14,9 @@ source include/master-slave.inc; connection slave; stop slave; connection master; +--disable_warnings create table t1 (a int) type=innodb; +--enable_warnings let $1=8000; disable_query_log; begin; From 129cb8e9c0d45df6d74c91542086e8cf98850d48 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Jun 2003 16:27:26 -0500 Subject: [PATCH 343/399] ft_update.c: Fix parse error per serg instructions. myisam/ft_update.c: Fix parse error per serg instructions. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + myisam/ft_update.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 202f30dd31e..806eac52759 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -77,6 +77,7 @@ nick@mysql.com nick@nick.leippe.com papa@gbichot.local paul@central.snake.net +paul@ice.snake.net paul@teton.kitebird.com pem@mysql.com peter@linux.local diff --git a/myisam/ft_update.c b/myisam/ft_update.c index 365fe0d98e3..cdf3b306087 100644 --- a/myisam/ft_update.c +++ b/myisam/ft_update.c @@ -64,8 +64,18 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) { DBUG_ENTER("_mi_ft_segiterator"); - if (!ftsi->num) DBUG_RETURN(0) else ftsi->num--; - if (!ftsi->seg) DBUG_RETURN(1) else ftsi->seg--; + if (!ftsi->num) + { + DBUG_RETURN(0); + } + else + ftsi->num--; + if (!ftsi->seg) + { + DBUG_RETURN(1); + } + else + ftsi->seg--; if (ftsi->seg->null_bit && (ftsi->rec[ftsi->seg->null_pos] & ftsi->seg->null_bit)) From 3ec47723618b6975b8b520dec31b22af84c988bd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jun 2003 12:41:29 +0200 Subject: [PATCH 344/399] FT2 bug in mi_delete fixed --- myisam/mi_delete.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 97d2f531f6f..2ab5c5d0319 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -260,7 +260,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, { DBUG_PRINT("info",("FT2: going down")); keyinfo=&info->s->ft2_keyinfo; - kpos-=keyinfo->keylength; /* we'll modify key entry 'in vivo' */ + kpos-=keyinfo->keylength+nod_flag; /* we'll modify key entry 'in vivo' */ key+=off; ret_value=_mi_ck_real_delete(info, &info->s->ft2_keyinfo, key, HA_FT_WLEN, &root); From f7aed0240511510dfe51083bd7ff12482d8716bc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jun 2003 04:29:02 -0700 Subject: [PATCH 345/399] Many files: New feature: preload indexes into key cache. mi_preload.c: new file Many files: Added preload statement. sql/ha_myisam.h: Added preload statement. sql/handler.cc: Added preload statement. sql/lex.h: Added preload statement. sql/mysql_priv.h: Added preload statement. sql/sql_lex.h: Added preload statement. sql/sql_base.cc: Added preload statement. sql/sql_table.cc: New feature: preload indexes into key cache. sql/sql_parse.cc: New feature: preload indexes into key cache. sql/mysqld.cc: New feature: preload indexes into key cache. sql/set_var.cc: New feature: preload indexes into key cache. sql/sql_yacc.yy: New feature: preload indexes into key cache. sql/ha_myisam.cc: New feature: preload indexes into key cache. sql/table.h: New feature: preload indexes into key cache. mysys/mf_keycache.c: New feature: preload indexes into key cache. myisam/myisamdef.h: New feature: preload indexes into key cache. myisam/mi_extra.c: New feature: preload indexes into key cache. myisam/Makefile.am: New feature: preload indexes into key cache. include/my_base.h: New feature: preload indexes into key cache. include/my_sys.h: New feature: preload indexes into key cache. include/myisam.h: New feature: preload indexes into key cache. --- include/my_base.h | 4 +- include/my_sys.h | 2 + include/myisam.h | 1 + myisam/Makefile.am | 1 + myisam/mi_extra.c | 3 ++ myisam/mi_preload.c | 118 ++++++++++++++++++++++++++++++++++++++++++++ myisam/myisamdef.h | 1 + mysys/mf_keycache.c | 80 ++++++++++++++++++++++++++++++ sql/ha_myisam.cc | 66 +++++++++++++++++++++++++ sql/ha_myisam.h | 1 + sql/handler.cc | 5 ++ sql/handler.h | 1 + sql/lex.h | 2 + sql/mysql_priv.h | 5 ++ sql/mysqld.cc | 6 +++ sql/set_var.cc | 4 ++ sql/sql_base.cc | 6 +-- sql/sql_class.h | 1 + sql/sql_lex.h | 2 +- sql/sql_parse.cc | 10 ++++ sql/sql_table.cc | 23 +++++++++ sql/sql_yacc.yy | 61 +++++++++++++++++++++-- sql/table.h | 1 + 23 files changed, 395 insertions(+), 9 deletions(-) create mode 100644 myisam/mi_preload.c diff --git a/include/my_base.h b/include/my_base.h index b806436fe0e..167c062deb5 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -123,7 +123,8 @@ enum ha_extra_function { HA_EXTRA_NO_IGNORE_DUP_KEY, HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */ HA_EXTRA_PREPARE_FOR_DELETE, - HA_EXTRA_PREPARE_FOR_UPDATE /* Remove read cache if problems */ + HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */ + HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */ }; /* The following is parameter to ha_panic() */ @@ -255,6 +256,7 @@ enum ha_base_keytype { #define HA_ERR_CANNOT_ADD_FOREIGN 150 /* Cannot add a foreign key constr. */ #define HA_ERR_NO_REFERENCED_ROW 151 /* Cannot add a child row */ #define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */ +#define HA_ERR_NON_UNIQUE_BLOCK_SIZE 153 /* Non unique key block size */ /* Other constants */ diff --git a/include/my_sys.h b/include/my_sys.h index 86ca6ec6a1f..75a7627dc07 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -644,6 +644,8 @@ extern int init_key_cache(ulong use_mem); extern int resize_key_cache(ulong use_mem); extern byte *key_cache_read(File file,my_off_t filepos,byte* buff,uint length, uint block_length,int return_buffer); +extern int key_cache_insert(File file, my_off_t filepos, + byte *buff, uint length); extern int key_cache_write(File file,my_off_t filepos,byte* buff,uint length, uint block_length,int force_write); extern int flush_key_blocks(int file, enum flush_type type); diff --git a/include/myisam.h b/include/myisam.h index 33aa6aa3f31..e85d3057672 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -410,6 +410,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows); void mi_flush_bulk_insert(MI_INFO *info, uint inx); void mi_end_bulk_insert(MI_INFO *info); +int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves); #ifdef __cplusplus } diff --git a/myisam/Makefile.am b/myisam/Makefile.am index f8225868d96..d4cd953ac66 100644 --- a/myisam/Makefile.am +++ b/myisam/Makefile.am @@ -47,6 +47,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \ mi_range.c mi_dbug.c mi_checksum.c mi_log.c \ mi_changed.c mi_static.c mi_delete_all.c \ mi_delete_table.c mi_rename.c mi_check.c \ + mi_preload.c \ ft_parser.c ft_stopwords.c ft_static.c \ ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \ rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c index 75057dd4e6a..4b71f3a867b 100644 --- a/myisam/mi_extra.c +++ b/myisam/mi_extra.c @@ -367,6 +367,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) if (!share->state.header.uniques) info->opt_flag|= OPT_NO_ROWS; break; + case HA_EXTRA_PRELOAD_BUFFER_SIZE: + info->preload_buff_size= *((ulong *) extra_arg); + break; case HA_EXTRA_KEY_CACHE: case HA_EXTRA_NO_KEY_CACHE: default: diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c new file mode 100644 index 00000000000..be45be66ecf --- /dev/null +++ b/myisam/mi_preload.c @@ -0,0 +1,118 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* + Preload indexes into key cache +*/ + +#include "myisamdef.h" + + +/* + Preload pages of the index file for a table into the key cache + + SYNOPSIS + mi_preload() + info open table + map map of indexes to preload into key cache + ignore_leaves only non-leaves pages are to be preloaded + + RETURN VALUE + 0 if a success. error code - otherwise. + + NOTES. + At present pages for all indexes are preloaded. + In future only pages for indexes specified in the key_map parameter + of the table will be preloaded. +*/ + +int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) +{ + uint i; + uint length; + uint block_length= 0; + uchar *buff= NULL; + MYISAM_SHARE* share= info->s; + uint keys= share->state.header.keys; + MI_KEYDEF *keyinfo= share->keyinfo; + my_off_t key_file_length= share->state.state.key_file_length; + my_off_t pos= share->base.keystart; + + if (!keys || !key_map || key_file_length == pos) + return 0; + + block_length= keyinfo[0].block_length; + + if (!key_map) + return 0; + + /* Check whether all indexes use the same block size */ + for (i= 1 ; i < keys ; i++) + { + if (keyinfo[i].block_length != block_length) + return (my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); + } + + length= info->preload_buff_size/block_length * block_length; + set_if_bigger(length, block_length); + + if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME)))) + return (my_errno= HA_ERR_OUT_OF_MEM); + + if (flush_key_blocks(share->kfile, FLUSH_RELEASE)) + goto err; + + do + { + /* Read the next block of index file into the preload buffer */ + set_if_smaller(length, key_file_length-pos); + if (my_pread(share->kfile, (byte*) buff, length, pos, MYF(MY_FAE))) + goto err; + + if (ignore_leaves) + { + uchar *end= buff+length; + do + { + if (mi_test_if_nod(buff)) + { + if (key_cache_insert(share->kfile, pos, (byte*) buff, block_length)) + goto err; + } + pos+= block_length; + } + while ((buff+= block_length) != end); + buff= end-length; + } + else + { + if (key_cache_insert(share->kfile, pos, (byte*) buff, length)) + goto err; + pos+= length; + } + + } + while (pos != key_file_length); + + my_free(buff, MYF(0)); + + return 0; + +err: + my_free(buff, MYF(MY_ALLOW_ZERO_PTR)); + return (my_errno= errno); +} + diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 50320f1ecbd..9321a3918e2 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -262,6 +262,7 @@ struct st_myisam_info { int save_lastinx; LIST open_list; IO_CACHE rec_cache; /* When cacheing records */ + uint preload_buff_size; /* When preloading indexes */ myf lock_wait; /* is 0 or MY_DONT_WAIT */ my_bool was_locked; /* Was locked in panic */ my_bool quick_mode; diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 264037e9a70..3276044fc2f 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1258,6 +1258,86 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length, } +/* + Insert a block of file data from a buffer into key cache + + SYNOPSIS + key_cache_insert() + file file descriptor + filepos file offset of the data from the buffer + buff buffer with data to insert into key cache + length length of the data in the buffer + + RETURN VALUE + 0 if a success, 1 -otherwise. +*/ + +int key_cache_insert(File file, my_off_t filepos, byte *buff, uint length) +{ + DBUG_ENTER("key_cache_insert"); + DBUG_PRINT("enter", ("file %u, filepos %lu, length %u", + (uint) file,(ulong) filepos, length)); + + if (my_disk_blocks > 0) + { + /* Key cache is used */ + reg1 BLOCK_LINK *block; + uint offset= (uint) (filepos & (key_cache_block_size-1)); + uint read_length; + int page_st; + + /* Read data into key cache from buff in key_cache_block_size increments */ + filepos-= offset; + do + { + read_length= length > key_cache_block_size ? + key_cache_block_size : length; + KEYCACHE_DBUG_ASSERT(read_length > 0); + keycache_pthread_mutex_lock(&THR_LOCK_keycache); + my_cache_r_requests++; + block=find_key_block(file, filepos, 0, &page_st); + if (block->status != BLOCK_ERROR && page_st != PAGE_READ) + { + /* The requested page is to be read into the block buffer */ +#if !defined(SERIALIZED_READ_FROM_CACHE) + keycache_pthread_mutex_unlock(&THR_LOCK_keycache); +#endif + + /* Copy data from buff */ + if (!(read_length & 511)) + bmove512(block->buffer+offset, buff, read_length); + else + memcpy(block->buffer+offset, buff, (size_t) read_length); + +#if !defined(SERIALIZED_READ_FROM_CACHE) + keycache_pthread_mutex_lock(&THR_LOCK_keycache); +#endif + block->status= BLOCK_READ; + block->length= read_length+offset; + } + + remove_reader(block); + /* + Link the block into the LRU chain + if it's the last submitted request for the block + */ + unreg_request(block,1); + + keycache_pthread_mutex_unlock(&THR_LOCK_keycache); + + if (block->status & BLOCK_ERROR) + DBUG_RETURN(1); + + buff+=read_length; + filepos+=read_length; + offset=0; + + } while ((length-= read_length)); + } + DBUG_RETURN(0); +} + + /* Write a buffer into disk; filepos must be a multiple of 'block_length', but it doesn't diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 213f5baf388..d9b9f3130de 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -674,6 +674,72 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize) } +/* + Preload pages of the index file for a table into the key cache. +*/ + +int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) +{ + int error; + const char *errmsg; + ulonglong map= ~(ulonglong) 0; + TABLE_LIST *table_list= table->pos_in_table_list; + my_bool ignore_leaves= table_list->ignore_leaves; + + DBUG_ENTER("ha_myisam::preload_keys"); + + /* Check validity of the index references */ + if (table_list->use_index) + { + key_map kmap= get_key_map_from_key_list(table, table_list->use_index); + if (kmap == ~(key_map) 0) + { + errmsg= thd->net.last_error; + error= HA_ADMIN_FAILED; + goto err; + } + if (kmap) + map= kmap; + } + + mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE, + (void *) &thd->variables.preload_buff_size); + + if ((error= mi_preload(file, map, ignore_leaves))) + { + switch (error) { + case HA_ERR_NON_UNIQUE_BLOCK_SIZE: + errmsg= "Indexes use different block sizes"; + break; + case HA_ERR_OUT_OF_MEM: + errmsg= "Failed to allocate buffer"; + break; + default: + char buf[ERRMSGSIZE+20]; + my_snprintf(buf, ERRMSGSIZE, + "Failed to read from index file (errno: %d)", my_errno); + errmsg= buf; + } + error= HA_ADMIN_FAILED; + goto err; + } + + DBUG_RETURN(HA_ADMIN_OK); + + err: + { + MI_CHECK param; + myisamchk_init(¶m); + param.thd= thd; + param.op_name= (char*)"preload_keys"; + param.db_name= table->table_cache_key; + param.table_name= table->table_name; + param.testflag= 0; + mi_check_print_error(¶m, errmsg); + DBUG_RETURN(error); + } +} + /* Deactive all not unique index that can be recreated fast diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index 154429ecc0d..8486e25556b 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -127,6 +127,7 @@ class ha_myisam: public handler int optimize(THD* thd, HA_CHECK_OPT* check_opt); int restore(THD* thd, HA_CHECK_OPT* check_opt); int backup(THD* thd, HA_CHECK_OPT* check_opt); + int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); #ifdef HAVE_REPLICATION int dump(THD* thd, int fd); int net_read_dump(NET* net); diff --git a/sql/handler.cc b/sql/handler.cc index f2b7dbdf531..e84c9bf3569 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -588,6 +588,11 @@ int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt) return HA_ADMIN_NOT_IMPLEMENTED; } +int handler::preload_keys(THD* thd, HA_CHECK_OPT* check_opt) +{ + return HA_ADMIN_NOT_IMPLEMENTED; +} + /* Read first row (only) from a table This is never called for InnoDB or BDB tables, as these table types diff --git a/sql/handler.h b/sql/handler.h index 8c23a3625e0..a2408ab0fe0 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -304,6 +304,7 @@ public: virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt); virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt); virtual int backup(THD* thd, HA_CHECK_OPT* check_opt); + virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); /* restore assumes .frm file must exist, and that generate_table() has been called; It will just copy the data file and run repair. diff --git a/sql/lex.h b/sql/lex.h index f85431aadf7..0cbc048e00c 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -221,6 +221,7 @@ static SYMBOL symbols[] = { { "KILL", SYM(KILL_SYM),0,0}, { "LAST", SYM(LAST_SYM),0,0}, { "LEADING", SYM(LEADING),0,0}, + { "LEAVES", SYM(LEAVES),0,0}, { "LEFT", SYM(LEFT),0,0}, { "LEVEL", SYM(LEVEL_SYM),0,0}, { "LIKE", SYM(LIKE),0,0}, @@ -299,6 +300,7 @@ static SYMBOL symbols[] = { { "POLYGON", SYM(POLYGON),0,0}, { "PURGE", SYM(PURGE),0,0}, { "PRECISION", SYM(PRECISION),0,0}, + { "PRELOAD", SYM(PRELOAD),0,0}, { "PREV", SYM(PREV_SYM),0,0}, { "PRIMARY", SYM(PRIMARY_SYM),0,0}, { "PROCEDURE", SYM(PROCEDURE),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index ea6e544a1fd..e0c3f5aeaec 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -246,6 +246,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); /* Options to add_table_to_list() */ #define TL_OPTION_UPDATING 1 #define TL_OPTION_FORCE_INDEX 2 +#define TL_OPTION_IGNORE_LEAVES 4 /* Some portable defines */ @@ -393,6 +394,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list, HA_CHECK_OPT* check_opt); int mysql_optimize_table(THD* thd, TABLE_LIST* table_list, HA_CHECK_OPT* check_opt); +int mysql_preload_keys(THD* thd, TABLE_LIST* table_list); + bool check_simple_select(); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); @@ -584,6 +587,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, extern const Item **not_found_item; Item ** find_item_in_list(Item *item, List &items, uint *counter, find_item_error_report_type report_error); +key_map get_key_map_from_key_list(TABLE *table, + List *index_list); bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator *it); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f73bd6721f0..7f3c69cb7c9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3464,6 +3464,7 @@ enum options OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT, OPT_OPEN_FILES_LIMIT, + OPT_PRELOAD_BUFFER_SIZE, OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE, OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER, OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE, @@ -4244,6 +4245,11 @@ Disable with --skip-isam", "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.", (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 65535, 0, 1, 0}, + {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, + "The size of the buffer that is allocated when preloading indexes", + (gptr*) &global_system_variables.preload_buff_size, + (gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG, + REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, "Don't cache results that are bigger than this.", diff --git a/sql/set_var.cc b/sql/set_var.cc index e4adbb0a318..ddaef4c4e14 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -199,6 +199,8 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count", &SV::net_retry_count, fix_net_retry_count); sys_var_thd_bool sys_new_mode("new", &SV::new_mode); +sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size", + &SV::preload_buff_size); sys_var_thd_ulong sys_read_buff_size("read_buffer_size", &SV::read_buff_size); sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size", @@ -402,6 +404,7 @@ sys_var *sys_variables[]= &sys_net_wait_timeout, &sys_net_write_timeout, &sys_new_mode, + &sys_preload_buff_size, &sys_pseudo_thread_id, &sys_query_cache_size, #ifdef HAVE_QUERY_CACHE @@ -573,6 +576,7 @@ struct show_var_st init_vars[]= { {"log_error", (char*) log_error_file, SHOW_CHAR}, {"port", (char*) &mysql_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, + {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index fc95f5deb40..c7db77e1d84 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -35,8 +35,6 @@ static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, const char *name, const char *alias); static void free_cache_entry(TABLE *entry); static void mysql_rm_tmp_tables(void); -static key_map get_key_map_from_key_list(TABLE *table, - List *index_list); extern "C" byte *table_cache_key(const byte *record,uint *length, @@ -2058,8 +2056,8 @@ bool setup_tables(TABLE_LIST *tables) } -static key_map get_key_map_from_key_list(TABLE *table, - List *index_list) +key_map get_key_map_from_key_list(TABLE *table, + List *index_list) { key_map map=0; List_iterator_fast it(*index_list); diff --git a/sql/sql_class.h b/sql/sql_class.h index 925afde2202..996331b071f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -365,6 +365,7 @@ struct system_variables ulong net_retry_count; ulong net_wait_timeout; ulong net_write_timeout; + ulong preload_buff_size; ulong query_cache_type; ulong read_buff_size; ulong read_rnd_buff_size; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f31b3305e07..04f784e62dc 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -59,7 +59,7 @@ enum enum_sql_command { SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, - SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, + SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_PRELOAD_KEYS, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_COMMIT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1d2449839d8..2596d349a1c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1819,6 +1819,15 @@ mysql_execute_command(THD *thd) res = mysql_restore_table(thd, tables); break; } + case SQLCOM_PRELOAD_KEYS: + { + if (check_db_used(thd, tables) || + check_access(thd, INDEX_ACL, tables->db, &tables->grant.privilege)) + goto error; + res = mysql_preload_keys(thd, tables); + break; + } + #ifndef EMBEDDED_LIBRARY case SQLCOM_CHANGE_MASTER: @@ -3937,6 +3946,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->lock_type= lock_type; ptr->updating= test(table_options & TL_OPTION_UPDATING); ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); + ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES); ptr->derived= table->sel; if (use_index) ptr->use_index=(List *) thd->memdup((gptr) use_index, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3cac88d05b2..a73f55077c9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1331,6 +1331,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, goto err; continue; } + table->table->pos_in_table_list= table; if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) { char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; @@ -1486,6 +1487,28 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) } +/* + Preload specified indexes for a table into key cache + + SYNOPSIS + mysql_preload_keys() + thd Thread object + tables Table list (one table only) + + RETURN VALUES + 0 ok + -1 error +*/ + +int mysql_preload_keys(THD* thd, TABLE_LIST* tables) +{ + DBUG_ENTER("mysql_preload_keys"); + DBUG_RETURN(mysql_admin_table(thd, tables, 0, + "preload_keys", TL_READ, 0, 0, 0, + &handler::preload_keys)); +} + + /* Create a table identical to the specified table diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e3b2c738949..6c120574644 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -256,6 +256,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token KEY_SYM %token LEADING %token LEAST_SYM +%token LEAVES %token LEVEL_SYM %token LEX_HOSTNAME %token LIKE @@ -309,6 +310,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token DUMPFILE %token PACK_KEYS_SYM %token PARTIAL +%token PRELOAD %token PRIMARY_SYM %token PRIVILEGES %token PROCESS @@ -584,7 +586,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); type int_type real_type order_dir opt_field_spec lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type - delete_option opt_temporary all_or_any opt_distinct + delete_option opt_temporary all_or_any opt_distinct opt_ignore_leafs %type ULONG_NUM raid_types merge_insert_types @@ -613,7 +615,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); key_alg opt_btree_or_rtree %type - key_usage_list + key_usage_list %type key_part @@ -661,10 +663,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type query verb_clause create change select do drop insert replace insert2 insert_values update delete truncate rename - show describe load alter optimize flush + show describe load alter optimize preload flush reset purge begin commit rollback slave master_def master_defs repair restore backup analyze check start field_list field_list_item field_spec kill column_def key_def + preload_list preload_keys select_item_list select_item values_list no_braces opt_limit_clause delete_limit_clause fields opt_values values procedure_list procedure_list2 procedure_item @@ -733,6 +736,7 @@ verb_clause: | lock | kill | optimize + | preload | purge | rename | repair @@ -1824,6 +1828,55 @@ table_to_table: YYABORT; }; +preload: + PRELOAD + { + LEX *lex=Lex; + lex->sql_command=SQLCOM_PRELOAD_KEYS; + } + preload_list + {} + ; + +preload_list: + preload_keys + | preload_list ',' preload_keys; + +preload_keys: + table_ident preload_keys_spec opt_ignore_leafs + { + LEX *lex=Lex; + SELECT_LEX *sel= &lex->select_lex; + if (!sel->add_table_to_list(lex->thd, $1, NULL, $3, + TL_READ, + sel->get_use_index(), + (List *)0)) + YYABORT; + } + ; + +preload_keys_spec: + keys_or_index { Select->select_lex()->interval_list.empty(); } + preload_key_list_or_empty + { + LEX *lex=Lex; + SELECT_LEX *sel= &lex->select_lex; + sel->use_index= sel->interval_list; + sel->use_index_ptr= &sel->use_index; + } + ; + +preload_key_list_or_empty: + /* empty */ + | '(' key_usage_list2 ')' {} + ; + +opt_ignore_leafs: + /* empty */ + { $$= 0; } + | IGNORE_SYM LEAVES { $$= TL_OPTION_IGNORE_LEAVES; } + ; + /* Select : retrieve data from table */ @@ -4251,6 +4304,7 @@ keyword: | INSERT_METHOD {} | RELAY_THREAD {} | LAST_SYM {} + | LEAVES {} | LEVEL_SYM {} | LINESTRING {} | LOCAL_SYM {} @@ -4294,6 +4348,7 @@ keyword: | PASSWORD {} | POINT_SYM {} | POLYGON {} + | PRELOAD {} | PREV_SYM {} | PROCESS {} | PROCESSLIST_SYM {} diff --git a/sql/table.h b/sql/table.h index 2aefe23cb2f..3132e72fb2f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -181,6 +181,7 @@ typedef struct st_table_list bool straight; /* optimize with prev table */ bool updating; /* for replicate-do/ignore table */ bool force_index; /* Prefer index over table scan */ + bool ignore_leaves; /* Preload only non-leaf nodes */ } TABLE_LIST; typedef struct st_changed_table_list From f3ecad8cc99f0db0c891fe51d1099c7bc5273078 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jun 2003 05:26:50 -0700 Subject: [PATCH 346/399] preload.result, preload.test: new file --- mysql-test/r/preload.result | 214 ++++++++++++++++++++++++++++++++++++ mysql-test/t/preload.test | 101 +++++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 mysql-test/r/preload.result create mode 100755 mysql-test/t/preload.test diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result new file mode 100644 index 00000000000..0afd95b6fb8 --- /dev/null +++ b/mysql-test/r/preload.result @@ -0,0 +1,214 @@ +drop table if exists t1, t2; +create table t1 ( +a int not null auto_increment, +b char(16) not null, +primary key (a), +key (b) +); +create table t2( +a int not null auto_increment, +b char(16) not null, +primary key (a), +key (b) +); +insert into t1(b) values +('test0'), +('test1'), +('test2'), +('test3'), +('test4'), +('test5'), +('test6'), +('test7'); +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +select count(*) from t1; +count(*) +33448 +select count(*) from t2; +count(*) +20672 +flush tables; +flush status; +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +select count(*) from t1 where b = 'test1'; +count(*) +4181 +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 217 +Key_reads 45 +Key_write_requests 0 +Key_writes 0 +select count(*) from t1 where b = 'test1'; +count(*) +4181 +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 434 +Key_reads 45 +Key_write_requests 0 +Key_writes 0 +flush tables; +flush status; +select @@preload_buffer_size; +@@preload_buffer_size +32768 +preload t1 keys; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +show status like "preload_%"; +Variable_name Value +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +select count(*) from t1 where b = 'test1'; +count(*) +4181 +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 217 +Key_reads 45 +Key_write_requests 0 +Key_writes 0 +flush tables; +flush status; +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +set session preload_buffer_size=256*1024; +select @@preload_buffer_size; +@@preload_buffer_size +262144 +preload t1 keys ignore leaves; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +select count(*) from t1 where b = 'test1'; +count(*) +4181 +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 217 +Key_reads 45 +Key_write_requests 0 +Key_writes 0 +flush tables; +flush status; +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +set session preload_buffer_size=1*1024; +select @@preload_buffer_size; +@@preload_buffer_size +1024 +preload t1 keys, t2 keys (primary,b) ignore leaves; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +test.t2 preload_keys status OK +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +select count(*) from t1 where b = 'test1'; +count(*) +4181 +select count(*) from t2 where b = 'test1'; +count(*) +2584 +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 351 +Key_reads 73 +Key_write_requests 0 +Key_writes 0 +flush tables; +flush status; +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +preload t3 keys, t2 keys (primary,b) ; +Table Op Msg_type Msg_text +test.t3 preload_keys error Table 'test.t3' doesn't exist +test.t2 preload_keys status OK +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +flush tables; +flush status; +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +preload t3 keys (b), t2 keys (c) ; +Table Op Msg_type Msg_text +test.t3 preload_keys error Table 'test.t3' doesn't exist +test.t2 preload_keys error Key column 'c' doesn't exist in table +test.t2 preload_keys status Operation failed +show status like "key_%"; +Variable_name Value +Key_blocks_used 918 +Key_read_requests 0 +Key_reads 0 +Key_write_requests 0 +Key_writes 0 +drop table t1, t2; diff --git a/mysql-test/t/preload.test b/mysql-test/t/preload.test new file mode 100755 index 00000000000..1fd0d0a5b17 --- /dev/null +++ b/mysql-test/t/preload.test @@ -0,0 +1,101 @@ +# +# Testing of PRELOAD +# + +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + + +create table t1 ( + a int not null auto_increment, + b char(16) not null, + primary key (a), + key (b) +); + +create table t2( + a int not null auto_increment, + b char(16) not null, + primary key (a), + key (b) +); + +insert into t1(b) values + ('test0'), + ('test1'), + ('test2'), + ('test3'), + ('test4'), + ('test5'), + ('test6'), + ('test7'); + +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; +insert into t2(b) select b from t1; +insert into t1(b) select b from t2; + +select count(*) from t1; +select count(*) from t2; + +flush tables; flush status; +show status like "key_%"; + +select count(*) from t1 where b = 'test1'; +show status like "key_%"; +select count(*) from t1 where b = 'test1'; +show status like "key_%"; + +flush tables; flush status; +select @@preload_buffer_size; +preload t1 keys; +show status like "preload_%"; +show status like "key_%"; +select count(*) from t1 where b = 'test1'; +show status like "key_%"; + +flush tables; flush status; +show status like "key_%"; +set session preload_buffer_size=256*1024; +select @@preload_buffer_size; +preload t1 keys ignore leaves; +show status like "key_%"; +select count(*) from t1 where b = 'test1'; +show status like "key_%"; + +flush tables; flush status; +show status like "key_%"; +set session preload_buffer_size=1*1024; +select @@preload_buffer_size; +preload t1 keys, t2 keys (primary,b) ignore leaves; +show status like "key_%"; +select count(*) from t1 where b = 'test1'; +select count(*) from t2 where b = 'test1'; +show status like "key_%"; + +flush tables; flush status; +show status like "key_%"; +preload t3 keys, t2 keys (primary,b) ; +show status like "key_%"; + +flush tables; flush status; +show status like "key_%"; +preload t3 keys (b), t2 keys (c) ; +show status like "key_%"; + +drop table t1, t2; From a921cb317483f5118d2505a591d841e5d7e217d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jun 2003 16:20:31 +0200 Subject: [PATCH 347/399] See each file's changeset for details. - Comments for future devs. - Start_log_event::exec_event() : when we hit it, do a rollback. - We don't need LOG_EVENT_FORCED_ROTATE_F. - Stop_log_event::exec_event() : when we hit it, we needn't clean anything. - Removed LOG_EVENT_TIME_F and LOG_EVENT_FORCED_ROTATE_F. - We don't need Stop events in the relay log. - Now filtering of server id is done in the I/O thread first. sql/log.cc: We don't need LOG_EVENT_FORCED_ROTATE_F sql/log_event.cc: - Comments for future devs. - Start_log_event::exec_event() : when we hit it, do a rollback. If the SQL thread was inside a transaction (for example, the master died while writing to the binlog, so did not commit (because we write to the binlog before committing), so will rollback), it's sensible to rollback. If we're not in a transaction, rollback will not hurt (it will do nothing). - We don't need LOG_EVENT_FORCED_ROTATE_F. - Stop_log_event::exec_event() : when we hit it, we needn't clean anything, because each threads has already written some cleaning statements (DROP TEMPORARY TABLE, DO RELEASE_LOCK); we still clean in Start_log_event::exec_event() (if 4.x). sql/log_event.h: - Comments for future devs. - Removed LOG_EVENT_TIME_F and LOG_EVENT_FORCED_ROTATE_F. sql/slave.cc: - We don't need Stop events in the relay log (see changeset's description about log_event.cc). So we can make event queuing (writing to the relay log) simpler. - Something that was marked TODO: now filtering of server id (if the server id of this event is the same as mine ignore it) is done in the I/O thread if the master is 4.x (it still also done in the SQL thread whatever the version of the master is, for safe upgrades). This saves disk space. sql/slave.h: We don't need master_info.ignore_stop_event anymore, as we don't write Stop_event to the relay log anymore. --- sql/log.cc | 8 ---- sql/log_event.cc | 59 ++++++++++++----------- sql/log_event.h | 119 ++++++++++++++++++++++++++++++++++++++++++----- sql/slave.cc | 79 ++++++++++++++++++++++--------- sql/slave.h | 2 - 5 files changed, 195 insertions(+), 72 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 0ccb40c5246..223df51d07f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -966,14 +966,6 @@ void MYSQL_LOG::new_file(bool need_lock) THD* thd = current_thd; Rotate_log_event r(thd,new_name+dirname_length(new_name)); r.set_log_pos(this); - - /* - Because this log rotation could have been initiated by a master of - the slave running with log-bin, we set the flag on rotate - event to prevent infinite log rotation loop - */ - if (thd->slave_thread) - r.flags|= LOG_EVENT_FORCED_ROTATE_F; r.write(&log_file); bytes_written += r.get_event_len(); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 3d500ede462..98a877616e0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1057,7 +1057,8 @@ int Start_log_event::write_data(IO_CACHE* file) The master started IMPLEMENTATION - - To handle the case where the master died without a stop event, + - To handle the case where the master died without having time to write DROP + TEMPORARY TABLE, DO RELEASE_LOCK (prepared statements' deletion is TODO), 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 @@ -1065,11 +1066,20 @@ int Start_log_event::write_data(IO_CACHE* file) on the slave when FLUSH LOGS is issued on the master). TODO - - Remove all active user locks + - Remove all active user locks. + Guilhem 2003-06: this is true but not urgent: the worst it can cause is + the use of a bit of memory for a user lock which will not be used + anymore. If the user lock is later used, the old one will be released. In + other words, no deadlock problem. - If we have an active transaction at this point, the master died in the middle while writing the transaction to the binary log. In this case we should stop the slave. - + Guilhem 2003-06: I don't think we should. As the binlog is written before + the table changes are committed, rollback has occured on the master; we + should rather rollback on the slave and go on. If we don't rollback, and + the next query is not BEGIN, then it will be considered as part of the + unfinished transaction, and so will be rolled back at next BEGIN, which is + a bug. */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) @@ -1079,6 +1089,11 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli) if (!rli->mi->old_format) { + /* + If the master died before writing the COMMIT to the binlog, rollback; + otherwise it does not hurt to rollback. + */ + ha_rollback(thd); /* If 4.0 master, all temporary tables have been deleted on the master; if 3.23 master, this is far from sure. @@ -1703,8 +1718,6 @@ void Rotate_log_event::pack_info(Protocol *protocol) b_pos+= ident_len; b_pos= strmov(b_pos, ";pos="); b_pos=longlong10_to_str(pos, b_pos, 10); - if (flags & LOG_EVENT_FORCED_ROTATE_F) - b_pos= strmov(b_pos ,"; forced by master"); protocol->store(buf, b_pos-buf, &my_charset_bin); my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); } @@ -1728,8 +1741,6 @@ void Rotate_log_event::print(FILE* file, bool short_form, char* last_db) my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, MYF(MY_NABP | MY_WME)); fprintf(file, " pos: %s", llstr(pos, buf)); - if (flags & LOG_EVENT_FORCED_ROTATE_F) - fprintf(file," forced by master"); fputc('\n', file); fflush(file); } @@ -2399,28 +2410,20 @@ void Stop_log_event::print(FILE* file, bool short_form, char* last_db) /* Stop_log_event::exec_event() - The master stopped. Clean up all temporary tables + locks that the - master may have set. - - TODO - - Remove all active user locks + The master stopped. + We used to clean up all temporary tables but this is useless as, as the master + has shut down properly, it has written all DROP TEMPORARY TABLE and DO + RELEASE_LOCK (prepared statements' deletion is TODO). + We used to clean up slave_load_tmpdir, but this is useless as it has been + cleared at the end of LOAD DATA INFILE. + So we have nothing to do here. + The place were we must do this cleaning is in Start_log_event::exec_event(), + not here. Because if we come here, the master was sane. */ #ifndef MYSQL_CLIENT int Stop_log_event::exec_event(struct st_relay_log_info* rli) { - /* - 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 occurred 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->group_master_log_pos > BIN_LOG_HEADER_SIZE) - { - close_temporary_tables(thd); - cleanup_load_tmpdir(); - } /* We do not want to update master_log pos because we get a rotate event before stop, so by now group_master_log_name is set to the next log. @@ -2965,10 +2968,10 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) goto err; } /* - We want to disable binary logging in slave thread because we need the file - events to appear in the same order as they do on the master relative to - other events, so that we can preserve ascending order of log sequence - numbers - needed to handle failover . + We are going to create a Load_log_event to finally load into the table. + This event should not go into the binlog: in the binlog we only want the + Create_file, Append_blocks and Execute_load. We disable binary logging and + restore the thread's options just after finishing the load. */ save_options = thd->options; thd->options &= ~ (ulong) (OPTION_BIN_LOG); diff --git a/sql/log_event.h b/sql/log_event.h index 1d2fc741fa8..bd5e1a82be4 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -34,15 +34,21 @@ #define LOG_READ_TOO_LARGE -7 #define LOG_EVENT_OFFSET 4 + #define BINLOG_VERSION 3 /* We could have used SERVER_VERSION_LENGTH, but this introduces an obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH - this would have broke the replication protocol + this would have broken the replication protocol */ #define ST_SERVER_VER_LEN 50 +/* + These are flags and structs to handle all the LOAD DATA INFILE options (LINES + TERMINATED etc). +*/ + #define DUMPFILE_FLAG 0x1 #define OPT_ENCLOSED_FLAG 0x2 #define REPLACE_FLAG 0x4 @@ -121,11 +127,17 @@ struct sql_ex_info See the #defines below for the format specifics. + The events which really update data are Query_log_event and + Load_log_event/Create_file_log_event/Execute_load_log_event (these 3 act + together to replicate LOAD DATA INFILE, with the help of + Append_block_log_event which prepares temporary files to load into the table). + ****************************************************************************/ +#define LOG_EVENT_HEADER_LEN 19 /* the fixed header length */ +#define OLD_HEADER_LEN 13 /* the fixed header length in 3.23 */ + /* event-specific post-header sizes */ -#define LOG_EVENT_HEADER_LEN 19 -#define OLD_HEADER_LEN 13 #define QUERY_HEADER_LEN (4 + 4 + 1 + 2) #define LOAD_HEADER_LEN (4 + 4 + 4 + 1 +1 + 4) #define START_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4) @@ -135,7 +147,10 @@ struct sql_ex_info #define EXEC_LOAD_HEADER_LEN 4 #define DELETE_FILE_HEADER_LEN 4 -/* event header offsets */ +/* + Event header offsets; + these point to places inside the fixed header. +*/ #define EVENT_TYPE_OFFSET 4 #define SERVER_ID_OFFSET 5 @@ -149,7 +164,7 @@ struct sql_ex_info #define ST_SERVER_VER_OFFSET 2 #define ST_CREATED_OFFSET (ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN) -/* slave event post-header */ +/* slave event post-header (this event is never written) */ #define SL_MASTER_PORT_OFFSET 8 #define SL_MASTER_POS_OFFSET 0 @@ -197,14 +212,20 @@ struct sql_ex_info #define R_POS_OFFSET 0 #define R_IDENT_OFFSET 8 +/* CF to DF handle LOAD DATA INFILE */ + +/* CF = "Create File" */ #define CF_FILE_ID_OFFSET 0 #define CF_DATA_OFFSET CREATE_FILE_HEADER_LEN +/* AB = "Append Block" */ #define AB_FILE_ID_OFFSET 0 #define AB_DATA_OFFSET APPEND_BLOCK_HEADER_LEN +/* EL = "Execute Load" */ #define EL_FILE_ID_OFFSET 0 +/* DF = "Delete File" */ #define DF_FILE_ID_OFFSET 0 #define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN) @@ -217,13 +238,31 @@ struct sql_ex_info #define EXEC_LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+EXEC_LOAD_HEADER_LEN) #define APPEND_BLOCK_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+APPEND_BLOCK_HEADER_LEN) - +/* 4 bytes which all binlogs should begin with */ #define BINLOG_MAGIC "\xfe\x62\x69\x6e" +/* + The 2 flags below were useless : + - the first one was never set + - the second one was set in all Rotate events on the master, but not used for + anything useful. + So they are now removed and their place may later be reused for other + flags. Then one must remember that Rotate events in 4.x have + LOG_EVENT_FORCED_ROTATE_F set, so one should not rely on the value of the + replacing flag when reading a Rotate event. + I keep the defines here just to remember what they were. +*/ +#ifdef TO_BE_REMOVED #define LOG_EVENT_TIME_F 0x1 -#define LOG_EVENT_FORCED_ROTATE_F 0x2 -#define LOG_EVENT_THREAD_SPECIFIC_F 0x4 /* query depends on thread - (for example: TEMPORARY TABLE) */ +#define LOG_EVENT_FORCED_ROTATE_F 0x2 +#endif +/* + If the query depends on the thread (for example: TEMPORARY TABLE). + Currently this is used by mysqlbinlog to know it must print + SET @@PSEUDO_THREAD_ID=xx; before the query (it would not hurt to print it + for every query but this would be slow). +*/ +#define LOG_EVENT_THREAD_SPECIFIC_F 0x4 enum Log_event_type { @@ -258,30 +297,81 @@ struct st_relay_log_info; class Log_event { public: + /* + The offset in the log where this event originally appeared (it is preserved + in relay logs, making SHOW SLAVE STATUS able to print coordinates of the + event in the master's binlog). Note: when a transaction is written by the + master to its binlog (wrapped in BEGIN/COMMIT) the log_pos of all the + queries it contains is the one of the BEGIN (this way, when one does SHOW + SLAVE STATUS it sees the offset of the BEGIN, which is logical as rollback + may occur), except the COMMIT query which has its real offset. + */ my_off_t log_pos; - char *temp_buf; + /* + A temp buffer for read_log_event; it is later analysed according to the + event's type, and its content is distributed in the event-specific fields. + */ + char *temp_buf; + /* + Timestamp on the master(for debugging and replication of NOW()/TIMESTAMP). + It is important for queries and LOAD DATA INFILE. This is set at the event's + creation time, except for Query and Load (et al.) events where this is set + at the query's execution time, which guarantees good replication (otherwise, + we could have a query and its event with different timestamps). + */ time_t when; + /* The number of seconds the query took to run on the master. */ ulong exec_time; + /* + The master's server id (is preserved in the relay log; used to prevent from + infinite loops in circular replication). + */ uint32 server_id; uint cached_event_len; + + /* + Some 16 flags. Only one is really used now; look above for + LOG_EVENT_TIME_F, LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F + for notes. + */ uint16 flags; + bool cache_stmt; #ifndef MYSQL_CLIENT THD* thd; Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt); Log_event(); + /* + read_log_event() functions read an event from a binlog or relay log; used by + SHOW BINLOG EVENTS, the binlog_dump thread on the master (reads master's + binlog), the slave IO thread (reads the event sent by binlog_dump), the + slave SQL thread (reads the event from the relay log). + */ // if mutex is 0, the read will proceed without mutex static Log_event* read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock, bool old_format); static int read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock); + /* set_log_pos() is used to fill log_pos with tell(log). */ void set_log_pos(MYSQL_LOG* log); + /* + init_show_field_list() prepares the column names and types for the output of + SHOW BINLOG EVENTS; it is used only by SHOW BINLOG EVENTS. + */ static void init_show_field_list(List* field_list); #ifdef HAVE_REPLICATION int net_send(Protocol *protocol, const char* log_name, my_off_t pos); + /* + pack_info() is used by SHOW BINLOG EVENTS; as print() it prepares and sends + a string to display to the user, so it resembles print(). + */ virtual void pack_info(Protocol *protocol); + /* + The SQL slave thread calls exec_event() to execute the event; this is where + the slave's data is modified. + */ virtual int exec_event(struct st_relay_log_info* rli); #endif /* HAVE_REPLICATION */ virtual const char* get_db() @@ -291,6 +381,7 @@ public: #else // avoid having to link mysqlbinlog against libpthread static Log_event* read_log_event(IO_CACHE* file, bool old_format); + /* print*() functions are used by mysqlbinlog */ virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0; void print_timestamp(FILE* file, time_t *ts = 0); void print_header(FILE* file); @@ -336,6 +427,7 @@ public: } static Log_event* read_log_event(const char* buf, int event_len, const char **error, bool old_format); + /* returns the human readable name of the event's type */ const char* get_type_str(); }; @@ -403,6 +495,8 @@ public: /***************************************************************************** Slave Log Event class + Note that this class is currently not used at all; no code writes a + Slave_log_event (though some code in repl_failsafe.cc reads Slave_log_event). ****************************************************************************/ class Slave_log_event: public Log_event @@ -593,7 +687,7 @@ public: Rand Log Event class - Logs random seed used by the next RAND() + Logs random seed used by the next RAND(), and by PASSWORD() in 4.1. ****************************************************************************/ class Rand_log_event: public Log_event @@ -626,6 +720,9 @@ class Rand_log_event: public Log_event User var Log Event class + Every time a query uses the value of a user variable, a User_var_log_event is + written before the Query_log_event, to set the user variable. + ****************************************************************************/ class User_var_log_event: public Log_event { diff --git a/sql/slave.cc b/sql/slave.cc index cc27bb96ab7..504bb0309cc 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1426,7 +1426,6 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname, DBUG_RETURN(0); mi->mysql=0; mi->file_id=1; - mi->ignore_stop_event=0; fn_format(fname, master_info_fname, mysql_data_home, "", 4+32); /* @@ -2746,6 +2745,8 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev) /* queue_old_event() + Writes a 3.23 event to the relay log. + TODO: Test this code before release - it has to be tested on a separate setup with 3.23 master @@ -2790,8 +2791,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, ev->log_pos = mi->master_log_pos; switch (ev->get_type_code()) { case STOP_EVENT: - ignore_event= mi->ignore_stop_event; - mi->ignore_stop_event=0; + ignore_event= 1; inc_pos= event_len; break; case ROTATE_EVENT: @@ -2801,7 +2801,6 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(1); } - mi->ignore_stop_event=1; inc_pos= 0; break; case CREATE_FILE_EVENT: @@ -2817,7 +2816,6 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, DBUG_RETURN(error); } default: - mi->ignore_stop_event=0; inc_pos= event_len; break; } @@ -2842,15 +2840,12 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, /* queue_event() - TODO: verify the issue with stop events, see if we need them at all - in the relay log */ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len) { int error= 0; ulong inc_pos; - bool ignore_event= 0; RELAY_LOG_INFO *rli= &mi->rli; DBUG_ENTER("queue_event"); @@ -2861,39 +2856,77 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len) /* TODO: figure out if other events in addition to Rotate - require special processing + require special processing. + Guilhem 2003-06 : I don't think so. */ switch (buf[EVENT_TYPE_OFFSET]) { case STOP_EVENT: - ignore_event= mi->ignore_stop_event; - mi->ignore_stop_event= 0; - inc_pos= event_len; - break; + /* + We needn't write this event to the relay log. Indeed, it just indicates a + master server shutdown. The only thing this does is cleaning. But cleaning + is already done on a per-master-thread basis (as the master server is + shutting down cleanly, it has written all DROP TEMPORARY TABLE and DO + RELEASE_LOCK; prepared statements' deletion are TODO). + + We don't even increment mi->master_log_pos, because we may be just after a + Rotate event. Btw, in a few milliseconds we are going to have a Start + event from the next binlog (unless the master is presently running without + --log-bin). + */ + goto err; case ROTATE_EVENT: { Rotate_log_event rev(buf,event_len,0); if (unlikely(process_io_rotate(mi,&rev))) { - pthread_mutex_unlock(&mi->data_lock); - DBUG_RETURN(1); + error= 1; + goto err; } - mi->ignore_stop_event= 1; + /* + Now the I/O thread has just changed its mi->master_log_name, so + incrementing mi->master_log_pos is nonsense. + */ inc_pos= 0; break; } default: - mi->ignore_stop_event= 0; inc_pos= event_len; break; } - - if (likely(!ignore_event && - !(error= rli->relay_log.appendv(buf,event_len,0)))) + + /* + If this event is originating from this server, don't queue it. + We don't check this for 3.23 events because it's simpler like this; 3.23 + will be filtered anyway by the SQL slave thread which also tests the server + id (we must also keep this test in the SQL thread, in case somebody + upgrades a 4.0 slave which has a not-filtered relay log). + + ANY event coming from ourselves can be ignored: it is obvious for queries; + for STOP_EVENT/ROTATE_EVENT/START_EVENT: these cannot come from ourselves + (--log-slave-updates would not log that) unless this slave is also its + direct master (an unsupported, useless setup!). + */ + + if (uint4korr(buf + SERVER_ID_OFFSET) == ::server_id) { + /* + Do not write it to the relay log. + We still want to increment, so that we won't re-read this event from the + master if the slave IO thread is now stopped/restarted (more efficient if + the events we are ignoring are big LOAD DATA INFILE). + */ mi->master_log_pos+= inc_pos; - DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); - rli->relay_log.harvest_bytes_written(&rli->log_space_total); - } + DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos)); + } + else /* write the event to the relay log */ + if (likely(!(error= rli->relay_log.appendv(buf,event_len,0)))) + { + mi->master_log_pos+= inc_pos; + DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); + rli->relay_log.harvest_bytes_written(&rli->log_space_total); + } + +err: pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); } diff --git a/sql/slave.h b/sql/slave.h index 1d00df67b22..429456eb0bb 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -308,8 +308,6 @@ typedef struct st_master_info bool old_format; /* master binlog is in 3.23 format */ volatile bool abort_slave, slave_running; volatile ulong slave_run_id; - bool ignore_stop_event; - st_master_info() :fd(-1), io_thd(0), inited(0), old_format(0),abort_slave(0), From a32fbfbdb14b6091513b09c593d74f9de9bcba2f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Jun 2003 23:16:21 +0200 Subject: [PATCH 348/399] user change to avoid conflicts with user 'test' mysql-test/t/rpl_temporary.test: user change to avoid conflicts with user 'test' (to which test connect.test gives password "gambling", so depending on the order of the tests, 'test' has password '' or 'gambling': better to use an unknown user which will be directed to ''@localhost with password always ''). --- mysql-test/t/rpl_temporary.test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 442788ad019..b50d9004f14 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -19,7 +19,9 @@ connection master; connect (con1,localhost,root,,); connect (con2,localhost,root,,); -connect (con3,localhost,test,,); +# user 'boo' does not exist, because we want to be ''@localhost or ''@127.0.0.1 +# (using user 'test' conflicts with what connect.test does). +connect (con3,localhost,boo,,); # We are going to use SET PSEUDO_THREAD_ID in this test; # check that it requires the SUPER privilege. From 5810811e6a3cb9c0ffb38f4f47b86d98b283a007 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Jun 2003 10:59:02 +0200 Subject: [PATCH 349/399] consistency fix - all help texts for command-line options should end with a dot. --- client/mysql.cc | 10 +- client/mysqladmin.c | 18 +-- client/mysqlbinlog.cc | 28 ++--- client/mysqlcheck.c | 14 +-- client/mysqldump.c | 14 +-- client/mysqlimport.c | 14 +-- client/mysqlmanager-pwgen.c | 8 +- client/mysqlshow.c | 16 +-- client/mysqltest.c | 29 +++-- extra/my_print_defaults.c | 13 +- extra/perror.c | 4 +- extra/resolveip.c | 2 +- include/sslopt-longopts.h | 12 +- myisam/ft_dump.c | 18 +-- myisam/myisamchk.c | 51 ++++---- myisam/myisampack.c | 4 +- sql/mysqld.cc | 238 ++++++++++++++++++------------------ tools/mysqlmanager.c | 14 +-- 18 files changed, 252 insertions(+), 255 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index a957f804537..66a2cebf89a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -563,12 +563,12 @@ static struct my_option my_long_options[] = {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.", (gptr*) ¤t_prompt, (gptr*) ¤t_prompt, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', - "Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file. ", + "Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file.", (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"raw", 'r', "Write fields without conversion. Used with --batch", + {"raw", 'r', "Write fields without conversion. Used with --batch.", (gptr*) &opt_raw_data, (gptr*) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"reconnect", OPT_RECONNECT, "Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default.", @@ -577,7 +577,7 @@ static struct my_option my_long_options[] = 0, 0}, #ifdef HAVE_SMEM {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"socket", 'S', "Socket file to use for connection.", @@ -601,7 +601,7 @@ static struct my_option my_long_options[] = {"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.", (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Write more. (-v -v -v gives the table output format)", 0, + {"verbose", 'v', "Write more. (-v -v -v gives the table output format).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqladmin.c b/client/mysqladmin.c index f5a9a70c820..018bcbc1963 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -113,16 +113,16 @@ static TYPELIB command_typelib= static struct my_option my_long_options[] = { {"count", 'c', - "Number of iterations to make. This works with -i (--sleep) only", + "Number of iterations to make. This works with -i (--sleep) only.", (gptr*) &nr_iterations, (gptr*) &nr_iterations, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Don't ask for confirmation on drop database; with multiple commands, continue even if an error occurs.", (gptr*) &option_force, (gptr*) &option_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"compress", 'C', "Use compression in server/client protocol", + {"compress", 'C', "Use compression in server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, @@ -130,7 +130,7 @@ static struct my_option my_long_options[] = (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_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', "Connect to host", (gptr*) &host, (gptr*) &host, 0, GET_STR, + {"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given it's asked from the tty.", @@ -141,7 +141,7 @@ static struct my_option my_long_options[] = #endif {"port", 'P', "Port number to use for connection.", (gptr*) &tcp_port, (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relative", 'r', "Show difference between current and previous values when used with -i. Currently works only with extended-status.", @@ -152,10 +152,10 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"silent", 's', "Silently exit if one can't connect to server", + {"silent", 's', "Silently exit if one can't connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "Socket file to use for connection.", (gptr*) &unix_port, (gptr*) &unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, @@ -170,13 +170,13 @@ static struct my_option my_long_options[] = #endif {"verbose", 'v', "Write more information.", (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"version", 'V', "Output version information and exit", 0, 0, 0, GET_NO_ARG, + {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"vertical", 'E', "Print output vertically. Is similar to --relative, but prints output vertically.", (gptr*) &opt_vertical, (gptr*) &opt_vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"wait", 'w', "Wait and retry if connection is down", 0, 0, 0, GET_UINT, + {"wait", 'w', "Wait and retry if connection is down.", 0, 0, 0, GET_UINT, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (gptr*) &opt_connect_timeout, (gptr*) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 3600*12, 0, diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index ff86882bad3..0ef0cb9b8c1 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -199,38 +199,38 @@ static struct my_option my_long_options[] = {"debug", '#', "Output debug log.", (gptr*) &default_dbug_option, (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"database", 'd', "List entries for just this database (local log only)", + {"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", + {"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", + {"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, + {"host", 'h', "Get the binlog from server.", (gptr*) &host, (gptr*) &host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"offset", 'o', "Skip the first N entries", (gptr*) &offset, (gptr*) &offset, + {"offset", 'o', "Skip the first N entries.", (gptr*) &offset, (gptr*) &offset, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"password", 'p', "Password to connect to remote server", + {"password", 'p', "Password to connect to remote server.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"port", 'P', "Use port to connect to the remote server", + {"port", 'P', "Use port to connect to the remote server.", (gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, - {"position", 'j', "Start reading the binlog at position N", + {"position", 'j', "Start reading the binlog at position N.", (gptr*) &position, (gptr*) &position, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"result-file", 'r', "Direct output to a given file", 0, 0, 0, GET_STR, + {"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"short-form", 's', "Just show the queries, no extra info", + {"short-form", 's', "Just show the queries, no extra info.", (gptr*) &short_form, (gptr*) &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"table", 't', "Get raw table dump using COM_TABLE_DUMB", (gptr*) &table, + {"table", 't', "Get raw table dump using COM_TABLE_DUMB.", (gptr*) &table, (gptr*) &table, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"user", 'u', "Connect to the remote server as username", + {"user", 'u', "Connect to the remote server as username.", (gptr*) &user, (gptr*) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"local-load", 'l', "Prepare files for local load in directory", - (gptr*) &dirname_for_local_load, (gptr*) &dirname_for_local_load, 0, + {"local-load", 'l', "Prepare files for local load in directory.", + (gptr*) &dirname_for_local_load, (gptr*) &dirname_for_local_load, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index b21a73aae4f..00767ae98a7 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -67,9 +67,9 @@ static struct my_option my_long_options[] = (gptr*) &opt_auto_repair, (gptr*) &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are", (gptr*) &charsets_dir, + "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"check", 'c', "Check table for errors", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, + {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"check-only-changed", 'C', "Check only tables that have changed since last check or haven't been closed properly.", @@ -81,12 +81,12 @@ static struct my_option my_long_options[] = "To check several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames.", (gptr*) &opt_databases, (gptr*) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set", (gptr*) &default_charset, + "Set the default character set.", (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"fast",'F', "Check only tables that haven't been closed properly", + {"fast",'F', "Check only tables that haven't been closed properly.", (gptr*) &opt_fast, (gptr*) &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Continue even if we get an sql-error.", @@ -115,7 +115,7 @@ static struct my_option my_long_options[] = {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "If you are using this option with CHECK TABLE, it prevents the check from scanning the rows to check for wrong links. This is the fastest check. If you are using this option with REPAIR TABLE, it will try to repair only the index tree. This is the fastest repair method for a table.", @@ -126,7 +126,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"silent", 's', "Print only error messages.", (gptr*) &opt_silent, diff --git a/client/mysqldump.c b/client/mysqldump.c index 67e83d58768..82737836485 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -132,7 +132,7 @@ static struct my_option my_long_options[] = "Allow creation of column names that are keywords.", (gptr*) &opt_keywords, (gptr*) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are", (gptr*) &charsets_dir, + "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compatible", OPT_COMPATIBLE, "Change the dump to be compatible with a given mode. By default tables are dumped without any restrictions. Legal modes are: mysql323, mysql40, postgresql, oracle, mssql, db2, sapdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option does a no operation on earlier server versions.", @@ -204,9 +204,9 @@ static struct my_option my_long_options[] = {"single-transaction", OPT_TRANSACTION, "Dump all tables in single transaction to get consistent snapshot. Mutually exclusive with --lock-tables.", (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, - GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-create-db", 'n', - "'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given.}", + "'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given.}.", (gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-create-info", 't', "Don't write table creation info.", @@ -227,17 +227,17 @@ static struct my_option my_long_options[] = "Password to use when connecting to server. If password is not given it's solicited on the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ - {"pipe", 'W', "Use named pipes to connect to server", 0, 0, 0, GET_NO_ARG, + {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "Don't buffer query, dump directly to stdout.", (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"quote-names",'Q', "Quote table and column names with a `", + {"quote-names",'Q', "Quote table and column names with backticks (`).", (gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"result-file", 'r', @@ -245,7 +245,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"skip-opt", OPT_SKIP_OPTIMIZATION, diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 8ee656f23b2..d049d69011b 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -59,7 +59,7 @@ static uint opt_protocol=0; static struct my_option my_long_options[] = { {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are", (gptr*) &charsets_dir, + "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", (gptr*) &default_charset, @@ -71,8 +71,8 @@ static struct my_option my_long_options[] = {"compress", 'C', "Use compression in server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug",'#', "Output debug log. Often this is 'd:t:o,filename'", 0, 0, 0, - GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, + GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"delete", 'd', "First delete all rows from table.", (gptr*) &opt_delete, (gptr*) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"fields-terminated-by", OPT_FTB, @@ -102,12 +102,12 @@ static struct my_option my_long_options[] = {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...", (gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"local", 'L', "Read all files through the client", (gptr*) &opt_local_file, + {"local", 'L', "Read all files through the client.", (gptr*) &opt_local_file, (gptr*) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"lock-tables", 'l', "Lock all tables for write.", (gptr*) &lock_tables, (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"low-priority", OPT_LOW_PRIORITY, - "Use LOW_PRIORITY when updating the table", (gptr*) &opt_low_priority, + "Use LOW_PRIORITY when updating the table.", (gptr*) &opt_low_priority, (gptr*) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given it's asked from the tty.", @@ -119,13 +119,13 @@ static struct my_option my_long_options[] = {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replace", 'r', "If duplicate unique key was found, replace old row.", (gptr*) &replace, (gptr*) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"silent", 's', "Be more silent.", (gptr*) &silent, (gptr*) &silent, 0, diff --git a/client/mysqlmanager-pwgen.c b/client/mysqlmanager-pwgen.c index 57d91b52f49..1d942e207ad 100644 --- a/client/mysqlmanager-pwgen.c +++ b/client/mysqlmanager-pwgen.c @@ -29,14 +29,14 @@ const char* outfile=0,*user="root"; static struct my_option my_long_options[] = { - {"output-file", 'o', "Write the output to the file with the given name", + {"output-file", 'o', "Write the output to the file with the given name.", (gptr*) &outfile, (gptr*) &outfile, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"user", 'u', "Put given user in the password file", (gptr*) &user, + {"user", 'u', "Put given user in the password file.", (gptr*) &user, (gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"help", '?', "Display this message and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, + {"help", '?', "Display this message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"version", 'V', "Display version info", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, + {"version", 'V', "Display version info.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 5bb611b713f..9dc5c0a30f4 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -155,16 +155,16 @@ int main(int argc, char **argv) static struct my_option my_long_options[] = { - {"character-sets-dir", 'c', "Directory where character sets are", + {"character-sets-dir", 'c', "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"compress", 'C', "Use compression in server/client protocol", + {"compress", 'C', "Use compression in server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_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}, @@ -173,10 +173,10 @@ static struct my_option my_long_options[] = {"status", 'i', "Shows a lot of extra information about each table.", (gptr*) &opt_status, (gptr*) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"keys", 'k', "Show keys for table", (gptr*) &opt_show_keys, + {"keys", 'k', "Show keys for table.", (gptr*) &opt_show_keys, (gptr*) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', - "Password to use when connecting to server. If password is not given it's asked from the tty.", + "Password to use when connecting to server. If password is not given it's asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, @@ -185,11 +185,11 @@ static struct my_option my_long_options[] = {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"socket", 'S', "Socket file to use for connection.", @@ -207,7 +207,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; - + static void print_version(void) { diff --git a/client/mysqltest.c b/client/mysqltest.c index 517c41c2b18..03a8206276f 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1808,34 +1808,34 @@ int read_query(struct st_query** q_ptr) static struct my_option my_long_options[] = { - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"basedir", 'b', "Basedir for tests", (gptr*) &opt_basedir, + {"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir, (gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"big-test", 'B', "Define BIG_TEST to 1", (gptr*) &opt_big_test, + {"big-test", 'B', "Define BIG_TEST to 1.", (gptr*) &opt_big_test, (gptr*) &opt_big_test, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"compress", 'C', "Use the compressed server/client protocol", + {"compress", 'C', "Use the compressed server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 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', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging", + {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging.", (gptr*) &manager_user, (gptr*) &manager_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"manager-host", OPT_MANAGER_HOST, "Undocumented: Used for debugging", + {"manager-host", OPT_MANAGER_HOST, "Undocumented: Used for debugging.", (gptr*) &manager_host, (gptr*) &manager_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"manager-password", OPT_MANAGER_PASSWD, "Undocumented: Used for debugging", + {"manager-password", OPT_MANAGER_PASSWD, "Undocumented: Used for debugging.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"manager-port", OPT_MANAGER_PORT, "Undocumented: Used for debugging", + {"manager-port", OPT_MANAGER_PORT, "Undocumented: Used for debugging.", (gptr*) &manager_port, (gptr*) &manager_port, 0, GET_INT, REQUIRED_ARG, MYSQL_MANAGER_PORT, 0, 0, 0, 0, 0}, {"manager-wait-timeout", OPT_MANAGER_WAIT_TIMEOUT, - "Undocumented: Used for debugging", (gptr*) &manager_wait_timeout, + "Undocumented: Used for debugging.", (gptr*) &manager_wait_timeout, (gptr*) &manager_wait_timeout, 0, GET_INT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -1848,16 +1848,16 @@ static struct my_option my_long_options[] = {"result-file", 'R', "Read/Store result from/in this file.", (gptr*) &result_file, (gptr*) &result_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"server-arg", 'A', "Send enbedded server this as a paramenter", + {"server-arg", 'A', "Send enbedded server this as a paramenter.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"server-file", 'F', "Read embedded server arguments from file", + {"server-file", 'F', "Read embedded server arguments from file.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"silent", 's', "Suppress all normal output. Synonym for --quiet.", (gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-safemalloc", OPT_SKIP_SAFEMALLOC, - "Don't use the memory allocation checking", 0, 0, 0, GET_NO_ARG, NO_ARG, + "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"sleep", 'T', "Sleep always this many seconds on sleep commands", + {"sleep", 'T', "Sleep always this many seconds on sleep commands.", (gptr*) &opt_sleep, (gptr*) &opt_sleep, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "Socket file to use for connection.", @@ -1866,7 +1866,7 @@ static struct my_option my_long_options[] = #include "sslopt-longopts.h" {"test-file", 'x', "Read test from/in this file (default stdin).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"tmpdir", 't', "Temporary directory where sockets are put", + {"tmpdir", 't', "Temporary directory where sockets are put.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"user", 'u', "User for login.", (gptr*) &user, (gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -1877,7 +1877,6 @@ static struct my_option my_long_options[] = { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; - static void print_version(void) { printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION, diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index c0f8a54f432..a5ce489c0fd 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -29,21 +29,21 @@ const char *config_file="my"; /* Default config file */ static struct my_option my_long_options[] = { - {"config-file", 'c', "The config file to be used", + {"config-file", 'c', "The config file to be used.", (gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"defaults-file", 'c', "Synonym for --config-file", + {"defaults-file", 'c', "Synonym for --config-file.", (gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"defaults-extra-file", 'e', + {"defaults-extra-file", 'e', "Read this file after the global /etc config file and before the config file in the users home directory.", (gptr*) &defaults_extra_file, (gptr*) &defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"extra-file", 'e', - "Synonym for --defaults-extra-file", + {"extra-file", 'e', + "Synonym for --defaults-extra-file.", (gptr*) &defaults_extra_file, (gptr*) &defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"no-defaults", 'n', "Return an empty string (useful for scripts)", + {"no-defaults", 'n', "Return an empty string (useful for scripts).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -52,7 +52,6 @@ static struct my_option my_long_options[] = {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; - static void usage(my_bool version) { printf("%s Ver 1.5 for %s at %s\n",my_progname,SYSTEM_TYPE, diff --git a/extra/perror.c b/extra/perror.c index a2951bff66a..1e47364bc5e 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -30,14 +30,14 @@ static struct my_option my_long_options[] = { {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"info", 'I', "Synonym for --help", 0, 0, 0, GET_NO_ARG, + {"info", 'I', "Synonym for --help.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SYS_ERRLIST {"all", 'a', "Print all the error messages and the number.", (gptr*) &print_all_codes, (gptr*) &print_all_codes, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"silent", 's', "Only print the error message", 0, 0, 0, GET_NO_ARG, NO_ARG, + {"silent", 's', "Only print the error message.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Print error code and message (default).", (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, diff --git a/extra/resolveip.c b/extra/resolveip.c index 95861bca2bc..cef79180720 100644 --- a/extra/resolveip.c +++ b/extra/resolveip.c @@ -43,7 +43,7 @@ static struct my_option my_long_options[] = { {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"info", 'I', "Synonym for --help", + {"info", 'I', "Synonym for --help.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"silent", 's', "Be more silent.", (gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index 397d8baa9d6..dc3b0922327 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -17,24 +17,24 @@ #ifdef HAVE_OPENSSL {"ssl", OPT_SSL_SSL, - "Enable SSL for connection (automatically enabled with other flags). Disable with --skip-ssl", + "Enable SSL for connection (automatically enabled with other flags). Disable with --skip-ssl.", (gptr*) &opt_use_ssl, (gptr*) &opt_use_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl)", + {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).", (gptr*) &opt_ssl_key, (gptr*) &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl)", + {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).", (gptr*) &opt_ssl_cert, (gptr*) &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-ca", OPT_SSL_CA, - "CA file in PEM format (check OpenSSL docs, implies --ssl)", + "CA file in PEM format (check OpenSSL docs, implies --ssl).", (gptr*) &opt_ssl_ca, (gptr*) &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-capath", OPT_SSL_CAPATH, - "CA directory (check OpenSSL docs, implies --ssl)", + "CA directory (check OpenSSL docs, implies --ssl).", (gptr*) &opt_ssl_capath, (gptr*) &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl)", + {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).", (gptr*) &opt_ssl_cipher, (gptr*) &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/myisam/ft_dump.c b/myisam/ft_dump.c index 67a99468645..57ae67c7a02 100644 --- a/myisam/ft_dump.c +++ b/myisam/ft_dump.c @@ -34,21 +34,23 @@ static uint lengths[256]; static struct my_option my_long_options[] = { - {"dump", 'd', "Dump index (incl. data offsets and word weights)", + {"dump", 'd', "Dump index (incl. data offsets and word weights).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"stats", 's', "Report global stats", + {"stats", 's', "Report global stats.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Be verbose", + {"verbose", 'v', "Be verbose.", (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"count", 'c', "Calculate per-word stats (counts and global weights)", + {"count", 'c', "Calculate per-word stats (counts and global weights).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"length", 'l', "Report length distribution", + {"length", 'l', "Report length distribution.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"execute", 'e', "Execute given query", (gptr*) &query, (gptr*) &query, 0, +#ifdef DISABLED + {"execute", 'e', "Execute given query.", (gptr*) &query, (gptr*) &query, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"help", 'h', "Display help and exit", +#endif + {"help", 'h', "Display help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"help", '?', "Synonym for -h", + {"help", '?', "Synonym for -h.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 834ad818972..72b2567278e 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -163,7 +163,7 @@ static struct my_option my_long_options[] = "No help available.", 0, 0, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"backup", 'B', - "Make a backup of the .MYD file as 'filename-time.BAK'", + "Make a backup of the .MYD file as 'filename-time.BAK'.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, "Directory where character sets are.", @@ -209,7 +209,7 @@ static struct my_option my_long_options[] = "Print statistics information about table that is checked.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"keys-used", 'k', - "Tell MyISAM to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts!", + "Tell MyISAM to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts.", (gptr*) &check_param.keys_in_use, (gptr*) &check_param.keys_in_use, 0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0}, @@ -225,7 +225,7 @@ static struct my_option my_long_options[] = "Can fix almost anything except unique keys that aren't unique.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"parallel-recover", 'p', - "Same as '-r' but creates all the keys in parallel", + "Same as '-r' but creates all the keys in parallel.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"safe-recover", 'o', "Uses old recovery method; Slower than '-r' but can handle a couple of cases where '-r' reports that it can't fix the data file.", @@ -337,9 +337,9 @@ static void usage(void) puts("Used without options all tables on the command will be checked for errors"); 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\ + -#, --debug=... Output debug log. Often this is 'd:t:o,filename'.\n\ -?, --help Display this help and exit.\n\ - -O, --set-variable var=option\n\ + -O, --set-variable var=option.\n\ Change the value of a variable. Please note that\n\ this option is deprecated; you can set variables\n\ directly with '--variable-name=value'.\n\ @@ -353,9 +353,9 @@ static void usage(void) ", they will be used\n\ in a round-robin fashion.\n\ -s, --silent Only print errors. One can use two -s to make\n\ - myisamchk very silent\n\ + myisamchk very silent.\n\ -v, --verbose Print more information. This can be used with\n\ - --description and --check. Use many -v for more verbosity!\n\ + --description and --check. Use many -v for more verbosity.\n\ -V, --version Print version and exit.\n\ -w, --wait Wait if table is locked.\n"); #ifdef DEBUG @@ -363,33 +363,33 @@ static void usage(void) #endif puts("Check options (check is the default action for myisamchk):\n\ - -c, --check Check table for errors\n\ + -c, --check Check table for errors.\n\ -e, --extend-check Check the table VERY throughly. Only use this in\n\ extreme cases as myisamchk should normally be able to\n\ - find out if the table is ok even without this switch\n\ - -F, --fast Check only tables that haven't been closed properly\n\ + find out if the table is ok even without this switch.\n\ + -F, --fast Check only tables that haven't been closed properly.\n\ -C, --check-only-changed\n\ - Check only tables that have changed since last check\n\ + Check only tables that have changed since last check.\n\ -f, --force Restart with '-r' if there are any errors in the table.\n\ - States will be updated as with '--update-state'\n\ - -i, --information Print statistics information about table that is checked\n\ + States will be updated as with '--update-state'.\n\ + -i, --information Print statistics information about table that is checked.\n\ -m, --medium-check Faster than extend-check, but only finds 99.99% of\n\ - all errors. Should be good enough for most cases\n\ - -U --update-state Mark tables as crashed if you find any errors\n\ - -T, --read-only Don't mark table as checked\n"); + all errors. Should be good enough for most cases.\n\ + -U --update-state Mark tables as crashed if you find any errors.\n\ + -T, --read-only Don't mark table as checked.\n"); - puts("Repair options (When using '-r' or '-o') \n\ - -B, --backup Make a backup of the .MYD file as 'filename-time.BAK'\n\ + puts("Repair options (When using '-r' or '-o'):\n\ + -B, --backup Make a backup of the .MYD file as 'filename-time.BAK'.\n\ --correct-checksum Correct checksum information for table.\n\ -D, --data-file-length=# Max length of data file (when recreating data\n\ - file when it's full)\n\ + file when it's full).\n\ -e, --extend-check Try to recover every possible row from the data file\n\ Normally this will also find a lot of garbage rows;\n\ Don't use this option if you are not totally desperate.\n\ -f, --force Overwrite old temporary files.\n\ -k, --keys-used=# Tell MyISAM to update only some specific keys. # is a\n\ bit mask of which keys to use. This can be used to\n\ - get faster inserts!\n\ + get faster inserts.\n\ -r, --recover Can fix almost anything except unique keys that aren't\n\ unique.\n\ -n, --sort-recover Forces recovering with sorting even if the temporary\n\ @@ -397,17 +397,16 @@ static void usage(void) -p, --parallel-recover\n\ Uses the same technique as '-r' and '-n', but creates\n\ all the keys in parallel, in different threads.\n\ - THIS IS ALPHA CODE. USE AT YOUR OWN RISK!\n\ -o, --safe-recover Uses old recovery method; Slower than '-r' but can\n\ handle a couple of cases where '-r' reports that it\n\ can't fix the data file.\n\ --character-sets-dir=...\n\ - Directory where character sets are\n\ + Directory where character sets are.\n\ --set-character-set=name\n\ - Change the character set used by the index\n\ + Change the character set used by the index.\n\ -q, --quick Faster repair by not modifying the data file.\n\ One can give a second '-q' to force myisamchk to\n\ - modify the original datafile in case of duplicate keys\n\ + modify the original datafile in case of duplicate keys.\n\ -u, --unpack Unpack file packed with myisampack.\n\ "); @@ -421,11 +420,11 @@ static void usage(void) If no value is given, then sets the next auto_increment\n\ value to the highest used value for the auto key + 1.\n\ -S, --sort-index Sort index blocks. This speeds up 'read-next' in\n\ - applications\n\ + applications.\n\ -R, --sort-records=#\n\ Sort records according to an index. This makes your\n\ data much more localized and may speed up things\n\ - (It may be VERY slow to do a sort the first time!)\n\ + (It may be VERY slow to do a sort the first time!).\n\ -b, --block-search=#\n\ Find a record, a block at given offset belongs to."); diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 3eded3b52f2..21b73ce244d 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -235,12 +235,12 @@ enum options_mp {OPT_CHARSETS_DIR_MP=256}; static struct my_option my_long_options[] = { - {"backup", 'b', "Make a backup of the table as table_name.OLD", + {"backup", 'b', "Make a backup of the table as table_name.OLD.", (gptr*) &backup, (gptr*) &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR_MP, "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Force packing of table even if it gets bigger or if tempfile exists.", diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3f3b2ee7c9f..df79e13da55 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3463,108 +3463,108 @@ enum options struct my_option my_long_options[] = { - {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax", 0, 0, 0, + {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"basedir", 'b', "Path to installation directory. All paths are usually resolved relative to this.", (gptr*) &mysql_home_ptr, (gptr*) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_BERKELEY_DB - {"bdb-home", OPT_BDB_HOME, "Berkeley home directory", (gptr*) &berkeley_home, + {"bdb-home", OPT_BDB_HOME, "Berkeley home directory.", (gptr*) &berkeley_home, (gptr*) &berkeley_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"bdb-lock-detect", OPT_BDB_LOCK, - "Berkeley lock detect (DEFAULT, OLDEST, RANDOM or YOUNGEST, # sec)", + "Berkeley lock detect (DEFAULT, OLDEST, RANDOM or YOUNGEST, # sec).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"bdb-logdir", OPT_BDB_LOG, "Berkeley DB log file directory", + {"bdb-logdir", OPT_BDB_LOG, "Berkeley DB log file directory.", (gptr*) &berkeley_logdir, (gptr*) &berkeley_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"bdb-no-recover", OPT_BDB_NO_RECOVER, - "Don't try to recover Berkeley DB tables on start", 0, 0, 0, GET_NO_ARG, + "Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"bdb-no-sync", OPT_BDB_NOSYNC, "Don't synchronously flush logs", 0, 0, 0, + {"bdb-no-sync", OPT_BDB_NOSYNC, "Don't synchronously flush logs.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"bdb-shared-data", OPT_BDB_SHARED, - "Start Berkeley DB in multi-process mode", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, + "Start Berkeley DB in multi-process mode.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"bdb-tmpdir", OPT_BDB_TMP, "Berkeley DB tempfile name", + {"bdb-tmpdir", OPT_BDB_TMP, "Berkeley DB tempfile name.", (gptr*) &berkeley_tmpdir, (gptr*) &berkeley_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_BERKELEY_DB */ {"bdb", OPT_BDB, "Enable Berkeley DB (if this version of MySQL supports it). \ -Disable with --skip-bdb (will save memory)", +Disable with --skip-bdb (will save memory).", (gptr*) &opt_bdb, (gptr*) &opt_bdb, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"big-tables", OPT_BIG_TABLES, - "Allow big result sets by saving all temporary sets on file (Solves most 'table full' errors)", + "Allow big result sets by saving all temporary sets on file (Solves most 'table full' errors).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-do-db", OPT_BINLOG_DO_DB, "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB, - "Tells the master that updates to the given database should not be logged tothe binary log", + "Tells the master that updates to the given database should not be logged tothe binary log.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to", + {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.", (gptr*) &my_bind_addr_str, (gptr*) &my_bind_addr_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts", 0, 0, 0, + {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows", + {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.", (gptr*) &opt_console, (gptr*) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ {"standalone", OPT_STANDALONE, - "Dummy option to start as a standalone program (NT)", 0, 0, 0, GET_NO_ARG, + "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"core-file", OPT_WANT_CORE, "Write core on errors", 0, 0, 0, GET_NO_ARG, + {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"chroot", 'r', "Chroot mysqld daemon during startup.", (gptr*) &mysqld_chroot, (gptr*) &mysqld_chroot, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are", (gptr*) &charsets_dir, + "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"datadir", 'h', "Path to the database root", (gptr*) &mysql_data_home, + {"datadir", 'h', "Path to the database root.", (gptr*) &mysql_data_home, (gptr*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF {"debug", '#', "Debug log.", (gptr*) &default_dbug_option, (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef SAFEMALLOC {"skip-safemalloc", OPT_SKIP_SAFEMALLOC, - "Don't use the memory allocation checking", 0, 0, 0, GET_NO_ARG, NO_ARG, + "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif #endif #ifdef HAVE_OPENSSL {"des-key-file", OPT_DES_KEY_FILE, - "Load keys for des_encrypt() and des_encrypt from given file", + "Load keys for des_encrypt() and des_encrypt from given file.", (gptr*) &des_key_file, (gptr*) &des_key_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_OPENSSL */ - {"default-character-set", 'C', "Set the default character set", - (gptr*) &default_character_set_name, (gptr*) &default_character_set_name, + {"default-character-set", 'C', "Set the default character set.", + (gptr*) &default_character_set_name, (gptr*) &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation", + {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation.", (gptr*) &default_collation_name, (gptr*) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-table-type", OPT_TABLE_TYPE, - "Set the default table type for tables", 0, 0, + "Set the default table type for tables.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE", + {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.", 0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE_ALL, - "Don't flush key buffers between writes for any MyISAM table (Deprecated option, use --delay-key-write=all instead)", + "Don't flush key buffers between writes for any MyISAM table (Deprecated option, use --delay-key-write=all instead).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"enable-locking", OPT_ENABLE_LOCK, - "Deprecated option, use --external-locking instead", + "Deprecated option, use --external-locking instead.", (gptr*) &opt_external_locking, (gptr*) &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NT__ - {"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT)", + {"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).", (gptr*) &opt_enable_named_pipe, (gptr*) &opt_enable_named_pipe, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure", + {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure.", (gptr*) &opt_do_pstack, (gptr*) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM @@ -3574,23 +3574,23 @@ Disable with --skip-bdb (will save memory)", #endif {"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands", 0, 0, 0, + {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN, "The maximum length of the result of function group_concat.", - (gptr*) &global_system_variables.group_concat_max_len, + (gptr*) &global_system_variables.group_concat_max_len, (gptr*) &max_system_variables.group_concat_max_len, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, (long) ~0, 0, 1, 0}, /* We must always support the next option to make scripts like mysqltest easier to do */ - {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role", 0, 0, 0, + {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH, - "Path to individual files and their sizes", + "Path to individual files and their sizes.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_INNOBASE_DB {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR, - "The common part for Innodb table spaces", (gptr*) &innobase_data_home_dir, + "The common part for Innodb table spaces.", (gptr*) &innobase_data_home_dir, (gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR, @@ -3598,53 +3598,52 @@ Disable with --skip-bdb (will save memory)", (gptr*) &innobase_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR, - "Where full logs should be archived", (gptr*) &innobase_log_arch_dir, + "Where full logs should be archived.", (gptr*) &innobase_log_arch_dir, (gptr*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_log_archive", OPT_INNODB_LOG_ARCHIVE, - "Set to 1 if you want to have logs archived", 0, 0, 0, GET_LONG, OPT_ARG, + "Set to 1 if you want to have logs archived.", 0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, - "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second)", + "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).", (gptr*) &innobase_flush_log_at_trx_commit, (gptr*) &innobase_flush_log_at_trx_commit, 0, GET_UINT, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD, - "With which method to flush data", (gptr*) &innobase_unix_file_flush_method, + "With which method to flush data.", (gptr*) &innobase_unix_file_flush_method, (gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN, - "Speeds up server shutdown process", (gptr*) &innobase_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, + "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, + {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup", + {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.", (gptr*) &opt_init_file, (gptr*) &opt_init_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"log", 'l', "Log connections and queries to file", (gptr*) &opt_logname, + {"log", 'l', "Log connections and queries to file.", (gptr*) &opt_logname, (gptr*) &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"language", 'L', - "Client error messages in given language. May be given as a full path", + "Client error messages in given language. May be given as a full path.", (gptr*) &language_ptr, (gptr*) &language_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"local-infile", OPT_LOCAL_INFILE, - "Enable/disable LOAD DATA LOCAL INFILE (takes values 1|0)", + "Enable/disable LOAD DATA LOCAL INFILE (takes values 1|0).", (gptr*) &opt_local_infile, (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"log-bin", OPT_BIN_LOG, - "Log update queries in binary format", + "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, - "File that holds the names for last binary log files", + "File that holds the names for last binary log files.", (gptr*) &opt_binlog_index_name, (gptr*) &opt_binlog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file", + {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.", (gptr*) &myisam_log_filename, (gptr*) &myisam_log_filename, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-update", OPT_UPDATE_LOG, @@ -3652,18 +3651,18 @@ Disable with --skip-bdb (will save memory)", (gptr*) &opt_update_logname, (gptr*) &opt_update_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-slow-queries", OPT_SLOW_QUERY_LOG, - "Log slow queries to this log file. Defaults logging to hostname-slow.log", + "Log slow queries to this log file. Defaults logging to hostname-slow.log file.", (gptr*) &opt_slow_logname, (gptr*) &opt_slow_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-long-format", OPT_LONG_FORMAT, - "Log some extra information to update log", 0, 0, 0, GET_NO_ARG, NO_ARG, + "Log some extra information to update log.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slave-updates", OPT_LOG_SLAVE_UPDATES, "Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.", (gptr*) &opt_log_slave_updates, (gptr*) &opt_log_slave_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"low-priority-updates", OPT_LOW_PRIORITY_UPDATES, - "INSERT/DELETE/UPDATE has lower priority than selects", + "INSERT/DELETE/UPDATE has lower priority than selects.", (gptr*) &global_system_variables.low_priority_updates, (gptr*) &max_system_variables.low_priority_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -3679,7 +3678,7 @@ Disable with --skip-bdb (will save memory)", "The password the slave thread will authenticate with when connecting to the master. If not set, an empty password is assumed.The value in master.info will take precedence if it can be read.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-port", OPT_MASTER_PORT, - "The port the master is listening on. If not set, the compiled setting of MYSQL_PORT is assumed. If you have not tinkered with configure options, this should be 3306. The value in master.info will take precedence if it can be read", + "The port the master is listening on. If not set, the compiled setting of MYSQL_PORT is assumed. If you have not tinkered with configure options, this should be 3306. The value in master.info will take precedence if it can be read.", (gptr*) &master_port, (gptr*) &master_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, {"master-connect-retry", OPT_MASTER_CONNECT_RETRY, @@ -3723,61 +3722,61 @@ Does nothing yet.", "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP or FORCE.", (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"memlock", OPT_MEMLOCK, "Lock mysqld in memory", (gptr*) &locked_in_memory, + {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (gptr*) &locked_in_memory, (gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT, - "Option used by mysql-test for debugging and testing of replication", + "Option used by mysql-test for debugging and testing of replication.", (gptr*) &disconnect_slave_event_count, (gptr*) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"abort-slave-event-count", OPT_ABORT_SLAVE_EVENT_COUNT, - "Option used by mysql-test for debugging and testing of replication", + "Option used by mysql-test for debugging and testing of replication.", (gptr*) &abort_slave_event_count, (gptr*) &abort_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS, - "Option used by mysql-test for debugging and testing of replication", + "Option used by mysql-test for debugging and testing of replication.", (gptr*) &max_binlog_dump_events, (gptr*) &max_binlog_dump_events, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL, - "Option used by mysql-test for debugging and testing of replication", + "Option used by mysql-test for debugging and testing of replication.", (gptr*) &opt_sporadic_binlog_dump_fail, (gptr*) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"safemalloc-mem-limit", OPT_SAFEMALLOC_MEM_LIMIT, - "Simulate memory shortage when compiled with the --with-debug=full option", + "Simulate memory shortage when compiled with the --with-debug=full option.", 0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"new", 'n', "Use very new possible 'unsafe' functions", + {"new", 'n', "Use very new possible 'unsafe' functions.", (gptr*) &global_system_variables.new_mode, (gptr*) &max_system_variables.new_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef NOT_YET - {"no-mix-table-types", OPT_NO_MIX_TYPE, "Don't allow commands with uses two different table types", + {"no-mix-table-types", OPT_NO_MIX_TYPE, "Don't allow commands with uses two different table types.", (gptr*) &opt_no_mix_types, (gptr*) &opt_no_mix_types, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"old-protocol", 'o', "Use the old (3.20) protocol client/server protocol", + {"old-protocol", 'o', "Use the old (3.20) protocol client/server protocol.", (gptr*) &protocol_version, (gptr*) &protocol_version, 0, GET_UINT, NO_ARG, PROTOCOL_VERSION, 0, 0, 0, 0, 0}, {"old-rpl-compat", OPT_OLD_RPL_COMPAT, - "Use old LOAD DATA format in the binary log (don't save data in file)", + "Use old LOAD DATA format in the binary log (don't save data in file).", (gptr*) &opt_old_rpl_compat, (gptr*) &opt_old_rpl_compat, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef ONE_THREAD {"one-thread", OPT_ONE_THREAD, - "Only use one thread (for debugging under Linux)", 0, 0, 0, GET_NO_ARG, + "Only use one thread (for debugging under Linux).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld", + {"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld.", (gptr*) &pidfile_name_ptr, (gptr*) &pidfile_name_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"log-error", OPT_ERROR_LOG_FILE, "Log error file", + {"log-error", OPT_ERROR_LOG_FILE, "Log error file.", (gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &mysql_port, (gptr*) &mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"reckless-slave", OPT_RECKLESS_SLAVE, "For debugging", 0, 0, 0, GET_NO_ARG, + {"reckless-slave", OPT_RECKLESS_SLAVE, "Used for debugging.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-do-db", OPT_REPLICATE_DO_DB, "Tells the slave thread to restrict replication to the specified database. To specify more than one database, use the directive multiple times, once for each database. Note that this will only work if you do not use cross-database queries such as UPDATE some_db.some_table SET foo='bar' while having selected a different or no database. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-do-table=db_name.%.", @@ -3786,7 +3785,7 @@ Does nothing yet.", "Tells the slave thread to restrict replication to the specified table. To specify more than one table, use the directive multiple times, once for each table. This will work for cross-database updates, in contrast to replicate-do-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE, - "Tells the slave thread to restrict replication to the tables that match the specified wildcard pattern. To specify more than one table, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-do-table=foo%.bar% will replicate only updates to tables in all databases that start with foo and whose table names start with bar", + "Tells the slave thread to restrict replication to the tables that match the specified wildcard pattern. To specify more than one table, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-do-table=foo%.bar% will replicate only updates to tables in all databases that start with foo and whose table names start with bar.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB, "Tells the slave thread to not replicate to the specified database. To specify more than one database to ignore, use the directive multiple times, once for each database. This option will not work if you use cross database updates. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-ignore-table=db_name.%. ", @@ -3798,37 +3797,37 @@ Does nothing yet.", "Tells the slave thread to not replicate to the tables that match the given wildcard pattern. To specify more than one table to ignore, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% will not do updates to tables in databases that start with foo and whose table names start with bar.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB, - "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name", + "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, // In replication, we may need to tell the other servers how to connect {"report-host", OPT_REPORT_HOST, "Hostname or IP of the slave to be reported to to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts.", (gptr*) &report_host, (gptr*) &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"report-user", OPT_REPORT_USER, "Undocumented", (gptr*) &report_user, + {"report-user", OPT_REPORT_USER, "Undocumented.", (gptr*) &report_user, (gptr*) &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"report-password", OPT_REPORT_PASSWORD, "Undocumented", + {"report-password", OPT_REPORT_PASSWORD, "Undocumented.", (gptr*) &report_password, (gptr*) &report_password, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"report-port", OPT_REPORT_PORT, "Port for connecting to slave reported to the master during slave registration. Set it only if the slave is listening on a non-default port or if you have a special tunnel from the master or other clients to the slave. If not sure, leave this option unset.", (gptr*) &report_port, (gptr*) &report_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, - {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented", + {"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, - "The location and name to use for relay logs", + {"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, + {"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", +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).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients)", + {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).", (gptr*) &opt_old_passwords, (gptr*) &opt_old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef TO_BE_DELETED {"safe-show-database", OPT_SAFE_SHOW_DB, @@ -3836,11 +3835,11 @@ relay logs", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"safe-user-create", OPT_SAFE_USER_CREATE, - "Don't allow new user creation by the user who has no write privileges to the mysql.user table", + "Don't allow new user creation by the user who has no write privileges to the mysql.user table.", (gptr*) &opt_safe_user_create, (gptr*) &opt_safe_user_create, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"server-id", OPT_SERVER_ID, - "Uniquely identifies the server instance in the community of replication partners", + "Uniquely identifies the server instance in the community of replication partners.", (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"set-variable", 'O', @@ -3848,15 +3847,15 @@ relay logs", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared_memory_base_name",OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, - "Show user and password in SHOW SLAVE STATUS", + "Show user and password in SHOW SLAVE STATUS.", (gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, - "Use concurrent insert with MyISAM. Disable with prefix --skip-", + "Use concurrent insert with MyISAM. Disable with --skip-concurrent-insert.", (gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"skip-grant-tables", OPT_SKIP_GRANT, @@ -3864,20 +3863,20 @@ relay logs", (gptr*) &opt_noacl, (gptr*) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"innodb", OPT_INNODB, "Enable InnoDB (if this version of MySQL supports it). \ -Disable with --skip-innodb (will save memory)", +Disable with --skip-innodb (will save memory).", (gptr*) &opt_innodb, (gptr*) &opt_innodb, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"isam", OPT_ISAM, "Enable isam (if this version of MySQL supports it). \ -Disable with --skip-isam", +Disable with --skip-isam.", (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"skip-locking", OPT_SKIP_LOCK, - "Deprecated option, use --skip-external-locking instead", + "Deprecated option, use --skip-external-locking instead.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names", 0, 0, 0, + {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-name-resolve", OPT_SKIP_RESOLVE, - "Don't resolve hostnames. All hostnames are IP's or 'localhost'", + "Don't resolve hostnames. All hostnames are IP's or 'localhost'.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-networking", OPT_SKIP_NETWORKING, "Don't allow connection with TCP/IP.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, @@ -3885,35 +3884,35 @@ Disable with --skip-isam", {"skip-new", OPT_SKIP_NEW, "Don't use new, possible wrong routines.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-show-database", OPT_SKIP_SHOW_DB, - "Don't allow 'SHOW DATABASE' commands", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, + "Don't allow 'SHOW DATABASE' commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-slave-start", OPT_SKIP_SLAVE_START, "If set, slave is not autostarted.", (gptr*) &opt_skip_slave_start, (gptr*) &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"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, + "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. Depricated option. Use --skip-symbolic-links instead", + {"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, 0, 0, 0, 0, 0}, - {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, + {"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", +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}, #ifdef HAVE_REPLICATION - {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, + {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, "The location where the slave should put its temporary files when \ -replicating a LOAD DATA INFILE command", +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, - "Tells the slave thread to continue replication when a query returns an error from the provided list", + "Tells the slave thread to continue replication when a query returns an error from the provided list.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"socket", OPT_SOCKET, "Socket file to use for connection", + {"socket", OPT_SOCKET, "Socket file to use for connection.", (gptr*) &mysql_unix_port, (gptr*) &mysql_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME, @@ -3942,28 +3941,28 @@ replicating a LOAD DATA INFILE command", (gptr*) &opt_mysql_tmpdir, (gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"transaction-isolation", OPT_TX_ISOLATION, - "Default transaction isolation level", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, + "Default transaction isolation level.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"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", + {"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}, - {"use-symbolic-links", 's', "Enable symbolic link support. Depricated option; Use --symbolic-links instead", + {"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", + {"--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}, - {"user", 'u', "Run mysqld daemon as user", 0, 0, 0, GET_STR, REQUIRED_ARG, + {"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, + {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"version", 'v', "Synonym for option -v", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, + {"version", 'v', "Synonym for option -V.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-warnings", 'W', "Log some not critical warnings to the log file", + {"log-warnings", 'W', "Log some not critical warnings to the log file.", (gptr*) &global_system_variables.log_warnings, (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"warnings", 'W', "Deprecated ; Use --log-warnings instead", + {"warnings", 'W', "Deprecated ; Use --log-warnings instead.", (gptr*) &global_system_variables.log_warnings, (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -3985,7 +3984,7 @@ replicating a LOAD DATA INFILE command", (gptr*) &berkeley_max_lock, (gptr*) &berkeley_max_lock, 0, GET_ULONG, REQUIRED_ARG, 10000, 0, (long) ~0, 0, 1, 0}, /* QQ: The following should be removed soon! */ - {"bdb_lock_max", OPT_BDB_MAX_LOCK, "Synonym for bdb_max_lock", + {"bdb_lock_max", OPT_BDB_MAX_LOCK, "Synonym for bdb_max_lock.", (gptr*) &berkeley_max_lock, (gptr*) &berkeley_max_lock, 0, GET_ULONG, REQUIRED_ARG, 10000, 0, (long) ~0, 0, 1, 0}, #endif /* HAVE_BERKELEY_DB */ @@ -3994,7 +3993,7 @@ replicating a LOAD DATA INFILE command", (gptr*) &binlog_cache_size, (gptr*) &binlog_cache_size, 0, GET_ULONG, REQUIRED_ARG, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, - "The number of seconds the mysqld server is waiting for a connect packet before responding with Bad handshake", + "The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.", (gptr*) &connect_timeout, (gptr*) &connect_timeout, 0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 }, {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT, @@ -4134,7 +4133,7 @@ replicating a LOAD DATA INFILE command", (gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads, 0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0}, {"max_error_count", OPT_MAX_ERROR_COUNT, - "Max number of errors/warnings to store for a statement", + "Max number of errors/warnings to store for a statement.", (gptr*) &global_system_variables.max_error_count, (gptr*) &max_system_variables.max_error_count, 0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 1, 65535, 0, 1, 0}, @@ -4149,12 +4148,12 @@ replicating a LOAD DATA INFILE command", (gptr*) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0}, {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA, - "Max number of bytes in sorted records", + "Max number of bytes in sorted records.", (gptr*) &global_system_variables.max_length_for_sort_data, (gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, {"max_prepared_statements", OPT_MAX_PREP_STMT, - "Max number of prepared_statements for a thread", + "Max number of prepared_statements for a thread.", (gptr*) &global_system_variables.max_prep_stmt_count, (gptr*) &max_system_variables.max_prep_stmt_count, 0, GET_ULONG, REQUIRED_ARG, DEFAULT_PREP_STMT_COUNT, 0, ~0L, 0, 1, 0}, @@ -4182,19 +4181,19 @@ replicating a LOAD DATA INFILE command", (gptr*) &max_system_variables.bulk_insert_buff_size, 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ~0L, 0, 1, 0}, {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE, - "Block size to be used for MyISAM index pages", + "Block size to be used for MyISAM index pages.", (gptr*) &opt_myisam_block_size, (gptr*) &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - "Used to help MySQL to decide when to use the slow but safe key cache index create method", + "Used to help MySQL to decide when to use the slow but safe key cache index create method.", (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, (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!", + "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, (ulonglong) MAX_FILE_SIZE, @@ -4278,12 +4277,12 @@ replicating a LOAD DATA INFILE command", (gptr*) &relay_log_purge, 0, GET_BOOL, NO_ARG, 1, 0, 1, 0, 1, 0}, {"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT, - "Maximum 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}, {"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL, - "Use compression on master/slave protocol", + "Use compression on master/slave protocol.", (gptr*) &opt_slave_compressed_protocol, (gptr*) &opt_slave_compressed_protocol, 0, GET_BOOL, REQUIRED_ARG, 0, 0, 1, 0, 1, 0}, @@ -4293,7 +4292,7 @@ replicating a LOAD DATA INFILE command", GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, #endif /* HAVE_REPLICATION */ {"read-only", OPT_READONLY, - "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege", + "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}, @@ -4329,7 +4328,7 @@ replicating a LOAD DATA INFILE command", (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, 1024*32, ~0L, 0, 1024, 0}, {"wait_timeout", OPT_WAIT_TIMEOUT, - "The number of seconds the server waits for activity on a connection before closing it", + "The number of seconds the server waits for activity on a connection before closing it.", (gptr*) &global_system_variables.net_wait_timeout, (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, @@ -4340,13 +4339,12 @@ replicating a LOAD DATA INFILE command", REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, { "default-week-format", OPT_DEFAULT_WEEK_FORMAT, "The default week format used by WEEK() functions.", - (gptr*) &global_system_variables.default_week_format, - (gptr*) &max_system_variables.default_week_format, + (gptr*) &global_system_variables.default_week_format, + (gptr*) &max_system_variables.default_week_format, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; - struct show_var_st status_vars[]= { {"Aborted_clients", (char*) &aborted_threads, SHOW_LONG}, {"Aborted_connects", (char*) &aborted_connects, SHOW_LONG}, diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c index 20fe2178005..70382c29735 100644 --- a/tools/mysqlmanager.c +++ b/tools/mysqlmanager.c @@ -283,7 +283,7 @@ struct manager_cmd commands[] = static struct my_option my_long_options[] = { #ifndef DBUG_OFF - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'", + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"help", '?', "Display this help and exit.", @@ -299,20 +299,20 @@ static struct my_option my_long_options[] = {"tcp-backlog", 'B', "Size of TCP/IP listen queue.", (gptr*) &manager_back_log, (gptr*) &manager_back_log, 0, GET_INT, REQUIRED_ARG, MANAGER_BACK_LOG, 0, 0, 0, 0, 0}, - {"greeting", 'g', "Set greeting on connect", (gptr*) &manager_greeting, + {"greeting", 'g', "Set greeting on connect.", (gptr*) &manager_greeting, (gptr*) &manager_greeting, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"max-command-len", 'm', "Maximum command length", + {"max-command-len", 'm', "Maximum command length.", (gptr*) &manager_max_cmd_len, (gptr*) &manager_max_cmd_len, 0, GET_UINT, REQUIRED_ARG, MANAGER_MAX_CMD_LEN, 0, 0, 0, 0, 0}, - {"one-thread", 'd', "Use one thread ( for debugging)", (gptr*) &one_thread, + {"one-thread", 'd', "Use one thread ( for debugging).", (gptr*) &one_thread, (gptr*) &one_thread, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"connect-retries", 'C', "Number of attempts to establish MySQL connection", + {"connect-retries", 'C', "Number of attempts to establish MySQL connection.", (gptr*) &manager_connect_retries, (gptr*) &manager_connect_retries, 0, GET_INT, REQUIRED_ARG, MANAGER_CONNECT_RETRIES, 0, 0, 0, 0, 0}, - {"password-file", 'p', "Password file for manager", + {"password-file", 'p', "Password file for manager.", (gptr*) &manager_pw_file, (gptr*) &manager_pw_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"pid-file", 'f', "Pid file to use", (gptr*) &pid_file, (gptr*) &pid_file, + {"pid-file", 'f', "Pid file to use.", (gptr*) &pid_file, (gptr*) &pid_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, From bb39536d7857cbe94367c60ac9f05f93f6dbefb0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Jun 2003 11:17:31 +0200 Subject: [PATCH 350/399] cleaned user used in tests 'connect' and 'rpl_temporary' mysql-test/r/connect.result: result update mysql-test/t/connect.test: clean after we are done mysql-test/t/rpl_temporary.test: use '' instead of 'boo' --- mysql-test/r/connect.result | 2 ++ mysql-test/t/connect.test | 5 +++++ mysql-test/t/rpl_temporary.test | 4 +--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index a80ddc24d05..9c848c3434f 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -44,3 +44,5 @@ tables_priv user show tables; Tables_in_test +delete from mysql.user where user="test"; +flush privileges; diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test index 7b441ee5f7b..e6ccc52f0d4 100644 --- a/mysql-test/t/connect.test +++ b/mysql-test/t/connect.test @@ -62,3 +62,8 @@ show tables; #--error 1045 #connect (con1,localhost,test,zorro,); #--error 1045 + +# remove user 'test' so that other tests which may use 'test' +# do not depend on this test. +delete from mysql.user where user="test"; +flush privileges; diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index b50d9004f14..79dba60964d 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -19,9 +19,7 @@ connection master; connect (con1,localhost,root,,); connect (con2,localhost,root,,); -# user 'boo' does not exist, because we want to be ''@localhost or ''@127.0.0.1 -# (using user 'test' conflicts with what connect.test does). -connect (con3,localhost,boo,,); +connect (con3,localhost,,,); # We are going to use SET PSEUDO_THREAD_ID in this test; # check that it requires the SUPER privilege. From b9374fabff99376c3b904e326de47ac60666f95e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Jun 2003 19:25:26 +0200 Subject: [PATCH 351/399] mysql.server should read [server] group from my.cnf - according to the manual --- support-files/mysql.server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 694e6fa8ebb..ed973b61e57 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -129,7 +129,7 @@ then extra_args="-e $datadir/my.cnf" fi -parse_arguments `$print_defaults $extra_args mysqld mysql_server mysql.server` +parse_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server` # Safeguard (relative paths, core dumps..) cd $basedir From 2c70308c68338098f94d6c882cdbeb4b34445631 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Jun 2003 23:00:04 +0200 Subject: [PATCH 352/399] bug #251 - destroyed object reused - fixed --- sql/field.h | 9 +++++---- sql/sql_select.cc | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sql/field.h b/sql/field.h index a1f19638658..a72ccfa8354 100644 --- a/sql/field.h +++ b/sql/field.h @@ -50,7 +50,7 @@ public: LEX_STRING comment; ulong query_id; // For quick test of used fields /* Field is part of the following keys */ - key_map key_start,part_of_key,part_of_sortkey; + key_map key_start,part_of_key,part_of_sortkey; enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL, CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD, BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD}; @@ -134,6 +134,7 @@ public: virtual void sort_string(char *buff,uint length)=0; virtual bool optimize_range(uint idx); virtual bool store_for_compare() { return 0; } + virtual void free() {} Field *new_field(MEM_ROOT *root, struct st_table *new_table) { Field *tmp= (Field*) memdup_root(root,(char*) this,size_of()); @@ -937,11 +938,11 @@ public: int pack_cmp(const char *b, uint key_length); uint packed_col_length(const char *col_ptr, uint length); uint max_packed_col_length(uint max_length); - inline void free() { value.free(); } + void free() { value.free(); } inline void clear_temporary() { bzero((char*) &value,sizeof(value)); } friend void field_conv(Field *to,Field *from); uint size_of() const { return sizeof(*this); } - bool has_charset(void) const + bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } }; @@ -949,7 +950,7 @@ public: class Field_geom :public Field_blob { public: enum geometry_type geom_type; - + Field_geom(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint blob_pack_length, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 61a64573eaa..a5fd69c8fbb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4791,7 +4791,7 @@ free_tmp_table(THD *thd, TABLE *entry) (void) ha_delete_table(entry->db_type,entry->real_name); /* free blobs */ for (Field **ptr=entry->field ; *ptr ; ptr++) - delete *ptr; + (*ptr)->free(); my_free((gptr) entry->record[0],MYF(0)); free_io_cache(entry); From ccf59c3874df6b260f613afe0a097a555b4ba642 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 Jun 2003 11:37:42 +0300 Subject: [PATCH 353/399] Cleanup after split of libmysql.c to client.c and libmysql.c. A 4.1 master/slave will now use the 4.1 protocol Fixed wrong value for SQLSTATE_LENGTH Added CLIENT_REMEMBER_OPTIONS to mysql_real_connect() Changed mysql_port and mysql_unix_port to mysqld_xxxx client/mysql.cc: Removed valgrind & compiler warnings client/sql_string.h: Fix to remove valgrind warnings include/mysql.h: Added read_timeout and write_timeout to mysql options struct. This is to be used for slave when connection to master. code cleanup include/mysql_com.h: Fixed wrong value for SQLSTATE_LENGTH Added CLIENT_REMEMBER_OPTIONS include/sql_common.h: Cleanup after split of libmysql.c to client.c and libmysql.c include/sql_state.h: Removed default states libmysql/client_settings.h: Cleanup after split of libmysql.c to client.c and libmysql.c libmysql/libmysql.c: Cleanup after split of libmysql.c to client.c and libmysql.c mysql-test/r/type_blob.result: Update results after someone updated error messages without running tests mysys/charset.c: More debug information mysys/errors.c: Fixed wrong error message sql-common/client.c: Cleanup after split of libmysql.c to client.c and libmysql.c sql/Makefile.am: Added sql_client.cc sql/client_settings.h: Cleanup after split of libmysql.c to client.c and libmysql.c sql/log.cc: Changed mysql_port and mysql_unix_port to mysqld_xxxx sql/mysql_priv.h: Changed mysql_port and mysql_unix_port to mysqld_xxxx sql/mysqld.cc: Changed mysql_port and mysql_unix_port to mysqld_xxxx sql/protocol.cc: Fix for SQLSTATE_LENGTH Moved function to sql_client.c sql/repl_failsafe.cc: Cleanup after split of libmysql.c to client.c and libmysql.c sql/set_var.cc: Changed mysql_port and mysql_unix_port to mysqld_xxxx sql/slave.cc: Cleanup after split of libmysql.c to client.c and libmysql.c --- client/mysql.cc | 5 +- client/sql_string.h | 8 + include/mysql.h | 22 +- include/mysql_com.h | 3 +- include/sql_common.h | 4 - include/sql_state.h | 3 - libmysql/client_settings.h | 25 +- libmysql/libmysql.c | 183 ++++---- mysql-test/r/type_blob.result | 2 +- mysys/charset.c | 12 +- mysys/errors.c | 2 +- sql-common/client.c | 825 ++++++++++++++++------------------ sql/Makefile.am | 2 +- sql/client_settings.h | 17 +- sql/log.cc | 4 +- sql/mysql_priv.h | 4 +- sql/mysqld.cc | 68 +-- sql/protocol.cc | 25 +- sql/repl_failsafe.cc | 21 +- sql/set_var.cc | 4 +- sql/slave.cc | 49 +- sql/sql_client.cc | 45 ++ 22 files changed, 639 insertions(+), 694 deletions(-) create mode 100644 sql/sql_client.cc diff --git a/client/mysql.cc b/client/mysql.cc index a957f804537..07fb67093ee 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1525,6 +1525,9 @@ static int com_server_help(String *buffer __attribute__((unused)), char last_char; int num_name, num_cat; + LINT_INIT(num_name); + LINT_INIT(num_cat); + if (num_fields == 2) { put_info("Many help items for your request exist", INFO_INFO); @@ -1841,7 +1844,7 @@ print_table_data(MYSQL_RES *result) separator.fill(separator.length()+length+2,'-'); separator.append('+'); } - tee_puts(separator.c_ptr(), PAGER); + tee_puts(separator.c_ptr_safe(), PAGER); if (column_names) { mysql_field_seek(result,0); diff --git a/client/sql_string.h b/client/sql_string.h index 33f34a43b7f..aec40466d2b 100644 --- a/client/sql_string.h +++ b/client/sql_string.h @@ -92,6 +92,14 @@ public: Ptr[str_length]=0; return Ptr; } + inline char *c_ptr_safe() + { + if (Ptr && str_length < Alloced_length) + Ptr[str_length]=0; + else + (void) realloc(str_length); + return Ptr; + } void set(String &str,uint32 offset,uint32 arg_length) { diff --git a/include/mysql.h b/include/mysql.h index 374ac9b8959..337e080e4cc 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -135,9 +135,9 @@ typedef struct st_mysql_data { } MYSQL_DATA; struct st_mysql_options { - unsigned int connect_timeout; + unsigned int connect_timeout, read_timeout, write_timeout; + unsigned int port, protocol; unsigned long client_flag; - unsigned int port; char *host,*user,*password,*unix_socket,*db; struct st_dynamic_array *init_commands; char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name; @@ -146,6 +146,7 @@ struct st_mysql_options { char *ssl_ca; /* PEM CA file */ char *ssl_capath; /* PEM directory of CA-s? */ char *ssl_cipher; /* cipher to use */ + char *shared_memory_base_name; unsigned long max_allowed_packet; my_bool use_ssl; /* if to use SSL or not */ my_bool compress,named_pipe; @@ -167,18 +168,15 @@ struct st_mysql_options { #ifdef EMBEDDED_LIBRARY my_bool separate_thread; #endif - char *shared_memory_base_name; - unsigned int protocol; }; enum mysql_option { - MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, MYSQL_INIT_COMMAND, - MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, - MYSQL_OPT_LOCAL_INFILE, MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME -#ifdef EMBEDDED_LIBRARY - , MYSQL_OPT_USE_RESULT -#endif + MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, + MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, + MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE, + MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT, + MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT }; enum mysql_status @@ -188,8 +186,8 @@ enum mysql_status enum mysql_protocol_type { - MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, MYSQL_PROTOCOL_PIPE, - MYSQL_PROTOCOL_MEMORY + MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET, + MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY }; /* There are three types of queries - the ones that have to go to diff --git a/include/mysql_com.h b/include/mysql_com.h index faa025c934e..e87001ff27d 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -25,7 +25,7 @@ #define HOSTNAME_LENGTH 60 #define USERNAME_LENGTH 16 #define SERVER_VERSION_LENGTH 60 -#define SQLSTATE_LENGTH 6 +#define SQLSTATE_LENGTH 5 #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." @@ -110,6 +110,7 @@ enum enum_server_command #define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ #define CLIENT_MULTI_QUERIES 65536 /* Enable/disable multiquery support */ #define CLIENT_MULTI_RESULTS 131072 /* Enable/disable multi-results */ +#define CLIENT_REMEMBER_OPTIONS (1L << 31) #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ diff --git a/include/sql_common.h b/include/sql_common.h index 65283486fb4..f3300281f29 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -42,9 +42,5 @@ my_bool mysql_reconnect(MYSQL *mysql); } #endif -#ifdef MYSQL_SERVER -#define protocol_41(A) FALSE -#else #define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41) -#endif diff --git a/include/sql_state.h b/include/sql_state.h index cc0fab7bfce..c998beaf578 100644 --- a/include/sql_state.h +++ b/include/sql_state.h @@ -86,7 +86,6 @@ ER_UNSUPPORTED_EXTENSION, "42000", "", ER_TABLE_MUST_HAVE_COLUMNS, "42000", "", ER_UNKNOWN_CHARACTER_SET, "42000", "", ER_TOO_BIG_ROWSIZE, "42000", "", -ER_STACK_OVERRUN, "HY000", "", ER_WRONG_OUTER_JOIN, "42000", "", ER_NULL_COLUMN_IN_INDEX, "42000", "", ER_PASSWORD_ANONYMOUS_USER, "42000", "", @@ -128,8 +127,6 @@ ER_REQUIRES_PRIMARY_KEY, "42000", "", ER_CHECK_NO_SUCH_TABLE, "42000", "", ER_CHECK_NOT_IMPLEMENTED, "42000", "", ER_CANT_DO_THIS_DURING_AN_TRANSACTION, "25000", "", -ER_ERROR_DURING_COMMIT, "HY000", "", -ER_ERROR_DURING_ROLLBACK, "HY000", "", ER_NEW_ABORTING_CONNECTION, "08S01", "", ER_MASTER_NET_READ, "08S01", "", ER_MASTER_NET_WRITE, "08S01", "", diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index 47d5185b6ca..8c28de73866 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -15,27 +15,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -static my_bool mysql_client_init=0; -extern uint mysql_port; -extern my_string mysql_unix_port; +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ + CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS | \ + CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ - | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \ - | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) - - -#ifdef __WIN__ -#define CONNECT_TIMEOUT 20 -#else -#define CONNECT_TIMEOUT 0 -#endif - -#ifdef HAVE_SMEM -char *shared_memory_base_name=0; -const char *def_shared_memory_base_name=default_shared_memory_base_name; -#endif - -static my_bool org_my_init_done=0; sig_handler pipe_sig_handler(int sig __attribute__((unused))); my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); @@ -48,7 +31,7 @@ my_bool send_file_to_server(MYSQL *mysql, const char *filename); */ #if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD) -#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0; +#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0 #define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler) #define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler); #else diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 7e379ab63ba..771278c1dbb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -59,24 +59,11 @@ #include -uint mysql_port=0; -my_string mysql_unix_port=0; ulong net_buffer_length=8192; ulong max_allowed_packet= 1024L*1024L*1024L; ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT; -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ - | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \ - | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) - - -#ifdef __WIN__ -#define CONNECT_TIMEOUT 20 -#else -#define CONNECT_TIMEOUT 0 -#endif - #if defined(MSDOS) || defined(__WIN__) /* socket_errno is defined in my_global.h for all platforms */ #define perror(A) @@ -85,10 +72,6 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT; #define SOCKET_ERROR -1 #endif /* __WIN__ */ -const char *sql_protocol_names_lib[] = -{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS }; -TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", - sql_protocol_names_lib}; /* If allowed through some configuration, then this needs to be changed @@ -101,7 +84,67 @@ sig_handler pipe_sig_handler(int sig); static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); -static my_bool org_my_init_done=0; + +/* + Initialize the MySQL library + + SYNOPSIS + mysql_once_init() + + NOTES + Can't be static on NetWare + This function is called by mysql_init() and indirectly called + by mysql_real_query(), so one should never have to call this from an + outside program. +*/ + +static my_bool mysql_client_init= 0; +static my_bool org_my_init_done= 0; + +void mysql_once_init(void) +{ + if (!mysql_client_init) + { + mysql_client_init=1; + org_my_init_done=my_init_done; + my_init(); /* Will init threads */ + init_client_errs(); + if (!mysql_port) + { + mysql_port = MYSQL_PORT; +#ifndef MSDOS + { + struct servent *serv_ptr; + char *env; + if ((serv_ptr = getservbyname("mysql", "tcp"))) + mysql_port = (uint) ntohs((ushort) serv_ptr->s_port); + if ((env = getenv("MYSQL_TCP_PORT"))) + mysql_port =(uint) atoi(env); + } +#endif + } + if (!mysql_unix_port) + { + char *env; +#ifdef __WIN__ + mysql_unix_port = (char*) MYSQL_NAMEDPIPE; +#else + mysql_unix_port = (char*) MYSQL_UNIX_ADDR; +#endif + if ((env = getenv("MYSQL_UNIX_PORT"))) + mysql_unix_port = env; + } + mysql_debug(NullS); +#if defined(SIGPIPE) && !defined(THREAD) && !defined(__WIN__) + (void) signal(SIGPIPE,SIG_IGN); +#endif + } +#ifdef THREAD + else + my_thread_init(); /* Init if new thread */ +#endif +} + int STDCALL mysql_server_init(int argc __attribute__((unused)), char **argv __attribute__((unused)), @@ -529,30 +572,6 @@ STDCALL mysql_rpl_query_type(const char* q, int len) return MYSQL_RPL_MASTER; /* By default, send to master */ } -/* - Fill in SSL part of MYSQL structure and set 'use_ssl' flag. - NB! Errors are not reported until you do mysql_real_connect. -*/ - -#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME)) - -my_bool STDCALL -mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , - const char *key __attribute__((unused)), - const char *cert __attribute__((unused)), - const char *ca __attribute__((unused)), - const char *capath __attribute__((unused)), - const char *cipher __attribute__((unused))) -{ -#ifdef HAVE_OPENSSL - mysql->options.ssl_key= strdup_if_not_null(key); - mysql->options.ssl_cert= strdup_if_not_null(cert); - mysql->options.ssl_ca= strdup_if_not_null(ca); - mysql->options.ssl_capath= strdup_if_not_null(capath); - mysql->options.ssl_cipher= strdup_if_not_null(cipher); -#endif /* HAVE_OPENSSL */ - return 0; -} /************************************************************************** Connect to sql server @@ -578,6 +597,7 @@ mysql_connect(MYSQL *mysql,const char *host, } #endif + /************************************************************************** Change user and database **************************************************************************/ @@ -836,56 +856,6 @@ STDCALL mysql_add_slave(MYSQL* mysql, const char* host, return 0; } -/************************************************************************** - Alloc struct for use with unbuffered reads. Data is fetched by domand - when calling to mysql_fetch_row. - mysql_data_seek is a noop. - - No other queries may be specified with the same MYSQL handle. - There shouldn't be much processing per row because mysql server shouldn't - have to wait for the client (and will not wait more than 30 sec/packet). -**************************************************************************/ - -MYSQL_RES * STDCALL -mysql_use_result(MYSQL *mysql) -{ - MYSQL_RES *result; - DBUG_ENTER("mysql_use_result"); - - mysql = mysql->last_used_con; - - if (!mysql->fields) - DBUG_RETURN(0); - if (mysql->status != MYSQL_STATUS_GET_RESULT) - { - strmov(mysql->net.sqlstate, unknown_sqlstate); - strmov(mysql->net.last_error, - ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - DBUG_RETURN(0); - } - if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+ - sizeof(ulong)*mysql->field_count, - MYF(MY_WME | MY_ZEROFILL)))) - DBUG_RETURN(0); - result->lengths=(ulong*) (result+1); - if (!(result->row=(MYSQL_ROW) - my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME)))) - { /* Ptrs: to one row */ - my_free((gptr) result,MYF(0)); - DBUG_RETURN(0); - } - result->fields= mysql->fields; - result->field_alloc= mysql->field_alloc; - result->field_count= mysql->field_count; - result->current_field=0; - result->handle= mysql; - result->current_row= 0; - mysql->fields=0; /* fields is now in result */ - mysql->status=MYSQL_STATUS_USE_RESULT; - DBUG_RETURN(result); /* Data is read to be fetched */ -} - - /************************************************************************** Return next field of the query results @@ -899,6 +869,13 @@ mysql_fetch_field(MYSQL_RES *result) return &result->fields[result->current_field++]; } + +/************************************************************************** + Get column lengths of the current row + If one uses mysql_use_result, res->lengths contains the length information, + else the lengths are calculated from the offset between pointers. +**************************************************************************/ + ulong * STDCALL mysql_fetch_lengths(MYSQL_RES *res) { @@ -911,6 +888,23 @@ mysql_fetch_lengths(MYSQL_RES *res) return res->lengths; } + +/************************************************************************** + Move to a specific row and column +**************************************************************************/ + +void STDCALL +mysql_data_seek(MYSQL_RES *result, my_ulonglong row) +{ + MYSQL_ROWS *tmp=0; + DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); + if (result->data) + for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; + result->current_row=0; + result->data_cursor = tmp; +} + + /************************************************************************* put the row or field cursor one a position one got from mysql_row_tell() This doesn't restore any data. The next mysql_fetch_row or @@ -935,6 +929,7 @@ mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset) return return_value; } + /***************************************************************************** List all databases *****************************************************************************/ @@ -2444,7 +2439,7 @@ static void send_data_long(MYSQL_BIND *param, longlong value) } default: { - char tmp[12]; + char tmp[22]; /* Enough for longlong */ uint length= (uint)(longlong10_to_str(value,(char *)tmp,10)-tmp); ulong copy_length= min((ulong)length-param->offset, param->buffer_length); memcpy(buffer, (char *)tmp+param->offset, copy_length); @@ -2492,7 +2487,7 @@ static void send_data_double(MYSQL_BIND *param, double value) } default: { - char tmp[12]; + char tmp[128]; uint length= my_sprintf(tmp,(tmp,"%g",value)); ulong copy_length= min((ulong)length-param->offset, param->buffer_length); memcpy(buffer, (char *)tmp+param->offset, copy_length); diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index a537aeeca07..d39f72cbe0b 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -29,7 +29,7 @@ drop table t1,t2,t3 CREATE TABLE t1 (a char(257) default "hello"); ERROR 42000: Too big column length for column 'a' (max = 255). Use BLOB instead CREATE TABLE t2 (a blob default "hello"); -ERROR 42000: BLOB column 'a' can't have a default value +ERROR 42000: BLOB/TEXT column 'a' can't have a default value drop table if exists t1,t2; create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr)); insert into t1 values (null,"a","A"); diff --git a/mysys/charset.c b/mysys/charset.c index ad0468a5087..7dab1a38325 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -368,6 +368,7 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) char *get_charsets_dir(char *buf) { const char *sharedir= SHAREDIR; + char *res; DBUG_ENTER("get_charsets_dir"); if (charsets_dir != NULL) @@ -381,9 +382,9 @@ char *get_charsets_dir(char *buf) strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR, NullS); } - convert_dirname(buf,buf,NullS); + res= convert_dirname(buf,buf,NullS); DBUG_PRINT("info",("charsets dir: '%s'", buf)); - DBUG_RETURN(strend(buf)); + DBUG_RETURN(res); } CHARSET_INFO *all_charsets[256]; @@ -613,6 +614,9 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, { CHARSET_INFO *cs=NULL; CHARSET_INFO **css; + DBUG_ENTER("get_charset_by_csname"); + DBUG_PRINT("enter",("name: '%s'", cs_name)); + (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ for (css= all_charsets; css < all_charsets+255; ++css) @@ -624,7 +628,7 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, cs= css[0]->number ? get_internal_charset(css[0]->number,flags) : NULL; break; } - } + } if (!cs && (flags & MY_WME)) { @@ -633,5 +637,5 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file); } - return cs; + DBUG_RETURN(cs); } diff --git a/mysys/errors.c b/mysys/errors.c index 8a120e0e869..a2226fc12c5 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -82,7 +82,7 @@ void init_glob_errs() EE(EE_OPEN_WARNING) = "%d files and %d streams is left open\n"; EE(EE_DISK_FULL) = "Disk is full writing '%s'. Waiting for someone to free space..."; EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)"; - EE(EE_UNKNOWN_CHARSET)= "Character set is not a compiled character set and is not specified in the %s file"; + EE(EE_UNKNOWN_CHARSET)= "Character set '%s' is not a compiled character set and is not specified in the %s file"; EE(EE_OUT_OF_FILERESOURCES)="Out of resources when opening file '%s' (Errcode: %d)"; EE(EE_CANT_READLINK)="Can't read value for symlink '%s' (Error %d)"; EE(EE_CANT_SYMLINK)="Can't create symlink '%s' pointing at '%s' (Error %d)"; diff --git a/sql-common/client.c b/sql-common/client.c index 3c025d18bd6..1f0f67e4ff1 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -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 @@ -37,13 +37,11 @@ #include -#if defined(MYSQL_SERVER) || defined(HAVE_EXTERNAL_CLIENT) - #include "mysql.h" -#if !defined(MYSQL_SERVER) && defined(__WIN__) || defined(_WIN32) || defined(_WIN64) +#if !defined(MYSQL_SERVER) && (defined(__WIN__) || defined(_WIN32) || defined(_WIN64)) #include #include -#endif +#endif /* !defined(MYSQL_SERVER) && (defined(__WIN__) ... */ #include #include #include @@ -55,21 +53,19 @@ #include #if defined(THREAD) && !defined(__WIN__) #include /* because of signal() */ -#endif +#endif /* defined(THREAD) && !defined(__WIN__) */ -#if defined( OS2) && defined(MYSQL_SERVER) +#if defined(OS2) && defined(MYSQL_SERVER) #undef ER #define ER CER -#endif +#endif /* defined( OS2) && defined(MYSQL_SERVER) */ #include #include #include - #ifdef HAVE_PWD_H #include #endif - #if !defined(MSDOS) && !defined(__WIN__) #include #include @@ -96,16 +92,27 @@ #define SOCKET_ERROR -1 #endif +#ifdef __WIN__ +#define CONNECT_TIMEOUT 20 +#else +#define CONNECT_TIMEOUT 0 +#endif + #include "client_settings.h" #include -const char *unknown_sqlstate= "HY0000"; +uint mysql_port=0; +char *mysql_unix_port= 0; +const char *unknown_sqlstate= "HY000"; const char *not_error_sqlstate= "00000"; - -#ifdef MYSQL_CLIENT -extern my_bool stmt_close(MYSQL_STMT *stmt,my_bool skip_list); +#ifdef HAVE_SMEM +char *shared_memory_base_name= 0; +const char def_shared_memory_base_name= default_shared_memory_base_name; #endif +static void mysql_close_free_options(MYSQL *mysql); +static void mysql_close_free(MYSQL *mysql); + /**************************************************************************** A modified version of connect(). my_connect() allows you to specify a timeout value, in seconds, that we should wait until we @@ -293,6 +300,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, } #endif + /* Create new shared memory connection, return handler of connection @@ -310,7 +318,8 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) /* event_connect_request is event object for start connection actions event_connect_answer is event object for confirm, that server put data - handle_connect_file_map is file-mapping object, use for create shared memory + handle_connect_file_map is file-mapping object, use for create shared + memory handle_connect_map is pointer on shared memory handle_map is pointer on shared memory for client event_server_wrote, @@ -594,8 +603,6 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, mysql->info=0; mysql->affected_rows= ~(my_ulonglong) 0; net_clear(&mysql->net); /* Clear receive buffer */ - if (!arg) - arg=""; if (net_write_command(net,(uchar) command, header, header_length, arg, arg_length)) @@ -640,8 +647,7 @@ void free_old_query(MYSQL *mysql) DBUG_ENTER("free_old_query"); if (mysql->fields) free_root(&mysql->field_alloc,MYF(0)); - else - init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ + init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ mysql->fields=0; mysql->field_count=0; /* For API */ DBUG_VOID_RETURN; @@ -676,6 +682,7 @@ void end_server(MYSQL *mysql) DBUG_VOID_RETURN; } + void STDCALL mysql_free_result(MYSQL_RES *result) { @@ -726,6 +733,11 @@ static const char *default_options[]= static TYPELIB option_types={array_elements(default_options)-1, "options",default_options}; +const char *sql_protocol_names_lib[] = +{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS }; +TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", + sql_protocol_names_lib}; + static int add_init_command(struct st_mysql_options *options, const char *cmd) { char *tmp; @@ -832,8 +844,8 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->db=my_strdup(opt_arg,MYF(MY_WME)); } break; -#ifdef MYSQL_CLIENT case 11: /* debug */ +#ifdef MYSQL_CLIENT mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace"); break; #endif @@ -885,26 +897,30 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->client_flag&= CLIENT_LOCAL_FILES; break; case 23: /* replication probe */ +#ifndef TO_BE_DELETED options->rpl_probe= 1; +#endif break; case 24: /* enable-reads-from-master */ options->no_master_reads= 0; break; case 25: /* repl-parse-query */ +#ifndef TO_BE_DELETED options->rpl_parse= 1; +#endif break; case 27: options->max_allowed_packet= atoi(opt_arg); break; -#ifdef MYSQL_CLIENT case 28: /* protocol */ - if ((options->protocol = find_type(opt_arg, &sql_protocol_typelib,0)) == ~(ulong) 0) + if ((options->protocol = find_type(opt_arg, + &sql_protocol_typelib,0)) + == ~(ulong) 0) { fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg); exit(1); } break; -#endif case 29: /* shared_memory_base_name */ #ifdef HAVE_SMEM if (options->shared_memory_base_name != def_shared_memory_base_name) @@ -928,6 +944,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, DBUG_VOID_RETURN; } + /************************************************************************** Get column lengths of the current row If one uses mysql_use_result, res->lengths contains the length information, @@ -956,51 +973,6 @@ void fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count) } -static inline void -unpack_fields_40(MYSQL_ROWS *row, MYSQL_FIELD *field, MEM_ROOT *alloc, - ulong *lengths, uint n_lengths, - my_bool default_value, my_bool long_flag_protocol) -{ - DBUG_ENTER("unpack_fields_40"); - - for (; row ; row = row->next,field++) - { - fetch_lengths(lengths, row->data, n_lengths); - field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]); - field->name= strdup_root(alloc,(char*) row->data[1]); - field->length= (uint) uint3korr(row->data[2]); - field->type= (enum enum_field_types) (uchar) row->data[3][0]; - - field->catalog=(char*) ""; - field->db= (char*) ""; - field->catalog_length= 0; - field->db_length= 0; - field->org_table_length= field->table_length= lengths[0]; - field->name_length= lengths[1]; - - if (long_flag_protocol) - { - field->flags= uint2korr(row->data[4]); - field->decimals=(uint) (uchar) row->data[4][2]; - } - else - { - field->flags= (uint) (uchar) row->data[4][0]; - field->decimals=(uint) (uchar) row->data[4][1]; - } - if (INTERNAL_NUM_FIELD(field)) - field->flags|= NUM_FLAG; - if (default_value && row->data[5]) - { - field->def=strdup_root(alloc,(char*) row->data[5]); - field->def_length= lengths[5]; - } - else - field->def=0; - field->max_length= 0; - } -} - /*************************************************************************** Change field rows to field structs ***************************************************************************/ @@ -1009,25 +981,19 @@ MYSQL_FIELD * unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, my_bool default_value, uint server_capabilities) { -#ifdef MYSQL_CLIENT MYSQL_ROWS *row; -#endif MYSQL_FIELD *field,*result; ulong lengths[9]; /* Max of fields */ DBUG_ENTER("unpack_fields"); - field=result=(MYSQL_FIELD*) alloc_root(alloc, - (uint) sizeof(MYSQL_FIELD)*fields); + field= result= (MYSQL_FIELD*) alloc_root(alloc, + (uint) sizeof(*field)*fields); if (!result) { free_rows(data); /* Free old data */ DBUG_RETURN(0); } bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields); -#ifdef MYSQL_SERVER - unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, - default_value, (my_bool)(server_capabilities & CLIENT_LONG_FLAG)); -#else if (server_capabilities & CLIENT_PROTOCOL_41) { /* server is 4.1, and returns the new field result format */ @@ -1071,10 +1037,46 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, } #ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL else - unpack_fields_40(data->data, field, alloc, lengths, default_value ? 6 : 5, - default_value, (my_bool)(server_capabilities & CLIENT_LONG_FLAG)); + { + /* old protocol, for backward compatibility */ + for (row=data->data; row ; row = row->next,field++) + { + fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5); + field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]); + field->name= strdup_root(alloc,(char*) row->data[1]); + field->length= (uint) uint3korr(row->data[2]); + field->type= (enum enum_field_types) (uchar) row->data[3][0]; + + field->catalog=(char*) ""; + field->db= (char*) ""; + field->catalog_length= 0; + field->db_length= 0; + field->org_table_length= field->table_length= lengths[0]; + field->name_length= lengths[1]; + + if (server_capabilities & CLIENT_LONG_FLAG) + { + field->flags= uint2korr(row->data[4]); + field->decimals=(uint) (uchar) row->data[4][2]; + } + else + { + field->flags= (uint) (uchar) row->data[4][0]; + field->decimals=(uint) (uchar) row->data[4][1]; + } + if (INTERNAL_NUM_FIELD(field)) + field->flags|= NUM_FLAG; + if (default_value && row->data[5]) + { + field->def=strdup_root(alloc,(char*) row->data[5]); + field->def_length= lengths[5]; + } + else + field->def=0; + field->max_length= 0; + } + } #endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */ -#endif /*MYSQL_SERVER*/ free_rows(data); /* Free old data */ DBUG_RETURN(result); } @@ -1172,13 +1174,11 @@ MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, } } *prev_ptr=0; /* last pointer is null */ -#ifndef MYSQL_SERVER if (pkt_len > 1) /* MySQL 4.1 protocol */ { mysql->warning_count= uint2korr(cp+1); DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count)); } -#endif DBUG_PRINT("exit",("Got %d rows",result->rows)); DBUG_RETURN(result); } @@ -1201,10 +1201,8 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) return -1; if (pkt_len <= 8 && net->read_pos[0] == 254) { -#ifndef MYSQL_SERVER if (pkt_len > 1) /* MySQL 4.1 protocol */ mysql->warning_count= uint2korr(net->read_pos+1); -#endif return 1; /* End of data */ } prev_pos= 0; /* allowed to write at packet[-1] */ @@ -1256,104 +1254,86 @@ mysql_init(MYSQL *mysql) } else bzero((char*) (mysql),sizeof(*(mysql))); -#ifndef MYSQL_SERVER - mysql->options.connect_timeout=CONNECT_TIMEOUT; - mysql->last_used_con = mysql->next_slave = mysql->master = mysql; + mysql->options.connect_timeout= CONNECT_TIMEOUT; + mysql->last_used_con= mysql->next_slave= mysql->master = mysql; /* By default, we are a replication pivot. The caller must reset it after we return if this is not the case. */ +#ifndef TO_BE_DELETED mysql->rpl_pivot = 1; -#if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__) +#endif +#if defined(SIGPIPE) && defined(THREAD) && !defined(__WIN__) && !defined(MYSQL_SERVER) if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) (void) signal(SIGPIPE,pipe_sig_handler); #endif -/* - Only enable LOAD DATA INFILE by default if configured with - --enable-local-infile -*/ -#ifdef ENABLED_LOCAL_INFILE + /* + Only enable LOAD DATA INFILE by default if configured with + --enable-local-infile + */ +#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER) mysql->options.client_flag|= CLIENT_LOCAL_FILES; #endif #ifdef HAVE_SMEM - mysql->options.shared_memory_base_name=(char*)def_shared_memory_base_name; + mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name; #endif - -#else /*MYSQL_SERVER*/ - -#ifdef __WIN__ - mysql->options.connect_timeout=20; -#endif -#endif /*MYSQL_SERVER*/ return mysql; } /* - Initialize the MySQL library - - SYNOPSIS - mysql_once_init() - - NOTES - Can't be static on NetWare - This function is called by mysql_init() and indirectly called - by mysql_query(), so one should never have to call this from an - outside program. + Fill in SSL part of MYSQL structure and set 'use_ssl' flag. + NB! Errors are not reported until you do mysql_real_connect. */ -void mysql_once_init(void) +#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME)) + +my_bool STDCALL +mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , + const char *key __attribute__((unused)), + const char *cert __attribute__((unused)), + const char *ca __attribute__((unused)), + const char *capath __attribute__((unused)), + const char *cipher __attribute__((unused))) { -#ifndef MYSQL_SERVER - - if (!mysql_client_init) - { - mysql_client_init=1; - org_my_init_done=my_init_done; - my_init(); /* Will init threads */ - init_client_errs(); - if (!mysql_port) - { - mysql_port = MYSQL_PORT; -#ifndef MSDOS - { - struct servent *serv_ptr; - char *env; - if ((serv_ptr = getservbyname("mysql", "tcp"))) - mysql_port = (uint) ntohs((ushort) serv_ptr->s_port); - if ((env = getenv("MYSQL_TCP_PORT"))) - mysql_port =(uint) atoi(env); - } -#endif - } - if (!mysql_unix_port) - { - char *env; -#ifdef __WIN__ - mysql_unix_port = (char*) MYSQL_NAMEDPIPE; -#else - mysql_unix_port = (char*) MYSQL_UNIX_ADDR; -#endif - if ((env = getenv("MYSQL_UNIX_PORT"))) - mysql_unix_port = env; - } - mysql_debug(NullS); -#if defined(SIGPIPE) && !defined(THREAD) && !defined(__WIN__) - (void) signal(SIGPIPE,SIG_IGN); -#endif - } -#ifdef THREAD - else - my_thread_init(); /* Init if new thread */ -#endif - -#else /*MYSQL_SERVER*/ - init_client_errs(); -#endif /*MYSQL_SERVER*/ +#ifdef HAVE_OPENSSL + mysql->options.ssl_key= strdup_if_not_null(key); + mysql->options.ssl_cert= strdup_if_not_null(cert); + mysql->options.ssl_ca= strdup_if_not_null(ca); + mysql->options.ssl_capath= strdup_if_not_null(capath); + mysql->options.ssl_cipher= strdup_if_not_null(cipher); +#endif /* HAVE_OPENSSL */ + return 0; } +/* + Free strings in the SSL structure and clear 'use_ssl' flag. + NB! Errors are not reported until you do mysql_real_connect. +*/ + +#ifdef HAVE_OPENSSL +static void +mysql_ssl_free(MYSQL *mysql __attribute__((unused))) +{ + my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.ssl_key = 0; + mysql->options.ssl_cert = 0; + mysql->options.ssl_ca = 0; + mysql->options.ssl_capath = 0; + mysql->options.ssl_cipher= 0; + mysql->options.use_ssl = FALSE; + mysql->connector_fd = 0; +} +#endif /* HAVE_OPENSSL */ + + /* Handle password authentication */ @@ -1423,6 +1403,7 @@ error: return 1; } + /* Note that the mysql argument must be initialized with mysql_init() before calling mysql_real_connect ! @@ -1433,12 +1414,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,ulong client_flag) { -#ifdef MYSQL_CLIENT - char *charset_name; - char charset_name_buff[16]; -#endif - char buff[NAME_LEN+USERNAME_LENGTH+100]; - char *end,*host_info; + char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; + char *end,*host_info,*charset_name; my_socket sock; uint32 ip_addr; struct sockaddr_in sock_addr; @@ -1447,16 +1424,14 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #ifdef MYSQL_SERVER thr_alarm_t alarmed; ALARM alarm_buff; - ulong max_allowed_packet; #endif - #ifdef __WIN__ HANDLE hPipe=INVALID_HANDLE_VALUE; #endif #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif - init_sigpipe_variables + init_sigpipe_variables; DBUG_ENTER("mysql_real_connect"); LINT_INIT(host_info); @@ -1469,9 +1444,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, set_sigpipe(mysql); net->vio = 0; /* If something goes wrong */ mysql->client_flag=0; /* For handshake */ -#ifdef MYSQL_SERVER - mysql->charset=default_charset_info; /* Set character set */ -#endif /* use default options */ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) @@ -1493,7 +1465,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (!passwd) { passwd=mysql->options.password; -#ifndef DONT_USE_MYSQL_PWD +#if !defined(DONT_USE_MYSQL_PWD) && !defined(MYSQL_SERVER) if (!passwd) passwd=getenv("MYSQL_PWD"); /* get it from environment */ #endif @@ -1511,7 +1483,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Grab a socket and connect it to the server */ -#ifdef HAVE_SMEM +#if defined(HAVE_SMEM) if ((!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && (!host || !strcmp(host,LOCAL_HOST))) @@ -1537,86 +1509,76 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, host=mysql->options.shared_memory_base_name; host_info=(char*) ER(CR_SHARED_MEMORY_CONNECTION); } - } else + } #endif /* HAVE_SMEM */ #if defined(HAVE_SYS_UN_H) - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_SOCKET)&& - (unix_socket || mysql_unix_port) && - (!host || !strcmp(host,LOCAL_HOST))) + if (!net->vio && + (!mysql->options.protocol || + mysql->options.protocol == MYSQL_PROTOCOL_SOCKET) && + (unix_socket || mysql_unix_port) && + (!host || !strcmp(host,LOCAL_HOST))) + { + host=LOCAL_HOST; + if (!unix_socket) + unix_socket=mysql_unix_port; + host_info=(char*) ER(CR_LOCALHOST_CONNECTION); + DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); + if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) { - host=LOCAL_HOST; - if (!unix_socket) - unix_socket=mysql_unix_port; - host_info=(char*) ER(CR_LOCALHOST_CONNECTION); - DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); - if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) - { - net->last_errno=CR_SOCKET_CREATE_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - sprintf(net->last_error,ER(net->last_errno),socket_errno); + net->last_errno=CR_SOCKET_CREATE_ERROR; + strmov(net->sqlstate, unknown_sqlstate); + sprintf(net->last_error,ER(net->last_errno),socket_errno); + goto error; + } + net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); + bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); + UNIXaddr.sun_family = AF_UNIX; + strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1); + if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), + mysql->options.connect_timeout)) + { + DBUG_PRINT("error",("Got error %d on connect to local server", + socket_errno)); + net->last_errno=CR_CONNECTION_ERROR; + strmov(net->sqlstate, unknown_sqlstate); + sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); + goto error; + } + mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; + } +#elif defined(__WIN__) + if (!net->vio && + (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || + (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || + (! have_tcpip && (unix_socket || !host && is_NT())))) + { + sock=0; + if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, + (char**) &host, (char**) &unix_socket)) == + INVALID_HANDLE_VALUE) + { + DBUG_PRINT("error", + ("host: '%s' socket: '%s' have_tcpip: %d", + host ? host : "", + unix_socket ? unix_socket : "", + (int) have_tcpip)); + if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || + (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || + (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) goto error; - } - net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); - bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); - UNIXaddr.sun_family = AF_UNIX; - strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1); - if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), - mysql->options.connect_timeout)) - { - DBUG_PRINT("error",("Got error %d on connect to local server", - socket_errno)); - net->last_errno=CR_CONNECTION_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - sprintf(net->last_error,ER(net->last_errno),unix_socket,socket_errno); - goto error; - } -#ifdef MYSQL_CLIENT - else - mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; -#endif + /* Try also with TCP/IP */ } else -#elif defined(__WIN__) { - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_PIPE)&& - ((unix_socket || !host && is_NT() || - host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||! have_tcpip))&& - (!net->vio)) - { - sock=0; - if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, - (char**) &host, (char**) &unix_socket)) == - INVALID_HANDLE_VALUE) - { - DBUG_PRINT("error", - ("host: '%s' socket: '%s' have_tcpip: %d", - host ? host : "", - unix_socket ? unix_socket : "", - (int) have_tcpip)); - if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE || - (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || - (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE))) - goto error; - /* Try also with TCP/IP */ - } - else - { - net->vio=vio_new_win32pipe(hPipe); - sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host, - unix_socket); - } - } + net->vio=vio_new_win32pipe(hPipe); + sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host, + unix_socket); } -#ifdef MYSQL_SERVER - if (hPipe == INVALID_HANDLE_VALUE) -#endif -#endif -#ifdef MYSQL_CLIENT - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_TCP)&&(!net->vio)) + } #endif + if (!net->vio && + (!mysql->options.protocol || + mysql->options.protocol == MYSQL_PROTOCOL_TCP)) { unix_socket=0; /* This is not used */ if (!port) @@ -1629,11 +1591,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, thr_alarm_init(&alarmed); thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff); #endif + /* _WIN64 ; Assume that the (int) range is enough for socket() */ sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); #ifdef MYSQL_SERVER thr_end_alarm(&alarmed); #endif - /* _WIN64 ; Assume that the (int) range is enough for socket() */ if (sock == SOCKET_ERROR) { net->last_errno=CR_IPSOCK_ERROR; @@ -1683,17 +1645,16 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, goto error; } } -#ifdef MYSQL_CLIENT - else if (!net->vio) + if (!net->vio) { DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); - net->last_errno= CR_CONN_UNKNOW_PROTOCOL; strmov(net->sqlstate, unknown_sqlstate); - sprintf(net->last_error ,ER(CR_CONN_UNKNOW_PROTOCOL)); + net->last_errno= CR_CONN_UNKNOW_PROTOCOL; + strmov(net->last_error, ER(CR_CONN_UNKNOW_PROTOCOL)); goto error; } -#endif /*MYSQL_CLIENT*/ - if (!net->vio || my_net_init(net, net->vio)) + + if (my_net_init(net, net->vio)) { vio_delete(net->vio); net->vio = 0; @@ -1703,9 +1664,14 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, goto error; } vio_keepalive(net->vio,TRUE); -#ifdef MYSQL_SERVER - net->read_timeout=slave_net_timeout; -#endif + /* Override local client variables */ + if (mysql->options.read_timeout) + net->read_timeout= mysql->options.read_timeout; + if (mysql->options.write_timeout) + net->write_timeout= mysql->options.write_timeout; + if (mysql->options.max_allowed_packet) + net->max_packet_size= mysql->options.max_allowed_packet; + /* Get version info */ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ if (mysql->options.connect_timeout && @@ -1725,9 +1691,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_DUMP("packet",(char*) net->read_pos,10); DBUG_PRINT("info",("mysql protocol version %d, server=%d", PROTOCOL_VERSION, mysql->protocol_version)); - if (mysql->protocol_version != PROTOCOL_VERSION - && mysql->protocol_version != PROTOCOL_VERSION-1) + if (mysql->protocol_version != PROTOCOL_VERSION) { + strmov(net->sqlstate, unknown_sqlstate); net->last_errno= CR_VERSION_ERROR; sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, PROTOCOL_VERSION); @@ -1747,7 +1713,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql->server_status=uint2korr(end+3); } -#ifdef MYSQL_CLIENT /* Set character set */ if ((charset_name=mysql->options.charset_name)) { @@ -1755,14 +1720,15 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (mysql->options.charset_dir) charsets_dir=mysql->options.charset_dir; mysql->charset=get_charset_by_csname(mysql->options.charset_name, - MY_CS_PRIMARY, - MYF(MY_WME)); + MY_CS_PRIMARY, + MYF(MY_WME)); charsets_dir=save; } else if (mysql->server_language) { charset_name=charset_name_buff; - sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */ + /* Save name in case of errors */ + int10_to_str(mysql->server_language, charset_name, 10); if (!(mysql->charset = get_charset((uint8) mysql->server_language, MYF(0)))) mysql->charset = default_charset_info; /* shouldn't be fatal */ @@ -1775,20 +1741,21 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, net->last_errno=CR_CANT_READ_CHARSET; strmov(net->sqlstate, unknown_sqlstate); if (mysql->options.charset_dir) - sprintf(net->last_error,ER(net->last_errno), - charset_name ? charset_name : "unknown", - mysql->options.charset_dir); + my_snprintf(net->last_error, sizeof(net->last_error)-1, + ER(net->last_errno), + charset_name ? charset_name : "unknown", + mysql->options.charset_dir); else { char cs_dir_name[FN_REFLEN]; get_charsets_dir(cs_dir_name); - sprintf(net->last_error,ER(net->last_errno), - charset_name ? charset_name : "unknown", - cs_dir_name); + my_snprintf(net->last_error, sizeof(net->last_error)-1, + ER(net->last_errno), + charset_name ? charset_name : "unknown", + cs_dir_name); } goto error; } -#endif /*MYSQL_CLIENT*/ /* Save connection information */ if (!user) user=""; @@ -1834,7 +1801,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (db) client_flag|=CLIENT_CONNECT_WITH_DB; -#ifdef MYSQL_CLIENT /* Remove options that server doesn't support */ client_flag= ((client_flag & ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) | @@ -1842,11 +1808,12 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #ifndef HAVE_COMPRESS client_flag&= ~CLIENT_COMPRESS; #endif + if (client_flag & CLIENT_PROTOCOL_41) { /* 4.1 server and 4.1 client has a 32 byte option flag */ int4store(buff,client_flag); - int4store(buff+4,max_allowed_packet); + int4store(buff+4, net->max_packet_size); buff[8]= mysql->charset->number; bzero(buff+9, 32-9); end= buff+32; @@ -1854,46 +1821,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, else { int2store(buff,client_flag); - int3store(buff+2,max_allowed_packet); + int3store(buff+2,net->max_packet_size); end= buff+5; } mysql->client_flag=client_flag; -#endif /*MYSQL_CLIENT*/ - -#ifdef MYSQL_SERVER -#ifdef HAVE_COMPRESS - if ((mysql->server_capabilities & CLIENT_COMPRESS) && - (mysql->options.compress || (client_flag & CLIENT_COMPRESS))) - client_flag|=CLIENT_COMPRESS; /* We will use compression */ - else -#endif - client_flag&= ~CLIENT_COMPRESS; -#endif /*MYSQL_SERVER*/ - -#ifdef MYSQL_SERVER -#ifdef HAVE_OPENSSL - if ((mysql->server_capabilities & CLIENT_SSL) && - (mysql->options.use_ssl || (client_flag & CLIENT_SSL))) - { - DBUG_PRINT("info", ("Changing IO layer to SSL")); - client_flag |= CLIENT_SSL; - } - else - { - if (client_flag & CLIENT_SSL) - { - DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL")); - } - client_flag &= ~CLIENT_SSL; - } -#endif /* HAVE_OPENSSL */ - - max_allowed_packet=mysql->net.max_packet_size; - int2store(buff,client_flag); - int3store(buff+2,max_allowed_packet); - end= buff+5; - mysql->client_flag=client_flag; -#endif /*MYSQL_SERVER*/ #ifdef HAVE_OPENSSL /* @@ -1902,9 +1833,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, */ if (client_flag & CLIENT_SSL) { -#ifdef MYSQL_CLIENT struct st_mysql_options *options= &mysql->options; -#endif if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) { strmov(net->sqlstate, unknown_sqlstate); @@ -1913,7 +1842,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, goto error; } /* Do the SSL layering. */ -#ifdef MYSQL_CLIENT if (!(mysql->connector_fd= (gptr) new_VioSSLConnectorFd(options->ssl_key, options->ssl_cert, @@ -1926,7 +1854,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, strmov(net->last_error,ER(net->last_errno)); goto error; } -#endif /*MYSQL_CLIENT*/ DBUG_PRINT("info", ("IO layer change in progress...")); if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), mysql->net.vio, (long) (mysql->options.connect_timeout))) @@ -1947,18 +1874,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (user && user[0]) strmake(end,user,32); /* Max user name */ else -#ifdef MYSQL_SERVER - { - user = getenv("USER"); - if (!user) user = "mysql"; - strmov((char*) end, user ); - } -#else read_user_name((char*) end); -#endif /*MYSQL_SERVER*/ + /* We have to handle different version of handshake here */ -#if defined(_CUSTOMCONFIG_) && defined(MYSQL_CLIENT) -#include "_cust_libmysql.h"; +#ifdef _CUSTOMCONFIG_ +#include "_cust_libmysql.h" #endif DBUG_PRINT("info",("user: %s",end)); /* @@ -2012,9 +1932,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (client_flag & CLIENT_COMPRESS) /* We will use compression */ net->compress=1; -#ifdef MYSQL_CLIENT - if (mysql->options.max_allowed_packet) - net->max_packet_size= mysql->options.max_allowed_packet; if (db && mysql_select_db(mysql,db)) goto error; @@ -2030,7 +1947,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, for (; ptrfields) { @@ -2039,13 +1956,13 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql_free_result(res); } } - mysql->reconnect=reconnect; } +#ifndef TO_BE_DELETED if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) goto error; -#endif /*MYSQL_CLIENT*/ +#endif DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); reset_sigpipe(mysql); @@ -2057,37 +1974,35 @@ error: net->last_errno, net->sqlstate, net->last_error)); { /* Free alloced memory */ - my_bool free_me=mysql->free_me; end_server(mysql); - mysql->free_me=0; - mysql_close(mysql); - mysql->free_me=free_me; + mysql_close_free(mysql); + if (!(client_flag & CLIENT_REMEMBER_OPTIONS)) + mysql_close_free_options(mysql); } DBUG_RETURN(0); } + /* needed when we move MYSQL structure to a different address */ +#ifndef TO_BE_DELETED static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) { + MYSQL *tmp, *tmp_prev; if (mysql->master == old_mysql) - mysql->master = mysql; + mysql->master= mysql; if (mysql->last_used_con == old_mysql) - mysql->last_used_con = mysql; + mysql->last_used_con= mysql; if (mysql->last_used_slave == old_mysql) - mysql->last_used_slave = mysql; -#ifdef MYSQL_CLIENT /*should work in MYSQL_SERVER also, but doesn't */ + mysql->last_used_slave= mysql; + for (tmp_prev = mysql, tmp = mysql->next_slave; + tmp != old_mysql;tmp = tmp->next_slave) { - MYSQL *tmp, *tmp_prev; - for (tmp_prev = mysql, tmp = mysql->next_slave; - tmp != old_mysql;tmp = tmp->next_slave) - { - tmp_prev = tmp; - } - tmp_prev->next_slave = mysql; + tmp_prev= tmp; } -#endif /*MYSQL_CLIENT*/ + tmp_prev->next_slave= mysql; } +#endif my_bool mysql_reconnect(MYSQL *mysql) @@ -2111,11 +2026,11 @@ my_bool mysql_reconnect(MYSQL *mysql) tmp_mysql.rpl_pivot = mysql->rpl_pivot; if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, mysql->db, mysql->port, mysql->unix_socket, - mysql->client_flag)) + mysql->client_flag | CLIENT_REMEMBER_OPTIONS)) { mysql->net.last_errno= tmp_mysql.net.last_errno; strmov(mysql->net.last_error, tmp_mysql.net.last_error); - strmov(mysql->net.sqlstate, unknown_sqlstate); + strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); DBUG_RETURN(1); } tmp_mysql.free_me=mysql->free_me; @@ -2128,6 +2043,7 @@ my_bool mysql_reconnect(MYSQL *mysql) DBUG_RETURN(0); } + /************************************************************************** Set current database **************************************************************************/ @@ -2146,42 +2062,62 @@ mysql_select_db(MYSQL *mysql, const char *db) DBUG_RETURN(0); } -/* - Free strings in the SSL structure and clear 'use_ssl' flag. - NB! Errors are not reported until you do mysql_real_connect. -*/ - -#ifdef HAVE_OPENSSL -static void -mysql_ssl_free(MYSQL *mysql __attribute__((unused))) -{ - my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); - mysql->options.ssl_key = 0; - mysql->options.ssl_cert = 0; - mysql->options.ssl_ca = 0; - mysql->options.ssl_capath = 0; - mysql->options.ssl_cipher= 0; - mysql->options.use_ssl = FALSE; - mysql->connector_fd = 0; -} -#endif /* HAVE_OPENSSL */ /************************************************************************* Send a QUIT to the server and close the connection If handle is alloced by mysql connect free it. *************************************************************************/ +static void mysql_close_free_options(MYSQL *mysql) +{ + my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); + if (mysql->options.init_commands) + { + DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; + char **ptr= (char**)init_commands->buffer; + char **end= ptr + init_commands->elements; + for (; ptroptions.shared_memory_base_name != def_shared_memory_base_name) + my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); +#endif /* HAVE_SMEM */ + bzero((char*) &mysql->options,sizeof(mysql->options)); +} + + +static void mysql_close_free(MYSQL *mysql) +{ + /* Clear pointers for better safety */ + my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); + mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; +} + + void STDCALL mysql_close(MYSQL *mysql) { DBUG_ENTER("mysql_close"); if (mysql) /* Some simple safety */ { + /* If connection is still up, send a QUIT message */ if (mysql->net.vio != 0) { free_old_query(mysql); @@ -2190,34 +2126,22 @@ mysql_close(MYSQL *mysql) simple_command(mysql,COM_QUIT,NullS,0,1); end_server(mysql); /* Sets mysql->net.vio= 0 */ } - my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); - if (mysql->options.init_commands) + mysql_close_free_options(mysql); + mysql_close_free(mysql); +#ifdef MYSQL_CLIENT + if (mysql->stmts) { - DYNAMIC_ARRAY *init_commands= mysql->options.init_commands; - char **ptr= (char**)init_commands->buffer; - char **end= ptr + init_commands->elements; - for (; ptrstmts; element; element= next_element) + { + next_element= element->next; + stmt_close((MYSQL_STMT *)element->data, 0); + } + mysql->stmts= 0; } -#ifdef HAVE_SMEM - if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) - my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); -#endif /* HAVE_SMEM */ - +#endif /*MYSQL_CLIENT*/ +#ifndef TO_BE_DELETED /* free/close slave list */ if (mysql->rpl_pivot) { @@ -2231,34 +2155,16 @@ mysql_close(MYSQL *mysql) } mysql->rpl_pivot=0; } -#ifdef MYSQL_CLIENT - if (mysql->stmts) - { - /* Free any open prepared statements */ - LIST *element, *next_element; - for (element= mysql->stmts; element; element= next_element) - { - next_element= element->next; - stmt_close((MYSQL_STMT *)element->data, 0); - } - } +#endif if (mysql != mysql->master) mysql_close(mysql->master); -#endif /*MYSQL_CLIENT*/ - -#ifdef HAVE_OPENSSL - mysql_ssl_free(mysql); -#endif /* HAVE_OPENSSL */ - /* Clear pointers for better safety */ - - mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; - bzero((char*) &mysql->options,sizeof(mysql->options)); if (mysql->free_me) my_free((gptr) mysql,MYF(0)); } DBUG_VOID_RETURN; } + my_bool STDCALL mysql_read_query_result(MYSQL *mysql) { uchar *pos; @@ -2267,18 +2173,16 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql) ulong length; DBUG_ENTER("mysql_read_query_result"); -#ifdef MYSQL_CLIENT /* Read from the connection which we actually used, which could differ from the original connection if we have slaves */ mysql = mysql->last_used_con; -#endif if ((length = net_safe_read(mysql)) == packet_error) DBUG_RETURN(1); - free_old_query(mysql); /* Free old result */ -#ifdef MYSQL_CLIENT /*or else gcc will warn of unused labels*/ + free_old_query(mysql); /* Free old result */ +#ifdef MYSQL_CLIENT /* Avoid warn of unused labels*/ get_info: #endif pos=(uchar*) mysql->net.read_pos; @@ -2341,7 +2245,7 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length) DBUG_ENTER("mysql_send_query"); DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d", mysql->options.rpl_parse, mysql->rpl_pivot)); -#ifdef MYSQL_CLIENT +#ifndef TO_BE_DELETED if (mysql->options.rpl_parse && mysql->rpl_pivot) { switch (mysql_rpl_query_type(query, length)) { @@ -2353,9 +2257,8 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length) break; /* fall through */ } } - mysql->last_used_con = mysql; -#endif /*MYSQL_CLIENT*/ +#endif DBUG_RETURN(simple_command(mysql, COM_QUERY, query, length, 1)); } @@ -2373,6 +2276,7 @@ mysql_real_query(MYSQL *mysql, const char *query, ulong length) DBUG_RETURN((int) mysql_read_query_result(mysql)); } + /************************************************************************** Alloc result struct for buffered results. All rows are read to buffer. mysql_data_seek may be used. @@ -2383,11 +2287,8 @@ mysql_store_result(MYSQL *mysql) { MYSQL_RES *result; DBUG_ENTER("mysql_store_result"); - -#ifdef MYSQL_CLIENT /* read from the actually used connection */ mysql = mysql->last_used_con; -#endif if (!mysql->fields) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) @@ -2426,8 +2327,59 @@ mysql_store_result(MYSQL *mysql) DBUG_RETURN(result); /* Data fetched */ } + /************************************************************************** - Return next row of the query results + Alloc struct for use with unbuffered reads. Data is fetched by domand + when calling to mysql_fetch_row. + mysql_data_seek is a noop. + + No other queries may be specified with the same MYSQL handle. + There shouldn't be much processing per row because mysql server shouldn't + have to wait for the client (and will not wait more than 30 sec/packet). +**************************************************************************/ + +MYSQL_RES * STDCALL +mysql_use_result(MYSQL *mysql) +{ + MYSQL_RES *result; + DBUG_ENTER("mysql_use_result"); + + mysql = mysql->last_used_con; + + if (!mysql->fields) + DBUG_RETURN(0); + if (mysql->status != MYSQL_STATUS_GET_RESULT) + { + strmov(mysql->net.sqlstate, unknown_sqlstate); + strmov(mysql->net.last_error, + ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + DBUG_RETURN(0); + } + if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+ + sizeof(ulong)*mysql->field_count, + MYF(MY_WME | MY_ZEROFILL)))) + DBUG_RETURN(0); + result->lengths=(ulong*) (result+1); + if (!(result->row=(MYSQL_ROW) + my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME)))) + { /* Ptrs: to one row */ + my_free((gptr) result,MYF(0)); + DBUG_RETURN(0); + } + result->fields= mysql->fields; + result->field_alloc= mysql->field_alloc; + result->field_count= mysql->field_count; + result->current_field=0; + result->handle= mysql; + result->current_row= 0; + mysql->fields=0; /* fields is now in result */ + mysql->status=MYSQL_STATUS_USE_RESULT; + DBUG_RETURN(result); /* Data is read to be fetched */ +} + + +/************************************************************************** + Return next row of the query results **************************************************************************/ MYSQL_ROW STDCALL @@ -2467,20 +2419,6 @@ mysql_fetch_row(MYSQL_RES *res) } } -/************************************************************************** - Move to a specific row and column -**************************************************************************/ - -void STDCALL -mysql_data_seek(MYSQL_RES *result, my_ulonglong row) -{ - MYSQL_ROWS *tmp=0; - DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); - if (result->data) - for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; - result->current_row=0; - result->data_cursor = tmp; -} int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) @@ -2491,11 +2429,17 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) case MYSQL_OPT_CONNECT_TIMEOUT: mysql->options.connect_timeout= *(uint*) arg; break; + case MYSQL_OPT_READ_TIMEOUT: + mysql->options.read_timeout= *(uint*) arg; + break; + case MYSQL_OPT_WRITE_TIMEOUT: + mysql->options.write_timeout= *(uint*) arg; + break; case MYSQL_OPT_COMPRESS: mysql->options.compress= 1; /* Remember for connect */ mysql->options.client_flag|= CLIENT_COMPRESS; break; - case MYSQL_OPT_NAMED_PIPE: + case MYSQL_OPT_NAMED_PIPE: /* This option is depricated */ mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */ break; case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ @@ -2504,11 +2448,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) else mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; break; -#ifdef MYSQL_CLIENT case MYSQL_INIT_COMMAND: add_init_command(&mysql->options,arg); break; -#endif case MYSQL_READ_DEFAULT_FILE: my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME)); @@ -2567,6 +2509,3 @@ const char * STDCALL mysql_error(MYSQL *mysql) { return mysql->net.last_error; } - -#endif /* defined(MYSQL_SERVER) || defined(HAVE_EXTERNAL_CLIENT) */ - diff --git a/sql/Makefile.am b/sql/Makefile.am index 7c98f1a9315..fd02cc906d7 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -84,7 +84,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \ sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \ slave.cc sql_repl.cc sql_union.cc sql_derived.cc \ - client.c mini_client_errors.c pack.c\ + client.c sql_client.cc mini_client_errors.c pack.c\ stacktrace.c repl_failsafe.h repl_failsafe.cc sql_olap.cc\ gstream.cc spatial.cc sql_help.cc protocol_cursor.cc gen_lex_hash_SOURCES = gen_lex_hash.cc diff --git a/sql/client_settings.h b/sql/client_settings.h index 1963281d980..16e11c4eb64 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -17,18 +17,15 @@ #include -extern char *mysql_unix_port; - -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ - | CLIENT_LOCAL_FILES | CLIENT_SECURE_CONNECTION) - +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ + CLIENT_SECURE_CONNECTION | CLIENT_TRANSACTIONS | \ + CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) #define init_sigpipe_variables #define set_sigpipe(mysql) #define reset_sigpipe(mysql) - -extern ulong slave_net_timeout; - -#ifdef HAVE_SMEM +#define read_user_name(A) {} +#define mysql_rpl_query_type(A,B) MYSQL_RPL_ADMIN +#define mysql_rpl_probe(mysql) 0 #undef HAVE_SMEM -#endif +#undef _CUSTOMCONFIG_ diff --git a/sql/log.cc b/sql/log.cc index 0ccb40c5246..8af9609850a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -209,9 +209,9 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, #ifdef EMBEDDED_LIBRARY sprintf(buff, "%s, Version: %s, embedded library\n", my_progname, server_version); #elif __NT__ - sprintf(buff, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysql_port, mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysqld_port, mysqld_unix_port); #else - sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysqld_port,mysqld_unix_port); #endif end=strmov(strend(buff),"Time Id Command Argument\n"); if (my_b_write(&log_file, (byte*) buff,(uint) (end-buff)) || diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 0508d0aa986..432ca533c6a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -732,7 +732,7 @@ extern ulong specialflag, current_pid; extern ulong expire_logs_days; extern my_bool relay_log_purge; extern uint test_flags,select_errors,ha_open_options; -extern uint protocol_version,dropping_tables; +extern uint protocol_version, mysqld_port, dropping_tables; extern uint delay_key_write_options; extern bool opt_endinfo, using_udf_functions, locked_in_memory; extern bool opt_using_transactions, mysql_embedded; @@ -747,7 +747,7 @@ extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern my_bool opt_readonly; extern my_bool opt_enable_named_pipe; extern my_bool opt_old_passwords, use_old_passwords; -extern char *shared_memory_base_name; +extern char *shared_memory_base_name, *mysqld_unix_port; extern bool opt_enable_shared_memory; extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3f3b2ee7c9f..d72ad8f6768 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -35,6 +35,7 @@ #include #include #include +#include #define mysqld_charset &my_charset_latin1 @@ -254,7 +255,7 @@ my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam; my_bool opt_readonly, use_temp_pool, relay_log_purge; volatile bool mqh_used = 0; -uint mysql_port, test_flags, select_errors, dropping_tables, ha_open_options; +uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; uint delay_key_write_options, protocol_version; uint volatile thread_count, thread_running, kill_cached_threads, wake_thread; @@ -303,7 +304,7 @@ char mysql_real_data_home[FN_REFLEN], char *language_ptr, *default_collation_name, *default_character_set_name; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION; -char *mysql_unix_port, *opt_mysql_tmpdir; +char *mysqld_unix_port, *opt_mysql_tmpdir; char *my_bind_addr_str; const char **errmesg; /* Error messages */ const char *myisam_recover_options_str="OFF"; @@ -561,7 +562,7 @@ static void close_connections(void) { (void) shutdown(unix_sock,2); (void) closesocket(unix_sock); - (void) unlink(mysql_unix_port); + (void) unlink(mysqld_unix_port); unix_sock= INVALID_SOCKET; } #endif @@ -670,7 +671,7 @@ static void close_server_sock() DBUG_PRINT("info",("calling closesocket on unix/IP socket")); VOID(closesocket(tmp_sock)); #endif - VOID(unlink(mysql_unix_port)); + VOID(unlink(mysqld_unix_port)); } DBUG_VOID_RETURN; #endif @@ -961,24 +962,24 @@ static void clean_up_mutexes() static void set_ports() { char *env; - if (!mysql_port && !opt_disable_networking) + if (!mysqld_port && !opt_disable_networking) { // Get port if not from commandline struct servent *serv_ptr; - mysql_port = MYSQL_PORT; - if ((serv_ptr = getservbyname("mysql", "tcp"))) - mysql_port = ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */ + mysqld_port= MYSQL_PORT; + if ((serv_ptr= getservbyname("mysql", "tcp"))) + mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */ if ((env = getenv("MYSQL_TCP_PORT"))) - mysql_port = (uint) atoi(env); /* purecov: inspected */ + mysqld_port= (uint) atoi(env); /* purecov: inspected */ } - if (!mysql_unix_port) + if (!mysqld_unix_port) { #ifdef __WIN__ - mysql_unix_port = (char*) MYSQL_NAMEDPIPE; + mysqld_unix_port= (char*) MYSQL_NAMEDPIPE; #else - mysql_unix_port = (char*) MYSQL_UNIX_ADDR; + mysqld_unix_port= (char*) MYSQL_UNIX_ADDR; #endif if ((env = getenv("MYSQL_UNIX_PORT"))) - mysql_unix_port = env; /* purecov: inspected */ + mysqld_unix_port= env; /* purecov: inspected */ } } @@ -1088,9 +1089,9 @@ static void server_init(void) set_ports(); - if (mysql_port != 0 && !opt_disable_networking && !opt_bootstrap) + if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap) { - DBUG_PRINT("general",("IP Socket is %d",mysql_port)); + DBUG_PRINT("general",("IP Socket is %d",mysqld_port)); ip_sock = socket(AF_INET, SOCK_STREAM, 0); if (ip_sock == INVALID_SOCKET) { @@ -1101,14 +1102,14 @@ static void server_init(void) bzero((char*) &IPaddr, sizeof(IPaddr)); IPaddr.sin_family = AF_INET; IPaddr.sin_addr.s_addr = my_bind_addr; - IPaddr.sin_port = (unsigned short) htons((unsigned short) mysql_port); + IPaddr.sin_port = (unsigned short) htons((unsigned short) mysqld_port); (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg)); if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), sizeof(IPaddr)) < 0) { DBUG_PRINT("error",("Got error: %d from bind",socket_errno)); sql_perror("Can't start server: Bind on TCP/IP port"); - sql_print_error("Do you already have another mysqld server running on port: %d ?",mysql_port); + sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port); unireg_abort(1); } if (listen(ip_sock,(int) back_log) < 0) @@ -1123,10 +1124,10 @@ static void server_init(void) #ifdef __NT__ /* create named pipe */ - if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap && + if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap && opt_enable_named_pipe) { - sprintf(szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port ); + sprintf(szPipeName, "\\\\.\\pipe\\%s", mysqld_unix_port ); ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) ); ZeroMemory( &sdPipeDescriptor, sizeof(sdPipeDescriptor) ); if ( !InitializeSecurityDescriptor(&sdPipeDescriptor, @@ -1172,9 +1173,9 @@ static void server_init(void) /* ** Create the UNIX socket */ - if (mysql_unix_port[0] && !opt_bootstrap) + if (mysqld_unix_port[0] && !opt_bootstrap) { - DBUG_PRINT("general",("UNIX Socket is %s",mysql_unix_port)); + DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port)); if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { @@ -1183,8 +1184,8 @@ static void server_init(void) } bzero((char*) &UNIXaddr, sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; - strmov(UNIXaddr.sun_path, mysql_unix_port); - (void) unlink(mysql_unix_port); + strmov(UNIXaddr.sun_path, mysqld_unix_port); + (void) unlink(mysqld_unix_port); (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg, sizeof(arg)); umask(0); @@ -1192,12 +1193,12 @@ static void server_init(void) sizeof(UNIXaddr)) < 0) { sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */ - sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysql_unix_port); + sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port); unireg_abort(1); /* purecov: tested */ } umask(((~my_umask) & 0666)); #if defined(S_IFSOCK) && defined(SECURE_SOCKETS) - (void) chmod(mysql_unix_port,S_IFSOCK); /* Fix solaris 2.6 bug */ + (void) chmod(mysqld_unix_port,S_IFSOCK); /* Fix solaris 2.6 bug */ #endif if (listen(unix_sock,(int) back_log) < 0) sql_print_error("Warning: listen() on Unix socket failed with error %d", @@ -2024,6 +2025,7 @@ static int init_common_variables(const char *conf_file_name, int argc, #endif unireg_init(opt_specialflag); /* Set up extern variabels */ init_errmessage(); /* Read error messages from file */ + init_client_errs(); lex_init(); item_init(); set_var_init(); @@ -2426,7 +2428,7 @@ The server will not act as a slave."); (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore #endif if (unix_sock != INVALID_SOCKET) - unlink(mysql_unix_port); + unlink(mysqld_unix_port); exit(1); } if (!opt_noacl) @@ -2458,8 +2460,8 @@ The server will not act as a slave."); create_maintenance_thread(); printf(ER(ER_READY),my_progname,server_version, - ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysql_unix_port), - mysql_port); + ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysqld_unix_port), + mysqld_port); fflush(stdout); #if defined(__NT__) || defined(HAVE_SMEM) @@ -3775,8 +3777,8 @@ Does nothing yet.", {"log-error", OPT_ERROR_LOG_FILE, "Log error file", (gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"port", 'P', "Port number to use for connection.", (gptr*) &mysql_port, - (gptr*) &mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"port", 'P', "Port number to use for connection.", (gptr*) &mysqld_port, + (gptr*) &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"reckless-slave", OPT_RECKLESS_SLAVE, "For debugging", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-do-db", OPT_REPLICATE_DO_DB, @@ -3914,7 +3916,7 @@ replicating a LOAD DATA INFILE command", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"socket", OPT_SOCKET, "Socket file to use for connection", - (gptr*) &mysql_unix_port, (gptr*) &mysql_unix_port, 0, GET_STR, + (gptr*) &mysqld_unix_port, (gptr*) &mysqld_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME, "If set, setting SQL_LOG_BIN to a value will automatically set SQL_LOG_UPDATE to the same value and vice versa.", @@ -4630,7 +4632,7 @@ static void mysql_init_variables(void) max_sort_char= 0; mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0; errmesg= 0; - mysql_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; + mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); bzero((gptr) &com_stat, sizeof(com_stat)); @@ -5037,7 +5039,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; case (int) OPT_SKIP_NETWORKING: opt_disable_networking=1; - mysql_port=0; + mysqld_port=0; break; case (int) OPT_SKIP_SHOW_DB: opt_skip_show_db=1; diff --git a/sql/protocol.cc b/sql/protocol.cc index 10fe2c1725e..1d730836d6e 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -103,8 +103,7 @@ void send_error(THD *thd, uint sql_errno, const char *err) { /* The first # is to make the protocol backward compatible */ buff[2]= '#'; - strmov(buff+3, mysql_errno_to_sqlstate(sql_errno)); - pos= buff + 2 + SQLSTATE_LENGTH +1; + pos= strmov(buff+3, mysql_errno_to_sqlstate(sql_errno)); } length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff); err=buff; @@ -236,28 +235,6 @@ net_printf(THD *thd, uint errcode, ...) DBUG_VOID_RETURN; } -/* - Function called by my_net_init() to set some check variables -*/ - -#ifndef EMBEDDED_LIBRARY -extern "C" { -void my_net_local_init(NET *net) -{ - net->max_packet= (uint) global_system_variables.net_buffer_length; - net->read_timeout= (uint) global_system_variables.net_read_timeout; - net->write_timeout=(uint) global_system_variables.net_write_timeout; - net->retry_count= (uint) global_system_variables.net_retry_count; - net->max_packet_size= max(global_system_variables.net_buffer_length, - global_system_variables.max_allowed_packet); -} -} - -#else /* EMBEDDED_LIBRARY */ -void my_net_local_init(NET *net __attribute__(unused)) -{ -} -#endif /* EMBEDDED_LIBRARY */ /* Return ok to the client. diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index bbfd7866aa2..60af9a92c76 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -450,11 +450,11 @@ int show_new_master(THD* thd) /* Asks the master for the list of its other connected slaves. - This is for failsafe replication : - in order for failsafe replication to work, the servers involved in replication - must know of each other. We accomplish this by having each slave report to the - master how to reach it, and on connection, each slave receives information - about where the other slaves are. + This is for failsafe replication: + in order for failsafe replication to work, the servers involved in + replication must know of each other. We accomplish this by having each + slave report to the master how to reach it, and on connection, each + slave receives information about where the other slaves are. SYNOPSIS update_slave_list() @@ -466,8 +466,8 @@ int show_new_master(THD* thd) hostname/port of the master, the username used by the slave to connect to the master. If the user used by the slave to connect to the master does not have the - REPLICATION SLAVE privilege, it will pop in this function because SHOW SLAVE - HOSTS will fail on the master. + REPLICATION SLAVE privilege, it will pop in this function because + SHOW SLAVE HOSTS will fail on the master. RETURN VALUES 1 error @@ -483,7 +483,6 @@ int update_slave_list(MYSQL* mysql, MASTER_INFO* mi) int port_ind; DBUG_ENTER("update_slave_list"); - if (mysql_real_query(mysql,"SHOW SLAVE HOSTS",16) || !(res = mysql_store_result(mysql))) { @@ -668,8 +667,10 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi) strmov(mysql->net.last_error, "Master is not configured"); DBUG_RETURN(1); } - mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&slave_net_timeout); - mysql_options(mysql, MYSQL_SET_CHARSET_NAME, (char *)default_charset_info); + mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout); + mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout); + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname); + mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir); if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, mi->port, 0, 0)) DBUG_RETURN(1); diff --git a/sql/set_var.cc b/sql/set_var.cc index ad3966f76f9..14a8738de01 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -596,7 +596,7 @@ struct show_var_st init_vars[]= { {"open_files_limit", (char*) &open_files_limit, SHOW_LONG}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, {"log_error", (char*) log_error_file, SHOW_CHAR}, - {"port", (char*) &mysql_port, SHOW_INT}, + {"port", (char*) &mysqld_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, @@ -627,7 +627,7 @@ struct show_var_st init_vars[]= { {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, {sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS}, #ifdef HAVE_SYS_UN_H - {"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR}, + {"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR}, #endif {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS}, {sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS}, diff --git a/sql/slave.cc b/sql/slave.cc index cc27bb96ab7..37a86e42215 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -71,7 +71,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, void* thread_killed_arg); static int request_table_dump(MYSQL* mysql, const char* db, const char* table); -static int create_table_from_dump(THD* thd, NET* net, const char* db, +static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, const char* table_name); static int check_master_version(MYSQL* mysql, MASTER_INFO* mi); char* rewrite_db(char* db); @@ -1049,10 +1049,10 @@ static int check_master_version(MYSQL* mysql, MASTER_INFO* mi) } -static int create_table_from_dump(THD* thd, NET* net, const char* db, +static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, const char* table_name) { - ulong packet_len = my_net_read(net); // read create table statement + ulong packet_len; char *query; Vio* save_vio; HA_CHECK_OPT check_opt; @@ -1060,7 +1060,9 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, int error= 1; handler *file; ulong save_options; + NET *net= &mysql->net; + packet_len= my_net_read(net); // read create table statement if (packet_len == packet_error) { send_error(thd, ER_MASTER_NET_READ); @@ -1068,32 +1070,27 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, } if (net->read_pos[0] == 255) // error from master { - net->read_pos[packet_len] = 0; - net_printf(thd, ER_MASTER, net->read_pos + 3); + char *err_msg; + err_msg= (char*) net->read_pos + ((mysql->server_capabilities & + CLIENT_PROTOCOL_41) ? + 3+SQLSTATE_LENGTH+1 : 3); + net_printf(thd, ER_MASTER, err_msg); return 1; } thd->command = COM_TABLE_DUMP; + thd->query_length= packet_len; /* Note that we should not set thd->query until the area is initalized */ - if (!(query = sql_alloc(packet_len + 1))) + if (!(query = thd->strmake((char*) net->read_pos, packet_len))) { sql_print_error("create_table_from_dump: out of memory"); net_printf(thd, ER_GET_ERRNO, "Out of memory"); return 1; } - memcpy(query, net->read_pos, packet_len); - query[packet_len]= 0; - thd->query_length= packet_len; - /* - We make the following lock in an attempt to ensure that the compiler will - not rearrange the code so that thd->query is set too soon - */ - VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query= query; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->current_tablenr = 0; thd->query_error = 0; thd->net.no_send_ok = 1; - + /* we do not want to log create table statement */ save_options = thd->options; thd->options &= ~(ulong) (OPTION_BIN_LOG); @@ -1185,8 +1182,7 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, errmsg= "Failed on table dump request"; goto err; } - if (create_table_from_dump(thd, &mysql->net, db_name, - table_name)) + if (create_table_from_dump(thd, mysql, db_name, table_name)) goto err; // create_table_from_dump will have sent the error already error = 0; @@ -2963,17 +2959,20 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, #ifndef DBUG_OFF events_till_disconnect = disconnect_slave_event_count; #endif - uint client_flag=0; + ulong client_flag= CLIENT_REMEMBER_OPTIONS; if (opt_slave_compressed_protocol) client_flag=CLIENT_COMPRESS; /* We will use compression */ + mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout); + mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout); + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname); + /* This one is not strictly needed but we have it here for completeness */ + mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir); + while (!(slave_was_killed = io_slave_killed(thd,mi)) && - (reconnect ? mysql_reconnect(mysql) != 0: - !(mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, - (char *)&thd->variables.net_read_timeout), - mysql_options(mysql, MYSQL_SET_CHARSET_NAME, (char *)default_charset_info), - mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, - mi->port, 0, client_flag)))) + (reconnect ? mysql_reconnect(mysql) != 0 : + mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, + mi->port, 0, client_flag) == 0)) { /* Don't repeat last error */ if ((int)mysql_errno(mysql) != last_errno) diff --git a/sql/sql_client.cc b/sql/sql_client.cc new file mode 100644 index 00000000000..464596f0734 --- /dev/null +++ b/sql/sql_client.cc @@ -0,0 +1,45 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* + This files defines some MySQL C API functions that are server specific +*/ + +#include + +/* + Function called by my_net_init() to set some check variables +*/ + +extern "C" { +void my_net_local_init(NET *net) +{ +#ifndef EMBEDDED_LIBRARY + net->max_packet= (uint) global_system_variables.net_buffer_length; + net->read_timeout= (uint) global_system_variables.net_read_timeout; + net->write_timeout=(uint) global_system_variables.net_write_timeout; + net->retry_count= (uint) global_system_variables.net_retry_count; + net->max_packet_size= max(global_system_variables.net_buffer_length, + global_system_variables.max_allowed_packet); +#endif +} +} + +extern "C" { +void mysql_once_init(void) +{ +} +} From fdd296c8b8d1f9c7f4980e9d12f0daefeba17d59 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 Jun 2003 17:33:25 -0400 Subject: [PATCH 354/399] fixed bug with './' prefix in mysql_install_db scripts/mysql_install_db.sh: fixed bug with './' prefix --- scripts/mysql_install_db.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 96e33d3e7c5..eb9800d02f8 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -186,7 +186,7 @@ fi echo "Installing all prepared tables" if ( - mysql_create_system_tables $create_option $mdata $hostname $windows + ./mysql_create_system_tables $create_option $mdata $hostname $windows if test -n "$fill_help_tables" then cat $fill_help_tables From fb2825e2b5bb05addbc836ae773783f8c652dd54 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Jun 2003 12:34:04 +0300 Subject: [PATCH 355/399] LAST_INSERT_ID()}will now return 0 if the last INSERT didn't insert any rows. mysql-test/r/auto_increment.result: Update results after bug fix --- mysql-test/r/auto_increment.result | 2 +- sql/sql_insert.cc | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index bd15c913d2e..5553f718799 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -143,5 +143,5 @@ insert into t1 values (NULL, 10); ERROR 23000: Duplicate entry '10' for key 2 select last_insert_id(); last_insert_id() -3 +0 drop table t1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f65ef4b968a..091de9d406f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -308,6 +308,11 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, } thd->row_count++; } + + /* + Now all rows are inserted. Time to update logs and sends response to + user + */ if (lock_type == TL_WRITE_DELAYED) { if (!error) @@ -341,7 +346,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, } if (id && values_list.elements != 1) thd->insert_id(id); // For update log - else if (table->next_number_field) + else if (table->next_number_field && info.copied) id=table->next_number_field->val_int(); // Return auto_increment value /* @@ -383,9 +388,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, thd->next_insert_id=0; // Reset this if wrongly used if (duplic != DUP_ERROR) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + + /* Reset value of LAST_INSERT_ID if no rows where inserted */ + if (!info.copied && thd->insert_id_used) + { + thd->insert_id(0); + id=0; + } if (error) goto abort; - if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) || !thd->cuted_fields)) send_ok(thd,info.copied+info.deleted,id); From ed1d28fdb6b6c828556917716c9b700bf7450426 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Jun 2003 23:24:37 +0300 Subject: [PATCH 356/399] Fixes for make_win_src_distributions Removed compiler warnings scripts/make_win_src_distribution.sh: Added option --dirname Also copy sql-common directory Create mysql data files even if mysqld is not installed scripts/mysql_create_system_tables.sh: Update for usage with make_win_src_distribution scripts/mysql_install_db.sh: Update for usage with make_win_src_distribution sql-common/client.c: Portability fix sql/item_cmpfunc.cc: Removed compiler warning sql/sql_acl.cc: Indentation cleanup Removed compiler warning sql/sql_parse.cc: Removed compiler warning sql/sql_select.cc: Removed compiler warning sql/sql_yacc.yy: Removed compiler warning strings/ctype-utf8.c: Removed compiler warning --- scripts/make_win_src_distribution.sh | 37 ++++++++++------- scripts/mysql_create_system_tables.sh | 33 +++++++-------- scripts/mysql_install_db.sh | 60 +++++++++++++++------------ sql-common/client.c | 2 +- sql/item_cmpfunc.cc | 2 + sql/sql_acl.cc | 14 ++++--- sql/sql_parse.cc | 1 - sql/sql_select.cc | 3 +- sql/sql_yacc.yy | 2 +- strings/ctype-utf8.c | 12 +++--- 10 files changed, 91 insertions(+), 75 deletions(-) diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index a6312193221..f76fe02e2bd 100755 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -12,6 +12,7 @@ CP="cp -p" DEBUG=0 SILENT=0 SUFFIX="" +DIRNAME="" OUTTAR=0 # @@ -75,6 +76,7 @@ parse_arguments() { --debug) DEBUG=1;; --tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;; --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;; + --dirname=*) DIRNAME=`echo "$arg" | sed -e "s;--dirname=;;"` ;; --silent) SILENT=1 ;; --tar) OUTTAR=1 ;; --help) show_usage ;; @@ -155,11 +157,15 @@ mkdir $BASE/Docs $BASE/extra $BASE/include # Copy directory files # -copy_dir_files() { - +copy_dir_files() +{ for arg do print_debug "Copying files from directory '$arg'" - cd $SOURCE/$arg/ + cd $SOURCE/$arg + if [ ! -d $BASE/$arg ]; then + print_debug "Creating directory '$arg'" + mkdir $BASE/$arg + fi for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def \ README INSTALL* LICENSE do @@ -199,9 +205,6 @@ copy_dir_dirs() { for i in * do if [ -d $SOURCE/$basedir/$i ] && [ "$i" != "SCCS" ]; then - if [ ! -d $BASE/$basedir/$i ]; then - mkdir $BASE/$basedir/$i - fi copy_dir_files $basedir/$i fi done @@ -214,7 +217,7 @@ copy_dir_dirs() { for i in client dbug extra heap include isam \ libmysql libmysqld merge myisam \ - myisammrg mysys regex sql strings \ + myisammrg mysys regex sql strings sql-common \ vio zlib do copy_dir_files $i @@ -270,15 +273,19 @@ done if [ -f scripts/mysql_install_db ]; then print_debug "Initializing the 'data' directory" - scripts/mysql_install_db --windows --datadir=$BASE/data + scripts/mysql_install_db --no-defaults --windows --datadir=$BASE/data fi - # # Specify the distribution package name and copy it # -NEW_DIR_NAME=mysql@MYSQL_SERVER_SUFFIX@-$version$SUFFIX +if test -z $DIRNAME +then + NEW_DIR_NAME=mysql@MYSQL_SERVER_SUFFIX@-$version$SUFFIX +else + NEW_DIR_NAME=$DIRNAME +fi NEW_NAME=$NEW_DIR_NAME-win-src BASE2=$TMP/$NEW_DIR_NAME @@ -345,7 +352,7 @@ set_tarzip_options() EXT=".zip" NEED_COMPRESS=0 if [ "$SILENT" = "1" ] ; then - OPT="-r" + OPT="$OPT -q" fi fi done @@ -386,9 +393,7 @@ fi print_debug "Removing temporary directory" rm -r -f $BASE -echo "$NEW_NAME$EXT created successfully !!" - +if [ "$SILENT" = "0" ] ; then + echo "$NEW_NAME$EXT created successfully !!" +fi # End of script - - - diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index c54394305cd..51fbb8a8097 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -1,6 +1,5 @@ #!/bin/sh - -# Copyright (C) 1997-2002 MySQL AB +# Copyright (C) 1997-2003 MySQL AB # For a more info consult the file COPYRIGHT distributed with this file # This script writes on stdout SQL commands to generate all not @@ -12,7 +11,7 @@ # $3 - hostname # $4 - windows option -if test x$1 = x"" ; +if test "$1" = "" then echo " This script writes on stdout SQL commands to generate all not @@ -20,9 +19,9 @@ existing MySQL system tables. It also replaces the help tables with new context from the manual (from fill_help_tables.sql). Usage: - mysql_create_system_tables {help|real|verbose} -"; - exit; + mysql_create_system_tables [test|verbose|real] +" + exit fi mdata=$2 @@ -44,7 +43,7 @@ i_ht="" # Check for old tables if test ! -f $mdata/db.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing db table" 1>&2; fi @@ -76,7 +75,7 @@ fi if test ! -f $mdata/host.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing host table" 1>&2; fi @@ -102,7 +101,7 @@ fi if test ! -f $mdata/user.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing user table" 1>&2; fi @@ -142,7 +141,7 @@ then c_u="$c_u )" c_u="$c_u comment='Users and global privileges';" - if test x$1 = x"test" + if test "$1" = "test" then i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); @@ -165,7 +164,7 @@ fi if test ! -f $mdata/func.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing func table" 1>&2; fi @@ -181,7 +180,7 @@ fi if test ! -f $mdata/tables_priv.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing tables_priv table" 1>&2; fi @@ -202,7 +201,7 @@ fi if test ! -f $mdata/columns_priv.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing columns_priv table" 1>&2; fi @@ -221,7 +220,7 @@ fi if test ! -f $mdata/help_topic.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing help_topic table" 1>&2; fi @@ -242,7 +241,7 @@ old_categories="yes" if test ! -f $mdata/help_category.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing help_category table" 1>&2; fi @@ -259,7 +258,7 @@ fi if test ! -f $mdata/help_keyword.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing help_keyword table" 1>&2; fi @@ -274,7 +273,7 @@ fi if test ! -f $mdata/help_relation.frm then - if test x$1 = x"verbose" ; then + if test "$1" = "verbose" ; then echo "Preparing help_relation table" 1>&2; fi diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 96e33d3e7c5..9e4f35dd5e1 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -8,18 +8,8 @@ # All unrecognized arguments to this script are passed to mysqld. in_rpm=0 -case "$1" in - --rpm) - in_rpm="1"; shift - ;; -esac windows=0 -case "$1" in - --windows) - windows="1"; shift - ;; -esac -defaults= +defaults="" case "$1" in --no-defaults|--defaults-file=*|--defaults-extra-file=*) defaults="$1"; shift @@ -44,6 +34,8 @@ parse_arguments() { --ldata=*|--datadir=*) ldata=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; --verbose) verbose=1 ;; + --rpm) in_rpm=1 ;; + --windows) windows=1 ;; *) if test -n "$pick_args" then @@ -61,6 +53,9 @@ parse_arguments() { if test -x ./bin/my_print_defaults then print_defaults="./bin/my_print_defaults" +elif test -x ./extra/my_print_defaults +then + print_defaults="./extra/my_print_defaults" elif test -x @bindir@/my_print_defaults then print_defaults="@bindir@/my_print_defaults" @@ -79,6 +74,7 @@ basedir= force=0 verbose=0 fill_help_tables="" + parse_arguments `$print_defaults $defaults mysqld mysql_install_db` parse_arguments PICK-ARGS-FROM-ARGV "$@" @@ -103,7 +99,7 @@ else fi # find fill_help_tables.sh -for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts `pwd` @pkgdatadir@ +for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts `pwd` `pwd`/scripts @pkgdatadir@ do if test -f $i/fill_help_tables.sql then @@ -115,22 +111,28 @@ if test -f $pkgdatadir/fill_help_tables.sql then fill_help_tables=$pkgdatadir/fill_help_tables.sql else - if test $verbose -eq 1 - then - echo "Could not find help file 'fill_help_tables.sql' ;$pkgdatadir; ;$basedir;". - fi + echo "Could not find help file 'fill_help_tables.sql' in @pkgdatadir@ or inside $basedir". + exit 1; fi mdata=$ldata/mysql +mysqld=$execdir/mysqld +mysqld_opt="" -if test "$windows" -eq 0 -a ! -x $execdir/mysqld +if test "$windows" = 1 +then + mysqld="./sql/mysqld" + mysqld_opt="--language=./sql/share/english" +fi + +if test ! -x $mysqld then if test "$in_rpm" -eq 1 then - echo "FATAL ERROR $execdir/mysqld not found!" + echo "FATAL ERROR $mysqld not found!" exit 1 else - echo "Didn't find $execdir/mysqld" + echo "Didn't find $mysqld" echo "You should do a 'make install' before executing this script" exit 1 fi @@ -184,23 +186,28 @@ else create_option="real" fi -echo "Installing all prepared tables" +if test "$in_rpm" -eq 0 -a "$windows" -eq 0 +then + echo "Installing all prepared tables" +fi if ( - mysql_create_system_tables $create_option $mdata $hostname $windows + $pkgdatadir/mysql_create_system_tables $create_option $mdata $hostname $windows if test -n "$fill_help_tables" then cat $fill_help_tables fi -) | eval "$execdir/mysqld $defaults --bootstrap --skip-grant-tables \ +) | eval "$mysqld $defaults $mysqld_opt --bootstrap --skip-grant-tables \ --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $args" then - echo "" - if test "$in_rpm" -eq 0 || "$windows" -eq 0 + if test "$in_rpm" -eq 0 -a "$windows" -eq 0 then + echo "" echo "To start mysqld at boot time you have to copy support-files/mysql.server" echo "to the right place for your system" echo fi + if test "$windows" -eq 0 + then echo "PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !" echo "This is done with:" echo "$bindir/mysqladmin -u root password 'new-password'" @@ -216,7 +223,7 @@ then echo "able to use the new GRANT command!" fi echo - if test "$in_rpm" -eq 0 -a "$windows" -eq 0 + if test "$in_rpm" -eq 0 then echo "You can start the MySQL daemon with:" echo "cd @prefix@ ; $bindir/mysqld_safe &" @@ -230,13 +237,14 @@ then echo "The latest information about MySQL is available on the web at" echo "http://www.mysql.com" echo "Support MySQL by buying support/licenses at https://order.mysql.com" + fi exit 0 else echo "Installation of grant tables failed!" echo echo "Examine the logs in $ldata for more information." echo "You can also try to start the mysqld daemon with:" - echo "$execdir/mysqld --skip-grant &" + echo "$mysqld --skip-grant &" echo "You can use the command line tool" echo "$bindir/mysql to connect to the mysql" echo "database and look at the grant tables:" diff --git a/sql-common/client.c b/sql-common/client.c index 1f0f67e4ff1..66a073ed53f 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -107,7 +107,7 @@ const char *unknown_sqlstate= "HY000"; const char *not_error_sqlstate= "00000"; #ifdef HAVE_SMEM char *shared_memory_base_name= 0; -const char def_shared_memory_base_name= default_shared_memory_base_name; +const char *def_shared_memory_base_name= default_shared_memory_base_name; #endif static void mysql_close_free_options(MYSQL *mysql); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 74036edf605..d4997f78a9e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1652,7 +1652,9 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { List_iterator li(list); Item *item; +#ifndef EMBEDDED_LIBRARY char buff[sizeof(char*)]; // Max local vars in function +#endif used_tables_cache=0; const_item_cache=0; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 49aad321702..1bdca7167e8 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3337,15 +3337,19 @@ int mysql_drop_user(THD *thd, List &list) } tables[0].table->field[0]->store(user_name->host.str,(uint) - user_name->host.length, system_charset_info); + user_name->host.length, + system_charset_info); tables[0].table->field[1]->store(user_name->user.str,(uint) - user_name->user.length, system_charset_info); + user_name->user.length, + system_charset_info); if (!tables[0].table->file->index_read_idx(tables[0].table->record[0],0, - (byte*) tables[0].table->field[0]->ptr,0, + (byte*) tables[0].table-> + field[0]->ptr,0, HA_READ_KEY_EXACT)) { int error; - if ((error = tables[0].table->file->delete_row(tables[0].table->record[0]))) + if ((error = tables[0].table->file->delete_row(tables[0].table-> + record[0]))) { tables[0].table->file->print_error(error, MYF(0)); tables[0].table->file->index_end(); @@ -3355,7 +3359,7 @@ int mysql_drop_user(THD *thd, List &list) } tables[0].table->file->index_end(); } -err: + VOID(pthread_mutex_unlock(&acl_cache->lock)); rw_unlock(&LOCK_grant); close_thread_tables(thd); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a9a29904b60..47c7026c184 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2308,7 +2308,6 @@ mysql_execute_command(THD *thd) break; } case SQLCOM_UPDATE: - TABLE_LIST *table; if (check_db_used(thd,tables)) goto error; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a5fd69c8fbb..248496d6b43 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8061,7 +8061,6 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) bool JOIN::rollup_init() { uint i,j; - ORDER *group; Item **ref_array; tmp_table_param.quick_group= 0; // Can't create groups in tmp table @@ -8145,7 +8144,7 @@ bool JOIN::rollup_make_fields(List &all_fields, List &fields, ... */ - for (level=0 ; level < send_group_parts > 0 ; level++) + for (level=0 ; level < send_group_parts ; level++) { uint i; uint pos= send_group_parts - level -1; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 91bd5a77d27..c385d6d5308 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3850,7 +3850,7 @@ purge_option: } Item *tmp= new Item_func_unix_timestamp($2); Lex->sql_command = SQLCOM_PURGE_BEFORE; - Lex->purge_time= tmp->val_int(); + Lex->purge_time= (ulong) tmp->val_int(); } ; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 4d9c735de21..f5da95571c4 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1723,13 +1723,13 @@ static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) , switch (count) { /* Fall through all cases!!! */ #ifdef UNICODE_32BIT - case 6: r[5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000; - case 5: r[4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000; - case 4: r[3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000; + case 6: r[5] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x4000000; + case 5: r[4] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x200000; + case 4: r[3] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x10000; #endif - case 3: r[2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800; - case 2: r[1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0; - case 1: r[0] = wc; + case 3: r[2] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x800; + case 2: r[1] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0xc0; + case 1: r[0] = (uchar) wc; } return count; } From 7ababc3bb43193f2e9d01267d65319291001d980 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jun 2003 03:13:22 +0500 Subject: [PATCH 357/399] Fix for compilation error. Compiler can signal error when init_sigpipe_variables expands as empty place. Had to remove all semicolons after init_sigpipe_variables libmysql/client_settings.h: semicolon added sql-common/client.c: we don't need semicolons after init_sigpipe_variables --- libmysql/client_settings.h | 2 +- sql-common/client.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index 8c28de73866..17e992be5b0 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -31,7 +31,7 @@ my_bool send_file_to_server(MYSQL *mysql, const char *filename); */ #if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD) -#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0 +#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0; #define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler) #define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler); #else diff --git a/sql-common/client.c b/sql-common/client.c index 1f0f67e4ff1..abeb64e82fb 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -514,7 +514,7 @@ net_safe_read(MYSQL *mysql) { NET *net= &mysql->net; ulong len=0; - init_sigpipe_variables; + init_sigpipe_variables /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); @@ -579,7 +579,7 @@ advanced_command(MYSQL *mysql, enum enum_server_command command, { NET *net= &mysql->net; my_bool result= 1; - init_sigpipe_variables; + init_sigpipe_variables /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); @@ -670,7 +670,7 @@ void end_server(MYSQL *mysql) DBUG_ENTER("end_server"); if (mysql->net.vio != 0) { - init_sigpipe_variables; + init_sigpipe_variables DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); set_sigpipe(mysql); vio_delete(mysql->net.vio); @@ -1431,7 +1431,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif - init_sigpipe_variables; + init_sigpipe_variables DBUG_ENTER("mysql_real_connect"); LINT_INIT(host_info); From 7a938aea268cde51a4947eb44622e50dee9fbb64 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jun 2003 00:13:23 +0200 Subject: [PATCH 358/399] bad merge fixed mysql-test/r/fulltext.result: test for CREATE FULLTEXT INDEX mysql-test/t/fulltext.test: test for CREATE FULLTEXT INDEX --- mysql-test/r/fulltext.result | 4 ++-- mysql-test/t/fulltext.test | 4 ++-- sql/sql_yacc.yy | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index caf93e7e973..157beec2c01 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -172,9 +172,9 @@ CREATE TABLE t1 ( id int(11) auto_increment, title varchar(100) default '', PRIMARY KEY (id), -KEY ind5 (title), -FULLTEXT KEY FT1 (title) +KEY ind5 (title) ) TYPE=MyISAM; +CREATE FULLTEXT INDEX ft1 ON t1(title); insert into t1 (title) values ('this is a test'); select * from t1 where match title against ('test' in boolean mode); id title diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 40ac7f905c7..d06e2dce0a1 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -135,10 +135,10 @@ CREATE TABLE t1 ( id int(11) auto_increment, title varchar(100) default '', PRIMARY KEY (id), - KEY ind5 (title), - FULLTEXT KEY FT1 (title) + KEY ind5 (title) ) TYPE=MyISAM; +CREATE FULLTEXT INDEX ft1 ON t1(title); insert into t1 (title) values ('this is a test'); select * from t1 where match title against ('test' in boolean mode); update t1 set title='this is A test' where id=1; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 91bd5a77d27..175fcc905ab 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1498,7 +1498,9 @@ keys_or_index: opt_unique_or_fulltext: /* empty */ { $$= Key::MULTIPLE; } | UNIQUE_SYM { $$= Key::UNIQUE; } - | SPATIAL_SYM { $$= Key::SPATIAL; }; + | FULLTEXT_SYM { $$= Key::FULLTEXT;} + | SPATIAL_SYM { $$= Key::SPATIAL; } + ; key_alg: /* empty */ { $$= HA_KEY_ALG_UNDEF; } From 0e7bd4425bd3b5103c99dc244ff5e13a1b383472 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jun 2003 01:13:24 +0300 Subject: [PATCH 359/399] Add missing defines --- sql/client_settings.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/client_settings.h b/sql/client_settings.h index 16e11c4eb64..efae3f18a8b 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -26,6 +26,8 @@ #define reset_sigpipe(mysql) #define read_user_name(A) {} #define mysql_rpl_query_type(A,B) MYSQL_RPL_ADMIN +#define mysql_master_send_query(A, B, C) 1 +#define mysql_slave_send_query(A, B, C) 1 #define mysql_rpl_probe(mysql) 0 #undef HAVE_SMEM #undef _CUSTOMCONFIG_ From 4cc0cd7b0da21c41f68985b43f9d6736ff629e42 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jun 2003 10:32:49 +0200 Subject: [PATCH 360/399] - changed "password" to "Password" as suggested by Paul DuBois to be consistent with the other column names in the table. --- scripts/mysql_fix_privilege_tables.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 3466e3cf799..43dc6d89481 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -4,7 +4,7 @@ ALTER TABLE host type=MyISAM; ALTER TABLE func type=MyISAM; ALTER TABLE columns_priv type=MyISAM; ALTER TABLE tables_priv type=MyISAM; -ALTER TABLE user change password password char(45) not null; +ALTER TABLE user change Password Password char(45) not null; ALTER TABLE user add File_priv enum('N','Y') NOT NULL; CREATE TABLE IF NOT EXISTS func ( name char(64) DEFAULT '' NOT NULL, From a4792eefad19e4f70471952afedef2221fbfbd64 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jun 2003 18:10:35 +0500 Subject: [PATCH 361/399] The default collation for cp1251 has been changed to general_ci --- sql/share/charsets/Index.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 6e091066654..c5a2ae5dfb6 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -208,7 +208,7 @@ To make maintaining easier please: windows-1251 ms-cyr ms-cyrillic - + Belarusian Bulgarian Macedonian @@ -219,7 +219,7 @@ To make maintaining easier please: - + Belarusian Bulgarian Macedonian From 740024005f141f3ef77e8364e32808b3652e757c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jun 2003 12:22:57 -0700 Subject: [PATCH 362/399] Added new HOWTO doc 'INSTALL-WIN-SOURCE' on building 'mysql clients and server' on WINDOWS from BitKeeper as well as from distributed source archive scripts/make_win_src_distribution.sh: Fix for INSTALL-WIN-SOURCE --- INSTALL-WIN-SOURCE | 192 +++++++++++++++++++++++++++ scripts/make_win_src_distribution.sh | 2 +- 2 files changed, 193 insertions(+), 1 deletion(-) create mode 100755 INSTALL-WIN-SOURCE diff --git a/INSTALL-WIN-SOURCE b/INSTALL-WIN-SOURCE new file mode 100755 index 00000000000..fb8cc185161 --- /dev/null +++ b/INSTALL-WIN-SOURCE @@ -0,0 +1,192 @@ +######################################################### +# # +# HOWTO : INSTALL MySQL FROM SOURCE # +# WINDOWS PORT # +# # +# COpyright (C) MySQL AB 1995-2003 # +######################################################### + +This is a simple 'HOWTO' document describing howto build +MySQL 4.1 and above version binaries for Windows from +'BitKeeper' tree as well as from normal source archive. + +--------------------------------------------------------- +NOTE +--------------------------------------------------------- + +This is strictly for users who wants to test the MySQL from +the latest source from BitKeeper branch on Windows and for +internal MySQL developers. + +Other wise better always strict to MySQL binary distributions +which is built specifically for optmistic performance, +available from: + +http://www.mysql.com/downloads/ + +-------------------------------------------------------- +TABLE OF CONTENTS +-------------------------------------------------------- +1. REQUIREMENTS +2. OBTAINING THE WINDOWS SOURCE ARCHIVE +3. CREATING SOURCE PACKAGE FROM 'BitKeeper' TREE. +4. BUILDING 'mysql server and clients' FROM VC++ WORKSPACE +5. BUILDING FROM 'nmake' MAKEFILES +6. STARTING AND CONFIGURING THE SERVER FOR FISRT TIME +7. TESTING THE CONNECTION +8. SPECIAL NOTES AND CONSIDERATIONS + +------------------------------------------------------- +1. REQUIREMENTS +------------------------------------------------------- + +To build MySQL on Windows from its bitkeeper source, you need +the following compilers and/or tools installed on your Windows +system: + + - Microsoft Visual C++ 6.0 and above + - MySQL Source package + (http://www.mysql.com/downloads) + - ~45 MB disk space + - 64 MB RAM + +In case from BitKeeper tree: + + - BitKeeper 3.0 (http://www.bitkeeper.com) + - Any working and fully built *UNIX* BK tree + +------------------------------------------------------- +2. OBTAINING WINDOWS SOURCE ARCHIVE +------------------------------------------------------- + +There are two ways you can get the Windows source package for +MySQL 4.1 and above versions: + + I. MySQL distributed source package for the perticular version, + which can be obtainied from: + http://www.mysql.com/downloads + + II. Source package archive From the latest Development + 'BitKeeper' tree. + +In case if you are using the OPTION 'I', then you can skip the +next section and go directly to 'BUILDING FROM VC++ WORKSPACE'. + +------------------------------------------------------- +3. CREATING SOURCE PACKAGE FROM 'BitKeeper' TREE +------------------------------------------------------- + +To build the latest Windows source package, Please follow the +following instructions from any of your '*UNIX*' operating +systems (preferably Linux): + +- Get the latest BK clone of MySQL 4.1 (or above, as desired) + and build the source. For more information how to do this, + follow the instructions from: + http://www.mysql.com/doc/en/Installing_source_tree.html + +- Make sure the build process went through. + +- Now run the following script from the mysql installed + root directory, which creates the windows source package: + + ./scripts/make_win_src_distribution + + You can even supply different options to this script based + on your needs. It takes: + + ./scripts/make_win_src_distribution --help + MySQL utility script to create a Windows src package, and it takes + the following arguments: + + --debug Debug, without creating the package + --tmp Specify the temporary location + --silent Do not list verbosely files processed + --tar Create tar.gz package instead of .zip + --help Show this help message + + By default it creates the zipped archive with the name: + mysql-$version-win-src.zip + + - Copy or upload this created windows source package to + your windows directory. + +--------------------------------------------------------- +4. BUILDING 'mysql server & clients' from VC++ WORKSPACE +--------------------------------------------------------- + +NOTE: MySQL 4.1 and above VC++ workspace files are compatible + with Microsoft Visual Studio 6.0 and above(7.0/.NET) + editions and tested by MySQL folks before each + release. + +Unpack the Windows source zipped archive to a folder and open +mysql.dsw from your top level directory. + +If you want to build both release and debug versions, then +select 'build' -> 'buildall' option or in case to build only +'release' or 'debug' versions, then select all appropriate +workspaces from 'custom build' option. + +The simplest solution to build basic clients and core server +is to set your current active workspace as 'mysqld' release +or debug version, and just hit 'build' or 'F7', which creates +necessary client binaries in 'client_release' or 'client_debug' +and the libraries are placed in 'lib_release' and 'lib_debug' +for release and debug versions respectively. + +Now, you are all up with the things. If you get any compiler +errors, please cross check and send the compiler output to +win32@lists.mysql.com for further assistance. + +--------------------------------------------------------- +5. BUILDING FROM 'nmake' MAKEFILESS +--------------------------------------------------------- +TODO from MySQL PIEFU team. + +--------------------------------------------------------- +6. STARTING THE MYSQL SERVER FIRST TIME +--------------------------------------------------------- + +First ensure to set or copy my.ini or my.cnf file to your +'data' directory that exists in the top-level directory or +point to existing 'data' directory. + +Now, start your server from 'client_release' or 'client_debug' +sub-directories by following the instructions from: + +http://www.mysql.com/doc/en/Windows_installation.html + +Thats all !!! See, its as simple as building 'mysql' on any +other platforms !!! + +--------------------------------------------------------- +7. TESTING THE CONNECTION +--------------------------------------------------------- + +Once the server is running in standalone or as a service +based on your configuration, try to connect to it from +'mysql' command line SQL interactive utility that exists +from your 'client_release' or 'client_debug' directory. + +--------------------------------------------------------- +8. SPECIAL NOTES AND CONSIDERATIONS +--------------------------------------------------------- + +- MySQL doesnot advice to use 'mysql' server built by + yourself from sources, instead stick to binaries shipped + by MySQL on the production environment. + +- If you find something is not working as expected, or + some improvements to the current one can be made, then + please send a mail to 'win32@lists.mysql.com'. + +Thanks +MySQL Team + + + + + + + diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index f76fe02e2bd..6c119e2f80e 100755 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -249,7 +249,7 @@ touch $BASE/innobase/ib_config.h cd $SOURCE for i in COPYING ChangeLog README \ INSTALL-SOURCE INSTALL-WIN \ - INSTALL-SOURCE-WIN \ + INSTALL-WIN-SOURCE Docs/manual_toc.html Docs/manual.html \ Docs/mysqld_error.txt Docs/INSTALL-BINARY From be551c2c4f45b1b951d7238bda6750cdce75fb16 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jun 2003 14:29:20 -0700 Subject: [PATCH 363/399] Fix for --dirname and --suffix (missed ones) scripts/make_win_src_distribution.sh: Fix for --dirname and --suffix (missed ones) --- scripts/make_win_src_distribution.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index 6c119e2f80e..1be301ee92a 100755 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -59,6 +59,8 @@ show_usage() echo "" echo " --debug Debug, without creating the package" echo " --tmp Specify the temporary location" + echo " --suffix Suffix name for the package" + echo " --dirname Directory name to copy files (intermediate)" echo " --silent Do not list verbosely files processed" echo " --tar Create tar.gz package instead of .zip" echo " --help Show this help message" From dbab44370bb755cb2eb02016f72869065b89a3e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jun 2003 17:47:23 -0500 Subject: [PATCH 364/399] INSTALL-WIN-SOURCE: Initial cleanup edits. INSTALL-WIN-SOURCE: Initial cleanup edits. --- INSTALL-WIN-SOURCE | 189 +++++++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 85 deletions(-) diff --git a/INSTALL-WIN-SOURCE b/INSTALL-WIN-SOURCE index fb8cc185161..ee3e35a91c8 100755 --- a/INSTALL-WIN-SOURCE +++ b/INSTALL-WIN-SOURCE @@ -3,36 +3,39 @@ # HOWTO : INSTALL MySQL FROM SOURCE # # WINDOWS PORT # # # -# COpyright (C) MySQL AB 1995-2003 # +# Copyright (C) MySQL AB 1995-2003 # ######################################################### -This is a simple 'HOWTO' document describing howto build -MySQL 4.1 and above version binaries for Windows from -'BitKeeper' tree as well as from normal source archive. +This is a simple 'HOWTO' document describing how to +build MySQL binaries for versions 4.1 and above on +Windows. Instructions are provided for building binaries +from a standard source distribution or from the BitKeeper +tree that contains the latest developer source. --------------------------------------------------------- NOTE --------------------------------------------------------- -This is strictly for users who wants to test the MySQL from -the latest source from BitKeeper branch on Windows and for -internal MySQL developers. - -Other wise better always strict to MySQL binary distributions -which is built specifically for optmistic performance, -available from: +Normally, it is best to use precompiled binary distributions +of MySQL that are built specifically for optimal performance +on Windows by MySQL AB. Binary distributions are available +from: http://www.mysql.com/downloads/ +The instructions in this document are strictly for users +who want to test MySQL on Windows from the latest source or +from the BitKeeper tree, and for internal MySQL developers. + -------------------------------------------------------- TABLE OF CONTENTS -------------------------------------------------------- 1. REQUIREMENTS -2. OBTAINING THE WINDOWS SOURCE ARCHIVE -3. CREATING SOURCE PACKAGE FROM 'BitKeeper' TREE. +2. OBTAINING A WINDOWS SOURCE DISTRIBUTION +3. CREATING A SOURCE PACKAGE FROM THE 'BitKeeper' TREE 4. BUILDING 'mysql server and clients' FROM VC++ WORKSPACE 5. BUILDING FROM 'nmake' MAKEFILES -6. STARTING AND CONFIGURING THE SERVER FOR FISRT TIME +6. STARTING THE MYSQL SERVER FOR THE FIRST TIME 7. TESTING THE CONNECTION 8. SPECIAL NOTES AND CONSIDERATIONS @@ -40,79 +43,100 @@ TABLE OF CONTENTS 1. REQUIREMENTS ------------------------------------------------------- -To build MySQL on Windows from its bitkeeper source, you need -the following compilers and/or tools installed on your Windows +To build MySQL on Windows from source, you need the +following compiler and resources available on your Windows system: - Microsoft Visual C++ 6.0 and above - - MySQL Source package - (http://www.mysql.com/downloads) - ~45 MB disk space - 64 MB RAM -In case from BitKeeper tree: +You'll also need a MySQL source distribution. You can +get the source for released versions of MySQL from: - - BitKeeper 3.0 (http://www.bitkeeper.com) - - Any working and fully built *UNIX* BK tree +http://www.mysql.com/downloads/ + +Alternatively, you can package a source distribution +yourself from the latest BitKeeper developer source +tree. If you plan to do this, you must create the +package on a Unix system and then transfer it to your +Windows system. (The reason for this is that the initial +configuration scripts and some of the build steps work +only on Unix.) The BitKeeper approach thus requires: + + - A system running Unix, or a Unix-like system such as Linux + - BitKeeper 3.0 installed on that system (you can obtain + BitKeeper from http://www.bitkeeper.com) ------------------------------------------------------- -2. OBTAINING WINDOWS SOURCE ARCHIVE +2. OBTAINING A WINDOWS SOURCE DISTRIBUTION ------------------------------------------------------- -There are two ways you can get the Windows source package for -MySQL 4.1 and above versions: +There are two ways you can get a Windows source distribution for +MySQL version 4.1 and above: - I. MySQL distributed source package for the perticular version, - which can be obtainied from: - http://www.mysql.com/downloads + I. Obtain a MySQL AB-distributed source distribution for the + particular version of MySQL in which you are interested. + Prepackaged source distributions are available for released + versions of MySQL and can be obtained from: + + http://www.mysql.com/downloads/ - II. Source package archive From the latest Development - 'BitKeeper' tree. + II. Create a source package yourself from the latest development + 'BitKeeper' source tree. + +If you are using the first option, you can skip the next +section and go directly to 'BUILDING FROM VC++ WORKSPACE'. -In case if you are using the OPTION 'I', then you can skip the -next section and go directly to 'BUILDING FROM VC++ WORKSPACE'. - ------------------------------------------------------- -3. CREATING SOURCE PACKAGE FROM 'BitKeeper' TREE +3. CREATING A SOURCE PACKAGE FROM THE 'BitKeeper' TREE ------------------------------------------------------- To build the latest Windows source package, Please follow the following instructions from any of your '*UNIX*' operating systems (preferably Linux): -- Get the latest BK clone of MySQL 4.1 (or above, as desired) - and build the source. For more information how to do this, - follow the instructions from: +- Clone the BitKeeper source tree for MySQL (version 4.1 + or above, as desired). For more information how to clone + the BitKeeper source tree, follow the instructions at: + http://www.mysql.com/doc/en/Installing_source_tree.html -- Make sure the build process went through. +- Build the distribution so that you have a server binary to + work with. One way to do this is to run the following + command in the top-level directory of your source tree: -- Now run the following script from the mysql installed - root directory, which creates the windows source package: + ./BUILD/compile-pentium-max + +- After making sure that build process completed successfully, + run the following utility script from top-level directory + of your source tree: ./scripts/make_win_src_distribution - You can even supply different options to this script based - on your needs. It takes: - - ./scripts/make_win_src_distribution --help - MySQL utility script to create a Windows src package, and it takes - the following arguments: + This script creates the Windows source package. You can + supply different options to the script based on your needs. + It accepts: the following options: --debug Debug, without creating the package --tmp Specify the temporary location + --suffix Suffix name for the package + --dirname Directory name to copy files (intermediate) --silent Do not list verbosely files processed --tar Create tar.gz package instead of .zip --help Show this help message - By default it creates the zipped archive with the name: - mysql-$version-win-src.zip + By default, make_win_src_distribution creates a zipped + archive with the name mysql-$version-win-src.zip, where + $version is the version of the MySQL source tree you + cloned. - - Copy or upload this created windows source package to - your windows directory. + - Copy or upload to your Windows machine the Windows source + package that you have just created, and compile it using + the instructions in the next section. --------------------------------------------------------- -4. BUILDING 'mysql server & clients' from VC++ WORKSPACE +4. BUILDING 'mysql server & clients' FROM VC++ WORKSPACE --------------------------------------------------------- NOTE: MySQL 4.1 and above VC++ workspace files are compatible @@ -121,72 +145,67 @@ NOTE: MySQL 4.1 and above VC++ workspace files are compatible release. Unpack the Windows source zipped archive to a folder and open -mysql.dsw from your top level directory. +mysql.dsw from your top-level directory. -If you want to build both release and debug versions, then -select 'build' -> 'buildall' option or in case to build only -'release' or 'debug' versions, then select all appropriate -workspaces from 'custom build' option. +If you want to build both release and debug versions, then +select 'build' -> 'buildall' option. To build only 'release' +or 'debug' versions, then select all appropriate workspaces +from the 'build' -> 'batch build' option. -The simplest solution to build basic clients and core server -is to set your current active workspace as 'mysqld' release -or debug version, and just hit 'build' or 'F7', which creates -necessary client binaries in 'client_release' or 'client_debug' -and the libraries are placed in 'lib_release' and 'lib_debug' -for release and debug versions respectively. +The simplest solution to build basic clients and core +server is to set your current active workspace as 'mysqld' +release or debug version, and just hit 'build' or 'F7', which +creates necessary client binaries in the 'client_release' or +'client_debug' directories. The libraries are placed in the +'lib_release' and 'lib_debug' directories for release and +debug versions, respectively. -Now, you are all up with the things. If you get any compiler +Now you have built the distribution. If you get any compiler errors, please cross check and send the compiler output to win32@lists.mysql.com for further assistance. --------------------------------------------------------- -5. BUILDING FROM 'nmake' MAKEFILESS +5. BUILDING FROM 'nmake' MAKEFILES --------------------------------------------------------- TODO from MySQL PIEFU team. --------------------------------------------------------- -6. STARTING THE MYSQL SERVER FIRST TIME +6. STARTING THE MYSQL SERVER FOR THE FIRST TIME --------------------------------------------------------- First ensure to set or copy my.ini or my.cnf file to your 'data' directory that exists in the top-level directory or point to existing 'data' directory. -Now, start your server from 'client_release' or 'client_debug' -sub-directories by following the instructions from: +Now, start your server from the 'client_release' or +'client_debug' directory (depending on which server you +want to use), by following the instructions from: http://www.mysql.com/doc/en/Windows_installation.html -Thats all !!! See, its as simple as building 'mysql' on any -other platforms !!! +That's all!!! See, it's as simple to build MySQL on Windows +as on any other platform!!! --------------------------------------------------------- 7. TESTING THE CONNECTION --------------------------------------------------------- -Once the server is running in standalone or as a service -based on your configuration, try to connect to it from -'mysql' command line SQL interactive utility that exists -from your 'client_release' or 'client_debug' directory. +Once the server is running in standalone fashion or as a +service based on your configuration, try to connect to it +from the 'mysql' command line SQL interactive utility that +exists in your 'client_release' or 'client_debug' directory. --------------------------------------------------------- 8. SPECIAL NOTES AND CONSIDERATIONS --------------------------------------------------------- -- MySQL doesnot advice to use 'mysql' server built by - yourself from sources, instead stick to binaries shipped - by MySQL on the production environment. +- For production use, MySQL AB does not advise using a MySQL + server built by yourself from source. Instead, stick to + binaries shipped by MySQL AB. -- If you find something is not working as expected, or - some improvements to the current one can be made, then - please send a mail to 'win32@lists.mysql.com'. +- If you find something not working as expected, or you have + suggestions about ways to improve the current build process + on Windows, please email to 'win32@lists.mysql.com'. Thanks MySQL Team - - - - - - - From a33ccd9e2f21ab7986a80651b7c3b905550cdba4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 14:12:50 +0200 Subject: [PATCH 365/399] triggers magic enforce REAL_EMAIL BitKeeper/deleted/.del-post-incoming~9f2168f531f09f3b: Delete: BitKeeper/triggers/post-incoming BitKeeper/deleted/.del-post-outgoing~1dd3d8f0f6e8f3cd: Delete: BitKeeper/triggers/post-outgoing BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + BitKeeper/triggers/post-incoming | 3 --- BitKeeper/triggers/post-outgoing | 3 --- BitKeeper/triggers/pre-commit | 12 ++++++++++++ 4 files changed, 13 insertions(+), 6 deletions(-) delete mode 100755 BitKeeper/triggers/post-incoming delete mode 100755 BitKeeper/triggers/post-outgoing create mode 100755 BitKeeper/triggers/pre-commit diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 806eac52759..0b6f4a222a0 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -97,6 +97,7 @@ sasha@mysql.sashanet.com serg@build.mysql2.com serg@serg.mylan serg@serg.mysql.com +serg@sergbook.mylan serg@sergbook.mysql.com sinisa@rhols221.adsl.netsonic.fi tfr@beta.frontier86.ee diff --git a/BitKeeper/triggers/post-incoming b/BitKeeper/triggers/post-incoming deleted file mode 100755 index f1ea2255de9..00000000000 --- a/BitKeeper/triggers/post-incoming +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/sh - -echo "Test: post-incoming works" diff --git a/BitKeeper/triggers/post-outgoing b/BitKeeper/triggers/post-outgoing deleted file mode 100755 index 3fc2cdbad67..00000000000 --- a/BitKeeper/triggers/post-outgoing +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/sh - -echo "Test: post-outgoing works" diff --git a/BitKeeper/triggers/pre-commit b/BitKeeper/triggers/pre-commit new file mode 100755 index 00000000000..2293dc55e2a --- /dev/null +++ b/BitKeeper/triggers/pre-commit @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ "$REAL_EMAIL" = "" ] +then + echo "Error: you must set REAL_EMAIL in your profile" + echo "e.g.: export REAL_EMAIL='Joe Dow '" + echo "" + echo "Commit FAILED!" + echo "Set REAL_EMAIL and retry." + exit 1 +fi + From 621215cd051b3c404ce68efe8642413cf8103a0e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 12:10:40 -0500 Subject: [PATCH 366/399] INSTALL-WIN-SOURCE: More edits to INSTALL-WIN-SOURCE. INSTALL-WIN-SOURCE: More edits to INSTALL-WIN-SOURCE. --- INSTALL-WIN-SOURCE | 116 ++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/INSTALL-WIN-SOURCE b/INSTALL-WIN-SOURCE index ee3e35a91c8..bce093633f5 100755 --- a/INSTALL-WIN-SOURCE +++ b/INSTALL-WIN-SOURCE @@ -10,7 +10,7 @@ This is a simple 'HOWTO' document describing how to build MySQL binaries for versions 4.1 and above on Windows. Instructions are provided for building binaries from a standard source distribution or from the BitKeeper -tree that contains the latest developer source. +tree that contains the latest development source. --------------------------------------------------------- NOTE @@ -51,29 +51,15 @@ system: - ~45 MB disk space - 64 MB RAM -You'll also need a MySQL source distribution. You can -get the source for released versions of MySQL from: - -http://www.mysql.com/downloads/ - -Alternatively, you can package a source distribution -yourself from the latest BitKeeper developer source -tree. If you plan to do this, you must create the -package on a Unix system and then transfer it to your -Windows system. (The reason for this is that the initial -configuration scripts and some of the build steps work -only on Unix.) The BitKeeper approach thus requires: - - - A system running Unix, or a Unix-like system such as Linux - - BitKeeper 3.0 installed on that system (you can obtain - BitKeeper from http://www.bitkeeper.com) +You'll also need a MySQL source distribution, which you +can obtain as described in section 2. ------------------------------------------------------- 2. OBTAINING A WINDOWS SOURCE DISTRIBUTION ------------------------------------------------------- -There are two ways you can get a Windows source distribution for -MySQL version 4.1 and above: +There are two ways you can get a Windows source distribution +for MySQL version 4.1 and above: I. Obtain a MySQL AB-distributed source distribution for the particular version of MySQL in which you are interested. @@ -82,41 +68,54 @@ MySQL version 4.1 and above: http://www.mysql.com/downloads/ - II. Create a source package yourself from the latest development - 'BitKeeper' source tree. + II. Alternatively, you can package a source distribution + yourself from the latest BitKeeper developer source + tree. If you plan to do this, you must create the + package on a Unix system and then transfer it to your + Windows system. (The reason for this is that some of the + configuration and build steps require tools that work only + on Unix.) The BitKeeper approach thus requires: + + - A system running Unix, or a Unix-like system such as Linux + - BitKeeper 3.0 installed on that system (you can obtain + BitKeeper from http://www.bitkeeper.com) If you are using the first option, you can skip the next -section and go directly to 'BUILDING FROM VC++ WORKSPACE'. +section and go directly to "BUILDING 'mysql server & clients' +FROM VC++ WORKSPACE" ------------------------------------------------------- 3. CREATING A SOURCE PACKAGE FROM THE 'BitKeeper' TREE ------------------------------------------------------- -To build the latest Windows source package, Please follow the -following instructions from any of your '*UNIX*' operating -systems (preferably Linux): +To build the latest Windows source package from the current +BitKeeper source tree, use the following instructions. Please +note that this procedure must be performed on a system +running a Unix or Unix-like operating system. (The procedure +is know to work well on Linux, for example. - Clone the BitKeeper source tree for MySQL (version 4.1 or above, as desired). For more information how to clone - the BitKeeper source tree, follow the instructions at: + the source tree, see the instructions at: http://www.mysql.com/doc/en/Installing_source_tree.html -- Build the distribution so that you have a server binary to - work with. One way to do this is to run the following - command in the top-level directory of your source tree: +- Configure and build the distribution so that you have a + server binary to work with. One way to do this is to run + the following command in the top-level directory of your + source tree: ./BUILD/compile-pentium-max -- After making sure that build process completed successfully, +- After making sure that the build process completed successfully, run the following utility script from top-level directory of your source tree: ./scripts/make_win_src_distribution - This script creates the Windows source package. You can - supply different options to the script based on your needs. - It accepts: the following options: + This script creates a Windows source package, to be used on + your Windows system. You can supply different options to the + script based on your needs. It accepts the following options: --debug Debug, without creating the package --tmp Specify the temporary location @@ -128,15 +127,14 @@ systems (preferably Linux): By default, make_win_src_distribution creates a zipped archive with the name mysql-$version-win-src.zip, where - $version is the version of the MySQL source tree you - cloned. + $version represents the version of your MySQL source tree. - Copy or upload to your Windows machine the Windows source - package that you have just created, and compile it using + package that you have just created. To compile it, use the instructions in the next section. --------------------------------------------------------- -4. BUILDING 'mysql server & clients' FROM VC++ WORKSPACE +4. BUILDING 'mysql server & clients' FROM VC++ WORKSPACE --------------------------------------------------------- NOTE: MySQL 4.1 and above VC++ workspace files are compatible @@ -148,20 +146,20 @@ Unpack the Windows source zipped archive to a folder and open mysql.dsw from your top-level directory. If you want to build both release and debug versions, then -select 'build' -> 'buildall' option. To build only 'release' -or 'debug' versions, then select all appropriate workspaces -from the 'build' -> 'batch build' option. +select 'build' -> 'buildall' option. To build only release +or debug versions, select all appropriate workspaces from +the 'build' -> 'batch build' option. -The simplest solution to build basic clients and core +The simplest solution to building the basic clients and core server is to set your current active workspace as 'mysqld' release or debug version, and just hit 'build' or 'F7', which -creates necessary client binaries in the 'client_release' or -'client_debug' directories. The libraries are placed in the +creates the necessary client binaries in the 'client_release' +or 'client_debug' directories. The libraries are placed in the 'lib_release' and 'lib_debug' directories for release and debug versions, respectively. Now you have built the distribution. If you get any compiler -errors, please cross check and send the compiler output to +errors, please cross check and email the compiler output to win32@lists.mysql.com for further assistance. --------------------------------------------------------- @@ -173,16 +171,28 @@ TODO from MySQL PIEFU team. 6. STARTING THE MYSQL SERVER FOR THE FIRST TIME --------------------------------------------------------- -First ensure to set or copy my.ini or my.cnf file to your -'data' directory that exists in the top-level directory or -point to existing 'data' directory. +The server built using the preceding instructions will +expect that the MySQL base directory and data directory +are C:\mysql and C:\mysql\data by default. If you want to +test your server using the source root directory and its +data directory as the base directory and data directory, +you will need to tell the server their pathnames. You can +either do this on the command line with the --basedir +and --data-dir options, or place appropriate options in +an option file (C:\my.cnf or the my.ini file in your +Windows directory). If you have an existing data directory +elsewhere that you want to use, you can specify its pathname +instead. -Now, start your server from the 'client_release' or -'client_debug' directory (depending on which server you -want to use), by following the instructions from: +Start your server from the 'client_release' or 'client_debug' +directory (depending on which server you want to use). The +general instructions are given here: http://www.mysql.com/doc/en/Windows_installation.html +You'll have to adapt the instructions appropriately if you +want to use a different base directory and/or data directory. + That's all!!! See, it's as simple to build MySQL on Windows as on any other platform!!! @@ -200,12 +210,12 @@ exists in your 'client_release' or 'client_debug' directory. --------------------------------------------------------- - For production use, MySQL AB does not advise using a MySQL - server built by yourself from source. Instead, stick to - binaries shipped by MySQL AB. + server built by yourself from source. It is preferable to + stick to using binaries shipped by MySQL AB. - If you find something not working as expected, or you have suggestions about ways to improve the current build process - on Windows, please email to 'win32@lists.mysql.com'. + on Windows, please email to win32@lists.mysql.com. Thanks MySQL Team From 76a06a4742764e08409251590145891cbbc9d4d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jun 2003 23:13:29 +0200 Subject: [PATCH 367/399] - added sql-common subdirectory and sql_common.h to source distribution Makefile.am: - added sql-common directory to distribution configure.in: - minor fixes - added sql-common/Makefile to AC_OUTPUT include/Makefile.am: - added sql_common.h to distribution --- Makefile.am | 2 +- configure.in | 8 +++++--- include/Makefile.am | 2 +- sql-common/Makefile.am | 21 +++++++++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 sql-common/Makefile.am diff --git a/Makefile.am b/Makefile.am index 1fcf498a84b..ffebf891795 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS = foreign EXTRA_DIST = INSTALL-SOURCE README \ COPYING COPYING.LIB SUBDIRS = . include @docs_dirs@ \ - @readline_topdir@ \ + @readline_topdir@ sql-common \ @thread_dirs@ pstack @sql_client_dirs@ \ @sql_server_dirs@ scripts man tests \ BUILD @netware_dir@ os2 @libmysqld_dirs@ \ diff --git a/configure.in b/configure.in index bddeeb6c989..63b33e391b2 100644 --- a/configure.in +++ b/configure.in @@ -2176,8 +2176,8 @@ AC_ARG_WITH(libedit, [ with_libedit=undefined ] ) -compile_readline= no -compile_libedit= no +compile_readline="no" +compile_libedit="no" if [test "$with_libedit" = "yes"] && [test "$with_readline" = "yes"] then @@ -2820,6 +2820,7 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile dnl libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile dnl libmysql/Makefile client/Makefile dnl pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl + sql-common/Makefile dnl merge/Makefile dbug/Makefile scripts/Makefile dnl include/Makefile sql-bench/Makefile tools/Makefile dnl tests/Makefile Docs/Makefile support-files/Makefile dnl @@ -2840,6 +2841,7 @@ echo "Remember to check the platform specific part of the reference manual for" echo "hints about installing MySQL on your platform. Also have a look at the" echo "files in the Docs directory." echo -# The following text is checked in ./Do-compile to se that the configure ends. +# The following text is checked in ./Do-compile to verify that configure +# ended sucessfully - don't remove it. echo "Thank you for choosing MySQL!" echo diff --git a/include/Makefile.am b/include/Makefile.am index 3a197c310aa..81966233a32 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -21,7 +21,7 @@ pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \ my_semaphore.h my_pthread.h my_no_pthread.h raid.h \ errmsg.h my_global.h my_net.h my_alloc.h \ my_getopt.h sslopt-longopts.h my_dir.h typelib.h \ - sslopt-vars.h sslopt-case.h $(BUILT_SOURCES) + sslopt-vars.h sslopt-case.h sql_common.h $(BUILT_SOURCES) noinst_HEADERS = config-win.h config-os2.h config-netware.h \ nisam.h heap.h merge.h my_bitmap.h\ myisam.h myisampack.h myisammrg.h ft_global.h\ diff --git a/sql-common/Makefile.am b/sql-common/Makefile.am new file mode 100644 index 00000000000..1f397c0ea87 --- /dev/null +++ b/sql-common/Makefile.am @@ -0,0 +1,21 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 + +## Process this file with automake to create Makefile.in +EXTRA_DIST = client.c pack.c + +# Don't update the files from bitkeeper +%::SCCS/s.% From 59e1e7b215e589325fcb101f7d11c8a402ba72c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 11:36:44 +0500 Subject: [PATCH 368/399] These functions now return a result of proper collation: BIN OCT CONV HEX CHAR FORMAT REPLACE --- mysql-test/r/func_str.result | 41 ++++++++++++++++++++++++++++++++++-- mysql-test/t/func_str.test | 17 +++++++++++++-- sql/item.cc | 2 +- sql/item_strfunc.cc | 15 +++++++++++++ sql/item_strfunc.h | 19 ++++++++++++++--- 5 files changed, 86 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index ffb7f2cd911..302d9d7374b 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -249,6 +249,24 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf'); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); 1 DROP TABLE t1; +select collation(bin(130)), coercibility(bin(130)); +collation(bin(130)) coercibility(bin(130)) +latin1_swedish_ci 3 +select collation(oct(130)), coercibility(oct(130)); +collation(oct(130)) coercibility(oct(130)) +latin1_swedish_ci 3 +select collation(conv(130,16,10)), coercibility(conv(130,16,10)); +collation(conv(130,16,10)) coercibility(conv(130,16,10)) +latin1_swedish_ci 3 +select collation(hex(130)), coercibility(hex(130)); +collation(hex(130)) coercibility(hex(130)) +latin1_swedish_ci 3 +select collation(char(130)), coercibility(hex(130)); +collation(char(130)) coercibility(hex(130)) +binary 3 +select collation(format(130,10)), coercibility(format(130,10)); +collation(format(130,10)) coercibility(format(130,10)) +latin1_swedish_ci 3 select collation(lcase(_latin2'a')), coercibility(lcase(_latin2'a')); collation(lcase(_latin2'a')) coercibility(lcase(_latin2'a')) latin2_general_ci 3 @@ -306,8 +324,17 @@ latin2_general_ci 3 select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef')); collation(insert(_latin2'abcd',2,3,_latin2'ef')) coercibility(insert(_latin2'abcd',2,3,_latin2'ef')) latin2_general_ci 3 +select collation(replace(_latin2'abcd',_latin2'b',_latin2'B')), coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B')); +collation(replace(_latin2'abcd',_latin2'b',_latin2'B')) coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B')) +latin2_general_ci 3 create table t1 select +bin(130), +oct(130), +conv(130,16,10), +hex(130), +char(130), +format(130,10), left(_latin2'a',1), right(_latin2'a',1), lcase(_latin2'a'), @@ -326,11 +353,20 @@ reverse(_latin2'ab'), quote(_latin2'ab'), soundex(_latin2'ab'), substring(_latin2'ab',1), -insert(_latin2'abcd',2,3,_latin2'ef') +insert(_latin2'abcd',2,3,_latin2'ef'), +replace(_latin2'abcd',_latin2'b',_latin2'B') ; +Warnings: +Warning 1263 Data truncated for column 'format(130,10)' at row 1 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( + `bin(130)` char(64) NOT NULL default '', + `oct(130)` char(64) NOT NULL default '', + `conv(130,16,10)` char(64) NOT NULL default '', + `hex(130)` char(6) NOT NULL default '', + `char(130)` char(1) NOT NULL default '', + `format(130,10)` char(4) NOT NULL default '', `left(_latin2'a',1)` char(1) character set latin2 NOT NULL default '', `right(_latin2'a',1)` char(1) character set latin2 NOT NULL default '', `lcase(_latin2'a')` char(1) character set latin2 NOT NULL default '', @@ -349,6 +385,7 @@ t1 CREATE TABLE `t1` ( `quote(_latin2'ab')` char(6) character set latin2 NOT NULL default '', `soundex(_latin2'ab')` char(4) character set latin2 NOT NULL default '', `substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '', - `insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '' + `insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '', + `replace(_latin2'abcd',_latin2'b',_latin2'B')` char(4) character set latin2 NOT NULL default '' ) TYPE=MyISAM CHARSET=latin1 drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 93e35efa455..1d33d196bdd 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -136,6 +136,12 @@ DROP TABLE t1; # # Test collation and coercibility # +select collation(bin(130)), coercibility(bin(130)); +select collation(oct(130)), coercibility(oct(130)); +select collation(conv(130,16,10)), coercibility(conv(130,16,10)); +select collation(hex(130)), coercibility(hex(130)); +select collation(char(130)), coercibility(hex(130)); +select collation(format(130,10)), coercibility(format(130,10)); select collation(lcase(_latin2'a')), coercibility(lcase(_latin2'a')); select collation(ucase(_latin2'a')), coercibility(ucase(_latin2'a')); select collation(left(_latin2'a',1)), coercibility(left(_latin2'a',1)); @@ -155,9 +161,16 @@ select collation(quote(_latin2'ab')), coercibility(quote(_latin2'ab')); select collation(soundex(_latin2'ab')), coercibility(soundex(_latin2'ab')); select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1)); select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef')); +select collation(replace(_latin2'abcd',_latin2'b',_latin2'B')), coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B')); create table t1 select + bin(130), + oct(130), + conv(130,16,10), + hex(130), + char(130), + format(130,10), left(_latin2'a',1), right(_latin2'a',1), lcase(_latin2'a'), @@ -176,8 +189,8 @@ select quote(_latin2'ab'), soundex(_latin2'ab'), substring(_latin2'ab',1), - insert(_latin2'abcd',2,3,_latin2'ef') + insert(_latin2'abcd',2,3,_latin2'ef'), + replace(_latin2'abcd',_latin2'b',_latin2'B') ; - show create table t1; drop table t1; diff --git a/sql/item.cc b/sql/item.cc index cdd78572a0a..57efd3e7bf3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -39,7 +39,7 @@ Item::Item(): { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; - coercibility=COER_IMPLICIT; + coercibility=COER_COERCIBLE; name= 0; decimals= 0; max_length= 0; THD *thd= current_thd; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d660f7c472c..9ab20281a97 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -813,6 +813,7 @@ null: void Item_func_replace::fix_length_and_dec() { + uint i; max_length=args[0]->max_length; int diff=(int) (args[2]->max_length - args[1]->max_length); if (diff > 0 && args[1]->max_length) @@ -825,6 +826,20 @@ void Item_func_replace::fix_length_and_dec() max_length=MAX_BLOB_WIDTH; maybe_null=1; } + set_charset(args[0]->charset(), args[0]->coercibility); + + for (i=1; i<3; i++) + { + if (set_charset(charset(), coercibility, + args[i]->charset(), args[i]->coercibility)) + { + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + charset()->name,coercion_name(coercibility), + args[i]->charset()->name,coercion_name(args[i]->coercibility), + func_name()); + break; + } + } } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 26c69668b0a..6bb1c510013 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -433,6 +433,7 @@ public: String *val_str(String *); void fix_length_and_dec() { + set_charset(default_charset()); max_length=args[0]->max_length+(args[0]->max_length-args[0]->decimals)/3; } const char *func_name() const { return "format"; } @@ -444,7 +445,11 @@ class Item_func_char :public Item_str_func public: Item_func_char(List &list) :Item_str_func(list) {} String *val_str(String *); - void fix_length_and_dec() { maybe_null=0; max_length=arg_count; } + void fix_length_and_dec() + { + set_charset(default_charset()); + maybe_null=0; max_length=arg_count; + } const char *func_name() const { return "char"; } }; @@ -490,7 +495,11 @@ public: Item_func_conv(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {} const char *func_name() const { return "conv"; } String *val_str(String *); - void fix_length_and_dec() { decimals=0; max_length=64; } + void fix_length_and_dec() + { + set_charset(default_charset()); + decimals=0; max_length=64; + } }; @@ -501,7 +510,11 @@ public: Item_func_hex(Item *a) :Item_str_func(a) {} const char *func_name() const { return "hex"; } String *val_str(String *); - void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length*2; } + void fix_length_and_dec() + { + set_charset(default_charset()); + decimals=0; max_length=args[0]->max_length*2; + } }; From 36e0b1cd078bac70ae62b5df3c85c624c2a68b22 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 13:12:55 +0500 Subject: [PATCH 369/399] LPAD, RPAD, MAKE_SET and EXPORT_SET now works correctly with collations --- mysql-test/r/func_str.result | 20 +++++++++++++++ mysql-test/t/func_str.test | 8 ++++++ sql/item_strfunc.cc | 47 +++++++++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 302d9d7374b..6ee452764c2 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -285,9 +285,21 @@ latin2_general_ci 3 select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b')); collation(concat(_latin2'a',_latin2'b')) coercibility(concat(_latin2'a',_latin2'b')) latin2_general_ci 3 +select collation(lpad(_latin2'a',4,_latin2'b')), coercibility(lpad(_latin2'a',4,_latin2'b')); +collation(lpad(_latin2'a',4,_latin2'b')) coercibility(lpad(_latin2'a',4,_latin2'b')) +binary 3 +select collation(rpad(_latin2'a',4,_latin2'b')), coercibility(rpad(_latin2'a',4,_latin2'b')); +collation(rpad(_latin2'a',4,_latin2'b')) coercibility(rpad(_latin2'a',4,_latin2'b')) +latin2_general_ci 3 select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b')); collation(concat_ws(_latin2'a',_latin2'b')) coercibility(concat_ws(_latin2'a',_latin2'b')) latin2_general_ci 3 +select collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')), coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c')); +collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')) coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c')) +latin2_general_ci 3 +select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')); +collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')) coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')) +binary 3 select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a ')); collation(trim(_latin2' a ')) coercibility(trim(_latin2' a ')) latin2_general_ci 3 @@ -341,7 +353,11 @@ lcase(_latin2'a'), ucase(_latin2'a'), substring(_latin2'a',1,1), concat(_latin2'a',_latin2'b'), +lpad(_latin2'a',4,_latin2'b'), +rpad(_latin2'a',4,_latin2'b'), concat_ws(_latin2'a',_latin2'b'), +make_set(255,_latin2'a',_latin2'b',_latin2'c'), +export_set(255,_latin2'y',_latin2'n',_latin2' '), trim(_latin2' a '), ltrim(_latin2' a '), rtrim(_latin2' a '), @@ -373,7 +389,11 @@ t1 CREATE TABLE `t1` ( `ucase(_latin2'a')` char(1) character set latin2 NOT NULL default '', `substring(_latin2'a',1,1)` char(1) character set latin2 NOT NULL default '', `concat(_latin2'a',_latin2'b')` char(2) character set latin2 NOT NULL default '', + `lpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '', + `rpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '', `concat_ws(_latin2'a',_latin2'b')` char(1) character set latin2 NOT NULL default '', + `make_set(255,_latin2'a',_latin2'b',_latin2'c')` char(5) character set latin2 NOT NULL default '', + `export_set(255,_latin2'y',_latin2'n',_latin2' ')` char(127) character set latin2 NOT NULL default '', `trim(_latin2' a ')` char(3) character set latin2 NOT NULL default '', `ltrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '', `rtrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '', diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 1d33d196bdd..83d49743a4a 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -148,7 +148,11 @@ select collation(left(_latin2'a',1)), coercibility(left(_latin2'a',1)); select collation(right(_latin2'a',1)), coercibility(right(_latin2'a',1)); select collation(substring(_latin2'a',1,1)), coercibility(substring(_latin2'a',1,1)); select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b')); +select collation(lpad(_latin2'a',4,_latin2'b')), coercibility(lpad(_latin2'a',4,_latin2'b')); +select collation(rpad(_latin2'a',4,_latin2'b')), coercibility(rpad(_latin2'a',4,_latin2'b')); select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b')); +select collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')), coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c')); +select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')); select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a ')); select collation(ltrim(_latin2' a ')), coercibility(ltrim(_latin2' a ')); select collation(rtrim(_latin2' a ')), coercibility(rtrim(_latin2' a ')); @@ -177,7 +181,11 @@ select ucase(_latin2'a'), substring(_latin2'a',1,1), concat(_latin2'a',_latin2'b'), + lpad(_latin2'a',4,_latin2'b'), + rpad(_latin2'a',4,_latin2'b'), concat_ws(_latin2'a',_latin2'b'), + make_set(255,_latin2'a',_latin2'b',_latin2'c'), + export_set(255,_latin2'y',_latin2'n',_latin2' '), trim(_latin2' a '), ltrim(_latin2' a '), rtrim(_latin2' a '), diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9ab20281a97..4955c699315 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1780,8 +1780,20 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array, void Item_func_make_set::fix_length_and_dec() { max_length=arg_count-1; - for (uint i=1 ; i < arg_count ; i++) + set_charset(args[0]->charset(), args[0]->coercibility); + for (uint i=0 ; i < arg_count ; i++) + { max_length+=args[i]->max_length; + if (set_charset(charset(), coercibility, + args[i]->charset(), args[i]->coercibility)) + { + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + charset()->name,coercion_name(coercibility), + args[i]->charset()->name,coercion_name(args[i]->coercibility), + func_name()); + break; + } + } used_tables_cache|=item->used_tables(); const_item_cache&=item->const_item(); with_sum_func= with_sum_func || item->with_sum_func; @@ -1964,6 +1976,15 @@ err: void Item_func_rpad::fix_length_and_dec() { + if (set_charset(args[0]->charset(), args[0]->coercibility, + args[2]->charset(), args[2]->coercibility)) + { + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + args[0]->charset()->name,coercion_name(args[0]->coercibility), + args[2]->charset()->name,coercion_name(args[2]->coercibility), + func_name()); + } + if (args[1]->const_item()) { uint32 length= (uint32) args[1]->val_int(); @@ -2024,6 +2045,15 @@ String *Item_func_rpad::val_str(String *str) void Item_func_lpad::fix_length_and_dec() { + if (set_charset(args[0]->charset(), args[0]->coercibility, + args[2]->charset(), args[2]->coercibility)) + { + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + args[0]->charset()->name,coercion_name(args[0]->coercibility), + args[2]->charset()->name,coercion_name(args[2]->coercibility), + func_name()); + } + if (args[1]->const_item()) { uint32 length= (uint32) args[1]->val_int(); @@ -2433,9 +2463,24 @@ String* Item_func_export_set::val_str(String* str) void Item_func_export_set::fix_length_and_dec() { + uint i; uint length=max(args[1]->max_length,args[2]->max_length); uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63; + + set_charset(args[1]->charset(), args[1]->coercibility); + for (i=2 ; i < 4 && i < arg_count ; i++) + { + if (set_charset(charset(), coercibility, + args[i]->charset(), args[i]->coercibility)) + { + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + charset()->name,coercion_name(coercibility), + args[i]->charset()->name,coercion_name(args[i]->coercibility), + func_name()); + break; + } + } } String* Item_func_inet_ntoa::val_str(String* str) From 85de209e76dea343bb2e8df334ed206d9f140730 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 10:46:45 +0200 Subject: [PATCH 370/399] - added libmysql/client_settings.h to distribution libmysql/Makefile.am: - added client_settings.h to distribution --- libmysql/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 128f1c03967..0125bd2b98d 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -28,6 +28,7 @@ libmysqlclient_la_SOURCES = $(target_sources) libmysqlclient_la_LIBADD = $(target_libadd) libmysqlclient_la_LDFLAGS = $(target_ldflags) EXTRA_DIST = Makefile.shared +noinst_HEADERS = client_settings.h # This is called from the toplevel makefile link_sources: From 32ddd42736b4399ed1ac5baabfafc91d4f0b84ca Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 02:34:33 -0700 Subject: [PATCH 371/399] preload.result, preload.test: Removed non-generic info (key used blocks) preload.result, preload.test, lex.h, sql_yacc.yy: Syntax change for preload statement sql/sql_yacc.yy: Syntax change for preload statement sql/lex.h: Syntax change for preload statement mysql-test/t/preload.test: Removed non-generic info (key used blocks) mysql-test/r/preload.result: Removed non-generic info (key used blocks) --- mysql-test/r/preload.result | 87 +++++++++---------------------------- mysql-test/t/preload.test | 41 +++++++++-------- sql/lex.h | 1 - sql/sql_yacc.yy | 10 ++--- 4 files changed, 44 insertions(+), 95 deletions(-) diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result index 0afd95b6fb8..4d9293c7929 100644 --- a/mysql-test/r/preload.result +++ b/mysql-test/r/preload.result @@ -46,169 +46,122 @@ count(*) 20672 flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 select count(*) from t1 where b = 'test1'; count(*) 4181 -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 217 Key_reads 45 -Key_write_requests 0 -Key_writes 0 select count(*) from t1 where b = 'test1'; count(*) 4181 -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 434 Key_reads 45 -Key_write_requests 0 -Key_writes 0 flush tables; flush status; select @@preload_buffer_size; @@preload_buffer_size 32768 -preload t1 keys; +load index into cache t1 keys; Table Op Msg_type Msg_text test.t1 preload_keys status OK -show status like "preload_%"; +show status like "key_read%"; Variable_name Value -show status like "key_%"; -Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 select count(*) from t1 where b = 'test1'; count(*) 4181 -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 217 Key_reads 45 -Key_write_requests 0 -Key_writes 0 flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 set session preload_buffer_size=256*1024; select @@preload_buffer_size; @@preload_buffer_size 262144 -preload t1 keys ignore leaves; +load index into cache t1 keys ignore leaves; Table Op Msg_type Msg_text test.t1 preload_keys status OK -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 select count(*) from t1 where b = 'test1'; count(*) 4181 -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 217 Key_reads 45 -Key_write_requests 0 -Key_writes 0 flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 set session preload_buffer_size=1*1024; select @@preload_buffer_size; @@preload_buffer_size 1024 -preload t1 keys, t2 keys (primary,b) ignore leaves; +load index into cache t1 keys, t2 keys (primary,b) ignore leaves; Table Op Msg_type Msg_text test.t1 preload_keys status OK test.t2 preload_keys status OK -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 select count(*) from t1 where b = 'test1'; count(*) 4181 select count(*) from t2 where b = 'test1'; count(*) 2584 -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 351 Key_reads 73 -Key_write_requests 0 -Key_writes 0 flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 -preload t3 keys, t2 keys (primary,b) ; +load index into cache t3 keys, t2 keys (primary,b) ; Table Op Msg_type Msg_text test.t3 preload_keys error Table 'test.t3' doesn't exist test.t2 preload_keys status OK -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 -preload t3 keys (b), t2 keys (c) ; +load index into cache t3 keys (b), t2 keys (c) ; Table Op Msg_type Msg_text test.t3 preload_keys error Table 'test.t3' doesn't exist test.t2 preload_keys error Key column 'c' doesn't exist in table test.t2 preload_keys status Operation failed -show status like "key_%"; +show status like "key_read%"; Variable_name Value -Key_blocks_used 918 Key_read_requests 0 Key_reads 0 -Key_write_requests 0 -Key_writes 0 drop table t1, t2; diff --git a/mysql-test/t/preload.test b/mysql-test/t/preload.test index 1fd0d0a5b17..7357b42c599 100755 --- a/mysql-test/t/preload.test +++ b/mysql-test/t/preload.test @@ -54,48 +54,47 @@ select count(*) from t1; select count(*) from t2; flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; select count(*) from t1 where b = 'test1'; -show status like "key_%"; +show status like "key_read%"; select count(*) from t1 where b = 'test1'; -show status like "key_%"; +show status like "key_read%"; flush tables; flush status; select @@preload_buffer_size; -preload t1 keys; -show status like "preload_%"; -show status like "key_%"; +load index into cache t1 keys; +show status like "key_read%"; select count(*) from t1 where b = 'test1'; -show status like "key_%"; +show status like "key_read%"; flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; set session preload_buffer_size=256*1024; select @@preload_buffer_size; -preload t1 keys ignore leaves; -show status like "key_%"; +load index into cache t1 keys ignore leaves; +show status like "key_read%"; select count(*) from t1 where b = 'test1'; -show status like "key_%"; +show status like "key_read%"; flush tables; flush status; -show status like "key_%"; +show status like "key_read%"; set session preload_buffer_size=1*1024; select @@preload_buffer_size; -preload t1 keys, t2 keys (primary,b) ignore leaves; -show status like "key_%"; +load index into cache t1 keys, t2 keys (primary,b) ignore leaves; +show status like "key_read%"; select count(*) from t1 where b = 'test1'; select count(*) from t2 where b = 'test1'; -show status like "key_%"; +show status like "key_read%"; flush tables; flush status; -show status like "key_%"; -preload t3 keys, t2 keys (primary,b) ; -show status like "key_%"; +show status like "key_read%"; +load index into cache t3 keys, t2 keys (primary,b) ; +show status like "key_read%"; flush tables; flush status; -show status like "key_%"; -preload t3 keys (b), t2 keys (c) ; -show status like "key_%"; +show status like "key_read%"; +load index into cache t3 keys (b), t2 keys (c) ; +show status like "key_read%"; drop table t1, t2; diff --git a/sql/lex.h b/sql/lex.h index 0c3e58c4a50..f7c4418cb8d 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -300,7 +300,6 @@ static SYMBOL symbols[] = { { "POLYGON", SYM(POLYGON),0,0}, { "PURGE", SYM(PURGE),0,0}, { "PRECISION", SYM(PRECISION),0,0}, - { "PRELOAD", SYM(PRELOAD),0,0}, { "PREV", SYM(PREV_SYM),0,0}, { "PRIMARY", SYM(PRIMARY_SYM),0,0}, { "PROCEDURE", SYM(PROCEDURE),0,0}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0b18b7ffdc5..323fa3da6b6 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -310,7 +310,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token DUMPFILE %token PACK_KEYS_SYM %token PARTIAL -%token PRELOAD %token PRIMARY_SYM %token PRIVILEGES %token PROCESS @@ -581,7 +580,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); type int_type real_type order_dir opt_field_spec lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type - delete_option opt_temporary all_or_any opt_distinct opt_ignore_leafs + delete_option opt_temporary all_or_any opt_distinct opt_ignore_leaves %type ULONG_NUM raid_types merge_insert_types @@ -1838,7 +1837,7 @@ table_to_table: }; preload: - PRELOAD + LOAD INDEX INTO CACHE_SYM { LEX *lex=Lex; lex->sql_command=SQLCOM_PRELOAD_KEYS; @@ -1852,7 +1851,7 @@ preload_list: | preload_list ',' preload_keys; preload_keys: - table_ident preload_keys_spec opt_ignore_leafs + table_ident preload_keys_spec opt_ignore_leaves { LEX *lex=Lex; SELECT_LEX *sel= &lex->select_lex; @@ -1880,7 +1879,7 @@ preload_key_list_or_empty: | '(' key_usage_list2 ')' {} ; -opt_ignore_leafs: +opt_ignore_leaves: /* empty */ { $$= 0; } | IGNORE_SYM LEAVES { $$= TL_OPTION_IGNORE_LEAVES; } @@ -4374,7 +4373,6 @@ keyword: | PASSWORD {} | POINT_SYM {} | POLYGON {} - | PRELOAD {} | PREV_SYM {} | PROCESS {} | PROCESSLIST_SYM {} From 3162f9a6821775a2aedfec780a2563c7bccd4a8b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 12:18:04 +0200 Subject: [PATCH 372/399] - revert wrong include of zlib.h as zlib is not part of the source distribution - better use -I../zlib where appropriate (usually we use the zlib installed in the system) --- sql/item_strfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9ab20281a97..fddb761fc53 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2572,7 +2572,7 @@ null: } #ifdef HAVE_COMPRESS -#include "../zlib/zlib.h" +#include "zlib.h" String *Item_func_compress::val_str(String *str) { From d152a8ce4346a4d9e705973a60b09fbafb84f3d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 13:46:10 +0200 Subject: [PATCH 373/399] - added missing include/sql_state.h to source distribution include/Makefile.am: - added missing sql_state.h to source distribution --- include/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Makefile.am b/include/Makefile.am index 81966233a32..2ec06d71fbe 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -21,7 +21,8 @@ pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \ my_semaphore.h my_pthread.h my_no_pthread.h raid.h \ errmsg.h my_global.h my_net.h my_alloc.h \ my_getopt.h sslopt-longopts.h my_dir.h typelib.h \ - sslopt-vars.h sslopt-case.h sql_common.h $(BUILT_SOURCES) + sslopt-vars.h sslopt-case.h sql_common.h \ + sql_state.h $(BUILT_SOURCES) noinst_HEADERS = config-win.h config-os2.h config-netware.h \ nisam.h heap.h merge.h my_bitmap.h\ myisam.h myisampack.h myisammrg.h ft_global.h\ From 9b83d3e536e051274469717f1ba1e6c524b9fdc9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 16:08:11 +0300 Subject: [PATCH 374/399] after merge fix --- mysql-test/r/func_group.result | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index b09bb72f879..26ef391024e 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -611,6 +611,4 @@ count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - select Case When Count(*) < MAX_REQ Then 1 Else 0 End from t1 where t1.USR_ID = 1 group by MAX_REQ; Case When Count(*) < MAX_REQ Then 1 Else 0 End 1 - - drop table t1; From 84bf9b8adb0afafbaeb24f6e8dfc53d3820e8964 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jun 2003 12:17:23 -0400 Subject: [PATCH 375/399] Fix error msg. Bug #681 BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/nt_servc.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index c9f82de08d3..6d700cfd6c6 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -52,6 +52,7 @@ jorge@linux.jorge.mysql.com kaj@work.mysql.com lenz@kallisto.mysql.com lenz@mysql.com +miguel@hegel.(none) miguel@hegel.br miguel@hegel.local miguel@light. diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index 93bae6f444d..25fc010d9a5 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -462,7 +462,7 @@ BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType) { /* a remove operation */ if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS ))) - printf("The service doesn't exists!\n"); + printf("The service doesn't exist!\n"); else { SERVICE_STATUS ss; From 2295fcc8769c4e7184cb012e3406f21b0d3a8d13 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 14:31:47 +0500 Subject: [PATCH 376/399] Added AsWKT() alias for AsText(). Renamed as_text(). sql/item_create.cc: Renamed as_text(). sql/item_create.h: Renamed as_text(). sql/lex.h: Added AsWKT() alias for AsText(). --- sql/item_create.cc | 2 +- sql/item_create.h | 2 +- sql/lex.h | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/item_create.cc b/sql/item_create.cc index eb442424ca8..908e74ac808 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -506,7 +506,7 @@ Item *create_func_quote(Item* a) return new Item_func_quote(a); } -Item *create_func_as_text(Item *a) +Item *create_func_as_wkt(Item *a) { return new Item_func_as_text(a); } diff --git a/sql/item_create.h b/sql/item_create.h index b679c639244..4151f59a87f 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -104,7 +104,7 @@ Item *create_func_is_used_lock(Item* a); Item *create_func_quote(Item* a); Item *create_func_geometry_from_text(Item *a); -Item *create_func_as_text(Item *a); +Item *create_func_as_wkt(Item *a); Item *create_func_as_wkb(Item *a); Item *create_func_srid(Item *a); Item *create_func_startpoint(Item *a); diff --git a/sql/lex.h b/sql/lex.h index f7c4418cb8d..bb6e7a81ab4 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -433,8 +433,9 @@ static SYMBOL sql_functions[] = { { "AREA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)}, { "ASIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)}, { "ASBINARY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)}, - { "ASTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_text)}, + { "ASTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)}, { "ASWKB", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)}, + { "ASWKT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)}, { "ATAN", SYM(ATAN),0,0}, { "ATAN2", SYM(ATAN),0,0}, { "BENCHMARK", SYM(BENCHMARK_SYM),0,0}, From fd3abc83eaef975979f227c564bd11d9a76a0cb4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 14:53:37 +0500 Subject: [PATCH 377/399] Renamed xxx_as_text() and xxx__from_text(). --- sql/item_create.cc | 2 +- sql/item_geofunc.cc | 4 +- sql/item_geofunc.h | 4 +- sql/spatial.cc | 90 ++++++++++++++++++++++----------------------- sql/spatial.h | 42 ++++++++++----------- 5 files changed, 71 insertions(+), 71 deletions(-) diff --git a/sql/item_create.cc b/sql/item_create.cc index 908e74ac808..6956582a8ca 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -508,7 +508,7 @@ Item *create_func_quote(Item* a) Item *create_func_as_wkt(Item *a) { - return new Item_func_as_text(a); + return new Item_func_as_wkt(a); } Item *create_func_as_wkb(Item *a) diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 6db139fdfa6..5ac87a25e67 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -85,7 +85,7 @@ void Item_func_geometry_from_wkb::fix_length_and_dec() } -String *Item_func_as_text::val_str(String *str) +String *Item_func_as_wkt::val_str(String *str) { String arg_val; String *swkb= args[0]->val_str(&arg_val); @@ -104,7 +104,7 @@ String *Item_func_as_text::val_str(String *str) return str; } -void Item_func_as_text::fix_length_and_dec() +void Item_func_as_wkt::fix_length_and_dec() { max_length=MAX_BLOB_WIDTH; } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 21e94735f31..d86914eb6c5 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -43,10 +43,10 @@ public: void fix_length_and_dec(); }; -class Item_func_as_text: public Item_str_func +class Item_func_as_wkt: public Item_str_func { public: - Item_func_as_text(Item *a): Item_str_func(a) {} + Item_func_as_wkt(Item *a): Item_str_func(a) {} const char *func_name() const { return "astext"; } String *val_str(String *); void fix_length_and_dec(); diff --git a/sql/spatial.cc b/sql/spatial.cc index c8dfb490a39..00db94a07d6 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -5,31 +5,31 @@ /***************************** GClassInfo *******************************/ -#define IMPLEMENT_GEOM(class_name, type_id, name) \ -{ \ - (GF_InitFromText) &class_name::init_from_text, \ - (GF_GetDataAsText) &class_name::get_data_as_text, \ - (GF_GetDataSize) &class_name::get_data_size, \ - (GF_GetMBR) &class_name::get_mbr, \ - (GF_GetD) &class_name::get_x, \ - (GF_GetD) &class_name::get_y, \ - (GF_GetD) &class_name::length, \ - (GF_GetD) &class_name::area, \ - (GF_GetI) &class_name::is_closed, \ - (GF_GetUI) &class_name::num_interior_ring, \ - (GF_GetUI) &class_name::num_points, \ - (GF_GetUI) &class_name::num_geometries, \ - (GF_GetUI) &class_name::dimension, \ - (GF_GetWS) &class_name::start_point, \ - (GF_GetWS) &class_name::end_point, \ - (GF_GetWS) &class_name::exterior_ring, \ - (GF_GetWS) &class_name::centroid, \ - (GF_GetUIWS) &class_name::point_n, \ - (GF_GetUIWS) &class_name::interior_ring_n, \ - (GF_GetUIWS) &class_name::geometry_n, \ - class_name::type_id, \ - name, \ - NULL \ +#define IMPLEMENT_GEOM(class_name, type_id, name) \ +{ \ + (GF_InitFromText) &class_name::init_from_wkt, \ + (GF_GetDataAsText) &class_name::get_data_as_wkt, \ + (GF_GetDataSize) &class_name::get_data_size, \ + (GF_GetMBR) &class_name::get_mbr, \ + (GF_GetD) &class_name::get_x, \ + (GF_GetD) &class_name::get_y, \ + (GF_GetD) &class_name::length, \ + (GF_GetD) &class_name::area, \ + (GF_GetI) &class_name::is_closed, \ + (GF_GetUI) &class_name::num_interior_ring, \ + (GF_GetUI) &class_name::num_points, \ + (GF_GetUI) &class_name::num_geometries, \ + (GF_GetUI) &class_name::dimension, \ + (GF_GetWS) &class_name::start_point, \ + (GF_GetWS) &class_name::end_point, \ + (GF_GetWS) &class_name::exterior_ring, \ + (GF_GetWS) &class_name::centroid, \ + (GF_GetUIWS) &class_name::point_n, \ + (GF_GetUIWS) &class_name::interior_ring_n, \ + (GF_GetUIWS) &class_name::geometry_n, \ + class_name::type_id, \ + name, \ + NULL \ }, @@ -113,7 +113,7 @@ int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream trs->set_error_msg("'(' expected"); return -1; } - if (init_from_text(trs, wkt)) return 1; + if (init_from_wkt(trs, wkt)) return 1; if (trs->get_next_symbol() != ')') { trs->set_error_msg("')' expected"); @@ -161,7 +161,7 @@ size_t GPoint::get_data_size() const return POINT_DATA_SIZE; } -int GPoint::init_from_text(GTextReadStream *trs, String *wkb) +int GPoint::init_from_wkt(GTextReadStream *trs, String *wkb) { double x, y; if (wkb->reserve(sizeof(double)*2)) @@ -176,7 +176,7 @@ int GPoint::init_from_text(GTextReadStream *trs, String *wkb) return 0; } -int GPoint::get_data_as_text(String *txt) const +int GPoint::get_data_as_wkt(String *txt) const { double x, y; if (get_xy(&x, &y)) @@ -207,7 +207,7 @@ size_t GLineString::get_data_size() const return 4 + n_points*POINT_DATA_SIZE; } -int GLineString::init_from_text(GTextReadStream *trs, String *wkb) +int GLineString::init_from_wkt(GTextReadStream *trs, String *wkb) { uint32 n_points = 0; int np_pos = wkb->length(); @@ -220,7 +220,7 @@ int GLineString::init_from_text(GTextReadStream *trs, String *wkb) for (;;) { - if (p.init_from_text(trs, wkb)) + if (p.init_from_wkt(trs, wkb)) return 1; ++n_points; if (trs->get_next_toc_type() == GTextReadStream::comma) @@ -239,7 +239,7 @@ int GLineString::init_from_text(GTextReadStream *trs, String *wkb) return 0; } -int GLineString::get_data_as_text(String *txt) const +int GLineString::get_data_as_wkt(String *txt) const { uint32 n_points; const char *data = m_data; @@ -459,7 +459,7 @@ size_t GPolygon::get_data_size() const return data - m_data; } -int GPolygon::init_from_text(GTextReadStream *trs, String *wkb) +int GPolygon::init_from_wkt(GTextReadStream *trs, String *wkb) { uint32 n_linear_rings = 0; int lr_pos = wkb->length(); @@ -478,7 +478,7 @@ int GPolygon::init_from_text(GTextReadStream *trs, String *wkb) trs->set_error_msg("'(' expected"); return 1; } - if (ls.init_from_text(trs, wkb)) + if (ls.init_from_wkt(trs, wkb)) return 1; if (trs->get_next_symbol() != ')') { @@ -503,7 +503,7 @@ int GPolygon::init_from_text(GTextReadStream *trs, String *wkb) return 0; } -int GPolygon::get_data_as_text(String *txt) const +int GPolygon::get_data_as_wkt(String *txt) const { uint32 n_linear_rings; const char *data= m_data; @@ -783,7 +783,7 @@ size_t GMultiPoint::get_data_size() const return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE); } -int GMultiPoint::init_from_text(GTextReadStream *trs, String *wkb) +int GMultiPoint::init_from_wkt(GTextReadStream *trs, String *wkb) { uint32 n_points = 0; int np_pos = wkb->length(); @@ -799,7 +799,7 @@ int GMultiPoint::init_from_text(GTextReadStream *trs, String *wkb) return 1; wkb->q_append((char)wkbNDR); wkb->q_append((uint32)wkbPoint); - if (p.init_from_text(trs, wkb)) + if (p.init_from_wkt(trs, wkb)) return 1; ++n_points; if (trs->get_next_toc_type() == GTextReadStream::comma) @@ -812,7 +812,7 @@ int GMultiPoint::init_from_text(GTextReadStream *trs, String *wkb) return 0; } -int GMultiPoint::get_data_as_text(String *txt) const +int GMultiPoint::get_data_as_wkt(String *txt) const { uint32 n_points; const char *data= m_data; @@ -904,7 +904,7 @@ size_t GMultiLineString::get_data_size() const return data - m_data; } -int GMultiLineString::init_from_text(GTextReadStream *trs, String *wkb) +int GMultiLineString::init_from_wkt(GTextReadStream *trs, String *wkb) { uint32 n_line_strings = 0; int ls_pos = wkb->length(); @@ -928,7 +928,7 @@ int GMultiLineString::init_from_text(GTextReadStream *trs, String *wkb) trs->set_error_msg("'(' expected"); return 1; } - if (ls.init_from_text(trs, wkb)) + if (ls.init_from_wkt(trs, wkb)) return 1; if (trs->get_next_symbol() != ')') @@ -947,7 +947,7 @@ int GMultiLineString::init_from_text(GTextReadStream *trs, String *wkb) return 0; } -int GMultiLineString::get_data_as_text(String *txt) const +int GMultiLineString::get_data_as_wkt(String *txt) const { uint32 n_line_strings; const char *data= m_data; @@ -1120,7 +1120,7 @@ size_t GMultiPolygon::get_data_size() const return data - m_data; } -int GMultiPolygon::init_from_text(GTextReadStream *trs, String *wkb) +int GMultiPolygon::init_from_wkt(GTextReadStream *trs, String *wkb) { uint32 n_polygons = 0; int np_pos = wkb->length(); @@ -1143,7 +1143,7 @@ int GMultiPolygon::init_from_text(GTextReadStream *trs, String *wkb) trs->set_error_msg("'(' expected"); return 1; } - if (p.init_from_text(trs, wkb)) + if (p.init_from_wkt(trs, wkb)) return 1; if (trs->get_next_symbol() != ')') { @@ -1160,7 +1160,7 @@ int GMultiPolygon::init_from_text(GTextReadStream *trs, String *wkb) return 0; } -int GMultiPolygon::get_data_as_text(String *txt) const +int GMultiPolygon::get_data_as_wkt(String *txt) const { uint32 n_polygons; const char *data= m_data; @@ -1403,7 +1403,7 @@ size_t GGeometryCollection::get_data_size() const return data - m_data; } -int GGeometryCollection::init_from_text(GTextReadStream *trs, String *wkb) +int GGeometryCollection::init_from_wkt(GTextReadStream *trs, String *wkb) { uint32 n_objects = 0; int no_pos = wkb->length(); @@ -1433,7 +1433,7 @@ int GGeometryCollection::init_from_text(GTextReadStream *trs, String *wkb) return 0; } -int GGeometryCollection::get_data_as_text(String *txt) const +int GGeometryCollection::get_data_as_wkt(String *txt) const { uint32 n_objects; const char *data = m_data; diff --git a/sql/spatial.h b/sql/spatial.h index d9c14afbe30..5fda257f1b1 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -228,8 +228,8 @@ public: class GClassInfo { public: - GF_InitFromText init_from_text; - GF_GetDataAsText get_data_as_text; + GF_InitFromText init_from_wkt; + GF_GetDataAsText get_data_as_wkt; GF_GetDataSize get_data_size; GF_GetMBR get_mbr; GF_GetD get_x; @@ -262,11 +262,11 @@ public: const GClassInfo *get_class_info() const { return m_vmt; } size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); } - int init_from_text(GTextReadStream *trs, String *wkb) - { return (this->*m_vmt->init_from_text)(trs, wkb); } + int init_from_wkt(GTextReadStream *trs, String *wkb) + { return (this->*m_vmt->init_from_wkt)(trs, wkb); } - int get_data_as_text(String *txt) const - { return (this->*m_vmt->get_data_as_text)(txt); } + int get_data_as_wkt(String *txt) const + { return (this->*m_vmt->get_data_as_wkt)(txt); } int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); } int dimension(uint32 *dim) const @@ -324,7 +324,7 @@ public: return 1; wkt->qs_append(get_class_info()->m_name); wkt->qs_append('('); - if (get_data_as_text(wkt)) + if (get_data_as_wkt(wkt)) return 1; wkt->qs_append(')'); return 0; @@ -364,8 +364,8 @@ class GPoint: public Geometry { public: size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; + int init_from_wkt(GTextReadStream *trs, String *wkb); + int get_data_as_wkt(String *txt) const; int get_mbr(MBR *mbr) const; int get_xy(double *x, double *y) const @@ -401,8 +401,8 @@ class GLineString: public Geometry { public: size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; + int init_from_wkt(GTextReadStream *trs, String *wkb); + int get_data_as_wkt(String *txt) const; int get_mbr(MBR *mbr) const; int length(double *len) const; @@ -420,8 +420,8 @@ class GPolygon: public Geometry { public: size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; + int init_from_wkt(GTextReadStream *trs, String *wkb); + int get_data_as_wkt(String *txt) const; int get_mbr(MBR *mbr) const; int area(double *ar) const; @@ -439,8 +439,8 @@ class GMultiPoint: public Geometry { public: size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; + int init_from_wkt(GTextReadStream *trs, String *wkb); + int get_data_as_wkt(String *txt) const; int get_mbr(MBR *mbr) const; int num_geometries(uint32 *num) const; @@ -454,8 +454,8 @@ class GMultiLineString: public Geometry { public: size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; + int init_from_wkt(GTextReadStream *trs, String *wkb); + int get_data_as_wkt(String *txt) const; int get_mbr(MBR *mbr) const; int num_geometries(uint32 *num) const; @@ -471,8 +471,8 @@ class GMultiPolygon: public Geometry { public: size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; + int init_from_wkt(GTextReadStream *trs, String *wkb); + int get_data_as_wkt(String *txt) const; int get_mbr(MBR *mbr) const; int num_geometries(uint32 *num) const; @@ -488,8 +488,8 @@ class GGeometryCollection: public Geometry { public: size_t get_data_size() const; - int init_from_text(GTextReadStream *trs, String *wkb); - int get_data_as_text(String *txt) const; + int init_from_wkt(GTextReadStream *trs, String *wkb); + int get_data_as_wkt(String *txt) const; int get_mbr(MBR *mbr) const; int num_geometries(uint32 *num) const; From 75689220fac09f19531e53402dd1736f11b003c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 13:57:51 +0200 Subject: [PATCH 378/399] - make sure that scripts/*.sql files are being added to the source distribution as well --- scripts/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 6006222992e..ff35170dcf3 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -62,7 +62,7 @@ EXTRA_DIST = $(EXTRA_SCRIPTS) \ mysqlaccess.conf \ mysqlbug -pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql +dist_pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql # mysqlbug should be distributed built so that people can report build # failures with it. From 1bc2349ec6bcf2c1c95402f58e52cddc6ef1a17a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 18:45:28 +0500 Subject: [PATCH 379/399] item_cmpfunc.cc: Rewritten in nicer way , sql/item_cmpfunc.cc: Rewritten in nicer way , --- sql/item_cmpfunc.cc | 69 +++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d4997f78a9e..e67c742928e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -90,38 +90,51 @@ static bool convert_constant_item(Field *field, Item **item) bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1, CHARSET_INFO *cs2, enum coercion co2) { - if ((cs1 == &my_charset_bin) || (cs2 == &my_charset_bin)) + if (!my_charset_same(cs1, cs2)) { - cmp_charset= &my_charset_bin; - return 0; - } - - if ((co1 == COER_NOCOLL) || (co2 == COER_NOCOLL)) - return 1; - - if (!my_charset_same(cs1,cs2)) - return 1; - - if (co1 < co2) - cmp_charset= cs1; - else if (co2 < co1) - cmp_charset= cs2; - else // co1==co2 - { - if (cs1 == cs2) + /* + We do allow to use BLOBS together with character strings + BLOBS have more precedance + */ + if ((co1 <= co2) && (cs1==&my_charset_bin)) + { cmp_charset= cs1; + coercibility= co1; + } + else if ((co2 <= co1) && (cs2==&my_charset_bin)) + { + cmp_charset= cs2; + coercibility= co2; + } else { - if (co1 == COER_COERCIBLE) - { - CHARSET_INFO *c; - if ((c= get_charset_by_csname(cs1->csname, MY_CS_PRIMARY, MYF(0)))) - { - cmp_charset= c; - return 0; - } - } - return 1; + cmp_charset= 0; + coercibility= COER_NOCOLL; + return 1; + } + } + else if (co1 < co2) + { + cmp_charset= cs1; + coercibility= co1; + } + else if (co2 < co1) + { + cmp_charset= cs2; + coercibility= co1; + } + else + { + if (cs1 == cs2) + { + cmp_charset= cs1; + coercibility= co1; + } + else + { + coercibility= COER_NOCOLL; + cmp_charset= 0; + return (co1 == COER_EXPLICIT) ? 1 : 0; } } return 0; From 0912871d6aeefe61dae1370ab9a1493341b9b4fc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jun 2003 19:05:45 +0500 Subject: [PATCH 380/399] item_cmpfunc.cc: Temporarily fix for test failure ,. sql/item_cmpfunc.cc: Temporarily fix for test failure ,. --- sql/item_cmpfunc.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index e67c742928e..5c2b9ed4682 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -90,6 +90,13 @@ static bool convert_constant_item(Field *field, Item **item) bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1, CHARSET_INFO *cs2, enum coercion co2) { + if (cs1 == &my_charset_bin || cs2 == &my_charset_bin) + { + cmp_charset= &my_charset_bin; + coercibility= co1 > co2 ? co1 : co2; + return 0; + } + if (!my_charset_same(cs1, cs2)) { /* From 4c1766ddee7216a540ec35f691b41825492d55db Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jun 2003 13:37:11 +0500 Subject: [PATCH 381/399] Item character set is stored in Item itself now, not in ITem->str_value --- sql/item.cc | 4 +++- sql/item.h | 18 ++++++++++-------- sql/sql_select.cc | 4 ++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 868cf4466a6..d74b9d7454f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -39,7 +39,8 @@ Item::Item(): { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; - coercibility=COER_COERCIBLE; + collation= &my_charset_bin; + coercibility= COER_COERCIBLE; name= 0; decimals= 0; max_length= 0; THD *thd= current_thd; @@ -67,6 +68,7 @@ Item::Item(THD *thd, Item &item): unsigned_flag(item.unsigned_flag), with_sum_func(item.with_sum_func), fixed(item.fixed), + collation(item.collation), coercibility(item.coercibility) { next=thd->free_list; // Put in free list diff --git a/sql/item.h b/sql/item.h index 5cfe8eb3907..df9ada72ce5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -65,6 +65,7 @@ public: my_bool unsigned_flag; my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ + CHARSET_INFO *collation; /* character set && collation */ enum coercion coercibility; /* Precedence order of collation */ // alloc & destruct is done as start of select using sql_alloc @@ -123,18 +124,17 @@ public: virtual Item *real_item() { return this; } virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); } - virtual bool binary() const - { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } CHARSET_INFO *default_charset() const; - CHARSET_INFO *charset() const { return str_value.charset(); }; - void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } + CHARSET_INFO *charset() const { return collation; }; + void set_charset(CHARSET_INFO *cs) + { collation= cs; } void set_charset(CHARSET_INFO *cs, enum coercion coer) - { - str_value.set_charset(cs); - coercibility= coer; - } + { collation= cs; coercibility= coer; } bool set_charset(CHARSET_INFO *cs1, enum coercion co1, CHARSET_INFO *cs2, enum coercion co2); + bool binary() const + { return charset()->state & MY_CS_BINSORT ? 1 : 0 ; } + virtual void set_outer_resolving() {} // Row emulation @@ -383,6 +383,7 @@ public: Item_string(const char *str,uint length, CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE) { + set_charset(cs); str_value.set(str,length,cs); coercibility= coer; max_length=length; @@ -392,6 +393,7 @@ public: Item_string(const char *name_par, const char *str, uint length, CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE) { + set_charset(cs); str_value.set(str,length,cs); coercibility= coer; max_length=length; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a4dcc3d7092..b8eb9e19cc7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4142,10 +4142,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case STRING_RESULT: if (item->max_length > 255) new_field= new Field_blob(item->max_length,maybe_null, - item->name,table,item->str_value.charset()); + item->name,table,item->charset()); else new_field= new Field_string(item->max_length,maybe_null, - item->name,table,item->str_value.charset()); + item->name,table,item->charset()); break; case ROW_RESULT: default: From fff1f663c2d55faa57aaeae29df11515772c1b0b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jun 2003 12:10:35 +0300 Subject: [PATCH 382/399] Fixed some new memory leaks Updated VC++ files VC++Files/client/mysql.dsp: Update of VC++ files VC++Files/client/mysqlclient.dsp: Update of VC++ files VC++Files/libmysqld/examples/test_libmysqld.dsp: Update of VC++ files VC++Files/libmysqld/libmysqld.def: Update of VC++ files VC++Files/libmysqld/libmysqld.dsp: Update of VC++ files VC++Files/myisam/myisam.dsp: Update of VC++ files VC++Files/mysql.dsw: Update of VC++ files VC++Files/sql/mysqld.dsp: Update of VC++ files include/mysql.h: Add missing client functions to embedded server libmysql/libmysql.def: sort functions to enable comparison with libmysqld.def libmysqld/libmysqld.c: Add missing client functions to embedded server libmysqld/libmysqld.def: sort functions to enable comparison with libmysql.def Added missing functions myisam/mi_preload.c: Fixed compiler warning. Small code cleanup scripts/make_win_src_distribution.sh: Fixed typo Don't run zip in verbose mode scripts/mysql_create_system_tables.sh: Change so that localhost has full access (to make this like 4.0) scripts/mysql_fix_privilege_tables.sh: Allow on to run this from the source distribution sql-common/client.c: Fixed memory leak sql/item_sum.cc: Removed compiler warning sql/slave.cc: Cleanup sql/sql_client.cc: Portability fix sql/sql_help.cc: Fixed memory leak --- VC++Files/client/mysql.dsp | 10 +- VC++Files/client/mysqlclient.dsp | 26 +-- .../libmysqld/examples/test_libmysqld.dsp | 24 ++- VC++Files/libmysqld/libmysqld.def | 185 ++++++++++++------ VC++Files/libmysqld/libmysqld.dsp | 50 ++++- VC++Files/myisam/myisam.dsp | 4 + VC++Files/mysql.dsw | 9 - VC++Files/sql/mysqld.dsp | 26 +-- include/mysql.h | 1 + libmysql/libmysql.def | 147 ++++++-------- libmysqld/libmysqld.c | 102 +++++++++- libmysqld/libmysqld.def | 185 ++++++++++++------ myisam/mi_preload.c | 22 +-- scripts/make_win_src_distribution.sh | 5 +- scripts/mysql_create_system_tables.sh | 11 +- scripts/mysql_fix_privilege_tables.sh | 3 + sql-common/client.c | 15 +- sql/item_sum.cc | 3 +- sql/slave.cc | 9 +- sql/sql_client.cc | 2 +- sql/sql_help.cc | 25 ++- 21 files changed, 566 insertions(+), 298 deletions(-) diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp index 1cd03ee2fcc..c0fd1e785d5 100644 --- a/VC++Files/client/mysql.dsp +++ b/VC++Files/client/mysql.dsp @@ -87,7 +87,7 @@ LINK32=link.exe # Name "mysql - Win32 Debug" # Begin Source File -SOURCE=..\mysys\my_gethostbyname.c +SOURCE=.\completion_hash.cpp # End Source File # Begin Source File @@ -101,6 +101,14 @@ SOURCE=.\mysql.cpp !ENDIF +# End Source File +# Begin Source File + +SOURCE=.\readline.cpp +# End Source File +# Begin Source File + +SOURCE=.\sql_string.cpp # End Source File # End Target # End Project diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp index 2f66d99b33c..0f4c46acd2a 100644 --- a/VC++Files/client/mysqlclient.dsp +++ b/VC++Files/client/mysqlclient.dsp @@ -25,7 +25,7 @@ CFG=mysqlclient - Win32 Debug # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" -CPP=xicl6.exe +CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "mysqlclient - Win32 Release" @@ -48,7 +48,7 @@ RSC=rc.exe BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LIB32=xilink6.exe -lib +LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"..\lib_release\mysqlclient.lib" @@ -72,7 +72,7 @@ LIB32=xilink6.exe -lib BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LIB32=xilink6.exe -lib +LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"..\lib_debug\mysqlclient.lib" @@ -108,14 +108,6 @@ SOURCE=..\libmysql\client.c # End Source File # Begin Source File -SOURCE=.\completion_hash.cpp -# End Source File -# Begin Source File - -SOURCE=.\completion_hash.h -# End Source File -# Begin Source File - SOURCE="..\strings\ctype-big5.c" # End Source File # Begin Source File @@ -426,10 +418,6 @@ SOURCE=..\libmysql\password.c # End Source File # Begin Source File -SOURCE=.\readline.cpp -# End Source File -# Begin Source File - SOURCE=..\mysys\safemalloc.c # End Source File # Begin Source File @@ -438,14 +426,6 @@ SOURCE=..\mysys\sha1.c # End Source File # Begin Source File -SOURCE=.\sql_string.cpp -# End Source File -# Begin Source File - -SOURCE=.\sql_string.h -# End Source File -# Begin Source File - SOURCE=..\strings\str2int.c # End Source File # Begin Source File diff --git a/VC++Files/libmysqld/examples/test_libmysqld.dsp b/VC++Files/libmysqld/examples/test_libmysqld.dsp index d5fd0a0982d..0f4b09d963e 100644 --- a/VC++Files/libmysqld/examples/test_libmysqld.dsp +++ b/VC++Files/libmysqld/examples/test_libmysqld.dsp @@ -7,18 +7,18 @@ CFG=test_libmysqld - Win32 Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "test_libmysqld.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "test_libmysqld.mak" CFG="test_libmysqld - Win32 Release" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "test_libmysqld - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -55,7 +55,19 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=..\..\client\completion_hash.cpp +# End Source File +# Begin Source File + SOURCE=..\..\client\mysql.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\client\readline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\client\sql_string.cpp # End Source File # End Group # Begin Source File diff --git a/VC++Files/libmysqld/libmysqld.def b/VC++Files/libmysqld/libmysqld.def index c6615ee971c..c3f757b5f1a 100644 --- a/VC++Files/libmysqld/libmysqld.def +++ b/VC++Files/libmysqld/libmysqld.def @@ -1,65 +1,130 @@ LIBRARY LIBMYSQLD -DESCRIPTION 'MySQL 4.0 Embedded Server Library' -VERSION 4.0 +DESCRIPTION 'MySQL 4.1 Embedded Server Library' +VERSION 4.1 EXPORTS - mysql_server_end - mysql_server_init - mysql_use_result - mysql_thread_safe - mysql_thread_id - mysql_store_result - mysql_stat - mysql_shutdown - mysql_select_db - mysql_row_tell - mysql_row_seek - mysql_real_query - mysql_real_connect - mysql_query - mysql_ping - mysql_options - mysql_num_rows - mysql_num_fields - mysql_list_tables - mysql_list_processes - mysql_list_fields - mysql_list_dbs - mysql_kill - mysql_insert_id - mysql_init - mysql_info - mysql_get_server_info - mysql_get_proto_info - mysql_get_host_info - mysql_get_client_info - mysql_free_result - mysql_field_tell + _dig_vec + bmove_upp + delete_dynamic + free_defaults + getopt_compare_strings + getopt_ull_limit_value + handle_options + init_dynamic_array + insert_dynamic + int2str + is_prefix + list_add + list_delete + load_defaults + max_allowed_packet + my_end + my_getopt_print_errors + my_init + my_malloc + my_memdup + my_no_flags_free + my_path + my_print_help + my_print_variables + my_realloc + my_strdup + my_thread_end + my_thread_init + myodbc_remove_escape + mysql_affected_rows + mysql_autocommit + mysql_change_user + mysql_character_set_name + mysql_close + mysql_commit + 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_fetch_row - mysql_fetch_lengths - mysql_fetch_fields - mysql_fetch_field_direct - mysql_fetch_field - mysql_escape_string - mysql_real_escape_string - mysql_error - mysql_errno - mysql_eof - mysql_dump_debug_info - mysql_drop_db - mysql_debug - mysql_data_seek - mysql_create_db - mysql_character_set_name - mysql_change_user - mysql_connect - mysql_close - mysql_affected_rows - mysql_thread_init - mysql_thread_end - mysql_send_query - mysql_read_query_result - mysql_refresh + 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_more_results + mysql_next_result + mysql_num_fields + mysql_num_rows mysql_odbc_escape_string - myodbc_remove_escape + mysql_options + mysql_ping + mysql_query + mysql_read_query_result + mysql_real_connect + mysql_real_escape_string + mysql_real_query + mysql_refresh + mysql_rollback + mysql_row_seek + mysql_row_tell + mysql_select_db + mysql_send_query + mysql_shutdown + mysql_ssl_set + mysql_stat + mysql_store_result + mysql_sqlstate + mysql_thread_id + mysql_thread_safe + mysql_use_result + mysql_warning_count + net_buffer_length + set_dynamic + strcend + strcont + strdup_root + strfill + strinstr + strmake + strmov + strxmov + mysql_server_end + mysql_server_init + get_tty_password + sql_protocol_typelib + mysql_get_server_version + mysql_sqlstate + charsets_dir + disabled_my_option + my_charset_latin1 + init_alloc_root + my_progname + get_charset_by_csname + print_defaults + find_type + strxnmov + strend + my_fopen + my_fclose + unpack_filename + str2int + int10_to_str + longlong10_to_str + my_snprintf_8bit + alloc_root + free_root + my_read diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp index 4db155e6ee6..691c66a074d 100644 --- a/VC++Files/libmysqld/libmysqld.dsp +++ b/VC++Files/libmysqld/libmysqld.dsp @@ -43,7 +43,8 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /mktyplib203 /win32 # ADD BASE MTL /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x416 /d "NDEBUG" # ADD RSC /l 0x416 /d "NDEBUG" @@ -68,7 +69,8 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /mktyplib203 /win32 # ADD BASE MTL /c +# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x416 /d "_DEBUG" # ADD RSC /l 0x416 /d "_DEBUG" @@ -87,7 +89,11 @@ LINK32=link.exe # Name "libmysqld - Win32 Debug" # Begin Source File -SOURCE=.\client.c +SOURCE="..\strings\ctype-latin1.c" +# End Source File +# Begin Source File + +SOURCE=..\mysys\default.c # End Source File # Begin Source File @@ -111,7 +117,7 @@ SOURCE=..\sql\filesort.cpp # End Source File # Begin Source File -SOURCE=..\libmysql\get_password.c +SOURCE=..\client\get_password.c # End Source File # Begin Source File @@ -159,6 +165,10 @@ SOURCE=..\sql\init.cpp # End Source File # Begin Source File +SOURCE=..\strings\int2str.c +# End Source File +# Begin Source File + SOURCE=..\sql\item.cpp # End Source File # Begin Source File @@ -240,6 +250,14 @@ SOURCE=..\sql\mf_iocache.cpp # End Source File # Begin Source File +SOURCE=..\mysys\my_alloc.c +# End Source File +# Begin Source File + +SOURCE=..\mysys\my_getopt.c +# End Source File +# Begin Source File + SOURCE=..\sql\net_serv.cpp # End Source File # Begin Source File @@ -384,6 +402,10 @@ SOURCE=..\sql\sql_show.cpp # End Source File # Begin Source File +SOURCE=..\sql\sql_state.c +# End Source File +# Begin Source File + SOURCE=..\sql\sql_string.cpp # End Source File # Begin Source File @@ -412,6 +434,26 @@ SOURCE=..\sql\sql_yacc.cpp # End Source File # Begin Source File +SOURCE=..\strings\str2int.c +# End Source File +# Begin Source File + +SOURCE=..\strings\strcend.c +# End Source File +# Begin Source File + +SOURCE=..\strings\strcont.c +# End Source File +# Begin Source File + +SOURCE=..\strings\strinstr.c +# End Source File +# Begin Source File + +SOURCE=..\strings\strxnmov.c +# End Source File +# Begin Source File + SOURCE=..\sql\table.cpp # End Source File # Begin Source File diff --git a/VC++Files/myisam/myisam.dsp b/VC++Files/myisam/myisam.dsp index 40d157a1c75..38cac3a0aba 100644 --- a/VC++Files/myisam/myisam.dsp +++ b/VC++Files/myisam/myisam.dsp @@ -193,6 +193,10 @@ SOURCE=.\mi_panic.c # End Source File # Begin Source File +SOURCE=.\mi_preload.c +# End Source File +# Begin Source File + SOURCE=.\mi_range.c # End Source File # Begin Source File diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw index 9903c91ba1b..d6903f4dbc7 100644 --- a/VC++Files/mysql.dsw +++ b/VC++Files/mysql.dsw @@ -725,19 +725,10 @@ Package=<5> Package=<4> {{{ - Begin Project Dependency - Project_Dep_Name strings - End Project Dependency - Begin Project Dependency - Project_Dep_Name mysys - End Project Dependency Begin Project Dependency Project_Dep_Name libmysqld End Project Dependency Begin Project Dependency - Project_Dep_Name vio - End Project Dependency - Begin Project Dependency Project_Dep_Name zlib End Project Dependency }}} diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 6aab591120a..8192623f957 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -28,7 +28,7 @@ CFG=mysqld - Win32 Release # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" -CPP=xicl6.exe +CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "mysqld - Win32 Release" @@ -45,14 +45,14 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../zlib" /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x410 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=xilink6.exe +LINK32=link.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:console /machine:I386 # ADD 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 Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-opt.exe" # SUBTRACT LINK32 /debug @@ -71,14 +71,14 @@ LINK32=xilink6.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../regex" /I "../bdb/build_win32" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c +# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c # SUBTRACT CPP /Fr /YX # ADD BASE RSC /l 0x410 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=xilink6.exe +LINK32=link.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:console /debug /machine:I386 /pdbtype:sept # ADD 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 Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\isam.lib ..\lib_debug\merge.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld.exe" /pdbtype:sept @@ -98,14 +98,14 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G5 /MT /W3 /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D "DBUG_OFF" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x410 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=xilink6.exe +LINK32=link.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 Wsock32.lib ..\lib_release\dbug.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /debug /machine:I386 # ADD 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 Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe" # SUBTRACT LINK32 /pdb:none /debug @@ -126,14 +126,14 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../bdb/build_win32" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=xilink6.exe +LINK32=link.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 Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe" # SUBTRACT BASE LINK32 /pdb:none /debug # ADD 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 Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-max-nt.exe" @@ -155,14 +155,14 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../bdb/build_win32" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=xilink6.exe +LINK32=link.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 Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /out:"../client_release/mysqld-opt.exe" # ADD 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 Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-max.exe" # SUBTRACT LINK32 /debug @@ -893,6 +893,10 @@ SOURCE=.\sql_class.cpp # End Source File # Begin Source File +SOURCE=.\sql_client.cpp +# End Source File +# Begin Source File + SOURCE=.\sql_crypt.cpp # End Source File # Begin Source File diff --git a/include/mysql.h b/include/mysql.h index 337e080e4cc..bd63a10ba45 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -266,6 +266,7 @@ typedef struct st_mysql my_bool free_me; /* If free in mysql_close */ my_ulonglong insert_id; /* id if insert on table with NEXTNR */ unsigned int last_errno; + unsigned int server_status; char *last_error; /* Used by embedded server */ char sqlstate[SQLSTATE_LENGTH+1]; /* Used by embedded server */ } MYSQL; diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 8c97ef45aa3..d641ca57274 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -2,8 +2,43 @@ LIBRARY LIBMYSQL DESCRIPTION 'MySQL 4.1 Client Library' VERSION 6.0 EXPORTS + _dig_vec + bmove_upp + delete_dynamic + free_defaults + getopt_compare_strings + getopt_ull_limit_value + handle_options + init_dynamic_array + insert_dynamic + int2str + is_prefix + list_add + list_delete + load_defaults + max_allowed_packet + my_end + my_getopt_print_errors + my_init + my_malloc + my_memdup + my_no_flags_free + my_path + my_print_help + my_print_variables + my_realloc + my_strdup + my_thread_end + my_thread_init + myodbc_remove_escape mysql_affected_rows + mysql_autocommit + mysql_bind_param + mysql_bind_result + mysql_change_user + mysql_character_set_name mysql_close + mysql_commit mysql_data_seek mysql_debug mysql_dump_debug_info @@ -11,6 +46,9 @@ EXPORTS mysql_errno mysql_error mysql_escape_string + mysql_execute + mysql_fetch + mysql_fetch_column mysql_fetch_field mysql_fetch_field_direct mysql_fetch_fields @@ -32,113 +70,54 @@ EXPORTS mysql_list_fields mysql_list_processes mysql_list_tables + mysql_more_results + mysql_next_result mysql_num_fields mysql_num_rows mysql_odbc_escape_string mysql_options + mysql_param_count + mysql_param_result mysql_ping + mysql_prepare + mysql_prepare_result mysql_query + mysql_read_query_result mysql_real_connect + mysql_real_escape_string mysql_real_query mysql_refresh + mysql_rollback mysql_row_seek mysql_row_tell mysql_select_db + mysql_send_long_data + mysql_send_query mysql_shutdown + mysql_ssl_set mysql_stat + mysql_stmt_affected_rows + mysql_stmt_close + mysql_stmt_data_seek + mysql_stmt_errno + mysql_stmt_error + mysql_stmt_free_result + mysql_stmt_num_rows + mysql_stmt_row_seek + mysql_stmt_row_tell + mysql_stmt_store_result mysql_store_result mysql_thread_id + mysql_thread_safe 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_init - my_end - my_strdup - my_malloc - my_memdup - my_no_flags_free - my_realloc - my_thread_end - my_thread_init + mysql_warning_count net_buffer_length set_dynamic strcend + strcont 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 - my_getopt_print_errors - handle_options - my_print_help - my_print_variables - getopt_ull_limit_value - getopt_compare_strings - mysql_warning_count - mysql_prepare - mysql_execute - mysql_param_count - mysql_bind_param - mysql_bind_result - mysql_param_result - mysql_prepare_result - mysql_stmt_close - mysql_stmt_free_result - mysql_stmt_error - mysql_stmt_errno - mysql_fetch - mysql_fetch_column - mysql_send_long_data - mysql_next_result - mysql_stmt_affected_rows - mysql_stmt_store_result - mysql_stmt_data_seek - mysql_stmt_row_seek - mysql_stmt_row_tell - mysql_stmt_num_rows - mysql_more_results - mysql_commit - mysql_rollback - mysql_autocommit - load_defaults - free_defaults - my_path - - - - - - - diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index a2d69b30c0d..ba2dfd68c00 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -49,6 +49,8 @@ static my_bool mysql_client_init=0; uint mysql_port=0; my_string mysql_unix_port=0; +const char *not_error_sqlstate= "00000"; + const char *sql_protocol_names_lib[] = { "TCP", "SOCKET", "PIPE", "MEMORY",NullS }; TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"", @@ -516,6 +518,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, client_flag&= ~CLIENT_COMPRESS; if (db) client_flag|=CLIENT_CONNECT_WITH_DB; + mysql->server_status= SERVER_STATUS_AUTOCOMMIT; if (mysql->options.init_commands) { @@ -1040,9 +1043,9 @@ mysql_list_fields(MYSQL *mysql __attribute__((unused)), const char *table __attr /* List all running processes (threads) in server */ MYSQL_RES * STDCALL -mysql_list_processes(MYSQL *mysql) +mysql_list_processes(MYSQL *mysql __attribute__((unused))) { -#ifdef DUMMY +#ifdef FOR_THE_FUTURE MYSQL_DATA *fields; uint field_count; uchar *pos; @@ -1063,7 +1066,7 @@ mysql_list_processes(MYSQL *mysql) mysql->status=MYSQL_STATUS_GET_RESULT; mysql->field_count=field_count; DBUG_RETURN(mysql_store_result(mysql)); -#endif /*DUMMY*/ +#endif /* FOR_THE_FUTURE */ return 0; } @@ -1535,3 +1538,96 @@ myodbc_remove_escape(MYSQL *mysql,char *name) } *to=0; } + + +/******************************************************************** + Transactional APIs +*********************************************************************/ + +/* + Commit the current transaction +*/ + +my_bool STDCALL mysql_commit(MYSQL * mysql) +{ + DBUG_ENTER("mysql_commit"); + DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6)); +} + +/* + Rollback the current transaction +*/ + +my_bool STDCALL mysql_rollback(MYSQL * mysql) +{ + DBUG_ENTER("mysql_rollback"); + DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8)); +} + + +/* + Set autocommit to either true or false +*/ + +my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode) +{ + DBUG_ENTER("mysql_autocommit"); + DBUG_PRINT("enter", ("mode : %d", auto_mode)); + + if (auto_mode) /* set to true */ + DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=1", 16)); + DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=0", 16)); +} + + +/******************************************************************** + Multi query execution + SPs APIs +*********************************************************************/ + +/* + Returns if there are any more query results exists to be read using + mysql_next_result() +*/ + +my_bool STDCALL mysql_more_results(MYSQL *mysql) +{ + my_bool res; + DBUG_ENTER("mysql_more_results"); + + res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ? + 1: 0); + DBUG_PRINT("exit",("More results exists ? %d", res)); + DBUG_RETURN(res); +} + + +/* + Reads and returns the next query results +*/ + +my_bool STDCALL mysql_next_result(MYSQL *mysql) +{ + DBUG_ENTER("mysql_next_result"); + + mysql->last_error[0]= 0; + mysql->last_errno= 0; + strmov(mysql->sqlstate, not_error_sqlstate); + mysql->affected_rows= ~(my_ulonglong) 0; + + if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS) + DBUG_RETURN(mysql_read_query_result(mysql)); + + DBUG_RETURN(0); +} + + +my_bool STDCALL +mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , + const char *key __attribute__((unused)), + const char *cert __attribute__((unused)), + const char *ca __attribute__((unused)), + const char *capath __attribute__((unused)), + const char *cipher __attribute__((unused))) +{ + return 0; +} diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index c6615ee971c..c3f757b5f1a 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -1,65 +1,130 @@ LIBRARY LIBMYSQLD -DESCRIPTION 'MySQL 4.0 Embedded Server Library' -VERSION 4.0 +DESCRIPTION 'MySQL 4.1 Embedded Server Library' +VERSION 4.1 EXPORTS - mysql_server_end - mysql_server_init - mysql_use_result - mysql_thread_safe - mysql_thread_id - mysql_store_result - mysql_stat - mysql_shutdown - mysql_select_db - mysql_row_tell - mysql_row_seek - mysql_real_query - mysql_real_connect - mysql_query - mysql_ping - mysql_options - mysql_num_rows - mysql_num_fields - mysql_list_tables - mysql_list_processes - mysql_list_fields - mysql_list_dbs - mysql_kill - mysql_insert_id - mysql_init - mysql_info - mysql_get_server_info - mysql_get_proto_info - mysql_get_host_info - mysql_get_client_info - mysql_free_result - mysql_field_tell + _dig_vec + bmove_upp + delete_dynamic + free_defaults + getopt_compare_strings + getopt_ull_limit_value + handle_options + init_dynamic_array + insert_dynamic + int2str + is_prefix + list_add + list_delete + load_defaults + max_allowed_packet + my_end + my_getopt_print_errors + my_init + my_malloc + my_memdup + my_no_flags_free + my_path + my_print_help + my_print_variables + my_realloc + my_strdup + my_thread_end + my_thread_init + myodbc_remove_escape + mysql_affected_rows + mysql_autocommit + mysql_change_user + mysql_character_set_name + mysql_close + mysql_commit + 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_fetch_row - mysql_fetch_lengths - mysql_fetch_fields - mysql_fetch_field_direct - mysql_fetch_field - mysql_escape_string - mysql_real_escape_string - mysql_error - mysql_errno - mysql_eof - mysql_dump_debug_info - mysql_drop_db - mysql_debug - mysql_data_seek - mysql_create_db - mysql_character_set_name - mysql_change_user - mysql_connect - mysql_close - mysql_affected_rows - mysql_thread_init - mysql_thread_end - mysql_send_query - mysql_read_query_result - mysql_refresh + 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_more_results + mysql_next_result + mysql_num_fields + mysql_num_rows mysql_odbc_escape_string - myodbc_remove_escape + mysql_options + mysql_ping + mysql_query + mysql_read_query_result + mysql_real_connect + mysql_real_escape_string + mysql_real_query + mysql_refresh + mysql_rollback + mysql_row_seek + mysql_row_tell + mysql_select_db + mysql_send_query + mysql_shutdown + mysql_ssl_set + mysql_stat + mysql_store_result + mysql_sqlstate + mysql_thread_id + mysql_thread_safe + mysql_use_result + mysql_warning_count + net_buffer_length + set_dynamic + strcend + strcont + strdup_root + strfill + strinstr + strmake + strmov + strxmov + mysql_server_end + mysql_server_init + get_tty_password + sql_protocol_typelib + mysql_get_server_version + mysql_sqlstate + charsets_dir + disabled_my_option + my_charset_latin1 + init_alloc_root + my_progname + get_charset_by_csname + print_defaults + find_type + strxnmov + strend + my_fopen + my_fclose + unpack_filename + str2int + int10_to_str + longlong10_to_str + my_snprintf_8bit + alloc_root + free_root + my_read diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c index be45be66ecf..a5d9bec160e 100644 --- a/myisam/mi_preload.c +++ b/myisam/mi_preload.c @@ -42,35 +42,32 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) { uint i; - uint length; - uint block_length= 0; + ulong length, block_length= 0; uchar *buff= NULL; MYISAM_SHARE* share= info->s; uint keys= share->state.header.keys; MI_KEYDEF *keyinfo= share->keyinfo; my_off_t key_file_length= share->state.state.key_file_length; my_off_t pos= share->base.keystart; + DBUG_ENTER("mi_preload"); if (!keys || !key_map || key_file_length == pos) - return 0; + DBUG_RETURN(0); block_length= keyinfo[0].block_length; - if (!key_map) - return 0; - /* Check whether all indexes use the same block size */ for (i= 1 ; i < keys ; i++) { if (keyinfo[i].block_length != block_length) - return (my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); + DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); } length= info->preload_buff_size/block_length * block_length; set_if_bigger(length, block_length); if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME)))) - return (my_errno= HA_ERR_OUT_OF_MEM); + DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); if (flush_key_blocks(share->kfile, FLUSH_RELEASE)) goto err; @@ -78,7 +75,8 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) do { /* Read the next block of index file into the preload buffer */ - set_if_smaller(length, key_file_length-pos); + if ((my_off_t) length > (key_file_length-pos)) + length= (ulong) (key_file_length-pos); if (my_pread(share->kfile, (byte*) buff, length, pos, MYF(MY_FAE))) goto err; @@ -103,16 +101,14 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) goto err; pos+= length; } - } while (pos != key_file_length); my_free(buff, MYF(0)); - - return 0; + DBUG_RETURN(0); err: my_free(buff, MYF(MY_ALLOW_ZERO_PTR)); - return (my_errno= errno); + DBUG_RETURN(my_errno= errno); } diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index 1be301ee92a..df7ac29ee0d 100755 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -251,7 +251,7 @@ touch $BASE/innobase/ib_config.h cd $SOURCE for i in COPYING ChangeLog README \ INSTALL-SOURCE INSTALL-WIN \ - INSTALL-WIN-SOURCE + INSTALL-WIN-SOURCE \ Docs/manual_toc.html Docs/manual.html \ Docs/mysqld_error.txt Docs/INSTALL-BINARY @@ -350,7 +350,7 @@ set_tarzip_options() else ZIPFILE1=zip ZIPFILE2="" - OPT="-vr" + OPT="-r" EXT=".zip" NEED_COMPRESS=0 if [ "$SILENT" = "1" ] ; then @@ -382,6 +382,7 @@ print_debug "Using $tar to create archive" cd $TMP +rm -f $SOURCE/$NEW_NAME$EXT $tar $OPT $SOURCE/$NEW_NAME$EXT $NEW_DIR_NAME cd $SOURCE diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index 51fbb8a8097..1f0579f87c2 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -145,20 +145,19 @@ then then i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user (host,user) values ('localhost',''); INSERT INTO user (host,user) values ('$hostname','');" else - i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user (host,user) values ('localhost','');" + i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);" if test "$windows" -eq 0 then i_u="$i_u INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user (host,user) values ('$hostname','');" - fi + INSERT INTO user (host,user) values ('localhost',''); + else + i_u="INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);" + fi fi fi diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 5d392f719f0..4b6f74eae06 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -57,6 +57,9 @@ then elif test -x @bindir@/mysql_print_defaults then print_defaults="@bindir@/mysql_print_defaults" +elif test -x extra/my_print_defaults +then + print_defaults="extra/my_print_defaults" else print_defaults="my_print_defaults" fi diff --git a/sql-common/client.c b/sql-common/client.c index 33f2b996971..721164c8301 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -2022,7 +2022,6 @@ my_bool mysql_reconnect(MYSQL *mysql) } mysql_init(&tmp_mysql); tmp_mysql.options=mysql->options; - bzero((char*) &mysql->options,sizeof(mysql->options)); tmp_mysql.rpl_pivot = mysql->rpl_pivot; if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, mysql->db, mysql->port, mysql->unix_socket, @@ -2033,7 +2032,9 @@ my_bool mysql_reconnect(MYSQL *mysql) strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); DBUG_RETURN(1); } - tmp_mysql.free_me=mysql->free_me; + tmp_mysql.free_me= mysql->free_me; + /* Don't free options as these are now used in tmp_mysql */ + bzero((char*) &mysql->options,sizeof(mysql->options)); mysql->free_me=0; mysql_close(mysql); *mysql=tmp_mysql; @@ -2070,9 +2071,6 @@ mysql_select_db(MYSQL *mysql, const char *db) static void mysql_close_free_options(MYSQL *mysql) { - my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); @@ -2099,14 +2097,17 @@ static void mysql_close_free_options(MYSQL *mysql) if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif /* HAVE_SMEM */ - bzero((char*) &mysql->options,sizeof(mysql->options)); + bzero((char*) &mysql->options,sizeof(mysql->options)); } static void mysql_close_free(MYSQL *mysql) { - /* Clear pointers for better safety */ my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); + /* Clear pointers for better safety */ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 34de672dbdb..6e606d53207 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -57,7 +57,8 @@ Item_sum::Item_sum(THD *thd, Item_sum &item): void Item_sum::mark_as_sum_func() { - current_thd->lex.current_select->with_sum_func= with_sum_func= 1; + current_thd->lex.current_select->with_sum_func= 1; + with_sum_func= 1; } diff --git a/sql/slave.cc b/sql/slave.cc index ccce8077cb8..c45c11f8bef 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2177,7 +2177,7 @@ extern "C" pthread_handler_decl(handle_slave_io,arg) DBUG_ENTER("handle_slave_io"); #ifndef DBUG_OFF -slave_begin: +slave_begin: #endif DBUG_ASSERT(mi->inited); mysql= NULL ; @@ -2218,7 +2218,7 @@ slave_begin: if (!(mi->mysql = mysql = mysql_init(NULL))) { - sql_print_error("Slave I/O thread: error in mc_mysql_init()"); + sql_print_error("Slave I/O thread: error in mysql_init()"); goto err; } @@ -2270,7 +2270,7 @@ dump"); goto err; } - thd->proc_info = "Waiiting to reconnect after a failed dump request"; + thd->proc_info = "Waiting to reconnect after a failed dump request"; end_server(mysql); /* First time retry immediately, assuming that we can recover @@ -3075,7 +3075,8 @@ replication resumed in log '%s' at position %s", mi->user, static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi, bool suppress_warnings) { - return connect_to_master(thd, mysql, mi, 1, suppress_warnings); + DBUG_ENTER("safe_reconnect"); + DBUG_RETURN(connect_to_master(thd, mysql, mi, 1, suppress_warnings)); } diff --git a/sql/sql_client.cc b/sql/sql_client.cc index 464596f0734..1ae9a23a924 100644 --- a/sql/sql_client.cc +++ b/sql/sql_client.cc @@ -18,7 +18,7 @@ This files defines some MySQL C API functions that are server specific */ -#include +#include "mysql_priv.h" /* Function called by my_net_init() to set some check variables diff --git a/sql/sql_help.cc b/sql/sql_help.cc index ba7c08ff15f..02fc8591370 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -22,6 +22,8 @@ struct st_find_field Field *field; }; +static void free_select(SQL_SELECT *sel); + /* Used fields */ static struct st_find_field init_used_fields[]= @@ -62,6 +64,7 @@ enum enum_used_fields help_relation_help_keyword_id }; + /* Fill st_find_field structure with pointers to fields @@ -94,8 +97,8 @@ static bool init_fields(THD *thd, TABLE_LIST *tables, DBUG_RETURN(0); } -/* +/* Returns variants of found topic for help (if it is just single topic, returns description and example, or else returns only names..) @@ -135,7 +138,7 @@ void memorize_variant_topic(THD *thd, TABLE *topics, int count, } else { - if (count==1) + if (count == 1) names->push_back(name); String *new_name= new String; get_field(mem_root,find_fields[help_topic_name].field,new_name); @@ -557,7 +560,7 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, String **end= pointers + names->elements; List_iterator it(*names); - for ( pos= pointers; pos!=end; (*pos++= it++)); + for (pos= pointers; pos!=end; (*pos++= it++)); qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); @@ -627,6 +630,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen, return prepare_simple_select(thd,cond,tables,table,error); } + /* Server-side function 'help' @@ -783,6 +787,21 @@ int mysqld_help(THD *thd, const char *mask) res= 0; send_eof(thd); + end: + free_select(select_topics_by_name); + free_select(select_keyword_by_name); + free_select(select_cat_by_name); + free_select(select_topics_by_cat); + free_select(select_cat_by_cat); + free_select(select_root_cats); + DBUG_RETURN(res); } + + +static void free_select(SQL_SELECT *sel) +{ + if (sel) + delete sel->quick; +} From 64d7734f3827ea28f6463978cde5a97de212dcf9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jun 2003 15:11:07 +0500 Subject: [PATCH 383/399] New class DTCollation (SQL:2003 calls it "declared type collation") It's a combination of collation and its derivation (precedence order) --- sql/item.cc | 24 ++++----- sql/item.h | 109 +++++++++++++++++++++++++++---------- sql/item_cmpfunc.cc | 70 ++++++++++++------------ sql/item_cmpfunc.h | 4 +- sql/item_create.cc | 2 +- sql/item_func.cc | 41 +++++++------- sql/item_func.h | 2 +- sql/item_strfunc.cc | 128 ++++++++++++++++++-------------------------- sql/item_strfunc.h | 10 ++-- sql/log_event.cc | 2 +- sql/sql_class.h | 3 +- 11 files changed, 212 insertions(+), 183 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index d74b9d7454f..4c7b30b0410 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -39,8 +39,7 @@ Item::Item(): { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; - collation= &my_charset_bin; - coercibility= COER_COERCIBLE; + set_charset(&my_charset_bin, DERIVATION_COERCIBLE); name= 0; decimals= 0; max_length= 0; THD *thd= current_thd; @@ -68,8 +67,7 @@ Item::Item(THD *thd, Item &item): unsigned_flag(item.unsigned_flag), with_sum_func(item.with_sum_func), fixed(item.fixed), - collation(item.collation), - coercibility(item.coercibility) + collation(item.collation) { next=thd->free_list; // Put in free list thd->free_list= this; @@ -185,12 +183,12 @@ CHARSET_INFO * Item::default_charset() const return current_thd->variables.collation_connection; } -bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1, - CHARSET_INFO *cs2, enum coercion co2) +bool Item::set_charset(CHARSET_INFO *cs1, Derivation co1, + CHARSET_INFO *cs2, Derivation co2) { if (cs1 == &my_charset_bin || cs2 == &my_charset_bin) { - set_charset(&my_charset_bin, COER_NOCOLL); + set_charset(&my_charset_bin, DERIVATION_NONE); return 0; } @@ -209,7 +207,7 @@ bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1, { if (cs1 != cs2) { - if (co1 == COER_EXPLICIT) + if (co1 == DERIVATION_EXPLICIT) { return 1; } @@ -218,7 +216,7 @@ bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1, CHARSET_INFO *bin= get_charset_by_csname(cs1->csname, MY_CS_BINSORT,MYF(0)); if (!bin) return 1; - set_charset(bin, COER_NOCOLL); + set_charset(bin, DERIVATION_NONE); } } else @@ -230,7 +228,7 @@ bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1, Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) { set_field(f); - coercibility= COER_IMPLICIT; + set_charset(DERIVATION_IMPLICIT); fixed= 1; // This item is not needed in fix_fields } @@ -239,7 +237,7 @@ Item_field::Item_field(THD *thd, Item_field &item): Item_ident(thd, item), field(item.field), result_field(item.result_field) -{ coercibility= COER_IMPLICIT; } +{ set_charset(DERIVATION_IMPLICIT); } void Item_field::set_field(Field *field_par) { @@ -251,7 +249,7 @@ void Item_field::set_field(Field *field_par) field_name=field_par->field_name; db_name=field_par->table->table_cache_key; unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); - set_charset(field_par->charset(), COER_IMPLICIT); + set_charset(field_par->charset(), DERIVATION_IMPLICIT); } const char *Item_ident::full_name() const @@ -1102,7 +1100,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length) str+=2; } *ptr=0; // Keep purify happy - coercibility= COER_COERCIBLE; + set_charset(&my_charset_bin, DERIVATION_COERCIBLE); } longlong Item_varbinary::val_int() diff --git a/sql/item.h b/sql/item.h index df9ada72ce5..ce79e70e5d6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -23,6 +23,63 @@ class Protocol; struct st_table_list; void item_init(void); /* Init item functions */ + +/* + "Declared Type Collation" + A combination of collation and its deriviation. +*/ + +enum Derivation +{ + DERIVATION_COERCIBLE= 3, + DERIVATION_IMPLICIT= 2, + DERIVATION_NONE= 1, + DERIVATION_EXPLICIT= 0 +}; + +class DTCollation { +public: + CHARSET_INFO *collation; + enum Derivation derivation; + + DTCollation() + { + collation= &my_charset_bin; + derivation= DERIVATION_NONE; + } + DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) + { + collation= collation_arg; + derivation= derivation_arg; + } + void set(DTCollation *dt) + { + collation= dt->collation; + derivation= dt->derivation; + } + void set(CHARSET_INFO *collation_arg, Derivation derivation_arg) + { + collation= collation_arg; + derivation= derivation_arg; + } + void set(CHARSET_INFO *collation_arg) + { collation= collation_arg; } + void set(Derivation derivation_arg) + { derivation= derivation_arg; } + bool aggregate(DTCollation *dt); + const char *derivation_name() const + { + switch(derivation) + { + case DERIVATION_COERCIBLE: return "COERCIBLE"; + case DERIVATION_IMPLICIT: return "IMPLICIT"; + case DERIVATION_EXPLICIT: return "EXPLICIT"; + case DERIVATION_NONE: return "NONE"; + default: return "UNKNOWN"; + } + } +}; + class Item { uint loop_id; /* Used to find selfrefering loops */ Item(const Item &); /* Prevent use of these */ @@ -41,19 +98,6 @@ public: SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; - enum coercion { COER_COERCIBLE=3, COER_IMPLICIT=2, - COER_NOCOLL=1, COER_EXPLICIT=0 }; - const char *coercion_name(enum coercion coer) const - { - switch(coer) - { - case COER_COERCIBLE: return "COERCIBLE"; - case COER_IMPLICIT: return "IMPLICIT"; - case COER_EXPLICIT: return "EXPLICIT"; - case COER_NOCOLL: return "NO COLLATION"; - default: return "UNKNOWN"; - } - } String str_value; /* used to store value */ my_string name; /* Name from select */ @@ -65,9 +109,8 @@ public: my_bool unsigned_flag; my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ - CHARSET_INFO *collation; /* character set && collation */ - enum coercion coercibility; /* Precedence order of collation */ - + DTCollation collation; + // alloc & destruct is done as start of select using sql_alloc Item(); /* @@ -125,13 +168,23 @@ public: virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); } CHARSET_INFO *default_charset() const; - CHARSET_INFO *charset() const { return collation; }; + Derivation derivation() const { return collation.derivation; } + CHARSET_INFO *charset() const { return collation.collation; } void set_charset(CHARSET_INFO *cs) - { collation= cs; } - void set_charset(CHARSET_INFO *cs, enum coercion coer) - { collation= cs; coercibility= coer; } - bool set_charset(CHARSET_INFO *cs1, enum coercion co1, - CHARSET_INFO *cs2, enum coercion co2); + { collation.collation= cs; } + void set_charset(Derivation dv) + { collation.derivation= dv; } + void set_charset(CHARSET_INFO *cs, Derivation dv) + { collation.collation= cs; collation.derivation= dv; } + void set_charset(Item &item) + { collation= item.collation; } + void set_charset(DTCollation *collation_arg) + { + collation.collation= collation_arg->collation; + collation.derivation= collation_arg->derivation; + } + bool set_charset(CHARSET_INFO *cs1, Derivation dv1, + CHARSET_INFO *cs2, Derivation dv2); bool binary() const { return charset()->state & MY_CS_BINSORT ? 1 : 0 ; } @@ -180,7 +233,7 @@ public: Item_field(const char *db_par,const char *table_name_par, const char *field_name_par) :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0) - { coercibility= COER_IMPLICIT; } + { set_charset(DERIVATION_IMPLICIT); } // Constructor need to process subselect with temporary tables (see Item) Item_field(THD *thd, Item_field &item); Item_field(Field *field); @@ -381,21 +434,19 @@ class Item_string :public Item { public: Item_string(const char *str,uint length, - CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE) + CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) { - set_charset(cs); + set_charset(cs, dv); str_value.set(str,length,cs); - coercibility= coer; max_length=length; set_name(str, length, cs); decimals=NOT_FIXED_DEC; } Item_string(const char *name_par, const char *str, uint length, - CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE) + CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) { - set_charset(cs); + set_charset(cs, dv); str_value.set(str,length,cs); - coercibility= coer; max_length=length; set_name(name_par,0,cs); decimals=NOT_FIXED_DEC; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5c2b9ed4682..035f85a45ba 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -23,6 +23,15 @@ #include "mysql_priv.h" #include + +static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) +{ + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + fname); +} + Item_bool_func2* Item_bool_func2::eq_creator(Item *a, Item *b) { return new Item_func_eq(a, b); @@ -87,13 +96,13 @@ static bool convert_constant_item(Field *field, Item **item) return 0; } -bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1, - CHARSET_INFO *cs2, enum coercion co2) +bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, Derivation co1, + CHARSET_INFO *cs2, Derivation co2) { if (cs1 == &my_charset_bin || cs2 == &my_charset_bin) { cmp_charset= &my_charset_bin; - coercibility= co1 > co2 ? co1 : co2; + //coercibility= co1 > co2 ? co1 : co2; return 0; } @@ -106,42 +115,42 @@ bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1, if ((co1 <= co2) && (cs1==&my_charset_bin)) { cmp_charset= cs1; - coercibility= co1; + //coercibility= co1; } else if ((co2 <= co1) && (cs2==&my_charset_bin)) { cmp_charset= cs2; - coercibility= co2; + //coercibility= co2; } else { cmp_charset= 0; - coercibility= COER_NOCOLL; + //coercibility= DERIVATION_NOCOLL; return 1; } } else if (co1 < co2) { cmp_charset= cs1; - coercibility= co1; + //coercibility= co1; } else if (co2 < co1) { cmp_charset= cs2; - coercibility= co1; + //coercibility= co1; } else { if (cs1 == cs2) { cmp_charset= cs1; - coercibility= co1; + //coercibility= co1; } else { - coercibility= COER_NOCOLL; + //coercibility= DERIVATION_NOCOLL; cmp_charset= 0; - return (co1 == COER_EXPLICIT) ? 1 : 0; + return (co1 == DERIVATION_EXPLICIT) ? 1 : 0; } } return 0; @@ -171,13 +180,13 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables, uint strong= 0; uint weak= 0; - if ((args[0]->coercibility < args[1]->coercibility) && + if ((args[0]->derivation() < args[1]->derivation()) && !my_charset_same(args[0]->charset(), args[1]->charset()) && (args[0]->charset()->state & MY_CS_UNICODE)) { weak= 1; } - else if ((args[1]->coercibility < args[0]->coercibility) && + else if ((args[1]->derivation() < args[0]->derivation()) && !my_charset_same(args[0]->charset(), args[1]->charset()) && (args[1]->charset()->state & MY_CS_UNICODE)) { @@ -194,26 +203,23 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables, cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), args[strong]->charset()); conv= new Item_string(cstr.ptr(),cstr.length(),cstr.charset(), - args[weak]->coercibility); + args[weak]->derivation()); ((Item_string*)conv)->str_value.copy(); } else { conv= new Item_func_conv_charset(args[weak],args[strong]->charset()); - conv->coercibility= args[weak]->coercibility; + //conv->coercibility= args[weak]->derivation(); } args[weak]= conv ? conv : args[weak]; - set_cmp_charset(args[0]->charset(), args[0]->coercibility, - args[1]->charset(), args[1]->coercibility); + set_cmp_charset(args[0]->charset(), args[0]->derivation(), + args[1]->charset(), args[1]->derivation()); } } if (!cmp_charset) { /* set_cmp_charset() failed */ - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - args[0]->charset()->name,coercion_name(args[0]->coercibility), - args[1]->charset()->name,coercion_name(args[1]->coercibility), - func_name()); + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); return 1; } return 0; @@ -266,8 +272,8 @@ void Item_bool_func2::fix_length_and_dec() We must set cmp_charset here as we may be called from for an automatic generated item, like in natural join */ - set_cmp_charset(args[0]->charset(), args[0]->coercibility, - args[1]->charset(), args[1]->coercibility); + set_cmp_charset(args[0]->charset(), args[0]->derivation(), + args[1]->charset(), args[1]->derivation()); } @@ -744,12 +750,9 @@ Item_func_ifnull::fix_length_and_dec() args[1]->result_type())) != REAL_RESULT) decimals= 0; - if (set_charset(args[0]->charset(),args[0]->coercibility, - args[1]->charset(),args[1]->coercibility)) - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - args[0]->charset()->name,coercion_name(args[0]->coercibility), - args[1]->charset()->name,coercion_name(args[1]->coercibility), - func_name()); + if (set_charset(args[0]->charset(),args[0]->derivation(), + args[1]->charset(),args[1]->derivation())) + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); } @@ -825,13 +828,10 @@ Item_func_if::fix_length_and_dec() else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT) { cached_result_type = STRING_RESULT; - if (set_charset(args[1]->charset(), args[1]->coercibility, - args[2]->charset(), args[2]->coercibility)) + if (set_charset(args[1]->charset(), args[1]->derivation(), + args[2]->charset(), args[2]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - args[0]->charset()->name,coercion_name(args[0]->coercibility), - args[1]->charset()->name,coercion_name(args[1]->coercibility), - func_name()); + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); return; } } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 549839b4f96..b38248d87e1 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -123,8 +123,8 @@ public: { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1); } - bool set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1, - CHARSET_INFO *cs2, enum coercion co2); + bool set_cmp_charset(CHARSET_INFO *cs1, Derivation co1, + CHARSET_INFO *cs2, Derivation co2); optimize_type select_optimize() const { return OPTIMIZE_OP; } virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 6956582a8ca..90f42cee959 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -450,7 +450,7 @@ Item *create_func_version(void) { return new Item_string(NullS,server_version, (uint) strlen(server_version), - system_charset_info, Item::COER_IMPLICIT); + system_charset_info, DERIVATION_IMPLICIT); } Item *create_func_weekday(Item* a) diff --git a/sql/item_func.cc b/sql/item_func.cc index 6482d81f484..170260c6819 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -31,6 +31,14 @@ #include #endif +static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) +{ + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + fname); +} + /* return TRUE if item is a constant */ bool @@ -859,14 +867,11 @@ void Item_func_min_max::fix_length_and_dec() maybe_null=0; cmp_type=item_cmp_type(cmp_type,args[i]->result_type()); if (i==0) - set_charset(args[i]->charset(), args[i]->coercibility); - else if (set_charset(charset(), coercibility, - args[i]->charset(), args[i]->coercibility)) + set_charset(*args[i]); + else if (set_charset(charset(), derivation(), + args[i]->charset(), args[i]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - charset()->name,coercion_name(coercibility), - args[i]->charset()->name,coercion_name(args[i]->coercibility), - func_name()); + my_coll_agg_error(collation, args[i]->collation, func_name()); break; } } @@ -1038,7 +1043,7 @@ longlong Item_func_coercibility::val_int() return 0; } null_value= 0; - return (longlong) args[0]->coercibility; + return (longlong) args[0]->derivation(); } longlong Item_func_locate::val_int() @@ -2000,7 +2005,7 @@ Item_func_set_user_var::fix_length_and_dec() void Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type, CHARSET_INFO *cs, - enum coercion coercibility) + Derivation dv) { if ((null_value=args[0]->null_value)) { @@ -2009,8 +2014,7 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length, my_free(entry->value,MYF(0)); entry->value=0; entry->length=0; - entry->var_charset=cs; - entry->var_coercibility= coercibility; + collation.set(cs, dv); } else { @@ -2041,8 +2045,7 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length, memcpy(entry->value,ptr,length); entry->length= length; entry->type=type; - entry->var_charset=cs; - entry->var_coercibility= coercibility; + entry->collation.set(cs, dv); } return; @@ -2085,7 +2088,7 @@ Item_func_set_user_var::val() { double value=args[0]->val(); update_hash((void*) &value,sizeof(value), REAL_RESULT, - &my_charset_bin, COER_NOCOLL); + &my_charset_bin, DERIVATION_NONE); return value; } @@ -2094,7 +2097,7 @@ Item_func_set_user_var::val_int() { longlong value=args[0]->val_int(); update_hash((void*) &value, sizeof(longlong), INT_RESULT, - &my_charset_bin, COER_NOCOLL); + &my_charset_bin, DERIVATION_NONE); return value; } @@ -2103,10 +2106,10 @@ Item_func_set_user_var::val_str(String *str) { String *res=args[0]->val_str(str); if (!res) // Null value - update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, COER_NOCOLL); + update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, DERIVATION_NONE); else update_hash((void*) res->ptr(), res->length(), STRING_RESULT, - res->charset(), args[0]->coercibility); + res->charset(), args[0]->derivation()); return res; } @@ -2147,7 +2150,7 @@ Item_func_get_user_var::val_str(String *str) str->set(*(longlong*) entry->value, &my_charset_bin); break; case STRING_RESULT: - if (str->copy(entry->value, entry->length, entry->var_charset)) + if (str->copy(entry->value, entry->length, entry->collation.collation)) { null_value=1; return NULL; @@ -2236,7 +2239,7 @@ void Item_func_get_user_var::fix_length_and_dec() ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)); user_var_event->user_var_event= var_entry; user_var_event->type= var_entry->type; - user_var_event->charset_number= var_entry->var_charset->number; + user_var_event->charset_number= var_entry->collation.collation->number; if (!var_entry->value) { /* NULL value*/ diff --git a/sql/item_func.h b/sql/item_func.h index 8ef2b85de52..4e39833c467 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -943,7 +943,7 @@ public: longlong val_int(); String *val_str(String *str); void update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, enum coercion coercibility); + CHARSET_INFO *cs, Derivation dv); bool update(); enum Item_result result_type () const { return cached_result_type; } bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3cc5ac218e3..23df49c81be 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -36,6 +36,14 @@ String empty_string("",default_charset_info); +static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) +{ + my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + fname); +} + uint nr_of_decimals(const char *str) { if ((str=strchr(str,'.'))) @@ -316,17 +324,14 @@ void Item_func_concat::fix_length_and_dec() bool first_coll= 1; max_length=0; - set_charset(args[0]->charset(),args[0]->coercibility); + set_charset(*args[0]); for (uint i=0 ; i < arg_count ; i++) { max_length+=args[i]->max_length; - if (set_charset(charset(), coercibility, - args[i]->charset(), args[i]->coercibility)) + if (set_charset(charset(), derivation(), + args[i]->charset(), args[i]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - charset()->name,coercion_name(coercibility), - args[i]->charset()->name,coercion_name(args[i]->coercibility), - func_name()); + my_coll_agg_error(collation, args[i]->collation, func_name()); break; } } @@ -622,18 +627,15 @@ void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array, void Item_func_concat_ws::fix_length_and_dec() { - set_charset(separator->charset(),separator->coercibility); + set_charset(*separator); max_length=separator->max_length*(arg_count-1); for (uint i=0 ; i < arg_count ; i++) { max_length+=args[i]->max_length; - if (set_charset(charset(), coercibility, - args[i]->charset(), args[i]->coercibility)) + if (set_charset(charset(), derivation(), + args[i]->charset(), args[i]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - charset()->name,coercion_name(coercibility), - args[i]->charset()->name,coercion_name(args[i]->coercibility), - func_name()); + my_coll_agg_error(collation, args[i]->collation, func_name()); break; } } @@ -702,7 +704,7 @@ String *Item_func_reverse::val_str(String *str) void Item_func_reverse::fix_length_and_dec() { - set_charset(args[0]->charset(),args[0]->coercibility); + set_charset(*args[0]); max_length = args[0]->max_length; } @@ -826,17 +828,14 @@ void Item_func_replace::fix_length_and_dec() max_length=MAX_BLOB_WIDTH; maybe_null=1; } - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); for (i=1; i<3; i++) { - if (set_charset(charset(), coercibility, - args[i]->charset(), args[i]->coercibility)) + if (set_charset(charset(), derivation(), + args[i]->charset(), args[i]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - charset()->name,coercion_name(coercibility), - args[i]->charset()->name,coercion_name(args[i]->coercibility), - func_name()); + my_coll_agg_error(collation, args[i]->collation, func_name()); break; } } @@ -876,13 +875,10 @@ null: void Item_func_insert::fix_length_and_dec() { - if (set_charset(args[0]->charset(), args[0]->coercibility, - args[3]->charset(), args[3]->coercibility)) + if (set_charset(args[0]->charset(), args[0]->derivation(), + args[3]->charset(), args[3]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - args[0]->charset()->name,coercion_name(args[0]->coercibility), - args[3]->charset()->name,coercion_name(args[3]->coercibility), - func_name()); + my_coll_agg_error(args[0]->collation, args[3]->collation, func_name()); } max_length=args[0]->max_length+args[3]->max_length; if (max_length > MAX_BLOB_WIDTH) @@ -963,7 +959,7 @@ void Item_str_func::left_right_max_length() void Item_func_left::fix_length_and_dec() { - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); left_right_max_length(); } @@ -990,7 +986,7 @@ String *Item_func_right::val_str(String *str) void Item_func_right::fix_length_and_dec() { - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); left_right_max_length(); } @@ -1024,7 +1020,7 @@ void Item_func_substr::fix_length_and_dec() { max_length=args[0]->max_length; - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); if (args[1]->const_item()) { int32 start=(int32) args[1]->val_int()-1; @@ -1320,18 +1316,15 @@ void Item_func_trim::fix_length_and_dec() max_length= args[0]->max_length; if (arg_count == 1) { - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); remove.set_charset(charset()); remove.set_ascii(" ",1); } else - if (set_charset(args[1]->charset(), args[1]->coercibility, - args[0]->charset(), args[0]->coercibility)) + if (set_charset(args[1]->charset(), args[1]->derivation(), + args[0]->charset(), args[0]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - args[1]->charset()->name,coercion_name(args[1]->coercibility), - args[0]->charset()->name,coercion_name(args[0]->coercibility), - func_name()); + my_coll_agg_error(args[1]->collation, args[0]->collation, func_name()); } } @@ -1545,7 +1538,7 @@ String *Item_func_user::val_str(String *str) void Item_func_soundex::fix_length_and_dec() { - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); max_length=args[0]->max_length; set_if_bigger(max_length,4); } @@ -1675,16 +1668,13 @@ void Item_func_elt::fix_length_and_dec() set_if_bigger(max_length,args[i]->max_length); set_if_bigger(decimals,args[i]->decimals); if (i == 0) - set_charset(args[i]->charset(),args[i]->coercibility); + set_charset(*args[0]); else { - if (set_charset(charset(), coercibility, - args[i]->charset(), args[i]->coercibility)) + if (set_charset(charset(), derivation(), + args[i]->charset(), args[i]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - charset()->name,coercion_name(coercibility), - args[i]->charset()->name,coercion_name(args[i]->coercibility), - func_name()); + my_coll_agg_error(collation, args[i]->collation, func_name()); break; } } @@ -1780,17 +1770,14 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array, void Item_func_make_set::fix_length_and_dec() { max_length=arg_count-1; - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); for (uint i=0 ; i < arg_count ; i++) { max_length+=args[i]->max_length; - if (set_charset(charset(), coercibility, - args[i]->charset(), args[i]->coercibility)) + if (set_charset(charset(), derivation(), + args[i]->charset(), args[i]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - charset()->name,coercion_name(coercibility), - args[i]->charset()->name,coercion_name(args[i]->coercibility), - func_name()); + my_coll_agg_error(collation, args[i]->collation, func_name()); break; } } @@ -1916,7 +1903,7 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value, void Item_func_repeat::fix_length_and_dec() { - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); if (args[1]->const_item()) { max_length=(long) (args[0]->max_length * args[1]->val_int()); @@ -1976,13 +1963,10 @@ err: void Item_func_rpad::fix_length_and_dec() { - if (set_charset(args[0]->charset(), args[0]->coercibility, - args[2]->charset(), args[2]->coercibility)) + if (set_charset(args[0]->charset(), args[0]->derivation(), + args[2]->charset(), args[2]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - args[0]->charset()->name,coercion_name(args[0]->coercibility), - args[2]->charset()->name,coercion_name(args[2]->coercibility), - func_name()); + my_coll_agg_error(args[0]->collation, args[2]->collation, func_name()); } if (args[1]->const_item()) @@ -2045,13 +2029,10 @@ String *Item_func_rpad::val_str(String *str) void Item_func_lpad::fix_length_and_dec() { - if (set_charset(args[0]->charset(), args[0]->coercibility, - args[2]->charset(), args[2]->coercibility)) + if (set_charset(args[0]->charset(), args[0]->derivation(), + args[2]->charset(), args[2]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - args[0]->charset()->name,coercion_name(args[0]->coercibility), - args[2]->charset()->name,coercion_name(args[2]->coercibility), - func_name()); + my_coll_agg_error(args[0]->collation, args[2]->collation, func_name()); } if (args[1]->const_item()) @@ -2173,7 +2154,7 @@ void Item_func_conv_charset::fix_length_and_dec() { set_charset(conv_charset); max_length = args[0]->max_length*conv_charset->mbmaxlen; - set_charset(conv_charset, COER_IMPLICIT); + set_charset(conv_charset, DERIVATION_IMPLICIT); } @@ -2277,7 +2258,7 @@ void Item_func_set_collation::fix_length_and_dec() colname,args[0]->charset()->csname); return; } - set_charset(set_collation, COER_EXPLICIT); + set_charset(set_collation, DERIVATION_EXPLICIT); max_length= args[0]->max_length; } @@ -2468,16 +2449,13 @@ void Item_func_export_set::fix_length_and_dec() uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63; - set_charset(args[1]->charset(), args[1]->coercibility); + set_charset(*args[1]); for (i=2 ; i < 4 && i < arg_count ; i++) { - if (set_charset(charset(), coercibility, - args[i]->charset(), args[i]->coercibility)) + if (set_charset(charset(), derivation(), + args[i]->charset(), args[i]->derivation())) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), - charset()->name,coercion_name(coercibility), - args[i]->charset()->name,coercion_name(args[i]->coercibility), - func_name()); + my_coll_agg_error(collation, args[i]->collation, func_name()); break; } } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6bb1c510013..3f2860f4b2b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -153,7 +153,7 @@ public: Item_str_conv(Item *item) :Item_str_func(item) {} void fix_length_and_dec() { - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); max_length = args[0]->max_length; } }; @@ -335,7 +335,7 @@ public: class Item_func_database :public Item_str_func { public: - Item_func_database() { coercibility= COER_IMPLICIT; } + Item_func_database() { set_charset(DERIVATION_IMPLICIT); } String *val_str(String *); void fix_length_and_dec() { @@ -348,7 +348,7 @@ public: class Item_func_user :public Item_str_func { public: - Item_func_user() { coercibility= COER_IMPLICIT; } + Item_func_user() { set_charset(DERIVATION_IMPLICIT); } String *val_str(String *); void fix_length_and_dec() { @@ -549,7 +549,7 @@ public: const char *func_name() const { return "load_file"; } void fix_length_and_dec() { - set_charset(&my_charset_bin, COER_COERCIBLE); + set_charset(&my_charset_bin, DERIVATION_COERCIBLE); maybe_null=1; max_length=MAX_BLOB_WIDTH; } @@ -586,7 +586,7 @@ public: String *val_str(String *); void fix_length_and_dec() { - set_charset(args[0]->charset(), args[0]->coercibility); + set_charset(*args[0]); max_length= args[0]->max_length * 2 + 2; } }; diff --git a/sql/log_event.cc b/sql/log_event.cc index 98a877616e0..749732384c7 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2230,7 +2230,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) } Item_func_set_user_var e(user_var_name, it); e.fix_fields(thd, 0, 0); - e.update_hash(val, val_len, type, charset, Item::COER_NOCOLL); + e.update_hash(val, val_len, type, charset, DERIVATION_NONE); free_root(&thd->mem_root,0); rli->inc_event_relay_log_pos(get_event_len()); diff --git a/sql/sql_class.h b/sql/sql_class.h index 33767bc4226..db99fb443c8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -975,8 +975,7 @@ class user_var_entry char *value; ulong length, update_query_id, used_query_id; Item_result type; - CHARSET_INFO *var_charset; - enum Item::coercion var_coercibility; + DTCollation collation; }; /* Class for unique (removing of duplicates) */ From 40654c71f4275c5ec324142a7a640f8ae08e7f54 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jun 2003 15:55:39 +0500 Subject: [PATCH 384/399] mysql_create_system_tables.sh: Type fix scripts/mysql_create_system_tables.sh: Type fix --- scripts/mysql_create_system_tables.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index 1f0579f87c2..a98e1739260 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -153,8 +153,8 @@ then then i_u="$i_u INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user (host,user) values ('$hostname','');" - INSERT INTO user (host,user) values ('localhost',''); + INSERT INTO user (host,user) values ('$hostname',''); + INSERT INTO user (host,user) values ('localhost','');" else i_u="INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);" fi From 3eaf8865ecdb8db3e5bc7c1b59716dfcff79dc92 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jun 2003 17:12:07 +0500 Subject: [PATCH 385/399] String comparison functions now use the same DTCollation with CONCAT() and other string functions. This allows to reuse a lot if code and to simplify further development. --- sql/item.cc | 77 +++++++++++++++---------- sql/item.h | 12 ++-- sql/item_cmpfunc.cc | 135 ++++++++++++-------------------------------- sql/item_cmpfunc.h | 10 ++-- sql/item_func.cc | 5 +- sql/item_strfunc.cc | 50 +++++++--------- 6 files changed, 116 insertions(+), 173 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 4c7b30b0410..950f27c5d69 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -183,44 +183,61 @@ CHARSET_INFO * Item::default_charset() const return current_thd->variables.collation_connection; } -bool Item::set_charset(CHARSET_INFO *cs1, Derivation co1, - CHARSET_INFO *cs2, Derivation co2) +bool DTCollation::aggregate(DTCollation &dt) { - if (cs1 == &my_charset_bin || cs2 == &my_charset_bin) + if (collation == &my_charset_bin || dt.collation == &my_charset_bin) { - set_charset(&my_charset_bin, DERIVATION_NONE); + collation= &my_charset_bin; + derivation= derivation > dt.derivation ? derivation : dt.derivation; return 0; } - - if (!my_charset_same(cs1,cs2)) - return 1; - - if (co1 < co2) + + if (!my_charset_same(collation, dt.collation)) { - set_charset(cs1, co1); - } - else if (co2 < co1) - { - set_charset(cs2, co2); - } - else // co2 == co1 - { - if (cs1 != cs2) + /* + We do allow to use binary strings (like BLOBS) + together with character strings. + Binaries have more precedance + */ + if ((derivation <= dt.derivation) && (collation == &my_charset_bin)) { - if (co1 == DERIVATION_EXPLICIT) - { - return 1; - } - else - { - CHARSET_INFO *bin= get_charset_by_csname(cs1->csname, MY_CS_BINSORT,MYF(0)); - if (!bin) - return 1; - set_charset(bin, DERIVATION_NONE); - } + // Do nothing + } + else if ((dt.derivation <= derivation) && (dt.collation==&my_charset_bin)) + { + set(dt); } else - set_charset(cs2, co2); + { + set(0, DERIVATION_NONE); + return 1; + } + } + else if (derivation < dt.derivation) + { + // Do nothing + } + else if (dt.derivation < derivation) + { + set(dt); + } + else + { + if (collation == dt.collation) + { + // Do nothing + } + else + { + if (derivation == DERIVATION_EXPLICIT) + { + set(0, DERIVATION_NONE); + return 1; + } + CHARSET_INFO *bin= get_charset_by_csname(collation->csname, + MY_CS_BINSORT,MYF(0)); + set(bin, DERIVATION_NONE); + } } return 0; } diff --git a/sql/item.h b/sql/item.h index ce79e70e5d6..e80648b89de 100644 --- a/sql/item.h +++ b/sql/item.h @@ -52,10 +52,10 @@ public: collation= collation_arg; derivation= derivation_arg; } - void set(DTCollation *dt) + void set(DTCollation &dt) { - collation= dt->collation; - derivation= dt->derivation; + collation= dt.collation; + derivation= dt.derivation; } void set(CHARSET_INFO *collation_arg, Derivation derivation_arg) { @@ -66,7 +66,9 @@ public: { collation= collation_arg; } void set(Derivation derivation_arg) { derivation= derivation_arg; } - bool aggregate(DTCollation *dt); + bool aggregate(DTCollation &dt); + bool set(DTCollation &dt1, DTCollation &dt2) + { set(dt1); return aggregate(dt2); } const char *derivation_name() const { switch(derivation) @@ -183,8 +185,6 @@ public: collation.collation= collation_arg->collation; collation.derivation= collation_arg->derivation; } - bool set_charset(CHARSET_INFO *cs1, Derivation dv1, - CHARSET_INFO *cs2, Derivation dv2); bool binary() const { return charset()->state & MY_CS_BINSORT ? 1 : 0 ; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 035f85a45ba..52bd14ed515 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -96,72 +96,26 @@ static bool convert_constant_item(Field *field, Item **item) return 0; } -bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, Derivation co1, - CHARSET_INFO *cs2, Derivation co2) -{ - if (cs1 == &my_charset_bin || cs2 == &my_charset_bin) - { - cmp_charset= &my_charset_bin; - //coercibility= co1 > co2 ? co1 : co2; - return 0; - } - - if (!my_charset_same(cs1, cs2)) - { - /* - We do allow to use BLOBS together with character strings - BLOBS have more precedance - */ - if ((co1 <= co2) && (cs1==&my_charset_bin)) - { - cmp_charset= cs1; - //coercibility= co1; - } - else if ((co2 <= co1) && (cs2==&my_charset_bin)) - { - cmp_charset= cs2; - //coercibility= co2; - } - else - { - cmp_charset= 0; - //coercibility= DERIVATION_NOCOLL; - return 1; - } - } - else if (co1 < co2) - { - cmp_charset= cs1; - //coercibility= co1; - } - else if (co2 < co1) - { - cmp_charset= cs2; - //coercibility= co1; - } - else - { - if (cs1 == cs2) - { - cmp_charset= cs1; - //coercibility= co1; - } - else - { - //coercibility= DERIVATION_NOCOLL; - cmp_charset= 0; - return (co1 == DERIVATION_EXPLICIT) ? 1 : 0; - } - } - return 0; -} - bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables, Item ** ref) { if (Item_int_func::fix_fields(thd, tables, ref)) return 1; + return 0; +} + + +void Item_bool_func2::fix_length_and_dec() +{ + max_length= 1; // Function returns 0 or 1 + + /* + As some compare functions are generated after sql_yacc, + we have to check for out of memory conditions here + */ + if (!args[0] || !args[1]) + return; /* We allow to convert to Unicode character sets in some cases. @@ -209,35 +163,12 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables, else { conv= new Item_func_conv_charset(args[weak],args[strong]->charset()); - //conv->coercibility= args[weak]->derivation(); + conv->collation.set(args[weak]->derivation()); } args[weak]= conv ? conv : args[weak]; - set_cmp_charset(args[0]->charset(), args[0]->derivation(), - args[1]->charset(), args[1]->derivation()); } } - if (!cmp_charset) - { - /* set_cmp_charset() failed */ - my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); - return 1; - } - return 0; -} - - -void Item_bool_func2::fix_length_and_dec() -{ - max_length= 1; // Function returns 0 or 1 - - /* - As some compare functions are generated after sql_yacc, - we have to check for out of memory conditions here - */ - if (!args[0] || !args[1]) - return; - - + // Make a special case of compare with fields to get nicer DATE comparisons if (args[0]->type() == FIELD_ITEM) { @@ -248,7 +179,8 @@ void Item_bool_func2::fix_length_and_dec() { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, INT_RESULT); // Works for all types. - cmp_charset= &my_charset_bin; // For test in fix_fields + cmp_collation.set(&my_charset_bin, + DERIVATION_NONE); // For test in fix_fields return; } } @@ -262,7 +194,8 @@ void Item_bool_func2::fix_length_and_dec() { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, INT_RESULT); // Works for all types. - cmp_charset= &my_charset_bin; // For test in fix_fields + cmp_collation.set(&my_charset_bin, + DERIVATION_NONE); // For test in fix_fields return; } } @@ -272,8 +205,12 @@ void Item_bool_func2::fix_length_and_dec() We must set cmp_charset here as we may be called from for an automatic generated item, like in natural join */ - set_cmp_charset(args[0]->charset(), args[0]->derivation(), - args[1]->charset(), args[1]->derivation()); + if (cmp_collation.set(args[0]->collation, args[1]->collation)) + { + /* set_cmp_charset() failed */ + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); + return; + } } @@ -315,7 +252,7 @@ int Arg_comparator::compare_string() if ((res2= (*b)->val_str(&owner->tmp_value2))) { owner->null_value= 0; - return sortcmp(res1,res2,owner->cmp_charset); + return sortcmp(res1,res2,owner->cmp_collation.collation); } } owner->null_value= 1; @@ -329,7 +266,7 @@ int Arg_comparator::compare_e_string() res2= (*b)->val_str(&owner->tmp_value2); if (!res1 || !res2) return test(res1 == res2); - return test(sortcmp(res1, res2, owner->cmp_charset) == 0); + return test(sortcmp(res1, res2, owner->cmp_collation.collation) == 0); } @@ -558,7 +495,7 @@ longlong Item_func_strcmp::val_int() null_value=1; return 0; } - int value= sortcmp(a,b,cmp_charset); + int value= sortcmp(a,b,cmp_collation.collation); null_value=0; return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1); } @@ -750,8 +687,7 @@ Item_func_ifnull::fix_length_and_dec() args[1]->result_type())) != REAL_RESULT) decimals= 0; - if (set_charset(args[0]->charset(),args[0]->derivation(), - args[1]->charset(),args[1]->derivation())) + if (collation.set(args[0]->collation,args[1]->collation)) my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); } @@ -828,8 +764,7 @@ Item_func_if::fix_length_and_dec() else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT) { cached_result_type = STRING_RESULT; - if (set_charset(args[1]->charset(), args[1]->derivation(), - args[2]->charset(), args[2]->derivation())) + if (collation.set(args[1]->collation, args[2]->collation)) { my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); return; @@ -1944,7 +1879,7 @@ longlong Item_func_like::val_int() null_value=0; if (canDoTurboBM) return turboBM_matches(res->ptr(), res->length()) ? 1 : 0; - return my_wildcmp(cmp_charset, + return my_wildcmp(cmp_collation.collation, res->ptr(),res->ptr()+res->length(), res2->ptr(),res2->ptr()+res2->length(), escape,wild_one,wild_many) ? 0 : 1; @@ -2148,7 +2083,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff) *splm1 = pattern_len; - if (cmp_charset == &my_charset_bin) + if (cmp_collation.collation == &my_charset_bin) { int i; for (i = pattern_len - 2; i >= 0; i--) @@ -2251,7 +2186,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts() for (i = bmBc; i < end; i++) *i = pattern_len; - if (cmp_charset == &my_charset_bin) + if (cmp_collation.collation == &my_charset_bin) { for (j = 0; j < plm1; j++) bmBc[(uint) (uchar) pattern[j]] = plm1 - j; @@ -2282,7 +2217,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const const int tlmpl= text_len - pattern_len; /* Searching */ - if (cmp_charset == &my_charset_bin) + if (cmp_collation.collation == &my_charset_bin) { while (j <= tlmpl) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b38248d87e1..70e477402d9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -112,25 +112,25 @@ class Item_bool_func2 :public Item_int_func protected: Arg_comparator cmp; String tmp_value1,tmp_value2; - CHARSET_INFO *cmp_charset; + DTCollation cmp_collation; public: Item_bool_func2(Item *a,Item *b): - Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), cmp_charset(0) {} + Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) + { cmp_collation.set(0,DERIVATION_NONE);} bool fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref); void fix_length_and_dec(); void set_cmp_func() { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1); } - bool set_cmp_charset(CHARSET_INFO *cs1, Derivation co1, - CHARSET_INFO *cs2, Derivation co2); optimize_type select_optimize() const { return OPTIMIZE_OP; } virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } void print(String *str) { Item_func::print_op(str); } bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } - virtual bool binary() const { return test(cmp_charset->state & MY_CS_BINSORT); } + virtual bool binary() const + { return test(cmp_collation.collation->state & MY_CS_BINSORT); } static Item_bool_func2* eq_creator(Item *a, Item *b); static Item_bool_func2* ne_creator(Item *a, Item *b); diff --git a/sql/item_func.cc b/sql/item_func.cc index 170260c6819..d0362ea9369 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -867,9 +867,8 @@ void Item_func_min_max::fix_length_and_dec() maybe_null=0; cmp_type=item_cmp_type(cmp_type,args[i]->result_type()); if (i==0) - set_charset(*args[i]); - else if (set_charset(charset(), derivation(), - args[i]->charset(), args[i]->derivation())) + collation.set(args[0]->collation); + if (collation.aggregate(args[i]->collation)) { my_coll_agg_error(collation, args[i]->collation, func_name()); break; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 23df49c81be..1c770456793 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -324,12 +324,11 @@ void Item_func_concat::fix_length_and_dec() bool first_coll= 1; max_length=0; - set_charset(*args[0]); + collation.set(args[0]->collation); for (uint i=0 ; i < arg_count ; i++) { max_length+=args[i]->max_length; - if (set_charset(charset(), derivation(), - args[i]->charset(), args[i]->derivation())) + if (collation.aggregate(args[i]->collation)) { my_coll_agg_error(collation, args[i]->collation, func_name()); break; @@ -627,13 +626,12 @@ void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array, void Item_func_concat_ws::fix_length_and_dec() { - set_charset(*separator); + collation.set(separator->collation); max_length=separator->max_length*(arg_count-1); for (uint i=0 ; i < arg_count ; i++) { max_length+=args[i]->max_length; - if (set_charset(charset(), derivation(), - args[i]->charset(), args[i]->derivation())) + if (collation.aggregate(args[i]->collation)) { my_coll_agg_error(collation, args[i]->collation, func_name()); break; @@ -828,12 +826,11 @@ void Item_func_replace::fix_length_and_dec() max_length=MAX_BLOB_WIDTH; maybe_null=1; } - set_charset(*args[0]); + collation.set(args[0]->collation); for (i=1; i<3; i++) { - if (set_charset(charset(), derivation(), - args[i]->charset(), args[i]->derivation())) + if (collation.aggregate(args[i]->collation)) { my_coll_agg_error(collation, args[i]->collation, func_name()); break; @@ -875,10 +872,10 @@ null: void Item_func_insert::fix_length_and_dec() { - if (set_charset(args[0]->charset(), args[0]->derivation(), - args[3]->charset(), args[3]->derivation())) + if (collation.set(args[0]->collation, args[3]->collation)) { my_coll_agg_error(args[0]->collation, args[3]->collation, func_name()); + return; } max_length=args[0]->max_length+args[3]->max_length; if (max_length > MAX_BLOB_WIDTH) @@ -1316,13 +1313,12 @@ void Item_func_trim::fix_length_and_dec() max_length= args[0]->max_length; if (arg_count == 1) { - set_charset(*args[0]); + collation.set(args[0]->collation); remove.set_charset(charset()); remove.set_ascii(" ",1); } else - if (set_charset(args[1]->charset(), args[1]->derivation(), - args[0]->charset(), args[0]->derivation())) + if (collation.set(args[1]->collation, args[0]->collation)) { my_coll_agg_error(args[1]->collation, args[0]->collation, func_name()); } @@ -1668,11 +1664,10 @@ void Item_func_elt::fix_length_and_dec() set_if_bigger(max_length,args[i]->max_length); set_if_bigger(decimals,args[i]->decimals); if (i == 0) - set_charset(*args[0]); + collation.set(args[0]->collation); else { - if (set_charset(charset(), derivation(), - args[i]->charset(), args[i]->derivation())) + if (collation.aggregate(args[i]->collation)) { my_coll_agg_error(collation, args[i]->collation, func_name()); break; @@ -1770,12 +1765,11 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array, void Item_func_make_set::fix_length_and_dec() { max_length=arg_count-1; - set_charset(*args[0]); + collation.set(args[0]->collation); for (uint i=0 ; i < arg_count ; i++) { max_length+=args[i]->max_length; - if (set_charset(charset(), derivation(), - args[i]->charset(), args[i]->derivation())) + if (collation.aggregate(args[i]->collation)) { my_coll_agg_error(collation, args[i]->collation, func_name()); break; @@ -1963,10 +1957,10 @@ err: void Item_func_rpad::fix_length_and_dec() { - if (set_charset(args[0]->charset(), args[0]->derivation(), - args[2]->charset(), args[2]->derivation())) + if (collation.set(args[0]->collation, args[2]->collation)) { my_coll_agg_error(args[0]->collation, args[2]->collation, func_name()); + return; } if (args[1]->const_item()) @@ -2029,10 +2023,10 @@ String *Item_func_rpad::val_str(String *str) void Item_func_lpad::fix_length_and_dec() { - if (set_charset(args[0]->charset(), args[0]->derivation(), - args[2]->charset(), args[2]->derivation())) + if (collation.set(args[0]->collation, args[2]->collation)) { my_coll_agg_error(args[0]->collation, args[2]->collation, func_name()); + return; } if (args[1]->const_item()) @@ -2152,9 +2146,8 @@ String *Item_func_conv_charset::val_str(String *str) void Item_func_conv_charset::fix_length_and_dec() { - set_charset(conv_charset); - max_length = args[0]->max_length*conv_charset->mbmaxlen; set_charset(conv_charset, DERIVATION_IMPLICIT); + max_length = args[0]->max_length*conv_charset->mbmaxlen; } @@ -2449,11 +2442,10 @@ void Item_func_export_set::fix_length_and_dec() uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63; - set_charset(*args[1]); + collation.set(args[1]->collation); for (i=2 ; i < 4 && i < arg_count ; i++) { - if (set_charset(charset(), derivation(), - args[i]->charset(), args[i]->derivation())) + if (collation.aggregate(args[i]->collation)) { my_coll_agg_error(collation, args[i]->collation, func_name()); break; From 4ccada56f13de8bd27b2fa3d7e7601a05e403758 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jun 2003 10:43:57 -0700 Subject: [PATCH 386/399] test for SQL_MODE with PIPES_AS_CONCAT, ANSI and IGNORE_SPACE tests/client_test.c: test for SQL_MODE with PIPES_AS_CONCAT, ANSI and IGNORE_SPACE --- tests/client_test.c | 139 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 4 deletions(-) diff --git a/tests/client_test.c b/tests/client_test.c index d22aa900a4e..2741da1bbba 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -7327,6 +7327,136 @@ static void test_free_store_result() mysql_stmt_close(stmt); } +/******************************************************** + To test SQLmode +*********************************************************/ + +static void test_sqlmode() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[2]; + char c1[5], c2[5]; + int rc; + + myheader("test_sqlmode"); + + rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_piping"); + myquery(rc); + + rc = mysql_commit(mysql); + myquery(rc); + + rc = mysql_query(mysql,"CREATE TABLE test_piping(name varchar(10))"); + myquery(rc); + + /* PIPES_AS_CONCAT */ + strcpy(query,"SET SQL_MODE=\"PIPES_AS_CONCAT\""); + fprintf(stdout,"\n With %s", query); + rc = mysql_query(mysql,query); + myquery(rc); + + strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); + fprintf(stdout,"\n query: %s", query); + stmt = mysql_prepare(mysql, query, strlen(query)); + mystmt_init(stmt); + + fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt)); + + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (char *)c1; + bind[0].buffer_length= 2; + bind[0].is_null= 0; + bind[0].length= 0; + + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= (char *)c2; + bind[1].buffer_length= 3; + bind[1].is_null= 0; + bind[1].length= 0; + + rc = mysql_bind_param(stmt, bind); + mystmt(stmt,rc); + + strcpy(c1,"My"); strcpy(c2, "SQL"); + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + mysql_stmt_close(stmt); + verify_col_data("test_piping","name","MySQL"); + + rc = mysql_query(mysql,"DELETE FROM test_piping"); + myquery(rc); + + strcpy(query, "SELECT connection_id ()"); + fprintf(stdout,"\n query: %s", query); + stmt = mysql_prepare(mysql, query, 70); + mystmt_init_r(stmt); + + /* ANSI */ + strcpy(query,"SET SQL_MODE=\"ANSI\""); + fprintf(stdout,"\n With %s", query); + rc = mysql_query(mysql,query); + myquery(rc); + + strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); + fprintf(stdout,"\n query: %s", query); + stmt = mysql_prepare(mysql, query, strlen(query)); + mystmt_init(stmt); + fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt)); + + rc = mysql_bind_param(stmt, bind); + mystmt(stmt,rc); + + strcpy(c1,"My"); strcpy(c2, "SQL"); + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + mysql_stmt_close(stmt); + verify_col_data("test_piping","name","MySQL"); + + /* ANSI mode spaces ... */ + strcpy(query, "SELECT connection_id ()"); + fprintf(stdout,"\n query: %s", query); + stmt = mysql_prepare(mysql, query, 70); + mystmt_init(stmt); + + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + myassert(rc == MYSQL_NO_DATA); + fprintf(stdout,"\n returned 1 row\n"); + + mysql_stmt_close(stmt); + + /* IGNORE SPACE MODE */ + strcpy(query,"SET SQL_MODE=\"IGNORE_SPACE\""); + fprintf(stdout,"\n With %s", query); + rc = mysql_query(mysql,query); + myquery(rc); + + strcpy(query, "SELECT connection_id ()"); + fprintf(stdout,"\n query: %s", query); + stmt = mysql_prepare(mysql, query, 70); + mystmt_init(stmt); + + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch(stmt); + myassert(rc == MYSQL_NO_DATA); + fprintf(stdout,"\n returned 1 row"); + + mysql_stmt_close(stmt); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -7467,10 +7597,6 @@ int main(int argc, char **argv) start_time= time((time_t *)0); client_query(); /* simple client query test */ - test_mem_overun(); - test_list_fields(); - test_fetch_offset(); /* to test mysql_fetch_column with offset */ - test_fetch_column(); /* to test mysql_fetch_column */ #if NOT_YET_WORKING /* Used for internal new development debugging */ test_drop_temp(); /* to test DROP TEMPORARY TABLE Access checks */ @@ -7572,6 +7698,11 @@ int main(int argc, char **argv) test_free_result(); /* test mysql_stmt_free_result() */ test_free_store_result(); /* test to make sure stmt results are cleared during stmt_free_result() */ + test_mem_overun(); /* memory ovverun bug */ + test_list_fields(); /* list_fields test */ + test_fetch_offset(); /* to test mysql_fetch_column with offset */ + test_fetch_column(); /* to test mysql_fetch_column */ + test_sqlmode(); /* test for SQL_MODE */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); From 15ee7b04daeefdb5010efed309ff412d43f88fa5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Jun 2003 15:07:20 +0500 Subject: [PATCH 387/399] LOCATE(), INSTR(), POSITION(), FIND_IN_SET(), SUBSTRING_INDEX() now process arguments according to standard SQL collation determation rules. --- mysql-test/r/func_str.result | 27 +++++++++++++++++++++++++++ mysql-test/t/func_str.test | 27 +++++++++++++++++++++++++++ sql/item_func.cc | 20 +++++++++++++++----- sql/item_func.h | 9 +++------ sql/item_strfunc.cc | 11 +++++++++++ sql/item_strfunc.h | 2 +- 6 files changed, 84 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 6ee452764c2..96c23ab1e22 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -249,6 +249,33 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf'); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); 1 DROP TABLE t1; +select POSITION(_latin1'B' IN _latin1'abcd'); +POSITION(_latin1'B' IN _latin1'abcd') +2 +select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin); +POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin) +0 +select POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd'); +POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd') +0 +select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE latin1_bin); +ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_general_ci,EXPLICIT) for operation 'locate' +select POSITION(_latin1'B' IN _latin2'abcd'); +ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'locate' +select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d'); +FIND_IN_SET(_latin1'B',_latin1'a,b,c,d') +2 +select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin); +ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'find_in_set' +select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d'); +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'find_in_set' +select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2); +SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2) +abcdabc +select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2); +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index' +select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2); +ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index' select collation(bin(130)), coercibility(bin(130)); collation(bin(130)) coercibility(bin(130)) latin1_swedish_ci 3 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 83d49743a4a..7e6d2648e1e 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -136,6 +136,33 @@ DROP TABLE t1; # # Test collation and coercibility # +select POSITION(_latin1'B' IN _latin1'abcd'); +select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin); +select POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd'); +--error 1265 +select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE latin1_bin); +--error 1265 +select POSITION(_latin1'B' IN _latin2'abcd'); + +select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d'); +--fix this: +--select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d' COLLATE latin1_bin); +--select FIND_IN_SET(_latin1'B' COLLATE latin1_bin,_latin1'a,b,c,d'); +--error 1265 +select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin); +--error 1265 +select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d'); + +select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2); +--fix this: +--select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_bin,_latin1'd',2); +--select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd' COLLATE latin1_bin,2); +--error 1265 +select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2); +--error 1265 +select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2); + + select collation(bin(130)), coercibility(bin(130)); select collation(oct(130)), coercibility(oct(130)); select collation(conv(130,16,10)), coercibility(conv(130,16,10)); diff --git a/sql/item_func.cc b/sql/item_func.cc index d0362ea9369..dc979cea2f8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1045,10 +1045,18 @@ longlong Item_func_coercibility::val_int() return (longlong) args[0]->derivation(); } +void Item_func_locate::fix_length_and_dec() +{ + maybe_null=0; max_length=11; + if (cmp_collation.set(args[0]->collation, args[1]->collation)) + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); +} + longlong Item_func_locate::val_int() { String *a=args[0]->val_str(&value1); String *b=args[1]->val_str(&value2); + bool binary_cmp= (cmp_collation.collation->state & MY_CS_BINSORT) ? 1 : 0; if (!a || !b) { null_value=1; @@ -1063,7 +1071,7 @@ longlong Item_func_locate::val_int() { start=(uint) args[2]->val_int()-1; #ifdef USE_MB - if (use_mb(a->charset())) + if (use_mb(cmp_collation.collation)) { start0=start; if (!binary_cmp) @@ -1076,7 +1084,7 @@ longlong Item_func_locate::val_int() if (!b->length()) // Found empty string at start return (longlong) (start+1); #ifdef USE_MB - if (use_mb(a->charset()) && !binary_cmp) + if (use_mb(cmp_collation.collation) && !binary_cmp) { const char *ptr=a->ptr()+start; const char *search=b->ptr(); @@ -1095,7 +1103,7 @@ longlong Item_func_locate::val_int() return (longlong) start0+1; } skipp: - if ((l=my_ismbchar(a->charset(),ptr,strend))) + if ((l=my_ismbchar(cmp_collation.collation,ptr,strend))) ptr+=l; else ++ptr; ++start0; @@ -1201,6 +1209,8 @@ void Item_func_find_in_set::fix_length_and_dec() } } } + if (cmp_collation.set(args[0]->collation, args[1]->collation)) + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); } static const char separator=','; @@ -1228,7 +1238,6 @@ longlong Item_func_find_in_set::val_int() null_value=0; int diff; - CHARSET_INFO *charset= find->charset(); if ((diff=buffer->length() - find->length()) >= 0) { const char *f_pos=find->ptr(); @@ -1242,7 +1251,8 @@ longlong Item_func_find_in_set::val_int() const char *pos= f_pos; while (pos != f_end) { - if (my_toupper(charset,*str) != my_toupper(charset,*pos)) + if (my_toupper(cmp_collation.collation,*str) != + my_toupper(cmp_collation.collation,*pos)) goto not_found; str++; pos++; diff --git a/sql/item_func.h b/sql/item_func.h index 4e39833c467..9ba5bea8b87 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -610,17 +610,13 @@ public: class Item_func_locate :public Item_int_func { String value1,value2; - bool binary_cmp; + DTCollation cmp_collation; public: Item_func_locate(Item *a,Item *b) :Item_int_func(a,b) {} Item_func_locate(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {} const char *func_name() const { return "locate"; } longlong val_int(); - void fix_length_and_dec() - { - maybe_null=0; max_length=11; - binary_cmp = args[0]->binary() || args[1]->binary(); - } + void fix_length_and_dec(); }; @@ -684,6 +680,7 @@ class Item_func_find_in_set :public Item_int_func String value,value2; uint enum_value; ulonglong enum_bit; + DTCollation cmp_collation; public: Item_func_find_in_set(Item *a,Item *b) :Item_int_func(a,b),enum_value(0) {} longlong val_int(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1c770456793..a57800c89d1 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1037,6 +1037,15 @@ void Item_func_substr::fix_length_and_dec() } +void Item_func_substr_index::fix_length_and_dec() +{ + max_length= args[0]->max_length; + if (collation.set(args[0]->collation, args[1]->collation) || + (collation.derivation == DERIVATION_NONE)) + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); +} + + String *Item_func_substr_index::val_str(String *str) { String *res =args[0]->val_str(str); @@ -1054,6 +1063,8 @@ String *Item_func_substr_index::val_str(String *str) if (!res->length() || !delimeter_length || !count) return &empty_string; // Wrong parameters + res->set_charset(collation.collation); + #ifdef USE_MB if (use_mb(res->charset())) { diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 3f2860f4b2b..6cc6d730627 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -215,7 +215,7 @@ class Item_func_substr_index :public Item_str_func public: Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {} String *val_str(String *); - void fix_length_and_dec() { max_length= args[0]->max_length; } + void fix_length_and_dec(); const char *func_name() const { return "substr_index"; } }; From 3187d1832b22b9ed10acd862bf1271a5ce91d669 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Jun 2003 16:51:00 +0300 Subject: [PATCH 388/399] fixed mistyping (BUG #699) --- sql/sql_select.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b8eb9e19cc7..cc80f80739b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1227,7 +1227,7 @@ JOIN::exec() { // Some tables may have been const curr_join->tmp_having->update_used_tables(); - JOIN_TAB *table= &curr_join->join_tab[const_tables]; + JOIN_TAB *table= &curr_join->join_tab[curr_join->const_tables]; table_map used_tables= curr_join->const_table_map | table->table->map; Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having, @@ -1263,7 +1263,7 @@ JOIN::exec() We can abort sorting after thd->select_limit rows if we there is no WHERE clause for any tables after the sorted one. */ - JOIN_TAB *table= &curr_join->join_tab[const_tables+1]; + JOIN_TAB *table= &curr_join->join_tab[curr_join->const_tables+1]; JOIN_TAB *end_table= &curr_join->join_tab[tables]; for (; table < end_table ; table++) { From 2534f837c177eda645ec45864b58fa5b44b1c083 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Jun 2003 19:50:27 +0500 Subject: [PATCH 389/399] item_func.cc: My stupid typo fix sql/item_func.cc: My stupid typo fix , --- sql/item_func.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index dc979cea2f8..cabffdfc7c2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2023,7 +2023,7 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length, my_free(entry->value,MYF(0)); entry->value=0; entry->length=0; - collation.set(cs, dv); + entry->collation.set(cs, dv); } else { From 774e3a594b94c16e4f9eb474abeae33849c8b077 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Jun 2003 16:25:03 -0500 Subject: [PATCH 390/399] modify error message --- 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/polish/errmsg.txt | 2 +- sql/share/portuguese/errmsg.txt | 2 +- sql/share/romanian/errmsg.txt | 2 +- sql/share/russian/errmsg.txt | 2 +- sql/share/serbian/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 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 273dfa0fcf5..b08e52fb745 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -259,7 +259,7 @@ v/* "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 1d39a328154..ad5afb5c5f1 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -253,7 +253,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 5b79f06b621..75092f8a28f 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -261,7 +261,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index f15e063c487..5f30141fa34 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -250,7 +250,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s" -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" +"Client does not support authentication protocol requested by server; consider upgrading MySQL client" "All parts of a SPATIAL KEY must be NOT NULL" "COLLATION '%s' is not valid for CHARACTER SET '%s'" "The slave was already running" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 506b5fc0188..6c2ff6af902 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -255,7 +255,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 8882e4dceda..029bb06c295 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -250,7 +250,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 1e8f5bb2c05..29dd448ea1c 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -259,7 +259,7 @@ "Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden.", "Select %u wurde während der Optimierung reduziert.", "Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde kann nicht in %-.32s verwendet werden", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index d322f3fbd6a..ee173d890f4 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -250,7 +250,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 162bfc5509c..52ce503dd22 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -252,7 +252,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 26d916a968d..5e6ded532bb 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -250,7 +250,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index a01a2b7ff6f..d5cff6baad1 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -252,7 +252,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 5f5526be04b..d0354e40c19 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -250,7 +250,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index bf1019d3d87..940f4144a94 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -252,7 +252,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 68c95bbf22b..2c9e5ff58a9 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -252,7 +252,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 5b93403c757..3f6b0a5e0c5 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -254,7 +254,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index edd3e3b813f..acb461163f8 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -250,7 +250,7 @@ "Cada tabela derivada deve ter seu próprio alias", "Select %u foi reduzido durante otimização", "Tabela '%-.64s' de um dos SELECT's não pode ser usada em %-.32s", -"Cliente não suporta o protocolo de autenticação exigido pelo servidor. Considere a atualização deo cliente MySQL", +"Cliente não suporta o protocolo de autenticação exigido pelo servidor; considere a atualização deo cliente MySQL", "Todas as partes de uma SPATIAL KEY devem ser NOT NULL", "COLLATION '%s' não é válida para CHARACTER SET '%s'", "O slave já está rodando", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 873a708fa7b..ed90efd8445 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -254,7 +254,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index a05ecde6808..45a52690c00 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -252,7 +252,7 @@ "Every derived table must have it's own alias", "Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index c1c0de779c7..3acf3553501 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -246,7 +246,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 26d673b847c..fb34c8841a3 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -258,7 +258,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 99a92f63c4e..dd9ad6fe499 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -251,7 +251,7 @@ "Every derived table must have it's own alias", "Select %u was reduced during optimisation", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index c613d205947..65482ed7d42 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -250,7 +250,7 @@ "Varje 'derived table' måste ha sitt eget alias", "Select %u reducerades vid optimiering", "Tabell '%-.64s' från en SELECT kan inte användas i %-.32s", -"Klienten stöder inte autentiseringsprotokollet som begärts av servern. Överväg uppgradering av klientprogrammet.", +"Klienten stöder inte autentiseringsprotokollet som begärts av servern; överväg uppgradering av klientprogrammet.", "Alla delar av en SPATIAL KEY måste vara NOT NULL", "COLLATION '%s' är inte tillåtet för CHARACTER SET '%s'", "Slaven har redan startat", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 6505c3c9cac..5effbba170a 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -255,7 +255,7 @@ "Every derived table must have it's own alias", "Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii", "Table '%-.64s' from one of SELECT's can not be used in %-.32s", -"Client does not support authentication protocol requested by server. Consider upgrading MySQL client", +"Client does not support authentication protocol requested by server; consider upgrading MySQL client", "All parts of a SPATIAL KEY must be NOT NULL", "COLLATION '%s' is not valid for CHARACTER SET '%s'", "The slave was already running", From 11e9c572ad1d81536902dd01d48c68ef00ce9018 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jun 2003 09:39:23 +0500 Subject: [PATCH 391/399] Bug fixed: mysql-test failure on rpl tests scripts/mysql_create_system_tables.sh: Fixed bug: mysql-test failure on rpl tests --- scripts/mysql_create_system_tables.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index a98e1739260..2739c45e750 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -145,6 +145,7 @@ then then i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); + REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user (host,user) values ('localhost',''); INSERT INTO user (host,user) values ('$hostname','');" else From 1d29092e2dded4d0081932759944de0e5ea3c2a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jun 2003 15:45:04 +0500 Subject: [PATCH 392/399] New messages for 3-adic and N-adic operations REPLACE() now processed arguments collations according to standard --- include/mysqld_error.h | 6 ++++-- sql/item_cmpfunc.cc | 20 ++++++++++++------- sql/item_cmpfunc.h | 2 +- sql/item_func.cc | 2 +- sql/item_strfunc.cc | 32 ++++++++++++++++++++----------- 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/polish/errmsg.txt | 2 ++ sql/share/portuguese/errmsg.txt | 2 ++ sql/share/romanian/errmsg.txt | 2 ++ sql/share/russian/errmsg.txt | 2 ++ sql/share/serbian/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 ++ 28 files changed, 86 insertions(+), 22 deletions(-) diff --git a/include/mysqld_error.h b/include/mysqld_error.h index ccccb188037..565c2812c50 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -281,7 +281,9 @@ #define ER_WARN_DATA_OUT_OF_RANGE 1262 #define ER_WARN_DATA_TRUNCATED 1263 #define ER_WARN_USING_OTHER_HANDLER 1264 -#define ER_CANT_AGGREGATE_COLLATIONS 1265 +#define ER_CANT_AGGREGATE_2COLLATIONS 1265 #define ER_DROP_USER 1266 #define ER_REVOKE_GRANTS 1267 -#define ER_ERROR_MESSAGES 266 +#define ER_CANT_AGGREGATE_3COLLATIONS 1268 +#define ER_CANT_AGGREGATE_NCOLLATIONS 1269 +#define ER_ERROR_MESSAGES 270 diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 52bd14ed515..ca3f55a9804 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -26,7 +26,7 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), c1.collation->name,c1.derivation_name(), c2.collation->name,c2.derivation_name(), fname); @@ -1968,7 +1968,12 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; max_length= 1; decimals= 0; - binary_cmp= (args[0]->binary() || args[1]->binary()); + + if (cmp_collation.set(args[0]->collation, args[1]->collation)) + { + my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); + return 1; + } used_tables_cache=args[0]->used_tables() | args[1]->used_tables(); const_item_cache=args[0]->const_item() && args[1]->const_item(); @@ -1984,9 +1989,10 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } int error; if ((error=regcomp(&preg,res->c_ptr(), - binary_cmp ? REG_EXTENDED | REG_NOSUB : + (cmp_collation.collation->state & MY_CS_BINSORT) ? + REG_EXTENDED | REG_NOSUB : REG_EXTENDED | REG_NOSUB | REG_ICASE, - res->charset()))) + cmp_collation.collation))) { (void) regerror(error,&preg,buff,sizeof(buff)); my_printf_error(ER_REGEXP_ERROR,ER(ER_REGEXP_ERROR),MYF(0),buff); @@ -2033,10 +2039,10 @@ longlong Item_func_regex::val_int() regex_compiled=0; } if (regcomp(&preg,res2->c_ptr(), - binary_cmp ? REG_EXTENDED | REG_NOSUB : + (cmp_collation.collation->state & MY_CS_BINSORT) ? + REG_EXTENDED | REG_NOSUB : REG_EXTENDED | REG_NOSUB | REG_ICASE, - res->charset())) - + cmp_collation.collation)) { null_value=1; return 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 70e477402d9..1221e316a72 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -747,7 +747,7 @@ class Item_func_regex :public Item_bool_func bool regex_compiled; bool regex_is_const; String prev_regexp; - bool binary_cmp; + DTCollation cmp_collation; public: Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b), regex_compiled(0),regex_is_const(0) {} diff --git a/sql/item_func.cc b/sql/item_func.cc index cabffdfc7c2..d7237f55522 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -33,7 +33,7 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), c1.collation->name,c1.derivation_name(), c2.collation->name,c2.derivation_name(), fname); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a57800c89d1..ae63ac85d4d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -38,12 +38,24 @@ String empty_string("",default_charset_info); static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { - my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0), + my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), c1.collation->name,c1.derivation_name(), c2.collation->name,c2.derivation_name(), fname); } +static void my_coll_agg3_error(DTCollation &c1, + DTCollation &c2, + DTCollation &c3, + const char *fname) +{ + my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + c3.collation->name,c3.derivation_name(), + fname); +} + uint nr_of_decimals(const char *str) { if ((str=strchr(str,'.'))) @@ -733,6 +745,8 @@ String *Item_func_replace::val_str(String *str) if (args[1]->null_value) goto null; + res->set_charset(collation.collation); + #ifdef USE_MB binary_cmp = (args[0]->binary() || args[1]->binary() || !use_mb(res->charset())); #endif @@ -813,7 +827,6 @@ null: void Item_func_replace::fix_length_and_dec() { - uint i; max_length=args[0]->max_length; int diff=(int) (args[2]->max_length - args[1]->max_length); if (diff > 0 && args[1]->max_length) @@ -828,14 +841,12 @@ void Item_func_replace::fix_length_and_dec() } collation.set(args[0]->collation); - for (i=1; i<3; i++) - { - if (collation.aggregate(args[i]->collation)) - { - my_coll_agg_error(collation, args[i]->collation, func_name()); - break; - } - } + if (!collation.aggregate(args[1]->collation)) + collation.aggregate(args[2]->collation); + + if (collation.derivation == DERIVATION_NONE) + my_coll_agg3_error(args[0]->collation, args[1]->collation, + args[2]->collation, func_name()); } @@ -931,7 +942,6 @@ String *Item_func_left::val_str(String *str) if (!res->alloced_length()) { // Don't change const str str_value= *res; // Not malloced string - set_charset(res->charset()); res= &str_value; } res->length((uint) length); diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 273dfa0fcf5..190d208a033 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -273,3 +273,5 @@ v/* "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 1d39a328154..909f69617a0 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -267,3 +267,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 5b79f06b621..8d8da1840fb 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -275,3 +275,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index f15e063c487..9e22377ce77 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -269,3 +269,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 506b5fc0188..c3b5fa7a2ec 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -269,3 +269,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 8882e4dceda..6c34663021c 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -264,3 +264,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 1e8f5bb2c05..2741d1e5a25 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -273,3 +273,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index d322f3fbd6a..b643e465846 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -264,3 +264,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 162bfc5509c..86fbb4dce6f 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -266,3 +266,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 26d916a968d..71c5d7f2c95 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -264,3 +264,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index a01a2b7ff6f..a9aa0747a59 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -266,3 +266,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 5f5526be04b..a6cf0a35dd0 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -264,3 +264,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index bf1019d3d87..062fd8dd8f7 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -266,3 +266,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 68c95bbf22b..d5268237ee4 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -266,3 +266,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 5b93403c757..e6861f7f8bb 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -268,3 +268,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index edd3e3b813f..f389084514b 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -264,3 +264,5 @@ "Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 873a708fa7b..32b0e0bcd03 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -268,3 +268,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index a05ecde6808..d8c5cac08d5 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -266,3 +266,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index c1c0de779c7..40a2e4cac95 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -260,3 +260,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 26d673b847c..9f3cc7ce877 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -272,3 +272,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 99a92f63c4e..56d246b9032 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -265,3 +265,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index c613d205947..84b648f5eca 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -264,3 +264,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 6505c3c9cac..1d46b125c8c 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -269,3 +269,5 @@ "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", "Can't drop one or more of the requested users" "Can't revoke all privileges, grant for one or more of the requested users" +"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", +"Illegal mix of collations for operation '%s'", From 3f810d0e906be42faeb407d1da140977725745af Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jun 2003 12:02:08 +0500 Subject: [PATCH 393/399] BETWEEN now works according to collation rules --- mysql-test/r/func_str.result | 20 +++++++++++++++++++ mysql-test/t/func_str.test | 12 ++++++++++++ sql/item_cmpfunc.cc | 38 +++++++++++++++++++++++++++--------- sql/item_cmpfunc.h | 2 +- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 96c23ab1e22..959cedeeb0d 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -276,6 +276,26 @@ select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2); ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index' select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2); ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index' +select _latin1'B' between _latin1'a' and _latin1'c'; +_latin1'B' between _latin1'a' and _latin1'c' +1 +select _latin1'B' collate latin1_bin between _latin1'a' and _latin1'c'; +_latin1'B' collate latin1_bin between _latin1'a' and _latin1'c' +0 +select _latin1'B' between _latin1'a' collate latin1_bin and _latin1'c'; +_latin1'B' between _latin1'a' collate latin1_bin and _latin1'c' +0 +select _latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin; +_latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin +0 +select _latin2'B' between _latin1'a' and _latin1'b'; +ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'between' +select _latin1'B' between _latin2'a' and _latin1'b'; +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'between' +select _latin1'B' between _latin1'a' and _latin2'b'; +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation 'between' +select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b'; +ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation 'between' select collation(bin(130)), coercibility(bin(130)); collation(bin(130)) coercibility(bin(130)) latin1_swedish_ci 3 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 7e6d2648e1e..41a37c0f7ab 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -162,6 +162,18 @@ select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2); --error 1265 select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2); +select _latin1'B' between _latin1'a' and _latin1'c'; +select _latin1'B' collate latin1_bin between _latin1'a' and _latin1'c'; +select _latin1'B' between _latin1'a' collate latin1_bin and _latin1'c'; +select _latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin; +--error 1268 +select _latin2'B' between _latin1'a' and _latin1'b'; +--error 1268 +select _latin1'B' between _latin2'a' and _latin1'b'; +--error 1268 +select _latin1'B' between _latin1'a' and _latin2'b'; +--error 1268 +select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b'; select collation(bin(130)), coercibility(bin(130)); select collation(oct(130)), coercibility(oct(130)); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ca3f55a9804..b764bb322d3 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -32,6 +32,18 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fnam fname); } +static void my_coll_agg3_error(DTCollation &c1, + DTCollation &c2, + DTCollation &c3, + const char *fname) +{ + my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + c3.collation->name,c3.derivation_name(), + fname); +} + Item_bool_func2* Item_bool_func2::eq_creator(Item *a, Item *b) { return new Item_func_eq(a, b); @@ -575,11 +587,19 @@ void Item_func_between::fix_length_and_dec() cmp_type=item_cmp_type(args[0]->result_type(), item_cmp_type(args[1]->result_type(), args[2]->result_type())); - /* QQ: COERCIBILITY */ - if (args[0]->binary() | args[1]->binary() | args[2]->binary()) - cmp_charset= &my_charset_bin; - else - cmp_charset= args[0]->charset(); + + if (cmp_type == STRING_RESULT) + { + cmp_collation.set(args[0]->collation); + if (!cmp_collation.aggregate(args[1]->collation)) + cmp_collation.aggregate(args[2]->collation); + if (cmp_collation.derivation == DERIVATION_NONE) + { + my_coll_agg3_error(args[0]->collation, args[1]->collation, + args[2]->collation, func_name()); + return; + } + } /* Make a special case of compare with date/time and longlong fields. @@ -611,17 +631,17 @@ longlong Item_func_between::val_int() a=args[1]->val_str(&value1); b=args[2]->val_str(&value2); if (!args[1]->null_value && !args[2]->null_value) - return (sortcmp(value,a,cmp_charset) >= 0 && - sortcmp(value,b,cmp_charset) <= 0) ? 1 : 0; + return (sortcmp(value,a,cmp_collation.collation) >= 0 && + sortcmp(value,b,cmp_collation.collation) <= 0) ? 1 : 0; if (args[1]->null_value && args[2]->null_value) null_value=1; else if (args[1]->null_value) { - null_value= sortcmp(value,b,cmp_charset) <= 0; // not null if false range. + null_value= sortcmp(value,b,cmp_collation.collation) <= 0; // not null if false range. } else { - null_value= sortcmp(value,a,cmp_charset) >= 0; // not null if false range. + null_value= sortcmp(value,a,cmp_collation.collation) >= 0; // not null if false range. } } else if (cmp_type == INT_RESULT) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 1221e316a72..792f2e2411c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -245,7 +245,7 @@ public: class Item_func_between :public Item_int_func { - CHARSET_INFO *cmp_charset; + DTCollation cmp_collation; public: Item_result cmp_type; String value0,value1,value2; From 4a03f6057191d268d5b24a3f7197051e57d9968e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jun 2003 10:07:22 +0200 Subject: [PATCH 394/399] - fixed typo (dbl -> dnl) in acinclude.m4 acinclude.m4: - fixed typo (dbl -> dnl) --- acinclude.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acinclude.m4 b/acinclude.m4 index 269b505386c..5a48e9840d2 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1113,7 +1113,7 @@ AC_DEFUN([MYSQL_CHECK_BDB_VERSION], [ # mysql_bdb=a # fi -dbl RAM: +dnl RAM: want_bdb_version="4.1.24" bdb_version_ok=yes From 6fd2a8585f169eac9cebd2c57a56397e9c865e9e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jun 2003 13:52:38 +0500 Subject: [PATCH 395/399] str0 IN (str1, str2, ...) now works according to collation rules --- mysql-test/r/func_str.result | 22 +++++++++++++++++ mysql-test/t/func_str.test | 15 ++++++++++++ sql/item_cmpfunc.cc | 47 ++++++++++++++++++------------------ sql/item_cmpfunc.h | 15 +++++++----- 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 959cedeeb0d..34c7752798d 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -296,6 +296,28 @@ select _latin1'B' between _latin1'a' and _latin2'b'; ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation 'between' select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b'; ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation 'between' +select _latin1'B' in (_latin1'a',_latin1'b'); +_latin1'B' in (_latin1'a',_latin1'b') +1 +select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b'); +_latin1'B' collate latin1_bin in (_latin1'a',_latin1'b') +0 +select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b'); +_latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b') +0 +select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin); +_latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin) +0 +select _latin2'B' in (_latin1'a',_latin1'b'); +ERROR HY000: Illegal mix of collations for operation ' IN ' +select _latin1'B' in (_latin2'a',_latin1'b'); +ERROR HY000: Illegal mix of collations for operation ' IN ' +select _latin1'B' in (_latin1'a',_latin2'b'); +ERROR HY000: Illegal mix of collations for operation ' IN ' +select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b'); +ERROR HY000: Illegal mix of collations for operation ' IN ' +select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin); +ERROR HY000: Illegal mix of collations for operation ' IN ' select collation(bin(130)), coercibility(bin(130)); collation(bin(130)) coercibility(bin(130)) latin1_swedish_ci 3 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 41a37c0f7ab..a898d3551d7 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -175,6 +175,21 @@ select _latin1'B' between _latin1'a' and _latin2'b'; --error 1268 select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b'; +select _latin1'B' in (_latin1'a',_latin1'b'); +select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b'); +select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b'); +select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin); +--error 1269 +select _latin2'B' in (_latin1'a',_latin1'b'); +--error 1269 +select _latin1'B' in (_latin2'a',_latin1'b'); +--error 1269 +select _latin1'B' in (_latin1'a',_latin2'b'); +--error 1269 +select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b'); +--error 1269 +select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin); + select collation(bin(130)), coercibility(bin(130)); select collation(oct(130)), coercibility(oct(130)); select collation(conv(130,16,10)), coercibility(conv(130,16,10)); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b764bb322d3..f9c2228b33d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1196,17 +1196,17 @@ void Item_func_coalesce::fix_length_and_dec() Classes and function for the IN operator ****************************************************************************/ -static int cmp_longlong(longlong *a,longlong *b) +static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b) { return *a < *b ? -1 : *a == *b ? 0 : 1; } -static int cmp_double(double *a,double *b) +static int cmp_double(void *cmp_arg, double *a,double *b) { return *a < *b ? -1 : *a == *b ? 0 : 1; } -static int cmp_row(cmp_item_row* a, cmp_item_row* b) +static int cmp_row(void *cmp_arg, cmp_item_row* a, cmp_item_row* b) { return a->compare(b); } @@ -1223,18 +1223,18 @@ int in_vector::find(Item *item) { uint mid=(start+end+1)/2; int res; - if ((res=(*compare)(base+mid*size,result)) == 0) + if ((res=(*compare)(collation, base+mid*size, result)) == 0) return 1; if (res < 0) start=mid; else end=mid-1; } - return (int) ((*compare)(base+start*size,result) == 0); + return (int) ((*compare)(collation, base+start*size, result) == 0); } -in_string::in_string(uint elements,qsort_cmp cmp_func) - :in_vector(elements, sizeof(String), cmp_func), +in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs) + :in_vector(elements, sizeof(String), cmp_func, cs), tmp(buff, sizeof(buff), &my_charset_bin) {} @@ -1273,7 +1273,7 @@ in_row::in_row(uint elements, Item * item) { base= (char*) new cmp_item_row[count= elements]; size= sizeof(cmp_item_row); - compare= (qsort_cmp) cmp_row; + compare= (qsort2_cmp) cmp_row; tmp.store_value(item); } @@ -1298,7 +1298,7 @@ void in_row::set(uint pos, Item *item) } in_longlong::in_longlong(uint elements) - :in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong) + :in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0) {} void in_longlong::set(uint pos,Item *item) @@ -1315,7 +1315,7 @@ byte *in_longlong::get_value(Item *item) } in_double::in_double(uint elements) - :in_vector(elements,sizeof(double),(qsort_cmp) cmp_double) + :in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0) {} void in_double::set(uint pos,Item *item) @@ -1462,17 +1462,8 @@ bool Item_func_in::nulls_in_row() return 0; } -static int srtcmp_in(const String *x,const String *y) +static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) { - CHARSET_INFO *cs= x->charset(); - return cs->coll->strnncollsp(cs, - (unsigned char *) x->ptr(),x->length(), - (unsigned char *) y->ptr(),y->length()); -} - -static int bincmp_in(const String *x,const String *y) -{ - CHARSET_INFO *cs= &my_charset_bin; return cs->coll->strnncollsp(cs, (unsigned char *) x->ptr(),x->length(), (unsigned char *) y->ptr(),y->length()); @@ -1488,10 +1479,18 @@ void Item_func_in::fix_length_and_dec() { switch (item->result_type()) { case STRING_RESULT: - if (item->binary()) - array=new in_string(arg_count,(qsort_cmp) srtcmp_in); - else - array=new in_string(arg_count,(qsort_cmp) bincmp_in); + uint i; + cmp_collation.set(item->collation); + for (i=0 ; icollation)) + break; + if (cmp_collation.derivation == DERIVATION_NONE) + { + my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),func_name()); + return; + } + array=new in_string(arg_count,(qsort2_cmp) srtcmp_in, + cmp_collation.collation); break; case INT_RESULT: array= new in_longlong(arg_count); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 792f2e2411c..1311cae335f 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -382,21 +382,23 @@ class in_vector :public Sql_alloc protected: char *base; uint size; - qsort_cmp compare; + qsort2_cmp compare; + CHARSET_INFO *collation; uint count; public: uint used_count; in_vector() {} - in_vector(uint elements,uint element_length,qsort_cmp cmp_func) + in_vector(uint elements,uint element_length,qsort2_cmp cmp_func, + CHARSET_INFO *cmp_coll) :base((char*) sql_calloc(elements*element_length)), - size(element_length), compare(cmp_func), count(elements), - used_count(elements) {} + size(element_length), compare(cmp_func), collation(cmp_coll), + count(elements), used_count(elements) {} virtual ~in_vector() {} virtual void set(uint pos,Item *item)=0; virtual byte *get_value(Item *item)=0; void sort() { - qsort(base,used_count,size,compare); + qsort2(base,used_count,size,compare,collation); } int find(Item *item); }; @@ -406,7 +408,7 @@ class in_string :public in_vector char buff[80]; String tmp; public: - in_string(uint elements,qsort_cmp cmp_func); + in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs); ~in_string(); void set(uint pos,Item *item); byte *get_value(Item *item); @@ -605,6 +607,7 @@ class Item_func_in :public Item_int_func in_vector *array; cmp_item *in_item; bool have_null; + DTCollation cmp_collation; public: Item_func_in(Item *a,List &list) :Item_int_func(list), item(a), array(0), in_item(0), have_null(0) From 7b54f4d6e00d1dbfe4ef24bc5ebc36049ce2f718 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jun 2003 16:08:52 +0500 Subject: [PATCH 396/399] When unifying arguments for comparion, binary strings won character strings, and comparison was done binary. Now, a binary string wins a character sting taking in account their derivation. That means a character field wins a binary literal and comparison is done according to the character field collation, not binary. --- mysql-test/r/ctype_latin1_de.result | 10 +++++----- mysql-test/t/ctype_latin1_de.test | 13 ++++++++----- sql/item.cc | 23 +++++++++++------------ 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result index 630fef9b679..e0cb7008899 100644 --- a/mysql-test/r/ctype_latin1_de.result +++ b/mysql-test/r/ctype_latin1_de.result @@ -215,21 +215,21 @@ 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; +select word, word=binary 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; +select * from t1 where word=binary 0xDF; word word2 ß ß select * from t1 where word=CAST(0xDF as CHAR); word word2 ss ss ß ß -select * from t1 where word2=0xDF; +select * from t1 where word2=binary 0xDF; word word2 ß ß select * from t1 where word2=CAST(0xDF as CHAR); @@ -244,7 +244,7 @@ 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; +select * from t1 where word between binary 0xDF and binary 0xDF; word word2 ß ß select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR); @@ -257,7 +257,7 @@ ae ae select * from t1 where word like 'AE'; word word2 ae ae -select * from t1 where word like 0xDF; +select * from t1 where word like binary 0xDF; word word2 ß ß select * from t1 where word like CAST(0xDF as CHAR); diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test index b63af87601b..22a4e14158d 100644 --- a/mysql-test/t/ctype_latin1_de.test +++ b/mysql-test/t/ctype_latin1_de.test @@ -52,21 +52,24 @@ drop table t1; # Test bug report #152 (problem with index on latin1_de) # +# +# The below checks both binary and character comparisons. +# 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=binary 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=binary 0xDF; select * from t1 where word=CAST(0xDF as CHAR); -select * from t1 where word2=0xDF; +select * from t1 where word2=binary 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 binary 0xDF and binary 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 binary 0xDF; select * from t1 where word like CAST(0xDF as CHAR); drop table t1; diff --git a/sql/item.cc b/sql/item.cc index 950f27c5d69..fea68837014 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -39,7 +39,7 @@ Item::Item(): { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; - set_charset(&my_charset_bin, DERIVATION_COERCIBLE); + set_charset(default_charset(), DERIVATION_COERCIBLE); name= 0; decimals= 0; max_length= 0; THD *thd= current_thd; @@ -185,13 +185,6 @@ CHARSET_INFO * Item::default_charset() const bool DTCollation::aggregate(DTCollation &dt) { - if (collation == &my_charset_bin || dt.collation == &my_charset_bin) - { - collation= &my_charset_bin; - derivation= derivation > dt.derivation ? derivation : dt.derivation; - return 0; - } - if (!my_charset_same(collation, dt.collation)) { /* @@ -199,13 +192,19 @@ bool DTCollation::aggregate(DTCollation &dt) together with character strings. Binaries have more precedance */ - if ((derivation <= dt.derivation) && (collation == &my_charset_bin)) + if (collation == &my_charset_bin) { - // Do nothing + if (derivation <= dt.derivation) + ; // Do nothing + else + set(dt); } - else if ((dt.derivation <= derivation) && (dt.collation==&my_charset_bin)) + else if (dt.collation == &my_charset_bin) { - set(dt); + if (dt.derivation <= derivation) + set(dt); + else + ; // Do nothing } else { From de52e5fa82b9e23a95a135c021f22f756b1d6a45 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jun 2003 16:09:53 +0500 Subject: [PATCH 397/399] item.cc: A better comment sql/item.cc: A better comment --- sql/item.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index fea68837014..c99493ff689 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -190,7 +190,8 @@ bool DTCollation::aggregate(DTCollation &dt) /* We do allow to use binary strings (like BLOBS) together with character strings. - Binaries have more precedance + Binaries have more precedance than a character + string of the same derivation. */ if (collation == &my_charset_bin) { From cb9c86ede6ae7201df768a3e7b4acb26f9503051 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jun 2003 18:51:39 +0300 Subject: [PATCH 398/399] Added support for structured options (WL task ID 947). --- include/my_getopt.h | 9 ++- mysys/my_getopt.c | 140 +++++++++++++++++++++++++++++++------------- sql/mysqld.cc | 12 +++- 3 files changed, 119 insertions(+), 42 deletions(-) diff --git a/include/my_getopt.h b/include/my_getopt.h index 3b4551b445e..213c8c3570e 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -17,7 +17,12 @@ C_MODE_START enum get_opt_var_type { GET_NO_ARG, GET_BOOL, GET_INT, GET_UINT, GET_LONG, - GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC }; + GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC + }; + +#define GET_ASK_ADDR 128 +#define GET_TYPE_MASK 127 + enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; struct my_option @@ -48,6 +53,8 @@ extern int handle_options (int *argc, char ***argv, char *)); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); +extern void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint, + const struct my_option *)); ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp); my_bool getopt_compare_strings(const char *s, const char *t, uint length); diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 759c96462f6..07f4f306198 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -34,6 +34,7 @@ static ulonglong getopt_ull(char *arg, const struct my_option *optp, static void init_variables(const struct my_option *options); static int setval(const struct my_option *opts, char *argument, my_bool set_maximum_value); +static char *check_struct_option(char *cur_arg, char *key_name); /* The following three variables belong to same group and the number and @@ -67,6 +68,14 @@ my_bool my_getopt_print_errors= 1; one. Call function 'get_one_option()' once for each option. */ +static gptr* (*getopt_get_addr)(char *, uint, const struct my_option *); + +void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint, + const struct my_option *)) +{ + getopt_get_addr= func_addr; +} + int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_bool (*get_one_option)(int, @@ -76,8 +85,10 @@ int handle_options(int *argc, char ***argv, uint opt_found, argvpos= 0, length, i; my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used, option_is_loose; - char *progname= *(*argv), **pos, **pos_end, *optend, *prev_found; + char **pos, **pos_end, *optend, *prev_found, + *opt_str, key_name[FN_REFLEN]; const struct my_option *optp; + gptr *value; int error; LINT_INIT(opt_found); @@ -110,7 +121,7 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, "%s: Option '-O' requires an argument\n", - progname); + my_progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -128,7 +139,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: Option '--set-variable' requires an argument\n", - progname); + my_progname); return EXIT_ARGUMENT_REQUIRED; } } @@ -142,7 +153,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: Option '--set-variable' requires an argument\n", - progname); + my_progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -159,19 +170,20 @@ int handle_options(int *argc, char ***argv, continue; } } - optend= strcend(cur_arg, '='); - length= optend - cur_arg; + opt_str= check_struct_option(cur_arg, key_name); + optend= strcend(opt_str, '='); + length= optend - opt_str; if (*optend == '=') optend++; else - optend=0; + optend= 0; /* Find first the right option. Return error in case of an ambiguous, or unknown option */ optp= longopts; - if (!(opt_found= findopt(cur_arg, length, &optp, &prev_found))) + if (!(opt_found= findopt(opt_str, length, &optp, &prev_found))) { /* Didn't find any matching option. Let's see if someone called @@ -183,18 +195,18 @@ int handle_options(int *argc, char ***argv, must_be_var= 1; /* option is followed by an argument */ for (i= 0; special_opt_prefix[i]; i++) { - if (!getopt_compare_strings(special_opt_prefix[i], cur_arg, + if (!getopt_compare_strings(special_opt_prefix[i], opt_str, special_opt_prefix_lengths[i]) && - cur_arg[special_opt_prefix_lengths[i]] == '-') + opt_str[special_opt_prefix_lengths[i]] == '-') { /* We were called with a special prefix, we can reuse opt_found */ special_used= 1; - cur_arg+= (special_opt_prefix_lengths[i] + 1); + opt_str+= (special_opt_prefix_lengths[i] + 1); if (i == OPT_LOOSE) option_is_loose= 1; - if ((opt_found= findopt(cur_arg, length - + if ((opt_found= findopt(opt_str, length - (special_opt_prefix_lengths[i] + 1), &optp, &prev_found))) { @@ -203,7 +215,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: ambiguous option '--%s-%s' (--%s-%s)\n", - progname, special_opt_prefix[i], cur_arg, + my_progname, special_opt_prefix[i], opt_str, special_opt_prefix[i], prev_found); return EXIT_AMBIGUOUS_OPTION; } @@ -237,8 +249,8 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, - "%s: %s: unknown variable '%s'\n", progname, - option_is_loose ? "WARNING" : "ERROR", cur_arg); + "%s: %s: unknown variable '%s'\n", my_progname, + option_is_loose ? "WARNING" : "ERROR", opt_str); if (!option_is_loose) return EXIT_UNKNOWN_VARIABLE; } @@ -246,8 +258,8 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, - "%s: %s: unknown option '--%s'\n", progname, - option_is_loose ? "WARNING" : "ERROR", cur_arg); + "%s: %s: unknown option '--%s'\n", my_progname, + option_is_loose ? "WARNING" : "ERROR", opt_str); if (!option_is_loose) return EXIT_UNKNOWN_OPTION; } @@ -264,57 +276,61 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, "%s: variable prefix '%s' is not unique\n", - progname, cur_arg); + my_progname, opt_str); return EXIT_VAR_PREFIX_NOT_UNIQUE; } else { if (my_getopt_print_errors) fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n", - progname, cur_arg, prev_found, optp->name); + my_progname, opt_str, prev_found, optp->name); return EXIT_AMBIGUOUS_OPTION; } } - if (must_be_var && optp->var_type == GET_NO_ARG) + if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG) { if (my_getopt_print_errors) fprintf(stderr, "%s: option '%s' cannot take an argument\n", - progname, optp->name); + my_progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } + value= optp->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value; + if (optp->arg_type == NO_ARG) { - if (optend && optp->var_type != GET_BOOL) + if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL) { if (my_getopt_print_errors) fprintf(stderr, "%s: option '--%s' cannot take an argument\n", - progname, optp->name); + my_progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } - if (optp->var_type == GET_BOOL) + if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) { /* Set bool to 1 if no argument or if the user has used --enable-'option-name'. *optend was set to '0' if one used --disable-option */ - *((my_bool*) optp->value)= (my_bool) (!optend || *optend == '1'); + *((my_bool*) value)= (my_bool) (!optend || *optend == '1'); (*argc)--; get_one_option(optp->id, optp, argument); continue; } argument= optend; } - else if (optp->arg_type == OPT_ARG && optp->var_type == GET_BOOL) + else if (optp->arg_type == OPT_ARG && + (optp->var_type & GET_TYPE_MASK) == GET_BOOL) { if (optend == disabled_my_option) - *((my_bool*) optp->value)= (my_bool) 0; + *((my_bool*) value)= (my_bool) 0; else { if (!optend) /* No argument -> enable option */ - *((my_bool*) optp->value)= (my_bool) 1; + *((my_bool*) value)= (my_bool) 1; else /* If argument differs from 0, enable option, else disable */ - *((my_bool*) optp->value)= (my_bool) atoi(optend) != 0; + *((my_bool*) value)= (my_bool) atoi(optend) != 0; } (*argc)--; continue; @@ -326,7 +342,7 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, "%s: option '--%s' requires an argument\n", - progname, optp->name); + my_progname, optp->name); return EXIT_ARGUMENT_REQUIRED; } argument= *pos; @@ -346,7 +362,8 @@ int handle_options(int *argc, char ***argv, { /* Option recognized. Find next what to do with it */ opt_found= 1; - if (optp->var_type == GET_BOOL && optp->arg_type == NO_ARG) + if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL && + optp->arg_type == NO_ARG) { *((my_bool*) optp->value)= (my_bool) 1; get_one_option(optp->id, optp, argument); @@ -370,7 +387,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: option '-%c' requires an argument\n", - progname, optp->id); + my_progname, optp->id); return EXIT_ARGUMENT_REQUIRED; } argument= *pos; @@ -382,7 +399,7 @@ int handle_options(int *argc, char ***argv, { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); @@ -393,7 +410,7 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, - "%s: unknown option '-%c'\n", progname, *optend); + "%s: unknown option '-%c'\n", my_progname, *optend); return EXIT_UNKNOWN_OPTION; } } @@ -404,7 +421,7 @@ int handle_options(int *argc, char ***argv, { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); @@ -424,6 +441,47 @@ int handle_options(int *argc, char ***argv, return 0; } + +/* + function: check_struct_option + + Arguments: Current argument under processing from argv and a variable + where to store the possible key name. + + Return value: In case option is a struct option, returns a pointer to + the current argument at the position where the struct option (key_name) + ends, the next character after the dot. In case argument is not a struct + option, returns a pointer to the argument. + + key_name will hold the name of the key, or 0 if not found. +*/ + +static char *check_struct_option(char *cur_arg, char *key_name) +{ + char *ptr, *ptr2; + + ptr= strcend(cur_arg, '.'); + ptr2= strcend(cur_arg, '='); + + /* + Minimum length for a struct option is 3 (--a.b) + If the (first) dot is after an equal sign, then it is part + of a variable value and the option is not a struct option. + */ + if (strlen(ptr) >= 3 && ptr2 - ptr > 0) + { + uint len= ptr - cur_arg; + strnmov(key_name, cur_arg, len); + key_name[len]= '\0'; + return ++ptr; + } + else + { + key_name= 0; + return cur_arg; + } +} + /* function: setval @@ -444,7 +502,7 @@ static int setval(const struct my_option *opts, char *argument, if (!result_pos) return EXIT_NO_PTR_TO_VARIABLE; - switch (opts->var_type) { + switch ((opts->var_type & GET_TYPE_MASK)) { case GET_INT: case GET_UINT: /* fall through */ *((int*) result_pos)= (int) getopt_ll(argument, opts, &err); @@ -634,7 +692,7 @@ static void init_variables(const struct my_option *options) { if (options->value) { - switch (options->var_type) { + switch ((options->var_type & GET_TYPE_MASK)) { case GET_BOOL: if (options->u_max_value) *((my_bool*) options->u_max_value)= (my_bool) options->max_value; @@ -706,13 +764,15 @@ void my_print_help(const struct my_option *options) { printf("--%s", optp->name); col+= 2 + strlen(optp->name); - if (optp->var_type == GET_STR || optp->var_type == GET_STR_ALLOC) + if ((optp->var_type & GET_TYPE_MASK) == GET_STR || + (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC) { printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "", optp->arg_type == OPT_ARG ? "]" : ""); col+= (optp->arg_type == OPT_ARG) ? 8 : 6; } - else if (optp->var_type == GET_NO_ARG || optp->var_type == GET_BOOL) + else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG || + (optp->var_type & GET_TYPE_MASK) == GET_BOOL) { putchar(' '); col++; @@ -775,7 +835,7 @@ void my_print_variables(const struct my_option *options) length= strlen(optp->name); for (; length < name_space; length++) putchar(' '); - switch (optp->var_type) { + switch ((optp->var_type & GET_TYPE_MASK)) { case GET_STR: case GET_STR_ALLOC: /* fall through */ printf("%s\n", *((char**) optp->value) ? *((char**) optp->value) : diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 68fa0cca2d5..72ee3e30c63 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4092,7 +4092,8 @@ replicating a LOAD DATA INFILE command.", IO_SIZE, 0}, {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", - (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL, + (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, + (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR), REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE, 0}, {"long_query_time", OPT_LONG_QUERY_TIME, @@ -5298,10 +5299,19 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } /* Initiates DEBUG - but no debugging here ! */ + +extern "C" gptr * +mysql_getopt_value(char *keyname, uint key_length, + const struct my_option *option) +{ + return option->value; +} + static void get_options(int argc,char **argv) { int ho_error; + my_getopt_register_get_addr(mysql_getopt_value); if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); if (argc > 0) From dfdb1e831b6ea46c6395ae917f84c75f81796cef Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jun 2003 23:00:33 +0300 Subject: [PATCH 399/399] after review patch --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6f9cb9ecf40..a25fdb4e8f7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7232,7 +7232,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, Item *it= *order->item; if (it->fix_fields(thd, tables, order->item) || //'it' ressigned because fix_field can change it - (it= *order->item), it->check_cols(1) || + (it= *order->item)->check_cols(1) || thd->is_fatal_error) return 1; // Wrong field uint el= all_fields.elements;