From cd78a8be66a18300e8bf48813adc2548ad7552c7 Mon Sep 17 00:00:00 2001
From: "monty@hundin.mysql.fi" <>
Date: Tue, 18 Sep 2001 04:58:15 +0300
Subject: [PATCH] Fix for LOAD DATA FROM MASTER when using tables with checksum
 Fixed some wrong test cases

---
 Docs/manual.texi                |  3 +++
 extra/perror.c                  | 17 ++++++++++++--
 include/myisam.h                |  3 ++-
 myisam/mi_check.c               | 33 ++++++++++++++++++++++++++--
 mysql-test/mysql-test-run.sh    |  4 ++--
 mysql-test/r/join.result        | 13 +++++++++++
 mysql-test/r/rpl000006.result   |  2 ++
 mysql-test/t/join.test          |  4 +++-
 mysql-test/t/rpl000001.test     |  2 +-
 mysql-test/t/rpl000006.test     | 39 ++++++++++++++++++++++-----------
 mysql-test/t/rpl000017-slave.sh |  2 +-
 mysql-test/t/rpl000017.test     |  3 +--
 sql/ha_myisam.cc                | 12 +++++-----
 sql/handler.cc                  |  3 +++
 sql/slave.cc                    |  2 +-
 15 files changed, 111 insertions(+), 31 deletions(-)

diff --git a/Docs/manual.texi b/Docs/manual.texi
index c43f3dbc1b5..9cf7f74feff 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -46853,6 +46853,9 @@ not yet 100% confident in this code.
 @appendixsubsec Changes in release 3.23.43
 @itemize @bullet
 @item
+Fixed bug in @code{LOAD DATA FROM MASTER} when using table with
+@code{CHECKSUM=1}.
+@item
 Added unique error message when one gets a DEADLOCK during a transaction with
 BDB tables.
 @item
diff --git a/extra/perror.c b/extra/perror.c
index 038665438d9..6cb86eedf27 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -17,7 +17,7 @@
 
 /* Return error-text for system error messages and nisam messages */
 
-#define PERROR_VERSION "2.6"
+#define PERROR_VERSION "2.7"
 
 #include <global.h>
 #include <my_sys.h>
@@ -71,6 +71,18 @@ static HA_ERRORS ha_errlist[]=
   { 147,"Lock table is full;  Restart program with a larger locktable"},
   { 148,"Updates are not allowed under a read only transactions"},
   { 149,"Lock deadlock; Retry transaction"},
+  { -30999, "DB_INCOMPLETE: Sync didn't finish"},
+  { -30998, "DB_KEYEMPTY: Key/data deleted or never created"},
+  { -30997, "DB_KEYEXIST: The key/data pair already exists"},
+  { -30996, "DB_LOCK_DEADLOCK: Deadlock"},
+  { -30995, "DB_LOCK_NOTGRANTED: Lock unavailable"},
+  { -30994, "DB_NOSERVER: Server panic return"},
+  { -30993, "DB_NOSERVER_HOME: Bad home sent to server"},
+  { -30992, "DB_NOSERVER_ID: Bad ID sent to server"},
+  { -30991, "DB_NOTFOUND: Key/data pair not found (EOF)"},
+  { -30990, "DB_OLD_VERSION: Out-of-date version"},
+  { -30989, "DB_RUNRECOVERY: Panic return"},
+  { -30988, "DB_VERIFY_BAD: Verify failed; bad format"},
   { 0,NullS },
 };
 
@@ -85,7 +97,8 @@ static void usage(void)
 {
   print_version();
   puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
-  printf("Print a description for a system error code or a error code from\na MyISAM/ISAM table handler\n");
+  printf("Print a description for a system error code or a error code from\na MyISAM/ISAM/BDB table handler.\n");
+  printf("If you want to get the error for a negative error code, you should use\n-- before the first error code to tell perror that there was no more options.\n\n");
   printf("Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]]\n",my_progname);
   printf("\n\
    -?, --help     Displays this help and exits.\n\
diff --git a/include/myisam.h b/include/myisam.h
index 8d25e17e589..9ecb5ef4294 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -274,6 +274,7 @@ extern uint mi_get_pointer_length(ulonglong file_length, uint def);
 #define T_SAFE_REPAIR		T_CREATE_MISSING_KEYS*2
 #define T_AUTO_REPAIR   	T_SAFE_REPAIR*2
 #define T_BACKUP_DATA		T_AUTO_REPAIR*2
+#define T_CALC_CHECKSUM		T_BACKUP_DATA*2
 
 #define O_NEW_INDEX	1		/* Bits set in out_flag */
 #define O_NEW_DATA	2
@@ -324,7 +325,7 @@ typedef struct st_mi_check_param
   uint testflag;
   uint8 language;
   my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
-  my_bool retry_repair,retry_without_quick, force_sort;
+  my_bool retry_repair,retry_without_quick, force_sort, calc_checksum;
   char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir;
   int tmpfile_createflag;
   myf myf_rw;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index aedea3ca78b..c4f37511ffa 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -1191,8 +1191,12 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
   del=info->state->del;
   info->state->records=info->state->del=share->state.split=0;
   info->state->empty=0;
+  param->glob_crc=0;
+  if (param->testflag & T_CALC_CHECKSUM)
+    param->calc_checksum=1;
   if (!rep_quick)
     share->state.checksum=0;
+
   info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
   for (i=0 ; i < info->s->base.keys ; i++)
     share->state.key_root[i]= HA_OFFSET_ERROR;
@@ -1284,7 +1288,14 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
     share->state.version=(ulong) time((time_t*) 0);	/* Force reopen */
   }
   else
+  {
     info->state->data_file_length=sort_info->max_pos;
+    if (param->testflag & T_CALC_CHECKSUM)
+    {
+      DBUG_PRINT("QQ",("set_checksum"));
+      share->state.checksum=param->glob_crc;
+    }
+  }
 
   if (!(param->testflag & T_SILENT))
   {
@@ -1867,6 +1878,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
   sort_param.sort_info=sort_info;
 
   del=info->state->del;
+  param->glob_crc=0;
+  if (param->testflag & T_CALC_CHECKSUM)
+    param->calc_checksum=1;
   if (! rep_quick)
     share->state.checksum=0;
 
@@ -1912,6 +1926,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
       param->retry_repair=1;
       goto err;
     }
+    param->calc_checksum=0;			/* No need to calc glob_crc */
 
     /* Set for next loop */
     sort_param.max_records=sort_info->max_records=
@@ -1987,6 +2002,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
 			       "Can't change size of datafile,  error: %d",
 			       my_errno);
   }
+  else if (param->testflag & T_CALC_CHECKSUM)
+    share->state.checksum=param->glob_crc;
+
   if (my_chsize(share->kfile,info->state->key_file_length,MYF(0)))
     mi_check_print_warning(param,
 			   "Can't change size of indexfile, error: %d",
@@ -2116,7 +2134,14 @@ static int sort_get_next_record(SORT_INFO *sort_info)
       sort_info->max_pos=(sort_info->pos+=share->base.pack_reclength);
       share->state.split++;
       if (*sort_info->record)
+      {
+	if (param->calc_checksum)
+	{
+	  DBUG_PRINT("QQ",("calc_checksum"));
+	  param->glob_crc+= mi_static_checksum(info,sort_info->record);
+	}
 	DBUG_RETURN(0);
+      }
       if (!sort_info->fix_datafile)
       {
 	info->state->del++;
@@ -2348,10 +2373,10 @@ static int sort_get_next_record(SORT_INFO *sort_info)
       {
 	if (param->read_cache.error < 0)
 	  DBUG_RETURN(1);
+	if (info->s->calc_checksum)
+	  info->checksum=mi_checksum(info,sort_info->record);
 	if ((param->testflag & (T_EXTEND | T_REP)) || searching)
 	{
-	  if (info->s->calc_checksum)
-	    info->checksum=mi_checksum(info,sort_info->record);
 	  if (_mi_rec_check(info, sort_info->record))
 	  {
 	    mi_check_print_info(param,"Found wrong packed record at %s",
@@ -2359,6 +2384,8 @@ static int sort_get_next_record(SORT_INFO *sort_info)
 	    goto try_next;
 	  }
 	}
+	if (param->calc_checksum)
+	  param->glob_crc+= info->checksum;
 	DBUG_RETURN(0);
       }
       if (!searching)
@@ -2421,6 +2448,8 @@ static int sort_get_next_record(SORT_INFO *sort_info)
 			 block_info.rec_len);
       share->state.split++;
       info->packed_length=block_info.rec_len;
+      if (param->calc_checksum)
+	param->glob_crc+= info->checksum;
       DBUG_RETURN(0);
     }
   }
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 5504e224ca9..3263494ef66 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -210,9 +210,9 @@ while test $# -gt 0; do
       ;;
     --debug)
       EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
-       --debug=d:t:O,$MYSQL_TEST_DIR/var/log/master.trace"
+       --debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/master.trace"
       EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
-       --debug=d:t:O,$MYSQL_TEST_DIR/var/log/slave.trace"
+       --debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/slave.trace"
       EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug"
       ;;
     -- )  shift; break ;;
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 00285c57a7e..3c5a72edc68 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -7,3 +7,16 @@ id	count(t2.id)
 id	count(t2.id)
 75	1
 107	1
+id	catid	stateid	countyid
+27	2	12	11
+28	2	12	11
+29	2	12	25
+26	1	6	37
+id	catid	stateid	countyid
+26	1	6	37
+27	2	12	11
+28	2	12	11
+29	2	12	25
+a
+1
+2
diff --git a/mysql-test/r/rpl000006.result b/mysql-test/r/rpl000006.result
index 31a36f88f39..56cd7166510 100644
--- a/mysql-test/r/rpl000006.result
+++ b/mysql-test/r/rpl000006.result
@@ -2,3 +2,5 @@ unix_timestamp(t)
 200006
 unix_timestamp(t)
 200006
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index 156f56a4d42..6fff628ccb9 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -85,5 +85,7 @@ drop table t1, t2;
 
 create table t1 (a int primary key);
 insert into t1 values(1),(2);
-select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a);
+select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a);
+--error 1116
+select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a);
 drop table t1;
diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test
index 99b5c3bfcae..54882d7bd43 100644
--- a/mysql-test/t/rpl000001.test
+++ b/mysql-test/t/rpl000001.test
@@ -73,7 +73,7 @@ create table t1 (n int);
 insert into t1 values(3456);
 use mysql;
 insert into user (Host, User, Password)
- VALUES ("10.10.10.%", "blafasel2", "blafasel2");
+ VALUES ("10.10.10.%", "blafasel2", password("blafasel2"));
 select select_priv,user from mysql.user where user = 'blafasel2';
 update user set Select_priv = "Y" where User="blafasel2";
 select select_priv,user from mysql.user where user = 'blafasel2';
diff --git a/mysql-test/t/rpl000006.test b/mysql-test/t/rpl000006.test
index b8ee690837e..495f34bd5e7 100644
--- a/mysql-test/t/rpl000006.test
+++ b/mysql-test/t/rpl000006.test
@@ -1,33 +1,46 @@
+#
+# Test forced timestamp
+#
 source include/master-slave.inc;
 connection master;
-set SQL_LOG_BIN=0;
-set timestamp=200006;
-drop table if exists foo;
-create table foo(t timestamp not null,a char(1));
-insert into foo ( a) values ('F');
-select unix_timestamp(t) from foo;
+
+# Don't log table creating to the slave as we want to test LOAD TABLE
+set SQL_LOG_BIN=0,timestamp=200006;
+drop table if exists t1;
+create table t1(t timestamp not null,a char(1));
+insert into t1 ( a) values ('F');
+select unix_timestamp(t) from t1;
 connection slave;
-drop table if exists foo;
-load table foo from master;
-select unix_timestamp(t) from foo;
+drop table if exists t1;
+load table t1 from master;
+select unix_timestamp(t) from t1;
+
+# Delete the created table on master and slave
 connection master;
-drop table foo;
+set SQL_LOG_BIN=1,timestamp=default;
+drop table t1;
 save_master_pos;
 connection slave;
 sync_with_master;
 connection master;
-set SQL_LOG_BIN=1;
+
+#
+# Test copying table with checksum
+#
+
+# Don't log table creating to the slave as we want to test LOAD TABLE
+set SQL_LOG_BIN=0;
+
 CREATE TABLE t1 (
  a int not null
 ) TYPE=MyISAM MAX_ROWS=4000 CHECKSUM=1;
-
 INSERT INTO t1 VALUES (1);
 save_master_pos;
 connection slave;
 sync_with_master;
-drop table t1;
 load table t1 from master;
 check table t1;
+drop table t1;
 connection master;
 drop table t1;
 save_master_pos;
diff --git a/mysql-test/t/rpl000017-slave.sh b/mysql-test/t/rpl000017-slave.sh
index 4415f093aad..269e144e278 100755
--- a/mysql-test/t/rpl000017-slave.sh
+++ b/mysql-test/t/rpl000017-slave.sh
@@ -3,7 +3,7 @@ master-bin.001
 4
 127.0.0.1
 replicate
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaab
 9306
 1
 EOF
diff --git a/mysql-test/t/rpl000017.test b/mysql-test/t/rpl000017.test
index d695561b671..04a2bc9c78a 100644
--- a/mysql-test/t/rpl000017.test
+++ b/mysql-test/t/rpl000017.test
@@ -2,8 +2,7 @@ connect (master,localhost,root,,test,0,mysql-master.sock);
 connect (slave,localhost,root,,test,0,mysql-slave.sock);
 connection master;
 reset master;
-grant file on *.* to replicate@localhost identified by
- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
+grant file on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab';
 connection slave;
 slave start;
 connection master;
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index a429d5308dd..c5c29f3c8bc 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -374,8 +374,10 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
   char* backup_dir = thd->lex.backup_dir;
   char src_path[FN_REFLEN], dst_path[FN_REFLEN];
   char* table_name = table->real_name;
+  DBUG_ENTER("restore");
+
   if (!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
-    return HA_ADMIN_INVALID;
+    DBUG_RETURN(HA_ADMIN_INVALID);
 
   int error = 0;
   const char* errmsg = "";
@@ -390,8 +392,8 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
 
   tmp_check_opt.init();
   tmp_check_opt.quick = 1;
-  tmp_check_opt.flags |= T_VERY_SILENT;
-  return repair(thd, &tmp_check_opt);
+  tmp_check_opt.flags |= T_VERY_SILENT | T_CALC_CHECKSUM;
+  DBUG_RETURN(repair(thd, &tmp_check_opt));
 
  err:
   {
@@ -403,7 +405,7 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
     param.table_name = table->table_name;
     param.testflag = 0;
     mi_check_print_error(&param,errmsg, errno );
-    return error;
+    DBUG_RETURN(error);
   }
 }
 
@@ -474,7 +476,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
   myisamchk_init(&param);
   param.thd = thd;
   param.op_name = (char*) "repair";
-  param.testflag = ((check_opt->flags & ~T_EXTEND) | 
+  param.testflag = ((check_opt->flags & ~(T_EXTEND)) | 
 		    T_SILENT | T_FORCE_CREATE |
 		    (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
   if (check_opt->quick)
diff --git a/sql/handler.cc b/sql/handler.cc
index 1c50634de1f..0a415040d82 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -702,6 +702,9 @@ void handler::print_error(int error, myf errflag)
   case HA_ERR_LOCK_TABLE_FULL:
     textno=ER_LOCK_TABLE_FULL;
     break;
+  case HA_ERR_LOCK_DEADLOCK:
+    textno=ER_LOCK_DEADLOCK;
+    break;
   case HA_ERR_READ_ONLY_TRANSACTION:
     textno=ER_READ_ONLY_TRANSACTION;
     break;
diff --git a/sql/slave.cc b/sql/slave.cc
index f6e8822ea14..52cde738b9a 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -390,7 +390,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
   }
 
   check_opt.init();
-  check_opt.flags|= T_VERY_SILENT;
+  check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM;
   check_opt.quick = 1;
   thd->proc_info = "Rebuilding the index on master dump table";
   // we do not want repair() to spam us with messages