diff --git a/mysql-test/std_data/bug48633.ARM b/mysql-test/std_data/bug48633.ARM new file mode 100644 index 00000000000..5a46ddacc3a Binary files /dev/null and b/mysql-test/std_data/bug48633.ARM differ diff --git a/mysql-test/std_data/bug48633.ARZ b/mysql-test/std_data/bug48633.ARZ new file mode 100644 index 00000000000..0aa85c690e5 Binary files /dev/null and b/mysql-test/std_data/bug48633.ARZ differ diff --git a/mysql-test/std_data/bug48633.frm b/mysql-test/std_data/bug48633.frm new file mode 100644 index 00000000000..5c2a8a688b7 Binary files /dev/null and b/mysql-test/std_data/bug48633.frm differ diff --git a/mysql-test/suite/archive/archive.result b/mysql-test/suite/archive/archive.result index b187c216120..b92018fba8b 100644 --- a/mysql-test/suite/archive/archive.result +++ b/mysql-test/suite/archive/archive.result @@ -12729,7 +12729,6 @@ id id name name 1 1 a b 2 2 a b DROP TABLE t1,t2; -flush tables; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -12741,7 +12740,7 @@ col1 col2 INSERT INTO t1 (col1, col2) VALUES (1, "value"); REPAIR TABLE t1; Table Op Msg_type Msg_text -test.t1 repair error Corrupt +test.t1 repair status OK DROP TABLE t1; # # Ensure that TRUNCATE fails for non-empty archive tables. @@ -12787,6 +12786,62 @@ a b c d e f DROP TABLE t1; SET sort_buffer_size=DEFAULT; # +# BUG#11756687 - 48633: ARCHIVE TABLES ARE NOT UPGRADEABLE +# +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` text, + `c` varchar(255) DEFAULT NULL, + `d` blob, + `e` blob +) ENGINE=ARCHIVE DEFAULT CHARSET=latin1 +SELECT * FROM t1; +a b c d e +1 text varchar blob1 blob2 +2 text varchar blob1 blob2 +SELECT * FROM t1; +a b c d e +1 text varchar blob1 blob2 +2 text varchar blob1 blob2 +FLUSH TABLE t1; +SELECT * FROM t1; +a b c d e +1 text varchar blob1 blob2 +2 text varchar blob1 blob2 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check error Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +SELECT * FROM t1; +a b c d e +1 text varchar blob1 blob2 +2 text varchar blob1 blob2 +INSERT INTO t1 VALUES(3, 'text', 'varchar', 'blob1', 'blob2'); +SELECT * FROM t1; +a b c d e +1 text varchar blob1 blob2 +2 text varchar blob1 blob2 +3 text varchar blob1 blob2 +FLUSH TABLE t1; +SELECT * FROM t1; +a b c d e +1 text varchar blob1 blob2 +2 text varchar blob1 blob2 +3 text varchar blob1 blob2 +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT * FROM t1; +a b c d e +1 text varchar blob1 blob2 +2 text varchar blob1 blob2 +3 text varchar blob1 blob2 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +# # BUG#11758979 - 51252: ARCHIVE TABLES STILL FAIL UNDER STRESS # TESTS: CRASH, CORRUPTION, 4G MEMOR # (to be executed with valgrind) diff --git a/mysql-test/suite/archive/archive.test b/mysql-test/suite/archive/archive.test index 5d96aa256fb..81a73683541 100644 --- a/mysql-test/suite/archive/archive.test +++ b/mysql-test/suite/archive/archive.test @@ -12,6 +12,7 @@ DROP TABLE if exists t1,t2,t3,t4,t5,t6; --enable_warnings SET storage_engine=ARCHIVE; +let $MYSQLD_DATADIR= `SELECT @@datadir`; CREATE TABLE t1 ( Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, @@ -1643,12 +1644,6 @@ DROP TABLE t1,t2; # # BUG#47012 archive tables are not upgradeable, and server crashes on any access # -let $MYSQLD_DATADIR= `SELECT @@datadir`; - -# Remove files to handle possible restart of test -flush tables; -remove_files_wildcard $MYSQLD_DATADIR/test t1.*; - copy_file std_data/bug47012.frm $MYSQLD_DATADIR/test/t1.frm; copy_file std_data/bug47012.ARZ $MYSQLD_DATADIR/test/t1.ARZ; copy_file std_data/bug47012.ARM $MYSQLD_DATADIR/test/t1.ARM; @@ -1661,7 +1656,6 @@ INSERT INTO t1 (col1, col2) VALUES (1, "value"); REPAIR TABLE t1; DROP TABLE t1; -remove_file $MYSQLD_DATADIR/test/t1.ARM; --echo # --echo # Ensure that TRUNCATE fails for non-empty archive tables. @@ -1711,6 +1705,36 @@ SELECT * FROM t1 ORDER BY f LIMIT 1; DROP TABLE t1; SET sort_buffer_size=DEFAULT; +--echo # +--echo # BUG#11756687 - 48633: ARCHIVE TABLES ARE NOT UPGRADEABLE +--echo # +copy_file std_data/bug48633.frm $MYSQLD_DATADIR/test/t1.frm; +copy_file std_data/bug48633.ARZ $MYSQLD_DATADIR/test/t1.ARZ; +copy_file std_data/bug48633.ARM $MYSQLD_DATADIR/test/t1.ARM; +SHOW CREATE TABLE t1; +# Test first table scan +SELECT * FROM t1; +# Test second table scan +SELECT * FROM t1; +# Test table close +FLUSH TABLE t1; +SELECT * FROM t1; +# Test check +CHECK TABLE t1; +SELECT * FROM t1; +# Test insert +INSERT INTO t1 VALUES(3, 'text', 'varchar', 'blob1', 'blob2'); +SELECT * FROM t1; +# Test table close after insert +FLUSH TABLE t1; +SELECT * FROM t1; +# Test repair +REPAIR TABLE t1; +SELECT * FROM t1; +# Test check table after upgrade +CHECK TABLE t1; +DROP TABLE t1; + --echo # --echo # BUG#11758979 - 51252: ARCHIVE TABLES STILL FAIL UNDER STRESS --echo # TESTS: CRASH, CORRUPTION, 4G MEMOR diff --git a/storage/archive/azio.c b/storage/archive/azio.c index 4519d15cefc..c1efe19e91f 100644 --- a/storage/archive/azio.c +++ b/storage/archive/azio.c @@ -77,6 +77,7 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd) s->version = (unsigned char)az_magic[1]; /* this needs to be a define to version */ s->minor_version= (unsigned char) az_magic[2]; /* minor version */ s->dirty= AZ_STATE_CLEAN; + s->start= 0; /* We do our own version of append by nature. @@ -186,6 +187,9 @@ int write_header(azio_stream *s) char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE]; char *ptr= buffer; + if (s->version == 1) + return 0; + s->block_size= AZ_BUFSIZE_WRITE; s->version = (unsigned char)az_magic[1]; s->minor_version = (unsigned char)az_magic[2]; @@ -308,9 +312,9 @@ void check_header(azio_stream *s) /* Peek ahead to check the gzip magic header */ if ( s->stream.next_in[0] == gz_magic[0] && s->stream.next_in[1] == gz_magic[1]) { + read_header(s, s->stream.next_in); s->stream.avail_in -= 2; s->stream.next_in += 2; - s->version= (unsigned char)2; /* Check the rest of the gzip header */ method = get_byte(s); @@ -339,7 +343,8 @@ void check_header(azio_stream *s) for (len = 0; len < 2; len++) (void)get_byte(s); } s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; - s->start = my_tell(s->file, MYF(0)) - s->stream.avail_in; + if (!s->start) + s->start= my_tell(s->file, MYF(0)) - s->stream.avail_in; } else if ( s->stream.next_in[0] == az_magic[0] && s->stream.next_in[1] == az_magic[1]) { @@ -401,9 +406,13 @@ void read_header(azio_stream *s, unsigned char *buffer) else if (buffer[0] == gz_magic[0] && buffer[1] == gz_magic[1]) { /* - Set version number to previous version (2). + Set version number to previous version (1). */ - s->version= (unsigned char) 2; + s->version= 1; + s->auto_increment= 0; + s->frm_length= 0; + s->longest_row= 0; + s->shortest_row= 0; } else { /* Unknown version. diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index bb66d329de0..82f2513ad59 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -97,6 +97,11 @@ inserts a lot faster, but would mean highly arbitrary reads. -Brian + + Archive file format versions: + <5.1.5 - v.1 + 5.1.5-5.1.15 - v.2 + >5.1.15 - v.3 */ @@ -192,9 +197,11 @@ static void init_archive_psi_keys(void) /* We just implement one additional file extension. + ARM is here just to properly drop 5.0 tables. */ static const char *ha_archive_exts[] = { ARZ, + ARM, NullS }; @@ -581,20 +588,13 @@ int ha_archive::open(const char *name, int mode, uint open_options) if (!share) DBUG_RETURN(rc); - /* - Allow open on crashed table in repair mode only. - Block open on 5.0 ARCHIVE table. Though we have almost all - routines to access these tables, they were not well tested. - For now we have to refuse to open such table to avoid - potential data loss. - */ + /* Allow open on crashed table in repair mode only. */ switch (rc) { case 0: break; case HA_ERR_TABLE_DEF_CHANGED: case HA_ERR_CRASHED_ON_USAGE: - case HA_ERR_TABLE_NEEDS_UPGRADE: if (open_options & HA_OPEN_FOR_REPAIR) { rc= 0; @@ -675,6 +675,17 @@ int ha_archive::frm_copy(azio_stream *src, azio_stream *dst) int rc= 0; uchar *frm_ptr; + if (!src->frm_length) + { + size_t frm_len; + if (!table_share->read_frm_image((const uchar**) &frm_ptr, &frm_len)) + { + azwrite_frm(dst, frm_ptr, frm_len); + table_share->free_frm_image(frm_ptr); + } + return 0; + } + if (!(frm_ptr= (uchar *) my_malloc(src->frm_length, MYF(MY_THREAD_SPECIFIC | MY_WME)))) return HA_ERR_OUT_OF_MEM; @@ -1639,19 +1650,13 @@ int ha_archive::info(uint flag) { DBUG_ENTER("ha_archive::info"); - /* - If dirty, we lock, and then reset/flush the data. - I found that just calling azflush() doesn't always work. - */ mysql_mutex_lock(&share->mutex); - if (share->dirty == TRUE) + if (share->dirty) { - if (share->dirty == TRUE) - { - DBUG_PRINT("ha_archive", ("archive flushing out rows for scan")); - azflush(&(share->archive_write), Z_SYNC_FLUSH); - share->dirty= FALSE; - } + DBUG_PRINT("ha_archive", ("archive flushing out rows for scan")); + DBUG_ASSERT(share->archive_write_open); + azflush(&(share->archive_write), Z_SYNC_FLUSH); + share->dirty= FALSE; } /* @@ -1727,7 +1732,10 @@ int ha_archive::end_bulk_insert() { DBUG_ENTER("ha_archive::end_bulk_insert"); bulk_insert= FALSE; - share->dirty= TRUE; + mysql_mutex_lock(&share->mutex); + if (share->archive_write_open) + share->dirty= true; + mysql_mutex_unlock(&share->mutex); DBUG_RETURN(0); }