mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-04 03:26:19 +00:00
Re-update modules in pt-table-sync and pt-table-checksum but keep old SchemaIterator.
This commit is contained in:
@@ -9,26 +9,26 @@ use warnings FATAL => 'all';
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
# ###########################################################################
|
||||
# TableParser package 7156
|
||||
# TableParser package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/TableParser.pm
|
||||
# trunk/common/t/TableParser.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/TableParser.pm
|
||||
# t/lib/TableParser.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
|
||||
{
|
||||
package TableParser;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
use Data::Dumper;
|
||||
$Data::Dumper::Indent = 1;
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
$Data::Dumper::Quotekeys = 0;
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(Quoter);
|
||||
@@ -319,6 +319,7 @@ sub get_keys {
|
||||
|
||||
sub get_fks {
|
||||
my ( $self, $ddl, $opts ) = @_;
|
||||
my $q = $self->{Quoter};
|
||||
my $fks = {};
|
||||
|
||||
foreach my $fk (
|
||||
@@ -328,17 +329,22 @@ sub get_fks {
|
||||
my ( $cols ) = $fk =~ m/FOREIGN KEY \(([^\)]+)\)/;
|
||||
my ( $parent, $parent_cols ) = $fk =~ m/REFERENCES (\S+) \(([^\)]+)\)/;
|
||||
|
||||
my ($db, $tbl) = $q->split_unquote($parent, $opts->{database});
|
||||
my %parent_tbl = (tbl => $tbl);
|
||||
$parent_tbl{db} = $db if $db;
|
||||
|
||||
if ( $parent !~ m/\./ && $opts->{database} ) {
|
||||
$parent = "`$opts->{database}`.$parent";
|
||||
$parent = $q->quote($opts->{database}) . ".$parent";
|
||||
}
|
||||
|
||||
$fks->{$name} = {
|
||||
name => $name,
|
||||
colnames => $cols,
|
||||
cols => [ map { s/[ `]+//g; $_; } split(',', $cols) ],
|
||||
parent_tbl => $parent,
|
||||
parent_colnames=> $parent_cols,
|
||||
parent_tbl => \%parent_tbl,
|
||||
parent_tblname => $parent,
|
||||
parent_cols => [ map { s/[ `]+//g; $_; } split(',', $parent_cols) ],
|
||||
parent_colnames=> $parent_cols,
|
||||
ddl => $fk,
|
||||
};
|
||||
}
|
||||
@@ -398,28 +404,29 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End TableParser package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# TableChecksum package 7080
|
||||
# TableChecksum package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/TableChecksum.pm
|
||||
# trunk/common/t/TableChecksum.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/TableChecksum.pm
|
||||
# t/lib/TableChecksum.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
package TableChecksum;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use List::Util qw(max);
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
use List::Util qw(max);
|
||||
|
||||
our %ALGOS = (
|
||||
CHECKSUM => { pref => 0, hash => 0 },
|
||||
BIT_XOR => { pref => 2, hash => 1 },
|
||||
@@ -780,28 +787,28 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End TableChecksum package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# OptionParser package 7102
|
||||
# OptionParser package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/OptionParser.pm
|
||||
# trunk/common/t/OptionParser.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/OptionParser.pm
|
||||
# t/lib/OptionParser.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
|
||||
{
|
||||
package OptionParser;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use List::Util qw(max);
|
||||
use English qw(-no_match_vars);
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
use List::Util qw(max);
|
||||
use Getopt::Long;
|
||||
|
||||
my $POD_link_re = '[LC]<"?([^">]+)"?>';
|
||||
@@ -851,9 +858,9 @@ sub new {
|
||||
defaults_to => {}, # rule: opt defaults to value of other opt
|
||||
DSNParser => undef,
|
||||
default_files => [
|
||||
"/etc/maatkit/maatkit.conf",
|
||||
"/etc/maatkit/$program_name.conf",
|
||||
"$home/.maatkit.conf",
|
||||
"/etc/percona-toolkit/percona-toolkit.conf",
|
||||
"/etc/percona-toolkit/$program_name.conf",
|
||||
"$home/.percona-toolkit.conf",
|
||||
"$home/.$program_name.conf",
|
||||
],
|
||||
types => {
|
||||
@@ -1801,20 +1808,20 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End OptionParser package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# DSNParser package 7388
|
||||
# DSNParser package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/DSNParser.pm
|
||||
# trunk/common/t/DSNParser.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/DSNParser.pm
|
||||
# t/lib/DSNParser.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
|
||||
{
|
||||
package DSNParser;
|
||||
|
||||
use strict;
|
||||
@@ -1831,7 +1838,6 @@ eval {
|
||||
};
|
||||
my $have_dbi = $EVAL_ERROR ? 0 : 1;
|
||||
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
foreach my $arg ( qw(opts) ) {
|
||||
@@ -2028,8 +2034,8 @@ sub get_dbh {
|
||||
my $dbh;
|
||||
my $tries = 2;
|
||||
while ( !$dbh && $tries-- ) {
|
||||
MKDEBUG && _d($cxn_string, ' ', $user, ' ', $pass, ' {',
|
||||
join(', ', map { "$_=>$defaults->{$_}" } keys %$defaults ), '}');
|
||||
MKDEBUG && _d($cxn_string, ' ', $user, ' ', $pass,
|
||||
join(', ', map { "$_=>$defaults->{$_}" } keys %$defaults ));
|
||||
|
||||
eval {
|
||||
$dbh = DBI->connect($cxn_string, $user, $pass, $defaults);
|
||||
@@ -2158,26 +2164,25 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End DSNParser package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# VersionParser package 6667
|
||||
# VersionParser package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/VersionParser.pm
|
||||
# trunk/common/t/VersionParser.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/VersionParser.pm
|
||||
# t/lib/VersionParser.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
package VersionParser;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
@@ -2242,26 +2247,25 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End VersionParser package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# MySQLDump package 6345
|
||||
# MySQLDump package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/MySQLDump.pm
|
||||
# trunk/common/t/MySQLDump.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/MySQLDump.pm
|
||||
# t/lib/MySQLDump.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
package MySQLDump;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
( our $before = <<'EOF') =~ s/^ //gm;
|
||||
@@ -2548,20 +2552,20 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End MySQLDump package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# TableChunker package 7169
|
||||
# TableChunker package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/TableChunker.pm
|
||||
# trunk/common/t/TableChunker.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/TableChunker.pm
|
||||
# t/lib/TableChunker.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
|
||||
{
|
||||
package TableChunker;
|
||||
|
||||
use strict;
|
||||
@@ -3481,26 +3485,25 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End TableChunker package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# Quoter package 6850
|
||||
# Quoter package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/Quoter.pm
|
||||
# trunk/common/t/Quoter.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/Quoter.pm
|
||||
# t/lib/Quoter.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
|
||||
{
|
||||
package Quoter;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
@@ -3559,7 +3562,7 @@ sub join_quote {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End Quoter package
|
||||
# ###########################################################################
|
||||
@@ -4178,23 +4181,22 @@ sub _d {
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# Daemon package 6255
|
||||
# Daemon package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/Daemon.pm
|
||||
# trunk/common/t/Daemon.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/Daemon.pm
|
||||
# t/lib/Daemon.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
|
||||
{
|
||||
package Daemon;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
use POSIX qw(setsid);
|
||||
use English qw(-no_match_vars);
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
@@ -4359,18 +4361,14 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End Daemon package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# SchemaIterator package 7512
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/SchemaIterator.pm
|
||||
# trunk/common/t/SchemaIterator.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# SchemaIterator r7512
|
||||
# Don't update this package!
|
||||
# ###########################################################################
|
||||
package SchemaIterator;
|
||||
|
||||
@@ -4740,13 +4738,14 @@ sub _d {
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# Retry package 7473
|
||||
# Retry package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/Retry.pm
|
||||
# trunk/common/t/Retry.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/Retry.pm
|
||||
# t/lib/Retry.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
package Retry;
|
||||
|
||||
use strict;
|
||||
@@ -4817,30 +4816,25 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End Retry package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# Progress package 7096
|
||||
# Progress package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the SVN repository at,
|
||||
# trunk/common/Progress.pm
|
||||
# trunk/common/t/Progress.t
|
||||
# See http://code.google.com/p/maatkit/wiki/Developers for more information.
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/Progress.pm
|
||||
# t/lib/Progress.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
package Progress;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
|
||||
use English qw(-no_match_vars);
|
||||
use Data::Dumper;
|
||||
$Data::Dumper::Indent = 1;
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
$Data::Dumper::Quotekeys = 0;
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
@@ -4963,7 +4957,7 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
}
|
||||
# ###########################################################################
|
||||
# End Progress package
|
||||
# ###########################################################################
|
||||
@@ -6584,7 +6578,7 @@ sub do_tbl_replicate {
|
||||
foreach my $warning ( @$warnings ) {
|
||||
if ( $warning->{message} =~ m/Data truncated for column 'boundaries'/ ) {
|
||||
_d("Warning: WHERE clause too large for boundaries column; ",
|
||||
"mk-table-sync may fail; value:", $where);
|
||||
"pt-table-sync may fail; value:", $where);
|
||||
}
|
||||
elsif ( ($warning->{code} || 0) == 1592 ) {
|
||||
# Error: 1592 SQLSTATE: HY000 (ER_BINLOG_UNSAFE_STATEMENT)
|
||||
@@ -7124,7 +7118,7 @@ Or,
|
||||
|
||||
Or,
|
||||
|
||||
pt-table-checksum host1 host2 ... hostN | mk-checksum-filter
|
||||
pt-table-checksum host1 host2 ... hostN | pt-checksum-filter
|
||||
|
||||
See L<"SPECIFYING HOSTS"> for more on the syntax of the host arguments.
|
||||
|
||||
@@ -7173,7 +7167,7 @@ on the same server, just checksum both databases:
|
||||
|
||||
pt-table-checksum --databases db1,db2
|
||||
|
||||
You can then use L<mk-checksum-filter> to compare the results in both databases
|
||||
You can then use L<pt-checksum-filter> to compare the results in both databases
|
||||
easily.
|
||||
|
||||
pt-table-checksum examines table structure only on the first host specified,
|
||||
@@ -7403,7 +7397,7 @@ Output is unsorted, though all lines for one table should be output together.
|
||||
For speed, all checksums are done in parallel (as much as possible) and may
|
||||
complete out of the order in which they were started. You might want to run
|
||||
them through another script or command-line utility to make sure they are in the
|
||||
order you want. If you pipe the output through L<mk-checksum-filter>, you
|
||||
order you want. If you pipe the output through L<pt-checksum-filter>, you
|
||||
can sort the output and/or avoid seeing output about tables that have no
|
||||
differences.
|
||||
|
||||
@@ -8167,8 +8161,8 @@ L<"--replicate-check"> option, pt-table-checksum can run the query for you to
|
||||
make it even easier. See L<"CONSISTENT CHECKSUMS"> for details.
|
||||
|
||||
If you find tables that have differences, you can use the chunk boundaries in a
|
||||
WHERE clause with L<mk-table-sync> to help repair them more efficiently. See
|
||||
L<mk-table-sync> for details.
|
||||
WHERE clause with L<pt-table-sync> to help repair them more efficiently. See
|
||||
L<pt-table-sync> for details.
|
||||
|
||||
The table must have at least these columns: db, tbl, chunk, boundaries,
|
||||
this_crc, master_crc, this_cnt, master_cnt. The table may be named anything you
|
||||
@@ -8597,7 +8591,7 @@ These DSN options are used to create a DSN. Each option is given like
|
||||
C<option=value>. The options are case-sensitive, so P and p are not the
|
||||
same option. There cannot be whitespace before or after the C<=> and
|
||||
if the value contains whitespace it must be quoted. DSN options are
|
||||
comma-separated. See the L<maatkit> manpage for full details.
|
||||
comma-separated. See the L<percona-toolkit> manpage for full details.
|
||||
|
||||
=over
|
||||
|
||||
|
@@ -6587,376 +6587,292 @@ sub _d {
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# SchemaIterator package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/SchemaIterator.pm
|
||||
# t/lib/SchemaIterator.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# SchemaIterator r7141
|
||||
# Don't update this package!
|
||||
# ###########################################################################
|
||||
{
|
||||
package SchemaIterator;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
use English qw(-no_match_vars);
|
||||
use Data::Dumper;
|
||||
$Data::Dumper::Indent = 1;
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
$Data::Dumper::Quotekeys = 0;
|
||||
|
||||
my $open_comment = qr{/\*!\d{5} };
|
||||
my $tbl_name = qr{
|
||||
CREATE\s+
|
||||
(?:TEMPORARY\s+)?
|
||||
TABLE\s+
|
||||
(?:IF NOT EXISTS\s+)?
|
||||
([^\(]+)
|
||||
}x;
|
||||
|
||||
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(OptionParser Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
foreach my $arg ( qw(Quoter) ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
|
||||
my ($file_itr, $dbh) = @args{qw(file_itr dbh)};
|
||||
die "I need either a dbh or file_itr argument"
|
||||
if (!$dbh && !$file_itr) || ($dbh && $file_itr);
|
||||
|
||||
my $self = {
|
||||
%args,
|
||||
filters => _make_filters(%args),
|
||||
filter => undef,
|
||||
dbs => [],
|
||||
};
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub _make_filters {
|
||||
my ( %args ) = @_;
|
||||
my @required_args = qw(OptionParser Quoter);
|
||||
sub make_filter {
|
||||
my ( $self, $o ) = @_;
|
||||
my @lines = (
|
||||
'sub {',
|
||||
' my ( $dbh, $db, $tbl ) = @_;',
|
||||
' my $engine = undef;',
|
||||
);
|
||||
|
||||
|
||||
my @permit_dbs = _make_filter('unless', '$db', $o->get('databases'))
|
||||
if $o->has('databases');
|
||||
my @reject_dbs = _make_filter('if', '$db', $o->get('ignore-databases'))
|
||||
if $o->has('ignore-databases');
|
||||
my @dbs_regex;
|
||||
if ( $o->has('databases-regex') && (my $p = $o->get('databases-regex')) ) {
|
||||
push @dbs_regex, " return 0 unless \$db && (\$db =~ m/$p/o);";
|
||||
}
|
||||
my @reject_dbs_regex;
|
||||
if ( $o->has('ignore-databases-regex')
|
||||
&& (my $p = $o->get('ignore-databases-regex')) ) {
|
||||
push @reject_dbs_regex, " return 0 if \$db && (\$db =~ m/$p/o);";
|
||||
}
|
||||
if ( @permit_dbs || @reject_dbs || @dbs_regex || @reject_dbs_regex ) {
|
||||
push @lines,
|
||||
' if ( $db ) {',
|
||||
(@permit_dbs ? @permit_dbs : ()),
|
||||
(@reject_dbs ? @reject_dbs : ()),
|
||||
(@dbs_regex ? @dbs_regex : ()),
|
||||
(@reject_dbs_regex ? @reject_dbs_regex : ()),
|
||||
' }';
|
||||
}
|
||||
|
||||
if ( $o->has('tables') || $o->has('ignore-tables')
|
||||
|| $o->has('ignore-tables-regex') ) {
|
||||
|
||||
my $have_qtbl = 0;
|
||||
my $have_only_qtbls = 0;
|
||||
my %qtbls;
|
||||
|
||||
my @permit_tbls;
|
||||
my @permit_qtbls;
|
||||
my %permit_qtbls;
|
||||
if ( $o->get('tables') ) {
|
||||
my %tbls;
|
||||
map {
|
||||
if ( $_ =~ m/\./ ) {
|
||||
$permit_qtbls{$_} = 1;
|
||||
}
|
||||
else {
|
||||
$tbls{$_} = 1;
|
||||
}
|
||||
} keys %{ $o->get('tables') };
|
||||
@permit_tbls = _make_filter('unless', '$tbl', \%tbls);
|
||||
@permit_qtbls = _make_filter('unless', '$qtbl', \%permit_qtbls);
|
||||
|
||||
if ( @permit_qtbls ) {
|
||||
push @lines,
|
||||
' my $qtbl = ($db ? "$db." : "") . ($tbl ? $tbl : "");';
|
||||
$have_qtbl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
my @reject_tbls;
|
||||
my @reject_qtbls;
|
||||
my %reject_qtbls;
|
||||
if ( $o->get('ignore-tables') ) {
|
||||
my %tbls;
|
||||
map {
|
||||
if ( $_ =~ m/\./ ) {
|
||||
$reject_qtbls{$_} = 1;
|
||||
}
|
||||
else {
|
||||
$tbls{$_} = 1;
|
||||
}
|
||||
} keys %{ $o->get('ignore-tables') };
|
||||
@reject_tbls= _make_filter('if', '$tbl', \%tbls);
|
||||
@reject_qtbls = _make_filter('if', '$qtbl', \%reject_qtbls);
|
||||
|
||||
if ( @reject_qtbls && !$have_qtbl ) {
|
||||
push @lines,
|
||||
' my $qtbl = ($db ? "$db." : "") . ($tbl ? $tbl : "");';
|
||||
}
|
||||
}
|
||||
|
||||
if ( keys %permit_qtbls && !@permit_dbs ) {
|
||||
my $dbs = {};
|
||||
map {
|
||||
my ($db, undef) = split(/\./, $_);
|
||||
$dbs->{$db} = 1;
|
||||
} keys %permit_qtbls;
|
||||
MKDEBUG && _d('Adding restriction "--databases',
|
||||
(join(',', keys %$dbs) . '"'));
|
||||
if ( keys %$dbs ) {
|
||||
$o->set('databases', $dbs);
|
||||
return $self->make_filter($o);
|
||||
}
|
||||
}
|
||||
|
||||
my @tbls_regex;
|
||||
if ( $o->has('tables-regex') && (my $p = $o->get('tables-regex')) ) {
|
||||
push @tbls_regex, " return 0 unless \$tbl && (\$tbl =~ m/$p/o);";
|
||||
}
|
||||
my @reject_tbls_regex;
|
||||
if ( $o->has('ignore-tables-regex')
|
||||
&& (my $p = $o->get('ignore-tables-regex')) ) {
|
||||
push @reject_tbls_regex,
|
||||
" return 0 if \$tbl && (\$tbl =~ m/$p/o);";
|
||||
}
|
||||
|
||||
my @get_eng;
|
||||
my @permit_engs;
|
||||
my @reject_engs;
|
||||
if ( ($o->has('engines') && $o->get('engines'))
|
||||
|| ($o->has('ignore-engines') && $o->get('ignore-engines')) ) {
|
||||
push @get_eng,
|
||||
' my $sql = "SHOW TABLE STATUS "',
|
||||
' . ($db ? "FROM `$db`" : "")',
|
||||
' . " LIKE \'$tbl\'";',
|
||||
' MKDEBUG && _d($sql);',
|
||||
' eval {',
|
||||
' $engine = $dbh->selectrow_hashref($sql)->{engine};',
|
||||
' };',
|
||||
' MKDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);',
|
||||
' MKDEBUG && _d($tbl, "uses engine", $engine);',
|
||||
' $engine = lc $engine if $engine;',
|
||||
@permit_engs
|
||||
= _make_filter('unless', '$engine', $o->get('engines'), 1);
|
||||
@reject_engs
|
||||
= _make_filter('if', '$engine', $o->get('ignore-engines'), 1)
|
||||
}
|
||||
|
||||
if ( @permit_tbls || @permit_qtbls || @reject_tbls || @tbls_regex
|
||||
|| @reject_tbls_regex || @permit_engs || @reject_engs ) {
|
||||
push @lines,
|
||||
' if ( $tbl ) {',
|
||||
(@permit_tbls ? @permit_tbls : ()),
|
||||
(@reject_tbls ? @reject_tbls : ()),
|
||||
(@tbls_regex ? @tbls_regex : ()),
|
||||
(@reject_tbls_regex ? @reject_tbls_regex : ()),
|
||||
(@permit_qtbls ? @permit_qtbls : ()),
|
||||
(@reject_qtbls ? @reject_qtbls : ()),
|
||||
(@get_eng ? @get_eng : ()),
|
||||
(@permit_engs ? @permit_engs : ()),
|
||||
(@reject_engs ? @reject_engs : ()),
|
||||
' }';
|
||||
}
|
||||
}
|
||||
|
||||
push @lines,
|
||||
' MKDEBUG && _d(\'Passes filters:\', $db, $tbl, $engine, $dbh);',
|
||||
' return 1;', '}';
|
||||
|
||||
my $code = join("\n", @lines);
|
||||
MKDEBUG && _d('filter sub:', $code);
|
||||
my $filter_sub= eval $code
|
||||
or die "Error compiling subroutine code:\n$code\n$EVAL_ERROR";
|
||||
|
||||
return $filter_sub;
|
||||
}
|
||||
|
||||
sub set_filter {
|
||||
my ( $self, $filter_sub ) = @_;
|
||||
$self->{filter} = $filter_sub;
|
||||
MKDEBUG && _d('Set filter sub');
|
||||
return;
|
||||
}
|
||||
|
||||
sub get_db_itr {
|
||||
my ( $self, %args ) = @_;
|
||||
my @required_args = qw(dbh);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($o, $q) = @args{@required_args};
|
||||
my ($dbh) = @args{@required_args};
|
||||
|
||||
my %filters;
|
||||
|
||||
|
||||
my @simple_filters = qw(
|
||||
databases tables engines
|
||||
ignore-databases ignore-tables ignore-engines);
|
||||
FILTER:
|
||||
foreach my $filter ( @simple_filters ) {
|
||||
if ( $o->has($filter) ) {
|
||||
my $objs = $o->get($filter);
|
||||
next FILTER unless $objs && scalar keys %$objs;
|
||||
my $is_table = $filter =~ m/table/ ? 1 : 0;
|
||||
foreach my $obj ( keys %$objs ) {
|
||||
die "Undefined value for --$filter" unless $obj;
|
||||
$obj = lc $obj;
|
||||
if ( $is_table ) {
|
||||
my ($db, $tbl) = $q->split_unquote($obj);
|
||||
$db ||= '*';
|
||||
MKDEBUG && _d('Filter', $filter, 'value:', $db, $tbl);
|
||||
$filters{$filter}->{$tbl} = $db;
|
||||
}
|
||||
else { # database
|
||||
MKDEBUG && _d('Filter', $filter, 'value:', $obj);
|
||||
$filters{$filter}->{$obj} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @regex_filters = qw(
|
||||
databases-regex tables-regex
|
||||
ignore-databases-regex ignore-tables-regex);
|
||||
REGEX_FILTER:
|
||||
foreach my $filter ( @regex_filters ) {
|
||||
if ( $o->has($filter) ) {
|
||||
my $pat = $o->get($filter);
|
||||
next REGEX_FILTER unless $pat;
|
||||
$filters{$filter} = qr/$pat/;
|
||||
MKDEBUG && _d('Filter', $filter, 'value:', $filters{$filter});
|
||||
}
|
||||
}
|
||||
|
||||
MKDEBUG && _d('Schema object filters:', Dumper(\%filters));
|
||||
return \%filters;
|
||||
}
|
||||
|
||||
sub next_schema_object {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my $schema_obj;
|
||||
if ( $self->{file_itr} ) {
|
||||
$schema_obj= $self->_iterate_files();
|
||||
}
|
||||
else { # dbh
|
||||
$schema_obj= $self->_iterate_dbh();
|
||||
}
|
||||
|
||||
if ( $schema_obj ) {
|
||||
if ( $schema_obj->{ddl} && $self->{TableParser} ) {
|
||||
$schema_obj->{tbl_struct}
|
||||
= $self->{TableParser}->parse($schema_obj->{ddl});
|
||||
}
|
||||
|
||||
delete $schema_obj->{ddl} unless $self->{keep_ddl};
|
||||
|
||||
if ( my $schema = $self->{Schema} ) {
|
||||
$schema->add_schema_object($schema_obj);
|
||||
}
|
||||
}
|
||||
|
||||
MKDEBUG && _d('Next schema object:', $schema_obj->{db}, $schema_obj->{tbl});
|
||||
return $schema_obj;
|
||||
}
|
||||
|
||||
sub _iterate_files {
|
||||
my ( $self ) = @_;
|
||||
|
||||
if ( !$self->{fh} ) {
|
||||
my ($fh, $file) = $self->{file_itr}->();
|
||||
if ( !$fh ) {
|
||||
MKDEBUG && _d('No more files to iterate');
|
||||
return;
|
||||
}
|
||||
$self->{fh} = $fh;
|
||||
$self->{file} = $file;
|
||||
}
|
||||
my $fh = $self->{fh};
|
||||
MKDEBUG && _d('Getting next schema object from', $self->{file});
|
||||
|
||||
local $INPUT_RECORD_SEPARATOR = '';
|
||||
CHUNK:
|
||||
while (defined(my $chunk = <$fh>)) {
|
||||
if ($chunk =~ m/Database: (\S+)/) {
|
||||
my $db = $1; # XXX
|
||||
$db =~ s/^`//; # strip leading `
|
||||
$db =~ s/`$//; # and trailing `
|
||||
if ( $self->database_is_allowed($db) ) {
|
||||
$self->{db} = $db;
|
||||
}
|
||||
}
|
||||
elsif ($self->{db} && $chunk =~ m/CREATE TABLE/) {
|
||||
if ($chunk =~ m/DROP VIEW IF EXISTS/) {
|
||||
MKDEBUG && _d('Table is a VIEW, skipping');
|
||||
next CHUNK;
|
||||
}
|
||||
|
||||
my ($tbl) = $chunk =~ m/$tbl_name/;
|
||||
$tbl =~ s/^\s*`//;
|
||||
$tbl =~ s/`\s*$//;
|
||||
if ( $self->table_is_allowed($self->{db}, $tbl) ) {
|
||||
my ($ddl) = $chunk =~ m/^(?:$open_comment)?(CREATE TABLE.+?;)$/ms;
|
||||
if ( !$ddl ) {
|
||||
warn "Failed to parse CREATE TABLE from\n" . $chunk;
|
||||
next CHUNK;
|
||||
}
|
||||
$ddl =~ s/ \*\/;\Z/;/; # remove end of version comment
|
||||
|
||||
my ($engine) = $ddl =~ m/\).*?(?:ENGINE|TYPE)=(\w+)/;
|
||||
|
||||
if ( !$engine || $self->engine_is_allowed($engine) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
ddl => $ddl,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} # CHUNK
|
||||
|
||||
MKDEBUG && _d('No more schema objects in', $self->{file});
|
||||
close $self->{fh};
|
||||
$self->{fh} = undef;
|
||||
|
||||
return $self->_iterate_files();
|
||||
}
|
||||
|
||||
sub _iterate_dbh {
|
||||
my ( $self ) = @_;
|
||||
my $q = $self->{Quoter};
|
||||
my $dbh = $self->{dbh};
|
||||
MKDEBUG && _d('Getting next schema object from dbh', $dbh);
|
||||
|
||||
if ( !defined $self->{dbs} ) {
|
||||
my $filter = $self->{filter};
|
||||
my @dbs;
|
||||
eval {
|
||||
my $sql = 'SHOW DATABASES';
|
||||
MKDEBUG && _d($sql);
|
||||
my @dbs = grep { $self->database_is_allowed($_) }
|
||||
@{$dbh->selectcol_arrayref($sql)};
|
||||
@dbs = grep {
|
||||
my $ok = $filter ? $filter->($dbh, $_, undef) : 1;
|
||||
$ok = 0 if $_ =~ m/information_schema|performance_schema|lost\+found/;
|
||||
$ok;
|
||||
} @{ $dbh->selectcol_arrayref($sql) };
|
||||
MKDEBUG && _d('Found', scalar @dbs, 'databases');
|
||||
$self->{dbs} = \@dbs;
|
||||
}
|
||||
};
|
||||
|
||||
if ( !$self->{db} ) {
|
||||
$self->{db} = shift @{$self->{dbs}};
|
||||
MKDEBUG && _d('Next database:', $self->{db});
|
||||
return unless $self->{db};
|
||||
}
|
||||
MKDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
|
||||
my $iterator = sub {
|
||||
return shift @dbs;
|
||||
};
|
||||
|
||||
if ( !defined $self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
MKDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
}
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
$self->table_is_allowed($self->{db}, $tbl)
|
||||
&& (!$type || ($type ne 'VIEW'));
|
||||
}
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
MKDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
if (wantarray) {
|
||||
return ($iterator, scalar @dbs);
|
||||
}
|
||||
else {
|
||||
return $iterator;
|
||||
}
|
||||
}
|
||||
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $engine;
|
||||
if ( $self->{filters}->{'engines'}
|
||||
|| $self->{filters}->{'ignore-engines'} ) {
|
||||
my $sql = "SHOW TABLE STATUS FROM " . $q->quote($self->{db})
|
||||
. " LIKE \'$tbl\'";
|
||||
sub get_tbl_itr {
|
||||
my ( $self, %args ) = @_;
|
||||
my @required_args = qw(dbh db);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($dbh, $db, $views) = @args{@required_args, 'views'};
|
||||
|
||||
my $filter = $self->{filter};
|
||||
my @tbls;
|
||||
if ( $db ) {
|
||||
eval {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM '
|
||||
. $self->{Quoter}->quote($db);
|
||||
MKDEBUG && _d($sql);
|
||||
$engine = $dbh->selectrow_hashref($sql)->{engine};
|
||||
MKDEBUG && _d($tbl, 'uses', $engine, 'engine');
|
||||
}
|
||||
|
||||
|
||||
if ( !$engine || $self->engine_is_allowed($engine) ) {
|
||||
my $ddl;
|
||||
if ( my $du = $self->{MySQLDump} ) {
|
||||
$ddl = $du->get_create_table($dbh, $q, $self->{db}, $tbl)->[1];
|
||||
@tbls = map {
|
||||
$_->[0]
|
||||
}
|
||||
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
ddl => $ddl,
|
||||
};
|
||||
}
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
my $ok = $filter ? $filter->($dbh, $db, $tbl) : 1;
|
||||
if ( !$views ) {
|
||||
$ok = 0 if ($type || '') eq 'VIEW';
|
||||
}
|
||||
$ok;
|
||||
}
|
||||
@{ $dbh->selectall_arrayref($sql) };
|
||||
MKDEBUG && _d('Found', scalar @tbls, 'tables in', $db);
|
||||
};
|
||||
MKDEBUG && $EVAL_ERROR && _d($EVAL_ERROR);
|
||||
}
|
||||
else {
|
||||
MKDEBUG && _d('No db given so no tables');
|
||||
}
|
||||
|
||||
MKDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
my $iterator = sub {
|
||||
return shift @tbls;
|
||||
};
|
||||
|
||||
return $self->_iterate_dbh();
|
||||
if ( wantarray ) {
|
||||
return ($iterator, scalar @tbls);
|
||||
}
|
||||
else {
|
||||
return $iterator;
|
||||
}
|
||||
}
|
||||
|
||||
sub database_is_allowed {
|
||||
my ( $self, $db ) = @_;
|
||||
die "I need a db argument" unless $db;
|
||||
|
||||
$db = lc $db;
|
||||
|
||||
my $filter = $self->{filters};
|
||||
|
||||
if ( $db =~ m/information_schema|performance_schema|lost\+found/ ) {
|
||||
MKDEBUG && _d('Database', $db, 'is a system database, ignoring');
|
||||
return 0;
|
||||
sub _make_filter {
|
||||
my ( $cond, $var_name, $objs, $lc ) = @_;
|
||||
my @lines;
|
||||
if ( scalar keys %$objs ) {
|
||||
my $test = join(' || ',
|
||||
map { "$var_name eq '" . ($lc ? lc $_ : $_) ."'" } keys %$objs);
|
||||
push @lines, " return 0 $cond $var_name && ($test);",
|
||||
}
|
||||
|
||||
if ( $self->{filters}->{'ignore-databases'}->{$db} ) {
|
||||
MKDEBUG && _d('Database', $db, 'is in --ignore-databases list');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'ignore-databases-regex'}
|
||||
&& $db =~ $filter->{'ignore-databases-regex'} ) {
|
||||
MKDEBUG && _d('Database', $db, 'matches --ignore-databases-regex');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'databases'}
|
||||
&& !$filter->{'databases'}->{$db} ) {
|
||||
MKDEBUG && _d('Database', $db, 'is not in --databases list, ignoring');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'databases-regex'}
|
||||
&& $db !~ $filter->{'databases-regex'} ) {
|
||||
MKDEBUG && _d('Database', $db, 'does not match --databases-regex, ignoring');
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub table_is_allowed {
|
||||
my ( $self, $db, $tbl ) = @_;
|
||||
die "I need a db argument" unless $db;
|
||||
die "I need a tbl argument" unless $tbl;
|
||||
|
||||
$db = lc $db;
|
||||
$tbl = lc $tbl;
|
||||
|
||||
my $filter = $self->{filters};
|
||||
|
||||
if ( $filter->{'ignore-tables'}->{$tbl}
|
||||
&& ($filter->{'ignore-tables'}->{$tbl} eq '*'
|
||||
|| $filter->{'ignore-tables'}->{$tbl} eq $db) ) {
|
||||
MKDEBUG && _d('Table', $tbl, 'is in --ignore-tables list');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'ignore-tables-regex'}
|
||||
&& $tbl =~ $filter->{'ignore-tables-regex'} ) {
|
||||
MKDEBUG && _d('Table', $tbl, 'matches --ignore-tables-regex');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'tables'}
|
||||
&& !$filter->{'tables'}->{$tbl} ) {
|
||||
MKDEBUG && _d('Table', $tbl, 'is not in --tables list, ignoring');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'tables-regex'}
|
||||
&& $tbl !~ $filter->{'tables-regex'} ) {
|
||||
MKDEBUG && _d('Table', $tbl, 'does not match --tables-regex, ignoring');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'tables'}
|
||||
&& $filter->{'tables'}->{$tbl}
|
||||
&& $filter->{'tables'}->{$tbl} ne '*'
|
||||
&& $filter->{'tables'}->{$tbl} ne $db ) {
|
||||
MKDEBUG && _d('Table', $tbl, 'is only allowed in database',
|
||||
$filter->{'tables'}->{$tbl});
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub engine_is_allowed {
|
||||
my ( $self, $engine ) = @_;
|
||||
die "I need an engine argument" unless $engine;
|
||||
|
||||
$engine = lc $engine;
|
||||
|
||||
my $filter = $self->{filters};
|
||||
|
||||
if ( $filter->{'ignore-engines'}->{$engine} ) {
|
||||
MKDEBUG && _d('Engine', $engine, 'is in --ignore-databases list');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $filter->{'engines'}
|
||||
&& !$filter->{'engines'}->{$engine} ) {
|
||||
MKDEBUG && _d('Engine', $engine, 'is not in --engines list, ignoring');
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return @lines;
|
||||
}
|
||||
|
||||
sub _d {
|
||||
@@ -6968,7 +6884,7 @@ sub _d {
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
# ###########################################################################
|
||||
# End SchemaIterator package
|
||||
# ###########################################################################
|
||||
@@ -10055,7 +9971,7 @@ User for login if not current user.
|
||||
=back
|
||||
|
||||
=head1 DOWNLOADING
|
||||
|
||||
|
||||
Visit L<http://www.percona.com/software/> to download the latest release of
|
||||
Percona Toolkit. Or, to get the latest release from the command line:
|
||||
|
||||
|
Reference in New Issue
Block a user