Files
percona-toolkit/lib/OSCCaptureSync.pm

139 lines
4.2 KiB
Perl

# This program is copyright 2011 Percona Inc.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
# licenses.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# ###########################################################################
# OSCCaptureSync package
# ###########################################################################
{
# Package: OSCCaptureSync
# OSCCaptureSync implements the capture and sync phases of an online schema
# change.
package OSCCaptureSync;
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
# Sub: new
#
# Parameters:
# %args - Arguments
#
# Returns:
# OSCCaptureSync object
sub new {
my ( $class, %args ) = @_;
my @required_args = qw();
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless $args{$arg};
}
my $self = {
%args,
};
return bless $self, $class;
}
sub capture {
my ( $self, %args ) = @_;
my @required_args = qw(msg dbh db tbl tmp_tbl columns chunk_column);
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless $args{$arg};
}
my ($msg, $dbh) = @args{@required_args};
my @triggers = $self->_make_triggers(%args);
foreach my $sql ( @triggers ) {
$msg->($sql);
$dbh->do($sql) unless $args{print};
}
return;
}
sub _make_triggers {
my ( $self, %args ) = @_;
my @required_args = qw(db tbl tmp_tbl chunk_column columns);
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless $args{$arg};
}
my ($db, $tbl, $tmp_tbl, $chunk_column) = @args{@required_args};
my $old_table = "`$db`.`$tbl`";
my $new_table = "`$db`.`$tmp_tbl`";
my $new_values = join(', ', map { "NEW.$_" } @{$args{columns}});
my $columns = join(', ', @{$args{columns}});
my $delete_trigger = "CREATE TRIGGER mk_osc_del AFTER DELETE ON $old_table "
. "FOR EACH ROW "
. "DELETE IGNORE FROM $new_table "
. "WHERE $new_table.$chunk_column = OLD.$chunk_column";
my $insert_trigger = "CREATE TRIGGER mk_osc_ins AFTER INSERT ON $old_table "
. "FOR EACH ROW "
. "REPLACE INTO $new_table ($columns) "
. "VALUES($new_values)";
my $update_trigger = "CREATE TRIGGER mk_osc_upd AFTER UPDATE ON $old_table "
. "FOR EACH ROW "
. "REPLACE INTO $new_table ($columns) "
. "VALUES ($new_values)";
return $delete_trigger, $update_trigger, $insert_trigger;
}
sub sync {
my ( $self, %args ) = @_;
my @required_args = qw();
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless $args{$arg};
}
return;
}
sub cleanup {
my ( $self, %args ) = @_;
my @required_args = qw(dbh db msg);
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless $args{$arg};
}
my ($dbh, $db, $msg) = @args{@required_args};
foreach my $trigger ( qw(del ins upd) ) {
my $sql = "DROP TRIGGER IF EXISTS `$db`.`mk_osc_$trigger`";
$msg->($sql);
$dbh->do($sql) unless $args{print};
}
return;
}
sub _d {
my ($package, undef, $line) = caller 0;
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
map { defined $_ ? $_ : 'undef' }
@_;
print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
}
1;
}
# ###########################################################################
# End OSCCaptureSync package
# ###########################################################################