'Class::Base' => 0,
'Class::Data::Inheritable' => 0.02,
'Class::MakeMethods' => 0,
+ 'Digest::SHA1' => 2.00,
'IO::Dir' => 0,
'Log::Log4perl' => 0,
'Parse::RecDescent' => 1.94,
* Added support for proper booleans in the mysql producer, when a mysql version of at least 4.x is supplied
* Added support for proper enums under pg (as of 8.3), with pg version check, and deferrable constraints
+* Added support to truncate long constraint and index names in the mysql producer, because of a change to DBIx::Class to produce such long names in some cases.
# ----------------------------------------------------------
# 0.0900 2008-02-25
=item * Daniel Ruoso <daniel@ruoso.com>
+=item * Ryan D Johnson <ryan@innerfence.com>
+
=back
If you would like to contribute to the project, you can send patches
$VERSION = sprintf "%d.%02d", q$Revision: 1.54 $ =~ /(\d+)\.(\d+)/;
$DEBUG = 0 unless defined $DEBUG;
+# Maximum length for most identifiers is 64, according to:
+# http://dev.mysql.com/doc/refman/4.1/en/identifiers.html
+# http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
+my $DEFAULT_MAX_ID_LENGTH = 64;
+
use Data::Dumper;
use SQL::Translator::Schema::Constants;
-use SQL::Translator::Utils qw(debug header_comment);
+use SQL::Translator::Utils qw(debug header_comment truncate_id_uniquely);
#
# Use only lowercase for the keys (e.g. "long" and not "LONG")
my $show_warnings = $translator->show_warnings || 0;
my $producer_args = $translator->producer_args;
my $mysql_version = $producer_args->{mysql_version} || 0;
+ my $max_id_length = $producer_args->{mysql_max_id_length} || $DEFAULT_MAX_ID_LENGTH;
my ($qt, $qf, $qc) = ('','', '');
$qt = '`' if $translator->quote_table_names;
no_comments => $no_comments,
quote_table_names => $qt,
quote_field_names => $qf,
+ max_id_length => $max_id_length,
mysql_version => $mysql_version
});
}
return join( ' ',
lc $index->type eq 'normal' ? 'INDEX' : $index->type . ' INDEX',
- $index->name,
+ truncate_id_uniquely( $index->name, $options->{max_id_length} || $DEFAULT_MAX_ID_LENGTH ),
'(' . $qf . join( "$qf, $qf", $index->fields ) . $qf . ')'
);
elsif ( $c->type eq UNIQUE ) {
return
'UNIQUE '.
- (defined $c->name ? $qf.$c->name.$qf.' ' : '').
+ (defined $c->name ? $qf.truncate_id_uniquely( $c->name, $options->{max_id_length} || $DEFAULT_MAX_ID_LENGTH ).$qf.' ' : '').
'(' . $qf . join("$qf, $qf", @fields). $qf . ')';
}
elsif ( $c->type eq FOREIGN_KEY ) {
#
my $table = $c->table;
- my $c_name = $c->name;
+ my $c_name = truncate_id_uniquely( $c->name, $options->{max_id_length} || $DEFAULT_MAX_ID_LENGTH );
my $def = join(' ',
map { $_ || () }
use base qw(Exporter);
use vars qw($VERSION $DEFAULT_COMMENT @EXPORT_OK);
+use Digest::SHA1 qw( sha1_hex );
+
use Exporter;
$VERSION = sprintf "%d.%02d", q$Revision: 1.12 $ =~ /(\d+)\.(\d+)/;
$DEFAULT_COMMENT = '-- ';
@EXPORT_OK = qw(
- debug normalize_name header_comment parse_list_arg $DEFAULT_COMMENT
+ debug normalize_name header_comment parse_list_arg truncate_id_uniquely $DEFAULT_COMMENT
);
# ----------------------------------------------------------------------
}
}
+# ----------------------------------------------------------------------
+# truncate_id_uniquely( $desired_name, $max_symbol_length )
+#
+# Truncates the name $desired_name to the $max_symbol_length by
+# including part of the hash of the full name at the end of the
+# truncated name, giving a high probability that the symbol will be
+# unique.
+# ----------------------------------------------------------------------
+my $COLLISION_TAG_LENGTH = 8;
+sub truncate_id_uniquely {
+ my ( $desired_name, $max_symbol_length ) = @_;
+
+ return $desired_name unless defined $desired_name && 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;
# ----------------------------------------------------------------------
parse_list_arg( [ 'id', 'name' ] );
parse_list_arg( qw[ id name ] );
+=head2 truncate_id_uniquely
+
+Takes a string ($desired_name) and int ($max_symbol_length). Truncates
+$desired_name to $max_symbol_length by including part of the hash of
+the full name at the end of the truncated name, giving a high
+probability that the symbol will be unique. For example,
+
+ truncate_id_uniquely( 'a' x 100, 64 )
+ truncate_id_uniquely( 'a' x 99 . 'b', 64 );
+ truncate_id_uniquely( 'a' x 99, 64 )
+
+Will give three different results; specifically:
+
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_7f900025
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_6191e39a
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_8cd96af2
+
=head2 $DEFAULT_COMMENT
This is the default comment string, '-- ' by default. Useful for
- type: NORMAL
fields:
- id
- name: index_2
+ name: really_long_name_bigger_than_64_chars_aaaaaaaaaaaaaaaaaaaaaaaaaaa
constraints:
- type: PRIMARY_KEY
fields:
"CREATE TABLE `thing` (
`id` unsigned int auto_increment,
`name` varchar(32),
- `swedish_name` varchar(32) CHARACTER SET swe7,
- `description` text CHARACTER SET utf8 COLLATE utf8_general_ci,
+ `swedish_name` varchar(32) character set swe7,
+ `description` text character set utf8 collate utf8_general_ci,
PRIMARY KEY (`id`),
UNIQUE `idx_unique_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;\n\n",
`foo` integer,
`foo2` integer,
INDEX index_1 (`id`),
- INDEX index_2 (`id`),
+ INDEX really_long_name_bigger_than_64_chars_aaaaaaaaaaaaaaaaa_aed44c47 (`id`),
INDEX (`foo`),
INDEX (`foo2`),
PRIMARY KEY (`id`, `foo`),