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

This commit is contained in:
Daniel Nichter
2012-02-20 11:09:36 -07:00
parent a6f9501fa8
commit 39fe787fdd
7 changed files with 120 additions and 63 deletions

View File

@@ -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};
} }

View File

@@ -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 {
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 { sub {
$osc->capture( $osc->capture(
dbh => $dbh, dbh => $dbh,
db => 'osc', db => 'osc',
tbl => 't', tbl => 't',
tmp_tbl => '__new_t', tmp_tbl => '__new_t',
columns => [qw(id c)], columns => ['id', $col],
chunk_column => 'id', chunk_column => 'id',
msg => $msg, msg => $msg,
) )
}, },
); "t/lib/samples/osc/$expect",
stderr => 1,
ok(
no_diff(
$output,
"t/lib/samples/osc/capsync001.txt",
cmd_output => 1,
), ),
"SQL statments to create triggers" "$tbl: SQL statments to create triggers"
); );
$dbh->do('insert into t values (6, "f")'); $dbh->do("insert into t values (6, 'f')");
$dbh->do('update t set c="z" where id=1'); $dbh->do("update t set `$col`='z' where id=1");
$dbh->do('delete from t where id=3'); $dbh->do("delete from t where id=3");
my $rows = $dbh->selectall_arrayref("select id, c from __new_t order by id"); my $rows = $dbh->selectall_arrayref("select id, `$col` from __new_t order by id");
is_deeply( is_deeply(
$rows, $rows,
[ [
[1, 'z'], # update t set c="z" where id=1 [1, 'z'], # update t set c="z" where id=1
[6, 'f'], # insert into t values (6, "f") [6, 'f'], # insert into t values (6, "f")
], ],
"Triggers work" "$tbl: Triggers work"
) or print Dumper($rows); ) or print Dumper($rows);
output(sub { output(sub {
$osc->cleanup( $osc->cleanup(
dbh => $dbh, dbh => $dbh,
db => 'osc', db => 'osc',
msg => $msg, msg => $msg,
); );
}); });
$rows = $dbh->selectall_arrayref("show triggers from `osc` like 't'"); $rows = $dbh->selectall_arrayref("show triggers from `osc` like 't'");
is_deeply( is_deeply(
$rows, $rows,
[], [],
"Cleanup removes the triggers" "$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;

View File

@@ -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`)

View 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`)

View 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`)

View 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');

View 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');