~percona-toolkit-dev/percona-toolkit/cant-nibble-bug-918056

« back to all changes in this revision

Viewing changes to lib/TableParser.pm

  • Committer: Daniel Nichter
  • Date: 2012-01-19 19:46:56 UTC
  • Revision ID: daniel@percona.com-20120119194656-3l1nzgtq1p7xvigo
Replace MKDEBUG with PTDEBUG in modules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
use strict;
35
35
use warnings FATAL => 'all';
36
36
use English qw(-no_match_vars);
37
 
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
 
37
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
38
38
 
39
39
use Data::Dumper;
40
40
$Data::Dumper::Indent    = 1;
62
62
           . q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), }
63
63
           . '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, '
64
64
           . '@@SQL_QUOTE_SHOW_CREATE := 1 */';
65
 
   MKDEBUG && _d($sql);
 
65
   PTDEBUG && _d($sql);
66
66
   eval { $dbh->do($sql); };
67
 
   MKDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
 
67
   PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
68
68
 
69
69
   # Must USE the tbl's db because some bug with SHOW CREATE TABLE on a
70
70
   # view when the current db isn't the view's db causes MySQL to crash.
71
71
   $sql = 'USE ' . $q->quote($db);
72
 
   MKDEBUG && _d($dbh, $sql);
 
72
   PTDEBUG && _d($dbh, $sql);
73
73
   $dbh->do($sql);
74
74
 
75
75
   $sql = "SHOW CREATE TABLE " . $q->quote($db, $tbl);
76
 
   MKDEBUG && _d($sql);
 
76
   PTDEBUG && _d($sql);
77
77
   my $href;
78
78
   eval { $href = $dbh->selectrow_hashref($sql); };
79
79
   if ( $EVAL_ERROR ) {
80
 
      MKDEBUG && _d($EVAL_ERROR);
 
80
      PTDEBUG && _d($EVAL_ERROR);
81
81
      return;
82
82
   }
83
83
 
84
84
   $sql = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, '
85
85
        . '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */';
86
 
   MKDEBUG && _d($sql);
 
86
   PTDEBUG && _d($sql);
87
87
   $dbh->do($sql);
88
88
 
89
89
   my ($key) = grep { m/create table/i } keys %$href;
90
90
   if ( $key ) {
91
 
      MKDEBUG && _d('This table is a base table');
 
91
      PTDEBUG && _d('This table is a base table');
92
92
      $href->{$key}  =~ s/\b[ ]{2,}/ /g;
93
93
      $href->{$key} .= "\n";
94
94
   }
95
95
   else {
96
 
      MKDEBUG && _d('This table is a view');
 
96
      PTDEBUG && _d('This table is a view');
97
97
      ($key) = grep { m/create view/i } keys %$href;
98
98
   }
99
99
 
125
125
 
126
126
   my @defs   = $ddl =~ m/^(\s+`.*?),?$/gm;
127
127
   my @cols   = map { $_ =~ m/`([^`]+)`/ } @defs;
128
 
   MKDEBUG && _d('Table cols:', join(', ', map { "`$_`" } @cols));
 
128
   PTDEBUG && _d('Table cols:', join(', ', map { "`$_`" } @cols));
129
129
 
130
130
   # Save the column definitions *exactly*
131
131
   my %def_for;
195
195
      }
196
196
      sort keys %{$tbl->{keys}};
197
197
 
198
 
   MKDEBUG && _d('Indexes sorted best-first:', join(', ', @indexes));
 
198
   PTDEBUG && _d('Indexes sorted best-first:', join(', ', @indexes));
199
199
   return @indexes;
200
200
}
201
201
 
218
218
         ($best) = $self->sort_indexes($tbl);
219
219
      }
220
220
   }
221
 
   MKDEBUG && _d('Best index found is', $best);
 
221
   PTDEBUG && _d('Best index found is', $best);
222
222
   return $best;
223
223
}
224
224
 
232
232
   return () unless $where;
233
233
   my $sql = 'EXPLAIN SELECT * FROM ' . $quoter->quote($database, $table)
234
234
      . ' WHERE ' . $where;
235
 
   MKDEBUG && _d($sql);
 
235
   PTDEBUG && _d($sql);
236
236
   my $expl = $dbh->selectrow_hashref($sql);
237
237
   # Normalize columns to lowercase
238
238
   $expl = { map { lc($_) => $expl->{$_} } keys %$expl };
239
239
   if ( $expl->{possible_keys} ) {
240
 
      MKDEBUG && _d('possible_keys =', $expl->{possible_keys});
 
240
      PTDEBUG && _d('possible_keys =', $expl->{possible_keys});
241
241
      my @candidates = split(',', $expl->{possible_keys});
242
242
      my %possible   = map { $_ => 1 } @candidates;
243
243
      if ( $expl->{key} ) {
244
 
         MKDEBUG && _d('MySQL chose', $expl->{key});
 
244
         PTDEBUG && _d('MySQL chose', $expl->{key});
245
245
         unshift @candidates, grep { $possible{$_} } split(',', $expl->{key});
246
 
         MKDEBUG && _d('Before deduping:', join(', ', @candidates));
 
246
         PTDEBUG && _d('Before deduping:', join(', ', @candidates));
247
247
         my %seen;
248
248
         @candidates = grep { !$seen{$_}++ } @candidates;
249
249
      }
250
 
      MKDEBUG && _d('Final list:', join(', ', @candidates));
 
250
      PTDEBUG && _d('Final list:', join(', ', @candidates));
251
251
      return @candidates;
252
252
   }
253
253
   else {
254
 
      MKDEBUG && _d('No keys in possible_keys');
 
254
      PTDEBUG && _d('No keys in possible_keys');
255
255
      return ();
256
256
   }
257
257
}
278
278
   my ($dbh, $db, $tbl) = @args{@required_args};
279
279
   my $q      = $self->{Quoter};
280
280
   my $db_tbl = $q->quote($db, $tbl);
281
 
   MKDEBUG && _d('Checking', $db_tbl);
 
281
   PTDEBUG && _d('Checking', $db_tbl);
282
282
 
283
283
   my $sql = "SHOW TABLES FROM " . $q->quote($db)
284
284
           . ' LIKE ' . $q->literal_like($tbl);
285
 
   MKDEBUG && _d($sql);
 
285
   PTDEBUG && _d($sql);
286
286
   my $row;
287
287
   eval {
288
288
      $row = $dbh->selectrow_arrayref($sql);
289
289
   };
290
290
   if ( $EVAL_ERROR ) {
291
 
      MKDEBUG && _d($EVAL_ERROR);
 
291
      PTDEBUG && _d($EVAL_ERROR);
292
292
      return 0;
293
293
   }
294
294
   if ( !$row->[0] || $row->[0] ne $tbl ) {
295
 
      MKDEBUG && _d('Table does not exist');
 
295
      PTDEBUG && _d('Table does not exist');
296
296
      return 0;
297
297
   }
298
298
 
299
299
   # Table exists, return true unless we have privs to check.
300
 
   MKDEBUG && _d('Table exists; no privs to check');
 
300
   PTDEBUG && _d('Table exists; no privs to check');
301
301
   return 1 unless $args{all_privs};
302
302
 
303
303
   # Get privs select,insert,update.
304
304
   $sql = "SHOW FULL COLUMNS FROM $db_tbl";
305
 
   MKDEBUG && _d($sql);
 
305
   PTDEBUG && _d($sql);
306
306
   eval {
307
307
      $row = $dbh->selectrow_hashref($sql);
308
308
   };
309
309
   if ( $EVAL_ERROR ) {
310
 
      MKDEBUG && _d($EVAL_ERROR);
 
310
      PTDEBUG && _d($EVAL_ERROR);
311
311
      return 0;
312
312
   }
313
313
   if ( !scalar keys %$row ) {
314
314
      # This should never happen.
315
 
      MKDEBUG && _d('Table has no columns:', Dumper($row));
 
315
      PTDEBUG && _d('Table has no columns:', Dumper($row));
316
316
      return 0;
317
317
   }
318
318
   my $privs = $row->{privileges} || $row->{Privileges};
319
319
 
320
320
   # Get delete priv since FULL COLUMNS doesn't show it.   
321
321
   $sql = "DELETE FROM $db_tbl LIMIT 0";
322
 
   MKDEBUG && _d($sql);
 
322
   PTDEBUG && _d($sql);
323
323
   eval {
324
324
      $dbh->do($sql);
325
325
   };
326
326
   my $can_delete = $EVAL_ERROR ? 0 : 1;
327
327
 
328
 
   MKDEBUG && _d('User privs on', $db_tbl, ':', $privs,
 
328
   PTDEBUG && _d('User privs on', $db_tbl, ':', $privs,
329
329
      ($can_delete ? 'delete' : ''));
330
330
 
331
331
   # Check that we have all privs.
332
332
   if ( !($privs =~ m/select/ && $privs =~ m/insert/ && $privs =~ m/update/
333
333
          && $can_delete) ) {
334
 
      MKDEBUG && _d('User does not have all privs');
 
334
      PTDEBUG && _d('User does not have all privs');
335
335
      return 0;
336
336
   }
337
337
 
338
 
   MKDEBUG && _d('User has all privs');
 
338
   PTDEBUG && _d('User has all privs');
339
339
   return 1;
340
340
}
341
341
 
342
342
sub get_engine {
343
343
   my ( $self, $ddl, $opts ) = @_;
344
344
   my ( $engine ) = $ddl =~ m/\).*?(?:ENGINE|TYPE)=(\w+)/;
345
 
   MKDEBUG && _d('Storage engine:', $engine);
 
345
   PTDEBUG && _d('Storage engine:', $engine);
346
346
   return $engine || undef;
347
347
}
348
348
 
380
380
      next KEY if $key =~ m/FOREIGN/;
381
381
 
382
382
      my $key_ddl = $key;
383
 
      MKDEBUG && _d('Parsed key:', $key_ddl);
 
383
      PTDEBUG && _d('Parsed key:', $key_ddl);
384
384
 
385
385
      # Make allowances for HASH bugs in SHOW CREATE TABLE.  A non-MEMORY table
386
386
      # will report its index as USING HASH even when this is not supported.
413
413
      }
414
414
      $name =~ s/`//g;
415
415
 
416
 
      MKDEBUG && _d( $name, 'key cols:', join(', ', map { "`$_`" } @cols));
 
416
      PTDEBUG && _d( $name, 'key cols:', join(', ', map { "`$_`" } @cols));
417
417
 
418
418
      $keys->{$name} = {
419
419
         name         => $name,
436
436
         elsif ( $this_key->{is_unique} && !$this_key->{is_nullable} ) {
437
437
            $clustered_key = $this_key->{name};
438
438
         }
439
 
         MKDEBUG && $clustered_key && _d('This key is the clustered key');
 
439
         PTDEBUG && $clustered_key && _d('This key is the clustered key');
440
440
      }
441
441
   }
442
442
 
497
497
      $sql .= ' LIKE ?';
498
498
      push @params, $like;
499
499
   }
500
 
   MKDEBUG && _d($sql, @params);
 
500
   PTDEBUG && _d($sql, @params);
501
501
   my $sth = $dbh->prepare($sql);
502
502
   eval { $sth->execute(@params); };
503
503
   if ($EVAL_ERROR) {
504
 
      MKDEBUG && _d($EVAL_ERROR);
 
504
      PTDEBUG && _d($EVAL_ERROR);
505
505
      return;
506
506
   }
507
507
   my @tables = @{$sth->fetchall_arrayref({})};