Parse-Dia-SQL
view release on metacpan or search on metacpan
lib/Parse/Dia/SQL/Output/SQLite3.pm view on Meta::CPAN
=head4 On Delete Cascade
Before delete on the parent table delete all dependent child records.
create trigger {constraint_name}_bdparent_tr before delete on {parent_table}
for each row
begin
delete from {child_table} where {child_table}.{child_fkcolumn}=old.{parent_key};
end;
=head4 On Delete Set Null
Before delete on the parent table set the foreign key field(s) in all dependent child records to NULL.
create trigger {constraint_name}_bdparent_tr before delete on {parent_table}
for each row
begin
update {child_table} set {child_table}.{child_fkcolumn}=null where {child_table}.{child_fkcolumn}=old.{parent_key};
end;
=cut
# Create sql for given association.
sub _get_create_association_sql {
my ( $self, $association ) = @_;
my $sqlstr = '';
my $temp;
# Sanity checks on input
if ( ref( $association ) ne 'ARRAY' ) {
$self->{log}
->error( q{Error in association input - cannot create association sql!} );
return;
}
# FK constraints are implemented as triggers in SQLite
my (
$table_name, $constraint_name, $key_column,
$ref_table, $ref_column, $constraint_action
) = @{$association};
# Shorten constraint name, if necessary (DB2 only)
$constraint_name = $self->_create_constraint_name( $constraint_name );
$temp = $constraint_name . "_bi_tr";
$sqlstr .=
qq{create trigger $temp before insert on $table_name for each row begin select raise(abort, 'insert on table $table_name violates foreign key constraint $constraint_name') where new.$key_column is not null and (select $ref_column from $ref_table wher...
. $self->{end_of_statement}
. $self->{newline};
$temp = $constraint_name . "_bu_tr";
$sqlstr .=
qq{create trigger $temp before update on $table_name for each row begin select raise(abort, 'update on table $table_name violates foreign key constraint $constraint_name') where new.$key_column is not null and (select $ref_column from $ref_table wher...
. $self->{end_of_statement}
. $self->{newline};
# note that the before delete triggers are on the parent ($ref_table)
$temp = $constraint_name . "_bdparent_tr";
if ( $constraint_action =~ /on delete cascade/i ) {
$sqlstr .=
qq{create trigger $temp before delete on $ref_table for each row begin delete from $table_name where $table_name.$key_column=old.$ref_column;end}
. $self->{end_of_statement}
. $self->{newline};
} elsif ( $constraint_action =~ /on delete set null/i ) {
$sqlstr .=
qq{create trigger $temp before delete on $ref_table for each row begin update $table_name set $key_column=null where $table_name.$key_column=old.$ref_column;end}
. $self->{end_of_statement}
. $self->{newline};
} else # default on delete restrict
{
$sqlstr .=
qq{create trigger $temp before delete on $ref_table for each row begin select raise(abort, 'delete on table $ref_table violates foreign key constraint $constraint_name on $table_name') where (select $key_column from $table_name where $key_column=old....
. $self->{end_of_statement}
. $self->{newline};
}
# Cascade updates doesn't work, so we always restrict
$temp = $constraint_name . "_buparent_tr";
$sqlstr .=
qq{create trigger $temp before update on $ref_table for each row when new.$ref_column <> old.$ref_column begin select raise(abort, 'update on table $ref_table violates foreign key constraint $constraint_name on $table_name') where (select $key_column...
. $self->{end_of_statement}
. $self->{newline};
$sqlstr .= $self->{newline};
return $sqlstr;
}
1;
=head1 TODO
Things that might get added in future versions:
=head3 Mandatory constraints
The current foreign key triggers allow NULL in the child table. This might use a keyword in the
multiplicity field (perhaps 'required') or could check the 'not null' state of the child fkcolumn.
=head3 Views
Views haven't been tested. They might already work, but who knows...
=head3 Other stuff
Bugs etc
=cut
__END__
( run in 0.913 second using v1.01-cache-2.11-cpan-39bf76dae61 )