From 47f8a473bd1179c7622deab59b491f5a9d91b211 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Oct 2004 18:38:48 +0500 Subject: [PATCH 01/15] A fix (bug #5615 type of aggregate function column wrong when using group by). mysql-test/r/func_group.result: test case (bug #5615 type of aggregate function column wrong when using group by) mysql-test/t/func_group.test: test case (bug #5615 type of aggregate function column wrong when using group by) sql/sql_select.cc: A fix (bug #5615 type of aggregate function column wrong when using group by): should create a temporary field of the proper type in case of MIN|MAX(field). --- mysql-test/r/func_group.result | 9 +++++++++ mysql-test/t/func_group.test | 10 ++++++++++ sql/sql_select.cc | 9 +++++++++ 3 files changed, 28 insertions(+) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index c25f89d4df3..ecf6422261f 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -719,3 +719,12 @@ one 2 two 2 three 1 drop table t1; +create table t1(a int, b datetime); +insert into t1 values (1, NOW()), (2, NOW()); +create table t2 select MAX(b) from t1 group by a; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `MAX(b)` datetime default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1, t2; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 3e001961f90..ecd3bf97f0b 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -458,3 +458,13 @@ INSERT INTO t1 VALUES select val, count(*) from t1 group by val; drop table t1; + +# +# Bug #5615: type of aggregate function column wrong when using group by +# + +create table t1(a int, b datetime); +insert into t1 values (1, NOW()), (2, NOW()); +create table t2 select MAX(b) from t1 group by a; +show create table t2; +drop table t1, t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 638ed229a70..7ffef151457 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4744,6 +4744,15 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->name,table,item_sum->decimals); case Item_sum::UNIQUE_USERS_FUNC: return new Field_long(9,maybe_null,item->name,table,1); + case Item_sum::MIN_FUNC: + case Item_sum::MAX_FUNC: + if (item_sum->args[0]->type() == Item::FIELD_ITEM) + { + *from_field= ((Item_field*) item_sum->args[0])->field; + return create_tmp_field_from_field(thd, *from_field, item, table, + modify_item, convert_blob_length); + } + /* fall through */ default: switch (item_sum->result_type()) { case REAL_RESULT: From 556950da46e61a1a04f0531f6d96ec60c7ede79c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Oct 2004 19:17:13 +0500 Subject: [PATCH 02/15] An addition (see ChangeSet 1.2082 04/10/11 18:38:48 ram@gw.mysql.r18.ru +3 -0 A fix (bug #5615 type of aggregate function column wrong when using group by).) Shouldn't it be 'int(11) not null' == the same as in the t1? --- mysql-test/r/show_check.result | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 8256c8d692a..5ea17c93f48 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -250,9 +250,11 @@ type_bool type_tiny type_short type_mediumint type_bigint type_decimal type_nume drop table t1; create table t1 (a int not null); create table t2 select max(a) from t1; +Warnings: +Warning 1263 Data truncated; NULL supplied to NOT NULL column 'max(a)' at row 1 show columns from t2; Field Type Null Key Default Extra -max(a) bigint(20) YES NULL +max(a) int(11) 0 drop table t1,t2; create table t1 (c decimal, d double, f float, r real); show columns from t1; From 3bffc522317ad18102f8a2e5079e3242b6866dcf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Oct 2004 14:51:17 +0500 Subject: [PATCH 03/15] A fix (bug #6089: FOUND_ROWS returns wrong values when no table/view is used). mysql-test/r/ps.result: A fix (bug #6089: FOUND_ROWS returns wrong values when no table/view is used). The second FOUND_ROWS() should return 1. sql/sql_class.cc: A fix (bug #6089: FOUND_ROWS returns wrong values when no table/view is used). limit_found_rows initialization added. sql/sql_select.cc: A fix (bug #6089: FOUND_ROWS returns wrong values when no table/view is used). thd->limit_found_rows is set to 1 when no table is used. --- mysql-test/r/ps.result | 2 +- mysql-test/r/select_found.result | 25 +++++++++++++++++++++++++ mysql-test/t/select_found.test | 15 +++++++++++++++ sql/sql_class.cc | 1 + sql/sql_select.cc | 4 +++- 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 6cad58282a2..8c55bb08249 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -135,7 +135,7 @@ FOUND_ROWS() 1 execute stmt1; FOUND_ROWS() -0 +1 deallocate prepare stmt1; drop table t1; create table t1 diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result index 00dbcb54d93..1eaa7033c99 100644 --- a/mysql-test/r/select_found.result +++ b/mysql-test/r/select_found.result @@ -246,3 +246,28 @@ SELECT FOUND_ROWS(); FOUND_ROWS() 0 DROP TABLE t1; +SELECT 'foo'; +foo +foo +SELECT FOUND_ROWS(); +FOUND_ROWS() +1 +SELECT SQL_CALC_FOUND_ROWS 'foo'; +foo +foo +SELECT FOUND_ROWS(); +FOUND_ROWS() +1 +SELECT SQL_CALC_FOUND_ROWS 'foo' limit 0; +foo +SELECT FOUND_ROWS(); +FOUND_ROWS() +1 +SELECT FOUND_ROWS(); +FOUND_ROWS() +1 +SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0; +foo +SELECT FOUND_ROWS(); +FOUND_ROWS() +2 diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test index 943174462e3..e51dd2442b9 100644 --- a/mysql-test/t/select_found.test +++ b/mysql-test/t/select_found.test @@ -166,3 +166,18 @@ INSERT INTO t1 VALUES (0), (0), (1), (2); SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a = 0 GROUP BY a HAVING a > 10; SELECT FOUND_ROWS(); DROP TABLE t1; + +# +# Bug #6089: queries which don't use any tables +# + +SELECT 'foo'; +SELECT FOUND_ROWS(); +SELECT SQL_CALC_FOUND_ROWS 'foo'; +SELECT FOUND_ROWS(); +SELECT SQL_CALC_FOUND_ROWS 'foo' limit 0; +SELECT FOUND_ROWS(); +SELECT FOUND_ROWS(); + +SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0; +SELECT FOUND_ROWS(); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index abe00027b07..b6fdac03526 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -177,6 +177,7 @@ THD::THD() lock=locked_tables=0; used_tables=0; cuted_fields= sent_row_count= 0L; + limit_found_rows= 0; statement_id_counter= 0UL; // Must be reset to handle error with THD's created for init of mysqld lex->current_select= 0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index df74a946b5c..1610057f877 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1067,7 +1067,9 @@ JOIN::exec() else error=(int) result->send_eof(); } - thd->limit_found_rows= thd->examined_row_count= 0; + /* Single select (without union and limit) always returns 1 row */ + thd->limit_found_rows= 1; + thd->examined_row_count= 0; DBUG_VOID_RETURN; } thd->limit_found_rows= thd->examined_row_count= 0; From df1fab9d45cb7ffb3cf850d933341be13f7f416b Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 5 Feb 2005 06:23:23 +0300 Subject: [PATCH 04/15] Fix for BUG#7519: Index statistics is not displayed after ANALYZE for temporary tables: Call file->extra() with HA_STATUS_CONST in mysqld_show_keys. The fix will not be merged into 4.1/5.0 because they don't have this problem already. mysql-test/r/show_check.result: Testcase for BUG#7519 mysql-test/t/show_check.test: Testcase for BUG#7519 sql/sql_show.cc: Fix for BUG#7519: Index statistics is not displayed after ANALYZE for temporary tables: When handling "SHOW INDEX" the call file->extra(HA_STATUS_CONST | ...) is made for regular tables but bypassed for temporary tables. Call file->extra() with HA_STATUS_CONST in mysqld_show_keys to make sure we're always using the current index cardinality values. --- mysql-test/r/show_check.result | 22 ++++++++++++++++++++++ mysql-test/t/show_check.test | 16 ++++++++++++++++ sql/sql_show.cc | 3 ++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index f40b0693585..6d23dde1f1b 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -233,3 +233,25 @@ c decimal(4,3) YES NULL d double(4,3) YES NULL f float(4,3) YES NULL drop table t1; +CREATE TABLE t1 ( a VARCHAR(20) ); +INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five'); +CREATE TEMPORARY TABLE t2 ( index (a(20)) ) SELECT a FROM t1 GROUP BY a; +SHOW INDEX FROM t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t2 X a X X X NULL X X X BTREE +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +SHOW INDEX FROM t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t2 X a X X X 5 X X X BTREE +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TEMPORARY TABLE `t2` ( + `a` varchar(20) default NULL, + KEY `a` (`a`) +) TYPE=MyISAM +SHOW INDEX FROM t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t2 X a X X X 5 X X X BTREE +DROP TEMPORARY TABLE t2; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 2cd2012d109..e712ed77f04 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -131,3 +131,19 @@ drop table t1; create table t1 (c decimal(3,3), d double(3,3), f float(3,3)); show columns from t1; drop table t1; + +# Fix for BUG#7519: For temporary tables, SHOW INDEX doesn't display index +# cardinality after ANALYZE. +CREATE TABLE t1 ( a VARCHAR(20) ); +INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five'); +CREATE TEMPORARY TABLE t2 ( index (a(20)) ) SELECT a FROM t1 GROUP BY a; +--replace_column 2 X 4 X 5 X 6 X 8 X 9 X 10 X +SHOW INDEX FROM t2; +ANALYZE TABLE t2; +--replace_column 2 X 4 X 5 X 6 X 8 X 9 X 10 X +SHOW INDEX FROM t2; +SHOW CREATE TABLE t2; +--replace_column 2 X 4 X 5 X 6 X 8 X 9 X 10 X +SHOW INDEX FROM t2; +DROP TEMPORARY TABLE t2; + diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2506033cda5..27246729162 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -686,7 +686,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) String *packet= &thd->packet; KEY *key_info=table->key_info; - table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); + table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME | + HA_STATUS_CONST); for (uint i=0 ; i < table->keys ; i++,key_info++) { KEY_PART_INFO *key_part= key_info->key_part; From 1a72e219f206fbf20691baaf2d1fbdb2dd73e13c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Feb 2005 17:15:04 +0300 Subject: [PATCH 05/15] Fix for BUG#8560: Set max_sort_char for any 8-bit charset with binary collation. max_sort_char is needed by my_like_range_simple to produce upper bound constants for LIKE "str_%" and similar expressions. mysql-test/r/ctype_cp1251.result: Test for BUG#8560 mysql-test/t/ctype_cp1251.test: Test for BUG#8560 --- mysql-test/r/ctype_cp1251.result | 16 ++++++++++++++++ mysql-test/t/ctype_cp1251.test | 14 ++++++++++++++ strings/ctype-bin.c | 9 ++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result index 3793e962d40..647f8c6236c 100644 --- a/mysql-test/r/ctype_cp1251.result +++ b/mysql-test/r/ctype_cp1251.result @@ -54,3 +54,19 @@ select collation(a), collation(b), collation(binary 'ccc') from t1 limit 1; collation(a) collation(b) collation(binary 'ccc') cp1251_bin binary binary drop table t1; +create table t1 ( +a varchar(16) character set cp1251 collate cp1251_bin not null, +b int(10) default null, +primary key(a) +) charset=cp1251; +insert into t1 (a) values ('air'), +('we'),('g'),('we_toshko'), ('s0urce'),('we_ivo'),('we_iliyan'), +('we_martin'),('vw_grado'),('vw_vasko'),('tn_vili'),('tn_kalina'), +('tn_fakira'),('vw_silvia'),('vw_starshi'),('vw_geo'),('vw_b0x1'); +select * from t1 where a like 'we_%'; +a b +we_iliyan NULL +we_ivo NULL +we_martin NULL +we_toshko NULL +drop table t1; diff --git a/mysql-test/t/ctype_cp1251.test b/mysql-test/t/ctype_cp1251.test index 66a8a5aa909..2d670ec3607 100644 --- a/mysql-test/t/ctype_cp1251.test +++ b/mysql-test/t/ctype_cp1251.test @@ -32,3 +32,17 @@ select * from t1 where lower(b)='bbb'; select charset(a), charset(b), charset(binary 'ccc') from t1 limit 1; select collation(a), collation(b), collation(binary 'ccc') from t1 limit 1; drop table t1; + +# Test for BUG#8560 +create table t1 ( + a varchar(16) character set cp1251 collate cp1251_bin not null, + b int(10) default null, + primary key(a) +) charset=cp1251; +insert into t1 (a) values ('air'), + ('we'),('g'),('we_toshko'), ('s0urce'),('we_ivo'),('we_iliyan'), + ('we_martin'),('vw_grado'),('vw_vasko'),('tn_vili'),('tn_kalina'), + ('tn_fakira'),('vw_silvia'),('vw_starshi'),('vw_geo'),('vw_b0x1'); + +select * from t1 where a like 'we_%'; +drop table t1; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 618879607ec..425985e6bc1 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -67,6 +67,13 @@ static uchar bin_char_array[] = }; +static my_bool +my_coll_init_8bit_bin(CHARSET_INFO *cs, + void *(*alloc)(uint) __attribute__((unused))) +{ + cs->max_sort_char=255; + return FALSE; +} static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)), const uchar *s, uint slen, @@ -428,7 +435,7 @@ skip: MY_COLLATION_HANDLER my_collation_8bit_bin_handler = { - NULL, /* init */ + my_coll_init_8bit_bin, my_strnncoll_8bit_bin, my_strnncollsp_8bit_bin, my_strnxfrm_8bit_bin, From d2ead18b69716bdd1e5610e666e26d1ae1d72197 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Feb 2005 20:21:21 +0300 Subject: [PATCH 06/15] Fix for BUG#8726: In JOIN::optimize on ER_TOO_BIG_SELECT error set JOIN::error to -1 to cause the error to be sent to the client. mysql-test/r/select_safe.result: Testcase for BUG#8726 mysql-test/t/select_safe.test: Testcase for BUG#8726 sql/sql_select.cc: Fix for BUG#8726: On ER_TOO_BIG_SELECT set JOIN::error to -1 to cause the error to be sent to the client. --- mysql-test/r/select_safe.result | 15 +++++++++++++++ mysql-test/t/select_safe.test | 20 ++++++++++++++++++++ sql/sql_select.cc | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result index 766ee8c0e14..7a29db42dd9 100644 --- a/mysql-test/r/select_safe.result +++ b/mysql-test/r/select_safe.result @@ -78,4 +78,19 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref b b 21 test.t1.b 6 Using where SET MAX_SEEKS_FOR_KEY=DEFAULT; drop table t1; +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +set local max_join_size=8; +select * from (select * from t1) x; +ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay +set local max_join_size=1; +select * from (select * from t1 a, t1 b) x; +ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay +set local max_join_size=1; +select * from (select 1 union select 2 union select 3) x; +ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay +drop table t1; SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT; diff --git a/mysql-test/t/select_safe.test b/mysql-test/t/select_safe.test index 3cafd31a879..5b2dfb00bb7 100644 --- a/mysql-test/t/select_safe.test +++ b/mysql-test/t/select_safe.test @@ -66,4 +66,24 @@ SET MAX_SEEKS_FOR_KEY=DEFAULT; drop table t1; +# BUG#8726 +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; + +set local max_join_size=8; +--error 1104 +select * from (select * from t1) x; + +set local max_join_size=1; +--error 1104 +select * from (select * from t1 a, t1 b) x; + +set local max_join_size=1; +--error 1104 +select * from (select 1 union select 2 union select 3) x; +drop table t1; + SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a210fbbbe02..d207d50e306 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -579,7 +579,7 @@ JOIN::optimize() !(select_options & SELECT_DESCRIBE)) { /* purecov: inspected */ my_message(ER_TOO_BIG_SELECT, ER(ER_TOO_BIG_SELECT), MYF(0)); - error= 1; /* purecov: inspected */ + error= -1; DBUG_RETURN(1); } if (const_tables && !thd->locked_tables && From b9b69440c10296bce67bbdaab2c4dbc0d9ba9243 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 13:54:48 +0200 Subject: [PATCH 07/15] InnoDB: Zero fill newly created pages and deleted records to remove old junk and to improve compression ratio. InnoDB: Make implicit type conversions explicit. (Bug #8826) innobase/btr/btr0cur.c: Add "offsets" parameter to page_cur_delete_rec() calls btr_cur_optimistic_delete(): Simplify the logic with a flag variable btr_cur_pessimistic_delete(): Compute "offsets" earlier innobase/include/page0cur.h: page_cur_delete_rec(): Add parameter "offsets" innobase/include/page0page.h: page_mem_free(): Replace parameter "index" with "offsets" innobase/include/page0page.ic: page_mem_free(): Replace parameter "index" with "offsets". Clear the data bytes of the freed record. (The "extra" bytes will be needed by free space management.) innobase/include/rem0rec.h: Remove unnecessary function rec_get_size() innobase/log/log0recv.c: Remove function rec_apply_log_recs_for_backup() unless #ifdef UNIV_HOTBACKUP. innobase/page/page0cur.c: Add parameter "offsets" to page_cur_delete_rec(). innobase/page/page0page.c: page_create(): Zero fill the data area. page_delete_rec_list_start(): Add parameter "offsets" to page_cur_delete_rec(). innobase/rem/rem0rec.c: Remove unnecessary function rec_get_size(). Fix compiler warnings about implicit type conversions. (Bug #8826) innobase/srv/srv0srv.c: Fix compiler warnings about implicit type conversions. (Bug #8826) innobase/sync/sync0sync.c: Fix compiler warnings about implicit type conversions. (Bug #8826) --- innobase/btr/btr0cur.c | 36 ++++++++++++++++++----------------- innobase/include/page0cur.h | 7 ++++--- innobase/include/page0page.h | 2 +- innobase/include/page0page.ic | 12 ++++++++++-- innobase/include/rem0rec.h | 9 --------- innobase/log/log0recv.c | 4 +++- innobase/page/page0cur.c | 17 ++++++++++++++--- innobase/page/page0page.c | 29 ++++++++++++++++++++-------- innobase/rem/rem0rec.c | 31 ++++-------------------------- innobase/srv/srv0srv.c | 11 +++++++---- innobase/sync/sync0sync.c | 4 ++-- 11 files changed, 85 insertions(+), 77 deletions(-) diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 8559df16d08..91ba47224ef 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -1642,7 +1642,7 @@ btr_cur_optimistic_update( btr_search_update_hash_on_delete(cursor); - page_cur_delete_rec(page_cursor, index, mtr); + page_cur_delete_rec(page_cursor, index, offsets, mtr); page_cur_move_to_prev(page_cursor); @@ -1885,7 +1885,7 @@ btr_cur_pessimistic_update( btr_search_update_hash_on_delete(cursor); - page_cur_delete_rec(page_cursor, index, mtr); + page_cur_delete_rec(page_cursor, index, offsets, mtr); page_cur_move_to_prev(page_cursor); @@ -2401,6 +2401,7 @@ btr_cur_optimistic_delete( mem_heap_t* heap = NULL; ulint offsets_[100] = { 100, }; ulint* offsets = offsets_; + ibool no_compress_needed; ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_page(cursor)), MTR_MEMO_PAGE_X_FIX)); @@ -2414,9 +2415,11 @@ btr_cur_optimistic_delete( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); - if (!rec_offs_any_extern(offsets) + no_compress_needed = !rec_offs_any_extern(offsets) && btr_cur_can_delete_without_compress( - cursor, rec_offs_size(offsets), mtr)) { + cursor, rec_offs_size(offsets), mtr); + + if (no_compress_needed) { lock_update_delete(rec); @@ -2425,20 +2428,17 @@ btr_cur_optimistic_delete( max_ins_size = page_get_max_insert_size_after_reorganize(page, 1); page_cur_delete_rec(btr_cur_get_page_cur(cursor), - cursor->index, mtr); + cursor->index, offsets, mtr); ibuf_update_free_bits_low(cursor->index, page, max_ins_size, mtr); - if (heap) { - mem_heap_free(heap); - } - return(TRUE); } if (heap) { mem_heap_free(heap); } - return(FALSE); + + return(no_compress_needed); } /***************************************************************** @@ -2478,6 +2478,7 @@ btr_cur_pessimistic_delete( ibool success; ibool ret = FALSE; mem_heap_t* heap; + ulint* offsets; page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); @@ -2503,20 +2504,20 @@ btr_cur_pessimistic_delete( } } - heap = mem_heap_create(256); + heap = mem_heap_create(1024); rec = btr_cur_get_rec(cursor); + offsets = rec_get_offsets(rec, cursor->index, + NULL, ULINT_UNDEFINED, &heap); + /* Free externally stored fields if the record is neither a node pointer nor in two-byte format. - This avoids unnecessary calls to rec_get_offsets(). */ + This avoids an unnecessary loop. */ if (cursor->index->table->comp ? !rec_get_node_ptr_flag(rec) : !rec_get_1byte_offs_flag(rec)) { btr_rec_free_externally_stored_fields(cursor->index, - rec, rec_get_offsets(rec, cursor->index, - NULL, ULINT_UNDEFINED, &heap), - in_rollback, mtr); - mem_heap_empty(heap); + rec, offsets, in_rollback, mtr); } if ((page_get_n_recs(page) < 2) @@ -2568,7 +2569,8 @@ btr_cur_pessimistic_delete( btr_search_update_hash_on_delete(cursor); - page_cur_delete_rec(btr_cur_get_page_cur(cursor), cursor->index, mtr); + page_cur_delete_rec(btr_cur_get_page_cur(cursor), cursor->index, + offsets, mtr); ut_ad(btr_check_node_ptr(tree, page, mtr)); diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h index 7c6ff081c6d..4fc62f37db7 100644 --- a/innobase/include/page0cur.h +++ b/innobase/include/page0cur.h @@ -182,9 +182,10 @@ next record after the deleted one. */ void page_cur_delete_rec( /*================*/ - page_cur_t* cursor, /* in: a page cursor */ - dict_index_t* index, /* in: record descriptor */ - mtr_t* mtr); /* in: mini-transaction handle */ + page_cur_t* cursor, /* in: a page cursor */ + dict_index_t* index, /* in: record descriptor */ + const ulint* offsets,/* in: rec_get_offsets(cursor->rec, index) */ + mtr_t* mtr); /* in: mini-transaction handle */ /******************************************************************** Searches the right position for a page cursor. */ UNIV_INLINE diff --git a/innobase/include/page0page.h b/innobase/include/page0page.h index d3ef8214eb6..144c297b811 100644 --- a/innobase/include/page0page.h +++ b/innobase/include/page0page.h @@ -528,7 +528,7 @@ page_mem_free( /*==========*/ page_t* page, /* in: index page */ rec_t* rec, /* in: pointer to the (origin of) record */ - dict_index_t* index); /* in: record descriptor */ + const ulint* offsets);/* in: array returned by rec_get_offsets() */ /************************************************************** The index page creation function. */ diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic index a63b5ca4238..e3e93e9f756 100644 --- a/innobase/include/page0page.ic +++ b/innobase/include/page0page.ic @@ -777,20 +777,28 @@ page_mem_free( /*==========*/ page_t* page, /* in: index page */ rec_t* rec, /* in: pointer to the (origin of) record */ - dict_index_t* index) /* in: record descriptor */ + const ulint* offsets)/* in: array returned by rec_get_offsets() */ { rec_t* free; ulint garbage; + ut_ad(rec_offs_validate(rec, NULL, offsets)); free = page_header_get_ptr(page, PAGE_FREE); page_rec_set_next(rec, free); page_header_set_ptr(page, PAGE_FREE, rec); + /* Clear the data bytes of the deleted record in order to improve + the compression ratio of the page and to make it easier to read + page dumps in corruption reports. The extra bytes of the record + cannot be cleared, because page_mem_alloc() needs them in order + to determine the size of the deleted record. */ + memset(rec, 0, rec_offs_data_size(offsets)); + garbage = page_header_get_field(page, PAGE_GARBAGE); page_header_set_field(page, PAGE_GARBAGE, - garbage + rec_get_size(rec, index)); + garbage + rec_offs_size(offsets)); } #ifdef UNIV_MATERIALIZE diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index c430def684a..6721fa85f16 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -435,15 +435,6 @@ rec_offs_size( /* out: size */ const ulint* offsets);/* in: array returned by rec_get_offsets() */ /************************************************************** -Returns the total size of a physical record. */ - -ulint -rec_get_size( -/*=========*/ - /* out: size */ - rec_t* rec, /* in: physical record */ - dict_index_t* index); /* in: record descriptor */ -/************************************************************** Returns a pointer to the start of the record. */ UNIV_INLINE byte* diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 40a7deee604..e1869a171b5 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -1435,9 +1435,10 @@ loop: mutex_exit(&(recv_sys->mutex)); } +#ifdef UNIV_HOTBACKUP /* This page is allocated from the buffer pool and used in the function below */ -page_t* recv_backup_application_page = NULL; +static page_t* recv_backup_application_page = NULL; /*********************************************************************** Applies log records in the hash table to a backup. */ @@ -1559,6 +1560,7 @@ skip_this_recv_addr: recv_sys_empty_hash(); } +#endif /* UNIV_HOTBACKUP */ #ifdef notdefined /*********************************************************************** diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c index 488d2757115..d083cc26069 100644 --- a/innobase/page/page0cur.c +++ b/innobase/page/page0cur.c @@ -1267,9 +1267,18 @@ page_cur_parse_delete_rec( ut_a(offset <= UNIV_PAGE_SIZE); if (page) { - page_cur_position(page + offset, &cursor); + mem_heap_t* heap = NULL; + ulint offsets_[100] = { 100, }; + rec_t* rec = page + offset; - page_cur_delete_rec(&cursor, index, mtr); + page_cur_position(rec, &cursor); + + page_cur_delete_rec(&cursor, index, + rec_get_offsets(rec, index, offsets_, + ULINT_UNDEFINED, &heap), mtr); + if (heap) { + mem_heap_free(heap); + } } return(ptr); @@ -1284,6 +1293,7 @@ page_cur_delete_rec( /*================*/ page_cur_t* cursor, /* in: a page cursor */ dict_index_t* index, /* in: record descriptor */ + const ulint* offsets,/* in: rec_get_offsets(cursor->rec, index) */ mtr_t* mtr) /* in: mini-transaction handle */ { page_dir_slot_t* cur_dir_slot; @@ -1300,6 +1310,7 @@ page_cur_delete_rec( page = page_cur_get_page(cursor); current_rec = cursor->rec; + ut_ad(rec_offs_validate(current_rec, index, offsets)); /* The record must not be the supremum or infimum record. */ ut_ad(current_rec != page_get_supremum_rec(page)); @@ -1365,7 +1376,7 @@ page_cur_delete_rec( page_dir_slot_set_n_owned(cur_dir_slot, cur_n_owned - 1); /* 6. Free the memory occupied by the record */ - page_mem_free(page, current_rec, index); + page_mem_free(page, current_rec, offsets); /* 7. Now we have decremented the number of owned records of the slot. If the number drops below PAGE_DIR_SLOT_MIN_N_OWNED, we balance the diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index 901c8cd0831..b393f0c0ad7 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -416,7 +416,7 @@ page_create( mem_heap_free(heap); - /* 4. INITIALIZE THE PAGE HEADER */ + /* 4. INITIALIZE THE PAGE */ page_header_set_field(page, PAGE_N_DIR_SLOTS, 2); page_header_set_ptr(page, PAGE_HEAP_TOP, heap_top); @@ -428,7 +428,9 @@ page_create( page_header_set_field(page, PAGE_N_DIRECTION, 0); page_header_set_field(page, PAGE_N_RECS, 0); page_set_max_trx_id(page, ut_dulint_zero); - + memset(heap_top, 0, UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START + - (heap_top - page)); + /* 5. SET POINTERS IN RECORDS AND DIR SLOTS */ /* Set the slots to point to infimum and supremum. */ @@ -829,12 +831,18 @@ page_delete_rec_list_start( { page_cur_t cur1; ulint log_mode; + ulint offsets_[100] = { 100, }; + ulint* offsets = offsets_; + mem_heap_t* heap = NULL; + byte type; - page_delete_rec_list_write_log(page, rec, index, - index->table->comp - ? MLOG_COMP_LIST_START_DELETE - : MLOG_LIST_START_DELETE, - mtr); + if (index->table->comp) { + type = MLOG_COMP_LIST_START_DELETE; + } else { + type = MLOG_LIST_START_DELETE; + } + + page_delete_rec_list_write_log(page, rec, index, type, mtr); page_cur_set_before_first(page, &cur1); @@ -850,8 +858,13 @@ page_delete_rec_list_start( log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); while (page_cur_get_rec(&cur1) != rec) { + offsets = rec_get_offsets(page_cur_get_rec(&cur1), index, + offsets, ULINT_UNDEFINED, &heap); + page_cur_delete_rec(&cur1, index, offsets, mtr); + } - page_cur_delete_rec(&cur1, index, mtr); + if (heap) { + mem_heap_free(heap); } /* Restore log mode */ diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c index 30f98f457ea..904f91b8945 100644 --- a/innobase/rem/rem0rec.c +++ b/innobase/rem/rem0rec.c @@ -620,7 +620,7 @@ rec_set_nth_field_extern_bit_new( mlog_write_ulint(lens + 1, len, MLOG_1BYTE, mtr); } else { - lens[1] = len; + lens[1] = (byte) len; } return; } @@ -658,29 +658,6 @@ rec_set_field_extern_bits( } } -/************************************************************** -Returns the total size of a physical record. */ - -ulint -rec_get_size( -/*=========*/ - /* out: size */ - rec_t* rec, /* in: physical record */ - dict_index_t* index) /* in: record descriptor */ -{ - mem_heap_t* heap = NULL; - ulint offsets_[100 + REC_OFFS_HEADER_SIZE] - = { 100, }; - ulint* offsets = rec_get_offsets(rec, index, offsets_, - ULINT_UNDEFINED, &heap); - ulint size = rec_offs_size(offsets); - - if (heap) { - mem_heap_free(heap); - } - return(size); -} - /*************************************************************** Sets an old-style record field to SQL null. The physical size of the field is not changed. */ @@ -935,13 +912,13 @@ init: || dtype_get_mtype(type) == DATA_BLOB); if (len < 128 || (dtype_get_len(type) < 256 && dtype_get_mtype(type) != DATA_BLOB)) { - *lens-- = len; + *lens-- = (byte) len; } else { /* the extern bits will be set later */ ut_ad(len < 16384); - *lens-- = len >> 8 | 0x80; - *lens-- = len; + *lens-- = (byte) (len >> 8) | 0x80; + *lens-- = (byte) len; } } copy: diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 55ce452772d..39bb5094053 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1501,7 +1501,7 @@ srv_suspend_mysql_thread( ut_usectime(&sec, &ms); finish_time = (ib_longlong)sec * 1000000 + ms; - diff_time = finish_time - start_time; + diff_time = (ulint) (finish_time - start_time); srv_n_lock_wait_current_count--; srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time; @@ -1799,9 +1799,12 @@ srv_export_innodb_status(void) export_vars.innodb_row_lock_waits= srv_n_lock_wait_count; export_vars.innodb_row_lock_current_waits= srv_n_lock_wait_current_count; export_vars.innodb_row_lock_time= srv_n_lock_wait_time / 10000; - export_vars.innodb_row_lock_time_avg= - (srv_n_lock_wait_count > 0) ? - (srv_n_lock_wait_time / 10000 / srv_n_lock_wait_count) : 0; + if (srv_n_lock_wait_count > 0) { + export_vars.innodb_row_lock_time_avg = (ulint) + (srv_n_lock_wait_time / 10000 / srv_n_lock_wait_count); + } else { + export_vars.innodb_row_lock_time_avg = 0; + } export_vars.innodb_row_lock_time_max= srv_n_lock_max_wait_time / 10000; export_vars.innodb_rows_read= srv_n_rows_read; export_vars.innodb_rows_inserted= srv_n_rows_inserted; diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index 98b91ed5211..e604912e996 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -369,11 +369,11 @@ mutex_spin_wait( { ulint index; /* index of the reserved wait cell */ ulint i; /* spin round count */ +#ifndef UNIV_HOTBACKUP ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */ ulint ltime_diff; ulint sec; ulint ms; -#ifndef UNIV_HOTBACKUP uint timer_started = 0; #endif /* !UNIV_HOTBACKUP */ ut_ad(mutex); @@ -535,7 +535,7 @@ finish_timing: ut_usectime(&sec, &ms); lfinish_time= (ib_longlong)sec * 1000000 + ms; - ltime_diff= lfinish_time - lstart_time; + ltime_diff= (ulint) (lfinish_time - lstart_time); mutex->lspent_time += ltime_diff; if (mutex->lmax_spent_time < ltime_diff) { From 6b5ad3c14320ba71293929df4a11b508c79536d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 05:54:48 -0600 Subject: [PATCH 08/15] my_mmap.c: Changed #warning pragma at the bottom to only occur when being used on non-Windows OS mysys/my_mmap.c: Changed #warning pragma at the bottom to only occur when being used on non-Windows OS --- mysys/my_mmap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index ed662a38712..98243c9d5d8 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -85,9 +85,7 @@ int my_msync(int fd, void *addr, size_t len, int flags) #endif -#ifdef _WINDOWS -#pragma message "no mmap!" -#else +#ifndef __WIN__ #warning "no mmap!" #endif From 1a3ee0dec50cb71d314ed6935a012760f0cb72d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 14:13:25 +0200 Subject: [PATCH 09/15] Fixed Bug#7906, "Cmdline help for mysqld --ansi option misses some info". --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f1b1d8a7d86..b5674d17901 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4173,7 +4173,7 @@ struct my_option my_long_options[] = (gptr*) &abort_slave_event_count, (gptr*) &abort_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ - {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax.", 0, 0, 0, + {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode will also set transaction isolation level 'serializable'.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"basedir", 'b', "Path to installation directory. All paths are usually resolved relative to this.", From 39cf45fd54247ca02554a2ecfedcbfbd996b9060 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 19:42:59 +0200 Subject: [PATCH 10/15] After review fixes. Fix bugs in TRUNCATE. innobase/dict/dict0crea.c: dict_truncate_index_tree(): Commit the mtr after deleting the index tree. Add diagnostics for error cases. Let the caller update SYS_INDEXES.PAGE_NO to the new root page number. Return the new root page number, or FIL_NULL on error. innobase/include/dict0crea.h: dict_truncate_index_tree(): Commit the mtr after deleting the index tree. Add diagnostics for error cases. Let the caller update SYS_INDEXES.PAGE_NO to the new root page number. Return the new root page number, or FIL_NULL on error. innobase/include/page0page.ic: page_mem_free(): Disable the memset() call, to make it possible to recover some data if someone accidentally deletes a large number of records from a table. innobase/log/log0recv.c: Do not disable InnoDB Hot Backup specific code in MySQL builds. innobase/row/row0mysql.c: row_truncate_table_for_mysql(): Remove an infinite loop in case a SYS_INDEXES record has been deleted. Avoid deadlocks by committing and restarting the mini-transaction. sql/ha_innodb.cc: ha_innobase::delete_all_rows(): set trx->active_trans = 1 --- innobase/dict/dict0crea.c | 43 +++++++++++++++++++++++++++++------ innobase/include/dict0crea.h | 7 ++++-- innobase/include/page0page.ic | 3 +++ innobase/log/log0recv.c | 2 -- innobase/row/row0mysql.c | 27 ++++++++++++++++++++-- sql/ha_innodb.cc | 2 ++ 6 files changed, 71 insertions(+), 13 deletions(-) diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index 4926797721c..fda09feca6f 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -729,14 +729,17 @@ dict_drop_index_tree( /*********************************************************************** Truncates the index tree associated with a row in SYS_INDEXES table. */ -void +ulint dict_truncate_index_tree( /*=====================*/ + /* out: new root page number, or + FIL_NULL on failure */ dict_table_t* table, /* in: the table the index belongs to */ rec_t* rec, /* in: record in the clustered index of SYS_INDEXES table */ mtr_t* mtr) /* in: mtr having the latch - on the record page */ + on the record page. The mtr may be + committed and restarted in this call. */ { ulint root_page_no; ulint space; @@ -761,7 +764,10 @@ dict_truncate_index_tree( if (root_page_no == FIL_NULL) { /* The tree has been freed. */ - return; + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Trying to TRUNCATE" + " a missing index of table %s!\n", table->name); + return(FIL_NULL); } ptr = rec_get_nth_field_old(rec, @@ -775,7 +781,10 @@ dict_truncate_index_tree( /* It is a single table tablespace and the .ibd file is missing: do nothing */ - return; + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Trying to TRUNCATE" + " a missing .ibd file of table %s!\n", table->name); + return(FIL_NULL); } ptr = rec_get_nth_field_old(rec, @@ -801,6 +810,20 @@ dict_truncate_index_tree( space, root_page_no, RW_X_LATCH, mtr)); btr_free_root(space, root_page_no, mtr); + /* We will temporarily write FIL_NULL to the PAGE_NO field + in SYS_INDEXES, so that the database will not get into an + inconsistent state in case it crashes between the mtr_commit() + below and the following mtr_commit() call. */ + page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, + FIL_NULL, mtr); + + /* We will need to commit the mini-transaction in order to avoid + deadlocks in the btr_create() call, because otherwise we would + be freeing and allocating pages in the same mini-transaction. */ + mtr_commit(mtr); + /* mtr_commit() will invalidate rec. */ + rec = NULL; + mtr_start(mtr); /* Find the index corresponding to this SYS_INDEXES record. */ for (index = UT_LIST_GET_FIRST(table->indexes); @@ -814,11 +837,17 @@ dict_truncate_index_tree( root_page_no = btr_create(type, space, index_id, comp, mtr); if (index) { index->tree->page = root_page_no; + } else { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Index %lu %lu of table %s is missing\n" + "InnoDB: from the data dictionary during TRUNCATE!\n", + ut_dulint_get_high(index_id), + ut_dulint_get_low(index_id), + table->name); } - page_rec_write_index_page_no(rec, - DICT_SYS_INDEXES_PAGE_NO_FIELD, - root_page_no, mtr); + return(root_page_no); } /************************************************************************* diff --git a/innobase/include/dict0crea.h b/innobase/include/dict0crea.h index 7164e53bceb..5dd571be59c 100644 --- a/innobase/include/dict0crea.h +++ b/innobase/include/dict0crea.h @@ -56,14 +56,17 @@ dict_create_index_step( /*********************************************************************** Truncates the index tree associated with a row in SYS_INDEXES table. */ -void +ulint dict_truncate_index_tree( /*=====================*/ + /* out: new root page number, or + FIL_NULL on failure */ dict_table_t* table, /* in: the table the index belongs to */ rec_t* rec, /* in: record in the clustered index of SYS_INDEXES table */ mtr_t* mtr); /* in: mtr having the latch - on the record page */ + on the record page. The mtr may be + committed and restarted in this call. */ /*********************************************************************** Drops the index tree associated with a row in SYS_INDEXES table. */ diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic index e3e93e9f756..ac6b0263a7d 100644 --- a/innobase/include/page0page.ic +++ b/innobase/include/page0page.ic @@ -788,12 +788,15 @@ page_mem_free( page_rec_set_next(rec, free); page_header_set_ptr(page, PAGE_FREE, rec); +#if 0 /* It's better not to destroy the user's data. */ + /* Clear the data bytes of the deleted record in order to improve the compression ratio of the page and to make it easier to read page dumps in corruption reports. The extra bytes of the record cannot be cleared, because page_mem_alloc() needs them in order to determine the size of the deleted record. */ memset(rec, 0, rec_offs_data_size(offsets)); +#endif garbage = page_header_get_field(page, PAGE_GARBAGE); diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index e1869a171b5..ac230f6461b 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -1435,7 +1435,6 @@ loop: mutex_exit(&(recv_sys->mutex)); } -#ifdef UNIV_HOTBACKUP /* This page is allocated from the buffer pool and used in the function below */ static page_t* recv_backup_application_page = NULL; @@ -1560,7 +1559,6 @@ skip_this_recv_addr: recv_sys_empty_hash(); } -#endif /* UNIV_HOTBACKUP */ #ifdef notdefined /*********************************************************************** diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 39c4b76f814..4c014d39f7a 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2615,6 +2615,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ rec_t* rec; const byte* field; ulint len; + ulint root_page_no; if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { /* The end of SYS_INDEXES has been reached. */ @@ -2633,11 +2634,33 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ if (rec_get_deleted_flag(rec, FALSE)) { /* The index has been dropped. */ - continue; + goto next_rec; } - dict_truncate_index_tree(table, rec, &mtr); + btr_pcur_store_position(&pcur, &mtr); + /* This call may commit and restart mtr. */ + root_page_no = dict_truncate_index_tree(table, rec, &mtr); + + btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr); + rec = btr_pcur_get_rec(&pcur); + + if (root_page_no != FIL_NULL) { + page_rec_write_index_page_no(rec, + DICT_SYS_INDEXES_PAGE_NO_FIELD, + root_page_no, &mtr); + /* We will need to commit and restart the + mini-transaction in order to avoid deadlocks. + The dict_truncate_index_tree() call has allocated + a page in this mini-transaction, and the rest of + this loop could latch another index page. */ + mtr_commit(&mtr); + mtr_start(&mtr); + btr_pcur_restore_position(BTR_MODIFY_LEAF, + &pcur, &mtr); + } + + next_rec: btr_pcur_move_to_next_user_rec(&pcur, &mtr); } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f68ad99ac44..c23b316f180 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4250,6 +4250,8 @@ ha_innobase::delete_all_rows(void) /* Truncate the table in InnoDB */ + trx->active_trans = 1; + error = row_truncate_table_for_mysql(prebuilt->table, trx); if (error == DB_ERROR) { /* Cannot truncate; resort to ha_innobase::delete_row() */ From 0319b958b50a47a42c4b1b185b1b1310ce0017aa Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 19:44:53 +0200 Subject: [PATCH 11/15] ha_innodb.cc: In TRUNCATE TABLE, MySQL may call innobase_xa_prepare() even though there is no active transaction because it was committed in ha_innobase::delete_all_rows(); in innobase_xa_prepare() InnoDB starts then a new transaction; let us adjust the trx->active_trans flag accordingly sql/ha_innodb.cc: In TRUNCATE TABLE, MySQL may call innobase_xa_prepare() even though there is no active transaction because it was committed in ha_innobase::delete_all_rows(); in innobase_xa_prepare() InnoDB starts then a new transaction; let us adjust the trx->active_trans flag accordingly --- sql/ha_innodb.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f68ad99ac44..121dbdccc12 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -6313,6 +6313,14 @@ innobase_xa_prepare( /* We were instructed to prepare the whole transaction, or this is an SQL statement end and autocommit is on */ + /* If there is no active InnoDB transaction, + trx_prepare_for_mysql() will (temporarily) start one */ + + if (trx->active_trans == 0) { + + trx->active_trans = 1; + } + error = trx_prepare_for_mysql(trx); } else { /* We just mark the SQL statement ended and do not do a From c0b1255317226e0a92f5c5d757fec14aa9de5b72 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 20:56:39 +0200 Subject: [PATCH 12/15] ha_innodb.cc: delete_all_rows(): Revert previous change. The transaction has been marked started already in external_lock(). sql/ha_innodb.cc: delete_all_rows(): Revert previous change. The transaction has been marked started already in external_lock(). --- sql/ha_innodb.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 83831858360..121dbdccc12 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4250,8 +4250,6 @@ ha_innobase::delete_all_rows(void) /* Truncate the table in InnoDB */ - trx->active_trans = 1; - error = row_truncate_table_for_mysql(prebuilt->table, trx); if (error == DB_ERROR) { /* Cannot truncate; resort to ha_innobase::delete_row() */ From 53bfeb48442ed04c8498cb4118b3715fd1dbeb42 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 22:19:19 +0200 Subject: [PATCH 13/15] Fix for Bug#5615 and merge from 4.1 mysql-test/r/func_group.result: Added some tests and fix for Bug#5615. mysql-test/r/show_check.result: Fix for Bug#5615. mysql-test/t/func_group.test: Added some tests. sql/item_sum.cc: Fix for Bug#5615. sql/item_sum.h: Fix for Bug#5615. sql/sql_select.cc: Fix for Bug#5615. sql/sql_select.h: Fix for Bug#5615. --- mysql-test/r/func_group.result | 16 ++++++++++++++-- mysql-test/r/show_check.result | 4 +--- mysql-test/t/func_group.test | 4 ++++ sql/item_sum.cc | 18 ++++++++++++++++-- sql/item_sum.h | 3 ++- sql/sql_select.cc | 8 ++++---- sql/sql_select.h | 4 ++++ 7 files changed, 45 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 6aadcd359b7..ea299455364 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -669,12 +669,24 @@ select charset(max(a)), coercibility(max(a)), charset(min(a)), coercibility(min(a)) from t1; charset(max(a)) coercibility(max(a)) charset(min(a)) coercibility(min(a)) latin2 2 latin2 2 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(1) character set latin2 default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 create table t2 select max(a),min(a) from t1; show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `max(a)` varchar(1) character set latin2 default NULL, - `min(a)` varchar(1) character set latin2 default NULL + `max(a)` char(1) character set latin2 default NULL, + `min(a)` char(1) character set latin2 default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t2; +create table t2 select concat(a) from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `concat(a)` varchar(1) character set latin2 default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t2,t1; create table t1 (a int); diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index a2b2eebf628..15cae7646f9 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -252,11 +252,9 @@ type_bool type_tiny type_short type_mediumint type_bigint type_decimal type_nume drop table t1; create table t1 (a int not null); create table t2 select max(a) from t1; -Warnings: -Warning 1263 Data truncated; NULL supplied to NOT NULL column 'max(a)' at row 1 show columns from t2; Field Type Null Key Default Extra -max(a) int(11) 0 +max(a) int(11) YES NULL drop table t1,t2; create table t1 (c decimal, d double, f float, r real); show columns from t1; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 51528be8952..96fd297dc20 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -395,8 +395,12 @@ create table t1 (a char character set latin2); insert into t1 values ('a'),('b'); select charset(max(a)), coercibility(max(a)), charset(min(a)), coercibility(min(a)) from t1; +show create table t1; create table t2 select max(a),min(a) from t1; show create table t2; +drop table t2; +create table t2 select concat(a) from t1; +show create table t2; drop table t2,t1; # diff --git a/sql/item_sum.cc b/sql/item_sum.cc index b4a53ba0f80..dbba02c3cf7 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -22,6 +22,7 @@ #endif #include "mysql_priv.h" +#include "sql_select.h" Item_sum::Item_sum(List &list) :arg_count(list.elements) @@ -303,6 +304,21 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return FALSE; } +Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, + uint convert_blob_length) +{ + if (args[0]->type() == Item::FIELD_ITEM) + { + Field *field= ((Item_field*) args[0])->field; + + if ((field= create_tmp_field_from_field(current_thd, field, this, table, + 0, convert_blob_length))) + field->flags&= ~NOT_NULL_FLAG; + return field; + } + return Item_sum::create_tmp_field(group, table, convert_blob_length); +} + /*********************************************************************** ** reset and add of sum_func @@ -2075,8 +2091,6 @@ my_decimal *Item_variance_field::val_decimal(my_decimal *dec_buf) ** COUNT(DISTINCT ...) ****************************************************************************/ -#include "sql_select.h" - int simple_str_key_cmp(void* arg, byte* key1, byte* key2) { Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg; diff --git a/sql/item_sum.h b/sql/item_sum.h index 81f5d45e42e..fead45f1881 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -94,7 +94,6 @@ public: Item *get_tmp_table_item(THD *thd); virtual Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); - bool walk (Item_processor processor, byte *argument); }; @@ -525,6 +524,8 @@ protected: void cleanup(); bool any_value() { return was_values; } void no_rows_in_result(); + Field *create_tmp_field(bool group, TABLE *table, + uint convert_blob_length); }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cbe7937355c..e886c658444 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7593,10 +7593,10 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) new_created field */ -static Field* create_tmp_field_from_field(THD *thd, Field* org_field, - Item *item, TABLE *table, - bool modify_item, - uint convert_blob_length) +Field* create_tmp_field_from_field(THD *thd, Field* org_field, + Item *item, TABLE *table, + bool modify_item, + uint convert_blob_length) { Field *new_field; diff --git a/sql/sql_select.h b/sql/sql_select.h index 0f26207b391..1b7893dbc7c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -399,6 +399,10 @@ void copy_funcs(Item **func_ptr); bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, int error, bool ignore_last_dupp_error); uint find_shortest_key(TABLE *table, const key_map *usable_keys); +Field* create_tmp_field_from_field(THD *thd, Field* org_field, + Item *item, TABLE *table, + bool modify_item, + uint convert_blob_length); /* functions from opt_sum.cc */ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order); From af529fd14c871e78acac4d6c0dd6091086692675 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 00:25:16 +0100 Subject: [PATCH 14/15] Makefile.am: updated ndb test makefile to make src dist complete ndb/test/ndbapi/Makefile.am: updated ndb test makefile to make src dist complete --- ndb/test/ndbapi/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am index 5eb3c215ee5..9a1726ae11a 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -74,8 +74,8 @@ testReadPerf_SOURCES = testReadPerf.cpp testLcp_SOURCES = testLcp.cpp testPartitioning_SOURCES = testPartitioning.cpp testBitfield_SOURCES = testBitfield.cpp -DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp -DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp +DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp +DbAsyncGenerator_SOURCES = bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel From 67457597b80a0f636a8477cffcca37bf64c7c1d0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 01:25:17 +0200 Subject: [PATCH 15/15] ha_innodb.cc: Correct indentation + some small style corrections sql/ha_innodb.cc: Correct indentation + some small style corrections --- sql/ha_innodb.cc | 215 ++++++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 97 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 121dbdccc12..35f60d1daf9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & Innobase Oy +/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -336,14 +336,18 @@ innobase_release_temporary_latches( /*===============================*/ THD *thd) { + trx_t* trx; + if (!innodb_inited) { return; } - trx_t *trx= (trx_t*) thd->ha_data[innobase_hton.slot]; - if (trx) - innobase_release_stat_resources(trx); + trx = (trx_t*) thd->ha_data[innobase_hton.slot]; + + if (trx) { + innobase_release_stat_resources(trx); + } } /************************************************************************ @@ -743,14 +747,15 @@ transaction internally. */ static void register_trans( -/*============*/ +/*===========*/ THD* thd) /* in: thd to use the handle */ { - /* register the start of the statement */ + /* Register the start of the statement */ trans_register_ha(thd, FALSE, &innobase_hton); + if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { - /* no autocommit mode, register for a transaction */ + /* No autocommit mode, register for a transaction */ trans_register_ha(thd, TRUE, &innobase_hton); } } @@ -1051,7 +1056,7 @@ ha_innobase::init_table_handle_for_HANDLER(void) /************************************************************************* Opens an InnoDB database. */ -handlerton * +handlerton* innobase_init(void) /*===============*/ /* out: TRUE if error */ @@ -1220,7 +1225,7 @@ innobase_init(void) srv_print_verbose_log = mysqld_embedded ? 0 : 1; - /* Store the default charset-collation number of this MySQL + /* Store the default charset-collation number of this MySQL installation */ data_mysql_default_charset_coll = (ulint)default_charset_info->number; @@ -1346,14 +1351,16 @@ innobase_commit_low( return; } +/* The following will be enabled later when we put the 4.1 functionality back +to 5.0. */ #ifdef DISABLE_HAVE_REPLICATION if (current_thd->slave_thread) { /* Update the replication position info inside InnoDB */ trx->mysql_master_log_file_name = active_mi->rli.group_master_log_name; - trx->mysql_master_log_pos= ((ib_longlong) - active_mi->rli.future_group_master_log_pos); + trx->mysql_master_log_pos = ((ib_longlong) + active_mi->rli.future_group_master_log_pos); } #endif /* HAVE_REPLICATION */ @@ -1456,7 +1463,8 @@ innobase_commit( "InnoDB: but trx->conc_state != TRX_NOT_STARTED\n"); } - if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { /* We were instructed to commit the whole transaction, or this is an SQL statement end and autocommit is on */ @@ -1489,10 +1497,9 @@ innobase_commit( DBUG_RETURN(0); } -/* - don't delete it - it may be re-enabled later - as an optimization for the most common case InnoDB+binlog -*/ +/* The following defined-out code will be enabled later when we put the +MySQL-4.1 functionality back to 5.0. This is needed to get InnoDB Hot Backup +to work. */ #if 0 /********************************************************************* This is called when MySQL writes the binlog entry for the current @@ -1627,7 +1634,8 @@ innobase_rollback( row_unlock_table_autoinc_for_mysql(trx); } - if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { error = trx_rollback_for_mysql(trx); trx->active_trans = 0; @@ -1686,6 +1694,7 @@ innobase_rollback_to_savepoint( ib_longlong mysql_binlog_cache_pos; int error = 0; trx_t* trx; + char name[64]; DBUG_ENTER("innobase_rollback_to_savepoint"); @@ -1698,8 +1707,8 @@ innobase_rollback_to_savepoint( innobase_release_stat_resources(trx); /* TODO: use provided savepoint data area to store savepoint data */ - char name[64]; - longlong2str((ulonglong)savepoint,name,36); + + longlong2str((ulonglong)savepoint, name, 36); error = trx_rollback_to_savepoint_for_mysql(trx, name, &mysql_binlog_cache_pos); @@ -1708,26 +1717,27 @@ innobase_rollback_to_savepoint( /********************************************************************* Release transaction savepoint name. */ - -static int +static +int innobase_release_savepoint( -/*===========================*/ +/*=======================*/ /* 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 */ - void *savepoint) /* in: savepoint data */ + void* savepoint) /* in: savepoint data */ { int error = 0; trx_t* trx; + char name[64]; DBUG_ENTER("innobase_release_savepoint"); trx = check_trx_exists(thd); /* TODO: use provided savepoint data area to store savepoint data */ - char name[64]; - longlong2str((ulonglong)savepoint,name,36); + + longlong2str((ulonglong)savepoint, name, 36); error = trx_release_savepoint_for_mysql(trx, name); @@ -1736,13 +1746,13 @@ innobase_release_savepoint( /********************************************************************* Sets a transaction savepoint. */ - -static int +static +int innobase_savepoint( /*===============*/ /* out: always 0, that is, always succeeds */ THD* thd, /* in: handle to the MySQL thread */ - void *savepoint) /* in: savepoint data */ + void* savepoint) /* in: savepoint data */ { int error = 0; trx_t* trx; @@ -1911,7 +1921,8 @@ ha_innobase::open( fields when packed actually became 1 byte longer, when we also stored the string length as the first byte. */ - upd_and_key_val_buff_len = table->s->reclength + table->s->max_key_length + upd_and_key_val_buff_len = + table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3; if (!(mysql_byte*) my_multi_malloc(MYF(MY_WME), &upd_buff, upd_and_key_val_buff_len, @@ -1963,7 +1974,8 @@ ha_innobase::open( innobase_prebuilt = row_create_prebuilt(ib_table); - ((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = table->s->reclength; + ((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = + table->s->reclength; /* Looks like MySQL-3.23 sometimes has primary key number != 0 */ @@ -1985,13 +1997,11 @@ ha_innobase::open( ((row_prebuilt_t*)innobase_prebuilt) ->clust_index_was_generated = FALSE; - /* - MySQL allocates the buffer for ref. key_info->key_length - includes space for all key columns + one byte for each column - that may be NULL. ref_length must be as exact as possible to - save space, because all row reference buffers are allocated - based on ref_length. - */ + /* MySQL allocates the buffer for ref. key_info->key_length + includes space for all key columns + one byte for each column + that may be NULL. ref_length must be as exact as possible to + save space, because all row reference buffers are allocated + based on ref_length. */ ref_length = table->key_info[primary_key].key_length; } else { @@ -2013,15 +2023,13 @@ ha_innobase::open( ref_length = DATA_ROW_ID_LEN; - /* - If we automatically created the clustered index, then - MySQL does not know about it, and MySQL must NOT be aware - of the index used on scan, to make it avoid checking if we - update the column of the index. That is why we assert below - that key_used_on_scan is the undefined value MAX_KEY. - The column is the row id in the automatical generation case, - and it will never be updated anyway. - */ + /* If we automatically created the clustered index, then + MySQL does not know about it, and MySQL must NOT be aware + of the index used on scan, to make it avoid checking if we + update the column of the index. That is why we assert below + that key_used_on_scan is the undefined value MAX_KEY. + The column is the row id in the automatical generation case, + and it will never be updated anyway. */ if (key_used_on_scan != MAX_KEY) { fprintf(stderr, @@ -2611,7 +2619,8 @@ ha_innobase::write_row( "InnoDB: Dump of 200 bytes around transaction.all: ", stderr); ut_print_buf(stderr, - ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100, 200); + ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100, + 200); putc('\n', stderr); ut_error; } @@ -2646,7 +2655,7 @@ ha_innobase::write_row( src_table = lock_get_src_table( prebuilt->trx, prebuilt->table, &mode); if (!src_table) { - no_commit: +no_commit: /* Unknown situation: do not commit */ /* ut_print_timestamp(stderr); @@ -2669,6 +2678,7 @@ ha_innobase::write_row( } else { /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ + if (!lock_is_table_exclusive(prebuilt->table, prebuilt->trx)) { goto no_commit; @@ -2746,11 +2756,11 @@ ha_innobase::write_row( if (error == DB_SUCCESS && auto_inc_used) { - /* Fetch the value that was set in the autoincrement field */ + /* Fetch the value that was set in the autoincrement field */ - auto_inc = table->next_number_field->val_int(); + auto_inc = table->next_number_field->val_int(); - if (auto_inc != 0) { + if (auto_inc != 0) { /* This call will calculate the max of the current value and the value supplied by the user and update the counter accordingly */ @@ -2762,15 +2772,15 @@ ha_innobase::write_row( The lock is released at each SQL statement's end. */ - error = row_lock_table_autoinc_for_mysql(prebuilt); + error = row_lock_table_autoinc_for_mysql(prebuilt); - if (error != DB_SUCCESS) { - - error = convert_error_code_to_mysql(error, user_thd); - goto func_exit; - } - dict_table_autoinc_update(prebuilt->table, auto_inc); - } + if (error != DB_SUCCESS) { + error = convert_error_code_to_mysql(error, + user_thd); + goto func_exit; + } + dict_table_autoinc_update(prebuilt->table, auto_inc); + } } innodb_srv_conc_exit_innodb(prebuilt->trx); @@ -2785,7 +2795,6 @@ func_exit: DBUG_RETURN(error); } - /****************************************************************** Converts field data for storage in an InnoDB update vector. */ inline @@ -4514,10 +4523,10 @@ ha_innobase::records_in_range( dict_index_t* index; mysql_byte* key_val_buff2 = (mysql_byte*) my_malloc( table->s->reclength - + table->s->max_key_length + 100, + + table->s->max_key_length + 100, MYF(MY_WME)); ulint buff2_len = table->s->reclength - + table->s->max_key_length + 100; + + table->s->max_key_length + 100; dtuple_t* range_start; dtuple_t* range_end; ib_longlong n_rows; @@ -4674,21 +4683,27 @@ ha_innobase::read_time( ha_rows total_rows; double time_for_scan; - if (index != table->s->primary_key) - return handler::read_time(index, ranges, rows); // Not clustered + if (index != table->s->primary_key) { + /* Not clustered */ + return(handler::read_time(index, ranges, rows)); + } - if (rows <= 2) - return (double) rows; + if (rows <= 2) { + + return((double) rows); + } /* Assume that the read time is proportional to the scan time for all rows + at most one seek per range. */ time_for_scan = scan_time(); - if ((total_rows = estimate_rows_upper_bound()) < rows) - return time_for_scan; + if ((total_rows = estimate_rows_upper_bound()) < rows) { - return (ranges + (double) rows / (double) total_rows * time_for_scan); + return(time_for_scan); + } + + return(ranges + (double) rows / (double) total_rows * time_for_scan); } /************************************************************************* @@ -5106,7 +5121,7 @@ ha_innobase::get_foreign_key_list(THD *thd, List *f_key_list) tmp_buff, i, 1); tmp_buff+= i + 1; f_key_info.referenced_table= make_lex_string(thd, 0, - tmp_buff, strlen(tmp_buff), 1); + tmp_buff, strlen(tmp_buff), 1); for (i= 0;;) { @@ -5624,7 +5639,6 @@ innodb_export_status(void) srv_export_innodb_status(); } - /**************************************************************************** Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB Monitor to the client. */ @@ -5636,6 +5650,8 @@ innodb_show_status( { Protocol *protocol= thd->protocol; trx_t* trx; + long flen; + char* str; DBUG_ENTER("innodb_show_status"); @@ -5652,14 +5668,13 @@ innodb_show_status( /* We let the InnoDB Monitor to output at most 64000 bytes of text. */ - long flen; - char* str; - mutex_enter_noninline(&srv_monitor_file_mutex); rewind(srv_monitor_file); + srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); os_file_set_eof(srv_monitor_file); + if (flen < 0) { flen = 0; } else if (flen > 64000 - 1) { @@ -5669,10 +5684,10 @@ innodb_show_status( /* allocate buffer for the string, and read the contents of the temporary file */ - if (!(str = my_malloc(flen + 1, MYF(0)))) - { - mutex_exit_noninline(&srv_monitor_file_mutex); - DBUG_RETURN(TRUE); + if (!(str = my_malloc(flen + 1, MYF(0)))) { + mutex_exit_noninline(&srv_monitor_file_mutex); + + DBUG_RETURN(TRUE); } rewind(srv_monitor_file); @@ -5686,7 +5701,6 @@ innodb_show_status( if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) { - my_free(str, MYF(0)); DBUG_RETURN(TRUE); @@ -5696,10 +5710,12 @@ innodb_show_status( protocol->store(str, flen, system_charset_info); my_free(str, MYF(0)); - if (protocol->write()) - DBUG_RETURN(TRUE); + if (protocol->write()) { + DBUG_RETURN(TRUE); + } send_eof(thd); + DBUG_RETURN(FALSE); } @@ -6093,7 +6109,7 @@ ha_innobase::get_auto_increment() if (error) { - return(~(ulonglong) 0); + return(~(ulonglong) 0); } return((ulonglong) nr); @@ -6115,7 +6131,8 @@ ha_innobase::cmp_ref( /* Do type-aware comparison of Primary Key members. PK members are always NOT NULL, so no checks for NULL are performed */ - KEY_PART_INFO *key_part= table->key_info[table->s->primary_key].key_part; + KEY_PART_INFO *key_part= + table->key_info[table->s->primary_key].key_part; KEY_PART_INFO *key_part_end= key_part + table->key_info[table->s->primary_key].key_parts; for (; key_part != key_part_end; ++key_part) { @@ -6260,19 +6277,21 @@ innobase_query_is_update(void) thd = (THD *)innobase_current_thd(); - if ( thd->lex->sql_command == SQLCOM_REPLACE || - thd->lex->sql_command == SQLCOM_REPLACE_SELECT || - ( thd->lex->sql_command == SQLCOM_LOAD && - thd->lex->duplicates == DUP_REPLACE )) { - return true; + if (thd->lex->sql_command == SQLCOM_REPLACE || + thd->lex->sql_command == SQLCOM_REPLACE_SELECT || + (thd->lex->sql_command == SQLCOM_LOAD && + thd->lex->duplicates == DUP_REPLACE)) { + + return(1); } - if ( thd->lex->sql_command == SQLCOM_INSERT && - thd->lex->duplicates == DUP_UPDATE ) { - return true; + if (thd->lex->sql_command == SQLCOM_INSERT && + thd->lex->duplicates == DUP_UPDATE) { + + return(1); } - return false; + return(0); } } @@ -6308,7 +6327,8 @@ innobase_xa_prepare( "InnoDB: but trx->conc_state != TRX_NOT_STARTED\n"); } - if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { /* We were instructed to prepare the whole transaction, or this is an SQL statement end and autocommit is on */ @@ -6359,10 +6379,11 @@ innobase_xa_recover( uint len) /* in: number of slots in xid_list */ { if (len == 0 || xid_list == NULL) { - return 0; + + return(0); } - return (trx_recover_for_mysql(xid_list, len)); + return(trx_recover_for_mysql(xid_list, len)); } /*********************************************************************** @@ -6373,7 +6394,7 @@ int innobase_commit_by_xid( /*===================*/ /* out: 0 or error number */ - XID* xid) /* in: X/Open XA Transaction Identification */ + XID* xid) /* in: X/Open XA transaction identification */ { trx_t* trx; @@ -6396,7 +6417,7 @@ int innobase_rollback_by_xid( /*=====================*/ /* out: 0 or error number */ - XID *xid) /* in : X/Open XA Transaction Idenfification */ + XID *xid) /* in: X/Open XA transaction idenfification */ { trx_t* trx;