mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-20 19:04:59 +00:00
Test and quote all idents, including reserved words and those with spaces, in CopyRowsInsertSelect.pm.
This commit is contained in:
@@ -37,13 +37,14 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
|||||||
# CopyRowsInsertSelect object
|
# CopyRowsInsertSelect object
|
||||||
sub new {
|
sub new {
|
||||||
my ( $class, %args ) = @_;
|
my ( $class, %args ) = @_;
|
||||||
my @required_args = qw(Retry);
|
my @required_args = qw(Retry 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 $self = {
|
my $self = {
|
||||||
%args,
|
Retry => $args{Retry},
|
||||||
|
Quoter => $args{Quoter},
|
||||||
};
|
};
|
||||||
|
|
||||||
return bless $self, $class;
|
return bless $self, $class;
|
||||||
@@ -56,9 +57,10 @@ sub copy {
|
|||||||
die "I need a $arg argument" unless $args{$arg};
|
die "I need a $arg argument" unless $args{$arg};
|
||||||
}
|
}
|
||||||
my ($dbh, $msg, $from_table, $to_table, $chunks) = @args{@required_args};
|
my ($dbh, $msg, $from_table, $to_table, $chunks) = @args{@required_args};
|
||||||
|
my $q = $self->{Quoter};
|
||||||
my $pr = $args{Progress};
|
my $pr = $args{Progress};
|
||||||
my $sleep = $args{sleep};
|
my $sleep = $args{sleep};
|
||||||
my $columns = join(', ', @{$args{columns}});
|
my $columns = join(', ', map { $q->quote($_) } @{$args{columns}});
|
||||||
my $n_chunks = @$chunks - 1;
|
my $n_chunks = @$chunks - 1;
|
||||||
|
|
||||||
for my $chunkno ( 0..$n_chunks ) {
|
for my $chunkno ( 0..$n_chunks ) {
|
||||||
|
@@ -17,6 +17,7 @@ use PerconaTest;
|
|||||||
use Progress;
|
use Progress;
|
||||||
use Transformers;
|
use Transformers;
|
||||||
use Retry;
|
use Retry;
|
||||||
|
use Quoter;
|
||||||
use CopyRowsInsertSelect;
|
use CopyRowsInsertSelect;
|
||||||
|
|
||||||
Transformers->import(qw(secs_to_time));
|
Transformers->import(qw(secs_to_time));
|
||||||
@@ -38,64 +39,124 @@ elsif ( !@{$dbh->selectcol_arrayref('SHOW DATABASES LIKE "sakila"')} ) {
|
|||||||
plan skip_all => "Sandbox master does not have the sakila database";
|
plan skip_all => "Sandbox master does not have the sakila database";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
plan tests => 8;
|
plan tests => 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $q = new Quoter();
|
||||||
my $rr = new Retry();
|
my $rr = new Retry();
|
||||||
my $osc = new CopyRowsInsertSelect(Retry => $rr);
|
my $osc = new CopyRowsInsertSelect(Retry => $rr, Quoter => $q);
|
||||||
my $msg = sub { print "$_[0]\n"; };
|
my $msg = sub { print "$_[0]\n"; };
|
||||||
my $output = "";
|
my $output = "";
|
||||||
|
my $rows;
|
||||||
|
|
||||||
$sb->load_file("master", "t/lib/samples/osc/tbl001.sql");
|
# ###########################################################################
|
||||||
$dbh->do("USE osc");
|
# Copy simple tables.
|
||||||
|
# ###########################################################################
|
||||||
|
|
||||||
$osc->copy(
|
sub test_copy_table {
|
||||||
dbh => $dbh,
|
my (%args) = @_;
|
||||||
from_table => 'osc.t',
|
my ($tbl, $col, $expect) = @args{qw(tbl col expect)};
|
||||||
to_table => 'osc.__new_t',
|
|
||||||
columns => [qw(id c)],
|
$sb->load_file("master", "t/lib/samples/osc/$tbl");
|
||||||
chunks => ['1=1'],
|
PerconaTest::wait_for_table($dbh, "osc.t", "id=5");
|
||||||
msg => $msg,
|
$dbh->do("USE osc");
|
||||||
|
|
||||||
|
$osc->copy(
|
||||||
|
dbh => $dbh,
|
||||||
|
from_table => 'osc.t',
|
||||||
|
to_table => 'osc.__new_t',
|
||||||
|
columns => ['id', $col],
|
||||||
|
chunks => ['1=1'],
|
||||||
|
msg => $msg,
|
||||||
|
);
|
||||||
|
|
||||||
|
$rows = $dbh->selectall_arrayref("select id, `$col` from __new_t order by id");
|
||||||
|
is_deeply(
|
||||||
|
$rows,
|
||||||
|
[ [1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e'], ],
|
||||||
|
"$tbl: One chunk copy"
|
||||||
|
) or print Dumper($rows);
|
||||||
|
|
||||||
|
$dbh->do("truncate table osc.__new_t");
|
||||||
|
|
||||||
|
ok(
|
||||||
|
no_diff(
|
||||||
|
sub {
|
||||||
|
$osc->copy(
|
||||||
|
dbh => $dbh,
|
||||||
|
from_table => 'osc.t',
|
||||||
|
to_table => 'osc.__new_t',
|
||||||
|
columns => ['id', $col],
|
||||||
|
chunks => ['id < 4', 'id >= 4 AND id < 6'],
|
||||||
|
msg => $msg,
|
||||||
|
print => 1,
|
||||||
|
engine_flags => 'LOCK IN SHARE MODE',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
"t/lib/samples/osc/$expect",
|
||||||
|
stderr => 1,
|
||||||
|
),
|
||||||
|
"$tbl: 2 chunk copy"
|
||||||
|
);
|
||||||
|
|
||||||
|
$rows = $dbh->selectall_arrayref("select id, `$col` from __new_t order by id");
|
||||||
|
is_deeply(
|
||||||
|
$rows,
|
||||||
|
[],
|
||||||
|
"$tbl: print doesn't exec statements"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_copy_table(
|
||||||
|
tbl => "tbl001.sql",
|
||||||
|
col => "c",
|
||||||
|
expect => "copyins001.txt",
|
||||||
);
|
);
|
||||||
|
|
||||||
my $rows = $dbh->selectall_arrayref("select id, c from __new_t order by id");
|
# Sleep callback.
|
||||||
is_deeply(
|
my $sleep_cnt = 0;
|
||||||
$rows,
|
|
||||||
[ [1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e'], ],
|
|
||||||
"One chunk copy"
|
|
||||||
) or print Dumper($rows);
|
|
||||||
|
|
||||||
|
|
||||||
$dbh->do("truncate table osc.__new_t");
|
$dbh->do("truncate table osc.__new_t");
|
||||||
$output = output( sub {
|
output( sub {
|
||||||
$osc->copy(
|
$osc->copy(
|
||||||
dbh => $dbh,
|
dbh => $dbh,
|
||||||
from_table => 'osc.t',
|
from_table => 'osc.t',
|
||||||
to_table => 'osc.__new_t',
|
to_table => 'osc.__new_t',
|
||||||
columns => [qw(id c)],
|
columns => [qw(id c)],
|
||||||
chunks => ['id < 4', 'id >= 4 AND id < 6'],
|
chunks => ['id < 4', 'id >= 4 AND id < 6'],
|
||||||
msg => $msg,
|
msg => $msg,
|
||||||
print => 1,
|
sleep => sub { $sleep_cnt++; },
|
||||||
engine_flags => 'LOCK IN SHARE MODE',
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
is(
|
||||||
|
$sleep_cnt,
|
||||||
|
1,
|
||||||
|
"Calls sleep callback after each chunk (except last chunk)"
|
||||||
|
);
|
||||||
|
|
||||||
|
eval {
|
||||||
|
$output = output(sub { $osc->cleanup(); } );
|
||||||
|
};
|
||||||
|
|
||||||
ok(
|
ok(
|
||||||
no_diff(
|
!$EVAL_ERROR && !$output,
|
||||||
$output,
|
"cleanup() works but doesn't do anything"
|
||||||
"t/lib/samples/osc/copyins001.txt",
|
|
||||||
cmd_output => 1,
|
|
||||||
),
|
|
||||||
"Prints 2 SQL statments for the 2 chunks"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$rows = $dbh->selectall_arrayref("select id, c from __new_t order by id");
|
test_copy_table(
|
||||||
is_deeply(
|
tbl => "tbl002.sql",
|
||||||
$rows,
|
col => "default",
|
||||||
[],
|
expect => "copyins002.txt",
|
||||||
"Doesn't exec those statements if print is true"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test_copy_table(
|
||||||
|
tbl => "tbl003.sql",
|
||||||
|
col => "space col",
|
||||||
|
expect => "copyins003.txt",
|
||||||
|
);
|
||||||
|
|
||||||
|
# ###########################################################################
|
||||||
|
# Copy a larger, more complex sakila table.
|
||||||
|
# ###########################################################################
|
||||||
$dbh->do('create table osc.city like sakila.city');
|
$dbh->do('create table osc.city like sakila.city');
|
||||||
$dbh->do('alter table osc.city engine=myisam');
|
$dbh->do('alter table osc.city engine=myisam');
|
||||||
my $chunks = [
|
my $chunks = [
|
||||||
@@ -140,35 +201,6 @@ like(
|
|||||||
"Reports copy progress if Progress obj given"
|
"Reports copy progress if Progress obj given"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
my $sleep_cnt = 0;
|
|
||||||
|
|
||||||
$dbh->do("truncate table osc.__new_t");
|
|
||||||
output( sub {
|
|
||||||
$osc->copy(
|
|
||||||
dbh => $dbh,
|
|
||||||
from_table => 'osc.t',
|
|
||||||
to_table => 'osc.__new_t',
|
|
||||||
columns => [qw(id c)],
|
|
||||||
chunks => ['id < 4', 'id >= 4 AND id < 6'],
|
|
||||||
msg => $msg,
|
|
||||||
sleep => sub { $sleep_cnt++; },
|
|
||||||
);
|
|
||||||
});
|
|
||||||
is(
|
|
||||||
$sleep_cnt,
|
|
||||||
1,
|
|
||||||
"Calls sleep callback after each chunk (except last chunk)"
|
|
||||||
);
|
|
||||||
|
|
||||||
eval {
|
|
||||||
$output = output(sub { $osc->cleanup(); } );
|
|
||||||
};
|
|
||||||
ok(
|
|
||||||
!$EVAL_ERROR && !$output,
|
|
||||||
"cleanup() works but doesn't do anything"
|
|
||||||
);
|
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Done.
|
# Done.
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
INSERT IGNORE INTO osc.__new_t (id, c) SELECT id, c FROM osc.t WHERE (id < 4) LOCK IN SHARE MODE
|
INSERT IGNORE INTO osc.__new_t (`id`, `c`) SELECT `id`, `c` FROM osc.t WHERE (id < 4) LOCK IN SHARE MODE
|
||||||
INSERT IGNORE INTO osc.__new_t (id, c) SELECT id, c FROM osc.t WHERE (id >= 4 AND id < 6) LOCK IN SHARE MODE
|
INSERT IGNORE INTO osc.__new_t (`id`, `c`) SELECT `id`, `c` FROM osc.t WHERE (id >= 4 AND id < 6) LOCK IN SHARE MODE
|
||||||
|
2
t/lib/samples/osc/copyins002.txt
Normal file
2
t/lib/samples/osc/copyins002.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
INSERT IGNORE INTO osc.__new_t (`id`, `default`) SELECT `id`, `default` FROM osc.t WHERE (id < 4) LOCK IN SHARE MODE
|
||||||
|
INSERT IGNORE INTO osc.__new_t (`id`, `default`) SELECT `id`, `default` FROM osc.t WHERE (id >= 4 AND id < 6) LOCK IN SHARE MODE
|
2
t/lib/samples/osc/copyins003.txt
Normal file
2
t/lib/samples/osc/copyins003.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
INSERT IGNORE INTO osc.__new_t (`id`, `space col`) SELECT `id`, `space col` FROM osc.t WHERE (id < 4) LOCK IN SHARE MODE
|
||||||
|
INSERT IGNORE INTO osc.__new_t (`id`, `space col`) SELECT `id`, `space col` FROM osc.t WHERE (id >= 4 AND id < 6) LOCK IN SHARE MODE
|
Reference in New Issue
Block a user