From: Allen Day Date: Tue, 2 Sep 2003 00:24:07 +0000 (+0000) Subject: turnkey producer still broken, will try to get it working on the plane... X-Git-Tag: v0.04~198 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=88f2d2fdc1f41cb9c49f8498a0126f8129ddbb1f;p=dbsrgits%2FSQL-Translator.git turnkey producer still broken, will try to get it working on the plane... --- diff --git a/lib/SQL/Translator/Producer/Turnkey.pm b/lib/SQL/Translator/Producer/Turnkey.pm index 8b668cc..bc28737 100644 --- a/lib/SQL/Translator/Producer/Turnkey.pm +++ b/lib/SQL/Translator/Producer/Turnkey.pm @@ -1,50 +1,72 @@ -package Turnkey::Package; +package Turnkey::Node; use strict; use Class::MakeMethods::Template::Hash ( new => [ 'new' ], - 'array' => [ qw( many ) ], - hash_of_arrays => [ qw( one2one one2many many2one many2many) ], + 'array_of_objects -class Turnkey::Edge' => [ qw( edges ) ], + 'array_of_objects -class Turnkey::CompoundEdge' => [ qw( compoundedges ) ], + 'array_of_objects -class Turnkey::HyperEdge' => [ qw( hyperedges ) ], + 'hash' => [ qw( many via has) ], scalar => [ qw( base name order primary_key primary_key_accessor table) ], ); -# get_set => [ qw(order base name table primary_key primary_key_accessor) ], -# new_with_init => 'new', -#; +package Turnkey::Edge; -sub init { +use strict; +use Class::MakeMethods::Template::Hash ( + new => ['new'], + scalar => [ qw( type ) ], + array => [ qw( traversals ) ], + object => [ + 'thisfield' => {class => 'SQL::Translator::Schema::Field'}, + 'thatfield' => {class => 'SQL::Translator::Schema::Field'}, + 'thisnode' => {class => 'Turnkey::Node'}, + 'thatnode' => {class => 'Turnkey::Node'}, + + ], +); + +sub flip { + my $self = shift; + return Turnkey::Edge->new( thisfield => $self->thatfield, + thatfield => $self->thisfield, + thisnode => $self->thatnode, + thatnode => $self->thisnode, + type => $self->type eq 'import' ? 'export' : 'import' + ); } -1; -package SQL::Translator::Producer::Turnkey; +package Turnkey::HyperEdge; + +use strict; +use base qw(Turnkey::Edge); +use Class::MakeMethods::Template::Hash ( + 'array_of_objects -class SQL::Translator::Schema::Field' => [ qw( thisviafield thatviafield thisfield thatfield) ], + 'array_of_objects -class Turnkey::Node' => [ qw( thisnode thatnode ) ], + object => [ 'vianode' => {class => 'Turnkey::Node'} ], +); + + +package Turnkey::CompoundEdge; + +use strict; +use base qw(Turnkey::Edge); +use Class::MakeMethods::Template::Hash ( + new => ['new'], + object => [ + 'via' => {class => 'Turnkey::Node'}, + ], + 'array_of_objects -class Turnkey::Edge' => [ qw( edges ) ], +); -# ------------------------------------------------------------------- -# $Id: Turnkey.pm,v 1.5 2003-08-29 14:52:56 kycl4rk Exp $ -# ------------------------------------------------------------------- -# Copyright (C) 2003 Allen Day , -# Brian O'Connor , -# Ying Zhang -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; version 2. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -# 02111-1307 USA -# ------------------------------------------------------------------- + +package SQL::Translator::Producer::Turnkey; use strict; use vars qw[ $VERSION $DEBUG ]; -$VERSION = sprintf "%d.%02d", q$Revision: 1.5 $ =~ /(\d+)\.(\d+)/; +$VERSION = sprintf "%d.%02d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/; $DEBUG = 1 unless defined $DEBUG; use SQL::Translator::Schema::Constants; @@ -62,104 +84,133 @@ my %CDBI_auto_pkgs = ( sub produce { my $t = shift; my $create = undef; - local $DEBUG = $t->debug; my $no_comments = $t->no_comments; my $schema = $t->schema; my $args = $t->producer_args; - my $db_user = $args->{'db_user'} || ''; - my $db_pass = $args->{'db_pass'} || ''; - my $main_pkg_name = $args->{'main_pkg_name'} || - $t->format_package_name('DBI'); - my $header = header_comment(__PACKAGE__, "# "); - my $parser_type = ( split /::/, $t->parser_type )[-1]; - my $from = $CDBI_auto_pkgs{ $parser_type } || ''; - my $dsn = $args->{'dsn'} || sprintf( 'dbi:%s:_', - $CDBI_auto_pkgs{ $parser_type } - ? $CDBI_auto_pkgs{ $parser_type } : $parser_type - ); - my $sep = '# ' . '-' x 67; - # - # Identify "link tables" (have only PK and FK fields). - # - my %linkable; - my %linktable; - my %packages; - my $order; + my $parser_type = (split /::/, $t->parser_type)[-1]; + + local $DEBUG = $t->debug; + + my %meta = ( + format_fk => $t->format_fk_name, + template => $args->{'template'} || '', + baseclass => $args->{'main_pkg_name'} || $t->format_package_name('DBI'), + db_user => $args->{'db_user'} || '', + db_pass => $args->{'db_pass'} || '', + parser => $t->parser_type, + producer => __PACKAGE__, + dsn => $args->{'dsn'} || sprintf( 'dbi:%s:_', $CDBI_auto_pkgs{ $parser_type } + ? $CDBI_auto_pkgs{ $parser_type } + : $parser_type + ) + ); + # # build package objects # + my %nodes; + my $order; foreach my $table ($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 = Turnkey::Node->new(); + $nodes{ $table->name } = $node; - my $package = Turnkey::Package->new(); - $packages{ $table->name } = $package; - - $package->order( ++$order ); - $package->name( $t->format_package_name($table->name) ); - $package->base( $main_pkg_name ); - $package->table( $table ); - $package->primary_key( ($table->primary_key->fields)[0] ); + $node->order( ++$order ); + $node->name( $t->format_package_name($table->name) ); + $node->base( $meta{'baseclass'} ); + $node->table( $table ); + $node->primary_key( ($table->primary_key->fields)[0] ); # Primary key may have a differenct accessor method name - $package->primary_key_accessor( - defined($t->format_pk_name) ? $t->format_pk_name->( $package->name, $package->primary_key ) - : undef - ); + $node->primary_key_accessor( + defined($t->format_pk_name) + ? $t->format_pk_name->( $node->name, $node->primary_key ) + : undef + ); + } - foreach my $field ($table->get_fields){ + foreach my $node (values %nodes){ + foreach my $field ($node->table->get_fields){ next unless $field->is_foreign_key; - $package->push_many( $field->foreign_key_reference->reference_table ); + my $that = $nodes{ $field->foreign_key_reference->reference_table }; + #this means we have an incomplete schema + next unless $that; + + my $edge = Turnkey::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 ); } } # - # identify FK relationships + # type MM relationships # - foreach my $maylink ( $schema->get_tables ){ - foreach my $left ($schema->get_tables){ - foreach my $right ($schema->get_tables){ - - next if $left->name eq $right->name; - - my $lpackage = $packages{$left->name}; - my $rpackage = $packages{$right->name}; - - my($link,$lconstraints,$rconstraints) = @{ $maylink->can_link($left,$right) }; -warn $left->name, "\t", $maylink->name, "\t", $right->name if $link ne '0'; - - #one FK to one FK - if( $link eq 'one2one'){ -warn "\tone2one"; - $lpackage->one2one_push($rpackage->name, [$rpackage, $maylink]); - $rpackage->one2one_push($lpackage->name, [$lpackage, $maylink]); - - #one FK to many FK - } elsif( $link eq 'one2many'){ -warn "\tone2many"; - $lpackage->one2many_push($rpackage->name, [$rpackage, $maylink]); - $rpackage->many2one_push($lpackage->name, [$lpackage, $maylink]); - - #many FK to one FK - } elsif( $link eq 'many2one'){ -warn "\tmany2one"; - $lpackage->many2one_push($rpackage->name, [$rpackage, $maylink]); - $rpackage->one2many_push($lpackage->name, [$lpackage, $maylink]); - - #many FK to many FK - } elsif( $link eq 'many2many'){ -warn "\tmany2many"; -warn $left->name; -warn $right->name; - $lpackage->many2many_push($rpackage->name, [$rpackage, $maylink]); - $rpackage->many2many_push($lpackage->name, [$lpackage, $maylink]); + foreach my $lnode (sort values %nodes){ + next if $lnode->table->is_data; + foreach my $inode1 (sort values %nodes){ + 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 values %nodes){ + my %i = map {$_->thatnode->name => 1} grep { $_->type eq 'import'} $lnode->edges; + if(scalar(keys %i) == 1) { } else { - #not linkable + 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 = Turnkey::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; + } } } @@ -167,178 +218,163 @@ warn $right->name; # # create methods # - foreach my $package_from (values %packages){ - next unless $package_from->table->is_data; - - my %linked; - - my %o2o = $package_from->one2one; -warn Dumper(%o2o); - my %o2m = $package_from->one2many; -warn Dumper(%o2m); - my %m2o = $package_from->many2one; -warn Dumper(%m2o); - my %m2m = $package_from->many2many; -warn Dumper(%m2m); - - foreach my $package_to (keys %{ $package_from->one2one }){ - $package_to = $packages{$package_to}; - foreach my $bridge ( $package_from->one2one($package_to->name) ){ - $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( - $package_from->one2one($package_to->name)->[1]->name, - $package_to->primary_key - ).'s' - : $package_from->one2one($package_to->name)->[1]->name .'_'. - $package_to->primary_key .'s'; - } - } + foreach my $node_from (values %nodes){ + next unless $node_from->table->is_data; + foreach my $cedge ( $node_from->compoundedges ){ + my $hyperedge = Turnkey::HyperEdge->new; - foreach my $package_to (keys %{ $package_from->one2many }){ - $package_to = $packages{$package_to}; - foreach my $bridge ( $package_from->one2many($package_to->name) ){ - $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( - $package_from->one2many($package_to->name)->[1]->name, - $package_to->primary_key - ).'s' - : $package_from->one2many($package_to->name)->[1]->name .'_'. - $package_to->primary_key .'s'; - } - } + my $node_to; - foreach my $package_to (keys %{ $package_from->many2one }){ - $package_to = $packages{$package_to}; - foreach my $bridge ( $package_from->many2one($package_to->name) ){ - $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( - $package_from->many2one($package_to->name)->[1]->name, - $package_to->primary_key - ).'s' - : $package_from->many2one($package_to->name)->[1]->name .'_'. - $package_to->primary_key .'s'; - } - } + foreach my $edge ($cedge->edges){ + if($edge->thisnode->name eq $node_from->name){ + $hyperedge->vianode($edge->thatnode); - foreach my $package_to (keys %{ $package_from->many2many }){ - $package_to = $packages{$package_to}; - foreach my $bridge ( $package_from->many2many($package_to->name) ){ - $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( - $package_from->many2many($package_to->name)->[1]->name, - $package_to->primary_key - ).'s' - : $package_from->many2many($package_to->name)->[1]->name .'_'. - $package_to->primary_key .'s'; - } - } + if($edge->thatnode->name ne $cedge->via->name){ + $node_to ||= $nodes{ $edge->thatnode->table->name }; + } + $hyperedge->push_thisnode($edge->thisnode); + $hyperedge->push_thisfield($edge->thisfield); + $hyperedge->push_thisviafield($edge->thatfield); + } else { + if($edge->thisnode->name ne $cedge->via->name){ + $node_to ||= $nodes{ $edge->thisnode->table->name }; + } -# #if one possible traversal via link table -# if (scalar(@rk_fields) == 1 and scalar(@lk_fields) == 1) { -# foreach my $rk_field (@rk_fields) { -# push @{ $packages{ $package->name }{'has_many'}{$link}{'link_one_one'} }, -# "sub ".$linkmethodname." { my \$self = shift; ". -# "return map \$_->". -# ($schema->get_table($link)->primary_key->fields)[0]. -# ", \$self->".$linkable{$table_from->name}{$link}->name. -# "_".$rk_field." }\n\n"; -# } -# #NOTE: we need to rethink the link method name, as the cardinality -# #has shifted on us. -# } elsif (scalar(@rk_fields) == 1) { -# foreach my $rk_field (@rk_fields) { -# # ADD CALLBACK FOR PLURALIZATION MANGLING HERE -# push @{ $packages{ $package->name }{'has_many'}{ $link }{'link_many_one'} }, -# "sub " . $linkable{$table_from->name}{$link}->name . -# "s { my \$self = shift; return \$self->" . -# $linkable{$table_from->name}{$link}->name . "_" . -# $rk_field . "(\@_) }\n\n"; -# } -# } elsif (scalar(@lk_fields) == 1) { -# #these will be taken care of on the other end... -# } else { -# #many many many. need multiple iterations here, data structure revision -# #to handle N FK sources. This code has not been tested and likely doesn't -# #work here -# foreach my $rk_field (@rk_fields) { -# # ADD CALLBACK FOR PLURALIZATION MANGLING HERE -# push @{ $packages{ $package->name }{'has_many'}{ $link }{'link_many_many'} }, -# "sub " . $linkable{$table_from->name}{$link}->name . "_" . $rk_field . -# "s { my \$self = shift; return \$self->" . -# $linkable{$table_from->name}{$link}->name . "_" . -# $rk_field . "(\@_) }\n\n"; -# } -# } -# } - - -# # -# # Use foreign keys to set up "has_a/has_many" relationships. -# # -# foreach my $field ( $table_from->get_fields ) { -# if ( $field->is_foreign_key ) { -# my $table_name = $table_from->name; -# my $field_name = $field->name; -# my $fk_method = $t->format_fk_name($table_name, $field_name); -# my $fk = $field->foreign_key_reference; -# my $ref_table = $fk->reference_table; -# my $ref_pkg = $t->format_package_name($ref_table); -# my $ref_field = ($fk->reference_fields)[0]; - -# push @{ $packages{ $package->name }{'has_a'} }, -# $package->name."->has_a( $field_name => '$ref_pkg');\n". -# "sub $fk_method { return shift->$field_name }\n\n" -# ; - - -# # -# # If this table "has a" to the other, then it follows -# # that the other table "has many" of this one, right? -# # -# # No... there is the possibility of 1-1 cardinality - -# #if there weren't M-M relationships via the has_many -# #being set up here, create nice pluralized method alias -# #rather for user as alt. to ugly tablename_fieldname name -# if(! $packages{ $ref_pkg }{ 'has_many' }{ $table_from->name } ){ -# # ADD CALLBACK FOR PLURALIZATION MANGLING HERE -# #push @{ $packages{ $ref_pkg }{'has_many'}{ $table_name } }, -# # "sub $table_name\s {\n return shift->$table_name\_$field_name\n}\n\n"; -# push @{ $packages{ $ref_pkg }{'has_many'}{ $table_from->name }{'fk_pluralized'} }, -# { table_name => $table_from->name, field_name => $field_name }; - -# #else ugly -# } else { -# } - -# #push @{ $packages{ $ref_pkg }{'has_many'}{ $table_name } }, -# # "$ref_pkg->has_many(\n '${table_name}_${field_name}', ". -# # "'$table_pkg_name' => '$field_name'\n);\n\n"; -# push @{ $packages{ $ref_pkg }{'has_many'}{ $table_name }{pluralized} }, -# { ref_pkg => $ref_pkg, table_pkg_name => $package->name, table_name => $table_from->name, field_name => $field_name }; -# } -# } + $hyperedge->push_thatnode($edge->thisnode); + $hyperedge->push_thatfield($edge->thisfield); + $hyperedge->push_thatviafield($edge->thatfield); + } + } + + if($hyperedge->count_thisnode == 1 and $hyperedge->count_thatnode == 1){ $hyperedge->type('one2one') } + elsif($hyperedge->count_thisnode > 1 and $hyperedge->count_thatnode == 1){ $hyperedge->type('many2one') } + elsif($hyperedge->count_thisnode == 1 and $hyperedge->count_thatnode > 1){ $hyperedge->type('one2many') } + elsif($hyperedge->count_thisnode > 1 and $hyperedge->count_thatnode > 1){ $hyperedge->type('many2many') } + +#warn $node_from->name ."\t". $node_to->name ."\t". $hyperedge->type ."\t". $hyperedge->vianode->name; + + $node_from->push_hyperedges($hyperedge); + } } - my %metadata; - $metadata{"packages"} = \%packages; - $metadata{"linkable"} = \%linkable; - return(translateForm($t, \%metadata)); + $meta{"nodes"} = \%nodes; + return(translateForm($t, \%meta)); } ########################################### # Here documents for the tt2 templates # ########################################### +my $turnkey_dbi_tt2 = <set_up_table('[% node.table.name %]'); +[% printPKAccessors(node.primary_key, node.table.name) %] +[% printHasA(node.edges, node) %] +[% printHasMany(node.edges, node) %] +[% printHasCompound(node.compoundedges, node.hyperedges, node.name) %] +[% END %] + +[% MACRO printPKAccessors(array, name) BLOCK %] +# +# Primary key accessors +# +[% FOREACH item = array %] +sub id { shift->[% item %] } +sub [% name %] { shift->[% item %] } +[% END %] +[% END %] + +[% MACRO printHasA(edges, name) BLOCK %] +# +# Has A +# +[% FOREACH edge = edges %] + [%- IF edge.type == 'import' -%] +[% node.name %]->has_a([% edge.thisfield.name %] => '[% edge.thatnode.name %]'); + [%- IF node.has(edge.thatnode.name) < 2 %] +sub [% edge.thatnode.table.name %] { return shift->[% edge.thisfield.name %] } + [%- ELSE %] +sub [% format_fk(edge.thisnode.table.name,edge.thisfield.name) %] { return shift->[% edge.thisfield.name %] } + [%- END %] + [%- END %] +[% END %] +[% END %] + +[% MACRO printHasMany(edges, node) BLOCK %] +# +# Has Many +# +[% FOREACH edge = edges %] + [%- IF edge.type == 'export' -%] +[% node.name %]->has_many([% edge.thatnode.table.name %]_[% edge.thatfield.name %], '[% edge.thatnode.name %]' => '[% edge.thatfield.name %]'); + [%- IF node.via(edge.thatnode.name) >= 1 %] +sub [% edge.thatnode.table.name %]_[% format_fk(edge.thatnode.table.name,edge.thatfield.name) %]s { return shift->[% edge.thatnode.table.name %]_[% edge.thatfield.name %] } + [%- ELSIF edge.thatnode.table.is_data %] +sub [% edge.thatnode.table.name %]s { return shift->[% edge.thatnode.table.name %]_[% edge.thatfield.name %] } + [%- END %] + [%- END %] +[% END %] +[% END %] + +[% MACRO printHasCompound(cedges,hedges,name) BLOCK %] +# +# Has Compound Many +# +[% FOREACH cedge = cedges %] +[% FOREACH edge = cedge.edges %] + [%- NEXT IF edge.thisnode.name != name -%] +sub [% cedge.via.table.name %]_[% format_fk(edge.thatnode.table.name,edge.thatfield.name) %]s { return shift->[% cedge.via.table.name %]_[% edge.thatfield.name %] } +[% END %] +[% END %] +[% FOREACH h = hedges %] + [%- NEXT IF h.thisnode.name != name -%] + [%- IF h.type == 'one2one' %] +1sub [% h.thatnode.table.name %]s { my \$self = shift; return map \$_->[% h.thatviafield.name %], \$self->[% h.vianode.table.name %]_[% h.thisviafield.name %] } + [%- ELSIF h.type == 'one2many' %] +2 + [%- ELSIF h.type == 'many2one' %] +3sub [% h.thatnode.table.name %]s { my \$self = shift; return map \$_->[% h.thatviafield.name %], \$self->[% h.vianode.table.name %]_[% h.thisviafield.name %] } + [%- ELSIF h.type == 'many2many' %] +4 + [%- END %] +[% END %] +[% END %] + +[% MACRO printList(array) BLOCK %][% FOREACH item = array %][% item %] [% END %][% END %] +package [% baseclass %]; + +# Created by SQL::Translator::Producer::Turnkey +# Template used: classdbi + +use strict; +use base qw(Class::DBI::Pg); + +Durian::Model::DBI->set_db('Main', '[% db_str %]', '[% db_user %]', '[% db_pass %]'); + +[% FOREACH node = nodes %] + [% printPackage(node.value) %] +[% END %] +EOF + my $turnkey_atom_tt2 = <<'EOF'; [% ###### DOCUMENT START ###### %] -[% FOREACH package = linkable %] +[% FOREACH node = linkable %] ############################################## -package Durian::Atom::[% package.key FILTER ucfirst %]; +package Durian::Atom::[% node.key FILTER ucfirst %]; -[% pname = package.key FILTER ucfirst%] +[% pname = node.key FILTER ucfirst%] [% pkey = "Durian::Model::${pname}" %] use base qw(Durian::Atom); @@ -353,7 +389,7 @@ sub render { my $dbobject = shift; # Assumption here that if it's not rendering on it's own dbobject # then it's a list. This will be updated when AtomLists are implemented -boconnor - if(ref($dbobject) eq 'Durian::Model::[% package.key FILTER ucfirst %]') { + if(ref($dbobject) eq 'Durian::Model::[% node.key FILTER ucfirst %]') { return(_render_record($dbobject)); } else { return(_render_list($dbobject)); } @@ -364,7 +400,7 @@ sub _render_record { my @output = (); my $row = {}; my $field_hash = {}; - [% FOREACH field = packages.$pkey.columns_essential %] + [% FOREACH field = nodes.$pkey.columns_essential %] $field_hash->{[% field %]} = $dbobject->[% field %](); [% END %] $row->{data} = $field_hash; @@ -376,12 +412,12 @@ sub _render_record { sub _render_list { my $dbobject = shift; my @output = (); - my @objects = $dbobject->[% package.key %]s; + my @objects = $dbobject->[% node.key %]s; foreach my $object (@objects) { my $row = {}; my $field_hash = {}; - [% FOREACH field = packages.$pkey.columns_essential %] + [% FOREACH field = nodes.$pkey.columns_essential %] $field_hash->{[% field %]} = $object->[% field %](); [% END %] $row->{data} = $field_hash; @@ -400,93 +436,6 @@ sub head { [% END %] EOF -my $turnkey_dbi_tt2 = <set_up_table('[% package.table %]'); -[% package.pkg_name %]->columns(Primary => qw/[% printList(package.columns_primary) %]/); -[% package.pkg_name %]->columns(Essential => qw/[% printList(package.columns_essential) %]/); - -[% printPKAccessors(package.columns_primary, package.table) %] -[% printHasMany(package.has_many, package.table) %] -[% printHasA(package.has_a, package.pkg_name) %] - -[% END %] - -[% MACRO printPKAccessors(array, name) BLOCK %] -# -# Primary key accessor -# -[% FOREACH item = array %] -sub [% name %] { - shift->[% item %]; -} -[% END %] -[% END %] - -[% MACRO printHasMany(hash, name) BLOCK %] -# -# Has Many -# -[% FOREACH group = hash %][% FOREACH item = group.value %][% FOREACH arr = item.value %] -# Key: [% group.key %] -# Relationship: [% item.key %] - [% IF item.key == 'fk_pluralized' %] -sub [% arr.table_name -%]s { - return shift->[% arr.table_name %]_[% arr.field_name %] - }; - [% ELSIF item.key == 'pluralized' %] -[% arr.ref_pkg %]->has_many('[% arr.table_name %]_[% arr.field_name %]', '[% arr.table_pkg_name %]' => '[% arr.field_name %]'); - [% ELSIF item.key == 'link_one_one' %] - [% FOREACH line = item.value %] -[% line %] - [% END %] - [% ELSIF item.key == 'link_many_one' %] - [% FOREACH line = item.value %] -[% line %] - [% END %] - [% ELSIF item.key == 'link_many_many' %] - [% FOREACH line = item.value %] -[% line %] - [% END %] - [% END %] - -[% END %][% END %][% END %][% END %] - -[% MACRO printHasA(hash, pkg_name) BLOCK %] -# -# Has A -# -[% #name %] -[% FOREACH item = hash %][% item %] -[% END %][% END %] - -[% MACRO printList(array) BLOCK %][% FOREACH item = array %][% item %] [% END %][% END %] - - -[% ###### DOCUMENT START ###### %] - -package Durian::Model::DBI; - -# Created by SQL::Translator::Producer::ClassDBI -# Template used AutoDBI.tt2 - -use strict; -use base qw(Class::DBI::Pg); - -Durian::Model::DBI->set_db('Main', '[% db_str %]', '[% db_user %]', '[% db_pass %]'); - -[% FOREACH package = packages %] - [% printPackage(package.value) %] -[% END %] -EOF - my $turnkey_xml_tt2 = < @@ -501,8 +450,8 @@ my $turnkey_xml_tt2 = < -[% FOREACH package = linkable %] - +[% FOREACH node = linkable %] + [%- END -%] @@ -576,24 +525,24 @@ my $turnkey_template_tt2 = <<'EOF'; [% END %] [% MACRO renderatom(atom, dbobject) SWITCH atom.name %] - [- FOREACH package = linkable -] - [% CASE '[- package.key FILTER ucfirst -]' %] - [% render[- package.key FILTER ucfirst -]Atom(atom.render(dbobject)) %] + [- FOREACH node = linkable -] + [% CASE '[- node.key FILTER ucfirst -]' %] + [% render[- node.key FILTER ucfirst -]Atom(atom.render(dbobject)) %] [- END -] [% CASE DEFAULT %] [% renderlist(atom.render(dbobject)) %] [% END %] -[- FOREACH package = linkable -] -[% MACRO render[- package.key FILTER ucfirst -]Atom(lstArr) BLOCK %] +[- FOREACH node = linkable -] +[% MACRO render[- node.key FILTER ucfirst -]Atom(lstArr) BLOCK %] [% FOREACH record = lstArr %] [% fields = record.data %] - [- pname = package.key FILTER ucfirst -] + [- pname = node.key FILTER ucfirst -] [- pkey = "Durian::Model::${pname}" -] - [- FOREACH field = packages.$pkey.columns_essential -] + [- FOREACH field = nodes.$pkey.columns_essential -] [- field -][% fields.[- field -] %] [- END -] [% id = record.id %] - Link + Link [% END %] [% END %] [- END -] @@ -604,12 +553,14 @@ my $turnkey_template_tt2 = <<'EOF'; [% END %] EOF + sub translateForm { my $t = shift; - my $output = shift; + my $meta = shift; +# my $output = shift; my $args = $t->producer_args; - my $tt2 = $args->{'template'}; + my $tt2 = $meta->{'template'}; my $tt2Ref; if ($tt2 eq 'atom') { $tt2Ref = \$turnkey_atom_tt2; } @@ -618,14 +569,6 @@ sub translateForm elsif ($tt2 eq 'template') { $tt2Ref = \$turnkey_template_tt2; } else { die __PACKAGE__." didn't recognize your template option: $tt2" } - my $vars = { - packages => $output->{packages}, - linkable => $output->{linkable}, - linktable => $output->{linktable}, - db_str => $args->{db_str}, - db_user => $args->{db_user}, - db_pass => $args->{db_pass}, - }; my $config = { EVAL_PERL => 1, # evaluate Perl code blocks }; @@ -636,7 +579,7 @@ sub translateForm my $result; # specify input filename, or file handle, text reference, etc. # process input template, substituting variables - $template->process($tt2Ref, $vars, \$result) || die $template->error(); + $template->process($tt2Ref, $meta, \$result) || die $template->error(); return($result); } diff --git a/lib/SQL/Translator/Schema/Table.pm b/lib/SQL/Translator/Schema/Table.pm index 35f51f6..03c51ad 100644 --- a/lib/SQL/Translator/Schema/Table.pm +++ b/lib/SQL/Translator/Schema/Table.pm @@ -1,7 +1,7 @@ package SQL::Translator::Schema::Table; # ---------------------------------------------------------------------- -# $Id: Table.pm,v 1.18 2003-08-29 14:54:01 kycl4rk Exp $ +# $Id: Table.pm,v 1.19 2003-09-02 00:24:07 allenday Exp $ # ---------------------------------------------------------------------- # Copyright (C) 2003 Ken Y. Clark # @@ -51,7 +51,7 @@ use Data::Dumper; use base 'Class::Base'; use vars qw( $VERSION $FIELD_ORDER ); -$VERSION = sprintf "%d.%02d", q$Revision: 1.18 $ =~ /(\d+)\.(\d+)/; +$VERSION = sprintf "%d.%02d", q$Revision: 1.19 $ =~ /(\d+)\.(\d+)/; # ---------------------------------------------------------------------- sub init { @@ -433,13 +433,21 @@ sub is_data { $self->{'is_data'} = 0; + my %fk = (); + foreach my $field ( $self->get_fields ) { if ( !$field->is_primary_key and !$field->is_foreign_key ) { $self->{'is_data'} = 1; return $self->{'is_data'}; +# } elsif($field->is_foreign_key) { +# $fk{$field->foreign_key_reference->reference_table}++; } } +# foreach my $referenced (keys %fk){ +# $self->{'is_data'} = 1 and last if $fk{$referenced} > 1; +# } + return $self->{'is_data'}; } diff --git a/t/data/pgsql/turnkey.sql b/t/data/pgsql/turnkey.sql new file mode 100644 index 0000000..b53ea86 --- /dev/null +++ b/t/data/pgsql/turnkey.sql @@ -0,0 +1,86 @@ +create table a ( + a_id serial not null, + primary key (a_id), + b_id int not null, + foreign key (b_id) references b (b_id), + name text +); + +--create table b ( +-- b_id serial not null, +-- primary key (b_id), +-- name text +--); + +--create table a_b ( +-- a_b_id serial not null, +-- primary key (a_b_id), +-- a_id int not null, +-- foreign key (a_id) references a (a_id), +-- b_id int not null, +-- foreign key (b_id) references b (b_id) +--); + +--create table c ( +-- c_id serial not null, +-- primary key (c_id), +-- b_id int not null, +-- foreign key (b_id) references b (b_id), +-- name text +--); + +--create table d ( +-- d_id serial not null, +-- primary key (d_id), +-- c_id int not null, +-- foreign key (c_id) references c (c_id), +-- name text +--); + +create table e ( + e_id serial not null, + primary key (e_id), + name text +); + +--create table c_e ( +-- c_e_id serial not null, +-- primary key (c_e_id), +-- c_id int not null, +-- foreign key (c_id) references c (c_id), +-- e_id int not null, +-- foreign key (e_id) references e (e_id) +--); + +--create table f ( +-- f_id serial not null, +-- primary key (f_id), +-- e1_id int not null, +-- foreign key (e1_id) references e (e_id), +-- e2_id int not null, +-- foreign key (e2_id) references e (e_id) +--); + +create table g ( + g_id serial not null, + primary key (g_id), + a_id int not null, + foreign key (a_id) references a (a_id), + e1_id int not null, + foreign key (e1_id) references e (e_id), + e2_id int not null, + foreign key (e2_id) references e (e_id) +); + +--create table h ( +-- h_id serial not null, +-- primary key (h_id), +-- a1_id int not null, +-- foreign key (a1_id) references a (a_id), +-- a2_id int not null, +-- foreign key (a2_id) references a (a_id), +-- g1_id int not null, +-- foreign key (g1_id) references g (g_id), +-- g2_id int not null, +-- foreign key (g2_id) references g (g_id) +--);