X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FTranslator%2FParser%2FDBIx%2FClass.pm;h=996d4613981c04219b5a5b52d43c340dd98c1fe6;hb=89cf6a706832b79c02f980077bd30525b3716ee0;hp=7e4421fa6430b2258e30a780dcd4098344c80c58;hpb=c8f572405272013bb6c2c79dec8421bd6a9a3cc5;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/SQL/Translator/Parser/DBIx/Class.pm b/lib/SQL/Translator/Parser/DBIx/Class.pm index 7e4421f..996d461 100644 --- a/lib/SQL/Translator/Parser/DBIx/Class.pm +++ b/lib/SQL/Translator/Parser/DBIx/Class.pm @@ -14,6 +14,7 @@ $DEBUG = 0 unless defined $DEBUG; use Exporter; use Data::Dumper; +use Digest::SHA1 qw( sha1_hex ); use SQL::Translator::Utils qw(debug normalize_name); use base qw(Exporter); @@ -95,29 +96,14 @@ sub parse { $table->primary_key($source->primary_columns); my @primary = $source->primary_columns; - foreach my $field (@primary) { - my $index = $table->add_index( - name => $field, - fields => [$field], - type => 'NORMAL', - ); - } my %unique_constraints = $source->unique_constraints; foreach my $uniq (sort keys %unique_constraints) { if (!$source->compare_relationship_keys($unique_constraints{$uniq}, \@primary)) { $table->add_constraint( type => 'unique', - name => "$uniq", + name => _create_unique_symbol($uniq), fields => $unique_constraints{$uniq} ); - - my $index = $table->add_index( - # TODO: Pick a better than that wont conflict - name => $unique_constraints{$uniq}->[0], - fields => $unique_constraints{$uniq}, - type => 'NORMAL', - ); - } } @@ -136,8 +122,15 @@ sub parse { my $rel_table = $othertable->name; # Get the key information, mapping off the foreign/self markers - my @cond = keys(%{$rel_info->{cond}}); + my @cond = keys(%{$rel_info->{cond}}); my @refkeys = map {/^\w+\.(\w+)$/} @cond; + + # Force the order of the referenced fields to be the same as + # ->add_columns method. + my $idx; + my %other_columns_idx = map {$_ => $idx++} $othertable->columns; + @refkeys = sort { $other_columns_idx{$a} cmp $other_columns_idx{$b} } @refkeys; + my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond; if($rel_table) @@ -153,7 +146,7 @@ sub parse { $on_update = $otherrelationship->{'attrs'}->{cascade_copy} ? 'CASCADE' : ''; } - my $is_deferrable = $rel_info->{attrs}{is_deferrable} || 0; + my $is_deferrable = $rel_info->{attrs}{is_deferrable}; # Make sure we dont create the same foreign key constraint twice my $key_test = join("\x00", @keys); @@ -179,16 +172,19 @@ sub parse { if (scalar(@keys)) { $table->add_constraint( type => 'foreign_key', - name => $table->name . "_fk_$keys[0]", + name => _create_unique_symbol($table->name + . '_fk_' + . join('_', @keys)), fields => \@keys, reference_fields => \@refkeys, reference_table => $rel_table, on_delete => $on_delete, - on_update => $on_update + on_update => $on_update, + (defined $is_deferrable ? ( deferrable => $is_deferrable ) : ()), ); my $index = $table->add_index( - name => join('_', @keys), + name => _create_unique_symbol(join('_', @keys)), fields => \@keys, type => 'NORMAL', ); @@ -208,5 +204,31 @@ sub parse { return 1; } -1; +# TODO - is there a reasonable way to pass configuration? +# Default of 64 comes from mysql's limit. +our $MAX_SYMBOL_LENGTH ||= 64; +our $COLLISION_TAG_LENGTH ||= 8; +# ------------------------------------------------------------------- +# $resolved_name = _create_unique_symbol($desired_name) +# +# If desired_name is really long, it will be truncated in a way that +# has a high probability of leaving it unique. +# ------------------------------------------------------------------- +sub _create_unique_symbol { + my $desired_name = shift; + return $desired_name if length $desired_name <= $MAX_SYMBOL_LENGTH; + + my $truncated_name = substr $desired_name, 0, $MAX_SYMBOL_LENGTH - $COLLISION_TAG_LENGTH - 1; + + # Hex isn't the most space-efficient, but it skirts around allowed + # charset issues + my $digest = sha1_hex($desired_name); + my $collision_tag = substr $digest, 0, $COLLISION_TAG_LENGTH; + + return $truncated_name + . '_' + . $collision_tag; +} + +1;