List:Commits« Previous MessageNext Message »
From:Guilhem Bichot Date:June 30 2008 10:00am
Subject:bzr commit into mysql-6.0 branch (guilhem:2670)
View as plain text  
#At file:///home/mysql_src/bzrrepos/mysql-6.0-maria/

 2670 Guilhem Bichot	2008-06-30 [merge]
      merge of 5.1-maria (mysql-maria branch) into mysql-6.0-maria
added:
  mysql-test/r/maria-recovery2.result
  mysql-test/r/row-checksum-old.result
  mysql-test/r/row-checksum.result
  mysql-test/t/maria-recovery2-master.opt
  mysql-test/t/maria-recovery2.test
  mysql-test/t/row-checksum-old-master.opt
  mysql-test/t/row-checksum-old.test
  mysql-test/t/row-checksum.test
modified:
  KNOWN_BUGS.txt
  mysql-test/r/maria-recovery.result
  mysql-test/r/old-mode.result
  mysql-test/t/maria-recovery.test
  mysql-test/t/old-mode.test
  sql/ha_partition.cc
  sql/handler.cc
  sql/handler.h
  sql/sql_show.cc
  sql/sql_table.cc
  storage/maria/ha_maria.cc
  storage/maria/ha_maria.h
  storage/maria/ma_blockrec.c
  storage/maria/ma_check.c
  storage/maria/ma_open.c
  storage/maria/ma_test1.c
  storage/maria/unittest/ma_test_loghandler_multithread-t.c
  storage/myisam/ha_myisam.cc
  storage/myisam/ha_myisam.h
  storage/myisam/mi_open.c
  storage/myisam/myisamdef.h

=== modified file 'KNOWN_BUGS.txt'
--- a/KNOWN_BUGS.txt	2008-06-02 20:53:25 +0000
+++ b/KNOWN_BUGS.txt	2008-06-28 15:09:03 +0000
@@ -27,9 +27,15 @@ Known bugs that we are working on and wi
 - We have some instabilities in log writing that is under investigatation
   This causes mainly assert to triggers in the code and sometimes
   the log handler doesn't start up after restart.
+  Most of this should now be fixed...
+
+- INSERT on a duplicate key against a key inserted by another connection
+  that has not yet ended will give a duplicate key error instead of
+  waiting for the other statement to end.
 
-Known bugs that are planned to be fixed before Beta
-===================================================
+
+Known bugs that are planned to be fixed before Gamma/RC
+=======================================================
 
 - If we get a write failure on disk (disk full or disk error) for the
   log, we should stop all usage of transactional tables and mark all
@@ -44,18 +50,31 @@ Known bugs that are planned to be fixed 
   or kill mysqld, remove logs and repair tables.
 
 
+Known bugs that are planned to be fixed later
+=============================================
+
+LOCK TABLES .. WRITE CONCURRENT is mainly done for testing MVCC.  Don't
+use this in production.  Things that is not working if you are using
+this on a table:
+
+- INSERT/REPLACE ... SELECT on an empty table may cause crashes or
+  wrong results if someone else is doing writes on the table during repair
+  or someone is doing selects during the repair index phase.
+
+INSERT ... SELECT, REPLACE ... SELECT and LOAD DATA are blocking
+inserts and SELECT for the table.  They should only have to do this if
+the destination is empty (as then we are using fast index rebuild).
+
 Missing features that is planned to fix before Beta
 ===================================================
 
-- Multiple concurrent inserts & multiple concurrent readers at same time
-  with full MVCC control.  Note that UPDATE and DELETE will still be
-  blocking (as with MyISAM)
-- COUNT(*) and TABLE CHECKSUM under MVCC (ie, they are instant and kept up
-  to date even with multiple inserter)
-
+None
 
 Features planned for future releases
 ====================================
 
+Most notable is full transaction support and multiple reader/writers
+in Maria 2.0
+
 http://forge.mysql.com/worklog/
 (you can enter "maria" in the "quick search" field there).

=== modified file 'mysql-test/r/maria-recovery.result'
--- a/mysql-test/r/maria-recovery.result	2008-06-26 17:48:42 +0000
+++ b/mysql-test/r/maria-recovery.result	2008-06-30 09:59:59 +0000
@@ -237,145 +237,6 @@ t1	CREATE TABLE `t1` (
 ) ENGINE=MARIA AUTO_INCREMENT=17 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
 insert into t1 values(null, "f");
 drop table t1;
-* TEST of removing logs manually
-* shut down mysqld, removed logs, restarted it
-* TEST of UNDO_ROW_DELETE preserving rowid
-create table t1(a int) engine=maria;
-insert into t1 values(1),(2);
-flush table t1;
-* copied t1 for comparison
-lock tables t1 write;
-insert into t1 values(3);
-delete from t1 where a in (1,2,3);
-SET SESSION debug="+d,maria_flush_whole_log,maria_crash";
-* crashing mysqld intentionally
-set global maria_checkpoint_interval=1;
-ERROR HY000: Lost connection to MySQL server during query
-* recovery happens
-check table t1 extended;
-Table	Op	Msg_type	Msg_text
-mysqltest.t1	check	status	OK
-* testing that checksum after recovery is as expected
-Checksum-check
-ok
-use mysqltest;
-drop table t1;
-* TEST of checkpoint
-set global debug="+d,info,query,enter,exit,loop,maria_checkpoint_indirect";
-set global maria_checkpoint_interval=10000;
-create table t1(a int, b varchar(10), index(a,b)) engine=maria;
-insert into t1 values(1,"a"),(2,"b"),(3,"c");
-delete from t1 where b="b";
-update t1 set b="d" where a=1;
-flush table t1;
-* copied t1 for comparison
-lock tables t1 write;
-insert into t1 values(4,"e"),(5,"f"),(6,"g");
-update t1 set b="h" where a=5;
-delete from t1 where b="g";
-show status like "Maria_pagecache_blocks_not_flushed";
-Variable_name	Value
-Maria_pagecache_blocks_not_flushed	3
-set global maria_checkpoint_interval=10000;
-update t1 set b="i" where a=5;
-SET SESSION debug="+d,maria_crash";
-* crashing mysqld intentionally
-set global maria_checkpoint_interval=1;
-ERROR HY000: Lost connection to MySQL server during query
-* recovery happens
-check table t1 extended;
-Table	Op	Msg_type	Msg_text
-mysqltest.t1	check	status	OK
-* testing that checksum after recovery is as expected
-Checksum-check
-ok
-use mysqltest;
-drop table t1;
-Test of REPAIR's implicit commit
-create table t1 (a varchar(100), key(a)) engine=maria;
-insert into t1 values(3);
-flush table t1;
-* copied t1 for comparison
-lock tables t1 write;
-insert into t1 values (1);
-repair table t1;
-Table	Op	Msg_type	Msg_text
-mysqltest.t1	repair	status	OK
-insert into t1 values(2);
-select * from t1;
-a
-1
-2
-3
-SET SESSION debug="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
-* crashing mysqld intentionally
-set global maria_checkpoint_interval=1;
-ERROR HY000: Lost connection to MySQL server during query
-* recovery happens
-check table t1 extended;
-Table	Op	Msg_type	Msg_text
-mysqltest.t1	check	status	OK
-* testing that checksum after recovery is as expected
-Checksum-check
-failure
-use mysqltest;
-select * from t1;
-a
-1
-3
-drop table t1;
-* TEST of recovery when crash before bulk-insert-with-repair is committed
-create table t1 (a varchar(100), key(a)) engine=maria;
-create table t2 (a varchar(100)) engine=myisam;
-set rand_seed1=12, rand_seed2=254;
-insert into t2 values (rand());
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t1 values(30);
-flush table t1;
-* copied t1 for comparison
-lock tables t1 write, t2 read;
-delete from t1 limit 1;
-insert into t1 select * from t2;
-SET SESSION debug="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
-* crashing mysqld intentionally
-set global maria_checkpoint_interval=1;
-ERROR HY000: Lost connection to MySQL server during query
-* recovery happens
-check table t1 extended;
-Table	Op	Msg_type	Msg_text
-mysqltest.t1	check	status	OK
-* testing that checksum after recovery is as expected
-Checksum-check
-ok
-use mysqltest;
-show keys from t1;
-Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment	Index_Comment
-t1	1	a	1	a	A	1	NULL	NULL	YES	BTREE		
-drop table t1;
-* TEST of recovery when OPTIMIZE has replaced the index file and crash
-create table t_corrupted1 (a varchar(100), key(a)) engine=maria;
-insert into t_corrupted1 select (rand()) from t2;
-flush table t_corrupted1;
-* copied t_corrupted1 for comparison
-SET SESSION debug="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash_sort_index";
-* crashing mysqld intentionally
-optimize table t_corrupted1;
-ERROR HY000: Lost connection to MySQL server during query
-* recovery happens
-check table t_corrupted1 extended;
-Table	Op	Msg_type	Msg_text
-mysqltest.t_corrupted1	check	warning	Table is marked as crashed and last repair failed
-mysqltest.t_corrupted1	check	status	OK
-* testing that checksum after recovery is as expected
-Checksum-check
-ok
-use mysqltest;
-drop table t_corrupted1, t2;
 drop database mysqltest_for_feeding_recovery;
 drop database mysqltest_for_comparison;
 drop database mysqltest;

=== added file 'mysql-test/r/maria-recovery2.result'
--- a/mysql-test/r/maria-recovery2.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/maria-recovery2.result	2008-06-30 09:59:59 +0000
@@ -0,0 +1,145 @@
+set global maria_log_file_size=4294967295;
+drop database if exists mysqltest;
+create database mysqltest;
+use mysqltest;
+* TEST of removing logs manually
+* shut down mysqld, removed logs, restarted it
+* TEST of UNDO_ROW_DELETE preserving rowid
+create table t1(a int) engine=maria;
+insert into t1 values(1),(2);
+flush table t1;
+* copied t1 for comparison
+lock tables t1 write;
+insert into t1 values(3);
+delete from t1 where a in (1,2,3);
+SET SESSION debug="+d,maria_flush_whole_log,maria_crash";
+* crashing mysqld intentionally
+set global maria_checkpoint_interval=1;
+ERROR HY000: Lost connection to MySQL server during query
+* recovery happens
+check table t1 extended;
+Table	Op	Msg_type	Msg_text
+mysqltest.t1	check	status	OK
+* testing that checksum after recovery is as expected
+Checksum-check
+ok
+use mysqltest;
+drop table t1;
+* TEST of checkpoint
+set global debug="+d,info,query,enter,exit,loop,maria_checkpoint_indirect";
+set global maria_checkpoint_interval=10000;
+create table t1(a int, b varchar(10), index(a,b)) engine=maria;
+insert into t1 values(1,"a"),(2,"b"),(3,"c");
+delete from t1 where b="b";
+update t1 set b="d" where a=1;
+flush table t1;
+* copied t1 for comparison
+lock tables t1 write;
+insert into t1 values(4,"e"),(5,"f"),(6,"g");
+update t1 set b="h" where a=5;
+delete from t1 where b="g";
+show status like "Maria_pagecache_blocks_not_flushed";
+Variable_name	Value
+Maria_pagecache_blocks_not_flushed	3
+set global maria_checkpoint_interval=10000;
+update t1 set b="i" where a=5;
+SET SESSION debug="+d,maria_crash";
+* crashing mysqld intentionally
+set global maria_checkpoint_interval=1;
+ERROR HY000: Lost connection to MySQL server during query
+* recovery happens
+check table t1 extended;
+Table	Op	Msg_type	Msg_text
+mysqltest.t1	check	status	OK
+* testing that checksum after recovery is as expected
+Checksum-check
+ok
+use mysqltest;
+drop table t1;
+Test of REPAIR's implicit commit
+create table t1 (a varchar(100), key(a)) engine=maria;
+insert into t1 values(3);
+flush table t1;
+* copied t1 for comparison
+lock tables t1 write;
+insert into t1 values (1);
+repair table t1;
+Table	Op	Msg_type	Msg_text
+mysqltest.t1	repair	status	OK
+insert into t1 values(2);
+select * from t1;
+a
+1
+2
+3
+SET SESSION debug="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
+* crashing mysqld intentionally
+set global maria_checkpoint_interval=1;
+ERROR HY000: Lost connection to MySQL server during query
+* recovery happens
+check table t1 extended;
+Table	Op	Msg_type	Msg_text
+mysqltest.t1	check	status	OK
+* testing that checksum after recovery is as expected
+Checksum-check
+failure
+use mysqltest;
+select * from t1;
+a
+1
+3
+drop table t1;
+* TEST of recovery when crash before bulk-insert-with-repair is committed
+create table t1 (a varchar(100), key(a)) engine=maria;
+create table t2 (a varchar(100)) engine=myisam;
+set rand_seed1=12, rand_seed2=254;
+insert into t2 values (rand());
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t1 values(30);
+flush table t1;
+* copied t1 for comparison
+lock tables t1 write, t2 read;
+delete from t1 limit 1;
+insert into t1 select * from t2;
+SET SESSION debug="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
+* crashing mysqld intentionally
+set global maria_checkpoint_interval=1;
+ERROR HY000: Lost connection to MySQL server during query
+* recovery happens
+check table t1 extended;
+Table	Op	Msg_type	Msg_text
+mysqltest.t1	check	status	OK
+* testing that checksum after recovery is as expected
+Checksum-check
+ok
+use mysqltest;
+show keys from t1;
+Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment	Index_Comment
+t1	1	a	1	a	A	1	NULL	NULL	YES	BTREE		
+drop table t1;
+* TEST of recovery when OPTIMIZE has replaced the index file and crash
+create table t_corrupted1 (a varchar(100), key(a)) engine=maria;
+insert into t_corrupted1 select (rand()) from t2;
+flush table t_corrupted1;
+* copied t_corrupted1 for comparison
+SET SESSION debug="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash_sort_index";
+* crashing mysqld intentionally
+optimize table t_corrupted1;
+ERROR HY000: Lost connection to MySQL server during query
+* recovery happens
+check table t_corrupted1 extended;
+Table	Op	Msg_type	Msg_text
+mysqltest.t_corrupted1	check	warning	Table is marked as crashed and last repair failed
+mysqltest.t_corrupted1	check	status	OK
+* testing that checksum after recovery is as expected
+Checksum-check
+ok
+use mysqltest;
+drop table t_corrupted1, t2;
+drop database mysqltest_for_comparison;
+drop database mysqltest;

=== modified file 'mysql-test/r/old-mode.result'
--- a/mysql-test/r/old-mode.result	2007-12-04 21:23:42 +0000
+++ b/mysql-test/r/old-mode.result	2008-06-28 12:45:15 +0000
@@ -5,8 +5,12 @@ insert t1 values (1, "aaa", "bbb"), (NUL
 insert t2 select * from t1;
 checksum table t1, t2;
 Table	Checksum
-test.t1	3442722830
+test.t1	2948697075
 test.t2	2948697075
+checksum table t1, t2 quick;
+Table	Checksum
+test.t1	NULL
+test.t2	NULL
 checksum table t1, t2 extended;
 Table	Checksum
 test.t1	2948697075

=== added file 'mysql-test/r/row-checksum-old.result'
--- a/mysql-test/r/row-checksum-old.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/row-checksum-old.result	2008-06-28 12:45:15 +0000
@@ -0,0 +1,85 @@
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	452555338
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	452555338
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=1;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	452555338
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	452555338
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=innodb checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	452555338
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	452555338
+drop table t1;
+create table t1 (a int null, v varchar(100)) engine=maria checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	452555338
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	452555338
+drop table t1;
+create table t1 (a int null, v varchar(100)) engine=maria checksum=1;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	452555338
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	452555338
+drop table t1;
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=1 row_format=fixed;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	4108368782
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	4108368782
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=innodb checksum=0 row_format=fixed;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	4108368782
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	4108368782
+drop table t1;

=== added file 'mysql-test/r/row-checksum.result'
--- a/mysql-test/r/row-checksum.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/row-checksum.result	2008-06-28 12:45:15 +0000
@@ -0,0 +1,85 @@
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	229851577
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	229851577
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=1;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	229851577
+checksum table t1 quick;
+Table	Checksum
+test.t1	229851577
+checksum table t1 extended;
+Table	Checksum
+test.t1	229851577
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=innodb checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	229851577
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	229851577
+drop table t1;
+create table t1 (a int null, v varchar(100)) engine=maria checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	229851577
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	229851577
+drop table t1;
+create table t1 (a int null, v varchar(100)) engine=maria checksum=1;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	229851577
+checksum table t1 quick;
+Table	Checksum
+test.t1	229851577
+checksum table t1 extended;
+Table	Checksum
+test.t1	229851577
+drop table t1;
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=1 row_format=fixed;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	3885665021
+checksum table t1 quick;
+Table	Checksum
+test.t1	3885665021
+checksum table t1 extended;
+Table	Checksum
+test.t1	3885665021
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=innodb checksum=0 row_format=fixed;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+Table	Checksum
+test.t1	3885665021
+checksum table t1 quick;
+Table	Checksum
+test.t1	NULL
+checksum table t1 extended;
+Table	Checksum
+test.t1	3885665021
+drop table t1;

=== modified file 'mysql-test/t/maria-recovery.test'
--- a/mysql-test/t/maria-recovery.test	2008-06-27 13:30:49 +0000
+++ b/mysql-test/t/maria-recovery.test	2008-06-30 09:59:59 +0000
@@ -195,129 +195,6 @@ show create table t1;
 insert into t1 values(null, "f");
 drop table t1;
 
-# Test of removing logs manually
---echo * TEST of removing logs manually
-let $mel_keep_control_file=1;
-# this will shut mysqld down cleanly (so, take a checkpoint) and
-# remove only logs; at restart Maria will create a new log with a high
-# number
--- source include/maria_empty_logs.inc
-let $mel_keep_control_file=0;
-# next test will help us verify that a next recovery is ok
-
---echo * TEST of UNDO_ROW_DELETE preserving rowid
-# we want recovery to use the tables as they were at time of crash
-let $mvr_restore_old_snapshot=0;
-# UNDO phase prevents physical comparison, normally,
-# so we'll only use checksums to compare.
-let $mms_compare_physically=0;
-let $mvr_crash_statement= set global maria_checkpoint_interval=1;
-create table t1(a int) engine=maria;
-insert into t1 values(1),(2);
--- source include/maria_make_snapshot_for_comparison.inc
-lock tables t1 write;
-insert into t1 values(3);
-delete from t1 where a in (1,2,3);
--- source include/maria_verify_recovery.inc
-drop table t1;
-
-# A basic checkpoint test
---echo * TEST of checkpoint
-# Don't take a full checkpoints, we want to test checkpoint vs dirty pages
-set global debug="+d,info,query,enter,exit,loop,maria_checkpoint_indirect";
-# restart checkpoint thread for it to notice the above
-set global maria_checkpoint_interval=10000;
-create table t1(a int, b varchar(10), index(a,b)) engine=maria;
-insert into t1 values(1,"a"),(2,"b"),(3,"c");
-delete from t1 where b="b";
-update t1 set b="d" where a=1;
--- source include/maria_make_snapshot_for_comparison.inc
-lock tables t1 write;
-insert into t1 values(4,"e"),(5,"f"),(6,"g");
-update t1 set b="h" where a=5;
-delete from t1 where b="g";
-show status like "Maria_pagecache_blocks_not_flushed";
-# force a checkpoint; there should be dirty pages and an open transaction
-set global maria_checkpoint_interval=10000;
-# do some more work
-update t1 set b="i" where a=5;
-let $mvr_restore_old_snapshot=0;
-let $mms_compare_physically=0;
-let $mvr_debug_option="+d,maria_crash";
-let $mvr_crash_statement= set global maria_checkpoint_interval=1;
-# Now we have a recovery, which should use the checkpoint record
-# and its dirty pages list.
--- source include/maria_verify_recovery.inc
-drop table t1;
-
---echo Test of REPAIR's implicit commit
-let $mms_tables=1;
-create table t1 (a varchar(100), key(a)) engine=maria;
-let $mvr_restore_old_snapshot=0;
-let $mms_compare_physically=0;
-let $mvr_crash_statement= set global maria_checkpoint_interval=1;
-
-let $mvr_debug_option="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
-insert into t1 values(3);
--- source include/maria_make_snapshot_for_comparison.inc
-lock tables t1 write;
-insert into t1 values (1);
-repair table t1;
-insert into t1 values(2);
-select * from t1;
-
-# checksum comparison failure is expected, SELECT output matters
--- source include/maria_verify_recovery.inc
-# 2 should be missing (rolled back) but 1 should be committed
-select * from t1;
-drop table t1;
-
---echo * TEST of recovery when crash before bulk-insert-with-repair is committed
-create table t1 (a varchar(100), key(a)) engine=maria;
-create table t2 (a varchar(100)) engine=myisam;
-let $mvr_restore_old_snapshot=0;
-let $mms_compare_physically=0;
-let $mvr_crash_statement= set global maria_checkpoint_interval=1;
-let $mvr_debug_option="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
-set rand_seed1=12, rand_seed2=254; # repeatable
-insert into t2 values (rand());
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t2 select (rand()) from t2;
-insert into t1 values(30);
--- source include/maria_make_snapshot_for_comparison.inc
-lock tables t1 write, t2 read;
-delete from t1 limit 1;
-# 127 rows in t2, >100, so this will use repair-at-end
-insert into t1 select * from t2;
--- source include/maria_verify_recovery.inc
-show keys from t1; # should be enabled
-drop table t1;
-
---echo * TEST of recovery when OPTIMIZE has replaced the index file and crash
-create table t_corrupted1 (a varchar(100), key(a)) engine=maria;
-# we use a special name because this test portion will generate
-# corruption warnings, which we tell mtr_report.pl to ignore by
-# putting the message in mtr_report.pl, but we don't want to it ignore
-# corruption messages of other tests, hence the special name
-# 't_corrupted' and not just 't'.
-let $mms_tname=t_corrupted;
-let $mvr_restore_old_snapshot=0;
-let $mms_compare_physically=0;
-let $mvr_crash_statement= optimize table t_corrupted1;
-let $mvr_debug_option="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash_sort_index";
-insert into t_corrupted1 select (rand()) from t2;
--- source include/maria_make_snapshot_for_comparison.inc
-# Recovery will not fix the table, but we expect to see it marked
-# "crashed on repair".
-# Because crash is mild, the table is actually not corrupted, so the
-# "check table extended" done below fixes the table.
--- source include/maria_verify_recovery.inc
-drop table t_corrupted1, t2;
-
 # clean up everything
 let $mms_purpose=feeding_recovery;
 eval drop database mysqltest_for_$mms_purpose;

=== added file 'mysql-test/t/maria-recovery2-master.opt'
--- a/mysql-test/t/maria-recovery2-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/maria-recovery2-master.opt	2008-06-30 09:59:59 +0000
@@ -0,0 +1 @@
+--skip-stack-trace --skip-core-file --loose-maria-log-dir-path=$MYSQLTEST_VARDIR/tmp

=== added file 'mysql-test/t/maria-recovery2.test'
--- a/mysql-test/t/maria-recovery2.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/maria-recovery2.test	2008-06-30 09:34:58 +0000
@@ -0,0 +1,159 @@
+--source include/not_embedded.inc
+# Don't test this under valgrind, memory leaks will occur as we crash
+--source include/not_valgrind.inc
+# Binary must be compiled with debug for crash to occur
+--source include/have_debug.inc
+--source include/have_maria.inc
+
+set global maria_log_file_size=4294967295;
+let $MARIA_LOG=../tmp;
+
+--disable_warnings
+drop database if exists mysqltest;
+--enable_warnings
+create database mysqltest;
+let $mms_tname=t;
+
+# Include scripts can perform SQL. For it to not influence the main test
+# they use a separate connection. This way if they use a DDL it would
+# not autocommit in the main test.
+connect (admin, 127.0.0.1, root,,mysqltest,,);
+--enable_reconnect
+
+connection default;
+use mysqltest;
+--enable_reconnect
+
+let $mms_tables=1;
+let $mvr_restore_old_snapshot=0;
+let $mms_compare_physically=0;
+let $mvr_debug_option="+d,maria_flush_whole_log,maria_crash";
+let $mvr_crash_statement= set global maria_checkpoint_interval=1;
+
+# Test of removing logs manually
+--echo * TEST of removing logs manually
+let $mel_keep_control_file=1;
+# this will shut mysqld down cleanly (so, take a checkpoint) and
+# remove only logs; at restart Maria will create a new log with a high
+# number
+-- source include/maria_empty_logs.inc
+let $mel_keep_control_file=0;
+# next test will help us verify that a next recovery is ok
+
+--echo * TEST of UNDO_ROW_DELETE preserving rowid
+# we want recovery to use the tables as they were at time of crash
+let $mvr_restore_old_snapshot=0;
+# UNDO phase prevents physical comparison, normally,
+# so we'll only use checksums to compare.
+let $mms_compare_physically=0;
+let $mvr_crash_statement= set global maria_checkpoint_interval=1;
+create table t1(a int) engine=maria;
+insert into t1 values(1),(2);
+-- source include/maria_make_snapshot_for_comparison.inc
+lock tables t1 write;
+insert into t1 values(3);
+delete from t1 where a in (1,2,3);
+-- source include/maria_verify_recovery.inc
+drop table t1;
+
+# A basic checkpoint test
+--echo * TEST of checkpoint
+# Don't take a full checkpoints, we want to test checkpoint vs dirty pages
+set global debug="+d,info,query,enter,exit,loop,maria_checkpoint_indirect";
+# restart checkpoint thread for it to notice the above
+set global maria_checkpoint_interval=10000;
+create table t1(a int, b varchar(10), index(a,b)) engine=maria;
+insert into t1 values(1,"a"),(2,"b"),(3,"c");
+delete from t1 where b="b";
+update t1 set b="d" where a=1;
+-- source include/maria_make_snapshot_for_comparison.inc
+lock tables t1 write;
+insert into t1 values(4,"e"),(5,"f"),(6,"g");
+update t1 set b="h" where a=5;
+delete from t1 where b="g";
+show status like "Maria_pagecache_blocks_not_flushed";
+# force a checkpoint; there should be dirty pages and an open transaction
+set global maria_checkpoint_interval=10000;
+# do some more work
+update t1 set b="i" where a=5;
+let $mvr_restore_old_snapshot=0;
+let $mms_compare_physically=0;
+let $mvr_debug_option="+d,maria_crash";
+let $mvr_crash_statement= set global maria_checkpoint_interval=1;
+# Now we have a recovery, which should use the checkpoint record
+# and its dirty pages list.
+-- source include/maria_verify_recovery.inc
+drop table t1;
+
+--echo Test of REPAIR's implicit commit
+let $mms_tables=1;
+create table t1 (a varchar(100), key(a)) engine=maria;
+let $mvr_restore_old_snapshot=0;
+let $mms_compare_physically=0;
+let $mvr_crash_statement= set global maria_checkpoint_interval=1;
+
+let $mvr_debug_option="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
+insert into t1 values(3);
+-- source include/maria_make_snapshot_for_comparison.inc
+lock tables t1 write;
+insert into t1 values (1);
+repair table t1;
+insert into t1 values(2);
+select * from t1;
+
+# checksum comparison failure is expected, SELECT output matters
+-- source include/maria_verify_recovery.inc
+# 2 should be missing (rolled back) but 1 should be committed
+select * from t1;
+drop table t1;
+
+--echo * TEST of recovery when crash before bulk-insert-with-repair is committed
+create table t1 (a varchar(100), key(a)) engine=maria;
+create table t2 (a varchar(100)) engine=myisam;
+let $mvr_restore_old_snapshot=0;
+let $mms_compare_physically=0;
+let $mvr_crash_statement= set global maria_checkpoint_interval=1;
+let $mvr_debug_option="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash";
+set rand_seed1=12, rand_seed2=254; # repeatable
+insert into t2 values (rand());
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t2 select (rand()) from t2;
+insert into t1 values(30);
+-- source include/maria_make_snapshot_for_comparison.inc
+lock tables t1 write, t2 read;
+delete from t1 limit 1;
+# 127 rows in t2, >100, so this will use repair-at-end
+insert into t1 select * from t2;
+-- source include/maria_verify_recovery.inc
+show keys from t1; # should be enabled
+drop table t1;
+
+--echo * TEST of recovery when OPTIMIZE has replaced the index file and crash
+create table t_corrupted1 (a varchar(100), key(a)) engine=maria;
+# we use a special name because this test portion will generate
+# corruption warnings, which we tell mtr_report.pl to ignore by
+# putting the message in mtr_report.pl, but we don't want to it ignore
+# corruption messages of other tests, hence the special name
+# 't_corrupted' and not just 't'.
+let $mms_tname=t_corrupted;
+let $mvr_restore_old_snapshot=0;
+let $mms_compare_physically=0;
+let $mvr_crash_statement= optimize table t_corrupted1;
+let $mvr_debug_option="+d,maria_flush_whole_log,maria_flush_whole_page_cache,maria_crash_sort_index";
+insert into t_corrupted1 select (rand()) from t2;
+-- source include/maria_make_snapshot_for_comparison.inc
+# Recovery will not fix the table, but we expect to see it marked
+# "crashed on repair".
+# Because crash is mild, the table is actually not corrupted, so the
+# "check table extended" done below fixes the table.
+-- source include/maria_verify_recovery.inc
+drop table t_corrupted1, t2;
+
+# clean up everything
+let $mms_purpose=comparison;
+eval drop database mysqltest_for_$mms_purpose;
+drop database mysqltest;

=== modified file 'mysql-test/t/old-mode.test'
--- a/mysql-test/t/old-mode.test	2007-12-04 21:23:42 +0000
+++ b/mysql-test/t/old-mode.test	2008-06-28 12:45:15 +0000
@@ -12,5 +12,6 @@ create table t2 (a int, b varchar(200), 
 insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
 insert t2 select * from t1;
 checksum table t1, t2;
+checksum table t1, t2 quick;
 checksum table t1, t2 extended;
 drop table t1,t2;

=== added file 'mysql-test/t/row-checksum-old-master.opt'
--- a/mysql-test/t/row-checksum-old-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/row-checksum-old-master.opt	2008-06-28 12:45:15 +0000
@@ -0,0 +1 @@
+--old

=== added file 'mysql-test/t/row-checksum-old.test'
--- a/mysql-test/t/row-checksum-old.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/row-checksum-old.test	2008-06-28 12:45:15 +0000
@@ -0,0 +1,4 @@
+#
+# Run row-checksum.test with old mode
+#
+--source t/row-checksum.test

=== added file 'mysql-test/t/row-checksum.test'
--- a/mysql-test/t/row-checksum.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/row-checksum.test	2008-06-28 12:45:15 +0000
@@ -0,0 +1,62 @@
+#
+# Test checksum
+#
+
+-- source include/have_innodb.inc
+-- source include/have_maria.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+checksum table t1 quick;
+checksum table t1 extended;
+drop table if exists t1;
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=1;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+checksum table t1 quick;
+checksum table t1 extended;
+drop table if exists t1;
+
+create table t1 (a int null, v varchar(100)) engine=innodb checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+checksum table t1 quick;
+checksum table t1 extended;
+drop table t1;
+
+create table t1 (a int null, v varchar(100)) engine=maria checksum=0;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+checksum table t1 quick;
+checksum table t1 extended;
+drop table t1;
+create table t1 (a int null, v varchar(100)) engine=maria checksum=1;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+checksum table t1 quick;
+checksum table t1 extended;
+drop table t1;
+
+
+#
+# These checksums will be different prefixes fixed sizes rows with one extra
+# flag byte
+#
+create table t1 (a int null, v varchar(100)) engine=myisam checksum=1 row_format=fixed;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+checksum table t1 quick;
+checksum table t1 extended;
+drop table if exists t1;
+
+create table t1 (a int null, v varchar(100)) engine=innodb checksum=0 row_format=fixed;
+insert into t1 values(null, null), (1, "hello");
+checksum table t1;
+checksum table t1 quick;
+checksum table t1 extended;
+drop table t1;

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2008-06-28 11:00:59 +0000
+++ b/sql/ha_partition.cc	2008-06-30 09:59:59 +0000
@@ -4746,7 +4746,7 @@ void ha_partition::get_dynamic_partition
   stat_info->update_time=          file->stats.update_time;
   stat_info->check_time=           file->stats.check_time;
   stat_info->check_sum= 0;
-  if (file->ha_table_flags() & HA_HAS_CHECKSUM)
+  if (file->ha_table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_NEW_CHECKSUM))
     stat_info->check_sum= file->checksum();
   return;
 }

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2008-06-28 11:00:59 +0000
+++ b/sql/handler.cc	2008-06-30 09:59:59 +0000
@@ -3457,7 +3457,7 @@ void handler::get_dynamic_partition_info
   stat_info->update_time=          stats.update_time;
   stat_info->check_time=           stats.check_time;
   stat_info->check_sum=            0;
-  if (table_flags() & (ulong) HA_HAS_CHECKSUM)
+  if (table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_OLD_CHECKSUM))
     stat_info->check_sum= checksum();
   return;
 }

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2008-06-17 20:04:19 +0000
+++ b/sql/handler.h	2008-06-30 09:59:59 +0000
@@ -163,7 +163,8 @@ typedef Bitmap<HA_MAX_ALTER_FLAGS> HA_AL
 #define HA_CAN_FULLTEXT        (1 << 21)
 #define HA_CAN_SQL_HANDLER     (1 << 22)
 #define HA_NO_AUTO_INCREMENT   (1 << 23)
-#define HA_HAS_CHECKSUM        (1 << 24)
+/* Has automatic checksums and uses the old checksum format */
+#define HA_HAS_OLD_CHECKSUM    (1 << 24)
 /* Table data are stored in separate files (for lower_case_table_names) */
 #define HA_FILE_BASED	       (1 << 26)
 #define HA_NO_VARCHAR	       (1 << 27)
@@ -184,6 +185,8 @@ typedef Bitmap<HA_MAX_ALTER_FLAGS> HA_AL
 #define HA_BINLOG_STMT_CAPABLE (LL(1) << 36)
 
 #define HA_ONLINE_ALTER        (LL(1) << 37)
+/* Has automatic checksums and uses the new checksum format */
+#define HA_HAS_NEW_CHECKSUM    (LL(1) << 38)
 
 /*
   Set of all binlog flags. Currently only contain the capabilities

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2008-06-28 11:00:59 +0000
+++ b/sql/sql_show.cc	2008-06-30 09:59:59 +0000
@@ -3714,7 +3714,7 @@ static int get_schema_tables_record(THD 
         table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
         table->field[16]->set_notnull();
       }
-      if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
+      if (file->ha_table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_NEW_CHECKSUM))
       {
         table->field[18]->store((longlong) file->checksum(), TRUE);
         table->field[18]->set_notnull();
@@ -5061,7 +5061,7 @@ static void store_schema_partitions_reco
     table->field[20]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
     table->field[20]->set_notnull();
   }
-  if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
+  if (file->ha_table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_NEW_CHECKSUM))
   {
     table->field[21]->store((longlong) stat_info.check_sum, TRUE);
     table->field[21]->set_notnull();

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2008-06-28 11:00:59 +0000
+++ b/sql/sql_table.cc	2008-06-30 09:59:59 +0000
@@ -7483,11 +7483,14 @@ bool mysql_checksum_table(THD *thd, TABL
     }
     else
     {
-      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
-	  !(check_opt->flags & T_EXTEND))
+      /* Call ->checksum() if the table checksum matches 'old_mode' settings */
+      if (!(check_opt->flags & T_EXTEND) &&
+          (((t->file->ha_table_flags() & HA_HAS_OLD_CHECKSUM) &&
+            thd->variables.old_mode) ||
+           ((t->file->ha_table_flags() & HA_HAS_NEW_CHECKSUM) &&
+            !thd->variables.old_mode)))
 	protocol->store((ulonglong)t->file->checksum());
-      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
-	       (check_opt->flags & T_QUICK))
+      else if (check_opt->flags & T_QUICK)
 	protocol->store_null();
       else
       {

=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc	2008-06-28 11:00:59 +0000
+++ b/storage/maria/ha_maria.cc	2008-06-30 09:59:59 +0000
@@ -923,7 +923,7 @@ int ha_maria::open(const char *name, int
     int_table_flags|= HA_CAN_INSERT_DELAYED;
   }
   if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
-    int_table_flags |= HA_HAS_CHECKSUM;
+    int_table_flags |= HA_HAS_NEW_CHECKSUM;
 
   for (i= 0; i < table->s->keys; i++)
   {
@@ -1112,15 +1112,20 @@ int ha_maria::repair(THD * thd, HA_CHECK
                    (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
   param.sort_buffer_length= THDVAR(thd, sort_buffer_size);
   start_records= file->state->records;
-  while ((error= repair(thd, param, 0)) && param.retry_repair)
+  while ((error= repair(thd, &param, 0)) && param.retry_repair)
   {
     param.retry_repair= 0;
     if (test_all_bits(param.testflag,
                       (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
     {
-      param.testflag &= ~T_RETRY_WITHOUT_QUICK;
-      sql_print_information("Retrying repair of: '%s' without quick",
-                            table->s->path.str);
+      param.testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK);
+      /* Ensure we don't loose any rows when retrying without quick */
+      param.testflag|= T_SAFE_REPAIR;
+      if (thd->vio_ok())
+        _ma_check_print_info(&param, "Retrying repair without quick");
+      else
+        sql_print_information("Retrying repair of: '%s' without quick",
+                              table->s->path.str);
       continue;
     }
     param.testflag &= ~T_QUICK;
@@ -1166,9 +1171,9 @@ int ha_maria::zerofill(THD * thd, HA_CHE
 int ha_maria::optimize(THD * thd, HA_CHECK_OPT *check_opt)
 {
   int error;
+  HA_CHECK param;
   if (!file)
     return HA_ADMIN_INTERNAL_ERROR;
-  HA_CHECK param;
 
   maria_chk_init(&param);
   param.thd= thd;
@@ -1176,21 +1181,21 @@ int ha_maria::optimize(THD * thd, HA_CHE
   param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
                    T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
   param.sort_buffer_length= THDVAR(thd, sort_buffer_size);
-  if ((error= repair(thd, param, 1)) && param.retry_repair)
+  if ((error= repair(thd, &param, 1)) && param.retry_repair)
   {
     sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
                       my_errno, param.db_name, param.table_name);
     param.testflag &= ~T_REP_BY_SORT;
-    error= repair(thd, param, 1);
+    error= repair(thd, &param, 1);
   }
   return error;
 }
 
 
-int ha_maria::repair(THD *thd, HA_CHECK &param, bool do_optimize)
+int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize)
 {
   int error= 0;
-  ulonglong local_testflag= param.testflag;
+  ulonglong local_testflag= param->testflag;
   bool optimize_done= !do_optimize, statistics_done= 0;
   const char *old_proc_info= thd->proc_info;
   char fixed_name[FN_REFLEN];
@@ -1222,20 +1227,20 @@ int ha_maria::repair(THD *thd, HA_CHECK 
   if (share->base.born_transactional && !share->now_transactional)
     _ma_copy_nontrans_state_information(file);
 
-  param.db_name= table->s->db.str;
-  param.table_name= table->alias;
-  param.tmpfile_createflag= O_RDWR | O_TRUNC;
-  param.using_global_keycache= 1;
-  param.thd= thd;
-  param.tmpdir= &mysql_tmpdir_list;
-  param.out_flag= 0;
+  param->db_name= table->s->db.str;
+  param->table_name= table->alias;
+  param->tmpfile_createflag= O_RDWR | O_TRUNC;
+  param->using_global_keycache= 1;
+  param->thd= thd;
+  param->tmpdir= &mysql_tmpdir_list;
+  param->out_flag= 0;
   strmov(fixed_name, share->open_file_name);
 
   // Don't lock tables if we have used LOCK TABLE
   if (!thd->locked_tables_mode &&
       maria_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
   {
-    _ma_check_print_error(&param, ER(ER_CANT_LOCK), my_errno);
+    _ma_check_print_error(param, ER(ER_CANT_LOCK), my_errno);
     DBUG_RETURN(HA_ADMIN_FAILED);
   }
 
@@ -1243,19 +1248,19 @@ int ha_maria::repair(THD *thd, HA_CHECK 
       ((share->data_file_type == BLOCK_RECORD) ?
        (share->state.changed & STATE_NOT_OPTIMIZED_ROWS) :
        (file->state->del || share->state.split != file->state->records)) &&
-      (!(param.testflag & T_QUICK) ||
+      (!(param->testflag & T_QUICK) ||
        (share->state.changed & (STATE_NOT_OPTIMIZED_KEYS |
                                 STATE_NOT_OPTIMIZED_ROWS))))
   {
     ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
                         maria_get_mask_all_keys_active(share->base.keys) :
                         share->state.key_map);
-    ulonglong save_testflag= param.testflag;
+    ulonglong save_testflag= param->testflag;
     if (maria_test_if_sort_rep(file, file->state->records, key_map, 0) &&
         (local_testflag & T_REP_BY_SORT))
     {
       local_testflag |= T_STATISTICS;
-      param.testflag |= T_STATISTICS;           // We get this for free
+      param->testflag |= T_STATISTICS;           // We get this for free
       statistics_done= 1;
       /* TODO: Remove BLOCK_RECORD test when parallel works with blocks */
       if (THDVAR(thd,repair_threads) > 1 &&
@@ -1265,28 +1270,28 @@ int ha_maria::repair(THD *thd, HA_CHECK 
         /* TODO: respect maria_repair_threads variable */
         my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
         thd_proc_info(thd, buf);
-        param.testflag|= T_REP_PARALLEL;
-        error= maria_repair_parallel(&param, file, fixed_name,
-                                     test(param.testflag & T_QUICK));
+        param->testflag|= T_REP_PARALLEL;
+        error= maria_repair_parallel(param, file, fixed_name,
+                                     test(param->testflag & T_QUICK));
         /* to reset proc_info, as it was pointing to local buffer */
         thd_proc_info(thd, "Repair done");
       }
       else
       {
         thd_proc_info(thd, "Repair by sorting");
-        param.testflag|= T_REP_BY_SORT;
-        error= maria_repair_by_sort(&param, file, fixed_name,
-                                    test(param.testflag & T_QUICK));
+        param->testflag|= T_REP_BY_SORT;
+        error= maria_repair_by_sort(param, file, fixed_name,
+                                    test(param->testflag & T_QUICK));
       }
     }
     else
     {
       thd_proc_info(thd, "Repair with keycache");
-      param.testflag &= ~(T_REP_BY_SORT | T_REP_PARALLEL);
-      error= maria_repair(&param, file, fixed_name,
-                          test(param.testflag & T_QUICK));
+      param->testflag &= ~(T_REP_BY_SORT | T_REP_PARALLEL);
+      error= maria_repair(param, file, fixed_name,
+                          test(param->testflag & T_QUICK));
     }
-    param.testflag= save_testflag;
+    param->testflag= save_testflag | (param->testflag & T_RETRY_WITHOUT_QUICK);
     optimize_done= 1;
   }
   if (!error)
@@ -1296,7 +1301,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
     {
       optimize_done= 1;
       thd_proc_info(thd, "Sorting index");
-      error= maria_sort_index(&param, file, fixed_name);
+      error= maria_sort_index(param, file, fixed_name);
     }
     if (!statistics_done && (local_testflag & T_STATISTICS))
     {
@@ -1304,7 +1309,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
       {
         optimize_done= 1;
         thd_proc_info(thd, "Analyzing");
-        error= maria_chk_key(&param, file);
+        error= maria_chk_key(param, file);
       }
       else
         local_testflag &= ~T_STATISTICS;        // Don't update statistics
@@ -1326,18 +1331,18 @@ int ha_maria::repair(THD *thd, HA_CHECK 
     if (file->state != &share->state.state)
       *file->state= share->state.state;
     if (share->base.auto_key)
-      _ma_update_auto_increment_key(&param, file, 1);
+      _ma_update_auto_increment_key(param, file, 1);
     if (optimize_done)
-      error= maria_update_state_info(&param, file,
+      error= maria_update_state_info(param, file,
                                      UPDATE_TIME | UPDATE_OPEN_COUNT |
                                      (local_testflag &
                                       T_STATISTICS ? UPDATE_STAT : 0));
     info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
          HA_STATUS_CONST);
-    if (rows != file->state->records && !(param.testflag & T_VERY_SILENT))
+    if (rows != file->state->records && !(param->testflag & T_VERY_SILENT))
     {
       char llbuff[22], llbuff2[22];
-      _ma_check_print_warning(&param, "Number of rows changed from %s to %s",
+      _ma_check_print_warning(param, "Number of rows changed from %s to %s",
                               llstr(rows, llbuff),
                               llstr(file->state->records, llbuff2));
       /* Abort if warning was converted to error */
@@ -1349,7 +1354,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
   {
     maria_mark_crashed_on_repair(file);
     file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
-    maria_update_state_info(&param, file, 0);
+    maria_update_state_info(param, file, 0);
   }
   pthread_mutex_unlock(&share->intern_lock);
   thd_proc_info(thd, old_proc_info);
@@ -1357,7 +1362,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
     maria_lock_database(file, F_UNLCK);
   error= error ? HA_ADMIN_FAILED :
     (optimize_done ?
-     (write_log_record_for_repair(&param, file) ? HA_ADMIN_FAILED :
+     (write_log_record_for_repair(param, file) ? HA_ADMIN_FAILED :
       HA_ADMIN_OK) : HA_ADMIN_ALREADY_DONE);
   DBUG_RETURN(error);
 }
@@ -1587,15 +1592,16 @@ int ha_maria::enable_indexes(uint mode)
     param.sort_buffer_length= THDVAR(thd,sort_buffer_size);
     param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method);
     param.tmpdir= &mysql_tmpdir_list;
-    if ((error= (repair(thd, param, 0) != HA_ADMIN_OK)) && param.retry_repair)
+    if ((error= (repair(thd, &param, 0) != HA_ADMIN_OK)) && param.retry_repair)
     {
-      sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
+      sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, "
+                        "retrying",
                         my_errno, param.db_name, param.table_name);
       /* This should never fail normally */
       DBUG_ASSERT(0);
       /* Repairing by sort failed. Now try standard repair method. */
-      param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
-      error= (repair(thd, param, 0) != HA_ADMIN_OK);
+      param.testflag &= ~T_REP_BY_SORT;
+      error= (repair(thd, &param, 0) != HA_ADMIN_OK);
       /*
         If the standard repair succeeded, clear all error messages which
         might have been set by the first repair. They can still be seen
@@ -1761,8 +1767,7 @@ end:
 
 bool ha_maria::check_and_repair(THD *thd)
 {
-  int error;
-  int marked_crashed;
+  int error, crashed;
   char *old_query;
   uint old_query_length;
   HA_CHECK_OPT check_opt;
@@ -1791,7 +1796,6 @@ bool ha_maria::check_and_repair(THD *thd
   // Don't use quick if deleted rows
   if (!file->state->del && (maria_recover_options & HA_RECOVER_QUICK))
     check_opt.flags |= T_QUICK;
-  sql_print_warning("Checking table:   '%s'", table->s->path.str);
 
   old_query= thd->query;
   old_query_length= thd->query_length;
@@ -1800,12 +1804,17 @@ bool ha_maria::check_and_repair(THD *thd
   thd->query_length= table->s->table_name.length;
   pthread_mutex_unlock(&LOCK_thread_count);
 
-  if ((marked_crashed= maria_is_crashed(file)) || check(thd, &check_opt))
+  if (!(crashed= maria_is_crashed(file)))
+  {
+    sql_print_warning("Checking table:   '%s'", table->s->path.str);
+    crashed= check(thd, &check_opt);
+  }
+
+  if (crashed)
   {
     sql_print_warning("Recovering table: '%s'", table->s->path.str);
     check_opt.flags=
       ((maria_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
-       (marked_crashed ? 0 : T_QUICK) |
        (maria_recover_options & HA_RECOVER_FORCE ? 0 : T_SAFE_REPAIR) |
        T_AUTO_REPAIR);
     if (repair(thd, &check_opt))
@@ -2350,6 +2359,11 @@ THR_LOCK_DATA **ha_maria::store_lock(THD
          thd->lex->sql_command != SQLCOM_LOCK_TABLES) &&
         mysql_bin_log.is_open())
       lock_type= TL_READ_NO_INSERT;
+    else if (lock_type == TL_WRITE_CONCURRENT_INSERT &&
+             (thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
+              thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
+              thd->lex->sql_command == SQLCOM_LOAD))
+      lock_type= TL_WRITE;
     file->lock.type= lock_type;
   }
   *to++= &file->lock;

=== modified file 'storage/maria/ha_maria.h'
--- a/storage/maria/ha_maria.h	2008-06-05 16:11:22 +0000
+++ b/storage/maria/ha_maria.h	2008-06-30 09:59:59 +0000
@@ -45,7 +45,7 @@ class ha_maria :public handler
     UNDO_BULK_INSERT with/without repair. 
   */
   uint8 bulk_insert_single_undo;
-  int repair(THD * thd, HA_CHECK &param, bool optimize);
+  int repair(THD * thd, HA_CHECK *param, bool optimize);
   int zerofill(THD * thd, HA_CHECK_OPT *check_opt);
 
 public:

=== modified file 'storage/maria/ma_blockrec.c'
--- a/storage/maria/ma_blockrec.c	2008-06-26 05:18:28 +0000
+++ b/storage/maria/ma_blockrec.c	2008-06-30 09:25:14 +0000
@@ -1345,21 +1345,22 @@ static void calc_record_size(MARIA_HA *i
 }
 
 
-/*
+/**
   Compact page by removing all space between rows
 
-  IMPLEMENTATION
-    Move up all rows to start of page.
-    Move blocks that are directly after each other with one memmove.
+  Moves up all rows to start of page. Moves blocks that are directly after
+  each other with one memmove.
 
-  SYNOPSIS
-    _ma_compact_block_page()
-    buff                Page to compact
-    block_size          Size of page
-    rownr               Put empty data after this row
-    extend_block	If 1, extend the block at 'rownr' to cover the
+  @note if rownr is the last row in the page, and extend_block is false,
+  caller has to make sure to update bitmap page afterwards to reflect freed
+  space.
+
+  @param  buff          Page to compact
+  @param  block_size    Size of page
+  @param  rownr         Put empty data after this row
+  @param  extend_block	If 1, extend the block at 'rownr' to cover the
                         whole block.
-    min_read_from       If <> 0, remove all trid's that are less than this
+  @param  min_read_from If <> 0, remove all trid's that are less than this
 */
 
 void _ma_compact_block_page(uchar *buff, uint block_size, uint rownr,

=== modified file 'storage/maria/ma_check.c'
--- a/storage/maria/ma_check.c	2008-06-26 18:29:30 +0000
+++ b/storage/maria/ma_check.c	2008-06-30 09:59:59 +0000
@@ -99,6 +99,7 @@ static my_bool _ma_flush_table_files_bef
                                                  MARIA_HA *info);
 static TrID max_trid_in_system(void);
 static void _ma_check_print_not_visible_error(HA_CHECK *param, TrID used_trid);
+void retry_if_quick(MARIA_SORT_PARAM *param, int error);
 
 
 /* Initialize check param with default values */
@@ -2233,6 +2234,10 @@ static int initialize_variables_for_repa
 {
   MARIA_SHARE *share= info->s;
 
+  /* Repair code relies on share->state.state so we have to update it here */
+  if (share->lock.update_status)
+    (*share->lock.update_status)(info);
+
   bzero((char*) sort_info,  sizeof(*sort_info));
   bzero((char*) sort_param, sizeof(*sort_param));
 
@@ -3303,11 +3308,16 @@ static my_bool maria_zerofill_data(HA_CH
         bzero(buff, LSN_SIZE);
       if (max_entry != 0)
       {
+        my_bool is_head_page= (page_type == HEAD_PAGE);
         dir= dir_entry_pos(buff, block_size, max_entry - 1);
         _ma_compact_block_page(buff, block_size, max_entry -1, 0,
-                               page_type == HEAD_PAGE ? ~(TrID) 0 : 0,
-                               page_type == HEAD_PAGE ?
+                               is_head_page ? ~(TrID) 0 : 0,
+                               is_head_page ?
                                share->base.min_block_length : 0);
+        /* compactation may have increased free space */
+        if (_ma_bitmap_set(info, page, is_head_page,
+                           uint2korr(buff + EMPTY_SPACE_OFFSET)))
+          goto err;
 
         /* Zerofill the not used part */
         offset= uint2korr(dir) + uint2korr(dir+2);
@@ -3329,10 +3339,9 @@ static my_bool maria_zerofill_data(HA_CH
                              PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
                              LSN_IMPOSSIBLE, 1);
   }
-  if (flush_pagecache_blocks(share->pagecache, &info->dfile,
-                             FLUSH_FORCE_WRITE))
-    DBUG_RETURN(1);
-  DBUG_RETURN(0);
+  DBUG_RETURN(_ma_bitmap_flush(share) ||
+              flush_pagecache_blocks(share->pagecache, &info->dfile,
+                                     FLUSH_FORCE_WRITE));
 
 err:
   pagecache_unlock_by_link(share->pagecache, page_link.link,
@@ -4632,9 +4641,12 @@ static int sort_get_next_record(MARIA_SO
       }
       /* Retry only if wrong record, not if disk error */
       if (flag != HA_ERR_WRONG_IN_RECORD)
+      {
+        retry_if_quick(sort_param, flag);
         DBUG_RETURN(flag);
+      }
     }
-    break;
+    break;                                      /* Impossible */
   }
   case STATIC_RECORD:
     for (;;)
@@ -4644,8 +4656,7 @@ static int sort_get_next_record(MARIA_SO
       {
 	if (sort_param->read_cache.error)
 	  param->out_flag |= O_DATA_LOST;
-        param->retry_repair=1;
-        param->testflag|=T_RETRY_WITHOUT_QUICK;
+        retry_if_quick(sort_param, my_errno);
 	DBUG_RETURN(-1);
       }
       sort_param->start_recpos=sort_param->pos;
@@ -6634,3 +6645,22 @@ static void _ma_check_print_not_visible_
     }
   }
 }
+
+
+/**
+  Mark that we can retry normal repair if we used quick repair
+
+  We shouldn't do this in case of disk error as in this case we are likely
+  to loose much more than expected.
+*/
+
+void retry_if_quick(MARIA_SORT_PARAM *sort_param, int error)
+{
+  HA_CHECK *param=sort_param->sort_info->param;
+
+  if (!sort_param->fix_datafile && error >= HA_ERR_FIRST)
+  {
+    param->retry_repair=1;
+    param->testflag|=T_RETRY_WITHOUT_QUICK;
+  }
+}

=== modified file 'storage/maria/ma_open.c'
--- a/storage/maria/ma_open.c	2008-06-26 17:48:42 +0000
+++ b/storage/maria/ma_open.c	2008-06-30 09:59:59 +0000
@@ -601,6 +601,15 @@ MARIA_HA *maria_open(const char *name, i
 	pos->null_bit=0;
 	pos->flag=0;					/* For purify */
 	pos++;
+
+        if ((share->keyinfo[i].flag & HA_NOSAME) && i != 0)
+        {
+          /*
+            We can't yet have versioning if there is more than one unique
+            key
+          */
+          versioning= 0;
+        }
       }
       for (i=0 ; i < uniques ; i++)
       {
@@ -1345,8 +1354,10 @@ static uchar *_ma_state_info_read(uchar 
    @param  state           state which will be filled
 */
 
-uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state)
+uint _ma_state_info_read_dsk(File file __attribute__((unused)),
+                             MARIA_STATE_INFO *state __attribute__((unused)))
 {
+#ifdef EXTERNAL_LOCKING
   uchar	buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE];
 
   /* trick to detect transactional tables */
@@ -1357,6 +1368,7 @@ uint _ma_state_info_read_dsk(File file, 
       return 1;
     _ma_state_info_read(buff, state);
   }
+#endif
   return 0;
 }
 

=== modified file 'storage/maria/ma_test1.c'
--- a/storage/maria/ma_test1.c	2008-06-26 17:48:42 +0000
+++ b/storage/maria/ma_test1.c	2008-06-30 09:59:59 +0000
@@ -130,7 +130,8 @@ static int run_test(const char *filename
     recinfo[2].type=FIELD_CHECK;
     recinfo[2].length=MARIA_UNIQUE_HASH_LENGTH;
   }
-  rec_length= recinfo[0].length+recinfo[1].length+recinfo[2].length;
+  rec_length= recinfo[0].length + recinfo[1].length + recinfo[2].length +
+    create_info.null_bytes;
 
   if (key_type == HA_KEYTYPE_VARTEXT1 &&
       key_length > 255)

=== modified file 'storage/maria/unittest/ma_test_loghandler_multithread-t.c'
--- a/storage/maria/unittest/ma_test_loghandler_multithread-t.c	2008-06-16 16:31:25 +0000
+++ b/storage/maria/unittest/ma_test_loghandler_multithread-t.c	2008-06-30 09:59:59 +0000
@@ -269,6 +269,11 @@ int main(int argc __attribute__((unused)
   int *param, error;
   int rc;
 
+  /* Disabled until Sanja tests */
+  plan(1);
+  ok(1, "disabled");
+  exit(0);
+
   plan(WRITERS + FLUSHERS +
        ITERATIONS * WRITERS * 3 + FLUSH_ITERATIONS * FLUSHERS );
 

=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc	2008-06-28 11:00:59 +0000
+++ b/storage/myisam/ha_myisam.cc	2008-06-30 09:59:59 +0000
@@ -645,9 +645,22 @@ int ha_myisam::open(const char *name, in
   if (!table->s->db_record_offset)
     int_table_flags|=HA_REC_NOT_IN_SEQ;
   if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
-    int_table_flags|=HA_HAS_CHECKSUM;
+  {
+    /*
+      Set which type of automatic checksum we have
+      The old checksum and new checksum are identical if there is no
+      null fields.
+      Files with new checksum has the HA_OPTION_NULL_FIELDS bit set.
+    */      
+    if ((file->s->options & HA_OPTION_NULL_FIELDS) ||
+        !file->s->has_null_fields)
+      int_table_flags|= HA_HAS_NEW_CHECKSUM;
+    if (!(file->s->options & HA_OPTION_NULL_FIELDS))
+      int_table_flags|= HA_HAS_OLD_CHECKSUM;
+  }
   
   keys_with_parts.clear_all();
+
   for (i= 0; i < table->s->keys; i++)
   {
     plugin_ref parser= table->key_info[i].parser;
@@ -856,7 +869,9 @@ int ha_myisam::repair(THD* thd, HA_CHECK
     if (test_all_bits(param.testflag,
 		      (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
     {
-      param.testflag&= ~T_RETRY_WITHOUT_QUICK;
+      param.testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK);
+      /* Ensure we don't loose any rows when retrying without quick */
+      param.testflag|= T_SAFE_REPAIR;
       sql_print_information("Retrying repair of: '%s' without quick",
                             table->s->path.str);
       continue;
@@ -990,7 +1005,7 @@ int ha_myisam::repair(THD *thd, HA_CHECK
       error=  mi_repair(&param, file, fixed_name,
 			test(param.testflag & T_QUICK));
     }
-    param.testflag=testflag;
+    param.testflag= testflag | (param.testflag & T_RETRY_WITHOUT_QUICK);
     optimize_done=1;
   }
   if (!error)
@@ -1969,6 +1984,27 @@ bool ha_myisam::check_if_incompatible_da
   return COMPATIBLE_DATA_YES;
 }
 
+
+/**
+  Check if a table is incompatible with the current version.
+
+  The cases are:
+  - Table has checksum, varchars and are not of dynamic record type
+*/
+
+int ha_myisam::check_for_upgrade(HA_CHECK_OPT *check_opt)
+{
+  if (!(file->s->options & HA_OPTION_NULL_FIELDS) &&
+      !(file->s->options & HA_OPTION_PACK_RECORD) &&
+      file->s->has_varchar_fields)
+  {
+    /* We need alter there to get the HA_OPTION_NULL_FIELDS flag to be set */
+    return HA_ADMIN_NEEDS_ALTER;
+  }
+  return HA_ADMIN_OK;
+}
+
+
 extern int mi_panic(enum ha_panic_function flag);
 int myisam_panic(handlerton *hton, ha_panic_function flag)
 {

=== modified file 'storage/myisam/ha_myisam.h'
--- a/storage/myisam/ha_myisam.h	2008-06-05 16:11:22 +0000
+++ b/storage/myisam/ha_myisam.h	2008-06-30 09:59:59 +0000
@@ -126,6 +126,7 @@ class ha_myisam: public handler
                                   ulonglong *nb_reserved_values);
   int rename_table(const char * from, const char * to);
   int delete_table(const char *name);
+  int check_for_upgrade(HA_CHECK_OPT *check_opt);
   int check(THD* thd, HA_CHECK_OPT* check_opt);
   int analyze(THD* thd,HA_CHECK_OPT* check_opt);
   int repair(THD* thd, HA_CHECK_OPT* check_opt);

=== modified file 'storage/myisam/mi_open.c'
--- a/storage/myisam/mi_open.c	2008-05-29 15:44:11 +0000
+++ b/storage/myisam/mi_open.c	2008-06-30 09:59:59 +0000
@@ -19,6 +19,7 @@
 #include "sp_defs.h"
 #include "rt_index.h"
 #include <m_ctype.h>
+#include <mysql_version.h>
 
 #if defined(MSDOS) || defined(__WIN__)
 #ifdef __WIN__
@@ -453,13 +454,20 @@ MI_INFO *mi_open(const char *name, int m
       share->rec[i].pack_type=0;
       share->rec[i].huff_tree=0;
       share->rec[i].offset=offset;
-      if (share->rec[i].type == (int) FIELD_BLOB)
+      if (share->rec[i].type == FIELD_BLOB)
       {
 	share->blobs[j].pack_length=
 	  share->rec[i].length - portable_sizeof_char_ptr;
 	share->blobs[j].offset=offset;
 	j++;
       }
+#if MYSQL_VERSION_ID <= 60100
+      /* This is to detect old checksum option */
+      if (share->rec[i].null_bit)
+        share->has_null_fields= 1;
+      if (share->rec[i].type == FIELD_VARCHAR)
+        share->has_varchar_fields= 1;
+#endif
       offset+=share->rec[i].length;
     }
     share->rec[i].type=(int) FIELD_LAST;	/* End marker */

=== modified file 'storage/myisam/myisamdef.h'
--- a/storage/myisam/myisamdef.h	2008-06-05 16:11:22 +0000
+++ b/storage/myisam/myisamdef.h	2008-06-30 09:59:59 +0000
@@ -211,6 +211,9 @@ typedef struct st_mi_isam_share
   enum data_file_type data_file_type;
   /* Below flag is needed to make log tables work with concurrent insert */
   my_bool is_log_table;
+  /* This is 1 if they table checksum is of old type */
+  my_bool has_null_fields;
+  my_bool has_varchar_fields;
 
   my_bool changed,                      /* If changed since lock */
     global_changed,                     /* If changed since open */

Thread
bzr commit into mysql-6.0 branch (guilhem:2670) Guilhem Bichot30 Jun