package Xmldoom::Schema::ForeignKey;
use Xmldoom::Threads;
use strict;
sub new
{
my $class = shift;
my $args = shift;
my $parent;
my $reference_table;
my $local_columns;
my $foreign_columns;
if ( ref($args) eq 'HASH' )
{
$parent = $args->{parent};
$reference_table = $args->{reference_table};
$local_columns = $args->{local_columns};
$foreign_columns = $args->{foreign_columns};
}
# make sure that the count of the two array's is the same.
if ( scalar @$local_columns != scalar @$foreign_columns )
{
die "A foreign-key must have the same number of local and foreign columns";
}
my $self = {
parent => $parent,
reference_table => $reference_table,
local_columns => $local_columns,
foreign_columns => $foreign_columns
};
bless $self, $class;
return Xmldoom::Threads::make_shared($self, $args->{shared});
}
sub DESTROY
{
my $self = shift;
$self->{parent} = undef;
}
sub get_table { return shift->{parent}; }
sub get_table_name { return shift->{parent}->get_name(); }
sub get_reference_table_name { return shift->{reference_table}; }
sub get_local_column_names { return shift->{local_columns}; }
sub get_foreign_column_names { return shift->{foreign_columns}; }
sub get_reference_table
{
my $self = shift;
return $self->get_table()->get_schema()->get_table( $self->{reference_table} );
}
sub get_local_columns
{
my $self = shift;
return $self->get_table()->get_columns( $self->{local_columns} );
}
sub get_foreign_columns
{
my $self = shift;
return $self->get_reference_table()->get_columns( $self->{foreign_columns} );
}
sub _is_list
{
my ($list1, $list2) = @_;
# quickest check, the lengths!
if ( scalar @$list1 != scalar @$list2 )
{
return 0;
}
name1: foreach my $name1 ( @$list1 )
{
foreach my $name2 ( @$list2 )
{
if ( $name1 eq $name2 )
{
next name1;
}
}
return 0;
}
return 1;
}
sub is_local_column_names
{
my ($self, $names) = @_;
return _is_list($self->{local_columns}, $names);
}
sub is_foreign_column_names
{
my ($self, $names) = @_;
return _is_list($self->{foreign_columns}, $names);
}
# TODO: this function was create soley for Table::get_foreign_key() which is
# broken anyway, so the usefulness of this function is debatable.
sub get_foreign_pair_name
{
my ($self, $name) = @_;
my @pair = grep { $_->{local_column} eq $name } @{$self->get_column_names()};
if ( scalar @pair > 0 )
{
return $pair[0]->{foreign_column};
}
return undef;
}
sub get_column_names
{
my $self = shift;
my @ret;
my $count = scalar @{$self->{local_columns}};
for( my $i = 0; $i < $count; $i++ )
{
push @ret, {
local_column => $self->{local_columns}->[$i],
foreign_column => $self->{foreign_columns}->[$i],
# for compatibility:
local_table => $self->get_table_name(),
foreign_table => $self->get_reference_table_name()
};
}
return \@ret;
}
sub get_columns
{
my $self = shift;
my $local_table = $self->get_table();
my $foreign_table = $self->get_reference_table();
my @ret;
my $count = scalar @{$self->{local_columns}};
for( my $i = 0; $i < $count; $i++ )
{
push @ret, {
local_column => $local_table->get_column( $self->{local_columns}->[$i] ),
foreign_column => $foreign_table->get_column( $self->{foreign_columns}->[$i] )
};
}
return \@ret;
}
sub equals
{
my ($self, $fkey) = @_;
return ( $self->{parent} == $fkey->{parent} and
$self->{reference_table} eq $fkey->{reference_table} and
_is_list($self->{local_columns}, $fkey->{local_columns}) and
_is_list($self->{foreign_columns}, $fkey->{foreign_columns}) );
}
sub clone_reverse
{
my $self = shift;
return Xmldoom::Schema::ForeignKey->new({
parent => $self->get_reference_table(),
reference_table => $self->get_table_name(),
local_columns => $self->get_foreign_column_names(),
foreign_columns => $self->get_local_column_names()
});
}
1;