From: Allen Day Date: Fri, 5 Sep 2003 11:21:26 +0000 (+0000) Subject: adding dg classes to represent schema. these are currently dependent on X-Git-Tag: v0.04~194 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=0caaf4c3fb70de1a3dcc6e8e70c06c53b56c007c;p=dbsrgits%2FSQL-Translator.git adding dg classes to represent schema. these are currently dependent on the schema::* classes, but i'd like them to break away at some point as an alternate way to represent a schema. --- diff --git a/lib/SQL/Translator/Schema/Graph.pm b/lib/SQL/Translator/Schema/Graph.pm new file mode 100644 index 0000000..64ae6d2 --- /dev/null +++ b/lib/SQL/Translator/Schema/Graph.pm @@ -0,0 +1,139 @@ +package SQL::Translator::Schema::Graph; + +use strict; + +use Data::Dumper; + +use SQL::Translator::Schema::Graph::Node; +use SQL::Translator::Schema::Graph::Edge; +use SQL::Translator::Schema::Graph::Port; +use SQL::Translator::Schema::Graph::CompoundEdge; +use SQL::Translator::Schema::Graph::HyperEdge; + +use constant Node => 'SQL::Translator::Schema::Graph::Node'; +use constant Edge => 'SQL::Translator::Schema::Graph::Edge'; +use constant Port => 'SQL::Translator::Schema::Graph::Port'; +use constant CompoundEdge => 'SQL::Translator::Schema::Graph::CompoundEdge'; +use constant HyperEdge => 'SQL::Translator::Schema::Graph::HyperEdge'; + +use Class::MakeMethods::Template::Hash ( + 'new --and_then_init' => 'new', + object => [ + 'translator' => {class => 'SQL::Translator'}, + ], + 'hash' => [ qw( node ) ], + 'scalar' => [ qw( baseclass ) ], + 'number --counter' => [ qw( order ) ], +); + +sub init { + my $self = shift; + # + # build package objects + # + foreach my $table ($self->translator->schema->get_tables){ + die __PACKAGE__." table ".$table->name." doesn't have a primary key!" unless $table->primary_key; + die __PACKAGE__." table ".$table->name." can't have a composite primary key!" if ($table->primary_key->fields)[1]; + + my $node = Node->new(); + + $self->node_push($table->name => $node); + + $node->order($self->order_incr()); + $node->name( $self->translator->format_package_name($table->name) ); + $node->base( $self->baseclass ); + $node->table( $table ); + $node->primary_key( ($table->primary_key->fields)[0] ); + + # Primary key may have a differenct accessor method name + $node->primary_key_accessor( + defined($self->translator->format_pk_name) + ? $self->translator->format_pk_name->( $node->name, $node->primary_key ) + : undef + ); + } + + foreach my $node ($self->node_values){ + foreach my $field ($node->table->get_fields){ + next unless $field->is_foreign_key; + + my $that = $self->node($field->foreign_key_reference->reference_table); + + #this means we have an incomplete schema + next unless $that; + + my $edge = Edge->new( + type => 'import', + thisnode => $node, + thisfield => $field, + thatnode => $that, + thatfield => ($field->foreign_key_reference->reference_fields)[0] + ); + + + $node->has($that->name, $node->has($that->name)+1); + $that->many($node->name, $that->many($node->name)+1); + + $node->push_edges( $edge ); + $that->push_edges( $edge->flip ); + } + } + + # + # type MM relationships + # + foreach my $lnode (sort $self->node_values){ + next if $lnode->table->is_data; + foreach my $inode1 (sort $self->node_values){ + next if $inode1 eq $lnode; + + my @inode1_imports = grep { $_->type eq 'import' and $_->thatnode eq $inode1 } $lnode->edges; + next unless @inode1_imports; + + foreach my $inode2 (sort $self->node_values){ + my %i = map {$_->thatnode->name => 1} grep { $_->type eq 'import'} $lnode->edges; + if(scalar(keys %i) == 1) { + } else { + last if $inode1 eq $inode2; + } + + next if $inode2 eq $lnode; + my @inode2_imports = grep { $_->type eq 'import' and $_->thatnode eq $inode2 } $lnode->edges; + next unless @inode2_imports; + + my $cedge = CompoundEdge->new(); + $cedge->via($lnode); + + $cedge->push_edges( map {$_->flip} grep {$_->type eq 'import' and ($_->thatnode eq $inode1 or $_->thatnode eq $inode2)} $lnode->edges); + + if(scalar(@inode1_imports) == 1 and scalar(@inode2_imports) == 1){ + $cedge->type('one2one'); + + $inode1->via($inode2->name,$inode1->via($inode2->name)+1); + $inode2->via($inode1->name,$inode2->via($inode1->name)+1); + } + elsif(scalar(@inode1_imports) > 1 and scalar(@inode2_imports) == 1){ + $cedge->type('many2one'); + + $inode1->via($inode2->name,$inode1->via($inode2->name)+1); + $inode2->via($inode1->name,$inode2->via($inode1->name)+1); + } + elsif(scalar(@inode1_imports) == 1 and scalar(@inode2_imports) > 1){ + #handled above + } + elsif(scalar(@inode1_imports) > 1 and scalar(@inode2_imports) > 1){ + $cedge->type('many2many'); + + $inode1->via($inode2->name,$inode1->via($inode2->name)+1); + $inode2->via($inode1->name,$inode2->via($inode1->name)+1); + } + + $inode1->push_compoundedges($cedge); + $inode2->push_compoundedges($cedge) unless $inode1 eq $inode2; + + } + } + } +} + +1; diff --git a/lib/SQL/Translator/Schema/Graph/CompoundEdge.pm b/lib/SQL/Translator/Schema/Graph/CompoundEdge.pm new file mode 100644 index 0000000..ab115b2 --- /dev/null +++ b/lib/SQL/Translator/Schema/Graph/CompoundEdge.pm @@ -0,0 +1,13 @@ +package SQL::Translator::Schema::Graph::CompoundEdge; + +use strict; +use base qw(SQL::Translator::Schema::Graph::Edge); +use Class::MakeMethods::Template::Hash ( + new => ['new'], + object => [ + 'via' => {class => 'SQL::Translator::Schema::Graph::Node'}, + ], + 'array_of_objects -class SQL::Translator::Schema::Graph::Edge' => [ qw( edges ) ], +); + +1; diff --git a/lib/SQL/Translator/Schema/Graph/Edge.pm b/lib/SQL/Translator/Schema/Graph/Edge.pm new file mode 100644 index 0000000..6915e71 --- /dev/null +++ b/lib/SQL/Translator/Schema/Graph/Edge.pm @@ -0,0 +1,28 @@ +package SQL::Translator::Schema::Graph::Edge; + +use strict; + +use Class::MakeMethods::Template::Hash ( + new => ['new'], + scalar => [ qw( type ) ], + array => [ qw( traversals ) ], + object => [ + 'thisfield' => {class => 'SQL::Translator::Schema::Field'}, #FIXME + 'thatfield' => {class => 'SQL::Translator::Schema::Field'}, #FIXME + 'thisnode' => {class => 'SQL::Translator::Schema::Graph::Node'}, + 'thatnode' => {class => 'SQL::Translator::Schema::Graph::Node'}, + + ], +); + +sub flip { + my $self = shift; + return SQL::Translator::Schema::Graph::Edge->new( thisfield => $self->thatfield, + thatfield => $self->thisfield, + thisnode => $self->thatnode, + thatnode => $self->thisnode, + type => $self->type eq 'import' ? 'export' : 'import' + ); +} + +1; diff --git a/lib/SQL/Translator/Schema/Graph/HyperEdge.pm b/lib/SQL/Translator/Schema/Graph/HyperEdge.pm new file mode 100644 index 0000000..c5ebec1 --- /dev/null +++ b/lib/SQL/Translator/Schema/Graph/HyperEdge.pm @@ -0,0 +1,12 @@ +package SQL::Translator::Schema::Graph::HyperEdge; + +use strict; +use base qw(SQL::Translator::Schema::Graph::Edge); + +use Class::MakeMethods::Template::Hash ( + 'array_of_objects -class SQL::Translator::Schema::Field' => [ qw( thisviafield thatviafield thisfield thatfield) ], #FIXME + 'array_of_objects -class SQL::Translator::Schema::Graph::Node' => [ qw( thisnode thatnode ) ], + object => [ 'vianode' => {class => 'SQL::Translator::Schema::Graph::Node'} ], +); + +1; diff --git a/lib/SQL/Translator/Schema/Graph/Node.pm b/lib/SQL/Translator/Schema/Graph/Node.pm new file mode 100644 index 0000000..156370a --- /dev/null +++ b/lib/SQL/Translator/Schema/Graph/Node.pm @@ -0,0 +1,15 @@ +package SQL::Translator::Schema::Graph::Node; + +use strict; + +use Class::MakeMethods::Template::Hash ( + new => [ 'new' ], + 'array_of_objects -class SQL::Translator::Schema::Graph::Edge' => [ qw( edges ) ], + 'array_of_objects -class SQL::Translator::Schema::Graph::CompoundEdge' => [ qw( compoundedges ) ], + 'array_of_objects -class SQL::Translator::Schema::Graph::HyperEdge' => [ qw( hyperedges ) ], + 'hash' => [ qw( many via has ) ], + scalar => [ qw( base name order primary_key primary_key_accessor table ) ], + number => [ qw( order ) ], +); + +1; diff --git a/lib/SQL/Translator/Schema/Graph/Port.pm b/lib/SQL/Translator/Schema/Graph/Port.pm new file mode 100644 index 0000000..f0aeab4 --- /dev/null +++ b/lib/SQL/Translator/Schema/Graph/Port.pm @@ -0,0 +1,5 @@ +package SQL::Translator::Schema::Graph::Port; + +use strict; + +1;