summaryrefslogtreecommitdiff
path: root/mysql-test/suite/innodb/t/table_flags.test
blob: 4d3afcb2decb39cb99a00e812a8d070b310a0515 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
--source include/innodb_page_size.inc
# Embedded server tests do not support restarting
--source include/not_embedded.inc

--disable_query_log
call mtr.add_suppression("InnoDB: New log files created, LSN=");
call mtr.add_suppression("InnoDB: Creating foreign key constraint system tables");
call mtr.add_suppression("InnoDB: Error: .*innodb_table_stats. not found");
call mtr.add_suppression("InnoDB: Table '.test.\\..t[cdzp].' in InnoDB data dictionary has unknown type (81|f21|8a1|3023)");
call mtr.add_suppression("InnoDB: Cannot open table test/t[cdzp] from the internal data dictionary of InnoDB");
call mtr.add_suppression("InnoDB: Error: table 'test/t[cdzp]'");
FLUSH TABLES;
--enable_query_log

let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
let MYSQLD_DATADIR=`select @@datadir`;

let bugdir= $MYSQLTEST_VARDIR/tmp/table_flags;
--mkdir $bugdir
--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err

--let $d=--innodb-data-home-dir=$bugdir --innodb-log-group-home-dir=$bugdir
--let $d=$d --innodb-data-file-path=ibdata1:10M:autoextend
--let $d=$d --innodb-undo-tablespaces=0
--let $restart_parameters=$d --innodb-stats-persistent=0 --innodb-file-format=1
--source include/restart_mysqld.inc

SET GLOBAL innodb_file_per_table=1;
CREATE TABLE tr(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
CREATE TABLE tc(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=COMPACT;
CREATE TABLE td(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
CREATE TABLE tz(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE=1;
# PAGE_COMPRESSED is supported starting with MariaDB 10.1.0
--error ER_UNKNOWN_OPTION
CREATE TABLE tp(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC
PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=9;
CREATE TABLE tp(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC;

--source include/shutdown_mysqld.inc
--perl
use strict;
my $ps= $ENV{INNODB_PAGE_SIZE};
my $file= "$ENV{bugdir}/ibdata1";
open(FILE, "+<", $file) || die "Unable to open $file\n";
# Read DICT_HDR_TABLES, the root page number of CLUST_IND (SYS_TABLES.NAME).
sysseek(FILE, 7*$ps+38+32, 0) || die "Unable to seek $file";
die "Unable to read $file" unless sysread(FILE, $_, 4) == 4;
my $sys_tables_root = unpack("N", $_);
my $page;
print "SYS_TABLES clustered index root page ($sys_tables_root):\n";
sysseek(FILE, $sys_tables_root*$ps, 0) || die "Unable to seek $file";
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
open(BACKUP, ">$ENV{bugdir}/sys_tables.bin") || die "Unable to open backup\n";
syswrite(BACKUP, $page, $ps)==$ps || die "Unable to write backup\n";
close(BACKUP) || die "Unable to close backup\n";
print "N_RECS=", unpack("n", substr($page,38+16,2));
print "; LEVEL=", unpack("n", substr($page,38+26,2));
print "; INDEX_ID=0x", unpack("H*", substr($page,38+28,8)), "\n";
my @fields=("NAME","DB_TRX_ID","DB_ROLL_PTR",
	    "ID","N_COLS","TYPE","MIX_ID","MIX_LEN","CLUSTER_NAME","SPACE");
for (my $offset= 0x65; $offset;
     $offset= unpack("n", substr($page,$offset-2,2)))
{
    print "header=0x", unpack("H*",substr($page,$offset-6,6)), " (";
    my $n_fields= unpack("n", substr($page,$offset-4,2)) >> 1 & 0x3ff;
    my $start= 0;
    my $name;
    for (my $i= 0; $i < $n_fields; $i++) {
	my $end= unpack("C", substr($page, $offset-7-$i, 1));
	print ",\n " if $i;
	print "$fields[$i]=";
	if ($end & 0x80) {
	    print "NULL(", ($end & 0x7f) - $start, " bytes)"
	} elsif ($n_fields > 1 && $i == 0) {
	    $name= substr($page,$offset+$start,$end-$start);
	    print "'$name'"
	} else {
	    print "0x", unpack("H*", substr($page,$offset+$start,$end-$start))
	}
	# Corrupt SYS_TABLES.TYPE
	if ($i == 5)
	{
	    my $flags= 0;
	    if ($name eq 'test/tr') {
#		$flags= 0x40 # DATA_DIR mismatch causes 10.0 crash!
	    } elsif ($name eq 'test/tc') {
		$flags= 0x80 # 10.1 PAGE_COMPRESSED
	    } elsif ($name eq 'test/td') {
		$flags= 0xf00 # 10.1 PAGE_COMPRESSION_LEVEL=15 (0..9 is valid)
	    } elsif ($name eq 'test/tz') {
		$flags= 0x3000 # 10.1 ATOMIC_WRITES=3 (0..2 is valid)
	    } elsif ($name eq 'test/tp') {
		$flags= 0x880 # 10.1 PAGE_COMPRESSED, PAGE_COMPRESSION_LEVEL=8
		    # (in 10.1, this leaves PAGE_COMPRESSION_LEVEL=1
		    # without PAGE_COMPRESSED, which should be invalid)
	    }

	    substr($page,$offset+$start,$end-$start)= pack(
		"N", $flags ^
		unpack("N", substr($page,$offset+$start,$end-$start)))
		if $flags;
	}
	# Corrupt SYS_TABLES.MIX_LEN (ignored for ROW_FORMAT=REDUNDANT)
	if ($i == 7 && $name eq 'test/tr')
	{
	    substr($page,$offset+$start,$end-$start)= chr(255) x 4;
	}
	$start= $end & 0x7f;
    }
    print ")\n";
}
substr($page,0,4)=pack("N",0xdeadbeef);
substr($page,$ps-8,4)=pack("N",0xdeadbeef);
sysseek(FILE, $sys_tables_root*$ps, 0) || die "Unable to seek $file";
syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n";
close(FILE) || die "Unable to close $file\n";
EOF
--source include/start_mysqld.inc

SHOW CREATE TABLE tr;
INSERT INTO tr VALUES(42);
--error ER_NO_SUCH_TABLE_IN_ENGINE
SHOW CREATE TABLE tc;
--error ER_NO_SUCH_TABLE_IN_ENGINE
SHOW CREATE TABLE td;
--error ER_NO_SUCH_TABLE_IN_ENGINE
SHOW CREATE TABLE tz;
--error ER_NO_SUCH_TABLE_IN_ENGINE
SHOW CREATE TABLE tp;

--source include/shutdown_mysqld.inc

let SEARCH_RANGE= -50000;
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
--let SEARCH_PATTERN= InnoDB: Table '.test.\..t[cdzp].' in InnoDB data dictionary has unknown type (81|f21|8a1|3023)
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Cannot open table test/t[cdzp] from the internal data dictionary of InnoDB
--source include/search_pattern_in_file.inc

# Restore the backup of the corrupted SYS_TABLES clustered index root page
--perl
use strict;
my $ps= $ENV{INNODB_PAGE_SIZE};
my $file= "$ENV{bugdir}/ibdata1";
open(FILE, "+<", $file) || die "Unable to open $file\n";
open(BACKUP, "<$ENV{bugdir}/sys_tables.bin") || die "Unable to open backup\n";
# Read DICT_HDR_TABLES, the root page number of CLUST_IND (SYS_TABLES.NAME).
sysseek(FILE, 7*$ps+38+32, 0) || die "Unable to seek $file";
die "Unable to read $file\n" unless sysread(FILE, $_, 4) == 4;
my $sys_tables_root = unpack("N", $_);
print "Restoring SYS_TABLES clustered index root page ($sys_tables_root)\n";
sysseek(FILE, $sys_tables_root*$ps, 0) || die "Unable to seek $file";
die "Unable to read backup\n" unless sysread(BACKUP, $_, $ps) == $ps;
die "Unable to restore backup\n" unless syswrite(FILE, $_, $ps) == $ps;
close(BACKUP);
close(FILE) || die "Unable to close $file\n";
EOF
--source include/start_mysqld.inc

SHOW CREATE TABLE tr;
SHOW CREATE TABLE tc;
SHOW CREATE TABLE td;
SHOW CREATE TABLE tz;
SHOW CREATE TABLE tp;

BEGIN;
INSERT INTO tr VALUES(1);
INSERT INTO tc VALUES(1);
INSERT INTO td VALUES(1);
INSERT INTO tz VALUES(1);
INSERT INTO tp VALUES(1);
ROLLBACK;

SELECT * FROM tr;
SELECT * FROM tc;
SELECT * FROM td;
SELECT * FROM tz;
SELECT * FROM tp;

DROP TABLE tr,tc,td,tz,tp;

--source include/shutdown_mysqld.inc

--let $restart_parameters=
--source include/start_mysqld.inc

--list_files $bugdir
--remove_files_wildcard $bugdir
--rmdir $bugdir