From af18865e5afedc31a4f58d15d781e420a5588e6a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Oct 2004 18:10:44 +0500 Subject: [PATCH 01/48] A fix (bug #6000 No "@%"-accounts after install). scripts/mysql_install_db.sh: A fix (bug #6000 No "@%"-accounts after install). Why do we need those REPLACE queries? Removed $hostname queries for windows builds. --- scripts/mysql_install_db.sh | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index f9f3160d220..c75f9854a2a 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -275,14 +275,16 @@ then 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 ('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 ('$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 ('localhost',''); - INSERT INTO user (host,user) values ('$hostname','');" + if test "$windows" = 1 + 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 (host,user) values ('localhost','');" + 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); + 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 ('localhost',''); + INSERT INTO user (host,user) values ('$hostname','');" + fi fi if test ! -f $mdata/func.frm From 489bd55741a663f1896fbe7fad5792ef41ed8913 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Jan 2005 11:53:39 +0200 Subject: [PATCH 02/48] error of parsing can occur in any SELECT, so all SELECTs have to be checked --- sql/sql_lex.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index d2ac0df1472..f5a0fef6769 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -163,7 +163,8 @@ void lex_start(THD *thd, uchar *buf,uint length) void lex_end(LEX *lex) { - lex->select_lex.expr_list.delete_elements(); // If error when parsing sql-varargs + for(SELECT_LEX *sl= lex->all_selects_list; sl; sl= sl->next_select_in_list()) + sl->expr_list.delete_elements(); // If error when parsing sql-varargs x_free(lex->yacc_yyss); x_free(lex->yacc_yyvs); } From 7f586778f33c9393c26c5c38e224a83d5e1837c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 16 Jan 2005 18:36:13 +0200 Subject: [PATCH 03/48] postreview changes sql/sql_lex.cc: layout fixed --- sql/sql_lex.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f5a0fef6769..e3137bf3766 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -163,7 +163,9 @@ void lex_start(THD *thd, uchar *buf,uint length) void lex_end(LEX *lex) { - for(SELECT_LEX *sl= lex->all_selects_list; sl; sl= sl->next_select_in_list()) + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) sl->expr_list.delete_elements(); // If error when parsing sql-varargs x_free(lex->yacc_yyss); x_free(lex->yacc_yyvs); From b3cd49f3127f5cf41d2b4e42c6597262ca6a5376 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Jan 2005 13:56:22 +0200 Subject: [PATCH 04/48] fixed problem with distinct select with grouping and subqueries (BUG#7946) mysql-test/r/derived.result: DISTINCT over grouped select on subquery in the FROM clause mysql-test/t/derived.test: DISTINCT over grouped select on subquery in the FROM clause sql/sql_select.cc: used current join copy for test --- mysql-test/r/derived.result | 9 +++++++++ mysql-test/t/derived.test | 10 ++++++++++ sql/sql_select.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 7e6b9b44566..61d745d0236 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -330,3 +330,12 @@ SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MA min max avg 10.00 10.00 10 DROP TABLE t1; +create table t1 (a integer, b integer); +insert into t1 values (1,4), (2,2),(2,2), (4,1),(4,1),(4,1),(4,1); +select distinct sum(b) from t1 group by a; +sum(b) +4 +select distinct sum(b) from (select a,b from t1) y group by a; +sum(b) +4 +drop table t1; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 64e3fe8929b..8b322746ed6 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -214,3 +214,13 @@ CREATE TABLE `t1` ( `itemid` int(11) NOT NULL default '0', `grpid` varchar(15) N insert into t1 values (128, 'rozn', 2, now(), 10),(128, 'rozn', 1, now(), 10); SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MAX(concat(date_,";",price)), 12) price FROM t1 WHERE itemid=128 AND grpid='rozn' GROUP BY itemid, grpid, vendor) lastprices; DROP TABLE t1; + +# +# DISTINCT over grouped select on subquery in the FROM clause +# +create table t1 (a integer, b integer); +insert into t1 values (1,4), (2,2),(2,2), (4,1),(4,1),(4,1),(4,1); +select distinct sum(b) from t1 group by a; +select distinct sum(b) from (select a,b from t1) y group by a; +drop table t1; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index aea7cb9ed6d..b2fb7ec0275 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1304,7 +1304,7 @@ JOIN::exec() curr_join->select_distinct=0; /* Each row is unique */ curr_join->join_free(0); /* Free quick selects */ - if (select_distinct && ! group_list) + if (curr_join->select_distinct && ! curr_join->group_list) { thd->proc_info="Removing duplicates"; if (curr_join->tmp_having) From d514a06a86d689065590b0115799f06fa109a70b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jan 2005 14:25:44 +0200 Subject: [PATCH 05/48] fixed column number fetchinmg for subqueries. (BUG#8020) fixed cols() method call (it have to be called only after fix_fields()) mysql-test/r/subselect.result: Comparison subquery with * and row mysql-test/t/subselect.test: Comparison subquery with * and row sql/item_cmpfunc.h: initialization allowed_arg_cols for autodetection sql/item_func.cc: support of allowed_arg_cols autodetection by first argument sql/item_func.h: commant sql/item_subselect.cc: correct column number fetching for subqueries sql/sql_lex.h: method to check that UNION is prepared --- mysql-test/r/subselect.result | 14 ++++++++++++++ mysql-test/t/subselect.test | 14 ++++++++++++++ sql/item_cmpfunc.h | 9 ++++++--- sql/item_func.cc | 18 ++++++++++++++++-- sql/item_func.h | 4 ++++ sql/item_subselect.cc | 6 ++++-- sql/sql_lex.h | 1 + 7 files changed, 59 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 02662f9900a..a7186c6953b 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2160,3 +2160,17 @@ ERROR 42S22: Unknown column 'a2' in 'scalar IN/ALL/ANY subquery' select * from t1 where a1 > any(select b1 from t2); a1 drop table t1,t2; +create table t1 (a integer, b integer); +select (select * from t1) = (select 1,2); +(select * from t1) = (select 1,2) +NULL +select (select 1,2) = (select * from t1); +(select 1,2) = (select * from t1) +NULL +select row(1,2) = ANY (select * from t1); +row(1,2) = ANY (select * from t1) +0 +select row(1,2) != ALL (select * from t1); +row(1,2) != ALL (select * from t1) +1 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 3ee498ee380..c8b44252139 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1414,8 +1414,11 @@ SELECT f1 FROM t1 WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000); drop table t1,t2; + +# # Test for BUG#7885: Server crash when 'any' subselect compared to # non-existant field. +# create table t1 (a1 int); create table t2 (b1 int); --error 1054 @@ -1423,3 +1426,14 @@ select * from t1 where a2 > any(select b1 from t2); select * from t1 where a1 > any(select b1 from t2); drop table t1,t2; + +# +# Comparison subquery with * and row +# +create table t1 (a integer, b integer); +select (select * from t1) = (select 1,2); +select (select 1,2) = (select * from t1); +# queries whih can be converted to IN +select row(1,2) = ANY (select * from t1); +select row(1,2) != ALL (select * from t1); +drop table t1; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 6834799688d..061ed468b78 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -213,7 +213,7 @@ class Item_bool_rowready_func2 :public Item_bool_func2 public: Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b) { - allowed_arg_cols= a->cols(); + allowed_arg_cols= 0; // Fetch this value from first argument } Item *neg_transformer(THD *thd); virtual Item *negated_item(); @@ -390,7 +390,10 @@ class Item_func_interval :public Item_int_func double *intervals; public: Item_func_interval(Item_row *a) - :Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); } + :Item_int_func(a),row(a),intervals(0) + { + allowed_arg_cols= 0; // Fetch this value from first argument + } longlong val_int(); void fix_length_and_dec(); const char *func_name() const { return "interval"; } @@ -743,7 +746,7 @@ class Item_func_in :public Item_int_func Item_func_in(List &list) :Item_int_func(list), array(0), in_item(0), have_null(0) { - allowed_arg_cols= args[0]->cols(); + allowed_arg_cols= 0; // Fetch this value from first argument } longlong val_int(); void fix_length_and_dec(); diff --git a/sql/item_func.cc b/sql/item_func.cc index 7125f4704b8..bff49541252 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -303,10 +303,24 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) We can't yet set item to *arg as fix_fields may change *arg We shouldn't call fix_fields() twice, so check 'fixed' field first */ - if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) || - (*arg)->check_cols(allowed_arg_cols)) + if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg))) return 1; /* purecov: inspected */ + item= *arg; + + if (allowed_arg_cols) + { + if (item->check_cols(allowed_arg_cols)) + return 1; + } + else + { + /* we have to fetch allowed_arg_cols from first argument */ + DBUG_ASSERT(arg == args); // it is first argument + allowed_arg_cols= item->cols(); + DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more + } + if (item->maybe_null) maybe_null=1; diff --git a/sql/item_func.h b/sql/item_func.h index ce2b34499d6..8a5347d675e 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -32,6 +32,10 @@ class Item_func :public Item_result_field { protected: Item **args, *tmp_arg[2]; + /* + Allowed numbers of columns in result (usually 1, which means scalar value) + 0 means get this number from first argument + */ uint allowed_arg_cols; public: uint arg_count; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8516ea76a7e..2597427253c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1421,13 +1421,15 @@ int subselect_indexsubquery_engine::exec() uint subselect_single_select_engine::cols() { - return select_lex->item_list.elements; + DBUG_ASSERT(select_lex->join); // should be called after fix_fields() + return select_lex->join->fields_list.elements; } uint subselect_union_engine::cols() { - return unit->first_select()->item_list.elements; + DBUG_ASSERT(unit->is_prepared()); // should be called after fix_fields() + return unit->types.elements; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e2e0bc61c23..7cb71607edf 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -371,6 +371,7 @@ public: ulong init_prepare_fake_select_lex(THD *thd); int change_result(select_subselect *result, select_subselect *old_result); + inline bool is_prepared() { return prepared; } friend void lex_start(THD *thd, uchar *buf, uint length); friend int subselect_union_engine::exec(); From 9182786918011c6d77beee27c5deec2569f4b6c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jan 2005 15:56:57 +0200 Subject: [PATCH 06/48] check that row elements have the same dimention that SELECT list elements in comporison between rows and subqueries added (BUG#8022) mysql-test/r/subselect.result: Comparison subquery and row with nested rows mysql-test/t/subselect.test: Comparison subquery and row with nested rows sql/item_subselect.cc: check that row elements have the same dimention that SELECT list elements --- mysql-test/r/subselect.result | 8 ++++++++ mysql-test/t/subselect.test | 12 ++++++++++++ sql/item_subselect.cc | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a7186c6953b..4a4cbcc38cd 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2174,3 +2174,11 @@ select row(1,2) != ALL (select * from t1); row(1,2) != ALL (select * from t1) 1 drop table t1; +create table t1 (a integer, b integer); +select row(1,(2,2)) in (select * from t1 ); +ERROR 21000: Operand should contain 2 column(s) +select row(1,(2,2)) = (select * from t1 ); +ERROR 21000: Operand should contain 2 column(s) +select (select * from t1) = row(1,(2,2)); +ERROR 21000: Operand should contain 1 column(s) +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c8b44252139..d8e58facaad 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1437,3 +1437,15 @@ select (select 1,2) = (select * from t1); select row(1,2) = ANY (select * from t1); select row(1,2) != ALL (select * from t1); drop table t1; + +# +# Comparison subquery and row with nested rows +# +create table t1 (a integer, b integer); +-- error 1241 +select row(1,(2,2)) in (select * from t1 ); +-- error 1241 +select row(1,(2,2)) = (select * from t1 ); +-- error 1241 +select (select * from t1) = row(1,(2,2)); +drop table t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 2597427253c..659d67eaf37 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -995,6 +995,10 @@ Item_in_subselect::row_value_transformer(JOIN *join) List_iterator_fast li(select_lex->item_list); for (uint i= 0; i < n; i++) { + DBUG_ASSERT(left_expr->fixed && select_lex->ref_pointer_array[i]->fixed); + if (select_lex->ref_pointer_array[i]-> + check_cols(left_expr->el(i)->cols())) + goto err; Item *func= new Item_ref_null_helper(this, select_lex->ref_pointer_array+i, (char *) "", From 38e664cf6460c4bfe586ad9d12b9f421acf48ebc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jan 2005 17:17:19 +0200 Subject: [PATCH 07/48] fixed way of forward reference detection to support literal constant (BUG#8025) mysql-test/r/subselect.result: Forward reference detection mysql-test/t/subselect.test: Forward reference detection sql/item.cc: now forward reference is detected via ref_pointer_array, because some literal constants are 'fixed' just after creation sql/sql_base.cc: fill ref_pointer_array with zerows for forward reference detection. --- mysql-test/r/subselect.result | 14 ++++++++++++++ mysql-test/t/subselect.test | 16 ++++++++++++++++ sql/item.cc | 6 ++++-- sql/sql_base.cc | 14 ++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 4a4cbcc38cd..03dcc23c919 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2182,3 +2182,17 @@ ERROR 21000: Operand should contain 2 column(s) select (select * from t1) = row(1,(2,2)); ERROR 21000: Operand should contain 1 column(s) drop table t1; +create table t1 (a integer); +insert into t1 values (1); +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx ; +ERROR 42S22: Reference 'xx' not supported (forward reference in item list) +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx; +ERROR 42S22: Reference 'xx' not supported (forward reference in item list) +select 1 as xx, 1 = ALL ( select 1 from t1 where 1 = xx ); +xx 1 = ALL ( select 1 from t1 where 1 = xx ) +1 1 +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx; +ERROR 42S22: Reference 'xx' not supported (forward reference in item list) +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL; +ERROR 42S22: Reference 'xx' not supported (forward reference in item list) +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index d8e58facaad..55400dae0be 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1449,3 +1449,19 @@ select row(1,(2,2)) = (select * from t1 ); -- error 1241 select (select * from t1) = row(1,(2,2)); drop table t1; + +# +# Forward reference detection +# +create table t1 (a integer); +insert into t1 values (1); +-- error 1247 +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx ; +-- error 1247 +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx; +select 1 as xx, 1 = ALL ( select 1 from t1 where 1 = xx ); +-- error 1247 +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx; +-- error 1247 +select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL; +drop table t1; diff --git a/sql/item.cc b/sql/item.cc index 640cc17411f..412cf315d4a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1482,12 +1482,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } else if (refer != (Item **)not_found_item) { - if (!(*refer)->fixed) + if (!last->ref_pointer_array[counter]) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, "forward reference in item list"); return -1; } + DBUG_ASSERT((*refer)->fixed); /* Here, a subset of actions performed by Item_ref::set_properties is not enough. So we pass ptr to NULL into Item_[direct]_ref @@ -2173,12 +2174,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) mark_as_dependent(thd, last, thd->lex->current_select, fld); return 0; } - if (!(*ref)->fixed) + if (!last->ref_pointer_array[counter]) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, "forward reference in item list"); return -1; } + DBUG_ASSERT((*ref)->fixed); mark_as_dependent(thd, last, thd->lex->current_select, this); if (place == IN_HAVING) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 263c68a82b7..fc987ef09b2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2405,6 +2405,20 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, thd->allow_sum_func= allow_sum_func; thd->where="field list"; + /* + To prevent fail on forward lookup we fill it with zerows, + then if we got pointer on zero after find_item_in_list we will know + that it is forward lookup. + + There is other way to solve problem: fill array with pointers to list, + but it will be slower. + + TODO: remove it when (if) we made one list for allfields and + ref_pointer_array + */ + if (ref_pointer_array) + bzero(ref_pointer_array, sizeof(Item *) * fields.elements); + Item **ref= ref_pointer_array; while ((item= it++)) { From e1b8a004fea3aca320d3d8fa36dfd7932ab045ca Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Jan 2005 12:06:55 -0800 Subject: [PATCH 08/48] Always call vio_in_addr() so that thd->remote is always initialized. (Bug #5569) vio/viosocket.c: Remove comment that is no longer correct sql/sql_parse.cc: Always call vio_in_addr() on successful connection, so that thd->remote always gets set vio/viossl.c: Remove comment that is no longer correct --- sql/sql_parse.cc | 5 +++-- vio/viosocket.c | 2 +- vio/viossl.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1aeb158dc11..efb534ed439 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -501,6 +501,9 @@ check_connections(THD *thd) thd->thread_id)); DBUG_PRINT("info",("New connection received on %s", vio_description(net->vio))); + + vio_in_addr(net->vio,&thd->remote.sin_addr); + if (!thd->host) // If TCP/IP connection { char ip[30]; @@ -521,7 +524,6 @@ check_connections(THD *thd) #endif if (!(specialflag & SPECIAL_NO_RESOLVE)) { - vio_in_addr(net->vio,&thd->remote.sin_addr); thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors); /* Cut very long hostnames to avoid possible overflows */ if (thd->host) @@ -543,7 +545,6 @@ check_connections(THD *thd) DBUG_PRINT("info",("Host: %s",thd->host)); thd->host_or_ip= thd->host; thd->ip= 0; - bzero((char*) &thd->remote,sizeof(struct sockaddr)); } vio_keepalive(net->vio, TRUE); diff --git a/vio/viosocket.c b/vio/viosocket.c index ad156fc33bf..1b6f46c57cf 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -295,7 +295,7 @@ void vio_in_addr(Vio *vio, struct in_addr *in) { DBUG_ENTER("vio_in_addr"); if (vio->localhost) - bzero((char*) in, sizeof(*in)); /* This should never be executed */ + bzero((char*) in, sizeof(*in)); else *in=vio->remote.sin_addr; DBUG_VOID_RETURN; diff --git a/vio/viossl.c b/vio/viossl.c index a489cb98f98..07713c83763 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -259,7 +259,7 @@ void vio_ssl_in_addr(Vio *vio, struct in_addr *in) { DBUG_ENTER("vio_ssl_in_addr"); if (vio->localhost) - bzero((char*) in, sizeof(*in)); /* This should never be executed */ + bzero((char*) in, sizeof(*in)); else *in=vio->remote.sin_addr; DBUG_VOID_RETURN; From 7ff1db2d6262494380885d2a5b68d4e099f31c9e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Jan 2005 22:11:21 +0200 Subject: [PATCH 09/48] sql_class.h, set_var.cc, mysqld.cc: Add settable variables for semi-sync replication sql/mysqld.cc: Add settable variables for semi-sync replication sql/set_var.cc: Add settable variables for semi-sync replication sql/sql_class.h: Add settable variables for semi-sync replication --- sql/mysqld.cc | 21 ++++++++++++++++++++- sql/set_var.cc | 14 ++++++++++++++ sql/sql_class.h | 5 +++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 21b1cb7ffd0..f7eab071808 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4087,7 +4087,11 @@ enum options_mysqld OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE, OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE, - OPT_SYNC_FRM, OPT_SYNC_BINLOG, OPT_BDB_NOSYNC, + OPT_SYNC_FRM, OPT_SYNC_BINLOG, + OPT_SYNC_REPLICATION, + OPT_SYNC_REPLICATION_SLAVE_ID, + OPT_SYNC_REPLICATION_TIMEOUT, + OPT_BDB_NOSYNC, OPT_ENABLE_SHARED_MEMORY, OPT_SHARED_MEMORY_BASE_NAME, OPT_OLD_PASSWORDS, @@ -5200,6 +5204,21 @@ The minimum value for this variable is 4096.", (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0}, + {"sync-replication", OPT_SYNC_REPLICATION, + "Enable synchronous replication", + (gptr*) &global_system_variables.sync_replication, + (gptr*) &global_system_variables.sync_replication, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, 1, 0, 1, 0}, + {"sync-replication-slave-id", OPT_SYNC_REPLICATION_SLAVE_ID, + "Synchronous replication is wished for this slave", + (gptr*) &global_system_variables.sync_replication_slave_id, + (gptr*) &global_system_variables.sync_replication_slave_id, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0}, + {"sync-replication-timeout", OPT_SYNC_REPLICATION_TIMEOUT, + "Synchronous replication timeout", + (gptr*) &global_system_variables.sync_replication_timeout, + (gptr*) &global_system_variables.sync_replication_timeout, + 0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0}, {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default", (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, diff --git a/sql/set_var.cc b/sql/set_var.cc index 1237c31075c..1807e0efbed 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -333,6 +333,14 @@ sys_var_thd_storage_engine sys_storage_engine("storage_engine", &SV::table_type); #ifdef HAVE_REPLICATION sys_var_sync_binlog_period sys_sync_binlog_period("sync_binlog", &sync_binlog_period); +sys_var_thd_ulong sys_sync_replication("sync_replication", + &SV::sync_replication); +sys_var_thd_ulong sys_sync_replication_slave_id( + "sync_replication_slave_id", + &SV::sync_replication_slave_id); +sys_var_thd_ulong sys_sync_replication_timeout( + "sync_replication_timeout", + &SV::sync_replication_timeout); #endif sys_var_bool_ptr sys_sync_frm("sync_frm", &opt_sync_frm); sys_var_long_ptr sys_table_cache_size("table_cache", @@ -605,6 +613,9 @@ sys_var *sys_variables[]= &sys_storage_engine, #ifdef HAVE_REPLICATION &sys_sync_binlog_period, + &sys_sync_replication, + &sys_sync_replication_slave_id, + &sys_sync_replication_timeout, #endif &sys_sync_frm, &sys_table_cache_size, @@ -850,6 +861,9 @@ struct show_var_st init_vars[]= { {sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS}, #ifdef HAVE_REPLICATION {sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS}, + {sys_sync_replication.name, (char*) &sys_sync_replication, SHOW_SYS}, + {sys_sync_replication_slave_id.name, (char*) &sys_sync_replication_slave_id,SHOW_SYS}, + {sys_sync_replication_timeout.name, (char*) &sys_sync_replication_timeout,SHOW_SYS}, #endif {sys_sync_frm.name, (char*) &sys_sync_frm, SHOW_SYS}, #ifdef HAVE_TZNAME diff --git a/sql/sql_class.h b/sql/sql_class.h index ce60ed06cfd..8128690ab02 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -397,6 +397,11 @@ struct system_variables my_bool low_priority_updates; my_bool new_mode; my_bool query_cache_wlock_invalidate; +#ifdef HAVE_REPLICATION + ulong sync_replication; + ulong sync_replication_slave_id; + ulong sync_replication_timeout; +#endif /* HAVE_REPLICATION */ #ifdef HAVE_INNOBASE_DB my_bool innodb_table_locks; #endif /* HAVE_INNOBASE_DB */ From 7a220becd2905e1d198c296b0a5b790914340520 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Jan 2005 22:42:50 +0200 Subject: [PATCH 10/48] buf0rea.c: Add more diagnostics about why page reads in recovery may hang: print the number of pending pread calls innobase/buf/buf0rea.c: Add more diagnostics about why page reads in recovery may hang: print the number of pending pread calls --- innobase/buf/buf0rea.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c index 58287d37387..055eede5c1a 100644 --- a/innobase/buf/buf0rea.c +++ b/innobase/buf/buf0rea.c @@ -679,7 +679,9 @@ buf_read_recv_pages( fprintf(stderr, "InnoDB: Error: InnoDB has waited for 50 seconds for pending\n" "InnoDB: reads to the buffer pool to be finished.\n" -"InnoDB: Number of pending reads %lu\n", (ulong) buf_pool->n_pend_reads); +"InnoDB: Number of pending reads %lu, pending pread calls %lu\n", + (ulong) buf_pool->n_pend_reads, + (ulong)os_file_n_pending_preads); os_aio_print_debug = TRUE; } From 755c9aabe27eaf0587b6f8331e1d688e855e6ed1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jan 2005 15:27:45 +0200 Subject: [PATCH 11/48] fixed cleanup of result object of subqueries. (BUG#8125) mysql-test/r/subselect.result: cleaning up of results of subselects test mysql-test/t/subselect.test: cleaning up of results of subselects test sql/item_subselect.cc: call result object cleupup on engine cleunup sql/sql_class.cc: added cleanup of select_max_min_finder_subselect sql/sql_class.h: added cleanup of select_max_min_finder_subselect --- mysql-test/r/subselect.result | 12 ++++++++++++ mysql-test/t/subselect.test | 14 ++++++++++++++ sql/item_subselect.cc | 6 ++++++ sql/sql_class.cc | 8 ++++++++ sql/sql_class.h | 1 + 5 files changed, 41 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 03dcc23c919..437fd624ae1 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2196,3 +2196,15 @@ ERROR 42S22: Reference 'xx' not supported (forward reference in item list) select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL; ERROR 42S22: Reference 'xx' not supported (forward reference in item list) drop table t1; +CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB; +CREATE TABLE t2 LIKE t1; +INSERT INTO t1 VALUES (1,1,1); +INSERT INTO t2 VALUES (1,1,1); +PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having +count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)"; +EXECUTE my_stmt; +b count(*) +EXECUTE my_stmt; +b count(*) +deallocate prepare my_stmt; +drop table t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 55400dae0be..cdec080611d 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1465,3 +1465,17 @@ select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx; -- error 1247 select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL; drop table t1; + +# +# cleaning up of results of subselects (BUG#8125) +# +CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB; +CREATE TABLE t2 LIKE t1; +INSERT INTO t1 VALUES (1,1,1); +INSERT INTO t2 VALUES (1,1,1); +PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having +count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)"; +EXECUTE my_stmt; +EXECUTE my_stmt; +deallocate prepare my_stmt; +drop table t1,t2; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 659d67eaf37..16186b1a6d3 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1127,6 +1127,7 @@ void subselect_single_select_engine::cleanup() DBUG_ENTER("subselect_single_select_engine::cleanup"); prepared= optimized= executed= 0; join= 0; + result->cleanup(); DBUG_VOID_RETURN; } @@ -1135,6 +1136,7 @@ void subselect_union_engine::cleanup() { DBUG_ENTER("subselect_union_engine::cleanup"); unit->reinit_exec_mechanism(); + result->cleanup(); DBUG_VOID_RETURN; } @@ -1142,6 +1144,10 @@ void subselect_union_engine::cleanup() void subselect_uniquesubquery_engine::cleanup() { DBUG_ENTER("subselect_uniquesubquery_engine::cleanup"); + /* + subselect_uniquesubquery_engine have not 'result' assigbed, so we do not + cleanup() it + */ DBUG_VOID_RETURN; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 596097d9dc2..e11d8369f57 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1240,6 +1240,14 @@ bool select_singlerow_subselect::send_data(List &items) } +void select_max_min_finder_subselect::cleanup() +{ + DBUG_ENTER("select_max_min_finder_subselect::cleanup"); + cache= 0; + DBUG_VOID_RETURN; +} + + bool select_max_min_finder_subselect::send_data(List &items) { DBUG_ENTER("select_max_min_finder_subselect::send_data"); diff --git a/sql/sql_class.h b/sql/sql_class.h index ce60ed06cfd..55099791ae0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1381,6 +1381,7 @@ public: select_max_min_finder_subselect(Item_subselect *item, bool mx) :select_subselect(item), cache(0), fmax(mx) {} + void cleanup(); bool send_data(List &items); bool cmp_real(); bool cmp_int(); From a12d52a1d7ff3ae0c6baca766400e7966c6e45a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Jan 2005 14:05:44 +0200 Subject: [PATCH 12/48] InnoDB: Tolerate negative return values from ftell(). sql/ha_innodb.cc: Tolerate negative return values from ftell(). --- sql/ha_innodb.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 2e441b4f085..1a870ce3abf 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4346,12 +4346,12 @@ ha_innobase::update_table_comment( (ulong) innobase_get_free_space()); dict_print_info_on_foreign_keys(FALSE, file, prebuilt->table); flen = ftell(file); - if(length + flen + 3 > 64000) { + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { flen = 64000 - 3 - length; } - ut_ad(flen > 0); - /* allocate buffer for the full string, and read the contents of the temporary file */ @@ -4414,12 +4414,12 @@ ha_innobase::get_foreign_key_create_info(void) prebuilt->trx->op_info = (char*)""; flen = ftell(file); - if(flen > 64000 - 1) { + if (flen < 0) { + flen = 0; + } else if(flen > 64000 - 1) { flen = 64000 - 1; } - ut_ad(flen >= 0); - /* allocate buffer for the string, and read the contents of the temporary file */ @@ -4800,12 +4800,12 @@ innodb_show_status( srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); os_file_set_eof(srv_monitor_file); - if(flen > 64000 - 1) { + if (flen < 0) { + flen = 0; + } else if (flen > 64000 - 1) { flen = 64000 - 1; } - ut_ad(flen > 0); - /* allocate buffer for the string, and read the contents of the temporary file */ From bde9e86041ed3cb80b26f5b3d5bb7168da031c5d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Jan 2005 17:12:21 +0200 Subject: [PATCH 13/48] configure.in: Add -DDBUG_ON to CXXFLAGS whenever it is added to CFLAGS. Thus, sql/ha_innodb.cc will be compiled with the same setting of UNIV_DEBUG as the rest of InnoDB, i.e., --with-debug enables InnoDB ut_ad() assertions everywhere. configure.in: Add -DDBUG_ON to CXXFLAGS whenever it is added to CFLAGS. Thus, sql/ha_innodb.cc will be compiled with the same setting of UNIV_DEBUG as the rest of InnoDB, i.e., --with-debug enables InnoDB ut_ad() assertions everywhere. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 65af867cbc0..8b8c0690a55 100644 --- a/configure.in +++ b/configure.in @@ -1632,12 +1632,12 @@ if test "$with_debug" = "yes" then # Medium debug. CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DSAFE_MUTEX $CXXFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DDBUG_ON -DSAFE_MUTEX $CXXFLAGS" elif test "$with_debug" = "full" then # Full debug. Very slow in some cases CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" else # Optimized version. No debug CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS" From c84ff9867260dfb1a8a95b993aad459ce76b85c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Jan 2005 22:00:36 +0200 Subject: [PATCH 14/48] fil0fil.c: We accidentally checked if the DIRECTORY is of type OS_FILE_TYPE_UNKNOWN; our intention was to check if the FILE is that; best to remove the check altogether, as in crash recovery it is safest to try to open also files whose type is unknown os0file.c: Fix a bug: in Windows, os_file_readdir_next_file() returned OS_FILE_TYPE_UNKNOWN as the type of a regular file; this did not break mysqld, but did break ibbackup on Windows innobase/os/os0file.c: Fix a bug: in Windows, os_file_readdir_next_file() returned OS_FILE_TYPE_UNKNOWN as the type of a regular file; this did not break mysqld, but did break ibbackup on Windows innobase/fil/fil0fil.c: We accidentally checked if the DIRECTORY is of type OS_FILE_TYPE_UNKNOWN; our intention was to check if the FILE is that; best to remove the check altogether, as in crash recovery it is safest to try to open also files whose type is unknown --- innobase/fil/fil0fil.c | 4 ++-- innobase/os/os0file.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index cc1c4a22983..a8da074cab9 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -3002,8 +3002,8 @@ fil_load_single_table_tablespaces(void) /* printf( " Looking at file %s\n", fileinfo.name); */ - if (fileinfo.type == OS_FILE_TYPE_DIR - || dbinfo.type == OS_FILE_TYPE_UNKNOWN) { + if (fileinfo.type == OS_FILE_TYPE_DIR) { + goto next_file_item; } diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 7090e8662f3..070096f4760 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -700,12 +700,12 @@ http://www.mysql.com/doc/en/Windows_symbolic_links.html */ } else if (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { info->type = OS_FILE_TYPE_DIR; - } else if (lpFindFileData->dwFileAttributes - & FILE_ATTRIBUTE_NORMAL) { -/* TODO: are FILE_ATTRIBUTE_NORMAL files really all normal files? */ - info->type = OS_FILE_TYPE_FILE; } else { - info->type = OS_FILE_TYPE_UNKNOWN; + /* It is probably safest to assume that all other + file types are normal. Better to check them rather + than blindly skip them. */ + + info->type = OS_FILE_TYPE_FILE; } } From 3487cba72d6d6ddabd55e5d220cecffa28c6f9ce Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Jan 2005 15:26:17 +0400 Subject: [PATCH 15/48] A fix (bug #6000: No "@%"-accounts after install). scripts/mysql_install_db.sh: A fix (bug #6000: No "@%"-accounts after install). Why do we need those REPLACE queries? Removed $hostname queries for windows builds. --- scripts/mysql_install_db.sh | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 8d47d67792a..40827f8b6ef 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -275,14 +275,16 @@ then 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 ('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 ('$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 ('localhost',''); - INSERT INTO user (host,user) values ('$hostname','');" + if test "$windows" = 1 + 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 (host,user) values ('localhost','');" + 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); + 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 ('localhost',''); + INSERT INTO user (host,user) values ('$hostname','');" + fi fi if test ! -f $mdata/func.frm From c392de41b2ca3c19b3b9bfad0257dc32b6436f55 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Jan 2005 20:58:16 +0200 Subject: [PATCH 16/48] os0file.c: Fix Windows porting bugs that broke ibbackup: 1) wrong error check in for CreateDirectory(), 2) wrong error check if the file did not exist in DeleteFile(), 3) too strict sharing restrictions in os_file_create_simple(): when ibbackup called that function, it would not allow mysqld to write to the file innobase/os/os0file.c: Fix Windows porting bugs that broke ibbackup: 1) wrong error check in for CreateDirectory(), 2) wrong error check if the file did not exist in DeleteFile(), 3) too strict sharing restrictions in os_file_create_simple(): when ibbackup called that function, it would not allow mysqld to write to the file --- innobase/os/os0file.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 070096f4760..cc743ffad41 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -823,7 +823,7 @@ os_file_create_directory( rcode = CreateDirectory(pathname, NULL); if (!(rcode != 0 || - (GetLastError() == ERROR_FILE_EXISTS && !fail_if_exists))) { + (GetLastError() == ERROR_ALREADY_EXISTS && !fail_if_exists))) { /* failure */ os_file_handle_error(pathname, "CreateDirectory"); @@ -907,8 +907,9 @@ try_again: file = CreateFile(name, access, - FILE_SHARE_READ,/* file can be read also by other - processes */ + FILE_SHARE_READ | FILE_SHARE_WRITE, + /* file can be read ansd written also + by other processes */ NULL, /* default security attributes */ create_flag, attributes, @@ -1013,7 +1014,7 @@ os_file_create_simple_no_error_handling( DWORD create_flag; DWORD access; DWORD attributes = 0; - DWORD share_mode = FILE_SHARE_READ; + DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; ut_a(name); @@ -1336,7 +1337,7 @@ loop: return(TRUE); } - if (GetLastError() == ERROR_PATH_NOT_FOUND) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) { /* the file does not exist, this not an error */ return(TRUE); @@ -1397,7 +1398,7 @@ loop: return(TRUE); } - if (GetLastError() == ERROR_PATH_NOT_FOUND) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) { /* If the file does not exist, we classify this as a 'mild' error and return */ From 47f15599e81f5e75599ac1574e6118a89d98c21e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Jan 2005 21:49:21 +0200 Subject: [PATCH 17/48] ut0ut.c: Use a 32-bit right-shift implementation through a 64-bit integer that should work ok for both gcc and Visual C++; the code depended on defining SIZEOF_LONG, and that is not set when compiling ibbackup innobase/ut/ut0ut.c: Use a 32-bit right-shift implementation through a 64-bit integer that should work ok for both gcc and Visual C++; the code depended on defining SIZEOF_LONG, and that is not set when compiling ibbackup --- innobase/ut/ut0ut.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c index 732380bcb1f..18722149a8f 100644 --- a/innobase/ut/ut0ut.c +++ b/innobase/ut/ut0ut.c @@ -44,13 +44,13 @@ ut_get_high32( /* out: a >> 32 */ ulint a) /* in: ulint */ { -#if SIZEOF_LONG == 4 - UT_NOT_USED(a); + ib_longlong i; - return 0; -#else - return(a >> 32); -#endif + i = (ib_longlong)a; + + i = i >> 32; + + return((ulint)i); } /************************************************************ From 96e4281f059cd6d534338c539a9e44caff984b93 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Jan 2005 16:43:10 -0800 Subject: [PATCH 18/48] Cleanup for lost file descriptors on close table for ha_archive. sql/examples/ha_archive.cc: More comments, fixed issue with lost file descriptors. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/examples/ha_archive.cc | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 52b8b0584bc..a579cac30bd 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -33,6 +33,7 @@ bk@mysql.r18.ru brian@avenger.(none) brian@brian-akers-computer.local brian@private-client-ip-101.oz.net +brian@zim.(none) carsten@tsort.bitbybit.dk davida@isil.mysql.com dellis@goetia.(none) diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index ef609513489..75fba96cad9 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -42,18 +42,20 @@ handle bulk inserts as well (that is if someone was trying to read at the same time since we would want to flush). - A "meta" file is kept. All this file does is contain information on - the number of rows. + A "meta" file is kept alongside the data file. This file serves two purpose. + The first purpose is to track the number of rows in the table. The second + purpose is to determine if the table was closed properly or not. When the + meta file is first opened it is marked as dirty. It is opened when the table + itself is opened for writing. When the table is closed the new count for rows + is written to the meta file and the file is marked as clean. If the meta file + is opened and it is marked as dirty, it is assumed that a crash occured. At + this point an error occurs and the user is told to rebuild the file. + A rebuild scans the rows and rewrites the meta file. If corruption is found + in the data file then the meta file is not repaired. - No attempts at durability are made. You can corrupt your data. A repair - method was added to repair the meta file that stores row information, - but if your data file gets corrupted I haven't solved that. I could - create a repair that would solve this, but do you want to take a - chance of loosing your data? + At some point a recovery method for such a drastic case needs to be divised. - Locks are row level, and you will get a consistant read. Transactions - will be added later (they are not that hard to add at this - stage). + Locks are row level, and you will get a consistant read. For performance as far as table scans go it is quite fast. I don't have good numbers but locally it has out performed both Innodb and MyISAM. For @@ -88,7 +90,6 @@ compression but may speed up ordered searches). Checkpoint the meta file to allow for faster rebuilds. Dirty open (right now the meta file is repaired if a crash occured). - Transactions. Option to allow for dirty reads, this would lower the sync calls, which would make inserts a lot faster, but would mean highly arbitrary reads. @@ -333,6 +334,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) opposite. */ (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE); + /* It is expensive to open and close the data files and since you can't have a gzip file that can be both read and written we keep a writer open @@ -379,6 +381,8 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE); if (gzclose(share->archive_write) == Z_ERRNO) rc= 1; + if (my_close(share->meta_file, MYF(0))) + rc= 1; my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&archive_mutex); From 0f7fae73d198a93956e81eb93af1cbf2d3506013 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 17:33:01 +0100 Subject: [PATCH 19/48] - Bootstrap: Rename already existing build directories to something more useful than *.old. - use the mtime of configure.in instead. This gives us a time stamp of when this last build directory was created, e.g. "mysql-4.0.24-build-2005-01-31-16:47" Build-tools/Bootstrap: - Rename already existing build directories to something more useful than *.old. - use the mtime of configure.in instead. This gives us a time stamp of when this last build directory was created, e.g. "mysql-4.0.24-build-2005-01-31-16:47" --- Build-tools/Bootstrap | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap index 10ebc5c2dd1..827eb4022d7 100755 --- a/Build-tools/Bootstrap +++ b/Build-tools/Bootstrap @@ -210,10 +210,16 @@ if (-d $target_dir) } else { - &logger("Renaming $target_dir to $target_dir.old." . $$); + # Get the time stamp of "configure.in" + @stat= stat("$target_dir/configure.in"); + my $mtime= $stat[9]; + my ($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime); + my $mtime= sprintf("%04d%-02d-%02d-%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min); + + &logger("Renaming $target_dir to $target_dir-$mtime"); $command= "mv "; $command.= "-v " if ($opt_verbose || defined $opt_log); - $command.= "$target_dir $target_dir.old." . $$; + $command.= "$target_dir $target_dir-$mtime"; &run_command($command, "Could not rename $target_dir!"); } } From 0e2e3df2b4bbbcc6c7625a9d2c998fa3c2733417 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 12:17:34 -0800 Subject: [PATCH 20/48] Removed duplicate close call and added archive to the debug build and test. BUILD/compile-ia64-debug-max: Added archive for this build. sql/examples/ha_archive.cc: Removed duplicate close call. --- BUILD/compile-ia64-debug-max | 2 +- sql/examples/ha_archive.cc | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/BUILD/compile-ia64-debug-max b/BUILD/compile-ia64-debug-max index 9cd54de428d..56c36059ea9 100755 --- a/BUILD/compile-ia64-debug-max +++ b/BUILD/compile-ia64-debug-max @@ -9,5 +9,5 @@ then (cd gemini && aclocal && autoheader && aclocal && automake && autoconf) fi -CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server +CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server --with-archive-storage-engine gmake diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index 6bf3d485575..491056d0e59 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -405,7 +405,6 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) rc= 1; if (my_close(share->meta_file, MYF(0))) rc= 1; - my_close(share->meta_file,MYF(0)); my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&archive_mutex); From af39ee001d4c7dbae6aee384802ab0252d2244a1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 22:28:55 +0200 Subject: [PATCH 21/48] mem0pool.c: Fix an assertion failure in 64-bit computers if UNIV_MEM_DEBUG is defined innobase/mem/mem0pool.c: Fix an assertion failure in 64-bit computers if UNIV_MEM_DEBUG is defined --- innobase/mem/mem0pool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c index cd75728c937..bb1f44d6fb7 100644 --- a/innobase/mem/mem0pool.c +++ b/innobase/mem/mem0pool.c @@ -597,8 +597,8 @@ mem_pool_validate( } } - ut_a(free + pool->reserved == pool->size - - (pool->size % MEM_AREA_MIN_SIZE)); + ut_a(free + pool->reserved == pool->size); + mutex_exit(&(pool->mutex)); return(TRUE); From 77cdf79fb4e19b6fceba93596f7ce786620c83a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Jan 2005 19:35:12 -0800 Subject: [PATCH 22/48] Add 'debug' to mysqladmin --help output. (Bug #8207) client/mysqladmin.cc: Add documentation for 'debug' command --- client/mysqladmin.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index d390a152fc7..0da7d5b3acf 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1008,6 +1008,7 @@ static void usage(void) print_defaults("my",load_default_groups); puts("\nWhere command is a one or more of: (Commands may be shortened)\n\ create databasename Create a new database\n\ + debug Instruct server to write debug information to log\n\ drop databasename Delete a database and all its tables\n\ extended-status Gives an extended status message from the server\n\ flush-hosts Flush all cached hosts\n\ From 7da72c932e302386beb243ab9cf61ed61a13f4d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 15:36:48 +0200 Subject: [PATCH 23/48] Remove #if 0 as this only confuses the code withing adding anything --- sql/sql_select.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8dcae9a24b7..29c15741347 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2138,15 +2138,9 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, x = used key parts (1 <= x <= c) */ double rec_per_key; -#if 0 - if (!(rec_per_key=(double) - keyinfo->rec_per_key[keyinfo->key_parts-1])) - rec_per_key=(double) s->records/rec+1; -#else rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ? (double) keyinfo->rec_per_key[keyinfo->key_parts-1] : (double) s->records/rec+1; -#endif if (!s->records) tmp=0; From c53184ebb775290d2e0f8397815832f1c84a8a5c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 16:27:08 +0200 Subject: [PATCH 24/48] Proper fix for comparision with ' ' (Bug #7788 "Table is full" occurs during a multitable update") client/mysqldump.c: Style fixes innobase/include/univ.i: UNIV_DEBUG should not depend on configure --debug but on --debug=full mysql-test/r/compare.result: Added test to find bug in previous bugfix mysql-test/t/compare.test: Added test to find bug in previous bugfix mysys/my_handler.c: Proper fix for comparision with ' ' strings/ctype-big5.c: Proper fix for comparision with ' ' strings/ctype-bin.c: Proper fix for comparision with ' ' strings/ctype-gbk.c: Proper fix for comparision with ' ' strings/ctype-latin1.c: Proper fix for comparision with ' ' strings/ctype-mb.c: Proper fix for comparision with ' ' strings/ctype-simple.c: Proper fix for comparision with ' ' strings/ctype-sjis.c: Proper fix for comparision with ' ' strings/ctype-tis620.c: Proper fix for comparision with ' ' strings/ctype-ucs2.c: Proper fix for comparision with ' ' strings/ctype-utf8.c: Proper fix for comparision with ' ' --- client/mysqldump.c | 36 ++++++++++++++++++------------------ innobase/include/univ.i | 4 ---- mysql-test/r/compare.result | 3 +++ mysql-test/t/compare.test | 2 ++ mysys/my_handler.c | 6 +++--- strings/ctype-big5.c | 4 ++-- strings/ctype-bin.c | 4 ++-- strings/ctype-gbk.c | 4 ++-- strings/ctype-latin1.c | 4 ++-- strings/ctype-mb.c | 4 ++-- strings/ctype-simple.c | 6 +++--- strings/ctype-sjis.c | 4 ++-- strings/ctype-tis620.c | 4 ++-- strings/ctype-ucs2.c | 4 ++-- strings/ctype-utf8.c | 4 ++-- 15 files changed, 47 insertions(+), 46 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index afaa2dc5a6d..52255ccb896 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2091,27 +2091,27 @@ static int dump_all_tables_in_db(char *database) RETURN void */ -static void get_actual_table_name( const char *old_table_name, - char *new_table_name, - int buf_size ) + +static void get_actual_table_name(const char *old_table_name, + char *new_table_name, + int buf_size) { - MYSQL_RES *tableRes; - MYSQL_ROW row; - char query[ NAME_LEN + 50 ]; + MYSQL_RES *tableRes; + MYSQL_ROW row; + char query[ NAME_LEN + 50 ]; + DBUG_ENTER("get_actual_table_name"); - DBUG_ENTER("get_actual_table_name"); + sprintf( query, "SHOW TABLES LIKE '%s'", old_table_name); + if (mysql_query_with_error_report(sock, 0, query)) + { + safe_exit(EX_MYSQLERR); + } - sprintf( query, "SHOW TABLES LIKE '%s'", old_table_name ); - if (mysql_query_with_error_report(sock, 0, query)) - { - safe_exit(EX_MYSQLERR); - } - - tableRes = mysql_store_result( sock ); - row = mysql_fetch_row( tableRes ); - strncpy( new_table_name, row[0], buf_size ); - mysql_free_result(tableRes); -} /* get_actual_table_name */ + tableRes= mysql_store_result( sock ); + row= mysql_fetch_row( tableRes ); + strmake(new_table_name, row[0], buf_size-1); + mysql_free_result(tableRes); +} static int dump_selected_tables(char *db, char **table_names, int tables) diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 6ae4fe1c2ce..625978ffc38 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -80,10 +80,6 @@ memory is read outside the allocated blocks. */ /* Make a non-inline debug version */ -#ifdef DBUG_ON -#define UNIV_DEBUG -#endif /* DBUG_ON */ - /* #define UNIV_DEBUG #define UNIV_MEM_DEBUG diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result index 49ec2dd85cc..6f667aabac0 100644 --- a/mysql-test/r/compare.result +++ b/mysql-test/r/compare.result @@ -39,3 +39,6 @@ DROP TABLE t1; SELECT CHAR(31) = '', '' = CHAR(31); CHAR(31) = '' '' = CHAR(31) 0 0 +SELECT CHAR(30) = '', '' = CHAR(30); +CHAR(30) = '' '' = CHAR(30) +0 0 diff --git a/mysql-test/t/compare.test b/mysql-test/t/compare.test index e3c042e608a..bc20786227b 100644 --- a/mysql-test/t/compare.test +++ b/mysql-test/t/compare.test @@ -33,3 +33,5 @@ DROP TABLE t1; # Bug #8134: Comparison against CHAR(31) at end of string SELECT CHAR(31) = '', '' = CHAR(31); +# Extra test +SELECT CHAR(30) = '', '' = CHAR(30); diff --git a/mysys/my_handler.c b/mysys/my_handler.c index df1e9e55e0a..5ee181ca78e 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -43,7 +43,7 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, return 0; if (skip_end_space && a_length != b_length) { - int swap= 0; + int swap= 1; /* We are using space compression. We have to check if longer key has next character < ' ', in which case it's less than the shorter @@ -57,12 +57,12 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, /* put shorter key in a */ a_length= b_length; a= b; - swap= -1 ^ 1; /* swap sign of result */ + swap= -1; /* swap sign of result */ } for (end= a + a_length-length; a < end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } return 0; } diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 997b8ce93d6..270b02212af 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -271,7 +271,7 @@ static int my_strnncollsp_big5(CHARSET_INFO * cs __attribute__((unused)), if (!res && a_length != b_length) { const uchar *end; - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -286,7 +286,7 @@ static int my_strnncollsp_big5(CHARSET_INFO * cs __attribute__((unused)), for (end= a + a_length-length; a < end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } } return res; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 95c52512243..618879607ec 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -157,7 +157,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)), } if (a_length != b_length) { - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -172,7 +172,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)), for (end= a + a_length-length; a < end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } } return 0; diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 731ad58a2fb..9daa9f90f3c 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -2632,7 +2632,7 @@ static int my_strnncollsp_gbk(CHARSET_INFO * cs __attribute__((unused)), if (!res && a_length != b_length) { const uchar *end; - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -2647,7 +2647,7 @@ static int my_strnncollsp_gbk(CHARSET_INFO * cs __attribute__((unused)), for (end= a + a_length-length; a < end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } } return res; diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 32d9a227c2f..4ab101add5b 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -611,7 +611,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)), if (a != a_end || b != b_end) { - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -626,7 +626,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)), for ( ; a < a_end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } } return 0; diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 731fc460cef..6cf48291c91 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -389,7 +389,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)), } if (a_length != b_length) { - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -404,7 +404,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)), for (end= a + a_length-length; a < end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } } return 0; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 4dc6a1be27b..1a09b16a264 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -143,7 +143,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length, } if (a_length != b_length) { - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -153,12 +153,12 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length, /* put shorter key in s */ a_length= b_length; a= b; - swap= -1^1; /* swap sign of result */ + swap= -1; /* swap sign of result */ } for (end= a + a_length-length; a < end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } } return 0; diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index c0b33a13cdd..0cb30a9b6ee 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -251,7 +251,7 @@ static int my_strnncollsp_sjis(CHARSET_INFO *cs __attribute__((unused)), int res= my_strnncoll_sjis_internal(cs, &a, a_length, &b, b_length); if (!res && (a != a_end || b != b_end)) { - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -266,7 +266,7 @@ static int my_strnncollsp_sjis(CHARSET_INFO *cs __attribute__((unused)), for (; a < a_end ; a++) { if (*a != ' ') - return ((int) *a - (int) ' ') ^ swap; + return (*a < ' ') ? -swap : swap; } } return res; diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 3a43c556ac8..6a6c55d214e 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -589,7 +589,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)), } if (a_length != b_length) { - int swap= 0; + int swap= 1; /* Check the next not space character of the longer key. If it's < ' ', then it's smaller than the other key. @@ -605,7 +605,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)), { if (*a != ' ') { - res= ((int) *a - (int) ' ') ^ swap; + res= (*a < ' ') ? -swap : swap; goto ret; } } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 936e2b6fdce..ea11f8816a5 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -275,7 +275,7 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)), if (slen != tlen) { - int swap= 0; + int swap= 1; if (slen < tlen) { s= t; @@ -286,7 +286,7 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)), for ( ; s < se ; s+= 2) { if (s[0] || s[1] != ' ') - return (((int)s[0] << 8) + (int) s[1] - (int) ' ') ^ swap; + return (s[0] == 0 && s[1] < ' ') ? -swap : swap; } } return 0; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 502d0ec285e..486d428bf1d 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2077,7 +2077,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs, if (slen != tlen) { - int swap= 0; + int swap= 1; if (slen < tlen) { slen= tlen; @@ -2098,7 +2098,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs, for ( ; s < se; s++) { if (*s != ' ') - return ((int)*s - (int) ' ') ^ swap; + return (*s < ' ') ? -swap : swap; } } return 0; From 3a890c8a874fe52dcac99864b6c4785de0210549 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 16:49:23 +0100 Subject: [PATCH 25/48] ndb - 1) New testcase Check every combination of ins/upd/del of length 5 Check reading savepoint's 2) Fix 1 liner in acc wrt committing read ndb/include/ndbapi/NdbConnection.hpp: Make testcase friend ndb/src/kernel/blocks/dbacc/DbaccMain.cpp: Fix so that committing a READ can _not_ result in setting elementIsDisappeared ndb/test/include/NDBT_Test.hpp: Make copy of testcase name ndb/test/ndbapi/testOperations.cpp: New testcase Check every combination of ins/upd/del of length 5 Check reading savepoint's ndb/test/src/HugoOperations.cpp: Close transaction in destructor ndb/test/src/NDBT_Test.cpp: Make copy of testcase name --- ndb/include/ndbapi/NdbConnection.hpp | 2 + ndb/src/kernel/blocks/dbacc/DbaccMain.cpp | 3 +- ndb/test/include/NDBT_Test.hpp | 4 +- ndb/test/ndbapi/testOperations.cpp | 283 ++++++++++++++++++++++ ndb/test/src/HugoOperations.cpp | 4 + ndb/test/src/NDBT_Test.cpp | 12 +- 6 files changed, 302 insertions(+), 6 deletions(-) diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index 166355cae17..f173cd8ac6e 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -687,6 +687,8 @@ private: void remove_list(NdbOperation*& head, NdbOperation*); void define_scan_op(NdbIndexScanOperation*); + + friend int runOperations(class NDBT_Context*, class NDBT_Step*); }; inline diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index 5c7cc597672..a82c96beebd 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -5704,7 +5704,8 @@ void Dbacc::commitOperation(Signal* signal) Uint32 tmp2Olq; if ((operationRecPtr.p->commitDeleteCheckFlag == ZFALSE) && - (operationRecPtr.p->operation != ZSCAN_OP)) { + (operationRecPtr.p->operation != ZSCAN_OP) && + (operationRecPtr.p->operation != ZREAD)) { jam(); /* This method is used to check whether the end result of the transaction will be to delete the tuple. In this case all operation will be marked diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp index 8b69faebde8..a60228c1a5d 100644 --- a/ndb/test/include/NDBT_Test.hpp +++ b/ndb/test/include/NDBT_Test.hpp @@ -188,7 +188,7 @@ public: NDBT_TestCase(NDBT_TestSuite* psuite, const char* name, const char* comment); - virtual ~NDBT_TestCase(){} + virtual ~NDBT_TestCase() {} // This is the default executor of a test case // When a test case is executed it will need to be suplied with a number of @@ -225,6 +225,8 @@ protected: void stopTimer(NDBT_Context*); void printTimer(NDBT_Context*); + BaseString _name; + BaseString _comment; const char* name; const char* comment; NDBT_TestSuite* suite; diff --git a/ndb/test/ndbapi/testOperations.cpp b/ndb/test/ndbapi/testOperations.cpp index 949f08281a5..92cc3e81b1a 100644 --- a/ndb/test/ndbapi/testOperations.cpp +++ b/ndb/test/ndbapi/testOperations.cpp @@ -98,6 +98,11 @@ OperationTestCase matrix[] = { result = NDBT_FAILED; \ break; } +#define C3(b) if (!(b)) { \ + g_err << "ERR: "<< step->getName() \ + << " failed on line " << __LINE__ << endl; \ + abort(); return NDBT_FAILED; } + int runOp(HugoOperations & hugoOps, Ndb * pNdb, @@ -228,11 +233,287 @@ runClearTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +enum OPS { o_DONE= 0, o_INS= 1, o_UPD= 2, o_DEL= 3 }; +typedef Vector Sequence; + +static +bool +valid(const Sequence& s) +{ + if(s.size() == 0) + return false; + + for(size_t i = 1; i>= 2; + } +} + +static +void +generate(Vector& out, size_t len) +{ + int max= 1; + while(len) + { + max <<= 2; + len--; + } + + len= 1; + for(int i = 0; i= len && valid(tmp)) + { + out.push_back(i); + len= tmp.size(); + } + else + { + //ndbout << "DISCARD: " << tmp << endl; + } + } +} + +int +runOperations(NDBT_Context* ctx, NDBT_Step* step) +{ + const Uint32 DUMMY = 0; + const Uint32 ROW = 1; + + int tmp; + Ndb* pNdb = GETNDB(step); + + Uint32 seqNo = ctx->getProperty("Sequence", (Uint32)0); + Uint32 no_wait = NdbOperation::LM_CommittedRead* + ctx->getProperty("NoWait", (Uint32)1); + + if(seqNo == 0) + { + return NDBT_FAILED; + } + + Sequence seq; + generate(seq, seqNo); + + { + // Dummy row + HugoOperations hugoOps(*ctx->getTab()); + C3(hugoOps.startTransaction(pNdb) == 0); + C3(hugoOps.pkInsertRecord(pNdb, DUMMY, 1, 0) == 0); + C3(hugoOps.execute_Commit(pNdb) == 0); + } + + const bool inital_row= (seq[0] != o_INS); + if(inital_row) + { + HugoOperations hugoOps(*ctx->getTab()); + C3(hugoOps.startTransaction(pNdb) == 0); + C3(hugoOps.pkInsertRecord(pNdb, ROW, 1, 0) == 0); + C3(hugoOps.execute_Commit(pNdb) == 0); + } + + HugoOperations trans1(*ctx->getTab()); + C3(trans1.startTransaction(pNdb) == 0); + for(size_t i = 0; igetTab()); + C3(other.startTransaction(pNdb) == 0); + C3(other.pkReadRecord(pNdb, ROW, 1, (NdbOperation::LockMode)j) == 0); + tmp= other.execute_Commit(pNdb); + if(j == NdbOperation::LM_CommittedRead) + { + C3(inital_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626); + } + else + { + C3(tmp == 266); + } + } + + /** + * Verify savepoint read + */ + Uint64 transactionId= trans1.getTransaction()->getTransactionId(); + for(size_t k=0; k<=i+1; k++) + { + for(size_t j = 0; j<3; j++) + { + const NdbOperation::LockMode lm= (NdbOperation::LockMode)j; + + HugoOperations same(*ctx->getTab()); + C3(same.startTransaction(pNdb) == 0); + same.getTransaction()->setTransactionId(transactionId); // Cheat + + /** + * Increase savepoint to k + */ + for(size_t l = 1; l<=k; l++) + { + C3(same.pkReadRecord(pNdb, DUMMY, 1, lm) == 0); // Read dummy row + C3(same.execute_NoCommit(pNdb) == 0); + g_info << "savepoint: " << l << endl; + } + + g_info << "op(" << k << ", " << i << "): " + << " lock mode " << lm << endl; + + C3(same.pkReadRecord(pNdb, ROW, 1, lm) == 0); // Read real row + tmp= same.execute_Commit(pNdb); + if(k == 0) + { + if(inital_row) + { + C3(tmp == 0 && same.verifyUpdatesValue(0) == 0); + } else + { + C3(tmp == 626); + } + } + else + { + switch(seq[k-1]){ + case o_INS: + case o_UPD: + C3(tmp == 0 && same.verifyUpdatesValue(k) == 0); + break; + case o_DEL: + C3(tmp == 626); + break; + case o_DONE: + abort(); + } + } + } + } + } + C3(trans1.execute_Commit(pNdb) == 0); + + return NDBT_OK; +} + int main(int argc, const char** argv){ ndb_init(); + Vector tmp; + generate(tmp, 5); + NDBT_TestSuite ts("testOperations"); + for(size_t i = 0; isetProperty("Sequence", tmp[i]); + pt->addInitializer(new NDBT_Initializer(pt, + "runClearTable", + runClearTable)); + + pt->addStep(new NDBT_ParallelStep(pt, + name.c_str()+1, + runOperations)); + + pt->addFinalizer(new NDBT_Finalizer(pt, + "runClearTable", + runClearTable)); + + ts.addTest(pt); + } + for(Uint32 i = 0; i; +template class Vector; diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp index e8e2d992345..caaa3a3a0ee 100644 --- a/ndb/test/src/HugoOperations.cpp +++ b/ndb/test/src/HugoOperations.cpp @@ -401,6 +401,10 @@ HugoOperations::HugoOperations(const NdbDictionary::Table& _tab): HugoOperations::~HugoOperations(){ deallocRows(); + if (pTrans != NULL){ + pTrans->close(); + pTrans = NULL; + } } diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp index bbbde008938..0e5f744d5ea 100644 --- a/ndb/test/src/NDBT_Test.cpp +++ b/ndb/test/src/NDBT_Test.cpp @@ -327,13 +327,17 @@ NDBT_Finalizer::NDBT_Finalizer(NDBT_TestCase* ptest, NDBT_TestCase::NDBT_TestCase(NDBT_TestSuite* psuite, const char* pname, const char* pcomment) : - name(pname) , - comment(pcomment), - suite(psuite){ + name(strdup(pname)) , + comment(strdup(pcomment)), + suite(psuite) +{ + _name.assign(pname); + _comment.assign(pcomment); + name= _name.c_str(); + comment= _comment.c_str(); assert(suite != NULL); } - NDBT_TestCaseImpl1::NDBT_TestCaseImpl1(NDBT_TestSuite* psuite, const char* pname, const char* pcomment) : From 9d548d7f2253ea5dd1f78960f61ba2f0822db177 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 17:08:39 +0100 Subject: [PATCH 26/48] ndb - Put all output from ndb tools during mysql-test-run into log file mysql-test/mysql-test-run.sh: Put all output from ndb_tool into log file mysql-test/t/ndb_autodiscover.test: Put all output from ndb_tool into log file mysql-test/t/ndb_restore.test: Put all output from ndb_tool into log file --- mysql-test/mysql-test-run.sh | 3 +++ mysql-test/t/ndb_autodiscover.test | 10 +++++----- mysql-test/t/ndb_restore.test | 6 +++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index c2ac26217b9..44d08d65759 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -472,6 +472,7 @@ export MASTER_MYPORT MASTER_MYPORT1 SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MA NDBCLUSTER_BASE_PORT=`expr $NDBCLUSTER_PORT + 2` NDBCLUSTER_OPTS="--port=$NDBCLUSTER_PORT --port-base=$NDBCLUSTER_BASE_PORT --data-dir=$MYSQL_TEST_DIR/var --ndb_mgm-extra-opts=$NDB_MGM_EXTRA_OPTS --ndb_mgmd-extra-opts=$NDB_MGMD_EXTRA_OPTS --ndbd-extra-opts=$NDBD_EXTRA_OPTS" NDB_BACKUP_DIR=$MYSQL_TEST_DIR/var/ndbcluster-$NDBCLUSTER_PORT +NDB_TOOLS_OUTPUT=$MYSQL_TEST_DIR/var/log/ndb_tools.log if [ x$SOURCE_DIST = x1 ] ; then MY_BASEDIR=$MYSQL_TEST_DIR @@ -637,6 +638,7 @@ export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR export NDB_TOOLS_DIR export NDB_MGM export NDB_BACKUP_DIR +export NDB_TOOLS_OUTPUT MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \ --user=$DBUSER --password=$DBPASSWD --silent -v --skip-safemalloc \ @@ -978,6 +980,7 @@ start_ndbcluster() { if [ ! -z "$USE_NDBCLUSTER" ] then + rm -f $NDBAPI_OUTPUT if [ -z "$USE_RUNNING_NDBCLUSTER" ] then echo "Starting ndbcluster" diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index 6551732adba..037115f5e82 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -199,7 +199,7 @@ insert into t4 values (1, "Automatic"); select * from t4; # Remove the table from NDB -system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 >> $NDB_TOOLS_OUTPUT ; # # Test that correct error is returned @@ -230,7 +230,7 @@ select * from t4; flush tables; # Remove the table from NDB -system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 >> $NDB_TOOLS_OUTPUT ; SHOW TABLES; @@ -264,8 +264,8 @@ insert into t8 values (8, "myisam table 8"); insert into t9 values (9); # Remove t3, t5 from NDB -system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 > /dev/null ; -system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 > /dev/null ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 >> $NDB_TOOLS_OUTPUT ; +system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 >> $NDB_TOOLS_OUTPUT ; # Remove t6, t7 from disk system rm var/master-data/test/t6.frm > /dev/null ; system rm var/master-data/test/t7.frm > /dev/null ; @@ -479,4 +479,4 @@ create table t10 ( insert into t10 values (1, 'kalle'); ---exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB` > /dev/null 2>&1 || true +--exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB` >> $NDB_TOOLS_OUTPUT 2>&1 || true diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test index 09939ec119d..d413453fb0e 100644 --- a/mysql-test/t/ndb_restore.test +++ b/mysql-test/t/ndb_restore.test @@ -141,10 +141,10 @@ create table t8_c engine=ndbcluster as select * from t8; create table t9_c engine=ndbcluster as select * from t9; ---exec $NDB_MGM --no-defaults -e "start backup" > /dev/null +--exec $NDB_MGM --no-defaults -e "start backup" >> $NDB_TOOLS_OUTPUT drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; ---exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 > /tmp/ndb_restore.out ---exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 > /tmp/ndb_restore.out +--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT +--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT show tables; From 0e50e32480920c29f2efacfcbfa35c9c93838840 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 19:48:05 +0000 Subject: [PATCH 27/48] WL#1967 Support for COMMIT/ROLLBACK optional arguments innobase/include/trx0roll.h: WL#1967 trx_release_savepoint_for_mysql() innobase/trx/trx0roll.c: WL#1967 trx_release_savepoint_for_mysql() mysql-test/r/innodb.result: WL#1967 Test for savepoint release mysql-test/t/innodb.test: WL#1967 Test for savepoint release sql/ha_innodb.cc: WL#1967 innobase_release_savepoint_name() sql/ha_innodb.h: WL#1967 innobase_release_savepoint_name() sql/handler.cc: WL#1967 ha_release_savepoint_name() sql/handler.h: WL#1967 ha_release_savepoint_name() sql/lex.h: WL#1967 New tokens: CHAIN, RELEASE sql/mysqld.cc: WL#1967 new option: completion-type sql/set_var.cc: WL#1967 new option: completion-type sql/sql_class.h: WL#1967 new option: completion-type sql/sql_lex.h: WL#1967 Support RELEASE SAVEPOINT additional flags to support COMMIT/ROLLBACK options sql/sql_parse.cc: WL#1967 Transaction operations in mysql_endtrans(), begin_trans() sql/sql_yacc.yy: WL#1967 Support COMMIT/ROLLBACK optional args --- innobase/include/trx0roll.h | 15 +++ innobase/trx/trx0roll.c | 45 ++++++++ mysql-test/r/innodb.result | 34 +++++- mysql-test/t/innodb.test | 13 +++ sql/ha_innodb.cc | 25 +++++ sql/ha_innodb.h | 3 + sql/handler.cc | 29 +++++ sql/handler.h | 1 + sql/lex.h | 2 + sql/mysqld.cc | 6 +- sql/set_var.cc | 23 ++++ sql/sql_class.h | 1 + sql/sql_lex.h | 3 +- sql/sql_parse.cc | 213 ++++++++++++++++++++++++++---------- sql/sql_yacc.yy | 65 +++++++++-- 15 files changed, 402 insertions(+), 76 deletions(-) diff --git a/innobase/include/trx0roll.h b/innobase/include/trx0roll.h index 9d025da4a5f..944142a299d 100644 --- a/innobase/include/trx0roll.h +++ b/innobase/include/trx0roll.h @@ -225,6 +225,21 @@ trx_savepoint_for_mysql( position corresponding to this connection at the time of the savepoint */ + +/*********************************************************************** +Releases a named savepoint. Savepoints which +were set after this savepoint are deleted. */ + +ulint +trx_release_savepoint_for_mysql( +/*================================*/ + /* out: if no savepoint + of the name found then + DB_NO_SAVEPOINT, + otherwise DB_SUCCESS */ + trx_t* trx, /* in: transaction handle */ + const char* savepoint_name); /* in: savepoint name */ + /*********************************************************************** Frees savepoint structs. */ diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index e5cffd2a4f3..cba3040fd0e 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -316,6 +316,51 @@ trx_savepoint_for_mysql( return(DB_SUCCESS); } +/*********************************************************************** +Releases a named savepoint. Savepoints which +were set after this savepoint are deleted. */ + +ulint +trx_release_savepoint_for_mysql( +/*================================*/ + /* out: if no savepoint + of the name found then + DB_NO_SAVEPOINT, + otherwise DB_SUCCESS */ + trx_t* trx, /* in: transaction handle */ + const char* savepoint_name) /* in: savepoint name */ +{ + trx_named_savept_t* savep; + + savep = UT_LIST_GET_FIRST(trx->trx_savepoints); + + while (savep != NULL) { + if (0 == ut_strcmp(savep->name, savepoint_name)) { + /* Found */ + break; + } + savep = UT_LIST_GET_NEXT(trx_savepoints, savep); + } + + if (savep == NULL) { + + return(DB_NO_SAVEPOINT); + } + + /* We can now free all savepoints strictly later than this one */ + + trx_roll_savepoints_free(trx, savep); + + /* Now we can free this savepoint too */ + + UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); + + mem_free(savep->name); + mem_free(savep); + + return(DB_SUCCESS); +} + /*********************************************************************** Returns a transaction savepoint taken at this point in time. */ diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 8d1c4e3fc90..5928688ca81 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -249,6 +249,30 @@ n 4 5 6 +set autocommit=0; +begin; +savepoint `my_savepoint`; +insert into t1 values (7); +savepoint `savept2`; +insert into t1 values (3); +select n from t1; +n +3 +4 +5 +6 +7 +rollback to savepoint `savept2`; +release savepoint `my_savepoint`; +select n from t1; +n +4 +5 +6 +7 +rollback to savepoint `my_savepoint`; +ERROR HY000: Got error 153 during ROLLBACK +set autocommit=1; rollback; drop table t1; create table t1 (n int not null primary key) engine=innodb; @@ -1609,14 +1633,14 @@ t2 CREATE TABLE `t2` ( drop table t2, t1; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 24 +Binlog_cache_use 25 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 0 create table t1 (a int) engine=innodb; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 25 +Binlog_cache_use 26 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 @@ -1625,7 +1649,7 @@ delete from t1; commit; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 26 +Binlog_cache_use 27 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 @@ -1693,10 +1717,10 @@ Variable_name Value Innodb_rows_deleted 2070 show status like "Innodb_rows_inserted"; Variable_name Value -Innodb_rows_inserted 31706 +Innodb_rows_inserted 31708 show status like "Innodb_rows_read"; Variable_name Value -Innodb_rows_read 80153 +Innodb_rows_read 80162 show status like "Innodb_rows_updated"; Variable_name Value Innodb_rows_updated 29530 diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 4fff24a61d5..da27fcfc734 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -129,6 +129,19 @@ insert into t1 values (6); -- error 1062 insert into t1 values (4); select n from t1; +set autocommit=0; +begin; +savepoint `my_savepoint`; +insert into t1 values (7); +savepoint `savept2`; +insert into t1 values (3); +select n from t1; +rollback to savepoint `savept2`; +release savepoint `my_savepoint`; +select n from t1; +-- error 1181 +rollback to savepoint `my_savepoint`; +set autocommit=1; # nop rollback; drop table t1; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index d6b6c140fbf..32b203f7ad6 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1612,6 +1612,31 @@ innobase_rollback_to_savepoint( DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); } +/********************************************************************* +Release transaction savepoint name. */ + +int +innobase_release_savepoint_name( +/*===========================*/ + /* out: 0 if success, HA_ERR_NO_SAVEPOINT if + no savepoint with the given name */ + THD* thd, /* in: handle to the MySQL thread of the user + whose transaction should be rolled back */ + char* savepoint_name) /* in: savepoint name */ +{ + ib_longlong mysql_binlog_cache_pos; + int error = 0; + trx_t* trx; + + DBUG_ENTER("innobase_release_savepoint_name"); + + trx = check_trx_exists(thd); + + error = trx_release_savepoint_for_mysql(trx, savepoint_name); + + DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); +} + /********************************************************************* Sets a transaction savepoint. */ diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 2154e238fd1..7a48de52422 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -244,6 +244,9 @@ int innobase_savepoint( THD* thd, char* savepoint_name, my_off_t binlog_cache_pos); +int innobase_release_savepoint_name( + THD* thd, + char* savepoint_name); int innobase_close_connection(THD *thd); int innobase_drop_database(char *path); bool innodb_show_status(THD* thd); diff --git a/sql/handler.cc b/sql/handler.cc index 059d1feaed1..a9bb19158dd 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -869,6 +869,35 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name) DBUG_RETURN(error); } +int ha_release_savepoint_name(THD *thd, char *savepoint_name) +{ + my_off_t binlog_cache_pos=0; + bool operation_done=0; + int error=0; + DBUG_ENTER("ha_release_savepoint_name"); +#ifdef USING_TRANSACTIONS + if (opt_using_transactions) + { +#ifdef HAVE_INNOBASE_DB + if ((error=innobase_release_savepoint_name(thd, savepoint_name))) + { + my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error); + error=1; + } + else if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); + if (mysql_bin_log.write(&qinfo)) + error= 1; + } + operation_done=1; +#endif + } +#endif /* USING_TRANSACTIONS */ + + DBUG_RETURN(error); +} + /* Sets a transaction savepoint. diff --git a/sql/handler.h b/sql/handler.h index e5a794ca1b2..2b5c66fd886 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -653,6 +653,7 @@ int ha_commit_trans(THD *thd, THD_TRANS *trans); int ha_rollback_trans(THD *thd, THD_TRANS *trans); int ha_rollback_to_savepoint(THD *thd, char *savepoint_name); int ha_savepoint(THD *thd, char *savepoint_name); +int ha_release_savepoint_name(THD *thd, char *savepoint_name); int ha_autocommit_or_rollback(THD *thd, int error); void ha_set_spin_retries(uint retries); bool ha_flush_logs(void); diff --git a/sql/lex.h b/sql/lex.h index 871d1d99750..7b03950b35a 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -99,6 +99,7 @@ static SYMBOL symbols[] = { { "CASCADE", SYM(CASCADE)}, { "CASCADED", SYM(CASCADED)}, { "CASE", SYM(CASE_SYM)}, + { "CHAIN", SYM(CHAIN_SYM)}, { "CHANGE", SYM(CHANGE)}, { "CHANGED", SYM(CHANGED)}, { "CHAR", SYM(CHAR_SYM)}, @@ -385,6 +386,7 @@ static SYMBOL symbols[] = { { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)}, { "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM)}, { "RELAY_THREAD", SYM(RELAY_THREAD)}, + { "RELEASE", SYM(RELEASE_SYM)}, { "RELOAD", SYM(RELOAD)}, { "RENAME", SYM(RENAME)}, { "REPAIR", SYM(REPAIR)}, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9b39f51fc5b..e4df359d35c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4176,7 +4176,7 @@ enum options_mysqld OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_SKIP_SAFEMALLOC, - OPT_TEMP_POOL, OPT_TX_ISOLATION, + OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE, OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS, OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL, OPT_SAFE_USER_CREATE, OPT_SQL_MODE, @@ -4363,6 +4363,10 @@ Disable with --skip-bdb (will save memory).", {"collation-server", 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 }, + {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.", + (gptr*) &global_system_variables.completion_type, + (gptr*) &max_system_variables.completion_type, 0, GET_ULONG, + REQUIRED_ARG, 0, 0, 2, 0, 1, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, "Use concurrent insert with MyISAM. Disable with --skip-concurrent-insert.", (gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert, diff --git a/sql/set_var.cc b/sql/set_var.cc index 7a528467e24..541bcf0ff7d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -100,6 +100,8 @@ static int check_pseudo_thread_id(THD *thd, set_var *var); static bool set_log_bin(THD *thd, set_var *var); static void fix_low_priority_updates(THD *thd, enum_var_type type); static void fix_tx_isolation(THD *thd, enum_var_type type); +static int check_completion_type(THD *thd, set_var *var); +static void fix_completion_type(THD *thd, enum_var_type type); static void fix_net_read_timeout(THD *thd, enum_var_type type); static void fix_net_write_timeout(THD *thd, enum_var_type type); static void fix_net_retry_count(THD *thd, enum_var_type type); @@ -149,6 +151,10 @@ sys_var_character_set_database sys_character_set_database("character_set_databas 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_thd_ulong sys_completion_type("completion_type", + &SV::completion_type, + check_completion_type, + fix_completion_type); sys_var_collation_connection sys_collation_connection("collation_connection"); sys_var_collation_database sys_collation_database("collation_database"); sys_var_collation_server sys_collation_server("collation_server"); @@ -532,6 +538,7 @@ sys_var *sys_variables[]= &sys_collation_connection, &sys_collation_database, &sys_collation_server, + &sys_completion_type, &sys_concurrent_insert, &sys_connect_timeout, &sys_date_format, @@ -708,6 +715,7 @@ struct show_var_st init_vars[]= { {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, {sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS}, {sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS}, + {sys_completion_type.name, (char*) &sys_completion_type, SHOW_SYS}, {sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS}, {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS}, {"datadir", mysql_real_data_home, SHOW_CHAR}, @@ -1122,6 +1130,21 @@ static void fix_tx_isolation(THD *thd, enum_var_type type) thd->variables.tx_isolation); } +static void fix_completion_type(THD *thd __attribute__(unused), + enum_var_type type __attribute__(unused)) {} + +static int check_completion_type(THD *thd, set_var *var) +{ + longlong val= var->value->val_int(); + if (val < 0 || val > 2) + { + char buf[64]; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf)); + return 1; + } + return 0; +} + /* If we are changing the thread variable, we have to copy it to NET too diff --git a/sql/sql_class.h b/sql/sql_class.h index 8e6204ab3a3..561cf099592 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -408,6 +408,7 @@ struct system_variables ulong table_type; ulong tmp_table_size; ulong tx_isolation; + ulong completion_type; /* Determines which non-standard SQL behaviour should be enabled */ ulong sql_mode; /* check of key presence in updatable view */ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 6ed5fb247dc..b2c214bf1fa 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -67,7 +67,7 @@ enum enum_sql_command { SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT, - SQLCOM_COMMIT, SQLCOM_SAVEPOINT, + SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, @@ -718,6 +718,7 @@ typedef struct st_lex uint8 create_view_check; bool drop_if_exists, drop_temporary, local_file, one_shot_set; bool in_comment, ignore_space, verbose, no_write_to_binlog; + bool tx_chain, tx_release; /* special JOIN::prepare mode: changing of query is prohibited */ bool view_prepare_mode; bool safe_to_cache_query; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 820a4f732a3..8b5986a805b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -134,6 +134,27 @@ static bool end_active_trans(THD *thd) DBUG_RETURN(error); } +static bool begin_trans(THD *thd) +{ + int error=0; + if (thd->locked_tables) + { + thd->lock=thd->locked_tables; + thd->locked_tables=0; // Will be automatically closed + close_thread_tables(thd); // Free tables + } + if (end_active_trans(thd)) + error= -1; + else + { + thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | + OPTION_BEGIN); + thd->server_status|= SERVER_STATUS_IN_TRANS; + if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) + error= ha_start_consistent_snapshot(thd); + } + return error; +} #ifdef HAVE_REPLICATION inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) @@ -1262,6 +1283,127 @@ err: DBUG_RETURN(error); } +/* + Ends the current transaction and (maybe) begin the next + First uint4 in packet is completion type + Remainder is savepoint name (if required) + + SYNOPSIS + mysql_endtrans() + thd Current thread + completion Completion type + savepoint_name Savepoint when doing ROLLBACK_SAVEPOINT_NAME + or RELEASE_SAVEPOINT_NAME + release (OUT) indicator for release operation + + RETURN + 0 - OK +*/ + +enum enum_mysql_completiontype { + ROLLBACK_RELEASE=-2, + COMMIT_RELEASE=-1, + COMMIT=0, + ROLLBACK=1, + SAVEPOINT_NAME_ROLLBACK=2, + SAVEPOINT_NAME_RELEASE=4, + COMMIT_AND_CHAIN=6, + ROLLBACK_AND_CHAIN=7, +}; + +int mysql_endtrans(THD *thd, enum enum_mysql_completiontype completion, + char *savepoint_name) +{ + bool do_release= 0; + int res= 0; + LEX *lex= thd->lex; + DBUG_ENTER("mysql_endtrans"); + + switch (completion) { + case COMMIT: + /* + We don't use end_active_trans() here to ensure that this works + even if there is a problem with the OPTION_AUTO_COMMIT flag + (Which of course should never happen...) + */ + thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + if (!(res= ha_commit(thd))) + send_ok(thd); + break; + case COMMIT_RELEASE: + do_release= 1; + case COMMIT_AND_CHAIN: + res= end_active_trans(thd); + if (!res && completion == COMMIT_AND_CHAIN) + res= begin_trans(thd); + if (!res) + send_ok(thd); + break; + case ROLLBACK_RELEASE: + do_release= 1; + case ROLLBACK: + case ROLLBACK_AND_CHAIN: + { + bool warn= 0; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + if (!ha_rollback(thd)) + { + /* + If a non-transactional table was updated, warn; don't warn if this is a + slave thread (because when a slave thread executes a ROLLBACK, it has + been read from the binary log, so it's 100% sure and normal to produce + error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the + slave SQL thread, it would not stop the thread but just be printed in + the error log; but we don't want users to wonder why they have this + message in the error log, so we don't send it. + */ + warn= (thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && + !thd->slave_thread; + } + else + res= -1; + thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + if (!res && (completion == ROLLBACK_AND_CHAIN)) + res= begin_trans(thd); + + if (!res) + { + if (warn) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARNING_NOT_COMPLETE_ROLLBACK, + ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); + send_ok(thd); + } + break; + } + case SAVEPOINT_NAME_ROLLBACK: + if (!(res=ha_rollback_to_savepoint(thd, savepoint_name))) + { + if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARNING_NOT_COMPLETE_ROLLBACK, + ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); + send_ok(thd); + } + break; + case SAVEPOINT_NAME_RELEASE: + if (!(res=ha_release_savepoint_name(thd, savepoint_name))) + send_ok(thd); + break; + default: + res= -1; + my_error(ER_UNKNOWN_COM_ERROR, MYF(0)); + DBUG_RETURN(-1); + } + + if (res < 0) + my_error(thd->killed_errno(), MYF(0)); + else if ((res == 0) && do_release) + thd->killed= THD::KILL_CONNECTION; + + DBUG_RETURN(res); +} #ifndef EMBEDDED_LIBRARY @@ -3648,74 +3790,23 @@ unsent_create_error: break; case SQLCOM_BEGIN: - if (thd->locked_tables) - { - thd->lock=thd->locked_tables; - thd->locked_tables=0; // Will be automatically closed - close_thread_tables(thd); // Free tables - } - if (end_active_trans(thd)) + if (begin_trans(thd)) goto error; else - { - thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | - OPTION_BEGIN); - thd->server_status|= SERVER_STATUS_IN_TRANS; - if (!(lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) || - !(res= ha_start_consistent_snapshot(thd))) - send_ok(thd); - } + send_ok(thd); break; case SQLCOM_COMMIT: - /* - We don't use end_active_trans() here to ensure that this works - even if there is a problem with the OPTION_AUTO_COMMIT flag - (Which of course should never happen...) - */ - { - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); - thd->server_status&= ~SERVER_STATUS_IN_TRANS; - if (!ha_commit(thd)) - { - send_ok(thd); - } - else + if (mysql_endtrans(thd, lex->tx_release ? COMMIT_RELEASE : + lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT, 0)) goto error; break; - } case SQLCOM_ROLLBACK: - thd->server_status&= ~SERVER_STATUS_IN_TRANS; - if (!ha_rollback(thd)) - { - /* - If a non-transactional table was updated, warn; don't warn if this is a - slave thread (because when a slave thread executes a ROLLBACK, it has - been read from the binary log, so it's 100% sure and normal to produce - error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the - slave SQL thread, it would not stop the thread but just be printed in - the error log; but we don't want users to wonder why they have this - message in the error log, so we don't send it. - */ - if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARNING_NOT_COMPLETE_ROLLBACK, - ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); - send_ok(thd); - } - else - res= TRUE; - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + if (mysql_endtrans(thd, lex->tx_release ? ROLLBACK_RELEASE : + lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK, 0)) + goto error; break; case SQLCOM_ROLLBACK_TO_SAVEPOINT: - if (!ha_rollback_to_savepoint(thd, lex->savepoint_name)) - { - if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARNING_NOT_COMPLETE_ROLLBACK, - ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); - send_ok(thd); - } - else + if (mysql_endtrans(thd, SAVEPOINT_NAME_ROLLBACK, lex->savepoint_name)) goto error; break; case SQLCOM_SAVEPOINT: @@ -3724,6 +3815,10 @@ unsent_create_error: else goto error; break; + case SQLCOM_RELEASE_SAVEPOINT: + if (mysql_endtrans(thd, SAVEPOINT_NAME_RELEASE, lex->savepoint_name)) + goto error; + break; case SQLCOM_CREATE_PROCEDURE: case SQLCOM_CREATE_SPFUNCTION: { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cc2443bd41b..e1c7c26060a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -219,6 +219,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token CASCADE %token CASCADED %token CAST_SYM +%token CHAIN_SYM %token CHARSET %token CHECKSUM_SYM %token CHECK_SYM @@ -385,6 +386,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token REDUNDANT_SYM %token REFERENCES %token REGEXP +%token RELEASE_SYM %token RELOAD %token RENAME %token REPEATABLE_SYM @@ -690,7 +692,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); 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_leaves fulltext_options spatial_type union_option - start_transaction_opts + start_transaction_opts opt_chain opt_work_and_chain opt_release %type ULONG_NUM raid_types merge_insert_types @@ -777,7 +779,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); query verb_clause create change select do drop insert replace insert2 insert_values update delete truncate rename show describe load alter optimize keycache preload flush - reset purge begin commit rollback savepoint + reset purge begin commit rollback savepoint release slave master_def master_defs master_file_def slave_until_opts repair restore backup analyze check start checksum field_list field_list_item field_spec kill column_def key_def @@ -876,6 +878,7 @@ statement: | preload | prepare | purge + | release | rename | repair | replace @@ -6901,6 +6904,7 @@ keyword: | BTREE_SYM {} | CACHE_SYM {} | CASCADED {} + | CHAIN_SYM {} | CHANGED {} | CHARSET {} | CHECKSUM_SYM {} @@ -7854,25 +7858,66 @@ opt_work: | WORK_SYM {;} ; +opt_chain: + /* empty */ { $$= (Lex->thd->variables.completion_type == 1); } + | AND_SYM NO_SYM CHAIN_SYM { $$=0; } + | AND_SYM CHAIN_SYM { $$=1; } + ; + +opt_release: + /* empty */ { $$= (Lex->thd->variables.completion_type == 2); } + | RELEASE_SYM { $$=1; } + | NO_SYM RELEASE_SYM { $$=0; } + ; + +opt_work_and_chain: + opt_work opt_chain { $$=$2; } + ; + +opt_savepoint: + /* empty */ {} + | SAVEPOINT_SYM {} + ; + commit: - COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;}; + COMMIT_SYM opt_work_and_chain opt_release + { + Lex->sql_command= SQLCOM_COMMIT; + Lex->tx_chain= $2; + Lex->tx_release= $3; + } + ; rollback: - ROLLBACK_SYM - { - Lex->sql_command = SQLCOM_ROLLBACK; + ROLLBACK_SYM opt_work_and_chain opt_release + { + Lex->sql_command= SQLCOM_ROLLBACK; + Lex->tx_chain= $2; + Lex->tx_release= $3; } - | ROLLBACK_SYM TO_SYM SAVEPOINT_SYM ident + | ROLLBACK_SYM opt_work + TO_SYM opt_savepoint ident { Lex->sql_command = SQLCOM_ROLLBACK_TO_SAVEPOINT; - Lex->savepoint_name = $4.str; - }; + Lex->savepoint_name = $5.str; + } + ; + savepoint: SAVEPOINT_SYM ident { Lex->sql_command = SQLCOM_SAVEPOINT; Lex->savepoint_name = $2.str; - }; + } + ; + +release: + RELEASE_SYM SAVEPOINT_SYM ident + { + Lex->sql_command = SQLCOM_RELEASE_SAVEPOINT; + Lex->savepoint_name = $3.str; + } + ; /* UNIONS : glue selects together From eca1f04aa43a9c02a6af1ed9ba9f666a5b684607 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 11:59:44 -0800 Subject: [PATCH 28/48] Make sure mysql_client_test and embedded test clients get added to binary distribution on all platforms. scripts/make_binary_distribution.sh: Add mysql_client_test and embedded versions to basic list of binaries and only list libtool-produced '.libs/' versions as non-netware binaries --- scripts/make_binary_distribution.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 22b51168c23..33d4794e4f7 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -107,8 +107,11 @@ BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \ client/mysql$BS client/mysqlshow$BS client/mysqladmin$BS \ client/mysqldump$BS client/mysqlimport$BS \ client/mysqltest$BS client/mysqlcheck$BS \ - client/mysqlbinlog$BS -"; + client/mysqlbinlog$BS \ + tests/mysql_client_test$BS \ + libmysqld/examples/mysql_client_test_embedded$BS \ + libmysqld/examples/mysqltest_embedded$BS \ + "; # Platform-specific bin dir files: if [ $BASE_SYSTEM = "netware" ] ; then @@ -127,8 +130,9 @@ else client/.libs/mysqltest client/.libs/mysqlcheck \ client/.libs/mysqlbinlog client/.libs/mysqlmanagerc \ client/.libs/mysqlmanager-pwgen tools/.libs/mysqlmanager \ - tests/.libs/mysql_client_test libmysqld/examples/mysql_client_test_embedded \ - libmysqld/examples/mysqltest_embedded \ + tests/.libs/mysql_client_test \ + libmysqld/examples/.libs/mysql_client_test_embedded \ + libmysqld/examples/.libs/mysqltest_embedded \ "; fi From 7d2dcab3a2b67c0dc32846e5ca4e59a9c3cb553b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 23:55:41 +0200 Subject: [PATCH 29/48] InnoDB: Fix debug compile error on Tru64 (Bug #8244) innobase/include/rem0rec.ic: Eliminate int16_t from an assertion, as it is not defined in the same system headers on all platforms. (Bug #8244) --- innobase/include/rem0rec.ic | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 366f1c3f77d..2593fb8edeb 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -279,7 +279,15 @@ rec_get_next_offs( /* Note that for 64 KiB pages, field_value can 'wrap around' and the debug assertion is not valid */ - ut_ad((int16_t)field_value + /* In the following assertion, field_value is interpreted + as signed 16-bit integer in 2's complement arithmetics. + If all platforms defined int16_t in the standard headers, + the expression could be written simpler as + (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE + */ + ut_ad((field_value >= 32768 + ? field_value - 65536 + : field_value) + ut_align_offset(rec, UNIV_PAGE_SIZE) < UNIV_PAGE_SIZE); #endif From 3c04bddb04774237acd11a7ef2c0207a49149a0e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 00:31:06 +0200 Subject: [PATCH 30/48] rem0rec.ic: Fix a debug assertion in rem0rec.ic on AMD64; 4.1 was already fixed innobase/include/rem0rec.ic: Fix a debug assertion in rem0rec.ic on AMD64; 4.1 was already fixed --- innobase/include/rem0rec.ic | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 75a8bdfd6bd..b28c17dc121 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -29,41 +29,41 @@ significant bytes and bits are written below less significant. and the shift needed to obtain each bit-field of the record. */ #define REC_NEXT 2 -#define REC_NEXT_MASK 0xFFFF +#define REC_NEXT_MASK 0xFFFFUL #define REC_NEXT_SHIFT 0 #define REC_SHORT 3 /* This is single byte bit-field */ -#define REC_SHORT_MASK 0x1 +#define REC_SHORT_MASK 0x1UL #define REC_SHORT_SHIFT 0 #define REC_N_FIELDS 4 -#define REC_N_FIELDS_MASK 0x7FE +#define REC_N_FIELDS_MASK 0x7FEUL #define REC_N_FIELDS_SHIFT 1 #define REC_HEAP_NO 5 -#define REC_HEAP_NO_MASK 0xFFF8 +#define REC_HEAP_NO_MASK 0xFFF8UL #define REC_HEAP_NO_SHIFT 3 #define REC_N_OWNED 6 /* This is single byte bit-field */ -#define REC_N_OWNED_MASK 0xF +#define REC_N_OWNED_MASK 0xFUL #define REC_N_OWNED_SHIFT 0 -#define REC_INFO_BITS_MASK 0xF0 +#define REC_INFO_BITS_MASK 0xF0UL #define REC_INFO_BITS_SHIFT 0 /* The deleted flag in info bits */ -#define REC_INFO_DELETED_FLAG 0x20 /* when bit is set to 1, it means the +#define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the record has been delete marked */ /* The following masks are used to filter the SQL null bit from one-byte and two-byte offsets */ -#define REC_1BYTE_SQL_NULL_MASK 0x80 -#define REC_2BYTE_SQL_NULL_MASK 0x8000 +#define REC_1BYTE_SQL_NULL_MASK 0x80UL +#define REC_2BYTE_SQL_NULL_MASK 0x8000UL /* In a 2-byte offset the second most significant bit denotes a field stored to another page: */ -#define REC_2BYTE_EXTERN_MASK 0x4000 +#define REC_2BYTE_EXTERN_MASK 0x4000UL /**************************************************************** Return field length or UNIV_SQL_NULL. */ @@ -133,7 +133,7 @@ rec_set_bit_field_1( ut_ad(rec); ut_ad(offs <= REC_N_EXTRA_BYTES); ut_ad(mask); - ut_ad(mask <= 0xFF); + ut_ad(mask <= 0xFFUL); ut_ad(((mask >> shift) << shift) == mask); ut_ad(((val << shift) & mask) == (val << shift)); @@ -172,8 +172,8 @@ rec_set_bit_field_2( { ut_ad(rec); ut_ad(offs <= REC_N_EXTRA_BYTES); - ut_ad(mask > 0xFF); - ut_ad(mask <= 0xFFFF); + ut_ad(mask > 0xFFUL); + ut_ad(mask <= 0xFFFFUL); ut_ad((mask >> shift) & 1); ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1))); ut_ad(((mask >> shift) << shift) == mask); @@ -189,7 +189,7 @@ rec_set_bit_field_2( + (REC_HEAP_NO_MASK << (8 * (REC_HEAP_NO - 4))) + (REC_N_OWNED_MASK << (8 * (REC_N_OWNED - 3))) + (REC_INFO_BITS_MASK << (8 * (REC_INFO_BITS - 3)))); - if (m != ut_dbg_zero + 0xFFFFFFFF) { + if (m != ut_dbg_zero + 0xFFFFFFFFUL) { fprintf(stderr, "Sum of masks %lx\n", m); ut_error; } From 099f50b67f2a9e87b2e5d996430410533e578454 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 23:43:09 +0000 Subject: [PATCH 31/48] Fix compile problem - line missing. sql/sql_parse.cc: typo - line awol during commit. --- sql/sql_parse.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8b5986a805b..05d6a00805c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -147,6 +147,7 @@ static bool begin_trans(THD *thd) error= -1; else { + LEX *lex= thd->lex; thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | OPTION_BEGIN); thd->server_status|= SERVER_STATUS_IN_TRANS; From d5311abe2cd50c5ea017044941cb1e9eae231442 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 01:43:25 +0200 Subject: [PATCH 32/48] eval0eval.ic: Remove wrong assertion that fails on 64 bits innobase/include/eval0eval.ic: Remove wrong assertion that fails on 64 bits --- innobase/include/eval0eval.ic | 2 -- 1 file changed, 2 deletions(-) diff --git a/innobase/include/eval0eval.ic b/innobase/include/eval0eval.ic index 2530c869206..069cbfe5f37 100644 --- a/innobase/include/eval0eval.ic +++ b/innobase/include/eval0eval.ic @@ -205,8 +205,6 @@ eval_node_copy_and_alloc_val( { byte* data; - ut_ad(UNIV_SQL_NULL > ULINT_MAX); - if (len == UNIV_SQL_NULL) { dfield_set_len(que_node_get_val(node), len); From 6d0d03dab9a74fb512f03ea0275d84d34657ce2a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 18:29:10 -0800 Subject: [PATCH 33/48] Fix QUOTE() to not reuse the input field for output, which resulted in incorrect results when the input was a constant across a multi-row SELECT statement. (Bug #8248) sql/item_strfunc.h: Add tmp_value member sql/item_strfunc.cc: Always allocate a new string for QUOTE(), in case the field is being reused for multiple rows. mysql-test/t/func_str.test: Add regression test mysql-test/r/func_str.result: Add test results --- mysql-test/r/func_str.result | 7 +++++++ mysql-test/t/func_str.test | 5 +++++ sql/item_strfunc.cc | 15 +++++---------- sql/item_strfunc.h | 1 + 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 278cd4dd935..9392f152bb4 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -297,3 +297,10 @@ quote(ltrim(concat(' ', 'a'))) select quote(trim(concat(' ', 'a'))); quote(trim(concat(' ', 'a'))) 'a' +CREATE TABLE t1 SELECT 1 UNION SELECT 2 UNION SELECT 3; +SELECT QUOTE('A') FROM t1; +QUOTE('A') +'A' +'A' +'A' +DROP TABLE t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 79a996e7e78..6c2abd27551 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -193,3 +193,8 @@ select trim(leading 'foo' from 'foo'); select quote(ltrim(concat(' ', 'a'))); select quote(trim(concat(' ', 'a'))); + +# Bad results from QUOTE(). Bug #8248 +CREATE TABLE t1 SELECT 1 UNION SELECT 2 UNION SELECT 3; +SELECT QUOTE('A') FROM t1; +DROP TABLE t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a852906ee2c..aeb63d6af00 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2183,18 +2183,13 @@ String *Item_func_quote::val_str(String *str) for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) new_length+= get_esc_bit(escmask, (uchar) *from); - /* - We have to use realloc() instead of alloc() as we want to keep the - old result in arg - */ - if (arg->realloc(new_length)) + if (tmp_value.alloc(new_length)) goto null; /* - As 'arg' and 'str' may be the same string, we must replace characters - from the end to the beginning + We replace characters from the end to the beginning */ - to= (char*) arg->ptr() + new_length - 1; + to= (char*) tmp_value.ptr() + new_length - 1; *to--= '\''; for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--) { @@ -2222,9 +2217,9 @@ String *Item_func_quote::val_str(String *str) } } *to= '\''; - arg->length(new_length); + tmp_value.length(new_length); null_value= 0; - return arg; + return &tmp_value; null: null_value= 1; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index fc98ebfe67d..ece15484fd9 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -535,6 +535,7 @@ public: class Item_func_quote :public Item_str_func { + String tmp_value; public: Item_func_quote(Item *a) :Item_str_func(a) {} const char *func_name() const { return "quote"; } From 1a2ef2be00e8cbe8ec7f043cb8ce50717bf024cf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 03:58:43 +0100 Subject: [PATCH 34/48] ndb - backup fix, found on powermacg4 ndb/src/kernel/blocks/backup/Backup.cpp: index typo overwrote attribute array, found on powermacg4 --- ndb/src/kernel/blocks/backup/Backup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index d72efdd0a52..2e62979ce8e 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -3201,7 +3201,7 @@ Backup::execSTART_BACKUP_REQ(Signal* signal) return; }//if - tabPtr.p->triggerAllocated[i] = true; + tabPtr.p->triggerAllocated[j] = true; trigPtr.p->backupPtr = ptr.i; trigPtr.p->tableId = tabPtr.p->tableId; trigPtr.p->tab_ptr_i = tabPtr.i; From 2ae812a7d6f5e8789143565364f9700c39c6a424 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 07:51:43 +0300 Subject: [PATCH 35/48] Adjust test results for BUG#7634: The result of EXPLAIN is different if OS doesn't support file sizes > 2G --- mysql-test/r/index_merge.result | 8 ++++---- mysql-test/t/index_merge.test | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 0f217b7b8ab..693cc63ba9e 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -371,11 +371,11 @@ alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(20 update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500; explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B -where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1) -and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1); +where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7or16 = 1 or A.key8=1) +and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7or16 = 1 or B.key8=1); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where -1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where +1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where +1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1) diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index f2f71cbe208..5acbcd8eaeb 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -306,6 +306,11 @@ select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200); update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500; + +# The next query will not use index i7 in intersection if the OS doesn't +# support file sizes > 2GB. (ha_myisam::ref_length depends on this and index +# scan cost estimates depend on ha_myisam::ref_length) +--replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?" 7 7or16 16 7or16 explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1) From 01e1ca9f67ce9fbc23ba37b804a3c81d4ae0b4f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 07:38:11 +0100 Subject: [PATCH 36/48] ndb - (backport from 4.1) Fix weird link error on sol9x86 - use incremental linker configure.in: Fix weird link error on sol9x86 - use incremental linker --- configure.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure.in b/configure.in index 98d060e660c..caa42004736 100644 --- a/configure.in +++ b/configure.in @@ -2954,6 +2954,15 @@ EOF AC_CONFIG_SUBDIRS(innobase) fi +case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc-$have_ndbcluster in + *solaris*-i?86-no-yes) + # ndb fail for whatever strange reason to link Sun Forte/x86 + # unless using incremental linker + CXXFLAGS="$CXXFLAGS -xildon" + ;; + *) ;; +esac + if test X"$have_ndbcluster" = Xyes then if test X"$mysql_cv_compress" != Xyes From 4c76152b356893c74bca0b57de7b48dca8ecd0f1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Feb 2005 23:34:31 -0800 Subject: [PATCH 37/48] func_str.result, func_str.test: Added a test case for bug #7751. item_strfunc.cc: Fixed bug #7751. The function Item_func_conv::val_str did not update the unsigned_flag value. sql/item_strfunc.cc: Fixed bug #7751. The function Item_func_conv::val_str did not update the unsigned_flag value. mysql-test/t/func_str.test: Added a test case for bug #7751. mysql-test/r/func_str.result: Added a test case for bug #7751. --- mysql-test/r/func_str.result | 23 +++++++++++++++++++++++ mysql-test/t/func_str.test | 27 +++++++++++++++++++++++++++ sql/item_strfunc.cc | 1 + 3 files changed, 51 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 0db62b133e7..58d66c7f712 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -703,3 +703,26 @@ NULL select trim('xyz' from null) as "must_be_null"; must_be_null NULL +CREATE TABLE t1 ( +id int(11) NOT NULL auto_increment, +a bigint(20) unsigned default NULL, +PRIMARY KEY (id) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES +('0','16307858876001849059'); +SELECT CONV('e251273eb74a8ee3', 16, 10); +CONV('e251273eb74a8ee3', 16, 10) +16307858876001849059 +EXPLAIN +SELECT id +FROM t1 +WHERE a = 16307858876001849059; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +EXPLAIN +SELECT id +FROM t1 +WHERE a = CONV('e251273eb74a8ee3', 16, 10); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +DROP TABLE t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index a5d95332caa..34bbb2bab0f 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -443,3 +443,30 @@ select quote(trim(concat(' ', 'a'))); # select trim(null from 'kate') as "must_be_null"; select trim('xyz' from null) as "must_be_null"; + +# +# Bug #7751 - conversion for a bigint unsigned constant +# + +CREATE TABLE t1 ( + id int(11) NOT NULL auto_increment, + a bigint(20) unsigned default NULL, + PRIMARY KEY (id) +) ENGINE=MyISAM; + +INSERT INTO t1 VALUES +('0','16307858876001849059'); + +SELECT CONV('e251273eb74a8ee3', 16, 10); + +EXPLAIN +SELECT id + FROM t1 + WHERE a = 16307858876001849059; + +EXPLAIN + SELECT id + FROM t1 + WHERE a = CONV('e251273eb74a8ee3', 16, 10); + +DROP TABLE t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index cd98fb62818..cee3316886a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2171,6 +2171,7 @@ String *Item_func_conv::val_str(String *str) return 0; } null_value=0; + unsigned_flag= !(from_base < 0); if (from_base < 0) dec= my_strntoll(res->charset(),res->ptr(),res->length(),-from_base,&endptr,&err); else From c83412f7059f54b8e7065d63fc544125ebf30aaa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 12:08:20 +0100 Subject: [PATCH 38/48] configure.in don't define UNIV_DEBUG in CFLAGS/CXXFLAGS anymore sql/mysqld.cc hide from the user options that do nothing sql/sql_update.cc better fix for uninitialized used_index configure.in: don't define UNIV_DEBUG in CFLAGS/CXXFLAGS anymore sql/mysqld.cc: hide from the user options that do nothing sql/sql_update.cc: better fix for uninitialized used_index --- configure.in | 4 ++-- sql/mysqld.cc | 2 ++ sql/sql_update.cc | 13 +++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/configure.in b/configure.in index 98d060e660c..e57cdabad25 100644 --- a/configure.in +++ b/configure.in @@ -1677,8 +1677,8 @@ then elif test "$with_debug" = "full" then # Full debug. Very slow in some cases - CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC -DUNIV_DEBUG $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC -DUNIV_DEBUG $CXXFLAGS" + CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" else # Optimized version. No debug CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS" diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c364b408f28..503fb5bfb99 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5215,6 +5215,7 @@ The minimum value for this variable is 4096.", (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0}, +#ifdef DOES_NOTHING_YET {"sync-replication", OPT_SYNC_REPLICATION, "Enable synchronous replication", (gptr*) &global_system_variables.sync_replication, @@ -5230,6 +5231,7 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.sync_replication_timeout, (gptr*) &global_system_variables.sync_replication_timeout, 0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0}, +#endif {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default", (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6ca794283f1..0ec71bdfba3 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -57,11 +57,11 @@ int mysql_update(THD *thd, enum enum_duplicates handle_duplicates, bool ignore) { - bool using_limit=limit != HA_POS_ERROR; + bool using_limit=limit != HA_POS_ERROR; bool safe_update= thd->options & OPTION_SAFE_UPDATES; bool used_key_is_modified, transactional_table, log_delayed; int error=0; - uint used_index= MAX_KEY; + uint used_index; #ifndef NO_EMBEDDED_ACCESS_CHECKS uint want_privilege; #endif @@ -71,7 +71,7 @@ int mysql_update(THD *thd, TABLE *table; SQL_SELECT *select; READ_RECORD info; - TABLE_LIST *update_table_list= ((TABLE_LIST*) + TABLE_LIST *update_table_list= ((TABLE_LIST*) thd->lex->select_lex.table_list.first); DBUG_ENTER("mysql_update"); @@ -159,10 +159,11 @@ int mysql_update(THD *thd, init_ftfuncs(thd, &thd->lex->select_lex, 1); /* Check if we are modifying a key that we are used to search with */ if (select && select->quick) + { + used_index=select->quick->index; used_key_is_modified= (!select->quick->unique_key_range() && - check_if_key_used(table, - (used_index=select->quick->index), - fields)); + check_if_key_used(table, used_index, fields)); + } else if ((used_index=table->file->key_used_on_scan) < MAX_KEY) used_key_is_modified=check_if_key_used(table, used_index, fields); else From d2784c988f3511f08fd2d51ee8bc6a7f2dda1e3b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 13:40:17 +0100 Subject: [PATCH 39/48] Small Do-compile improvements: - added Option "--comment" to be able to override the default compilation comment - improved the abort subroutine to not rely on an external "tail" command (the default /usr/bin/tail on Solaris does not understand the "-n" notation). Get rid of a "useless use of cat" case in the process. Build-tools/Do-compile: - added Option "--comment" to be able to override the default compilation comment - improved the abort subroutine to not rely on an external "tail" command (the default /usr/bin/tail on Solaris does not understand the "-n" notation). Get rid of a "useless use of cat" case in the process. --- Build-tools/Do-compile | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index 4034533f2eb..1c3ff01796f 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -7,7 +7,7 @@ use Sys::Hostname; @config_options= (); @make_options= (); -$opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env=""; +$opt_comment=$opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env=""; $opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix=""; $opt_tmp=$opt_version_suffix=""; $opt_bundled_zlib=$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_one_error=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_archive=$opt_with_cluster=$opt_with_csv=$opt_with_example=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=$opt_readline=0; @@ -17,6 +17,7 @@ GetOptions( "bdb", "build-thread=i", "bundled-zlib", + "comment=s", "config-env=s" => \@config_env, "config-extra-env=s" => \@config_extra_env, "config-options=s" => \@config_options, @@ -110,6 +111,7 @@ $log="$pwd/Logs/$host-$major.$minor$opt_version_suffix.log"; $opt_distribution =~ /(mysql[^\/]*)\.tar/; $ver=$1; $gcc_version=which("gcc"); +$opt_comment= "Official MySQL$opt_version_suffix binary" unless $opt_comment; if (defined($gcc_version) && ! $opt_config_env) { $tmp=`$gcc_version -v 2>&1`; @@ -303,7 +305,7 @@ if ($opt_stage <= 1) } $prefix="/usr/local/mysql"; - check_system("$opt_config_env ./configure --prefix=$prefix --localstatedir=$prefix/data --libexecdir=$prefix/bin --with-comment=\"Official MySQL$opt_version_suffix binary\" --with-extra-charsets=complex --with-server-suffix=\"$opt_version_suffix\" --enable-thread-safe-client --enable-local-infile $opt_config_options","Thank you for choosing MySQL"); + check_system("$opt_config_env ./configure --prefix=$prefix --localstatedir=$prefix/data --libexecdir=$prefix/bin --with-comment=\"$opt_comment\" --with-extra-charsets=complex --with-server-suffix=\"$opt_version_suffix\" --enable-thread-safe-client --enable-local-infile $opt_config_options","Thank you for choosing MySQL"); if (-d "$pwd/$host/include-mysql") { safe_system("cp -r $pwd/$host/include-mysql/* $pwd/$host/$ver/include"); @@ -530,6 +532,10 @@ When running several Do-compile runs in parallel, each build should have its own thread ID, so running the test suites does not cause conflicts with duplicate TCP port numbers. +--comment= +Replace the default compilation comment that is embedded into +the mysqld binary. + --config-env= To set up the environment, like 'CC=cc CXX=gcc CXXFLAGS=-O3' @@ -684,16 +690,20 @@ sub abort if ($opt_user) { - $mail_header_file="$opt_tmp/do-command.$$"; - open(TMP,">$mail_header_file"); + # Take the last 40 lines of the build log + open(LOG, "$log") or die $!; + my @log= ; + close LOG; + splice @log => 0, -40; + my $mail_file="$opt_tmp/do-command.$$"; + open(TMP,">$mail_file") or die $!; print TMP "From: mysqldev\@$full_host_name\n"; print TMP "To: $email\n"; print TMP "Subject: $host($uname): $ver$opt_version_suffix compilation failed\n\n"; + print TMP @log; close TMP; - system("tail -n 40 $log > $log.mail"); - system("cat $mail_header_file $log.mail | $sendmail -t -f $email"); - unlink($mail_header_file); - unlink("$log.mail"); + system("$sendmail -t -f $email < $mail_file"); + unlink($mail_file); } exit 1; } From 8ecae2e65cd09568bdfcedd9b22b5fe41cf6144c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 09:05:52 -0800 Subject: [PATCH 40/48] Fix merge of func_str tests (accidently duplicated a test). mysql-test/t/func_str.test: Remove duplicated test that crept in during merge mysql-test/r/func_str.result: Update results --- mysql-test/r/func_str.result | 26 +++++++++++++------------- mysql-test/t/func_str.test | 7 +------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index a8a7ad0e349..88b1a5ea743 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -325,6 +325,19 @@ trim(trailing 'foo' from 'foo') select trim(leading 'foo' from 'foo'); trim(leading 'foo' from 'foo') +select quote(ltrim(concat(' ', 'a'))); +quote(ltrim(concat(' ', 'a'))) +'a' +select quote(trim(concat(' ', 'a'))); +quote(trim(concat(' ', 'a'))) +'a' +CREATE TABLE t1 SELECT 1 UNION SELECT 2 UNION SELECT 3; +SELECT QUOTE('A') FROM t1; +QUOTE('A') +'A' +'A' +'A' +DROP TABLE t1; select 1=_latin1'1'; 1=_latin1'1' 1 @@ -691,19 +704,6 @@ select count(*) as total, left(c,10) as reg from t1 group by reg order by reg de total reg 10 2004-12-10 drop table t1; -select quote(ltrim(concat(' ', 'a'))); -quote(ltrim(concat(' ', 'a'))) -'a' -select quote(trim(concat(' ', 'a'))); -quote(trim(concat(' ', 'a'))) -'a' -CREATE TABLE t1 SELECT 1 UNION SELECT 2 UNION SELECT 3; -SELECT QUOTE('A') FROM t1; -QUOTE('A') -'A' -'A' -'A' -DROP TABLE t1; select trim(null from 'kate') as "must_be_null"; must_be_null NULL diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 2bf130d1538..6d5974ca5ed 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -206,6 +206,7 @@ select quote(trim(concat(' ', 'a'))); CREATE TABLE t1 SELECT 1 UNION SELECT 2 UNION SELECT 3; SELECT QUOTE('A') FROM t1; DROP TABLE t1; + # Test collation and coercibility # @@ -440,12 +441,6 @@ create table t1 (a int not null primary key, b varchar(40), c datetime); insert into t1 (a,b,c) values (1,'Tom','2004-12-10 12:13:14'),(2,'ball games','2004-12-10 12:13:14'), (3,'Basil','2004-12-10 12:13:14'), (4,'Dean','2004-12-10 12:13:14'),(5,'Ellis','2004-12-10 12:13:14'), (6,'Serg','2004-12-10 12:13:14'), (7,'Sergei','2004-12-10 12:13:14'),(8,'Georg','2004-12-10 12:13:14'),(9,'Salle','2004-12-10 12:13:14'),(10,'Sinisa','2004-12-10 12:13:14'); select count(*) as total, left(c,10) as reg from t1 group by reg order by reg desc limit 0,12; drop table t1; -# crashing bug with QUOTE() and LTRIM() or TRIM() fixed -# Bug #7495 -# - -select quote(ltrim(concat(' ', 'a'))); -select quote(trim(concat(' ', 'a'))); # # Bug#7455 unexpected result: TRIM( FROM ) gives NOT NULL From d4ac4cb112076cb9f79674f46591c3608cc10318 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 19:23:24 +0100 Subject: [PATCH 41/48] - typo fix... --- Build-tools/Bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap index 827eb4022d7..8b769dca3c4 100755 --- a/Build-tools/Bootstrap +++ b/Build-tools/Bootstrap @@ -214,7 +214,7 @@ if (-d $target_dir) @stat= stat("$target_dir/configure.in"); my $mtime= $stat[9]; my ($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime); - my $mtime= sprintf("%04d%-02d-%02d-%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min); + my $mtime= sprintf("%04d-%02d-%02d-%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min); &logger("Renaming $target_dir to $target_dir-$mtime"); $command= "mv "; From 3d0f9d96d7236af2c4dc4bf844233e27497d59dc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 20:28:01 +0200 Subject: [PATCH 42/48] Fixed during review of new pulled code extra/perror.c: Use strmov() instead of strcpy() Indentation fixes sql/sql_table.cc: Revert back part of the old code as the new code didn't use mysql_data_home, which would have caused problems in the embedded server sql/sql_update.cc: Ensure that used_index is always set (It has to be set because it's value is tested if order != 0) --- extra/perror.c | 14 ++++++++------ sql/sql_table.cc | 9 +++++++-- sql/sql_update.cc | 3 +++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/extra/perror.c b/extra/perror.c index fc10d8eaecc..27027520cbe 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -213,12 +213,14 @@ int main(int argc,char *argv[]) string 'Unknown Error'. To avoid printing it we try to find the error string by asking for an impossible big error message. */ - msg = strerror(10000); + msg= strerror(10000); - /* allocate a buffer for unknown_error since strerror always returns the same pointer - on some platforms such as Windows */ - unknown_error = malloc( strlen(msg)+1 ); - strcpy( unknown_error, msg ); + /* + Allocate a buffer for unknown_error since strerror always returns + the same pointer on some platforms such as Windows + */ + unknown_error= malloc(strlen(msg)+1); + strmov(unknown_error, msg); for ( ; argc-- > 0 ; argv++) { @@ -271,7 +273,7 @@ int main(int argc,char *argv[]) /* if we allocated a buffer for unknown_error, free it now */ if (unknown_error) - free(unknown_error); + free(unknown_error); exit(error); return error; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f3c107c2696..5f3875ba934 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2272,7 +2272,10 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, strxmov(src_path, (*tmp_table)->path, reg_ext, NullS); else { - fn_format( src_path, src_table, src_db, reg_ext, MYF(MY_UNPACK_FILENAME)); + strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table, + reg_ext, NullS); + /* Resolve symlinks (for windows) */ + fn_format(src_path, src_path, "", "", MYF(MY_UNPACK_FILENAME)); if (access(src_path, F_OK)) { my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table); @@ -2299,7 +2302,9 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, } else { - fn_format( dst_path, table_name, db, reg_ext, MYF(MY_UNPACK_FILENAME)); + strxmov(dst_path, mysql_data_home, "/", db, "/", table_name, + reg_ext, NullS); + fn_format(dst_path, dst_path, "", "", MYF(MY_UNPACK_FILENAME)); if (!access(dst_path, F_OK)) goto table_exists; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 0ec71bdfba3..663f2d2be34 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -167,7 +167,10 @@ int mysql_update(THD *thd, else if ((used_index=table->file->key_used_on_scan) < MAX_KEY) used_key_is_modified=check_if_key_used(table, used_index, fields); else + { used_key_is_modified=0; + used_index= MAX_KEY; + } if (used_key_is_modified || order) { /* From 1bbfa6f75fcbe8514d5c494972f50f43dba0f7e0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 21:03:46 +0100 Subject: [PATCH 43/48] ndb - add abort to multi op test case ndb/include/ndbapi/NdbConnection.hpp: Add aborts to test case ndb/test/include/HugoOperations.hpp: Add aborts to test case ndb/test/ndbapi/testOperations.cpp: Add aborts to test case ndb/test/src/HugoOperations.cpp: Add aborts to test case ndb/test/src/HugoTransactions.cpp: Add aborts to test case --- ndb/include/ndbapi/NdbConnection.hpp | 2 +- ndb/test/include/HugoOperations.hpp | 2 + ndb/test/ndbapi/testOperations.cpp | 240 ++++++++++++++++++--------- ndb/test/src/HugoOperations.cpp | 7 + ndb/test/src/HugoTransactions.cpp | 122 +++++++------- 5 files changed, 234 insertions(+), 139 deletions(-) diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index f173cd8ac6e..53830dd93c5 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -688,7 +688,7 @@ private: void remove_list(NdbOperation*& head, NdbOperation*); void define_scan_op(NdbIndexScanOperation*); - friend int runOperations(class NDBT_Context*, class NDBT_Step*); + friend class HugoOperations; }; inline diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp index fe22e4b5649..9ca2772e768 100644 --- a/ndb/test/include/HugoOperations.hpp +++ b/ndb/test/include/HugoOperations.hpp @@ -30,6 +30,8 @@ public: int closeTransaction(Ndb*); NdbConnection* getTransaction(); void refresh(); + + void setTransactionId(Uint64); int pkInsertRecord(Ndb*, int recordNo, diff --git a/ndb/test/ndbapi/testOperations.cpp b/ndb/test/ndbapi/testOperations.cpp index 92cc3e81b1a..e254aff58dc 100644 --- a/ndb/test/ndbapi/testOperations.cpp +++ b/ndb/test/ndbapi/testOperations.cpp @@ -103,6 +103,10 @@ OperationTestCase matrix[] = { << " failed on line " << __LINE__ << endl; \ abort(); return NDBT_FAILED; } +#define C3(b) if (!(b)) { \ + g_err << "ERR: failed on line " << __LINE__ << endl; \ + return NDBT_FAILED; } + int runOp(HugoOperations & hugoOps, Ndb * pNdb, @@ -326,18 +330,122 @@ generate(Vector& out, size_t len) } } +static const Uint32 DUMMY = 0; +static const Uint32 ROW = 1; + +int +verify_other(NDBT_Context* ctx, + Ndb* pNdb, int seq, OPS latest, bool initial_row, bool commit) +{ + Uint32 no_wait = NdbOperation::LM_CommittedRead* + ctx->getProperty("NoWait", (Uint32)1); + + for(size_t j = no_wait; j<3; j++) + { + HugoOperations other(*ctx->getTab()); + C3(other.startTransaction(pNdb) == 0); + C3(other.pkReadRecord(pNdb, ROW, 1, (NdbOperation::LockMode)j) == 0); + int tmp= other.execute_Commit(pNdb); + if(seq == 0){ + if(j == NdbOperation::LM_CommittedRead) + { + C3(initial_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626); + } + else + { + C3(tmp == 266); + } + } + else if(commit) + { + switch(latest){ + case o_INS: + case o_UPD: + C3(tmp == 0 && other.verifyUpdatesValue(seq) == 0); + break; + case o_DEL: + C3(tmp == 626); + break; + case o_DONE: + abort(); + } + } + else + { + // rollback + C3(initial_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626); + } + } + + return NDBT_OK; +} + +int +verify_savepoint(NDBT_Context* ctx, + Ndb* pNdb, int seq, OPS latest, + Uint64 transactionId) +{ + bool initial_row= (seq == 0) && latest == o_INS; + + for(size_t j = 0; j<3; j++) + { + const NdbOperation::LockMode lm= (NdbOperation::LockMode)j; + + HugoOperations same(*ctx->getTab()); + C3(same.startTransaction(pNdb) == 0); + same.setTransactionId(transactionId); // Cheat + + /** + * Increase savepoint to k + */ + for(size_t l = 1; l<=seq; l++) + { + C3(same.pkReadRecord(pNdb, DUMMY, 1, lm) == 0); // Read dummy row + C3(same.execute_NoCommit(pNdb) == 0); + g_info << "savepoint: " << l << endl; + } + + g_info << "op(" << seq << "): " + << " lock mode " << lm << endl; + + C3(same.pkReadRecord(pNdb, ROW, 1, lm) == 0); // Read real row + int tmp= same.execute_Commit(pNdb); + if(seq == 0) + { + if(initial_row) + { + C3(tmp == 0 && same.verifyUpdatesValue(0) == 0); + } else + { + C3(tmp == 626); + } + } + else + { + switch(latest){ + case o_INS: + case o_UPD: + C3(tmp == 0 && same.verifyUpdatesValue(seq) == 0); + break; + case o_DEL: + C3(tmp == 626); + break; + case o_DONE: + abort(); + } + } + } + return NDBT_OK; +} + int runOperations(NDBT_Context* ctx, NDBT_Step* step) { - const Uint32 DUMMY = 0; - const Uint32 ROW = 1; - int tmp; Ndb* pNdb = GETNDB(step); Uint32 seqNo = ctx->getProperty("Sequence", (Uint32)0); - Uint32 no_wait = NdbOperation::LM_CommittedRead* - ctx->getProperty("NoWait", (Uint32)1); + Uint32 commit= ctx->getProperty("Commit", (Uint32)1); if(seqNo == 0) { @@ -355,8 +463,8 @@ runOperations(NDBT_Context* ctx, NDBT_Step* step) C3(hugoOps.execute_Commit(pNdb) == 0); } - const bool inital_row= (seq[0] != o_INS); - if(inital_row) + const bool initial_row= (seq[0] != o_INS); + if(initial_row) { HugoOperations hugoOps(*ctx->getTab()); C3(hugoOps.startTransaction(pNdb) == 0); @@ -389,80 +497,36 @@ runOperations(NDBT_Context* ctx, NDBT_Step* step) /** * Verify other transaction */ - for(size_t j = no_wait; j<3; j++) - { - HugoOperations other(*ctx->getTab()); - C3(other.startTransaction(pNdb) == 0); - C3(other.pkReadRecord(pNdb, ROW, 1, (NdbOperation::LockMode)j) == 0); - tmp= other.execute_Commit(pNdb); - if(j == NdbOperation::LM_CommittedRead) - { - C3(inital_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626); - } - else - { - C3(tmp == 266); - } - } - + if(verify_other(ctx, pNdb, 0, seq[0], initial_row, commit) != NDBT_OK) + return NDBT_FAILED; + /** * Verify savepoint read */ Uint64 transactionId= trans1.getTransaction()->getTransactionId(); + for(size_t k=0; k<=i+1; k++) { - for(size_t j = 0; j<3; j++) - { - const NdbOperation::LockMode lm= (NdbOperation::LockMode)j; - - HugoOperations same(*ctx->getTab()); - C3(same.startTransaction(pNdb) == 0); - same.getTransaction()->setTransactionId(transactionId); // Cheat - - /** - * Increase savepoint to k - */ - for(size_t l = 1; l<=k; l++) - { - C3(same.pkReadRecord(pNdb, DUMMY, 1, lm) == 0); // Read dummy row - C3(same.execute_NoCommit(pNdb) == 0); - g_info << "savepoint: " << l << endl; - } - - g_info << "op(" << k << ", " << i << "): " - << " lock mode " << lm << endl; - - C3(same.pkReadRecord(pNdb, ROW, 1, lm) == 0); // Read real row - tmp= same.execute_Commit(pNdb); - if(k == 0) - { - if(inital_row) - { - C3(tmp == 0 && same.verifyUpdatesValue(0) == 0); - } else - { - C3(tmp == 626); - } - } - else - { - switch(seq[k-1]){ - case o_INS: - case o_UPD: - C3(tmp == 0 && same.verifyUpdatesValue(k) == 0); - break; - case o_DEL: - C3(tmp == 626); - break; - case o_DONE: - abort(); - } - } - } - } + if(verify_savepoint(ctx, pNdb, k, + k>0 ? seq[k-1] : initial_row ? o_INS : o_DONE, + transactionId) != NDBT_OK) + return NDBT_FAILED; + } + } + + if(commit) + { + C3(trans1.execute_Commit(pNdb) == 0); + } + else + { + C3(trans1.execute_Rollback(pNdb) == 0); } - C3(trans1.execute_Commit(pNdb) == 0); + if(verify_other(ctx, pNdb, seq.size(), seq.back(), + initial_row, commit) != NDBT_OK) + return NDBT_FAILED; + return NDBT_OK; } @@ -495,16 +559,20 @@ main(int argc, const char** argv){ } } + BaseString n1; + n1.append(name); + n1.append("_COMMIT"); + NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts, - name.c_str()+1, ""); - + n1.c_str()+1, ""); + pt->setProperty("Sequence", tmp[i]); pt->addInitializer(new NDBT_Initializer(pt, "runClearTable", runClearTable)); pt->addStep(new NDBT_ParallelStep(pt, - name.c_str()+1, + "run", runOperations)); pt->addFinalizer(new NDBT_Finalizer(pt, @@ -512,8 +580,26 @@ main(int argc, const char** argv){ runClearTable)); ts.addTest(pt); - } + name.append("_ABORT"); + pt = new NDBT_TestCaseImpl1(&ts, name.c_str()+1, ""); + pt->setProperty("Sequence", tmp[i]); + pt->setProperty("Commit", (Uint32)0); + pt->addInitializer(new NDBT_Initializer(pt, + "runClearTable", + runClearTable)); + + pt->addStep(new NDBT_ParallelStep(pt, + "run", + runOperations)); + + pt->addFinalizer(new NDBT_Finalizer(pt, + "runClearTable", + runClearTable)); + + ts.addTest(pt); + } + for(Uint32 i = 0; isetTransactionId(id); + } +} + int HugoOperations::closeTransaction(Ndb* pNdb){ if (pTrans != NULL){ diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp index 096f5406bbf..a2ed9c77db7 100644 --- a/ndb/test/src/HugoTransactions.cpp +++ b/ndb/test/src/HugoTransactions.cpp @@ -92,7 +92,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -102,13 +102,13 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -127,7 +127,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, while((eof = rs->nextResult(true)) == 0){ rows++; if (calc.verifyRowValues(&row) != 0){ - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -137,11 +137,11 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, rs->close(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_OK; } } @@ -150,7 +150,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR_INFO(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); switch (err.code){ case 488: @@ -164,17 +164,17 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); g_info << rows << " rows have been read" << endl; if (records != 0 && rows != records){ g_err << "Check expected number of records failed" << endl - << " expected=" << records <<", " << endl - << " read=" << rows << endl; + << " expected=" << records <<", " << endl + << " read=" << rows << endl; return NDBT_FAILED; } @@ -248,7 +248,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -258,13 +258,13 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -283,7 +283,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, while((eof = rs->nextResult(true)) == 0){ rows++; if (calc.verifyRowValues(&row) != 0){ - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -293,11 +293,11 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, rs->close(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_OK; } } @@ -306,7 +306,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR_INFO(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); switch (err.code){ case 488: @@ -320,17 +320,17 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); g_info << rows << " rows have been read" << endl; if (records != 0 && rows != records){ g_err << "Check expected number of records failed" << endl - << " expected=" << records <<", " << endl - << " read=" << rows << endl; + << " expected=" << records <<", " << endl + << " read=" << rows << endl; return NDBT_FAILED; } @@ -344,9 +344,9 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, int HugoTransactions::scanUpdateRecords(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ + int records, + int abortPercent, + int parallelism){ if(m_defaultScanUpdateMethod == 1){ return scanUpdateRecords1(pNdb, records, abortPercent, parallelism); } else if(m_defaultScanUpdateMethod == 2){ @@ -707,7 +707,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, while (true){ - restart: +restart: if (retryAttempt++ >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; @@ -743,7 +743,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, for(a=0; agetValue(tab.getColumn(a)->getName())) == NULL){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -752,7 +752,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, if( check == -1 ) { const NdbError err = pTrans->getNdbError(); ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); if (err.status == NdbError::TemporaryError){ NdbSleep_MilliSleep(50); continue; @@ -777,7 +777,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, NdbOperation* pUp = rs->updateTuple(); if(pUp == 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } const int updates = calc.getUpdatesValue(&row) + 1; @@ -786,7 +786,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pUp, a, r, updates ) != 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -795,7 +795,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, if (rows == abortCount && abortTrans == true){ g_info << "Scan is aborted" << endl; // This scan should be aborted - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_OK; } } while((check = rs->nextResult(false)) == 0); @@ -807,7 +807,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, const NdbError err = pTrans->getNdbError(); if( check == -1 ) { - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); ERR(err); if (err.status == NdbError::TemporaryError){ NdbSleep_MilliSleep(50); @@ -819,7 +819,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, const NdbError err = pTrans->getNdbError(); if( check == -1 ) { - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); ERR(err); if (err.status == NdbError::TemporaryError){ NdbSleep_MilliSleep(50); @@ -828,7 +828,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb, return NDBT_FAILED; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); g_info << rows << " rows have been updated" << endl; return NDBT_OK; @@ -1772,7 +1772,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, pUpdOp = pTrans->getNdbOperation(tab.getName()); if (pUpdOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -1788,7 +1788,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pUpdOp, a, r) != 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -1805,7 +1805,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, check = pUpdOp->incValue(attr->getName(), valToIncWith); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -1817,7 +1817,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, (calc.isUpdateCol(a) == false)){ if(setValueForAttr(pUpdOp, a, r, updates ) != 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -1846,7 +1846,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); r++; // Read next record @@ -1900,7 +1900,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, pOp = pTrans->getNdbOperation(tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -1928,7 +1928,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb, switch(err.status){ case NdbError::TemporaryError: ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; @@ -2066,18 +2066,18 @@ HugoTransactions::lockRecords(Ndb* pNdb, if (err.status == NdbError::TemporaryError){ ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } for (int b=0; (bcloseTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -2178,7 +2178,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, pOp = pTrans->getNdbIndexOperation(idxName, tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } check = pOp->readTuple(); @@ -2186,7 +2186,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName()); if (sOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -2196,7 +2196,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -2205,7 +2205,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -2216,7 +2216,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, if((rows[b]->attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == 0) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -2257,11 +2257,11 @@ HugoTransactions::indexReadRecords(Ndb* pNdb, if(ordered && rs->nextResult(true) == 0){ ndbout << "Error when comparing records " << " - index op next_result to many" << endl; - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); } deallocRows(); g_info << reads << " records read" << endl; @@ -2322,21 +2322,21 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, pOp = pTrans->getNdbIndexOperation(idxName, tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } check = pOp->readTupleExclusive(); if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } else { pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -2349,7 +2349,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -2371,7 +2371,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, if( check == -1 ) { const NdbError err = pTrans->getNdbError(); ERR(err); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); if (err.status == NdbError::TemporaryError){ NdbSleep_MilliSleep(50); @@ -2405,13 +2405,13 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, if (pUpdOp == NULL) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } if( check == -1 ) { ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } @@ -2420,7 +2420,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, if (tab.getColumn(a)->getPrimaryKey() == true){ if(equalForAttr(pUpdOp, a, r+b) != 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -2431,7 +2431,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, if (tab.getColumn(a)->getPrimaryKey() == false){ if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){ ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); return NDBT_FAILED; } } @@ -2455,7 +2455,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb, updated += batchsize; } - pNdb->closeTransaction(pTrans); + closeTransaction(pNdb); r+= batchsize; // Read next record } From ad21db5e0727704ee0527c08410bafff4d3150f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 22:35:36 +0200 Subject: [PATCH 44/48] Use -DUNIV_DEBUG (extra debugging for InnoDB) when configuring with --debug=full --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index e57cdabad25..98d060e660c 100644 --- a/configure.in +++ b/configure.in @@ -1677,8 +1677,8 @@ then elif test "$with_debug" = "full" then # Full debug. Very slow in some cases - CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" + CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC -DUNIV_DEBUG $CFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC -DUNIV_DEBUG $CXXFLAGS" else # Optimized version. No debug CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS" From d5c03608988ef35d2e384f50e52abe2a727c0786 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 22:39:21 +0200 Subject: [PATCH 45/48] Review fixed sql/ha_federated.cc: Fixed compiler warnings and some indentation problems (still a lot more indentation problems to fix, will come in a later patch) sql/mysql_priv.h: Remove duplicated append_escaped() sql/sql_analyse.cc: Remove duplicated append_escaped() sql/sql_insert.cc: Move extra(HA_EXTRA_IGNORE_DUP_KEY) to a more logical places Add missing DBUG_RETURN() --- sql/ha_federated.cc | 22 +++++++++++----------- sql/mysql_priv.h | 1 - sql/sql_analyse.cc | 37 ------------------------------------- sql/sql_insert.cc | 11 +++-------- 4 files changed, 14 insertions(+), 57 deletions(-) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 5185e0bbe9a..695c71677c0 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -586,16 +586,13 @@ uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) DBUG_RETURN(0); } -bool ha_federated::create_where_from_key( - String *to, - KEY *key_info, - const byte *key, - uint key_length - ) +bool ha_federated::create_where_from_key(String *to, KEY *key_info, + const byte *key, uint key_length) { uint second_loop= 0; KEY_PART_INFO *key_part; bool needs_quotes; + String tmp; DBUG_ENTER("ha_federated::create_where_from_key"); for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++) @@ -656,7 +653,9 @@ bool ha_federated::create_where_from_key( uint blob_length= uint2korr(key); key+= HA_KEY_BLOB_LENGTH; key_length-= HA_KEY_BLOB_LENGTH; - if (append_escaped(to, (char *)(key), blob_length)) + + tmp.set_quick((char*) key, blob_length, &my_charset_bin); + if (append_escaped(to, &tmp)) DBUG_RETURN(1); DBUG_PRINT("ha_federated::create_where_from_key", ("blob type %s", to->c_ptr_quick())); @@ -666,7 +665,8 @@ bool ha_federated::create_where_from_key( { length= uint2korr(key); key+= HA_KEY_BLOB_LENGTH; - if (append_escaped(to, (char *)(key), length)) + tmp.set_quick((char*) key, length, &my_charset_bin); + if (append_escaped(to, &tmp)) DBUG_RETURN(1); DBUG_PRINT("ha_federated::create_where_from_key", ("varchar type %s", to->c_ptr_quick())); @@ -680,7 +680,7 @@ bool ha_federated::create_where_from_key( res= field->val_str(&str, (char *)(key)); if (field->result_type() == STRING_RESULT) { - if (append_escaped(to, (char *) res->ptr(), res->length())) + if (append_escaped(to, res)) DBUG_RETURN(1); res= field->val_str(&str, (char *)(key)); @@ -1235,7 +1235,7 @@ int ha_federated::update_row( update_string.append(new_field_value); new_field_value.length(0); - if (x+1 < table->s->fields) + if ((uint) x+1 < table->s->fields) { update_string.append(", "); if (! has_a_primary_key) @@ -1311,7 +1311,7 @@ int ha_federated::delete_row(const byte * buf) delete_string.append(data_string); data_string.length(0); - if (x+1 < table->s->fields) + if ((uint) x+1 < table->s->fields) delete_string.append(" AND "); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e725cd177c3..bf84e0a394e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -715,7 +715,6 @@ bool mysql_do(THD *thd, List &values); /* sql_analyse.h */ bool append_escaped(String *to_str, String *from_str); -bool append_escaped(String *to_str, char *from, uint from_len); /* sql_show.cc */ bool mysqld_show_open_tables(THD *thd,const char *wild); diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 3f97cab1511..b6bd49b1553 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -59,8 +59,6 @@ int compare_ulonglong2(void* cmp_arg __attribute__((unused)), return compare_ulonglong(s,t); } -bool append_escaped(String *to_str, String *from_str); -bool append_escaped(String *to_str, char *from, uint from_len); Procedure * proc_analyse_init(THD *thd, ORDER *param, select_result *result, @@ -1087,38 +1085,3 @@ bool append_escaped(String *to_str, String *from_str) } return 0; } - -bool append_escaped(String *to_str, char *from, uint from_len) -{ - char *end, c; - - if (to_str->realloc(to_str->length() + from_len)) - return 1; - - end= from + from_len; - - for (; from < end; from++) - { - c= *from; - switch (c) { - case '\0': - c= '0'; - break; - case '\032': - c= 'Z'; - break; - case '\\': - case '\'': - break; - default: - goto normal_character; - } - if (to_str->append('\\')) - return 1; - - normal_character: - if (to_str->append(c)) - return 1; - } - return 0; -} diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 4cb62d5e9d7..fa6f1e05dc6 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1811,13 +1811,13 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) is the same table (Bug #6034). Do the preparation after the select phase in select_insert::prepare2(). */ - if (info.ignore || info.handle_duplicates != DUP_ERROR) - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); table->file->start_bulk_insert((ha_rows) 0); } restore_record(table,s->default_values); // Get empty record table->next_number_field=table->found_next_number_field; thd->cuted_fields=0; + if (info.ignore || info.handle_duplicates != DUP_ERROR) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); thd->no_trans_update= 0; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & @@ -1847,14 +1847,9 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) int select_insert::prepare2(void) { DBUG_ENTER("select_insert::prepare2"); - if (thd->lex->current_select->options & OPTION_BUFFER_RESULT) - { - if (info.ignore || info.handle_duplicates != DUP_ERROR) - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); table->file->start_bulk_insert((ha_rows) 0); - } - return 0; + DBUG_RETURN(0); } From bb0507fa5d3e1161d418112f1c412fb9fa815571 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Feb 2005 10:54:38 +0200 Subject: [PATCH 46/48] Fixed a bug: deadlock without any locking, simple select and update (Bug #7975). innobase/row/row0ins.c: If the SQL-query will update or replace duplicate key row we take X-lcok for duplicate row. sql/ha_innodb.cc: INSERT ON DUPLICATE KEY UPDATE will also update duplicate key and we can take X-lock in this case for duplicate key records. BitKeeper/etc/ignore: Added innobase/row/row0index.c to the ignore list --- .bzrignore | 1 + innobase/row/row0ins.c | 41 +++++++++++++++++++++++------------------ sql/ha_innodb.cc | 19 +++++++++++++++---- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/.bzrignore b/.bzrignore index bb1cdb1c0c3..3aab3a7b4df 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1055,3 +1055,4 @@ vio/viotest-ssl include/mysqld_ername.h include/mysqld_error.h include/sql_state.h +innobase/row/row0index.c diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index aab0f5affa7..9edc18025d7 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -51,14 +51,19 @@ innobase_invalidate_query_cache( chars count */ /********************************************************************** -This function returns true if SQL-query in the current thread +This function returns true if + +1) SQL-query in the current thread is either REPLACE or LOAD DATA INFILE REPLACE. + +2) SQL-query in the current thread +is INSERT ON DUPLICATE KEY UPDATE. + NOTE that /mysql/innobase/row/row0ins.c must contain the prototype for this function ! */ ibool -innobase_query_is_replace(void); -/*===========================*/ +innobase_query_is_update(void); /************************************************************************* Creates an insert node struct. */ @@ -1597,12 +1602,12 @@ row_ins_scan_sec_index_for_duplicate( offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); - if (innobase_query_is_replace()) { + if (innobase_query_is_update()) { - /* The manual defines the REPLACE semantics that it - is either an INSERT or DELETE(s) for duplicate key - + INSERT. Therefore, we should take X-lock for - duplicates */ + /* If the SQL-query will update or replace + duplicate key we will take X-lock for + duplicates ( REPLACE, LOAD DATAFILE REPLACE, + INSERT ON DUPLICATE KEY UPDATE). */ err = row_ins_set_exclusive_rec_lock(LOCK_ORDINARY, rec, index, offsets, thr); @@ -1720,12 +1725,12 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ - if (innobase_query_is_replace()) { + if (innobase_query_is_update()) { - /* The manual defines the REPLACE semantics - that it is either an INSERT or DELETE(s) - for duplicate key + INSERT. Therefore, we - should take X-lock for duplicates */ + /* If the SQL-query will update or replace + duplicate key we will take X-lock for + duplicates ( REPLACE, LOAD DATAFILE REPLACE, + INSERT ON DUPLICATE KEY UPDATE). */ err = row_ins_set_exclusive_rec_lock( LOCK_REC_NOT_GAP,rec,cursor->index, @@ -1759,12 +1764,12 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); - /* The manual defines the REPLACE semantics that it - is either an INSERT or DELETE(s) for duplicate key - + INSERT. Therefore, we should take X-lock for - duplicates. */ + if (innobase_query_is_update()) { - if (innobase_query_is_replace()) { + /* If the SQL-query will update or replace + duplicate key we will take X-lock for + duplicates ( REPLACE, LOAD DATAFILE REPLACE, + INSERT ON DUPLICATE KEY UPDATE). */ err = row_ins_set_exclusive_rec_lock( LOCK_REC_NOT_GAP, rec, diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 797f51c0293..04ae0211970 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -6142,13 +6142,19 @@ innobase_get_at_most_n_mbchars( extern "C" { /********************************************************************** -This function returns true if SQL-query in the current thread +This function returns true if + +1) SQL-query in the current thread is either REPLACE or LOAD DATA INFILE REPLACE. + +2) SQL-query in the current thread +is INSERT ON DUPLICATE KEY UPDATE. + NOTE that /mysql/innobase/row/row0ins.c must contain the prototype for this function ! */ ibool -innobase_query_is_replace(void) +innobase_query_is_update(void) /*===========================*/ { THD* thd; @@ -6160,9 +6166,14 @@ innobase_query_is_replace(void) ( thd->lex->sql_command == SQLCOM_LOAD && thd->lex->duplicates == DUP_REPLACE )) { return true; - } else { - return false; } + + if ( thd->lex->sql_command == SQLCOM_INSERT && + thd->lex->duplicates == DUP_UPDATE ) { + return true; + } + + return false; } } From 888c211805fdc501e078c7f8576821b121eb6637 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Feb 2005 12:35:04 +0200 Subject: [PATCH 47/48] Revert error I did. BitKeeper/etc/ignore: Revert the ignore change I did. --- .bzrignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index 3aab3a7b4df..bb1cdb1c0c3 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1055,4 +1055,3 @@ vio/viotest-ssl include/mysqld_ername.h include/mysqld_error.h include/sql_state.h -innobase/row/row0index.c From 8e279c4cf8e3bba242ed7e1790227ff9a4c5d966 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Feb 2005 18:00:50 +0200 Subject: [PATCH 48/48] After merge fixes sql/item.cc: After merge fixes (bug during merge) sql/sql_show.cc: Ensure that lex->all_select_list is properly reset on function end (Caused crashes after merge) --- mysql-test/r/derived.result | 10 +++++----- mysql-test/r/func_str.result | 6 ------ sql/item.cc | 2 +- sql/sql_show.cc | 31 ++++++++++++++++--------------- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 8322933a360..071cb673501 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -330,11 +330,6 @@ SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MA min max avg 10.00 10.00 10 DROP TABLE t1; -CREATE TABLE t1 (a char(10), b char(10)); -INSERT INTO t1 VALUES ('root','localhost'), ('root','%'); -SELECT * FROM (SELECT (SELECT a.a FROM t1 AS a WHERE a.a = b.a) FROM t1 AS b) AS c; -ERROR 21000: Subquery returns more than 1 row -DROP TABLE t1; create table t1 (a integer, b integer); insert into t1 values (1,4), (2,2),(2,2), (4,1),(4,1),(4,1),(4,1); select distinct sum(b) from t1 group by a; @@ -344,3 +339,8 @@ select distinct sum(b) from (select a,b from t1) y group by a; sum(b) 4 drop table t1; +CREATE TABLE t1 (a char(10), b char(10)); +INSERT INTO t1 VALUES ('root','localhost'), ('root','%'); +SELECT * FROM (SELECT (SELECT a.a FROM t1 AS a WHERE a.a = b.a) FROM t1 AS b) AS c; +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index cb07ae0c173..71a1a7539b0 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -707,12 +707,6 @@ select count(*) as total, left(c,10) as reg from t1 group by reg order by reg de total reg 10 2004-12-10 drop table t1; -select quote(ltrim(concat(' ', 'a'))); -quote(ltrim(concat(' ', 'a'))) -'a' -select quote(trim(concat(' ', 'a'))); -quote(trim(concat(' ', 'a'))) -'a' select trim(null from 'kate') as "must_be_null"; must_be_null NULL diff --git a/sql/item.cc b/sql/item.cc index 76d802e972f..08de3889ae6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1775,7 +1775,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) if (select_ref != not_found_item && !ambiguous_fields) { DBUG_ASSERT(*select_ref); - if (!last->ref_pointer_array[counter]) + if (!select->ref_pointer_array[counter]) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), ref->name, "forward reference in item list"); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e9126871045..9c544142b14 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1786,7 +1786,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) enum enum_schema_tables schema_table_idx; thr_lock_type lock_type; List bases; + List_iterator_fast it(bases); COND *partial_cond; + int error= 1; DBUG_ENTER("get_all_tables"); LINT_INIT(end); @@ -1803,13 +1805,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) if (schema_table->process_table(thd, show_table_list, table, res, show_table_list->db, show_table_list->alias)) - { - DBUG_RETURN(1); - } + goto err; close_thread_tables(thd, 0, 0, old_open_tables); show_table_list->table= 0; - lex->all_selects_list= select_lex; - DBUG_RETURN(0); + error= 0; + goto err; } lex->all_selects_list= &sel; @@ -1822,14 +1822,14 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) /* information schema name always is first in list */ if (schema_db_add(thd, &bases, idx_field_vals.db_value, &with_i_schema)) - return 1; + goto err; if (mysql_find_files(thd, &bases, NullS, mysql_data_home, idx_field_vals.db_value, 1)) - return 1; + goto err; - List_iterator_fast it(bases); partial_cond= make_cond_for_info_schema(cond, tables); + it.rewind(); /* To get access to new elements in basis list */ while ((base_name= it++) || /* generate error for non existing database. @@ -1851,7 +1851,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) if (with_i_schema) // information schema table names { if (schema_tables_add(thd, &files, idx_field_vals.table_value)) - DBUG_RETURN(1); + goto err; } else { @@ -1860,7 +1860,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) len= FN_LEN - len; if (mysql_find_files(thd, &files, base_name, path, idx_field_vals.table_value, 0)) - DBUG_RETURN(1); + goto err; } List_iterator_fast it_files(files); @@ -1906,16 +1906,14 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) int res; TABLE *old_open_tables= thd->open_tables; if (make_table_list(thd, &sel, base_name, file_name)) - DBUG_RETURN(1); + goto err; TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first; show_table_list->lock_type= lock_type; res= open_and_lock_tables(thd, show_table_list); if (schema_table->process_table(thd, show_table_list, table, res, base_name, show_table_list->alias)) - { - DBUG_RETURN(1); - } + goto err; close_thread_tables(thd, 0, 0, old_open_tables); } } @@ -1927,8 +1925,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) with_i_schema= 0; } } + + error= 0; +err: lex->all_selects_list= select_lex; - DBUG_RETURN(0); + DBUG_RETURN(error); }