Test and quote all idents, including reserved words and those with spaces, in CopyRowsInsertSelect.pm.

This commit is contained in:
Daniel Nichter
2012-02-20 11:37:34 -07:00
parent 39fe787fdd
commit 17fe96f361
5 changed files with 111 additions and 73 deletions

View File

@@ -37,13 +37,14 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
# CopyRowsInsertSelect object
sub new {
my ( $class, %args ) = @_;
my @required_args = qw(Retry);
my @required_args = qw(Retry Quoter);
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless $args{$arg};
}
my $self = {
%args,
Retry => $args{Retry},
Quoter => $args{Quoter},
};
return bless $self, $class;
@@ -56,9 +57,10 @@ sub copy {
die "I need a $arg argument" unless $args{$arg};
}
my ($dbh, $msg, $from_table, $to_table, $chunks) = @args{@required_args};
my $q = $self->{Quoter};
my $pr = $args{Progress};
my $sleep = $args{sleep};
my $columns = join(', ', @{$args{columns}});
my $columns = join(', ', map { $q->quote($_) } @{$args{columns}});
my $n_chunks = @$chunks - 1;
for my $chunkno ( 0..$n_chunks ) {

View File

@@ -17,6 +17,7 @@ use PerconaTest;
use Progress;
use Transformers;
use Retry;
use Quoter;
use CopyRowsInsertSelect;
Transformers->import(qw(secs_to_time));
@@ -38,36 +39,84 @@ elsif ( !@{$dbh->selectcol_arrayref('SHOW DATABASES LIKE "sakila"')} ) {
plan skip_all => "Sandbox master does not have the sakila database";
}
else {
plan tests => 8;
plan tests => 14;
}
my $q = new Quoter();
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 $output = "";
my $rows;
$sb->load_file("master", "t/lib/samples/osc/tbl001.sql");
# ###########################################################################
# Copy simple tables.
# ###########################################################################
sub test_copy_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");
$osc->copy(
dbh => $dbh,
from_table => 'osc.t',
to_table => 'osc.__new_t',
columns => [qw(id c)],
columns => ['id', $col],
chunks => ['1=1'],
msg => $msg,
);
my $rows = $dbh->selectall_arrayref("select id, c from __new_t order by id");
$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'], ],
"One chunk copy"
"$tbl: One chunk copy"
) or print Dumper($rows);
$dbh->do("truncate table osc.__new_t");
$output = output( sub {
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",
);
# Sleep callback.
my $sleep_cnt = 0;
$dbh->do("truncate table osc.__new_t");
output( sub {
$osc->copy(
dbh => $dbh,
from_table => 'osc.t',
@@ -75,27 +124,39 @@ $output = output( sub {
columns => [qw(id c)],
chunks => ['id < 4', 'id >= 4 AND id < 6'],
msg => $msg,
print => 1,
engine_flags => 'LOCK IN SHARE MODE',
sleep => sub { $sleep_cnt++; },
);
});
is(
$sleep_cnt,
1,
"Calls sleep callback after each chunk (except last chunk)"
);
eval {
$output = output(sub { $osc->cleanup(); } );
};
ok(
no_diff(
$output,
"t/lib/samples/osc/copyins001.txt",
cmd_output => 1,
),
"Prints 2 SQL statments for the 2 chunks"
!$EVAL_ERROR && !$output,
"cleanup() works but doesn't do anything"
);
$rows = $dbh->selectall_arrayref("select id, c from __new_t order by id");
is_deeply(
$rows,
[],
"Doesn't exec those statements if print is true"
test_copy_table(
tbl => "tbl002.sql",
col => "default",
expect => "copyins002.txt",
);
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('alter table osc.city engine=myisam');
my $chunks = [
@@ -140,35 +201,6 @@ like(
"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.
# #############################################################################

View File

@@ -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 AND id < 6) 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

View 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

View 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