Merge lp:~percona-toolkit-dev/percona-toolkit/fix-1047335-crashed-tables into lp:percona-toolkit/2.1

Proposed by Brian Fraser
Status: Superseded
Proposed branch: lp:~percona-toolkit-dev/percona-toolkit/fix-1047335-crashed-tables
Merge into: lp:percona-toolkit/2.1
Diff against target: 593 lines (+232/-68)
18 files modified
bin/pt-archiver (+2/-4)
bin/pt-config-diff (+3/-1)
bin/pt-duplicate-key-checker (+14/-5)
bin/pt-find (+2/-4)
bin/pt-heartbeat (+2/-4)
bin/pt-index-usage (+14/-5)
bin/pt-kill (+5/-5)
bin/pt-online-schema-change (+5/-5)
bin/pt-query-advisor (+2/-4)
bin/pt-query-digest (+2/-4)
bin/pt-table-checksum (+14/-5)
bin/pt-table-sync (+2/-2)
bin/pt-upgrade (+2/-4)
lib/SchemaIterator.pm (+16/-1)
lib/TableParser.pm (+2/-8)
t/lib/SchemaIterator.t (+70/-2)
t/lib/TableParser.t (+64/-5)
t/lib/samples/bug_1047335_crashed_table.sql (+11/-0)
To merge this branch: bzr merge lp:~percona-toolkit-dev/percona-toolkit/fix-1047335-crashed-tables
Reviewer Review Type Date Requested Status
Daniel Nichter Needs Resubmitting
Review via email: mp+132185@code.launchpad.net

This proposal has been superseded by a proposal from 2012-10-30.

To post a comment you must log in.
Revision history for this message
Daniel Nichter (daniel-nichter) wrote :

This diff has other stuff, for MasterSlave and PXC. Can you isolate just the changes for this branch/bug?

review: Needs Resubmitting
Revision history for this message
Daniel Nichter (daniel-nichter) wrote :

Also, the local $EVAL_ERROR (re another branch).

I think we have a crashed .frm in the source somewhere; I just looked but couldn't find it; I recall testing this before for something else.

Re 469 +# This might fail. Doesn't matter -- stop_sandbox will just rm -rf the folder -- will this cause output to STDERR? If so, that's bad because it shows up as an error.

436. By Brian Fraser

Fix for 1047335: SchemaIterator fails when it encounters a crashed table

437. By Brian Fraser

Removed local $EVAL_ERROR, added a test using t/lib/samples/broken_tbl.frm, and updated all modules

438. By Brian Fraser

Fixes per Daniel's review

439. By Brian Fraser

t/lib/samples/bug_1047335_crashed_table.sql: Use a single INSERT with all the values instead of 1k statements

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/pt-archiver'
2--- bin/pt-archiver 2012-10-22 18:17:08 +0000
3+++ bin/pt-archiver 2012-10-30 21:38:20 +0000
4@@ -1584,13 +1584,11 @@
5 PTDEBUG && _d($show_sql);
6 my $href;
7 eval { $href = $dbh->selectrow_hashref($show_sql); };
8- if ( $EVAL_ERROR ) {
9- PTDEBUG && _d($EVAL_ERROR);
10-
11+ if ( my $e = $EVAL_ERROR ) {
12 PTDEBUG && _d($old_sql_mode);
13 $dbh->do($old_sql_mode);
14
15- return;
16+ die $e;
17 }
18
19 PTDEBUG && _d($old_sql_mode);
20
21=== modified file 'bin/pt-config-diff'
22--- bin/pt-config-diff 2012-10-22 18:17:08 +0000
23+++ bin/pt-config-diff 2012-10-30 21:38:20 +0000
24@@ -1576,7 +1576,9 @@
25 PTDEBUG && _d($sql);
26 my $row = $self->{dbh}->selectrow_arrayref($sql);
27 PTDEBUG && _d(defined $row ? @$row : 'undef');
28- $self->{is_cluster_node} = $row && $row->[0] ? 1 : 0;
29+ $self->{is_cluster_node} = $row && $row->[1]
30+ ? ($row->[1] eq 'ON' || $row->[1] eq '1')
31+ : 0;
32
33 return $self->{is_cluster_node};
34 }
35
36=== modified file 'bin/pt-duplicate-key-checker'
37--- bin/pt-duplicate-key-checker 2012-10-22 18:17:08 +0000
38+++ bin/pt-duplicate-key-checker 2012-10-30 21:38:20 +0000
39@@ -226,13 +226,11 @@
40 PTDEBUG && _d($show_sql);
41 my $href;
42 eval { $href = $dbh->selectrow_hashref($show_sql); };
43- if ( $EVAL_ERROR ) {
44- PTDEBUG && _d($EVAL_ERROR);
45-
46+ if ( my $e = $EVAL_ERROR ) {
47 PTDEBUG && _d($old_sql_mode);
48 $dbh->do($old_sql_mode);
49
50- return;
51+ die $e;
52 }
53
54 PTDEBUG && _d($old_sql_mode);
55@@ -3138,7 +3136,18 @@
56 }
57
58 while ( my $tbl = shift @{$self->{tbls}} ) {
59- my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl);
60+ local $EVAL_ERROR;
61+ my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
62+ if ( my $e = $EVAL_ERROR ) {
63+ my $table_name = "$self->{db}.$tbl";
64+ if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
65+ PTDEBUG && _d("Skipping $table_name because it no longer exists");
66+ }
67+ else {
68+ warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
69+ }
70+ next;
71+ }
72 my $tbl_struct = $tp->parse($ddl);
73 if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
74 return {
75
76=== modified file 'bin/pt-find'
77--- bin/pt-find 2012-10-22 18:17:08 +0000
78+++ bin/pt-find 2012-10-30 21:38:20 +0000
79@@ -1623,13 +1623,11 @@
80 PTDEBUG && _d($show_sql);
81 my $href;
82 eval { $href = $dbh->selectrow_hashref($show_sql); };
83- if ( $EVAL_ERROR ) {
84- PTDEBUG && _d($EVAL_ERROR);
85-
86+ if ( my $e = $EVAL_ERROR ) {
87 PTDEBUG && _d($old_sql_mode);
88 $dbh->do($old_sql_mode);
89
90- return;
91+ die $e;
92 }
93
94 PTDEBUG && _d($old_sql_mode);
95
96=== modified file 'bin/pt-heartbeat'
97--- bin/pt-heartbeat 2012-10-22 18:17:08 +0000
98+++ bin/pt-heartbeat 2012-10-30 21:38:20 +0000
99@@ -2549,13 +2549,11 @@
100 PTDEBUG && _d($show_sql);
101 my $href;
102 eval { $href = $dbh->selectrow_hashref($show_sql); };
103- if ( $EVAL_ERROR ) {
104- PTDEBUG && _d($EVAL_ERROR);
105-
106+ if ( my $e = $EVAL_ERROR ) {
107 PTDEBUG && _d($old_sql_mode);
108 $dbh->do($old_sql_mode);
109
110- return;
111+ die $e;
112 }
113
114 PTDEBUG && _d($old_sql_mode);
115
116=== modified file 'bin/pt-index-usage'
117--- bin/pt-index-usage 2012-10-22 18:17:08 +0000
118+++ bin/pt-index-usage 2012-10-30 21:38:20 +0000
119@@ -2821,13 +2821,11 @@
120 PTDEBUG && _d($show_sql);
121 my $href;
122 eval { $href = $dbh->selectrow_hashref($show_sql); };
123- if ( $EVAL_ERROR ) {
124- PTDEBUG && _d($EVAL_ERROR);
125-
126+ if ( my $e = $EVAL_ERROR ) {
127 PTDEBUG && _d($old_sql_mode);
128 $dbh->do($old_sql_mode);
129
130- return;
131+ die $e;
132 }
133
134 PTDEBUG && _d($old_sql_mode);
135@@ -3968,7 +3966,18 @@
136 }
137
138 while ( my $tbl = shift @{$self->{tbls}} ) {
139- my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl);
140+ local $EVAL_ERROR;
141+ my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
142+ if ( my $e = $EVAL_ERROR ) {
143+ my $table_name = "$self->{db}.$tbl";
144+ if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
145+ PTDEBUG && _d("Skipping $table_name because it no longer exists");
146+ }
147+ else {
148+ warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
149+ }
150+ next;
151+ }
152 my $tbl_struct = $tp->parse($ddl);
153 if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
154 return {
155
156=== modified file 'bin/pt-kill'
157--- bin/pt-kill 2012-10-22 18:17:08 +0000
158+++ bin/pt-kill 2012-10-30 21:38:20 +0000
159@@ -2499,13 +2499,11 @@
160 PTDEBUG && _d($show_sql);
161 my $href;
162 eval { $href = $dbh->selectrow_hashref($show_sql); };
163- if ( $EVAL_ERROR ) {
164- PTDEBUG && _d($EVAL_ERROR);
165-
166+ if ( my $e = $EVAL_ERROR ) {
167 PTDEBUG && _d($old_sql_mode);
168 $dbh->do($old_sql_mode);
169
170- return;
171+ die $e;
172 }
173
174 PTDEBUG && _d($old_sql_mode);
175@@ -4807,7 +4805,9 @@
176 PTDEBUG && _d($sql);
177 my $row = $self->{dbh}->selectrow_arrayref($sql);
178 PTDEBUG && _d(defined $row ? @$row : 'undef');
179- $self->{is_cluster_node} = $row && $row->[0] ? 1 : 0;
180+ $self->{is_cluster_node} = $row && $row->[1]
181+ ? ($row->[1] eq 'ON' || $row->[1] eq '1')
182+ : 0;
183
184 return $self->{is_cluster_node};
185 }
186
187=== modified file 'bin/pt-online-schema-change'
188--- bin/pt-online-schema-change 2012-10-22 20:23:05 +0000
189+++ bin/pt-online-schema-change 2012-10-30 21:38:20 +0000
190@@ -2733,13 +2733,11 @@
191 PTDEBUG && _d($show_sql);
192 my $href;
193 eval { $href = $dbh->selectrow_hashref($show_sql); };
194- if ( $EVAL_ERROR ) {
195- PTDEBUG && _d($EVAL_ERROR);
196-
197+ if ( my $e = $EVAL_ERROR ) {
198 PTDEBUG && _d($old_sql_mode);
199 $dbh->do($old_sql_mode);
200
201- return;
202+ die $e;
203 }
204
205 PTDEBUG && _d($old_sql_mode);
206@@ -3437,7 +3435,9 @@
207 PTDEBUG && _d($sql);
208 my $row = $self->{dbh}->selectrow_arrayref($sql);
209 PTDEBUG && _d(defined $row ? @$row : 'undef');
210- $self->{is_cluster_node} = $row && $row->[0] ? 1 : 0;
211+ $self->{is_cluster_node} = $row && $row->[1]
212+ ? ($row->[1] eq 'ON' || $row->[1] eq '1')
213+ : 0;
214
215 return $self->{is_cluster_node};
216 }
217
218=== modified file 'bin/pt-query-advisor'
219--- bin/pt-query-advisor 2012-10-22 18:17:08 +0000
220+++ bin/pt-query-advisor 2012-10-30 21:38:20 +0000
221@@ -5311,13 +5311,11 @@
222 PTDEBUG && _d($show_sql);
223 my $href;
224 eval { $href = $dbh->selectrow_hashref($show_sql); };
225- if ( $EVAL_ERROR ) {
226- PTDEBUG && _d($EVAL_ERROR);
227-
228+ if ( my $e = $EVAL_ERROR ) {
229 PTDEBUG && _d($old_sql_mode);
230 $dbh->do($old_sql_mode);
231
232- return;
233+ die $e;
234 }
235
236 PTDEBUG && _d($old_sql_mode);
237
238=== modified file 'bin/pt-query-digest'
239--- bin/pt-query-digest 2012-10-22 18:17:08 +0000
240+++ bin/pt-query-digest 2012-10-30 21:38:20 +0000
241@@ -8140,13 +8140,11 @@
242 PTDEBUG && _d($show_sql);
243 my $href;
244 eval { $href = $dbh->selectrow_hashref($show_sql); };
245- if ( $EVAL_ERROR ) {
246- PTDEBUG && _d($EVAL_ERROR);
247-
248+ if ( my $e = $EVAL_ERROR ) {
249 PTDEBUG && _d($old_sql_mode);
250 $dbh->do($old_sql_mode);
251
252- return;
253+ die $e;
254 }
255
256 PTDEBUG && _d($old_sql_mode);
257
258=== modified file 'bin/pt-table-checksum'
259--- bin/pt-table-checksum 2012-10-26 23:06:21 +0000
260+++ bin/pt-table-checksum 2012-10-30 21:38:20 +0000
261@@ -3725,13 +3725,11 @@
262 PTDEBUG && _d($show_sql);
263 my $href;
264 eval { $href = $dbh->selectrow_hashref($show_sql); };
265- if ( $EVAL_ERROR ) {
266- PTDEBUG && _d($EVAL_ERROR);
267-
268+ if ( my $e = $EVAL_ERROR ) {
269 PTDEBUG && _d($old_sql_mode);
270 $dbh->do($old_sql_mode);
271
272- return;
273+ die $e;
274 }
275
276 PTDEBUG && _d($old_sql_mode);
277@@ -6784,7 +6782,18 @@
278 }
279
280 while ( my $tbl = shift @{$self->{tbls}} ) {
281- my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl);
282+ local $EVAL_ERROR;
283+ my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
284+ if ( my $e = $EVAL_ERROR ) {
285+ my $table_name = "$self->{db}.$tbl";
286+ if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
287+ PTDEBUG && _d("Skipping $table_name because it no longer exists");
288+ }
289+ else {
290+ warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
291+ }
292+ next;
293+ }
294 my $tbl_struct = $tp->parse($ddl);
295 if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
296 return {
297
298=== modified file 'bin/pt-table-sync'
299--- bin/pt-table-sync 2012-10-22 18:17:08 +0000
300+++ bin/pt-table-sync 2012-10-30 21:38:20 +0000
301@@ -2990,7 +2990,7 @@
302 my ( $self, $dbh, $quoter, $db, $tbl, $what ) = @_;
303
304 if ( $what eq 'table' ) {
305- my $ddl = $self->get_create_table($dbh, $quoter, $db, $tbl);
306+ my $ddl = $self->get_create_table($dbh, $dbh, $db, $tbl);
307 return unless $ddl;
308 if ( $ddl->[0] eq 'table' ) {
309 return $before
310@@ -3033,7 +3033,7 @@
311 }
312 }
313 elsif ( $what eq 'view' ) {
314- my $ddl = $self->get_create_table($dbh, $quoter, $db, $tbl);
315+ my $ddl = $self->get_create_table($dbh, $dbh, $db, $tbl);
316 return '/*!50001 DROP TABLE IF EXISTS ' . $quoter->quote($tbl) . "*/;\n"
317 . '/*!50001 DROP VIEW IF EXISTS ' . $quoter->quote($tbl) . "*/;\n"
318 . '/*!50001 ' . $ddl->[1] . "*/;\n";
319
320=== modified file 'bin/pt-upgrade'
321--- bin/pt-upgrade 2012-10-22 18:17:08 +0000
322+++ bin/pt-upgrade 2012-10-30 21:38:20 +0000
323@@ -498,13 +498,11 @@
324 PTDEBUG && _d($show_sql);
325 my $href;
326 eval { $href = $dbh->selectrow_hashref($show_sql); };
327- if ( $EVAL_ERROR ) {
328- PTDEBUG && _d($EVAL_ERROR);
329-
330+ if ( my $e = $EVAL_ERROR ) {
331 PTDEBUG && _d($old_sql_mode);
332 $dbh->do($old_sql_mode);
333
334- return;
335+ die $e;
336 }
337
338 PTDEBUG && _d($old_sql_mode);
339
340=== modified file 'lib/SchemaIterator.pm'
341--- lib/SchemaIterator.pm 2012-04-03 18:21:15 +0000
342+++ lib/SchemaIterator.pm 2012-10-30 21:38:20 +0000
343@@ -352,7 +352,22 @@
344 }
345
346 while ( my $tbl = shift @{$self->{tbls}} ) {
347- my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl);
348+ local $EVAL_ERROR;
349+ my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
350+ if ( my $e = $EVAL_ERROR ) {
351+ my $table_name = "$self->{db}.$tbl";
352+ # SHOW CREATE TABLE failed. This is a bit puzzling;
353+ # maybe the table got dropped, or crashed. Not much we can
354+ # do about it; If the table is missing, just PTDEBUG it, but
355+ # otherwise, warn with the error.
356+ if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
357+ PTDEBUG && _d("Skipping $table_name because it no longer exists");
358+ }
359+ else {
360+ warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
361+ }
362+ next;
363+ }
364 my $tbl_struct = $tp->parse($ddl);
365 if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
366 return {
367
368=== modified file 'lib/TableParser.pm'
369--- lib/TableParser.pm 2012-10-19 23:14:07 +0000
370+++ lib/TableParser.pm 2012-10-30 21:38:20 +0000
371@@ -82,18 +82,12 @@
372 PTDEBUG && _d($show_sql);
373 my $href;
374 eval { $href = $dbh->selectrow_hashref($show_sql); };
375- if ( $EVAL_ERROR ) {
376- # TODO: I think we fail silently for tools which may try to call
377- # this on temp tables, or don't care if the table goes away. We
378- # should warn $EVAL_ERROR and require callers to eval us and do
379- # what they want with the warning.
380- PTDEBUG && _d($EVAL_ERROR);
381-
382+ if ( my $e = $EVAL_ERROR ) {
383 # Restore old SQL mode.
384 PTDEBUG && _d($old_sql_mode);
385 $dbh->do($old_sql_mode);
386
387- return;
388+ die $e;
389 }
390
391 # Restore old SQL mode.
392
393=== modified file 't/lib/SchemaIterator.t'
394--- t/lib/SchemaIterator.t 2012-06-07 03:14:20 +0000
395+++ t/lib/SchemaIterator.t 2012-10-30 21:38:20 +0000
396@@ -9,7 +9,7 @@
397 use strict;
398 use warnings FATAL => 'all';
399 use English qw(-no_match_vars);
400-use Test::More tests => 30;
401+use Test::More;
402
403 use SchemaIterator;
404 use FileIterator;
405@@ -407,7 +407,75 @@
406 );
407
408 # #############################################################################
409+# Bug 1047335: pt-duplicate-key-checker fails when it encounters a crashed table
410+# https://bugs.launchpad.net/percona-toolkit/+bug/1047335
411+# #############################################################################
412+
413+use File::Spec;
414+
415+my $master3_port = 2900;
416+diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`);
417+diag(`$trunk/sandbox/start-sandbox master $master3_port >/dev/null`);
418+my $dbh3 = $sb->get_dbh_for("master3");
419+
420+$sb->load_file('master3', File::Spec->catfile(qw(t lib samples bug_1047335_crashed_table.sql)));
421+my $sth = $dbh3->prepare("INSERT INTO bug_1047335.crashed_table (trx_id, etc) VALUES(?, ?)");
422+$sth->execute($_, $_ x 100) for 1..1000;
423+$sth->finish();
424+
425+# Create the SI object before crashing the table
426+my $tmp_si = new SchemaIterator(
427+ dbh => $dbh3,
428+ OptionParser => $o,
429+ Quoter => $q,
430+ TableParser => $tp,
431+ # This is needed because the way we corrupt tables
432+ # accidentally removes the database from SHOW DATABASES
433+ db => 'bug_1047335',
434+ );
435+
436+my $master_basedir = File::Spec->catdir(File::Spec->tmpdir(), $master3_port);
437+my $db_dir = File::Spec->catdir($master_basedir, "data", "bug_1047335");
438+my $myi = glob(File::Spec->catfile($db_dir, "crashed_table.[Mm][Yy][Iy]"));
439+my $frm = glob(File::Spec->catfile($db_dir, "crashed_table.[Ff][Rr][Mm]"));
440+
441+die "Cannot find .myi file for crashed_table" unless $myi && -f $myi;
442+
443+# Truncate the .myi file to corrupt it
444+truncate($myi, 4096);
445+
446+use File::Slurp qw( prepend_file append_file write_file );
447+
448+# Corrupt the .frm file
449+open my $urand_fh, q{<}, "/dev/urandom"
450+ or die "Cannot open /dev/urandom";
451+prepend_file($frm, scalar(<$urand_fh>));
452+append_file($frm, scalar(<$urand_fh>));
453+close $urand_fh;
454+
455+$dbh3->do("FLUSH TABLES");
456+eval { $dbh3->do("SELECT etc FROM bug_1047335.crashed_table WHERE etc LIKE '10001' ORDER BY id ASC LIMIT 1") };
457+
458+my $w = '';
459+{
460+ local $SIG{__WARN__} = sub { $w .= shift };
461+ 1 while $tmp_si->next();
462+}
463+
464+like(
465+ $w,
466+ qr/because SHOW CREATE TABLE failed:/,
467+ "->next() gives a warning if ->get_create_table dies from a strange error",
468+);
469+
470+# This might fail. Doesn't matter -- stop_sandbox will just rm -rf the folder
471+eval { $dbh3->do("DROP DATABASE IF EXISTS bug_1047335") };
472+
473+diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`);
474+
475+# #############################################################################
476 # Done.
477 # #############################################################################
478 ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
479-exit;
480+
481+done_testing;
482
483=== modified file 't/lib/TableParser.t'
484--- t/lib/TableParser.t 2012-10-20 23:59:28 +0000
485+++ t/lib/TableParser.t 2012-10-30 21:38:20 +0000
486@@ -9,7 +9,7 @@
487 use strict;
488 use warnings FATAL => 'all';
489 use English qw(-no_match_vars);
490-use Test::More tests => 40;
491+use Test::More;
492
493 use TableParser;
494 use Quoter;
495@@ -32,10 +32,10 @@
496 skip 'Sandbox master does not have the sakila database', 2
497 unless @{$dbh->selectcol_arrayref("SHOW DATABASES LIKE 'sakila'")};
498
499- is(
500- $tp->get_create_table($dbh, 'sakila', 'FOO'),
501- undef,
502- "get_create_table(nonexistent table)"
503+ eval { $tp->get_create_table($dbh, 'sakila', 'FOO') };
504+ ok(
505+ $EVAL_ERROR,
506+ "get_create_table(nonexistent table) dies"
507 );
508
509 my $ddl = $tp->get_create_table($dbh, 'sakila', 'actor');
510@@ -893,8 +893,67 @@
511 );
512
513 # #############################################################################
514+# Bug 1047335: pt-duplicate-key-checker fails when it encounters a crashed table
515+# https://bugs.launchpad.net/percona-toolkit/+bug/1047335
516+# #############################################################################
517+
518+# We need to create a new server here, otherwise the whole test suite might die
519+# if the crashed table can't be dropped.
520+
521+use File::Spec;
522+
523+my $master3_port = 2900;
524+diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`);
525+diag(`$trunk/sandbox/start-sandbox master $master3_port >/dev/null`);
526+my $dbh3 = $sb->get_dbh_for("master3");
527+
528+$sb->load_file('master3', File::Spec->catfile(qw(t lib samples bug_1047335_crashed_table.sql)));
529+my $sth = $dbh3->prepare("INSERT INTO bug_1047335.crashed_table (trx_id, etc) VALUES(?, ?)");
530+$sth->execute($_, $_ x 100) for 1..1000;
531+$sth->finish();
532+
533+
534+my $master_basedir = File::Spec->catdir(File::Spec->tmpdir(), $master3_port);
535+my $db_dir = File::Spec->catdir($master_basedir, "data", "bug_1047335");
536+my $myi = glob(File::Spec->catfile($db_dir, "crashed_table.[Mm][Yy][Iy]"));
537+my $frm = glob(File::Spec->catfile($db_dir, "crashed_table.[Ff][Rr][Mm]"));
538+
539+die "Cannot find .myi file for crashed_table" unless $myi && -f $myi;
540+
541+# Truncate the .myi file to corrupt it
542+truncate($myi, 4096);
543+
544+# Corrupt the .frm file
545+open my $urand_fh, q{<}, "/dev/urandom"
546+ or die "Cannot open /dev/urandom: $OS_ERROR";
547+
548+open my $tmp_fh, q{>}, $frm
549+ or die "Cannot open $frm: $OS_ERROR";
550+print { $tmp_fh } scalar(<$urand_fh>), slurp_file($frm), scalar(<$urand_fh>);
551+close $tmp_fh;
552+
553+close $urand_fh;
554+
555+$dbh3->do("FLUSH TABLES");
556+eval { $dbh3->do("SELECT etc FROM bug_1047335.crashed_table WHERE etc LIKE '10001' ORDER BY id ASC LIMIT 1") };
557+
558+eval { $tp->get_create_table($dbh3, 'bug_1047335', 'crashed_table') };
559+ok(
560+ $EVAL_ERROR,
561+ "get_create_table dies if SHOW CREATE TABLE failed",
562+);
563+
564+# This might fail. Doesn't matter -- stop_sandbox will just rm -rf the folder
565+eval { $dbh3->do("DROP DATABASE IF EXISTS bug_1047335") };
566+
567+diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`);
568+
569+# #############################################################################
570 # Done.
571 # #############################################################################
572 $sb->wipe_clean($dbh) if $dbh;
573 ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
574+
575+done_testing;
576+
577 exit;
578
579=== added file 't/lib/samples/bug_1047335_crashed_table.sql'
580--- t/lib/samples/bug_1047335_crashed_table.sql 1970-01-01 00:00:00 +0000
581+++ t/lib/samples/bug_1047335_crashed_table.sql 2012-10-30 21:38:20 +0000
582@@ -0,0 +1,11 @@
583+DROP DATABASE IF EXISTS bug_1047335;
584+CREATE DATABASE bug_1047335;
585+USE bug_1047335;
586+CREATE TABLE bug_1047335.crashed_table (
587+ `id` int(10) unsigned NOT NULL auto_increment,
588+ `trx_id` int(10) unsigned default NULL,
589+ `etc` text,
590+ PRIMARY KEY (`id`),
591+ KEY `idx1` (`trx_id`),
592+ KEY `idx2` (`trx_id`, `etc`(128))
593+) ENGINE=MyISAM;

Subscribers

People subscribed via source and target branches