mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-25 21:54:48 +00:00
PT-1114 test fix
This commit is contained in:
@@ -6292,6 +6292,7 @@ use strict;
|
|||||||
use warnings FATAL => 'all';
|
use warnings FATAL => 'all';
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||||
|
use IndexLength;
|
||||||
|
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
$Data::Dumper::Indent = 1;
|
$Data::Dumper::Indent = 1;
|
||||||
@@ -6690,11 +6691,11 @@ sub row_estimate {
|
|||||||
|
|
||||||
sub can_nibble {
|
sub can_nibble {
|
||||||
my (%args) = @_;
|
my (%args) = @_;
|
||||||
my @required_args = qw(Cxn tbl chunk_size OptionParser TableParser);
|
my @required_args = qw(Cxn tbl chunk_size OptionParser TableParser Quoter);
|
||||||
foreach my $arg ( @required_args ) {
|
foreach my $arg ( @required_args ) {
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
die "I need a $arg argument" unless $args{$arg};
|
||||||
}
|
}
|
||||||
my ($cxn, $tbl, $chunk_size, $o) = @args{@required_args};
|
my ($cxn, $tbl, $chunk_size, $o, $q) = @args{@required_args};
|
||||||
|
|
||||||
my $where = $o->has('where') ? $o->get('where') : '';
|
my $where = $o->has('where') ? $o->get('where') : '';
|
||||||
|
|
||||||
@@ -6705,13 +6706,30 @@ sub can_nibble {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ( !$where ) {
|
if ( !$where ) {
|
||||||
$mysql_index = undef;
|
$mysql_index = undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $chunk_size_limit = $o->get('chunk-size-limit') || 1;
|
my $chunk_size_limit = $o->get('chunk-size-limit') || 1;
|
||||||
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
|
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
|
||||||
? $row_est <= $chunk_size * $chunk_size_limit
|
? $row_est <= $chunk_size * $chunk_size_limit
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
if ($mysql_index) {
|
||||||
|
my $idx_len = IndexLength->new(Quoter => $q);
|
||||||
|
my ($key_len, $key) = $idx_len->index_length(
|
||||||
|
Cxn => $args{Cxn},
|
||||||
|
tbl => $tbl,
|
||||||
|
index => $mysql_index,
|
||||||
|
n_index_cols => $o->get('chunk-index-columns'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( !$key || !$key_len || lc($key) ne lc($mysql_index)) {
|
||||||
|
$one_nibble = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$one_nibble = 1;
|
||||||
|
}
|
||||||
|
|
||||||
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
|
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
|
||||||
|
|
||||||
if ( $args{resume}
|
if ( $args{resume}
|
||||||
@@ -9660,14 +9678,14 @@ sub _get_first_values {
|
|||||||
. "WHERE " . join(' AND ', @where)
|
. "WHERE " . join(' AND ', @where)
|
||||||
. " ORDER BY $index_columns "
|
. " ORDER BY $index_columns "
|
||||||
. "LIMIT 1 /*key_len*/"; # only need 1 row
|
. "LIMIT 1 /*key_len*/"; # only need 1 row
|
||||||
PTDEBUG && _d($sql);
|
PTDEBUG && _d("_get_first_values: $sql");
|
||||||
my $vals = $cxn->dbh()->selectrow_arrayref($sql);
|
my $vals = $cxn->dbh()->selectrow_arrayref($sql);
|
||||||
return $vals;
|
return $vals;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _make_range_query {
|
sub _make_range_query {
|
||||||
my ($self, %args) = @_;
|
my ($self, %args) = @_;
|
||||||
my @required_args = qw(tbl index n_index_cols vals);
|
my @required_args = qw(tbl index n_index_cols);
|
||||||
foreach my $arg ( @required_args ) {
|
foreach my $arg ( @required_args ) {
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
die "I need a $arg argument" unless $args{$arg};
|
||||||
}
|
}
|
||||||
@@ -9682,13 +9700,11 @@ sub _make_range_query {
|
|||||||
if ( $n_index_cols > 1 ) {
|
if ( $n_index_cols > 1 ) {
|
||||||
foreach my $n ( 0..($n_index_cols - 2) ) {
|
foreach my $n ( 0..($n_index_cols - 2) ) {
|
||||||
my $col = $index_cols->[$n];
|
my $col = $index_cols->[$n];
|
||||||
my $val = $vals->[$n];
|
|
||||||
push @where, $q->quote($col) . " = ?";
|
push @where, $q->quote($col) . " = ?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $col = $index_cols->[$n_index_cols - 1];
|
my $col = $index_cols->[$n_index_cols - 1];
|
||||||
my $val = $vals->[-1]; # should only be as many vals as cols
|
|
||||||
push @where, $q->quote($col) . " >= ?";
|
push @where, $q->quote($col) . " >= ?";
|
||||||
|
|
||||||
my $sql = "EXPLAIN SELECT /*!40001 SQL_NO_CACHE */ * "
|
my $sql = "EXPLAIN SELECT /*!40001 SQL_NO_CACHE */ * "
|
||||||
|
@@ -26,6 +26,7 @@ use strict;
|
|||||||
use warnings FATAL => 'all';
|
use warnings FATAL => 'all';
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||||
|
use IndexLength;
|
||||||
|
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
$Data::Dumper::Indent = 1;
|
$Data::Dumper::Indent = 1;
|
||||||
@@ -487,11 +488,11 @@ sub row_estimate {
|
|||||||
|
|
||||||
sub can_nibble {
|
sub can_nibble {
|
||||||
my (%args) = @_;
|
my (%args) = @_;
|
||||||
my @required_args = qw(Cxn tbl chunk_size OptionParser TableParser);
|
my @required_args = qw(Cxn tbl chunk_size OptionParser TableParser Quoter);
|
||||||
foreach my $arg ( @required_args ) {
|
foreach my $arg ( @required_args ) {
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
die "I need a $arg argument" unless $args{$arg};
|
||||||
}
|
}
|
||||||
my ($cxn, $tbl, $chunk_size, $o) = @args{@required_args};
|
my ($cxn, $tbl, $chunk_size, $o, $q) = @args{@required_args};
|
||||||
|
|
||||||
my $where = $o->has('where') ? $o->get('where') : '';
|
my $where = $o->has('where') ? $o->get('where') : '';
|
||||||
|
|
||||||
@@ -502,6 +503,23 @@ sub can_nibble {
|
|||||||
where => $where,
|
where => $where,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
my $can_get_keys;
|
||||||
|
if ($mysql_index) {
|
||||||
|
my $idx_len = IndexLength->new(Quoter => $q);
|
||||||
|
my ($key_len, $key) = $idx_len->index_length(
|
||||||
|
Cxn => $args{Cxn},
|
||||||
|
tbl => $tbl,
|
||||||
|
index => $mysql_index,
|
||||||
|
n_index_cols => $o->get('chunk-index-columns'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( !$key || !$key_len || lc($key) ne lc($mysql_index)) {
|
||||||
|
$can_get_keys = 0;
|
||||||
|
} else {
|
||||||
|
$can_get_keys = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# MySQL's chosen index is only something we should prefer
|
# MySQL's chosen index is only something we should prefer
|
||||||
# if --where is used. Else, we can chose our own index
|
# if --where is used. Else, we can chose our own index
|
||||||
# and disregard the MySQL index from the row estimate.
|
# and disregard the MySQL index from the row estimate.
|
||||||
@@ -521,6 +539,10 @@ sub can_nibble {
|
|||||||
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
|
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
|
||||||
? $row_est <= $chunk_size * $chunk_size_limit
|
? $row_est <= $chunk_size * $chunk_size_limit
|
||||||
: 0;
|
: 0;
|
||||||
|
if (!$can_get_keys) {
|
||||||
|
$one_nibble = 1;
|
||||||
|
}
|
||||||
|
|
||||||
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
|
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
|
||||||
|
|
||||||
# Special case: we're resuming and there's no boundaries, so the table
|
# Special case: we're resuming and there's no boundaries, so the table
|
||||||
|
72
t/pt-table-checksum/pt-1114.t
Normal file
72
t/pt-table-checksum/pt-1114.t
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env 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;
|
||||||
|
|
||||||
|
use PerconaTest;
|
||||||
|
use Sandbox;
|
||||||
|
use SqlModes;
|
||||||
|
require "$trunk/bin/pt-table-checksum";
|
||||||
|
|
||||||
|
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||||
|
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||||
|
my $dsn = $sb->dsn_for('master');
|
||||||
|
my $dbh = $sb->get_dbh_for('master');
|
||||||
|
|
||||||
|
if ( !$dbh ) {
|
||||||
|
plan skip_all => 'Cannot connect to sandbox master';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
plan tests => 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
diag("loading samples");
|
||||||
|
$sb->load_file('master', 't/pt-table-checksum/samples/pt-1114.sql');
|
||||||
|
|
||||||
|
my $master_port = $sb->port_for('master');
|
||||||
|
my $num_rows = 40000;
|
||||||
|
|
||||||
|
diag(`util/mysql_random_data_load --host=127.0.0.1 --port=$master_port --user=msandbox --password=msandbox test t1 $num_rows`);
|
||||||
|
|
||||||
|
$dbh->do('set global innodb_stats_persistent=0;');
|
||||||
|
$dbh->do('DELETE FROM test.t1');
|
||||||
|
|
||||||
|
my @args = ($dsn);
|
||||||
|
my $output;
|
||||||
|
my $exit_status;
|
||||||
|
|
||||||
|
# Test #1
|
||||||
|
$output = output(
|
||||||
|
sub { $exit_status = pt_table_checksum::main(@args) },
|
||||||
|
stderr => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
$exit_status,
|
||||||
|
0,
|
||||||
|
"Exit status OK",
|
||||||
|
);
|
||||||
|
diag($output);
|
||||||
|
|
||||||
|
like(
|
||||||
|
$output,
|
||||||
|
qr/0\s+0\s+0\s+0\s+1\s+0\s+\d+\.\d+\s+test\.t1/,
|
||||||
|
"Checksumed test.t1 even when it is empty",
|
||||||
|
);
|
||||||
|
|
||||||
|
$dbh->do('SET GLOBAL binlog_format="STATEMENT"');
|
||||||
|
|
||||||
|
# #############################################################################
|
||||||
|
# Done.
|
||||||
|
# #############################################################################
|
||||||
|
$sb->wipe_clean($dbh);
|
||||||
|
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||||
|
exit;
|
Reference in New Issue
Block a user