2393
2464
# ###########################################################################
2395
2466
# ###########################################################################
2397
# This package is a copy without comments from the original. The original
2398
# with comments and its test file can be found in the Bazaar repository at,
2401
# See https://launchpad.net/percona-toolkit for more information.
2402
# ###########################################################################
2407
use warnings FATAL => 'all';
2408
use English qw(-no_match_vars);
2409
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
2411
( our $before = <<'EOF') =~ s/^ //gm;
2412
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
2413
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
2414
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
2415
/*!40101 SET NAMES utf8 */;
2416
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
2417
/*!40103 SET TIME_ZONE='+00:00' */;
2418
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
2419
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
2420
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
2421
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
2424
( our $after = <<'EOF') =~ s/^ //gm;
2425
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
2426
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
2427
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
2428
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
2429
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
2430
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
2431
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
2432
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
2436
my ( $class, %args ) = @_;
2438
cache => 0, # Afaik no script uses this cache any longer because
2440
return bless $self, $class;
2444
my ( $self, $dbh, $quoter, $db, $tbl, $what ) = @_;
2446
if ( $what eq 'table' ) {
2447
my $ddl = $self->get_create_table($dbh, $quoter, $db, $tbl);
2449
if ( $ddl->[0] eq 'table' ) {
2451
. 'DROP TABLE IF EXISTS ' . $quoter->quote($tbl) . ";\n"
2452
. $ddl->[1] . ";\n";
2455
return 'DROP TABLE IF EXISTS ' . $quoter->quote($tbl) . ";\n"
2456
. '/*!50001 DROP VIEW IF EXISTS '
2457
. $quoter->quote($tbl) . "*/;\n/*!50001 "
2458
. $self->get_tmp_table($dbh, $quoter, $db, $tbl) . "*/;\n";
2461
elsif ( $what eq 'triggers' ) {
2462
my $trgs = $self->get_triggers($dbh, $quoter, $db, $tbl);
2463
if ( $trgs && @$trgs ) {
2464
my $result = $before . "\nDELIMITER ;;\n";
2465
foreach my $trg ( @$trgs ) {
2466
if ( $trg->{sql_mode} ) {
2467
$result .= qq{/*!50003 SET SESSION SQL_MODE='$trg->{sql_mode}' */;;\n};
2469
$result .= "/*!50003 CREATE */ ";
2470
if ( $trg->{definer} ) {
2472
= map { s/'/''/g; "'$_'"; }
2473
split('@', $trg->{definer}, 2);
2474
$result .= "/*!50017 DEFINER=$user\@$host */ ";
2476
$result .= sprintf("/*!50003 TRIGGER %s %s %s ON %s\nFOR EACH ROW %s */;;\n\n",
2477
$quoter->quote($trg->{trigger}),
2478
@{$trg}{qw(timing event)},
2479
$quoter->quote($trg->{table}),
2482
$result .= "DELIMITER ;\n\n/*!50003 SET SESSION SQL_MODE=\@OLD_SQL_MODE */;\n\n";
2489
elsif ( $what eq 'view' ) {
2490
my $ddl = $self->get_create_table($dbh, $quoter, $db, $tbl);
2491
return '/*!50001 DROP TABLE IF EXISTS ' . $quoter->quote($tbl) . "*/;\n"
2492
. '/*!50001 DROP VIEW IF EXISTS ' . $quoter->quote($tbl) . "*/;\n"
2493
. '/*!50001 ' . $ddl->[1] . "*/;\n";
2496
die "You didn't say what to dump.";
2501
my ( $self, $dbh, $quoter, $new ) = @_;
2503
PTDEBUG && _d('No new DB to use');
2506
my $sql = 'USE ' . $quoter->quote($new);
2507
PTDEBUG && _d($dbh, $sql);
2512
sub get_create_table {
2513
my ( $self, $dbh, $quoter, $db, $tbl ) = @_;
2514
if ( !$self->{cache} || !$self->{tables}->{$db}->{$tbl} ) {
2515
my $sql = '/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, '
2516
. q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), }
2517
. '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, '
2518
. '@@SQL_QUOTE_SHOW_CREATE := 1 */';
2519
PTDEBUG && _d($sql);
2520
eval { $dbh->do($sql); };
2521
PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
2522
$self->_use_db($dbh, $quoter, $db);
2523
$sql = "SHOW CREATE TABLE " . $quoter->quote($db, $tbl);
2524
PTDEBUG && _d($sql);
2526
eval { $href = $dbh->selectrow_hashref($sql); };
2527
if ( $EVAL_ERROR ) {
2528
warn "Failed to $sql. The table may be damaged.\nError: $EVAL_ERROR";
2532
$sql = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, '
2533
. '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */';
2534
PTDEBUG && _d($sql);
2536
my ($key) = grep { m/create table/i } keys %$href;
2538
PTDEBUG && _d('This table is a base table');
2539
$self->{tables}->{$db}->{$tbl} = [ 'table', $href->{$key} ];
2542
PTDEBUG && _d('This table is a view');
2543
($key) = grep { m/create view/i } keys %$href;
2544
$self->{tables}->{$db}->{$tbl} = [ 'view', $href->{$key} ];
2547
return $self->{tables}->{$db}->{$tbl};
2551
my ( $self, $dbh, $quoter, $db, $tbl ) = @_;
2552
PTDEBUG && _d('Get columns for', $db, $tbl);
2553
if ( !$self->{cache} || !$self->{columns}->{$db}->{$tbl} ) {
2554
$self->_use_db($dbh, $quoter, $db);
2555
my $sql = "SHOW COLUMNS FROM " . $quoter->quote($db, $tbl);
2556
PTDEBUG && _d($sql);
2557
my $cols = $dbh->selectall_arrayref($sql, { Slice => {} });
2559
$self->{columns}->{$db}->{$tbl} = [
2562
@row{ map { lc $_ } keys %$_ } = values %$_;
2567
return $self->{columns}->{$db}->{$tbl};
2571
my ( $self, $dbh, $quoter, $db, $tbl ) = @_;
2572
my $result = 'CREATE TABLE ' . $quoter->quote($tbl) . " (\n";
2573
$result .= join(",\n",
2574
map { ' ' . $quoter->quote($_->{field}) . ' ' . $_->{type} }
2575
@{$self->get_columns($dbh, $quoter, $db, $tbl)});
2577
PTDEBUG && _d($result);
2582
my ( $self, $dbh, $quoter, $db, $tbl ) = @_;
2583
if ( !$self->{cache} || !$self->{triggers}->{$db} ) {
2584
$self->{triggers}->{$db} = {};
2585
my $sql = '/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, '
2586
. q{@@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), }
2587
. '@OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, '
2588
. '@@SQL_QUOTE_SHOW_CREATE := 1 */';
2589
PTDEBUG && _d($sql);
2590
eval { $dbh->do($sql); };
2591
PTDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
2592
$sql = "SHOW TRIGGERS FROM " . $quoter->quote($db);
2593
PTDEBUG && _d($sql);
2594
my $sth = $dbh->prepare($sql);
2597
my $trgs = $sth->fetchall_arrayref({});
2598
foreach my $trg (@$trgs) {
2600
@trg{ map { lc $_ } keys %$trg } = values %$trg;
2601
push @{ $self->{triggers}->{$db}->{ $trg{table} } }, \%trg;
2604
$sql = '/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, '
2605
. '@@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */';
2606
PTDEBUG && _d($sql);
2610
return $self->{triggers}->{$db}->{$tbl};
2612
return values %{$self->{triggers}->{$db}};
2616
my ( $self, $dbh, $quoter, $like ) = @_;
2617
if ( !$self->{cache} || !$self->{databases} || $like ) {
2618
my $sql = 'SHOW DATABASES';
2622
push @params, $like;
2624
my $sth = $dbh->prepare($sql);
2625
PTDEBUG && _d($sql, @params);
2626
$sth->execute( @params );
2627
my @dbs = map { $_->[0] } @{$sth->fetchall_arrayref()};
2628
$self->{databases} = \@dbs unless $like;
2631
return @{$self->{databases}};
2634
sub get_table_status {
2635
my ( $self, $dbh, $quoter, $db, $like ) = @_;
2636
if ( !$self->{cache} || !$self->{table_status}->{$db} || $like ) {
2637
my $sql = "SHOW TABLE STATUS FROM " . $quoter->quote($db);
2641
push @params, $like;
2643
PTDEBUG && _d($sql, @params);
2644
my $sth = $dbh->prepare($sql);
2645
$sth->execute(@params);
2646
my @tables = @{$sth->fetchall_arrayref({})};
2648
my %tbl; # Make a copy with lowercased keys
2649
@tbl{ map { lc $_ } keys %$_ } = values %$_;
2650
$tbl{engine} ||= $tbl{type} || $tbl{comment};
2654
$self->{table_status}->{$db} = \@tables unless $like;
2657
return @{$self->{table_status}->{$db}};
2660
sub get_table_list {
2661
my ( $self, $dbh, $quoter, $db, $like ) = @_;
2662
if ( !$self->{cache} || !$self->{table_list}->{$db} || $like ) {
2663
my $sql = "SHOW /*!50002 FULL*/ TABLES FROM " . $quoter->quote($db);
2667
push @params, $like;
2669
PTDEBUG && _d($sql, @params);
2670
my $sth = $dbh->prepare($sql);
2671
$sth->execute(@params);
2672
my @tables = @{$sth->fetchall_arrayref()};
2676
engine => ($_->[1] || '') eq 'VIEW' ? 'VIEW' : '',
2680
$self->{table_list}->{$db} = \@tables unless $like;
2683
return @{$self->{table_list}->{$db}};
2687
my ($package, undef, $line) = caller 0;
2688
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
2689
map { defined $_ ? $_ : 'undef' }
2691
print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
2696
# ###########################################################################
2697
# End MySQLDump package
2698
# ###########################################################################
2700
# ###########################################################################
2701
2467
# TableChunker package
2702
2468
# This package is a copy without comments from the original. The original
2703
2469
# with comments and its test file can be found in the Bazaar repository at,