mirror of
https://github.com/percona/percona-toolkit.git
synced 2026-04-17 01:01:39 +08:00
Merge pt-osc-2.1. Fix NibbleItertor.pm to work with OobNibbleIterator when resuming at oob boundaries (t/pt-table-checksum/resume.t was failing).
This commit is contained in:
@@ -9,7 +9,7 @@ BEGIN {
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use Test::More tests => 2;
|
||||
use Test::More tests => 4;
|
||||
|
||||
use PerconaTest;
|
||||
use CleanupTask;
|
||||
@@ -30,6 +30,23 @@ is(
|
||||
"Cleanup task called after obj destroyed"
|
||||
);
|
||||
|
||||
|
||||
$foo = 0;
|
||||
my $set_foo = new CleanupTask(sub { $foo = 42; });
|
||||
|
||||
is(
|
||||
$foo,
|
||||
0,
|
||||
"Cleanup task not called yet"
|
||||
);
|
||||
|
||||
$set_foo = undef;
|
||||
is(
|
||||
$foo,
|
||||
42,
|
||||
"Cleanup task called after obj=undef"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
||||
@@ -9,7 +9,7 @@ BEGIN {
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use Test::More tests => 12;
|
||||
use Test::More tests => 14;
|
||||
|
||||
use MySQLStatusWaiter;
|
||||
use PerconaTest;
|
||||
@@ -72,7 +72,7 @@ my $sw = new MySQLStatusWaiter(
|
||||
oktorun => \&oktorun,
|
||||
get_status => \&get_status,
|
||||
sleep => \&sleep,
|
||||
spec => [qw(Threads_connected Threads_running)],
|
||||
max_spec => [qw(Threads_connected Threads_running)],
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
@@ -136,7 +136,7 @@ $sw = new MySQLStatusWaiter(
|
||||
oktorun => \&oktorun,
|
||||
get_status => \&get_status,
|
||||
sleep => \&sleep,
|
||||
spec => [qw(Threads_connected=5 Threads_running=5)],
|
||||
max_spec => [qw(Threads_connected=5 Threads_running=5)],
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
@@ -178,7 +178,7 @@ $sw = new MySQLStatusWaiter(
|
||||
oktorun => \&oktorun,
|
||||
get_status => \&get_status,
|
||||
sleep => \&sleep,
|
||||
spec => [],
|
||||
max_spec => [],
|
||||
);
|
||||
|
||||
is(
|
||||
@@ -204,6 +204,40 @@ is(
|
||||
"No spec, no sleep"
|
||||
);
|
||||
|
||||
# ############################################################################
|
||||
# Critical thresholds (with static vals).
|
||||
# ############################################################################
|
||||
@vals = (
|
||||
# first check, no wait
|
||||
{ Threads_running => 1, },
|
||||
{ Threads_running => 9, },
|
||||
);
|
||||
|
||||
$sw = new MySQLStatusWaiter(
|
||||
oktorun => \&oktorun,
|
||||
get_status => \&get_status,
|
||||
sleep => \&sleep,
|
||||
max_spec => [qw(Threads_running=4)],
|
||||
critical_spec => [qw(Threads_running=8)],
|
||||
|
||||
);
|
||||
|
||||
@checked = ();
|
||||
$slept = 0;
|
||||
$sw->wait();
|
||||
|
||||
is(
|
||||
$slept,
|
||||
0,
|
||||
"Vals not critical, did not sleep"
|
||||
);
|
||||
|
||||
throws_ok(
|
||||
sub { $sw->wait(); },
|
||||
qr/Threads_running=9 exceeds its critical threshold 8/,
|
||||
"Die on critical threshold"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
||||
@@ -39,7 +39,7 @@ if ( !$dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master';
|
||||
}
|
||||
else {
|
||||
plan tests => 46;
|
||||
plan tests => 48;
|
||||
}
|
||||
|
||||
my $q = new Quoter();
|
||||
@@ -94,6 +94,7 @@ sub make_nibble_iter {
|
||||
one_nibble => $args{one_nibble},
|
||||
resume => $args{resume},
|
||||
order_by => $args{order_by},
|
||||
comments => $args{comments},
|
||||
%common_modules,
|
||||
);
|
||||
|
||||
@@ -527,7 +528,7 @@ $ni = make_nibble_iter(
|
||||
$ni->next();
|
||||
is(
|
||||
$ni->statements()->{nibble}->{Statement},
|
||||
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code` FROM `sakila`.`address` FORCE INDEX(`PRIMARY`) WHERE ((`address_id` >= ?)) AND ((`address_id` <= ?)) /*checksum chunk*/",
|
||||
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code` FROM `sakila`.`address` FORCE INDEX(`PRIMARY`) WHERE ((`address_id` >= ?)) AND ((`address_id` <= ?)) /*nibble table*/",
|
||||
"--ignore-columns"
|
||||
);
|
||||
|
||||
@@ -545,7 +546,7 @@ $ni->next();
|
||||
|
||||
is(
|
||||
$ni->statements()->{nibble}->{Statement},
|
||||
"SELECT `actor_id`, `film_id`, `last_update` FROM `sakila`.`film_actor` FORCE INDEX(`PRIMARY`) WHERE ((`actor_id` > ?) OR (`actor_id` = ? AND `film_id` >= ?)) AND ((`actor_id` < ?) OR (`actor_id` = ? AND `film_id` <= ?)) ORDER BY `actor_id`, `film_id` /*checksum chunk*/",
|
||||
"SELECT `actor_id`, `film_id`, `last_update` FROM `sakila`.`film_actor` FORCE INDEX(`PRIMARY`) WHERE ((`actor_id` > ?) OR (`actor_id` = ? AND `film_id` >= ?)) AND ((`actor_id` < ?) OR (`actor_id` = ? AND `film_id` <= ?)) ORDER BY `actor_id`, `film_id` /*nibble table*/",
|
||||
"Add ORDER BY to nibble SQL"
|
||||
);
|
||||
|
||||
@@ -722,7 +723,7 @@ $ni = make_nibble_iter(
|
||||
my $sql = $ni->statements()->{nibble}->{Statement};
|
||||
is(
|
||||
$sql,
|
||||
"SELECT `c` FROM `test`.`t` WHERE c>'m' /*checksum table*/",
|
||||
"SELECT `c` FROM `test`.`t` WHERE c>'m' /*bite table*/",
|
||||
"One nibble SQL with where"
|
||||
);
|
||||
|
||||
@@ -795,6 +796,43 @@ is_deeply(
|
||||
"Resume from end"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Customize bite and nibble statement comments.
|
||||
# #############################################################################
|
||||
$ni = make_nibble_iter(
|
||||
db => 'sakila',
|
||||
tbl => 'address',
|
||||
argv => [qw(--tables sakila.address --chunk-size 10)],
|
||||
comments => {
|
||||
bite => "my bite",
|
||||
nibble => "my nibble",
|
||||
}
|
||||
);
|
||||
|
||||
$ni->next();
|
||||
is(
|
||||
$ni->statements()->{nibble}->{Statement},
|
||||
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code`, `phone`, `last_update` FROM `sakila`.`address` FORCE INDEX(`PRIMARY`) WHERE ((`address_id` >= ?)) AND ((`address_id` <= ?)) /*my nibble*/",
|
||||
"Custom nibble comment"
|
||||
);
|
||||
|
||||
$ni = make_nibble_iter(
|
||||
db => 'sakila',
|
||||
tbl => 'address',
|
||||
argv => [qw(--tables sakila.address --chunk-size 1000)],
|
||||
comments => {
|
||||
bite => "my bite",
|
||||
nibble => "my nibble",
|
||||
}
|
||||
);
|
||||
|
||||
$ni->next();
|
||||
is(
|
||||
$ni->statements()->{nibble}->{Statement},
|
||||
"SELECT `address_id`, `address`, `address2`, `district`, `city_id`, `postal_code`, `phone`, `last_update` FROM `sakila`.`address` /*my bite*/",
|
||||
"Custom bite comment"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
#!/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;
|
||||
|
||||
use DSNParser;
|
||||
use Sandbox;
|
||||
use PerconaTest;
|
||||
use Quoter;
|
||||
use OSCCaptureSync;
|
||||
|
||||
use Data::Dumper;
|
||||
$Data::Dumper::Indent = 1;
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
$Data::Dumper::Quotekeys = 0;
|
||||
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $dbh = $sb->get_dbh_for('master');
|
||||
|
||||
if ( !$dbh ) {
|
||||
plan skip_all => 'Cannot connect to MySQL';
|
||||
|
||||
}
|
||||
else {
|
||||
plan tests => 10;
|
||||
}
|
||||
|
||||
my $q = new Quoter();
|
||||
my $osc = new OSCCaptureSync(Quoter => $q);
|
||||
my $msg = sub { print "$_[0]\n"; };
|
||||
my $output;
|
||||
|
||||
sub test_table {
|
||||
my (%args) = @_;
|
||||
my ($tbl, $col, $expect) = @args{qw(tbl col expect)};
|
||||
|
||||
$sb->load_file("master", "t/lib/samples/osc/$tbl");
|
||||
PerconaTest::wait_for_table($dbh, "osc.t", "id=5");
|
||||
$dbh->do("USE osc");
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub {
|
||||
$osc->capture(
|
||||
dbh => $dbh,
|
||||
db => 'osc',
|
||||
tbl => 't',
|
||||
tmp_tbl => '__new_t',
|
||||
columns => ['id', $col],
|
||||
chunk_column => 'id',
|
||||
msg => $msg,
|
||||
)
|
||||
},
|
||||
"t/lib/samples/osc/$expect",
|
||||
stderr => 1,
|
||||
),
|
||||
"$tbl: SQL statments to create triggers"
|
||||
);
|
||||
|
||||
$dbh->do("insert into t values (6, 'f')");
|
||||
$dbh->do("update t set `$col`='z' where id=1");
|
||||
$dbh->do("delete from t where id=3");
|
||||
|
||||
my $rows = $dbh->selectall_arrayref("select id, `$col` from __new_t order by id");
|
||||
is_deeply(
|
||||
$rows,
|
||||
[
|
||||
[1, 'z'], # update t set c="z" where id=1
|
||||
[6, 'f'], # insert into t values (6, "f")
|
||||
],
|
||||
"$tbl: Triggers work"
|
||||
) or print Dumper($rows);
|
||||
|
||||
output(sub {
|
||||
$osc->cleanup(
|
||||
dbh => $dbh,
|
||||
db => 'osc',
|
||||
msg => $msg,
|
||||
);
|
||||
});
|
||||
|
||||
$rows = $dbh->selectall_arrayref("show triggers from `osc` like 't'");
|
||||
is_deeply(
|
||||
$rows,
|
||||
[],
|
||||
"$tbl: Cleanup removes the triggers"
|
||||
);
|
||||
}
|
||||
|
||||
test_table(
|
||||
tbl => "tbl001.sql",
|
||||
col => "c",
|
||||
expect => "capsync001.txt",
|
||||
);
|
||||
|
||||
test_table(
|
||||
tbl => "tbl002.sql",
|
||||
col => "default",
|
||||
expect => "capsync002.txt",
|
||||
);
|
||||
|
||||
test_table(
|
||||
tbl => "tbl003.sql",
|
||||
col => "space col",
|
||||
expect => "capsync003.txt",
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
{
|
||||
local *STDERR;
|
||||
open STDERR, '>', \$output;
|
||||
$osc->_d('Complete test coverage');
|
||||
}
|
||||
like(
|
||||
$output,
|
||||
qr/Complete test coverage/,
|
||||
'_d() works'
|
||||
);
|
||||
$sb->wipe_clean($dbh);
|
||||
exit;
|
||||
@@ -191,7 +191,6 @@ $ni = make_nibble_iter(
|
||||
argv => [qw(--databases test --chunk-size 8)],
|
||||
);
|
||||
|
||||
|
||||
$dbh->do("delete from test.t where c='a' or c='z'");
|
||||
|
||||
@rows = ();
|
||||
@@ -204,8 +203,6 @@ is_deeply(
|
||||
'a-z nibble 1 with oob'
|
||||
) or print Dumper(\@rows);
|
||||
|
||||
$dbh->do("insert into test.t values ('a'), ('z')");
|
||||
|
||||
@rows = ();
|
||||
for (1..8) {
|
||||
push @rows, $ni->next();
|
||||
@@ -226,6 +223,13 @@ is_deeply(
|
||||
'a-z nibble 3 with oob'
|
||||
) or print Dumper(\@rows);
|
||||
|
||||
# NibbleIterator is done (b-y), now insert a row on the low end (a),
|
||||
# and one on the high end (z), past what NibbleIterator originally
|
||||
# saw as the first and last boundaries. OobNibbleIterator should kick
|
||||
# in and see a and z.
|
||||
$dbh->do("insert into test.t values ('a'), ('z')");
|
||||
|
||||
# OobNibbleIterator checks the low end first.
|
||||
@rows = ();
|
||||
push @rows, $ni->next();
|
||||
is_deeply(
|
||||
@@ -234,6 +238,7 @@ is_deeply(
|
||||
'a-z nibble 4 lower oob'
|
||||
) or print Dumper(\@rows);
|
||||
|
||||
# Then it checks the high end.
|
||||
@rows = ();
|
||||
push @rows, $ni->next();
|
||||
is_deeply(
|
||||
|
||||
Reference in New Issue
Block a user