How do you manage triggers in RDBMS.
RDBMSレベルのtriggerはアプリケーションレベルのトリガーにくらべてもれもなく、安心感があってよいものですね。
しかし一方で、RDBMS レベルのtriggerは、deploy がむずかしいという問題もあります。
わたくしは、以下のようなスクリプトをつかって、スキーマと実際のDBの様子をつきあわせて、ちがっていれば DROP して CREATE しなおすというようなスクリプトをかいています。
みなさんはどのように管理していますか?
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use 5.10.0;
use autodie;
use Log::Minimal;
use File::Spec;
use Data::Dumper;
...
my $dbh = $dbh;
my %db_triggers = map { $_->{Trigger} => $_ } @{$dbh->selectall_arrayref(q{show triggers}, +{Slice => {}})};
my %triggers = parse_trigger_sql(File::Spec->catfile($c->base_dir, q{sql/trigger.sql}));
while (my ($name, $attr) = each %triggers) {
if (need_install($db_triggers{$name}->{Statement}, $attr->{sql})) {
say qq{-- $attr->{name}\@$attr->{table} --};
say qq{LOCK TABLES $attr->{table} WRITE;};
say qq{DROP TRIGGER IF EXISTS $attr->{name};};
say qq{DELIMITER |};
say qq{$attr->{header}};
say qq{$attr->{sql}};
say qq{|};
say qq{DELIMITER ;};
say qq{UNLOCK TABLES;};
say qq{};
}
}
exit;
# print trigger source
my $trigger_file = File::Spec->catfile($c->base_dir, 'sql/trigger.sql');
open my $fh, '<', $trigger_file;
print $_ while <$fh>;
close $fh;
sub need_install {
my ($dbt, $srct) = @_;
return 1 unless $dbt;
$dbt =~ s/"\n"/"\\n"/g;
$dbt =~ s/"\r"/"\\r"/g;
$dbt =~ s/\n/ /g;
$dbt =~ s/\s{2,}/ /g;
$dbt =~ s/\s+$//g;
$srct =~ s/\n/ /g;
$srct =~ s/\s+$//g;
if ($dbt ne $srct) {
debugf("db : %s", ddf($dbt));
debugf("src: %s", ddf($srct));
return 1;
} else {
return 0;
}
}
sub parse_trigger_sql {
my ($src) = shift;
open my $fh, '<', $src or die "Cannot open file: $src";
my $delimiter = 'eMpTy'x10;
my $sql;
my %triggers;
my $name;
while (<$fh>) {
s/--.+//;
s/^\s+//;
s/\s{2,}/ /g;
next unless /\S/;
given ($_) {
when (/^DELIMITER\s+(.)$/) {
$delimiter = quotemeta $1;
}
when (/^$delimiter/) {
$triggers{$name}->{sql} = $sql;
undef $sql;
}
when (/(?<header>CREATE TRIGGER (?<name>\S+) (?<before_after>\S+) (?<command>\S+) ON (?<table>\S+) FOR EACH ROW) BEGIN/) {
$name = $+{name};
$triggers{$name} = {%+};
$sql = "BEGIN\n";
}
default {
$sql .= $_;
}
}
}
close $fh;
return %triggers;
}
Published: 2010-12-14(Tue) 05:25