mirror of
https://github.com/percona/percona-toolkit.git
synced 2026-04-19 01:00:34 +08:00
Fix bug 1217013: exact dupe unique keys not detected.
This commit is contained in:
@@ -143,8 +143,6 @@ sub get_duplicate_keys {
|
|||||||
push @dupes,
|
push @dupes,
|
||||||
$self->remove_prefix_duplicates(\@fulltext_keys, \@fulltext_keys, %args, exact_duplicates => 1);
|
$self->remove_prefix_duplicates(\@fulltext_keys, \@fulltext_keys, %args, exact_duplicates => 1);
|
||||||
|
|
||||||
# TODO: other structs
|
|
||||||
|
|
||||||
# Remove clustered duplicates.
|
# Remove clustered duplicates.
|
||||||
my $clustered_key = $args{clustered_key} ? $keys{$args{clustered_key}}
|
my $clustered_key = $args{clustered_key} ? $keys{$args{clustered_key}}
|
||||||
: undef;
|
: undef;
|
||||||
@@ -314,7 +312,7 @@ sub remove_prefix_duplicates {
|
|||||||
if ( substr($left_cols, 0, $right_len_cols)
|
if ( substr($left_cols, 0, $right_len_cols)
|
||||||
eq substr($right_cols, 0, $right_len_cols) ) {
|
eq substr($right_cols, 0, $right_len_cols) ) {
|
||||||
|
|
||||||
# FULLTEXT keys, for example, are only duplicates if they
|
# UNIQUE and FULLTEXT indexes are only duplicates if they
|
||||||
# are exact duplicates.
|
# are exact duplicates.
|
||||||
if ( $args{exact_duplicates} && ($right_len_cols<$left_len_cols) ) {
|
if ( $args{exact_duplicates} && ($right_len_cols<$left_len_cols) ) {
|
||||||
PTDEBUG && _d($right_name, 'not exact duplicate of', $left_name);
|
PTDEBUG && _d($right_name, 'not exact duplicate of', $left_name);
|
||||||
@@ -333,10 +331,10 @@ sub remove_prefix_duplicates {
|
|||||||
|
|
||||||
PTDEBUG && _d('Remove', $right_name);
|
PTDEBUG && _d('Remove', $right_name);
|
||||||
my $reason;
|
my $reason;
|
||||||
if ( $right_keys->[$right_index]->{unconstrained} ) {
|
if ( my $type = $right_keys->[$right_index]->{unconstrained} ) {
|
||||||
$reason .= "Uniqueness of $right_name ignored because "
|
$reason .= "Uniqueness of $right_name ignored because "
|
||||||
. $right_keys->[$right_index]->{constraining_key}->{name}
|
. $right_keys->[$right_index]->{constraining_key}->{name}
|
||||||
. " is a stronger constraint\n";
|
. " is a $type constraint\n";
|
||||||
}
|
}
|
||||||
my $exact_dupe = $right_len_cols < $left_len_cols ? 0 : 1;
|
my $exact_dupe = $right_len_cols < $left_len_cols ? 0 : 1;
|
||||||
$reason .= $right_name
|
$reason .= $right_name
|
||||||
@@ -454,14 +452,23 @@ sub unconstrain_keys {
|
|||||||
next unless $unique_key; # primary key may be undefined
|
next unless $unique_key; # primary key may be undefined
|
||||||
my $cols = $unique_key->{cols};
|
my $cols = $unique_key->{cols};
|
||||||
if ( @$cols == 1 ) {
|
if ( @$cols == 1 ) {
|
||||||
PTDEBUG && _d($unique_key->{name},'defines unique column:',$cols->[0]);
|
|
||||||
# Save only the first unique key for the unique col. If there
|
|
||||||
# are others, then they are exact duplicates and will be removed
|
|
||||||
# later when unique keys are compared to unique keys.
|
|
||||||
if ( !exists $unique_cols{$cols->[0]} ) {
|
if ( !exists $unique_cols{$cols->[0]} ) {
|
||||||
|
PTDEBUG && _d($unique_key->{name}, 'defines unique column:',
|
||||||
|
$cols->[0]);
|
||||||
$unique_cols{$cols->[0]} = $unique_key;
|
$unique_cols{$cols->[0]} = $unique_key;
|
||||||
$unique_key->{unique_col} = 1;
|
$unique_key->{unique_col} = 1;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
# https://bugs.launchpad.net/percona-toolkit/+bug/1217013
|
||||||
|
# If two unique indexes are not exact, then they must be enforcing
|
||||||
|
# different uniqueness constraints. Else they're exact dupes
|
||||||
|
# so one can be treated as a non-unique and removed later
|
||||||
|
# when comparing unique to non-unique.
|
||||||
|
PTDEBUG && _d($unique_key->{name},
|
||||||
|
'redundantly constrains unique column:', $cols->[0]);
|
||||||
|
$unique_key->{exact_dupe} = 1;
|
||||||
|
$unique_key->{constraining_key} = $unique_cols{$cols->[0]};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
local $LIST_SEPARATOR = '-';
|
local $LIST_SEPARATOR = '-';
|
||||||
@@ -496,18 +503,25 @@ sub unconstrain_keys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# And finally, unconstrain the redudantly unique sets found above by
|
# And finally, unconstrain the redundantly unique sets found above by
|
||||||
# removing them from the list of unique keys and adding them to the
|
# removing them from the list of unique keys and adding them to the
|
||||||
# list of normal keys.
|
# list of normal keys.
|
||||||
for my $i ( 0..(scalar @$unique_keys-1) ) {
|
for my $i ( 0..(scalar @$unique_keys-1) ) {
|
||||||
if ( exists $unconstrain{$unique_keys->[$i]->{name}} ) {
|
if ( exists $unconstrain{$unique_keys->[$i]->{name}} ) {
|
||||||
PTDEBUG && _d('Unconstraining', $unique_keys->[$i]->{name});
|
PTDEBUG && _d('Unconstraining weak', $unique_keys->[$i]->{name});
|
||||||
$unique_keys->[$i]->{unconstrained} = 1;
|
$unique_keys->[$i]->{unconstrained} = 'stronger';
|
||||||
$unique_keys->[$i]->{constraining_key}
|
$unique_keys->[$i]->{constraining_key}
|
||||||
= $unconstrain{$unique_keys->[$i]->{name}};
|
= $unconstrain{$unique_keys->[$i]->{name}};
|
||||||
push @unconstrained_keys, $unique_keys->[$i];
|
push @unconstrained_keys, $unique_keys->[$i];
|
||||||
delete $unique_keys->[$i];
|
delete $unique_keys->[$i];
|
||||||
}
|
}
|
||||||
|
elsif ( $unique_keys->[$i]->{exact_dupe} ) {
|
||||||
|
# https://bugs.launchpad.net/percona-toolkit/+bug/1217013
|
||||||
|
PTDEBUG && _d('Unconstraining dupe', $unique_keys->[$i]->{name});
|
||||||
|
$unique_keys->[$i]->{unconstrained} = 'duplicate';
|
||||||
|
push @unconstrained_keys, $unique_keys->[$i];
|
||||||
|
delete $unique_keys->[$i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PTDEBUG && _d('No more keys');
|
PTDEBUG && _d('No more keys');
|
||||||
|
|||||||
@@ -757,7 +757,7 @@ is_deeply(
|
|||||||
duplicate_of_cols => [ 'row_id' ],
|
duplicate_of_cols => [ 'row_id' ],
|
||||||
duplicate_of_ddl => 'PRIMARY KEY (`row_id`),',
|
duplicate_of_ddl => 'PRIMARY KEY (`row_id`),',
|
||||||
key => 'row_id',
|
key => 'row_id',
|
||||||
reason => 'row_id is a duplicate of PRIMARY',
|
reason => "Uniqueness of row_id ignored because PRIMARY is a duplicate constraint\nrow_id is a duplicate of PRIMARY",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cols => [ 'player_id' ],
|
cols => [ 'player_id' ],
|
||||||
@@ -803,6 +803,35 @@ is_deeply(
|
|||||||
# "Prefix bug 1214114"
|
# "Prefix bug 1214114"
|
||||||
#) or diag(Dumper($dupes));
|
#) or diag(Dumper($dupes));
|
||||||
|
|
||||||
|
# #############################################################################
|
||||||
|
# https://bugs.launchpad.net/percona-toolkit/+bug/1217013
|
||||||
|
#############################################################################
|
||||||
|
$ddl = load_file('t/lib/samples/dupekeys/simple_dupe_bug_1217013.sql');
|
||||||
|
$dupes = [];
|
||||||
|
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||||
|
$dk->get_duplicate_keys(
|
||||||
|
$keys,
|
||||||
|
clustered_key => $ck,
|
||||||
|
clustered => 1,
|
||||||
|
callback => $callback,
|
||||||
|
tbl_info => { engine => 'InnoDB', ddl => $ddl },
|
||||||
|
);
|
||||||
|
|
||||||
|
is_deeply(
|
||||||
|
$dupes,
|
||||||
|
[{
|
||||||
|
cols => ['domain'],
|
||||||
|
ddl => 'UNIQUE KEY `domain` (`domain`),',
|
||||||
|
dupe_type => 'exact',
|
||||||
|
duplicate_of => 'unique_key_domain',
|
||||||
|
duplicate_of_cols => ['domain'],
|
||||||
|
duplicate_of_ddl => 'UNIQUE KEY `unique_key_domain` (`domain`)',
|
||||||
|
key => 'domain',
|
||||||
|
reason => "Uniqueness of domain ignored because unique_key_domain is a duplicate constraint\ndomain is a duplicate of unique_key_domain",
|
||||||
|
}],
|
||||||
|
"Exact dupe uniques (bug 1217013)"
|
||||||
|
) or diag(Dumper($dupes));
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Done.
|
# Done.
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
|||||||
7
t/lib/samples/dupekeys/simple_dupe_bug_1217013.sql
Normal file
7
t/lib/samples/dupekeys/simple_dupe_bug_1217013.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
CREATE TABLE `domains` (
|
||||||
|
`id` bigint(20) NOT NULL,
|
||||||
|
`domain` varchar(175) COLLATE utf8_bin NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `domain` (`domain`),
|
||||||
|
UNIQUE KEY `unique_key_domain` (`domain`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
|
||||||
Reference in New Issue
Block a user