merged pt-duplicate-key-checker-fails-with-verbose-1402730

This commit is contained in:
Frank Cizmich
2015-04-09 11:45:35 -03:00
5 changed files with 89 additions and 62 deletions

View File

@@ -2336,7 +2336,8 @@ sub get_duplicate_keys {
my @dupes;
KEY:
foreach my $key ( values %keys ) {
# sort by key name for consistent testing
foreach my $key ( sort {$a->{name} cmp $b->{name}} values %keys ) {
$key->{real_cols} = [ @{$key->{cols}} ];
$key->{len_cols} = length $key->{colnames};
@@ -2412,7 +2413,8 @@ sub get_duplicate_keys {
sub get_duplicate_fks {
my ( $self, $fks, %args ) = @_;
die "I need a fks argument" unless $fks;
my @fks = values %$fks;
# sort by name for consistent testing
my @fks = sort {$a->{name} cmp $b->{name}} values %$fks;
my @dupes;
foreach my $i ( 0..$#fks - 1 ) {
@@ -4881,7 +4883,7 @@ my $hdr_fmt = "# %-${hdr_width}s\n";
sub main {
local @ARGV = @_; # set global ARGV for this package
my %summary = ( 'Total Indexes' => 0 );
my %summary = ( 'items' => {'Total Indexes' => 0} );
my %seen_tbl;
my $q = new Quoter();
@@ -4972,51 +4974,49 @@ sub main {
print_all_keys($keys, $tbl, \%seen_tbl) if $keys;
print_all_keys($fks, $tbl, \%seen_tbl) if $fks;
}
else {
PTDEBUG && _d('Getting duplicate keys on',
$tbl->{db}, $tbl->{tbl});
if ( $keys ) {
$dk->get_duplicate_keys(
$keys,
clustered_key => $clustered_key,
tbl_info => $tbl,
callback => \&print_duplicate_key,
%tp_opts,
# get_duplicate_keys() ignores these args but passes them
# to the callback:
dbh => $dbh,
is_fk => 0,
o => $o,
ks => $ks,
tp => $tp,
q => $q,
seen_tbl => \%seen_tbl,
summary => \%summary,
);
}
if ( $fks ) {
$dk->get_duplicate_fks(
$fks,
tbl_info => $tbl,
callback => \&print_duplicate_key,
%tp_opts,
# get_duplicate_fks() ignores these args but passes them
# to the callback:
dbh => $dbh,
is_fk => 1,
o => $o,
ks => $ks,
tp => $tp,
q => $q,
seen_tbl => \%seen_tbl,
summary => \%summary,
);
}
PTDEBUG && _d('Getting duplicate keys on',
$tbl->{db}, $tbl->{tbl});
if ( $keys ) {
$dk->get_duplicate_keys(
$keys,
clustered_key => $clustered_key,
tbl_info => $tbl,
callback => \&print_duplicate_key,
%tp_opts,
# get_duplicate_keys() ignores these args but passes them
# to the callback:
dbh => $dbh,
is_fk => 0,
o => $o,
ks => $ks,
tp => $tp,
q => $q,
seen_tbl => \%seen_tbl,
summary => \%summary,
);
}
if ( $fks ) {
$dk->get_duplicate_fks(
$fks,
tbl_info => $tbl,
callback => \&print_duplicate_key,
%tp_opts,
# get_duplicate_fks() ignores these args but passes them
# to the callback:
dbh => $dbh,
is_fk => 1,
o => $o,
ks => $ks,
tp => $tp,
q => $q,
seen_tbl => \%seen_tbl,
summary => \%summary,
);
}
# Always count Total Keys so print_key_summary won't die
# because %summary is empty.
$summary{'Total Indexes'} += (scalar keys %$keys)
$summary{items}->{'Total Indexes'} += (scalar keys %$keys)
+ (scalar keys %$fks)
}
};
@@ -5044,7 +5044,8 @@ sub print_all_keys {
printf $hdr_fmt, "$db.$tbl";
printf $hdr_fmt, ('#' x $hdr_width);
}
foreach my $key ( values %$keys ) {
# Print keys sorted by name (easier to test)
foreach my $key ( sort {$a->{name} cmp $b->{name}} values %$keys ) {
print "\n# $key->{name} ($key->{colnames})";
}
print "\n";
@@ -5069,6 +5070,10 @@ sub print_duplicate_key {
my $summary = $args{summary};
my $struct = $tp->parse($args{tbl_info}->{ddl});
if ($dupe->{ddl} =~ /FULLTEXT/) {
$summary->{has_fulltext_dupe}++;
}
if ( !$seen_tbl->{"$db$tbl"}++ ) {
printf $hdr_fmt, ('#' x $hdr_width);
printf $hdr_fmt, "$db.$tbl";
@@ -5111,7 +5116,7 @@ sub print_duplicate_key {
print "\n";
if ( $o->get('summary') && $summary ) {
$summary->{'Total Duplicate Indexes'} += 1;
$summary->{'items'}->{'Total Duplicate Indexes'} += 1;
my ($size, $chosen_key) = $ks->get_key_size(
name => $dupe->{key},
cols => $dupe->{cols},
@@ -5128,7 +5133,7 @@ sub print_duplicate_key {
$size ||= 0;
# Create Size Duplicate Keys summary even if there's no valid keys.
$summary->{'Size Duplicate Indexes'} += $size;
$summary->{'items'}->{'Size Duplicate Indexes'} += $size;
if ( $size ) {
if ( $chosen_key && $chosen_key ne $dupe->{key} ) {
@@ -5143,14 +5148,19 @@ sub print_duplicate_key {
sub print_key_summary {
my ( %summary ) = @_;
my $items = $summary{items};
printf $hdr_fmt, ('#' x $hdr_width);
printf $hdr_fmt, 'Summary of indexes';
printf $hdr_fmt, ('#' x $hdr_width);
print "\n";
my $max_item = max(map { length($_) } keys %summary);
my $line_fmt = "# %-${max_item}s %-s\n";
foreach my $item ( sort keys %summary ) {
printf $line_fmt, $item, $summary{$item};
my $max_item = max(map { length($_) } keys %$items);
my $line_fmt = "# %-${max_item}s %-s";
foreach my $item ( sort keys %$items ) {
printf $line_fmt, $item, $items->{$item};
if ( $item eq 'Size Duplicate Indexes' && $summary{has_fulltext_dupe} ) {
print ' (not including FULLTEXT indexes)';
}
print "\n";
}
return;
}

View File

@@ -142,11 +142,24 @@ $sb->load_file('master', 't/lib/samples/dupekeys/simple_dupe_bug_1217013.sql', '
ok(
no_diff(
sub { pt_duplicate_key_checker::main(@args, qw(-t test.domains)) },
"$sample/simple_dupe_bug_1217013.txt"),
sub { pt_duplicate_key_checker::main(@args, qw(-t test.domains -v)) },
"$sample/simple_dupe_bug_1217013.txt", keep_output=>1),
'Exact unique dupes (bug 1217013)'
) or diag($test_diff);
# #############################################################################
# Same thing, but added --verbose option to test for:
# https://bugs.launchpad.net/percona-toolkit/+bug/1402730
# #############################################################################
ok(
no_diff(
sub { pt_duplicate_key_checker::main(@args, qw(-t test.domains --verbose)) },
"$sample/simple_dupe_bug_1217013.txt", keep_output=>1),
q[--verbose option doesn't skip dupes reporting (bug 1402730)]
) or diag($test_diff);
# #############################################################################
# Done.
# #############################################################################

View File

@@ -41,10 +41,10 @@ $sb->load_file('master', 't/pt-duplicate-key-checker/samples/issue_331.sql', 'te
ok(
no_diff(
sub { pt_duplicate_key_checker::main(@args, qw(-d issue_331)) },
't/pt-duplicate-key-checker/samples/issue_331.txt',
't/pt-duplicate-key-checker/samples/issue_331.txt'
),
'Issue 331 crash on fks'
);
) or diag($test_diff);
# #############################################################################
# Done.

View File

@@ -2,14 +2,14 @@
# issue_331.issue_331_t2
# ########################################################################
# FOREIGN KEY fk_1 (`id`) REFERENCES `issue_331`.`issue_331_t1` (`t1_id`) is a duplicate of FOREIGN KEY fk_2 (`id`) REFERENCES `issue_331`.`issue_331_t1` (`t1_id`)
# FOREIGN KEY fk_2 (`id`) REFERENCES `issue_331`.`issue_331_t1` (`t1_id`) is a duplicate of FOREIGN KEY fk_1 (`id`) REFERENCES `issue_331`.`issue_331_t1` (`t1_id`)
# Key definitions:
# CONSTRAINT `fk_1` FOREIGN KEY (`id`) REFERENCES `issue_331_t1` (`t1_id`)
# CONSTRAINT `fk_2` FOREIGN KEY (`id`) REFERENCES `issue_331_t1` (`t1_id`)
# CONSTRAINT `fk_1` FOREIGN KEY (`id`) REFERENCES `issue_331_t1` (`t1_id`)
# Column types:
# `id` bigint(20) not null default '0'
# To remove this duplicate foreign key, execute:
ALTER TABLE `issue_331`.`issue_331_t2` DROP FOREIGN KEY `fk_1`;
ALTER TABLE `issue_331`.`issue_331_t2` DROP FOREIGN KEY `fk_2`;
# MySQL uses the PRIMARY index for this foreign key constraint

View File

@@ -2,15 +2,19 @@
# test.domains
# ########################################################################
# Uniqueness of domain ignored because unique_key_domain is a duplicate constraint
# domain is a duplicate of unique_key_domain
# PRIMARY (`id`)
# domain (`domain`)
# unique_key_domain (`domain`)
# Uniqueness of unique_key_domain ignored because domain is a duplicate constraint
# unique_key_domain is a duplicate of domain
# Key definitions:
# UNIQUE KEY `domain` (`domain`),
# UNIQUE KEY `unique_key_domain` (`domain`)
# UNIQUE KEY `domain` (`domain`),
# Column types:
# `domain` varchar(175) collate utf8_bin not null
# To remove this duplicate index, execute:
ALTER TABLE `test`.`domains` DROP INDEX `domain`;
ALTER TABLE `test`.`domains` DROP INDEX `unique_key_domain`;
# ########################################################################
# Summary of indexes