CREATE OR REPLACE FUNCTION check_updates() RETURNS TRIGGER AS $$ BEGIN { strict->import(); } use PLPerl::CheckTrigger; my $states = { assertion_present => 0, assertion_name => 1, assertion_message => 2, columns_list => 3, condition => 4, condition_columns => 5 }; # This should be a row level trigger die 'should be called as a row level trigger' unless ($_TD->{level} eq 'ROW'); # Do nothing if event is not UPDATE return if ($_TD->{event} ne 'UPDATE'); die "$_TD->{name} takes at least 2 argument" unless ($_TD->{argc} >= 2); my ($options_arg, $condition); my @deny_columns = (); my @condition_columns = (); my $state = $states->{assertion_present}; my ($assertname, $assertmessage); foreach (@{$_TD->{args}}) { if ($state == $states->{assertion_present}) { # get the options for check_columns $options_arg = uc($_); # check whether we have ASSERT_MESSAGE option foreach my $option (split (/,\s*/, $options_arg)) { if ($option eq "ASSERT_MESSAGE") { $state = $states->{assertion_name}; last; } } # skip assertion name and message parsing # if the corresponding option is not present $state = $states->{columns_list} if ($state == $states->{assertion_present}); next; } elsif ($state == $states->{assertion_name}) { $assertname = $_; $state = $states->{assertion_message}; next; } elsif ($state == $states->{assertion_message}) { $assertmessage = $_; $state = $states->{columns_list}; next; } elsif ($state == $states->{columns_list}) { # get the list of columns for check_columns. # Read the values until they are valid column names. if (defined $_TD->{new}{$_}) { push @deny_columns, $_; next; } else { $state = $states->{condition}; } } if ($state == $states->{condition}) { # get the condition to check $condition = $_; $state = $states->{condition_columns}; } elsif ($state == $states->{condition_columns}) { # get the columns for check_condition push @condition_columns, $_; } else { # shouldn't be there die "Invalid state: $state"; } } # create a new instance of the 'helper' class. my $ch = new PLPerl::CheckTrigger($_TD); my $result; my $errmsg = ""; eval { # check whether this update touches columns that shouldn't change $result = $ch->check_columns($options_arg, @deny_columns); if ($result == 0) { # this update should be denied, however, we allow it if the # condition passed will be satisfied. $errmsg = $ch->{errmsg}; $result = $ch->check_condition($condition, @condition_columns); } }; die $@ if ($@); if (!$result) { $errmsg .= " when " . $ch->{errmsg}; $errmsg =~ s/, UPDATE is not allowed//; if ($assertname ne "" and $assertmessage ne "") { $errmsg = "\nASSERTION $assertname: $assertmessage.\nDETAIL: ".$errmsg; } die $errmsg } return; $$ LANGUAGE plperlu; -- vi: noexpandtab