Merge lp:~percona-toolkit-dev/percona-toolkit/fix-deep-recursion-bug-1136559 into lp:~percona-toolkit-dev/percona-toolkit/release-2.2.4
- fix-deep-recursion-bug-1136559
- Merge into release-2.2.4
Proposed by
Daniel Nichter
Status: | Merged |
---|---|
Merged at revision: | 586 |
Proposed branch: | lp:~percona-toolkit-dev/percona-toolkit/fix-deep-recursion-bug-1136559 |
Merge into: | lp:~percona-toolkit-dev/percona-toolkit/release-2.2.4 |
Diff against target: |
854 lines (+510/-268) 8 files modified
bin/pt-duplicate-key-checker (+57/-52) bin/pt-index-usage (+57/-52) bin/pt-table-checksum (+57/-52) bin/pt-table-sync (+57/-52) lib/SchemaIterator.pm (+61/-58) t/lib/SchemaIterator.t (+16/-2) t/lib/samples/100-dbs-drop.sql (+100/-0) t/lib/samples/100-dbs.sql (+105/-0) |
To merge this branch: | bzr merge lp:~percona-toolkit-dev/percona-toolkit/fix-deep-recursion-bug-1136559 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Nichter | Approve | ||
Review via email: mp+171435@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Daniel Nichter (daniel-nichter) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bin/pt-duplicate-key-checker' |
2 | --- bin/pt-duplicate-key-checker 2013-06-25 22:32:19 +0000 |
3 | +++ bin/pt-duplicate-key-checker 2013-06-25 23:35:31 +0000 |
4 | @@ -3297,58 +3297,63 @@ |
5 | $self->{dbs} = \@dbs; |
6 | } |
7 | |
8 | - if ( !$self->{db} ) { |
9 | - $self->{db} = shift @{$self->{dbs}}; |
10 | - PTDEBUG && _d('Next database:', $self->{db}); |
11 | - return unless $self->{db}; |
12 | - } |
13 | - |
14 | - if ( !defined $self->{tbls} ) { |
15 | - my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
16 | - PTDEBUG && _d($sql); |
17 | - my @tbls = map { |
18 | - $_->[0]; # (tbl, type) |
19 | - } |
20 | - grep { |
21 | - my ($tbl, $type) = @$_; |
22 | - (!$type || ($type ne 'VIEW')) |
23 | - && $self->_resume_from_table($tbl) |
24 | - && $self->table_is_allowed($self->{db}, $tbl); |
25 | - } |
26 | - @{$dbh->selectall_arrayref($sql)}; |
27 | - PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db}); |
28 | - $self->{tbls} = \@tbls; |
29 | - } |
30 | - |
31 | - while ( my $tbl = shift @{$self->{tbls}} ) { |
32 | - my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
33 | - if ( my $e = $EVAL_ERROR ) { |
34 | - my $table_name = "$self->{db}.$tbl"; |
35 | - if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
36 | - PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
37 | - } |
38 | - else { |
39 | - warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
40 | - } |
41 | - next; |
42 | - } |
43 | - my $tbl_struct = $tp->parse($ddl); |
44 | - if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
45 | - return { |
46 | - db => $self->{db}, |
47 | - tbl => $tbl, |
48 | - name => $q->quote($self->{db}, $tbl), |
49 | - ddl => $ddl, |
50 | - tbl_struct => $tbl_struct, |
51 | - }; |
52 | - } |
53 | - } |
54 | - |
55 | - PTDEBUG && _d('No more tables in database', $self->{db}); |
56 | - $self->{db} = undef; |
57 | - $self->{tbls} = undef; |
58 | - |
59 | - return $self->_iterate_dbh(); |
60 | + DATABASE: |
61 | + while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) { |
62 | + if ( !$self->{db} ) { |
63 | + PTDEBUG && _d('Next database:', $db); |
64 | + $self->{db} = $db; |
65 | + } |
66 | + |
67 | + if ( !$self->{tbls} ) { |
68 | + my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
69 | + PTDEBUG && _d($sql); |
70 | + my @tbls = map { |
71 | + $_->[0]; # (tbl, type) |
72 | + } |
73 | + grep { |
74 | + my ($tbl, $type) = @$_; |
75 | + (!$type || ($type ne 'VIEW')) |
76 | + && $self->_resume_from_table($tbl) |
77 | + && $self->table_is_allowed($self->{db}, $tbl); |
78 | + } |
79 | + @{$dbh->selectall_arrayref($sql)}; |
80 | + PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db}); |
81 | + $self->{tbls} = \@tbls; |
82 | + } |
83 | + |
84 | + TABLE: |
85 | + while ( my $tbl = shift @{$self->{tbls}} ) { |
86 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
87 | + if ( my $e = $EVAL_ERROR ) { |
88 | + my $table_name = "$self->{db}.$tbl"; |
89 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
90 | + PTDEBUG && _d("$table_name no longer exists"); |
91 | + } |
92 | + else { |
93 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
94 | + } |
95 | + next TABLE; |
96 | + } |
97 | + |
98 | + my $tbl_struct = $tp->parse($ddl); |
99 | + if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
100 | + return { |
101 | + db => $self->{db}, |
102 | + tbl => $tbl, |
103 | + name => $q->quote($self->{db}, $tbl), |
104 | + ddl => $ddl, |
105 | + tbl_struct => $tbl_struct, |
106 | + }; |
107 | + } |
108 | + } |
109 | + |
110 | + PTDEBUG && _d('No more tables in database', $self->{db}); |
111 | + $self->{db} = undef; |
112 | + $self->{tbls} = undef; |
113 | + } # DATABASE |
114 | + |
115 | + PTDEBUG && _d('No more databases'); |
116 | + return; |
117 | } |
118 | |
119 | sub database_is_allowed { |
120 | |
121 | === modified file 'bin/pt-index-usage' |
122 | --- bin/pt-index-usage 2013-06-25 22:32:19 +0000 |
123 | +++ bin/pt-index-usage 2013-06-25 23:35:31 +0000 |
124 | @@ -4131,58 +4131,63 @@ |
125 | $self->{dbs} = \@dbs; |
126 | } |
127 | |
128 | - if ( !$self->{db} ) { |
129 | - $self->{db} = shift @{$self->{dbs}}; |
130 | - PTDEBUG && _d('Next database:', $self->{db}); |
131 | - return unless $self->{db}; |
132 | - } |
133 | - |
134 | - if ( !defined $self->{tbls} ) { |
135 | - my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
136 | - PTDEBUG && _d($sql); |
137 | - my @tbls = map { |
138 | - $_->[0]; # (tbl, type) |
139 | - } |
140 | - grep { |
141 | - my ($tbl, $type) = @$_; |
142 | - (!$type || ($type ne 'VIEW')) |
143 | - && $self->_resume_from_table($tbl) |
144 | - && $self->table_is_allowed($self->{db}, $tbl); |
145 | - } |
146 | - @{$dbh->selectall_arrayref($sql)}; |
147 | - PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db}); |
148 | - $self->{tbls} = \@tbls; |
149 | - } |
150 | - |
151 | - while ( my $tbl = shift @{$self->{tbls}} ) { |
152 | - my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
153 | - if ( my $e = $EVAL_ERROR ) { |
154 | - my $table_name = "$self->{db}.$tbl"; |
155 | - if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
156 | - PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
157 | - } |
158 | - else { |
159 | - warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
160 | - } |
161 | - next; |
162 | - } |
163 | - my $tbl_struct = $tp->parse($ddl); |
164 | - if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
165 | - return { |
166 | - db => $self->{db}, |
167 | - tbl => $tbl, |
168 | - name => $q->quote($self->{db}, $tbl), |
169 | - ddl => $ddl, |
170 | - tbl_struct => $tbl_struct, |
171 | - }; |
172 | - } |
173 | - } |
174 | - |
175 | - PTDEBUG && _d('No more tables in database', $self->{db}); |
176 | - $self->{db} = undef; |
177 | - $self->{tbls} = undef; |
178 | - |
179 | - return $self->_iterate_dbh(); |
180 | + DATABASE: |
181 | + while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) { |
182 | + if ( !$self->{db} ) { |
183 | + PTDEBUG && _d('Next database:', $db); |
184 | + $self->{db} = $db; |
185 | + } |
186 | + |
187 | + if ( !$self->{tbls} ) { |
188 | + my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
189 | + PTDEBUG && _d($sql); |
190 | + my @tbls = map { |
191 | + $_->[0]; # (tbl, type) |
192 | + } |
193 | + grep { |
194 | + my ($tbl, $type) = @$_; |
195 | + (!$type || ($type ne 'VIEW')) |
196 | + && $self->_resume_from_table($tbl) |
197 | + && $self->table_is_allowed($self->{db}, $tbl); |
198 | + } |
199 | + @{$dbh->selectall_arrayref($sql)}; |
200 | + PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db}); |
201 | + $self->{tbls} = \@tbls; |
202 | + } |
203 | + |
204 | + TABLE: |
205 | + while ( my $tbl = shift @{$self->{tbls}} ) { |
206 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
207 | + if ( my $e = $EVAL_ERROR ) { |
208 | + my $table_name = "$self->{db}.$tbl"; |
209 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
210 | + PTDEBUG && _d("$table_name no longer exists"); |
211 | + } |
212 | + else { |
213 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
214 | + } |
215 | + next TABLE; |
216 | + } |
217 | + |
218 | + my $tbl_struct = $tp->parse($ddl); |
219 | + if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
220 | + return { |
221 | + db => $self->{db}, |
222 | + tbl => $tbl, |
223 | + name => $q->quote($self->{db}, $tbl), |
224 | + ddl => $ddl, |
225 | + tbl_struct => $tbl_struct, |
226 | + }; |
227 | + } |
228 | + } |
229 | + |
230 | + PTDEBUG && _d('No more tables in database', $self->{db}); |
231 | + $self->{db} = undef; |
232 | + $self->{tbls} = undef; |
233 | + } # DATABASE |
234 | + |
235 | + PTDEBUG && _d('No more databases'); |
236 | + return; |
237 | } |
238 | |
239 | sub database_is_allowed { |
240 | |
241 | === modified file 'bin/pt-table-checksum' |
242 | --- bin/pt-table-checksum 2013-06-25 22:32:19 +0000 |
243 | +++ bin/pt-table-checksum 2013-06-25 23:35:31 +0000 |
244 | @@ -7344,58 +7344,63 @@ |
245 | $self->{dbs} = \@dbs; |
246 | } |
247 | |
248 | - if ( !$self->{db} ) { |
249 | - $self->{db} = shift @{$self->{dbs}}; |
250 | - PTDEBUG && _d('Next database:', $self->{db}); |
251 | - return unless $self->{db}; |
252 | - } |
253 | - |
254 | - if ( !defined $self->{tbls} ) { |
255 | - my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
256 | - PTDEBUG && _d($sql); |
257 | - my @tbls = map { |
258 | - $_->[0]; # (tbl, type) |
259 | - } |
260 | - grep { |
261 | - my ($tbl, $type) = @$_; |
262 | - (!$type || ($type ne 'VIEW')) |
263 | - && $self->_resume_from_table($tbl) |
264 | - && $self->table_is_allowed($self->{db}, $tbl); |
265 | - } |
266 | - @{$dbh->selectall_arrayref($sql)}; |
267 | - PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db}); |
268 | - $self->{tbls} = \@tbls; |
269 | - } |
270 | - |
271 | - while ( my $tbl = shift @{$self->{tbls}} ) { |
272 | - my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
273 | - if ( my $e = $EVAL_ERROR ) { |
274 | - my $table_name = "$self->{db}.$tbl"; |
275 | - if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
276 | - PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
277 | - } |
278 | - else { |
279 | - warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
280 | - } |
281 | - next; |
282 | - } |
283 | - my $tbl_struct = $tp->parse($ddl); |
284 | - if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
285 | - return { |
286 | - db => $self->{db}, |
287 | - tbl => $tbl, |
288 | - name => $q->quote($self->{db}, $tbl), |
289 | - ddl => $ddl, |
290 | - tbl_struct => $tbl_struct, |
291 | - }; |
292 | - } |
293 | - } |
294 | - |
295 | - PTDEBUG && _d('No more tables in database', $self->{db}); |
296 | - $self->{db} = undef; |
297 | - $self->{tbls} = undef; |
298 | - |
299 | - return $self->_iterate_dbh(); |
300 | + DATABASE: |
301 | + while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) { |
302 | + if ( !$self->{db} ) { |
303 | + PTDEBUG && _d('Next database:', $db); |
304 | + $self->{db} = $db; |
305 | + } |
306 | + |
307 | + if ( !$self->{tbls} ) { |
308 | + my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
309 | + PTDEBUG && _d($sql); |
310 | + my @tbls = map { |
311 | + $_->[0]; # (tbl, type) |
312 | + } |
313 | + grep { |
314 | + my ($tbl, $type) = @$_; |
315 | + (!$type || ($type ne 'VIEW')) |
316 | + && $self->_resume_from_table($tbl) |
317 | + && $self->table_is_allowed($self->{db}, $tbl); |
318 | + } |
319 | + @{$dbh->selectall_arrayref($sql)}; |
320 | + PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db}); |
321 | + $self->{tbls} = \@tbls; |
322 | + } |
323 | + |
324 | + TABLE: |
325 | + while ( my $tbl = shift @{$self->{tbls}} ) { |
326 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
327 | + if ( my $e = $EVAL_ERROR ) { |
328 | + my $table_name = "$self->{db}.$tbl"; |
329 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
330 | + PTDEBUG && _d("$table_name no longer exists"); |
331 | + } |
332 | + else { |
333 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
334 | + } |
335 | + next TABLE; |
336 | + } |
337 | + |
338 | + my $tbl_struct = $tp->parse($ddl); |
339 | + if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
340 | + return { |
341 | + db => $self->{db}, |
342 | + tbl => $tbl, |
343 | + name => $q->quote($self->{db}, $tbl), |
344 | + ddl => $ddl, |
345 | + tbl_struct => $tbl_struct, |
346 | + }; |
347 | + } |
348 | + } |
349 | + |
350 | + PTDEBUG && _d('No more tables in database', $self->{db}); |
351 | + $self->{db} = undef; |
352 | + $self->{tbls} = undef; |
353 | + } # DATABASE |
354 | + |
355 | + PTDEBUG && _d('No more databases'); |
356 | + return; |
357 | } |
358 | |
359 | sub database_is_allowed { |
360 | |
361 | === modified file 'bin/pt-table-sync' |
362 | --- bin/pt-table-sync 2013-06-25 22:32:19 +0000 |
363 | +++ bin/pt-table-sync 2013-06-25 23:35:31 +0000 |
364 | @@ -7690,58 +7690,63 @@ |
365 | $self->{dbs} = \@dbs; |
366 | } |
367 | |
368 | - if ( !$self->{db} ) { |
369 | - $self->{db} = shift @{$self->{dbs}}; |
370 | - PTDEBUG && _d('Next database:', $self->{db}); |
371 | - return unless $self->{db}; |
372 | - } |
373 | - |
374 | - if ( !defined $self->{tbls} ) { |
375 | - my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
376 | - PTDEBUG && _d($sql); |
377 | - my @tbls = map { |
378 | - $_->[0]; # (tbl, type) |
379 | - } |
380 | - grep { |
381 | - my ($tbl, $type) = @$_; |
382 | - (!$type || ($type ne 'VIEW')) |
383 | - && $self->_resume_from_table($tbl) |
384 | - && $self->table_is_allowed($self->{db}, $tbl); |
385 | - } |
386 | - @{$dbh->selectall_arrayref($sql)}; |
387 | - PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db}); |
388 | - $self->{tbls} = \@tbls; |
389 | - } |
390 | - |
391 | - while ( my $tbl = shift @{$self->{tbls}} ) { |
392 | - my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
393 | - if ( my $e = $EVAL_ERROR ) { |
394 | - my $table_name = "$self->{db}.$tbl"; |
395 | - if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
396 | - PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
397 | - } |
398 | - else { |
399 | - warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
400 | - } |
401 | - next; |
402 | - } |
403 | - my $tbl_struct = $tp->parse($ddl); |
404 | - if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
405 | - return { |
406 | - db => $self->{db}, |
407 | - tbl => $tbl, |
408 | - name => $q->quote($self->{db}, $tbl), |
409 | - ddl => $ddl, |
410 | - tbl_struct => $tbl_struct, |
411 | - }; |
412 | - } |
413 | - } |
414 | - |
415 | - PTDEBUG && _d('No more tables in database', $self->{db}); |
416 | - $self->{db} = undef; |
417 | - $self->{tbls} = undef; |
418 | - |
419 | - return $self->_iterate_dbh(); |
420 | + DATABASE: |
421 | + while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) { |
422 | + if ( !$self->{db} ) { |
423 | + PTDEBUG && _d('Next database:', $db); |
424 | + $self->{db} = $db; |
425 | + } |
426 | + |
427 | + if ( !$self->{tbls} ) { |
428 | + my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
429 | + PTDEBUG && _d($sql); |
430 | + my @tbls = map { |
431 | + $_->[0]; # (tbl, type) |
432 | + } |
433 | + grep { |
434 | + my ($tbl, $type) = @$_; |
435 | + (!$type || ($type ne 'VIEW')) |
436 | + && $self->_resume_from_table($tbl) |
437 | + && $self->table_is_allowed($self->{db}, $tbl); |
438 | + } |
439 | + @{$dbh->selectall_arrayref($sql)}; |
440 | + PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db}); |
441 | + $self->{tbls} = \@tbls; |
442 | + } |
443 | + |
444 | + TABLE: |
445 | + while ( my $tbl = shift @{$self->{tbls}} ) { |
446 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
447 | + if ( my $e = $EVAL_ERROR ) { |
448 | + my $table_name = "$self->{db}.$tbl"; |
449 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
450 | + PTDEBUG && _d("$table_name no longer exists"); |
451 | + } |
452 | + else { |
453 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
454 | + } |
455 | + next TABLE; |
456 | + } |
457 | + |
458 | + my $tbl_struct = $tp->parse($ddl); |
459 | + if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
460 | + return { |
461 | + db => $self->{db}, |
462 | + tbl => $tbl, |
463 | + name => $q->quote($self->{db}, $tbl), |
464 | + ddl => $ddl, |
465 | + tbl_struct => $tbl_struct, |
466 | + }; |
467 | + } |
468 | + } |
469 | + |
470 | + PTDEBUG && _d('No more tables in database', $self->{db}); |
471 | + $self->{db} = undef; |
472 | + $self->{tbls} = undef; |
473 | + } # DATABASE |
474 | + |
475 | + PTDEBUG && _d('No more databases'); |
476 | + return; |
477 | } |
478 | |
479 | sub database_is_allowed { |
480 | |
481 | === modified file 'lib/SchemaIterator.pm' |
482 | --- lib/SchemaIterator.pm 2013-01-03 00:19:16 +0000 |
483 | +++ lib/SchemaIterator.pm 2013-06-25 23:35:31 +0000 |
484 | @@ -334,64 +334,67 @@ |
485 | $self->{dbs} = \@dbs; |
486 | } |
487 | |
488 | - if ( !$self->{db} ) { |
489 | - $self->{db} = shift @{$self->{dbs}}; |
490 | - PTDEBUG && _d('Next database:', $self->{db}); |
491 | - return unless $self->{db}; |
492 | - } |
493 | - |
494 | - if ( !defined $self->{tbls} ) { |
495 | - my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
496 | - PTDEBUG && _d($sql); |
497 | - my @tbls = map { |
498 | - $_->[0]; # (tbl, type) |
499 | - } |
500 | - grep { |
501 | - my ($tbl, $type) = @$_; |
502 | - (!$type || ($type ne 'VIEW')) |
503 | - && $self->_resume_from_table($tbl) |
504 | - && $self->table_is_allowed($self->{db}, $tbl); |
505 | - } |
506 | - @{$dbh->selectall_arrayref($sql)}; |
507 | - PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db}); |
508 | - $self->{tbls} = \@tbls; |
509 | - } |
510 | - |
511 | - while ( my $tbl = shift @{$self->{tbls}} ) { |
512 | - my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
513 | - if ( my $e = $EVAL_ERROR ) { |
514 | - my $table_name = "$self->{db}.$tbl"; |
515 | - # SHOW CREATE TABLE failed. This is a bit puzzling; |
516 | - # maybe the table got dropped, or crashed. Not much we can |
517 | - # do about it; If the table is missing, just PTDEBUG it, but |
518 | - # otherwise, warn with the error. |
519 | - if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
520 | - PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
521 | - } |
522 | - else { |
523 | - warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
524 | - } |
525 | - next; |
526 | - } |
527 | - my $tbl_struct = $tp->parse($ddl); |
528 | - if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
529 | - return { |
530 | - db => $self->{db}, |
531 | - tbl => $tbl, |
532 | - name => $q->quote($self->{db}, $tbl), |
533 | - ddl => $ddl, |
534 | - tbl_struct => $tbl_struct, |
535 | - }; |
536 | - } |
537 | - } |
538 | - |
539 | - PTDEBUG && _d('No more tables in database', $self->{db}); |
540 | - $self->{db} = undef; |
541 | - $self->{tbls} = undef; |
542 | - |
543 | - # Recurse to get the next database. If there's no next db, then the |
544 | - # call will return undef and we'll return undef, too. |
545 | - return $self->_iterate_dbh(); |
546 | + DATABASE: |
547 | + while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) { |
548 | + if ( !$self->{db} ) { |
549 | + PTDEBUG && _d('Next database:', $db); |
550 | + $self->{db} = $db; |
551 | + } |
552 | + |
553 | + if ( !$self->{tbls} ) { |
554 | + my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db}); |
555 | + PTDEBUG && _d($sql); |
556 | + my @tbls = map { |
557 | + $_->[0]; # (tbl, type) |
558 | + } |
559 | + grep { |
560 | + my ($tbl, $type) = @$_; |
561 | + (!$type || ($type ne 'VIEW')) |
562 | + && $self->_resume_from_table($tbl) |
563 | + && $self->table_is_allowed($self->{db}, $tbl); |
564 | + } |
565 | + @{$dbh->selectall_arrayref($sql)}; |
566 | + PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db}); |
567 | + $self->{tbls} = \@tbls; |
568 | + } |
569 | + |
570 | + TABLE: |
571 | + while ( my $tbl = shift @{$self->{tbls}} ) { |
572 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
573 | + if ( my $e = $EVAL_ERROR ) { |
574 | + my $table_name = "$self->{db}.$tbl"; |
575 | + # SHOW CREATE TABLE failed. This is a bit puzzling; |
576 | + # maybe the table got dropped, or crashed. Not much we can |
577 | + # do about it; If the table is missing, just PTDEBUG it, but |
578 | + # otherwise, warn with the error. |
579 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
580 | + PTDEBUG && _d("$table_name no longer exists"); |
581 | + } |
582 | + else { |
583 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
584 | + } |
585 | + next TABLE; |
586 | + } |
587 | + |
588 | + my $tbl_struct = $tp->parse($ddl); |
589 | + if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
590 | + return { |
591 | + db => $self->{db}, |
592 | + tbl => $tbl, |
593 | + name => $q->quote($self->{db}, $tbl), |
594 | + ddl => $ddl, |
595 | + tbl_struct => $tbl_struct, |
596 | + }; |
597 | + } |
598 | + } |
599 | + |
600 | + PTDEBUG && _d('No more tables in database', $self->{db}); |
601 | + $self->{db} = undef; |
602 | + $self->{tbls} = undef; |
603 | + } # DATABASE |
604 | + |
605 | + PTDEBUG && _d('No more databases'); |
606 | + return; |
607 | } |
608 | |
609 | sub database_is_allowed { |
610 | |
611 | === modified file 't/lib/SchemaIterator.t' |
612 | --- t/lib/SchemaIterator.t 2012-12-07 18:52:33 +0000 |
613 | +++ t/lib/SchemaIterator.t 2013-06-25 23:35:31 +0000 |
614 | @@ -548,9 +548,23 @@ |
615 | diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`); |
616 | |
617 | # ############################################################################# |
618 | +# Bug 1136559: Deep recursion on subroutine "SchemaIterator::_iterate_dbh" |
619 | +# ############################################################################# |
620 | + |
621 | +$sb->wipe_clean($dbh); |
622 | +diag(`/tmp/12345/use < $trunk/t/lib/samples/100-dbs.sql`); |
623 | + |
624 | +test_so( |
625 | + filters => [], |
626 | + result => "foo001.bar001 ", |
627 | + lives_ok => 1, |
628 | + test_name => "Bug 1136559: Deep recursion on subroutine SchemaIterator::_iterate_dbh", |
629 | +); |
630 | + |
631 | +diag(`/tmp/12345/use < $trunk/t/lib/samples/100-dbs-drop.sql`); |
632 | + |
633 | +# ############################################################################# |
634 | # Done. |
635 | # ############################################################################# |
636 | ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); |
637 | - |
638 | done_testing; |
639 | -exit; |
640 | |
641 | === added file 't/lib/samples/100-dbs-drop.sql' |
642 | --- t/lib/samples/100-dbs-drop.sql 1970-01-01 00:00:00 +0000 |
643 | +++ t/lib/samples/100-dbs-drop.sql 2013-06-25 23:35:31 +0000 |
644 | @@ -0,0 +1,100 @@ |
645 | +DROP DATABASE IF EXISTS foo001; |
646 | +DROP DATABASE IF EXISTS foo002; |
647 | +DROP DATABASE IF EXISTS foo003; |
648 | +DROP DATABASE IF EXISTS foo004; |
649 | +DROP DATABASE IF EXISTS foo005; |
650 | +DROP DATABASE IF EXISTS foo006; |
651 | +DROP DATABASE IF EXISTS foo007; |
652 | +DROP DATABASE IF EXISTS foo008; |
653 | +DROP DATABASE IF EXISTS foo009; |
654 | +DROP DATABASE IF EXISTS foo010; |
655 | +DROP DATABASE IF EXISTS foo011; |
656 | +DROP DATABASE IF EXISTS foo012; |
657 | +DROP DATABASE IF EXISTS foo013; |
658 | +DROP DATABASE IF EXISTS foo014; |
659 | +DROP DATABASE IF EXISTS foo015; |
660 | +DROP DATABASE IF EXISTS foo016; |
661 | +DROP DATABASE IF EXISTS foo017; |
662 | +DROP DATABASE IF EXISTS foo018; |
663 | +DROP DATABASE IF EXISTS foo019; |
664 | +DROP DATABASE IF EXISTS foo020; |
665 | +DROP DATABASE IF EXISTS foo021; |
666 | +DROP DATABASE IF EXISTS foo022; |
667 | +DROP DATABASE IF EXISTS foo023; |
668 | +DROP DATABASE IF EXISTS foo024; |
669 | +DROP DATABASE IF EXISTS foo025; |
670 | +DROP DATABASE IF EXISTS foo026; |
671 | +DROP DATABASE IF EXISTS foo027; |
672 | +DROP DATABASE IF EXISTS foo028; |
673 | +DROP DATABASE IF EXISTS foo029; |
674 | +DROP DATABASE IF EXISTS foo030; |
675 | +DROP DATABASE IF EXISTS foo031; |
676 | +DROP DATABASE IF EXISTS foo032; |
677 | +DROP DATABASE IF EXISTS foo033; |
678 | +DROP DATABASE IF EXISTS foo034; |
679 | +DROP DATABASE IF EXISTS foo035; |
680 | +DROP DATABASE IF EXISTS foo036; |
681 | +DROP DATABASE IF EXISTS foo037; |
682 | +DROP DATABASE IF EXISTS foo038; |
683 | +DROP DATABASE IF EXISTS foo039; |
684 | +DROP DATABASE IF EXISTS foo040; |
685 | +DROP DATABASE IF EXISTS foo041; |
686 | +DROP DATABASE IF EXISTS foo042; |
687 | +DROP DATABASE IF EXISTS foo043; |
688 | +DROP DATABASE IF EXISTS foo044; |
689 | +DROP DATABASE IF EXISTS foo045; |
690 | +DROP DATABASE IF EXISTS foo046; |
691 | +DROP DATABASE IF EXISTS foo047; |
692 | +DROP DATABASE IF EXISTS foo048; |
693 | +DROP DATABASE IF EXISTS foo049; |
694 | +DROP DATABASE IF EXISTS foo050; |
695 | +DROP DATABASE IF EXISTS foo051; |
696 | +DROP DATABASE IF EXISTS foo052; |
697 | +DROP DATABASE IF EXISTS foo053; |
698 | +DROP DATABASE IF EXISTS foo054; |
699 | +DROP DATABASE IF EXISTS foo055; |
700 | +DROP DATABASE IF EXISTS foo056; |
701 | +DROP DATABASE IF EXISTS foo057; |
702 | +DROP DATABASE IF EXISTS foo058; |
703 | +DROP DATABASE IF EXISTS foo059; |
704 | +DROP DATABASE IF EXISTS foo060; |
705 | +DROP DATABASE IF EXISTS foo061; |
706 | +DROP DATABASE IF EXISTS foo062; |
707 | +DROP DATABASE IF EXISTS foo063; |
708 | +DROP DATABASE IF EXISTS foo064; |
709 | +DROP DATABASE IF EXISTS foo065; |
710 | +DROP DATABASE IF EXISTS foo066; |
711 | +DROP DATABASE IF EXISTS foo067; |
712 | +DROP DATABASE IF EXISTS foo068; |
713 | +DROP DATABASE IF EXISTS foo069; |
714 | +DROP DATABASE IF EXISTS foo070; |
715 | +DROP DATABASE IF EXISTS foo071; |
716 | +DROP DATABASE IF EXISTS foo072; |
717 | +DROP DATABASE IF EXISTS foo073; |
718 | +DROP DATABASE IF EXISTS foo074; |
719 | +DROP DATABASE IF EXISTS foo075; |
720 | +DROP DATABASE IF EXISTS foo076; |
721 | +DROP DATABASE IF EXISTS foo077; |
722 | +DROP DATABASE IF EXISTS foo078; |
723 | +DROP DATABASE IF EXISTS foo079; |
724 | +DROP DATABASE IF EXISTS foo080; |
725 | +DROP DATABASE IF EXISTS foo081; |
726 | +DROP DATABASE IF EXISTS foo082; |
727 | +DROP DATABASE IF EXISTS foo083; |
728 | +DROP DATABASE IF EXISTS foo084; |
729 | +DROP DATABASE IF EXISTS foo085; |
730 | +DROP DATABASE IF EXISTS foo086; |
731 | +DROP DATABASE IF EXISTS foo087; |
732 | +DROP DATABASE IF EXISTS foo088; |
733 | +DROP DATABASE IF EXISTS foo089; |
734 | +DROP DATABASE IF EXISTS foo090; |
735 | +DROP DATABASE IF EXISTS foo091; |
736 | +DROP DATABASE IF EXISTS foo092; |
737 | +DROP DATABASE IF EXISTS foo093; |
738 | +DROP DATABASE IF EXISTS foo094; |
739 | +DROP DATABASE IF EXISTS foo095; |
740 | +DROP DATABASE IF EXISTS foo096; |
741 | +DROP DATABASE IF EXISTS foo097; |
742 | +DROP DATABASE IF EXISTS foo098; |
743 | +DROP DATABASE IF EXISTS foo099; |
744 | +DROP DATABASE IF EXISTS foo100; |
745 | |
746 | === added file 't/lib/samples/100-dbs.sql' |
747 | --- t/lib/samples/100-dbs.sql 1970-01-01 00:00:00 +0000 |
748 | +++ t/lib/samples/100-dbs.sql 2013-06-25 23:35:31 +0000 |
749 | @@ -0,0 +1,105 @@ |
750 | +CREATE DATABASE IF NOT EXISTS foo001; |
751 | +CREATE DATABASE IF NOT EXISTS foo002; |
752 | +CREATE DATABASE IF NOT EXISTS foo003; |
753 | +CREATE DATABASE IF NOT EXISTS foo004; |
754 | +CREATE DATABASE IF NOT EXISTS foo005; |
755 | +CREATE DATABASE IF NOT EXISTS foo006; |
756 | +CREATE DATABASE IF NOT EXISTS foo007; |
757 | +CREATE DATABASE IF NOT EXISTS foo008; |
758 | +CREATE DATABASE IF NOT EXISTS foo009; |
759 | +CREATE DATABASE IF NOT EXISTS foo010; |
760 | +CREATE DATABASE IF NOT EXISTS foo011; |
761 | +CREATE DATABASE IF NOT EXISTS foo012; |
762 | +CREATE DATABASE IF NOT EXISTS foo013; |
763 | +CREATE DATABASE IF NOT EXISTS foo014; |
764 | +CREATE DATABASE IF NOT EXISTS foo015; |
765 | +CREATE DATABASE IF NOT EXISTS foo016; |
766 | +CREATE DATABASE IF NOT EXISTS foo017; |
767 | +CREATE DATABASE IF NOT EXISTS foo018; |
768 | +CREATE DATABASE IF NOT EXISTS foo019; |
769 | +CREATE DATABASE IF NOT EXISTS foo020; |
770 | +CREATE DATABASE IF NOT EXISTS foo021; |
771 | +CREATE DATABASE IF NOT EXISTS foo022; |
772 | +CREATE DATABASE IF NOT EXISTS foo023; |
773 | +CREATE DATABASE IF NOT EXISTS foo024; |
774 | +CREATE DATABASE IF NOT EXISTS foo025; |
775 | +CREATE DATABASE IF NOT EXISTS foo026; |
776 | +CREATE DATABASE IF NOT EXISTS foo027; |
777 | +CREATE DATABASE IF NOT EXISTS foo028; |
778 | +CREATE DATABASE IF NOT EXISTS foo029; |
779 | +CREATE DATABASE IF NOT EXISTS foo030; |
780 | +CREATE DATABASE IF NOT EXISTS foo031; |
781 | +CREATE DATABASE IF NOT EXISTS foo032; |
782 | +CREATE DATABASE IF NOT EXISTS foo033; |
783 | +CREATE DATABASE IF NOT EXISTS foo034; |
784 | +CREATE DATABASE IF NOT EXISTS foo035; |
785 | +CREATE DATABASE IF NOT EXISTS foo036; |
786 | +CREATE DATABASE IF NOT EXISTS foo037; |
787 | +CREATE DATABASE IF NOT EXISTS foo038; |
788 | +CREATE DATABASE IF NOT EXISTS foo039; |
789 | +CREATE DATABASE IF NOT EXISTS foo040; |
790 | +CREATE DATABASE IF NOT EXISTS foo041; |
791 | +CREATE DATABASE IF NOT EXISTS foo042; |
792 | +CREATE DATABASE IF NOT EXISTS foo043; |
793 | +CREATE DATABASE IF NOT EXISTS foo044; |
794 | +CREATE DATABASE IF NOT EXISTS foo045; |
795 | +CREATE DATABASE IF NOT EXISTS foo046; |
796 | +CREATE DATABASE IF NOT EXISTS foo047; |
797 | +CREATE DATABASE IF NOT EXISTS foo048; |
798 | +CREATE DATABASE IF NOT EXISTS foo049; |
799 | +CREATE DATABASE IF NOT EXISTS foo050; |
800 | +CREATE DATABASE IF NOT EXISTS foo051; |
801 | +CREATE DATABASE IF NOT EXISTS foo052; |
802 | +CREATE DATABASE IF NOT EXISTS foo053; |
803 | +CREATE DATABASE IF NOT EXISTS foo054; |
804 | +CREATE DATABASE IF NOT EXISTS foo055; |
805 | +CREATE DATABASE IF NOT EXISTS foo056; |
806 | +CREATE DATABASE IF NOT EXISTS foo057; |
807 | +CREATE DATABASE IF NOT EXISTS foo058; |
808 | +CREATE DATABASE IF NOT EXISTS foo059; |
809 | +CREATE DATABASE IF NOT EXISTS foo060; |
810 | +CREATE DATABASE IF NOT EXISTS foo061; |
811 | +CREATE DATABASE IF NOT EXISTS foo062; |
812 | +CREATE DATABASE IF NOT EXISTS foo063; |
813 | +CREATE DATABASE IF NOT EXISTS foo064; |
814 | +CREATE DATABASE IF NOT EXISTS foo065; |
815 | +CREATE DATABASE IF NOT EXISTS foo066; |
816 | +CREATE DATABASE IF NOT EXISTS foo067; |
817 | +CREATE DATABASE IF NOT EXISTS foo068; |
818 | +CREATE DATABASE IF NOT EXISTS foo069; |
819 | +CREATE DATABASE IF NOT EXISTS foo070; |
820 | +CREATE DATABASE IF NOT EXISTS foo071; |
821 | +CREATE DATABASE IF NOT EXISTS foo072; |
822 | +CREATE DATABASE IF NOT EXISTS foo073; |
823 | +CREATE DATABASE IF NOT EXISTS foo074; |
824 | +CREATE DATABASE IF NOT EXISTS foo075; |
825 | +CREATE DATABASE IF NOT EXISTS foo076; |
826 | +CREATE DATABASE IF NOT EXISTS foo077; |
827 | +CREATE DATABASE IF NOT EXISTS foo078; |
828 | +CREATE DATABASE IF NOT EXISTS foo079; |
829 | +CREATE DATABASE IF NOT EXISTS foo080; |
830 | +CREATE DATABASE IF NOT EXISTS foo081; |
831 | +CREATE DATABASE IF NOT EXISTS foo082; |
832 | +CREATE DATABASE IF NOT EXISTS foo083; |
833 | +CREATE DATABASE IF NOT EXISTS foo084; |
834 | +CREATE DATABASE IF NOT EXISTS foo085; |
835 | +CREATE DATABASE IF NOT EXISTS foo086; |
836 | +CREATE DATABASE IF NOT EXISTS foo087; |
837 | +CREATE DATABASE IF NOT EXISTS foo088; |
838 | +CREATE DATABASE IF NOT EXISTS foo089; |
839 | +CREATE DATABASE IF NOT EXISTS foo090; |
840 | +CREATE DATABASE IF NOT EXISTS foo091; |
841 | +CREATE DATABASE IF NOT EXISTS foo092; |
842 | +CREATE DATABASE IF NOT EXISTS foo093; |
843 | +CREATE DATABASE IF NOT EXISTS foo094; |
844 | +CREATE DATABASE IF NOT EXISTS foo095; |
845 | +CREATE DATABASE IF NOT EXISTS foo096; |
846 | +CREATE DATABASE IF NOT EXISTS foo097; |
847 | +CREATE DATABASE IF NOT EXISTS foo098; |
848 | +CREATE DATABASE IF NOT EXISTS foo099; |
849 | +CREATE DATABASE IF NOT EXISTS foo100; |
850 | +CREATE TABLE IF NOT EXISTS foo001.bar001 ( |
851 | + `id` int unsigned NOT NULL AUTO_INCREMENT, |
852 | + `value` varchar(255) NOT NULL, |
853 | + PRIMARY KEY (`id`) |
854 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8; |