mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-12 06:00:14 +00:00
PT-1572 WIP
This commit is contained in:
@@ -13262,6 +13262,10 @@ the values are converted to strings by the CONCAT() function, and MySQL chooses
|
||||
the string representation. If you specify a value of 2, for example, then the
|
||||
values 1.008 and 1.009 will be rounded to 1.01, and will checksum as equal.
|
||||
|
||||
=item --force-concat-enums
|
||||
|
||||
bla bla bla bla bla
|
||||
|
||||
=item --function
|
||||
|
||||
type: string
|
||||
|
@@ -134,14 +134,37 @@ sub new {
|
||||
);
|
||||
PTDEBUG && _d('Ascend params:', Dumper($asc));
|
||||
|
||||
# Check if enum fields items are sorted or not.
|
||||
# If they are sorted we can skip adding CONCAT to improve the queries eficiency.
|
||||
my $force_concat_enums = $o->has('force-concat-enums') && $o->get('force-concat-enums');
|
||||
for my $index (@{$index_cols}) {
|
||||
if ($tbl->{tbl_struct}->{type_for}->{$index} eq 'enum') {
|
||||
if ($tbl->{tbl_struct}->{defs}->{$index} =~ m/enum\s*\((.*?)\)/) {
|
||||
my @items = split(/,\s*/, $1);
|
||||
my $sorted = 1; # Asume the items list is sorted to later check if this is true
|
||||
for (my $i=1; $i < scalar(@items); $i++) {
|
||||
if ($items[$i-1] gt $items[$i]) {
|
||||
$sorted = 0;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (!$force_concat_enums && !$sorted) {
|
||||
die "The index " . $index . " in table " . $tbl->{name} .
|
||||
" has unsorted enum items.\nPlease read the documentation for the --force-concat-enums parameter\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Make SQL statements, prepared on first call to next(). FROM and
|
||||
# ORDER BY are the same for all statements. FORCE IDNEX and ORDER BY
|
||||
# are needed to ensure deterministic nibbling.
|
||||
|
||||
my $from = "$tbl->{name} FORCE INDEX(`$index`)";
|
||||
my $order_by = join(', ', map { $tbl->{tbl_struct}->{type_for}->{$_} eq 'enum'
|
||||
my $order_by = join(', ', map { $tbl->{tbl_struct}->{type_for}->{$_} eq 'enum' && $force_concat_enums
|
||||
? "CONCAT(".$q->quote($_).")" : $q->quote($_)} @{$index_cols});
|
||||
|
||||
my $order_by_dec = join(' DESC,', map { $tbl->{tbl_struct}->{type_for}->{$_} eq 'enum'
|
||||
my $order_by_dec = join(' DESC,', map { $tbl->{tbl_struct}->{type_for}->{$_} eq 'enum' && $force_concat_enums
|
||||
? "CONCAT(".$q->quote($_).")" : $q->quote($_)} @{$index_cols});
|
||||
|
||||
# The real first row in the table. Usually we start nibbling from
|
||||
|
@@ -38,6 +38,8 @@ my $dbh = $sb->get_dbh_for('master');
|
||||
|
||||
if ( !$dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master';
|
||||
} else {
|
||||
plan tests => 60;
|
||||
}
|
||||
|
||||
my $q = new Quoter();
|
||||
@@ -879,7 +881,7 @@ is_deeply(
|
||||
# #############################################################################
|
||||
|
||||
diag(`/tmp/12345/use < $trunk/t/lib/samples/cardinality.sql >/dev/null`);
|
||||
|
||||
$dbh->do('analyze table bad_tables.inv');
|
||||
$ni = make_nibble_iter(
|
||||
db => 'cardb',
|
||||
tbl => 't',
|
||||
@@ -892,6 +894,56 @@ is(
|
||||
"Use non-unique index with highest cardinality (bug 1199591)"
|
||||
);
|
||||
|
||||
$sb->load_file('master', "t/lib/samples/NibbleIterator/enum_keys.sql");
|
||||
$ni = undef;
|
||||
eval {
|
||||
$ni = make_nibble_iter(
|
||||
db => 'test',
|
||||
tbl => 't1',
|
||||
argv => [qw(--databases test --chunk-size 3)],
|
||||
);
|
||||
};
|
||||
|
||||
like(
|
||||
$EVAL_ERROR,
|
||||
qr/The index f3 in table `test`.`t1` has unsorted enum items/,
|
||||
"PT-1572 Die on unsorted enum items in index",
|
||||
);
|
||||
|
||||
eval {
|
||||
$ni = make_nibble_iter(
|
||||
db => 'test',
|
||||
tbl => 't1',
|
||||
argv => [qw(--databases test --force-concat-enums --chunk-size 3)],
|
||||
);
|
||||
};
|
||||
|
||||
like(
|
||||
$ni->{explain_first_lb_sql},
|
||||
qr/ORDER BY `f1`, `f2`, CONCAT\(`f3`\)/,
|
||||
"PT-1572 Use of CONCAT for unsorted ENUM field items without --",
|
||||
);
|
||||
|
||||
eval {
|
||||
$ni = make_nibble_iter(
|
||||
db => 'test',
|
||||
tbl => 't2',
|
||||
argv => [qw(--databases test --chunk-size 3)],
|
||||
);
|
||||
};
|
||||
|
||||
is(
|
||||
$EVAL_ERROR,
|
||||
'',
|
||||
"PT-1572 No errors on sorted enum items in index",
|
||||
);
|
||||
|
||||
like(
|
||||
$ni->{explain_first_lb_sql},
|
||||
qr/ORDER BY `f1`, `f2`, `f3`/,
|
||||
"PT-1572 Don't use CONCAT for sorted ENUM field items without --force-concat-enums",
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
@@ -905,6 +957,7 @@ like(
|
||||
qr/Complete test coverage/,
|
||||
'_d() works'
|
||||
);
|
||||
|
||||
$sb->wipe_clean($dbh);
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
done_testing;
|
||||
|
47
t/lib/samples/NibbleIterator/enum_keys.sql
Normal file
47
t/lib/samples/NibbleIterator/enum_keys.sql
Normal file
@@ -0,0 +1,47 @@
|
||||
DROP DATABASE IF EXISTS test;
|
||||
CREATE DATABASE test;
|
||||
USE test;
|
||||
|
||||
-- Don't change the comments. The enum word inside the comment is there to test the table parser
|
||||
|
||||
CREATE TABLE `test`.`t1` (
|
||||
f1 DATE NOT NULL,
|
||||
f2 INT(10) UNSIGNED NOT NULL,
|
||||
f3 ENUM('c','a','b','d') NOT NULL DEFAULT 'c' COMMENT "unsorted enum items",
|
||||
f4 INT(10) UNSIGNED NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`f1`,`f2`,`f3`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
INSERT INTO `t1` VALUES
|
||||
('2018-07-27',165910161,'c',1375471152),
|
||||
('2018-07-27',393713658,'d',1382302491),
|
||||
('2018-07-27',472875023,'c',525456967),
|
||||
('2018-07-27',543582931,'c',1657080267),
|
||||
('2018-07-27',583532949,'d',280366509),
|
||||
('2018-07-27',1396416465,'d',1252007743),
|
||||
('2018-07-27',1705409249,'c',1714682759),
|
||||
('2018-07-27',1801160058,'a',1022430181),
|
||||
('2018-07-27',1898674299,'c',1310715836),
|
||||
('2018-07-27',2011751560,'a',109015753);
|
||||
|
||||
CREATE TABLE `test`.`t2` (
|
||||
f1 DATE NOT NULL,
|
||||
f2 INT(10) UNSIGNED NOT NULL,
|
||||
f3 ENUM('a','b','c','d') NOT NULL DEFAULT 'c' COMMENT "sorted enum items",
|
||||
f4 INT(10) UNSIGNED NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`f1`,`f2`,`f3`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
INSERT INTO `t2` VALUES
|
||||
('2018-07-27',165910161,'c',1375471152),
|
||||
('2018-07-27',393713658,'d',1382302491),
|
||||
('2018-07-27',472875023,'c',525456967),
|
||||
('2018-07-27',543582931,'c',1657080267),
|
||||
('2018-07-27',583532949,'d',280366509),
|
||||
('2018-07-27',1396416465,'d',1252007743),
|
||||
('2018-07-27',1705409249,'c',1714682759),
|
||||
('2018-07-27',1801160058,'a',1022430181),
|
||||
('2018-07-27',1898674299,'c',1310715836),
|
||||
('2018-07-27',2011751560,'a',109015753);
|
Reference in New Issue
Block a user