mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-10-19 17:04:00 +00:00
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
This commit is contained in:
746
t/lib/DuplicateKeyFinder.t
Normal file
746
t/lib/DuplicateKeyFinder.t
Normal file
@@ -0,0 +1,746 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
BEGIN {
|
||||
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
|
||||
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
|
||||
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use Test::More tests => 37;
|
||||
|
||||
use DuplicateKeyFinder;
|
||||
use Quoter;
|
||||
use TableParser;
|
||||
use MaatkitTest;
|
||||
|
||||
my $dk = new DuplicateKeyFinder();
|
||||
my $q = new Quoter();
|
||||
my $tp = new TableParser(Quoter => $q);
|
||||
|
||||
my $sample = "t/lib/samples/dupekeys/";
|
||||
my $dupes;
|
||||
my $callback = sub {
|
||||
push @$dupes, $_[0];
|
||||
};
|
||||
|
||||
my $opt = { version => '004001000' };
|
||||
my $ddl;
|
||||
my $tbl;
|
||||
|
||||
isa_ok($dk, 'DuplicateKeyFinder');
|
||||
|
||||
$ddl = load_file('t/lib/samples/one_key.sql');
|
||||
$dupes = [];
|
||||
my ($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
],
|
||||
'One key, no dupes'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/dupe_key.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'a',
|
||||
'cols' => [qw(a)],
|
||||
ddl => 'KEY `a` (`a`),',
|
||||
'duplicate_of' => 'a_2',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'KEY `a_2` (`a`,`b`)',
|
||||
'reason' => 'a is a left-prefix of a_2',
|
||||
dupe_type => 'prefix',
|
||||
}
|
||||
],
|
||||
'Two dupe keys on table dupe_key'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/dupe_key_reversed.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'a',
|
||||
'cols' => [qw(a)],
|
||||
ddl => 'KEY `a` (`a`),',
|
||||
'duplicate_of' => 'a_2',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'KEY `a_2` (`a`,`b`),',
|
||||
'reason' => 'a is a left-prefix of a_2',
|
||||
dupe_type => 'prefix',
|
||||
}
|
||||
],
|
||||
'Two dupe keys on table dupe_key in reverse'
|
||||
);
|
||||
|
||||
# This test might fail if your system sorts a_3 before a_2, because the
|
||||
# keys are sorted by columns, not name. If this happens, then a_3 will
|
||||
# duplicate a_2.
|
||||
$ddl = load_file('t/lib/samples/dupe_keys_thrice.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'a_3',
|
||||
'cols' => [qw(a b)],
|
||||
ddl => 'KEY `a_3` (`a`,`b`)',
|
||||
'duplicate_of' => 'a_2',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'KEY `a_2` (`a`,`b`),',
|
||||
'reason' => 'a_3 is a duplicate of a_2',
|
||||
dupe_type => 'exact',
|
||||
},
|
||||
{
|
||||
'key' => 'a',
|
||||
'cols' => [qw(a)],
|
||||
ddl => 'KEY `a` (`a`),',
|
||||
'duplicate_of' => 'a_2',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'KEY `a_2` (`a`,`b`),',
|
||||
'reason' => 'a is a left-prefix of a_2',
|
||||
dupe_type => 'prefix',
|
||||
},
|
||||
],
|
||||
'Dupe keys only output once (may fail due to different sort order)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/nondupe_fulltext.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'No dupe keys b/c of fulltext'
|
||||
);
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
ignore_structure => 1,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'a',
|
||||
'cols' => [qw(a)],
|
||||
ddl => 'KEY `a` (`a`),',
|
||||
'duplicate_of' => 'a_2',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'FULLTEXT KEY `a_2` (`a`,`b`),',
|
||||
'reason' => 'a is a left-prefix of a_2',
|
||||
dupe_type => 'prefix',
|
||||
},
|
||||
],
|
||||
'Dupe keys when ignoring structure'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/nondupe_fulltext_not_exact.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'No dupe keys b/c fulltext requires exact match (issue 10)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/dupe_fulltext_exact.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'ft_idx_a_b_2',
|
||||
'cols' => [qw(a b)],
|
||||
ddl => 'FULLTEXT KEY `ft_idx_a_b_2` (`a`,`b`)',
|
||||
'duplicate_of' => 'ft_idx_a_b_1',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'FULLTEXT KEY `ft_idx_a_b_1` (`a`,`b`),',
|
||||
'reason' => 'ft_idx_a_b_2 is a duplicate of ft_idx_a_b_1',
|
||||
dupe_type => 'exact',
|
||||
}
|
||||
],
|
||||
'Dupe exact fulltext keys (issue 10)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/dupe_fulltext_reverse_order.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'ft_idx_a_b',
|
||||
'cols' => [qw(a b)],
|
||||
ddl => 'FULLTEXT KEY `ft_idx_a_b` (`a`,`b`),',
|
||||
'duplicate_of' => 'ft_idx_b_a',
|
||||
'duplicate_of_cols' => [qw(b a)],
|
||||
duplicate_of_ddl => 'FULLTEXT KEY `ft_idx_b_a` (`b`,`a`)',
|
||||
'reason' => 'ft_idx_a_b is a duplicate of ft_idx_b_a',
|
||||
dupe_type => 'exact',
|
||||
}
|
||||
],
|
||||
'Dupe reverse order fulltext keys (issue 10)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/dupe_key_unordered.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'No dupe keys because of order'
|
||||
);
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
ignore_order => 1,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'a',
|
||||
'cols' => [qw(b a)],
|
||||
ddl => 'KEY `a` (`b`,`a`),',
|
||||
'duplicate_of' => 'a_2',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'KEY `a_2` (`a`,`b`),',
|
||||
'reason' => 'a is a duplicate of a_2',
|
||||
dupe_type => 'exact',
|
||||
}
|
||||
],
|
||||
'Two dupe keys when ignoring order'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Clustered key tests.
|
||||
# #############################################################################
|
||||
$ddl = load_file('t/lib/samples/innodb_dupe.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'No duplicate keys with ordinary options'
|
||||
);
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
clustered => 1,
|
||||
tbl_info => { engine => 'InnoDB', ddl => $ddl },
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'b',
|
||||
'cols' => [qw(b a)],
|
||||
ddl => 'KEY `b` (`b`,`a`)',
|
||||
'duplicate_of' => 'PRIMARY',
|
||||
'duplicate_of_cols' => [qw(a)],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`a`),',
|
||||
'reason' => 'Key b ends with a prefix of the clustered index',
|
||||
dupe_type => 'clustered',
|
||||
short_key => '`b`',
|
||||
}
|
||||
],
|
||||
'Duplicate keys with cluster option'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/dupe_if_it_were_innodb.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
clustered => 1,
|
||||
tbl_info => {engine => 'MyISAM', ddl => $ddl},
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'No cluster-duplicate keys because not InnoDB'
|
||||
);
|
||||
|
||||
# This table is a test case for an infinite loop I ran into while writing the
|
||||
# cluster stuff
|
||||
$ddl = load_file('t/lib/samples/mysql_db.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
clustered => 1,
|
||||
tbl_info => { engine => 'InnoDB', ddl => $ddl },
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'No cluster-duplicate keys in mysql.db'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Duplicate FOREIGN KEY tests.
|
||||
# #############################################################################
|
||||
$ddl = load_file('t/lib/samples/dupe_fk_one.sql');
|
||||
$dupes = [];
|
||||
$dk->get_duplicate_fks(
|
||||
$tp->get_fks($ddl, {database => 'test'}),
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 't1_ibfk_1',
|
||||
'cols' => [qw(a b)],
|
||||
ddl => 'CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`, `b`) REFERENCES `t2` (`a`, `b`)',
|
||||
'duplicate_of' => 't1_ibfk_2',
|
||||
'duplicate_of_cols' => [qw(b a)],
|
||||
duplicate_of_ddl => 'CONSTRAINT `t1_ibfk_2` FOREIGN KEY (`b`, `a`) REFERENCES `t2` (`b`, `a`)',
|
||||
'reason' => 'FOREIGN KEY t1_ibfk_1 (`a`, `b`) REFERENCES `test`.`t2` (`a`, `b`) is a duplicate of FOREIGN KEY t1_ibfk_2 (`b`, `a`) REFERENCES `test`.`t2` (`b`, `a`)',
|
||||
dupe_type => 'fk',
|
||||
}
|
||||
],
|
||||
'Two duplicate foreign keys'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/sakila_film.sql');
|
||||
$dupes = [];
|
||||
$dk->get_duplicate_fks(
|
||||
$tp->get_fks($ddl, {database => 'sakila'}),
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'No duplicate foreign keys in sakila_film.sql'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Issue 9: mk-duplicate-key-checker should treat unique and FK indexes specially
|
||||
# #############################################################################
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_9-1.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'Unique and non-unique keys with common prefix not dupes (issue 9)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_9-2.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'PRIMARY and non-unique keys with common prefix not dupes (issue 9)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_9-3.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'j',
|
||||
'cols' => [qw(a b)],
|
||||
ddl => 'KEY `j` (`a`,`b`)',
|
||||
'duplicate_of' => 'i',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'UNIQUE KEY `i` (`a`,`b`),',
|
||||
'reason' => 'j is a duplicate of i',
|
||||
dupe_type => 'exact',
|
||||
}
|
||||
],
|
||||
'Non-unique key dupes unique key with same col cover (issue 9)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_9-4.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'j',
|
||||
'cols' => [qw(a b)],
|
||||
ddl => 'KEY `j` (`a`,`b`)',
|
||||
'duplicate_of' => 'PRIMARY',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`a`,`b`),',
|
||||
'reason' => 'j is a duplicate of PRIMARY',
|
||||
dupe_type => 'exact',
|
||||
}
|
||||
],
|
||||
'Non-unique key dupes PRIMARY key same col cover (issue 9)'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_9-5.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'Two unique keys with common prefix are not dupes'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/uppercase_names.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'A',
|
||||
'cols' => [qw(A)],
|
||||
ddl => 'KEY `A` (`A`)',
|
||||
'duplicate_of' => 'PRIMARY',
|
||||
'duplicate_of_cols' => [qw(A)],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`A`),',
|
||||
'reason' => "A is a duplicate of PRIMARY",
|
||||
dupe_type => 'exact',
|
||||
},
|
||||
],
|
||||
'Finds duplicates OK on uppercase columns',
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_9-7.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'ua_b',
|
||||
'cols' => [qw(a b)],
|
||||
ddl => 'UNIQUE KEY `ua_b` (`a`,`b`),',
|
||||
'duplicate_of' => 'a_b_c',
|
||||
'duplicate_of_cols' => [qw(a b c)],
|
||||
duplicate_of_ddl => 'KEY `a_b_c` (`a`,`b`,`c`)',
|
||||
'reason' => "Uniqueness of ua_b ignored because PRIMARY is a stronger constraint\nua_b is a left-prefix of a_b_c",
|
||||
dupe_type => 'prefix',
|
||||
},
|
||||
],
|
||||
'Redundantly unique key dupes normal key after unconstraining'
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_9-6.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'duplicate_of' => 'PRIMARY',
|
||||
'reason' => 'a is a left-prefix of PRIMARY',
|
||||
dupe_type => 'prefix',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`a`,`b`),',
|
||||
'cols' => [qw(a)],
|
||||
'key' => 'a',
|
||||
ddl => 'KEY `a` (`a`),',
|
||||
},
|
||||
{
|
||||
'duplicate_of' => 'PRIMARY',
|
||||
'reason' => 'a_b is a duplicate of PRIMARY',
|
||||
dupe_type => 'exact',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`a`,`b`),',
|
||||
'cols' => [qw(a b)],
|
||||
'key' => 'a_b',
|
||||
ddl => 'KEY `a_b` (`a`,`b`),',
|
||||
},
|
||||
{
|
||||
'duplicate_of' => 'PRIMARY',
|
||||
'reason' => "Uniqueness of ua_b ignored because ua is a stronger constraint\nua_b is a duplicate of PRIMARY",
|
||||
dupe_type => 'exact',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`a`,`b`),',
|
||||
'cols' => [qw(a b)],
|
||||
'key' => 'ua_b',
|
||||
ddl => 'UNIQUE KEY `ua_b` (`a`,`b`),',
|
||||
},
|
||||
{
|
||||
'duplicate_of' => 'PRIMARY',
|
||||
'reason' => "Uniqueness of ua_b2 ignored because ua is a stronger constraint\nua_b2 is a duplicate of PRIMARY",
|
||||
dupe_type => 'exact',
|
||||
'duplicate_of_cols' => [qw(a b)],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`a`,`b`),',
|
||||
'cols' => [qw(a b)],
|
||||
'key' => 'ua_b2',
|
||||
ddl => 'UNIQUE KEY `ua_b2` (`a`,`b`),',
|
||||
}
|
||||
],
|
||||
'Very pathological case',
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Issue 269: mk-duplicate-key-checker: Wrongly suggesting removing index
|
||||
# #############################################################################
|
||||
$ddl = load_file('t/lib/samples/issue_269-1.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
],
|
||||
'Keep stronger unique constraint that is prefix'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Issue 331: mk-duplicate-key-checker crashes when printing column types
|
||||
# #############################################################################
|
||||
$ddl = load_file('t/lib/samples/issue_331.sql');
|
||||
$dupes = [];
|
||||
$dk->get_duplicate_fks(
|
||||
$tp->get_fks($ddl, {database => 'test'}),
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[
|
||||
{
|
||||
'key' => 'fk_1',
|
||||
'cols' => [qw(id)],
|
||||
ddl => 'CONSTRAINT `fk_1` FOREIGN KEY (`id`) REFERENCES `issue_331_t1` (`t1_id`)',
|
||||
'duplicate_of' => 'fk_2',
|
||||
'duplicate_of_cols' => [qw(id)],
|
||||
duplicate_of_ddl => 'CONSTRAINT `fk_2` FOREIGN KEY (`id`) REFERENCES `issue_331_t1` (`t1_id`)',
|
||||
'reason' => 'FOREIGN KEY fk_1 (`id`) REFERENCES `test`.`issue_331_t1` (`t1_id`) is a duplicate of FOREIGN KEY fk_2 (`id`) REFERENCES `test`.`issue_331_t1` (`t1_id`)',
|
||||
dupe_type => 'fk',
|
||||
}
|
||||
],
|
||||
'fk col not in referencing table (issue 331)'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Issue 295: Enhance rules for clustered keys in mk-duplicate-key-checker
|
||||
# #############################################################################
|
||||
is(
|
||||
$dk->shorten_clustered_duplicate('`a`', '`b`,`a`'),
|
||||
'`b`',
|
||||
"shorten_clustered_duplicate('`a`', '`b`,`a`')"
|
||||
);
|
||||
|
||||
is(
|
||||
$dk->shorten_clustered_duplicate('`a`', '`a`'),
|
||||
'`a`',
|
||||
"shorten_clustered_duplicate('`a`', '`a`')"
|
||||
);
|
||||
|
||||
is(
|
||||
$dk->shorten_clustered_duplicate('`a`,`b`', '`c`,`a`,`b`'),
|
||||
'`c`',
|
||||
"shorten_clustered_duplicate('`a`,`b`', '`c`,`a`,`b`'),"
|
||||
);
|
||||
|
||||
$ddl = load_file('t/lib/samples/issue_295-1.sql');
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
callback => $callback);
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'Do not remove clustered key acting as primary key'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Issue 904: Tables that confuse mk-duplicate-key-checker
|
||||
# #############################################################################
|
||||
$ddl = load_file("$sample/issue-904-1.txt");
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
clustered => 1,
|
||||
tbl_info => { engine => 'InnoDB', ddl => $ddl },
|
||||
callback => $callback
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'Clustered key with multiple columns (issue 904 1)'
|
||||
);
|
||||
|
||||
$ddl = load_file("$sample/issue-904-2.txt");
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
clustered => 1,
|
||||
tbl_info => { engine => 'InnoDB', ddl => $ddl },
|
||||
callback => $callback
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'Clustered key with multiple columns (issue 904 2)'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Issue 1004: mk-dupe-key-checker recommends dropping and re-adding same index
|
||||
# #############################################################################
|
||||
$ddl = load_file("$sample/issue-1004.txt");
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
clustered => 1,
|
||||
tbl_info => { engine => 'InnoDB', ddl => $ddl },
|
||||
callback => $callback
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[],
|
||||
'Issue 1004'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Issue 1192: DROP/ADD leaves structure unchanged
|
||||
# #############################################################################
|
||||
$ddl = load_file("$sample/issue-1192.sql");
|
||||
$dupes = [];
|
||||
($keys, $ck) = $tp->get_keys($ddl, $opt);
|
||||
$dk->get_duplicate_keys(
|
||||
$keys,
|
||||
clustered_key => $ck,
|
||||
clustered => 1,
|
||||
tbl_info => { engine => 'InnoDB', ddl => $ddl },
|
||||
callback => $callback
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
$dupes,
|
||||
[{
|
||||
key => 'a',
|
||||
cols => ['a'],
|
||||
ddl => 'KEY `a` (`a`),',
|
||||
reason => 'a is a duplicate of PRIMARY',
|
||||
dupe_type => 'exact',
|
||||
duplicate_of => 'PRIMARY',
|
||||
duplicate_of_cols => ['a'],
|
||||
duplicate_of_ddl => 'PRIMARY KEY (`a`),',
|
||||
}],
|
||||
'Issue 1192'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
my $output = '';
|
||||
{
|
||||
local *STDERR;
|
||||
open STDERR, '>', \$output;
|
||||
$dk->_d('Complete test coverage');
|
||||
}
|
||||
like(
|
||||
$output,
|
||||
qr/Complete test coverage/,
|
||||
'_d() works'
|
||||
);
|
||||
exit;
|
Reference in New Issue
Block a user