X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FTranslator%2FParser%2FDBIx%2FClass.pm;h=a53a7a5786b7e263e9ef16d5e43fdd085cf6dd1a;hb=aaf2403d17fd75fea98d22c2ef28c42d3285ef03;hp=c0fece0e30f91a3052f408b03fb9323d6652ce9d;hpb=7b90bb139d64454ea6ebae5876fcb181988c03c1;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/SQL/Translator/Parser/DBIx/Class.pm b/lib/SQL/Translator/Parser/DBIx/Class.pm index c0fece0..a53a7a5 100644 --- a/lib/SQL/Translator/Parser/DBIx/Class.pm +++ b/lib/SQL/Translator/Parser/DBIx/Class.pm @@ -5,6 +5,8 @@ package # hide from PAUSE # Some mistakes the fault of Matt S Trout +# Others the fault of Ash Berlin + use strict; use warnings; use vars qw($DEBUG $VERSION @EXPORT_OK); @@ -26,10 +28,11 @@ use base qw(Exporter); # We're working with DBIx::Class Schemas, not data streams. # ------------------------------------------------------------------- sub parse { - my ($tr, $data) = @_; - my $args = $tr->parser_args; - my $dbixschema = $args->{'DBIx::Schema'} || $data; - $dbixschema ||= $args->{'package'}; + my ($tr, $data) = @_; + my $args = $tr->parser_args; + my $dbixschema = $args->{'DBIx::Schema'} || $data; + $dbixschema ||= $args->{'package'}; + my $limit_sources = $args->{'sources'}; die 'No DBIx::Schema' unless ($dbixschema); if (!ref $dbixschema) { @@ -43,12 +46,33 @@ sub parse { # print Dumper($dbixschema->registered_classes); #foreach my $tableclass ($dbixschema->registered_classes) - foreach my $moniker ($dbixschema->sources) + + my %seen_tables; + + my @monikers = $dbixschema->sources; + if ($limit_sources) { + my $ref = ref $limit_sources || ''; + die "'sources' parameter must be an array or hash ref" unless $ref eq 'ARRAY' || ref eq 'HASH'; + + # limit monikers to those specified in + my $sources; + if ($ref eq 'ARRAY') { + $sources->{$_} = 1 for (@$limit_sources); + } else { + $sources = $limit_sources; + } + @monikers = grep { $sources->{$_} } @monikers; + } + + + foreach my $moniker (@monikers) { #eval "use $tableclass"; #print("Can't load $tableclass"), next if($@); my $source = $dbixschema->source($moniker); + next if $seen_tables{$source->name}++; + my $table = $schema->add_table( name => $source->name, type => 'TABLE', @@ -76,7 +100,7 @@ sub parse { my @primary = $source->primary_columns; my %unique_constraints = $source->unique_constraints; foreach my $uniq (keys %unique_constraints) { - if (!equal_keys($unique_constraints{$uniq}, \@primary)) { + if (!$source->compare_relationship_keys($unique_constraints{$uniq}, \@primary)) { $table->add_constraint( type => 'unique', name => "$uniq", @@ -86,15 +110,19 @@ sub parse { } my @rels = $source->relationships(); + + my %created_FK_rels; + foreach my $rel (@rels) { my $rel_info = $source->relationship_info($rel); - my $rel_table = $source->related_source($rel)->name; - # Ignore any rel cond that isn't a straight hash next unless ref $rel_info->{cond} eq 'HASH'; + my $othertable = $source->related_source($rel); + my $rel_table = $othertable->name; + # Get the key information, mapping off the foreign/self markers my @cond = keys(%{$rel_info->{cond}}); my @refkeys = map {/^\w+\.(\w+)$/} @cond; @@ -102,63 +130,53 @@ sub parse { if($rel_table) { + my $reverse_rels = $source->reverse_relationship_info($rel); + my ($otherrelname, $otherrelationship) = each %{$reverse_rels}; + + my $on_delete = ''; + my $on_update = ''; + + if (defined $otherrelationship) { + $on_delete = $otherrelationship->{'attrs'}->{cascade_delete} ? 'CASCADE' : ''; + $on_update = $otherrelationship->{'attrs'}->{cascade_copy} ? 'CASCADE' : ''; + } + + # Make sure we dont create the same foreign key constraint twice + my $key_test = join("\x00", @keys); #Decide if this is a foreign key based on whether the self #items are our primary columns. # If the sets are different, then we assume it's a foreign key from # us to another table. - if (!equal_keys(\@keys, \@primary)) { + # OR: If is_foreign_key_constraint attr is explicity set (or set to false) on the relation + if ( ! exists $created_FK_rels{$rel_table}->{$key_test} && + ( exists $rel_info->{attrs}{is_foreign_key_constraint} && + $rel_info->{attrs}{is_foreign_key_constraint} || + !$source->compare_relationship_keys(\@keys, \@primary) + ) + ) + { + $created_FK_rels{$rel_table}->{$key_test} = 1; $table->add_constraint( type => 'foreign_key', name => "fk_$keys[0]", fields => \@keys, reference_fields => \@refkeys, reference_table => $rel_table, + on_delete => $on_delete, + on_update => $on_update ); } } } - } - return 1; -} - -# ------------------------------------------------------------------- -# equal_keys($key1, $key2) -# -# See if the set of keys in $key1 is equal to the set of keys in $key2 -# ------------------------------------------------------------------- -sub equal_keys { - my ($key1, $key2) = @_; - - # Make sure every key1 is in key2 - my $found; - foreach my $key (@$key1) { - $found = 0; - foreach my $prim (@$key2) { - if ($prim eq $key) { - $found = 1; - last; - } - } - last unless $found; - } - # Make sure every key2 is in key1 - if ($found) { - foreach my $prim (@$key2) { - $found = 0; - foreach my $key (@$key1) { - if ($prim eq $key) { - $found = 1; - last; - } - } - last unless $found; + if ($source->result_class->can('sqlt_deploy_hook')) { + $source->result_class->sqlt_deploy_hook($table); } } - - return $found; + return 1; } 1; +