PT-1572 WIP

This commit is contained in:
Carlos Salguero
2018-07-27 22:16:02 -03:00
parent 909125faf9
commit ea4886ad9d
4 changed files with 130 additions and 3 deletions

View File

@@ -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 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. 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 =item --function
type: string type: string

View File

@@ -134,14 +134,37 @@ sub new {
); );
PTDEBUG && _d('Ascend params:', Dumper($asc)); 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 # Make SQL statements, prepared on first call to next(). FROM and
# ORDER BY are the same for all statements. FORCE IDNEX and ORDER BY # ORDER BY are the same for all statements. FORCE IDNEX and ORDER BY
# are needed to ensure deterministic nibbling. # are needed to ensure deterministic nibbling.
my $from = "$tbl->{name} FORCE INDEX(`$index`)"; 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}); ? "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}); ? "CONCAT(".$q->quote($_).")" : $q->quote($_)} @{$index_cols});
# The real first row in the table. Usually we start nibbling from # The real first row in the table. Usually we start nibbling from

View File

@@ -38,6 +38,8 @@ my $dbh = $sb->get_dbh_for('master');
if ( !$dbh ) { if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master'; plan skip_all => 'Cannot connect to sandbox master';
} else {
plan tests => 60;
} }
my $q = new Quoter(); my $q = new Quoter();
@@ -879,7 +881,7 @@ is_deeply(
# ############################################################################# # #############################################################################
diag(`/tmp/12345/use < $trunk/t/lib/samples/cardinality.sql >/dev/null`); diag(`/tmp/12345/use < $trunk/t/lib/samples/cardinality.sql >/dev/null`);
$dbh->do('analyze table bad_tables.inv');
$ni = make_nibble_iter( $ni = make_nibble_iter(
db => 'cardb', db => 'cardb',
tbl => 't', tbl => 't',
@@ -892,6 +894,56 @@ is(
"Use non-unique index with highest cardinality (bug 1199591)" "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. # Done.
# ############################################################################# # #############################################################################
@@ -905,6 +957,7 @@ like(
qr/Complete test coverage/, qr/Complete test coverage/,
'_d() works' '_d() works'
); );
$sb->wipe_clean($dbh); $sb->wipe_clean($dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing; done_testing;

View 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);