mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-10 05:00:45 +00:00
Test and quote all idents, including reserved words and those with spaces, in OSCCaptureSync.pm.
This commit is contained in:
@@ -37,13 +37,13 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
|||||||
# OSCCaptureSync object
|
# OSCCaptureSync object
|
||||||
sub new {
|
sub new {
|
||||||
my ( $class, %args ) = @_;
|
my ( $class, %args ) = @_;
|
||||||
my @required_args = qw();
|
my @required_args = qw(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,
|
Quoter => $args{Quoter},
|
||||||
};
|
};
|
||||||
|
|
||||||
return bless $self, $class;
|
return bless $self, $class;
|
||||||
@@ -73,11 +73,14 @@ sub _make_triggers {
|
|||||||
die "I need a $arg argument" unless $args{$arg};
|
die "I need a $arg argument" unless $args{$arg};
|
||||||
}
|
}
|
||||||
my ($db, $tbl, $tmp_tbl, $chunk_column) = @args{@required_args};
|
my ($db, $tbl, $tmp_tbl, $chunk_column) = @args{@required_args};
|
||||||
|
my $q = $self->{Quoter};
|
||||||
|
|
||||||
my $old_table = "`$db`.`$tbl`";
|
$chunk_column = $q->quote($chunk_column);
|
||||||
my $new_table = "`$db`.`$tmp_tbl`";
|
|
||||||
my $new_values = join(', ', map { "NEW.$_" } @{$args{columns}});
|
my $old_table = $q->quote($db, $tbl);
|
||||||
my $columns = join(', ', @{$args{columns}});
|
my $new_table = $q->quote($db, $tmp_tbl);
|
||||||
|
my $new_values = join(', ', map { "NEW.".$q->quote($_) } @{$args{columns}});
|
||||||
|
my $columns = join(', ', map { $q->quote($_) } @{$args{columns}});
|
||||||
|
|
||||||
my $delete_trigger = "CREATE TRIGGER mk_osc_del AFTER DELETE ON $old_table "
|
my $delete_trigger = "CREATE TRIGGER mk_osc_del AFTER DELETE ON $old_table "
|
||||||
. "FOR EACH ROW "
|
. "FOR EACH ROW "
|
||||||
@@ -113,9 +116,10 @@ sub cleanup {
|
|||||||
die "I need a $arg argument" unless $args{$arg};
|
die "I need a $arg argument" unless $args{$arg};
|
||||||
}
|
}
|
||||||
my ($dbh, $db, $msg) = @args{@required_args};
|
my ($dbh, $db, $msg) = @args{@required_args};
|
||||||
|
my $q = $self->{Quoter};
|
||||||
|
|
||||||
foreach my $trigger ( qw(del ins upd) ) {
|
foreach my $trigger ( qw(del ins upd) ) {
|
||||||
my $sql = "DROP TRIGGER IF EXISTS `$db`.`mk_osc_$trigger`";
|
my $sql = "DROP TRIGGER IF EXISTS " . $q->quote($db, "mk_osc_$trigger");
|
||||||
$msg->($sql);
|
$msg->($sql);
|
||||||
$dbh->do($sql) unless $args{print};
|
$dbh->do($sql) unless $args{print};
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,7 @@ use Test::More;
|
|||||||
use DSNParser;
|
use DSNParser;
|
||||||
use Sandbox;
|
use Sandbox;
|
||||||
use PerconaTest;
|
use PerconaTest;
|
||||||
|
use Quoter;
|
||||||
use OSCCaptureSync;
|
use OSCCaptureSync;
|
||||||
|
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
@@ -30,72 +31,92 @@ if ( !$dbh ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
plan tests => 4;
|
plan tests => 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sb->load_file("master", "t/lib/samples/osc/tbl001.sql");
|
my $q = new Quoter();
|
||||||
$dbh->do("USE osc");
|
my $osc = new OSCCaptureSync(Quoter => $q);
|
||||||
|
|
||||||
my $osc = new OSCCaptureSync();
|
|
||||||
|
|
||||||
my $msg = sub { print "$_[0]\n"; };
|
my $msg = sub { print "$_[0]\n"; };
|
||||||
|
my $output;
|
||||||
|
|
||||||
my $output = output(
|
sub test_table {
|
||||||
sub {
|
my (%args) = @_;
|
||||||
$osc->capture(
|
my ($tbl, $col, $expect) = @args{qw(tbl col expect)};
|
||||||
dbh => $dbh,
|
|
||||||
db => 'osc',
|
|
||||||
tbl => 't',
|
|
||||||
tmp_tbl => '__new_t',
|
|
||||||
columns => [qw(id c)],
|
|
||||||
chunk_column => 'id',
|
|
||||||
msg => $msg,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
ok(
|
$sb->load_file("master", "t/lib/samples/osc/$tbl");
|
||||||
no_diff(
|
PerconaTest::wait_for_table($dbh, "osc.t", "id=5");
|
||||||
$output,
|
$dbh->do("USE osc");
|
||||||
"t/lib/samples/osc/capsync001.txt",
|
|
||||||
cmd_output => 1,
|
|
||||||
),
|
|
||||||
"SQL statments to create triggers"
|
|
||||||
);
|
|
||||||
|
|
||||||
$dbh->do('insert into t values (6, "f")');
|
ok(
|
||||||
$dbh->do('update t set c="z" where id=1');
|
no_diff(
|
||||||
$dbh->do('delete from t where id=3');
|
sub {
|
||||||
|
$osc->capture(
|
||||||
my $rows = $dbh->selectall_arrayref("select id, c from __new_t order by id");
|
dbh => $dbh,
|
||||||
is_deeply(
|
db => 'osc',
|
||||||
$rows,
|
tbl => 't',
|
||||||
[
|
tmp_tbl => '__new_t',
|
||||||
[1, 'z'], # update t set c="z" where id=1
|
columns => ['id', $col],
|
||||||
[6, 'f'], # insert into t values (6, "f")
|
chunk_column => 'id',
|
||||||
],
|
msg => $msg,
|
||||||
"Triggers work"
|
)
|
||||||
) or print Dumper($rows);
|
},
|
||||||
|
"t/lib/samples/osc/$expect",
|
||||||
output(sub {
|
stderr => 1,
|
||||||
$osc->cleanup(
|
),
|
||||||
dbh => $dbh,
|
"$tbl: SQL statments to create triggers"
|
||||||
db => 'osc',
|
|
||||||
msg => $msg,
|
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
$rows = $dbh->selectall_arrayref("show triggers from `osc` like 't'");
|
$dbh->do("insert into t values (6, 'f')");
|
||||||
is_deeply(
|
$dbh->do("update t set `$col`='z' where id=1");
|
||||||
$rows,
|
$dbh->do("delete from t where id=3");
|
||||||
[],
|
|
||||||
"Cleanup removes the triggers"
|
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.
|
# Done.
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
$output = '';
|
|
||||||
{
|
{
|
||||||
local *STDERR;
|
local *STDERR;
|
||||||
open STDERR, '>', \$output;
|
open STDERR, '>', \$output;
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
CREATE TRIGGER mk_osc_del AFTER DELETE ON `osc`.`t` FOR EACH ROW DELETE IGNORE FROM `osc`.`__new_t` WHERE `osc`.`__new_t`.id = OLD.id
|
CREATE TRIGGER mk_osc_del AFTER DELETE ON `osc`.`t` FOR EACH ROW DELETE IGNORE FROM `osc`.`__new_t` WHERE `osc`.`__new_t`.`id` = OLD.`id`
|
||||||
CREATE TRIGGER mk_osc_upd AFTER UPDATE ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (id, c) VALUES (NEW.id, NEW.c)
|
CREATE TRIGGER mk_osc_upd AFTER UPDATE ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (`id`, `c`) VALUES (NEW.`id`, NEW.`c`)
|
||||||
CREATE TRIGGER mk_osc_ins AFTER INSERT ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (id, c) VALUES(NEW.id, NEW.c)
|
CREATE TRIGGER mk_osc_ins AFTER INSERT ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (`id`, `c`) VALUES(NEW.`id`, NEW.`c`)
|
||||||
|
3
t/lib/samples/osc/capsync002.txt
Normal file
3
t/lib/samples/osc/capsync002.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
CREATE TRIGGER mk_osc_del AFTER DELETE ON `osc`.`t` FOR EACH ROW DELETE IGNORE FROM `osc`.`__new_t` WHERE `osc`.`__new_t`.`id` = OLD.`id`
|
||||||
|
CREATE TRIGGER mk_osc_upd AFTER UPDATE ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (`id`, `default`) VALUES (NEW.`id`, NEW.`default`)
|
||||||
|
CREATE TRIGGER mk_osc_ins AFTER INSERT ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (`id`, `default`) VALUES(NEW.`id`, NEW.`default`)
|
3
t/lib/samples/osc/capsync003.txt
Normal file
3
t/lib/samples/osc/capsync003.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
CREATE TRIGGER mk_osc_del AFTER DELETE ON `osc`.`t` FOR EACH ROW DELETE IGNORE FROM `osc`.`__new_t` WHERE `osc`.`__new_t`.`id` = OLD.`id`
|
||||||
|
CREATE TRIGGER mk_osc_upd AFTER UPDATE ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (`id`, `space col`) VALUES (NEW.`id`, NEW.`space col`)
|
||||||
|
CREATE TRIGGER mk_osc_ins AFTER INSERT ON `osc`.`t` FOR EACH ROW REPLACE INTO `osc`.`__new_t` (`id`, `space col`) VALUES(NEW.`id`, NEW.`space col`)
|
13
t/lib/samples/osc/tbl002.sql
Normal file
13
t/lib/samples/osc/tbl002.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
DROP DATABASE IF EXISTS osc;
|
||||||
|
CREATE DATABASE osc;
|
||||||
|
USE osc;
|
||||||
|
|
||||||
|
CREATE TABLE t (
|
||||||
|
id INT UNSIGNED PRIMARY KEY,
|
||||||
|
`default` VARCHAR(16)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
CREATE TABLE __new_t LIKE t;
|
||||||
|
|
||||||
|
INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e');
|
||||||
|
|
13
t/lib/samples/osc/tbl003.sql
Normal file
13
t/lib/samples/osc/tbl003.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
DROP DATABASE IF EXISTS osc;
|
||||||
|
CREATE DATABASE osc;
|
||||||
|
USE osc;
|
||||||
|
|
||||||
|
CREATE TABLE t (
|
||||||
|
id INT UNSIGNED PRIMARY KEY,
|
||||||
|
`space col` VARCHAR(16)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
CREATE TABLE __new_t LIKE t;
|
||||||
|
|
||||||
|
INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e');
|
||||||
|
|
Reference in New Issue
Block a user