mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-04 19:37:49 +00:00
Handle resume in NibbleIterator.
This commit is contained in:
@@ -64,6 +64,14 @@ sub new {
|
||||
: 0;
|
||||
MKDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
|
||||
|
||||
if ( my $nibble = $args{resume} ) {
|
||||
if ( !defined $nibble->{lower_boundary}
|
||||
&& !defined $nibble->{upper_boundary} ) {
|
||||
MKDEBUG && _d('Resuming from one nibble table');
|
||||
$one_nibble = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Get an index to nibble by. We'll order rows by the index's columns.
|
||||
my $index = _find_best_index(%args, mysql_index => $mysql_index);
|
||||
if ( !$index && !$one_nibble ) {
|
||||
@@ -103,6 +111,7 @@ sub new {
|
||||
limit => 0,
|
||||
nibble_sql => $nibble_sql,
|
||||
explain_nibble_sql => $explain_nibble_sql,
|
||||
no_more_boundaries => $args{resume} ? 1 : 0,
|
||||
};
|
||||
}
|
||||
else {
|
||||
@@ -125,11 +134,15 @@ sub new {
|
||||
my $order_by = join(', ', map {$q->quote($_)} @{$index_cols});
|
||||
|
||||
# These statements are only executed once, so they don't use sths.
|
||||
my $first_lb_where = $where ? "($where)" : '';
|
||||
if ( $args{resume} ) {
|
||||
$first_lb_where .= ($where ? " AND " : '') . $asc->{boundaries}->{'>'};
|
||||
}
|
||||
my $first_lb_sql
|
||||
= "SELECT /*!40001 SQL_NO_CACHE */ "
|
||||
. join(', ', map { $q->quote($_) } @{$asc->{scols}})
|
||||
. " FROM $from"
|
||||
. ($where ? " WHERE $where" : '')
|
||||
. ($first_lb_where ? " WHERE $first_lb_where" : '')
|
||||
. " ORDER BY $order_by"
|
||||
. " LIMIT 1"
|
||||
. " /*first lower boundary*/";
|
||||
@@ -204,6 +217,7 @@ sub new {
|
||||
nibble_sql => $nibble_sql,
|
||||
explain_ub_sql => "EXPLAIN $ub_sql",
|
||||
explain_nibble_sql => $explain_nibble_sql,
|
||||
resume => $args{resume},
|
||||
sql => {
|
||||
columns => $asc->{scols},
|
||||
from => $from,
|
||||
@@ -520,7 +534,17 @@ sub _get_bounds {
|
||||
|
||||
my $dbh = $self->{Cxn}->dbh();
|
||||
|
||||
$self->{first_lower} = $dbh->selectrow_arrayref($self->{first_lb_sql});
|
||||
if ( my $nibble = $self->{resume} ) {
|
||||
my $sth = $dbh->prepare($self->{first_lb_sql});
|
||||
my @ub = split ',', $nibble->{upper_boundary};
|
||||
MKDEBUG && _d($sth->{Statement}, 'params:', @ub);
|
||||
$sth->execute(@ub);
|
||||
$self->{first_lower} = $sth->fetchrow_arrayref();
|
||||
$sth->finish();
|
||||
}
|
||||
else {
|
||||
$self->{first_lower} = $dbh->selectrow_arrayref($self->{first_lb_sql});
|
||||
}
|
||||
$self->{next_lower} = $self->{first_lower};
|
||||
MKDEBUG && _d('First lower boundary:', Dumper($self->{next_lower}));
|
||||
|
||||
@@ -544,6 +568,13 @@ sub _next_boundaries {
|
||||
return 1; # continue nibbling
|
||||
}
|
||||
|
||||
if ( !$self->{next_lower} ) {
|
||||
# This happens if we resume from the end of the table.
|
||||
MKDEBUG && _d('At end of table');
|
||||
$self->{no_more_boundaries} = 1; # for next call
|
||||
return; # stop nibbling
|
||||
}
|
||||
|
||||
# Detect infinite loops. If the lower boundary we just nibbled from
|
||||
# is identical to the next lower boundary, then this next nibble won't
|
||||
# go anywhere, so to speak, unless perhaps the chunk size has changed
|
||||
|
@@ -39,7 +39,7 @@ if ( !$dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master';
|
||||
}
|
||||
else {
|
||||
plan tests => 42;
|
||||
plan tests => 44;
|
||||
}
|
||||
|
||||
my $q = new Quoter();
|
||||
@@ -92,6 +92,7 @@ sub make_nibble_iter {
|
||||
callbacks => $args{callbacks},
|
||||
select => $args{select},
|
||||
one_nibble => $args{one_nibble},
|
||||
resume => $args{resume},
|
||||
%common_modules,
|
||||
);
|
||||
|
||||
@@ -720,6 +721,47 @@ is_deeply(
|
||||
"--chunk-size-limit 0 on empty table"
|
||||
);
|
||||
|
||||
# ############################################################################
|
||||
# Resume.
|
||||
# ############################################################################
|
||||
$ni = make_nibble_iter(
|
||||
sql_file => "a-z.sql",
|
||||
db => 'test',
|
||||
tbl => 't',
|
||||
argv => [qw(--databases test --chunk-size 5)],
|
||||
resume => { upper_boundary => 'j' },
|
||||
);
|
||||
|
||||
@rows = ();
|
||||
while (my $row = $ni->next()) {
|
||||
push @rows, @$row;
|
||||
}
|
||||
|
||||
is_deeply(
|
||||
\@rows,
|
||||
[ ('k'..'z') ],
|
||||
"Resume from middle"
|
||||
);
|
||||
|
||||
$ni = make_nibble_iter(
|
||||
sql_file => "a-z.sql",
|
||||
db => 'test',
|
||||
tbl => 't',
|
||||
argv => [qw(--databases test --chunk-size 5)],
|
||||
resume => { upper_boundary => 'z' },
|
||||
);
|
||||
|
||||
@rows = ();
|
||||
while (my $row = $ni->next()) {
|
||||
push @rows, @$row;
|
||||
}
|
||||
|
||||
is_deeply(
|
||||
\@rows,
|
||||
[ ],
|
||||
"Resume from end"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
Reference in New Issue
Block a user