From 298c067eeede9e086252390856c990633fe08231 Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Thu, 25 Mar 2010 23:57:06 +0400
Subject: [PATCH] BUG#46565 - repair of partition fail for archive engine

There was no way to repair corrupt ARCHIVE data file,
when unrecoverable data loss is inevitable.

With this fix REPAIR ... EXTENDED attempts to restore
as much rows as possible, ignoring unrecoverable data.

Normal REPAIR is still able to repair meta-data file
only.

mysql-test/r/archive.result:
  A test case for BUG#46565.
mysql-test/std_data/bug46565.ARZ:
  A test case for BUG#46565.
mysql-test/std_data/bug46565.frm:
  A test case for BUG#46565.
mysql-test/t/archive.test:
  A test case for BUG#46565.
storage/archive/ha_archive.cc:
  Allow unrecoverable data loss when extended repair
  is requested.
---
 mysql-test/r/archive.result      |  19 +++++++++++++++++++
 mysql-test/std_data/bug46565.ARZ | Bin 0 -> 8670 bytes
 mysql-test/std_data/bug46565.frm | Bin 0 -> 8554 bytes
 mysql-test/t/archive.test        |  23 +++++++++++++++++++++++
 storage/archive/ha_archive.cc    |  14 ++++++++++----
 5 files changed, 52 insertions(+), 4 deletions(-)
 create mode 100644 mysql-test/std_data/bug46565.ARZ
 create mode 100644 mysql-test/std_data/bug46565.frm

diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
index f14f6a39386..f90bcb521e1 100644
--- a/mysql-test/r/archive.result
+++ b/mysql-test/r/archive.result
@@ -12737,3 +12737,22 @@ SELECT * FROM t1;
 ERROR HY000: Can't find file: 't1' (errno: 2)
 DROP TABLE t1;
 ERROR 42S02: Unknown table 't1'
+#
+# BUG#46565 - repair of partition fail for archive engine
+#
+# Installing corrupted table files for t1.
+SELECT * FROM t1;
+ERROR HY000: Table 't1' is marked as crashed and should be repaired
+REPAIR TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	error	Corrupt
+SELECT * FROM t1;
+ERROR HY000: Table 't1' is marked as crashed and should be repaired
+REPAIR TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	status	OK
+SELECT * FROM t1;
+a
+1
+2
+DROP TABLE t1;
diff --git a/mysql-test/std_data/bug46565.ARZ b/mysql-test/std_data/bug46565.ARZ
new file mode 100644
index 0000000000000000000000000000000000000000..f26b31218a1bd990e73a9f83a9acbf77544d789d
GIT binary patch
literal 8670
zcmeI&u?m7v6b9h`UX=_R45Fo_z@@1cA3!3gC88l3jR?Z0XzD?thiGr?EgE}*Chdq<
zYium~59m3bbG^v7dQ(gJm;p$7ax-x@wN*AuzQ3)>TXl1pF_5adFE9BD7)pXuO`u)4
zC>oNB@Fm?YK(lNN20*ubV5R^CC_n)UP=Epypa2CZKmiI+;A;gmvg+GRRYSBGO{U9n
zHDEyj3Q&Lo6rcbFC_n)UP=Epypuo=xBuakz|8XcNgz!Ybfn7Pw(UyK5A+*x1e)q$W
rJ@gv3_B?2yvzHw#IXscAGrW#wY_@UyxViy$$HOT<kx?}4U==l<WuYIx

literal 0
HcmV?d00001

diff --git a/mysql-test/std_data/bug46565.frm b/mysql-test/std_data/bug46565.frm
new file mode 100644
index 0000000000000000000000000000000000000000..5c0180bdc1e4f685419765277582bfc8a0eb840b
GIT binary patch
literal 8554
zcmeI&F$%&!5QX8llLRAaB8ZJmTC3RP03w2RVqu@wQ+PLT;z3+TVz#za{9iM(v#=~*
zyZZ>!I+N-kt-YvFij^ug47?7hz1(loY#g+$)Qk%%0tg_000IagfB*srAb<b@2z;%8
zDW<!<yNNcZ?f!7yr41Sc5I_I{1Q0*~0R#|0009IL_*sEV@JIhYPEb&%$^{DL$>FGl
f&tK_e!RD*x!}uB2E4QkWNz1FBkoo6{*hf79pB@qn

literal 0
HcmV?d00001

diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index 67ad0517ed2..7084f5f540e 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -1655,3 +1655,26 @@ FLUSH TABLE t1;
 SELECT * FROM t1;
 --error ER_BAD_TABLE_ERROR
 DROP TABLE t1;
+
+
+--echo #
+--echo # BUG#46565 - repair of partition fail for archive engine
+--echo #
+--echo # Installing corrupted table files for t1.
+# bug46565 was created, filled and damaged as following:
+# CREATE TABLE bug46565(a INT) ENGINE=archive;
+# INSERT INTO bug46565 VALUES(1);
+# FLUSH TABLE bug46565;
+# INSERT INTO bug46565 VALUES(2),(3);
+# FLUSH TABLE bug46565;
+# dd if=bug46565.ARZ of=std_data/bug46565.ARZ bs=1 count=8670
+copy_file std_data/bug46565.frm $MYSQLD_DATADIR/test/t1.frm;
+copy_file std_data/bug46565.ARZ $MYSQLD_DATADIR/test/t1.ARZ;
+--error ER_CRASHED_ON_USAGE
+SELECT * FROM t1;
+REPAIR TABLE t1;
+--error ER_CRASHED_ON_USAGE
+SELECT * FROM t1;
+REPAIR TABLE t1 EXTENDED;
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 364ffba0f6c..988337ec50e 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1269,13 +1269,12 @@ int ha_archive::rnd_pos(uchar * buf, uchar *pos)
 
 /*
   This method repairs the meta file. It does this by walking the datafile and 
-  rewriting the meta file. Currently it does this by calling optimize with
-  the extended flag.
+  rewriting the meta file. If EXTENDED repair is requested, we attempt to
+  recover as much data as possible.
 */
 int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
 {
   DBUG_ENTER("ha_archive::repair");
-  check_opt->flags= T_EXTEND;
   int rc= optimize(thd, check_opt);
 
   if (rc)
@@ -1369,7 +1368,14 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
     DBUG_PRINT("ha_archive", ("recovered %llu archive rows", 
                         (unsigned long long)share->rows_recorded));
 
-    if (rc && rc != HA_ERR_END_OF_FILE)
+    /*
+      If REPAIR ... EXTENDED is requested, try to recover as much data
+      from data file as possible. In this case if we failed to read a
+      record, we assume EOF. This allows massive data loss, but we can
+      hardly do more with broken zlib stream. And this is the only way
+      to restore at least what is still recoverable.
+    */
+    if (rc && rc != HA_ERR_END_OF_FILE && !(check_opt->flags & T_EXTEND))
       goto error;
   }