X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FTranslator%2FUtils.pm;h=980a6228312644658921ae767d1f22c242e8dde5;hb=ea93df61568d8fa52a9764a09c4351928ff9374d;hp=54f99fefa946312cafb14b38fd9d09de610a8552;hpb=c96037738918b18fc64a2e683f6bb177edc35e3c;p=dbsrgits%2FSQL-Translator.git diff --git a/lib/SQL/Translator/Utils.pm b/lib/SQL/Translator/Utils.pm index 54f99fe..980a622 100644 --- a/lib/SQL/Translator/Utils.pm +++ b/lib/SQL/Translator/Utils.pm @@ -1,9 +1,7 @@ package SQL::Translator::Utils; # ---------------------------------------------------------------------- -# $Id: Utils.pm,v 1.10 2003-10-09 16:35:55 kycl4rk Exp $ -# ---------------------------------------------------------------------- -# Copyright (C) 2003 darren chamberlain +# Copyright (C) 2002-2009 SQLFairy Authors # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -23,14 +21,16 @@ package SQL::Translator::Utils; use strict; 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.10 $ =~ /(\d+)\.(\d+)/; +$VERSION = '1.59'; $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 parse_mysql_version parse_dbms_version ); +use constant COLLISION_TAG_LENGTH => 8; # ---------------------------------------------------------------------- # debug(@msg) @@ -72,7 +72,7 @@ sub debug { # ---------------------------------------------------------------------- sub normalize_name { - my $name = shift || ''; + my $name = shift or return ''; # The name can only begin with a-zA-Z_; if there's anything # else, prefix with _ @@ -135,7 +135,7 @@ sub parse_list_arg { # This processes string-like arguments. # else { - return [ + return [ map { s/^\s+|\s+$//g; $_ } map { split /,/ } grep { defined && length } @$list @@ -143,6 +143,122 @@ sub parse_list_arg { } } +# ---------------------------------------------------------------------- +# 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. +# ---------------------------------------------------------------------- +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; +} + + +#--------------------------------------------------------------------- +# parse_mysql_version ( $version_string, $result_target) +# +# Attempts to parse an arbitrary string as a mysql version number. +# Returns either a floating point perl style string, or a mysql style +# 5 digit string, depending on the supplied $result_target +#--------------------------------------------------------------------- +sub parse_mysql_version { + my ($v, $target) = @_; + + return undef unless $v; + + $target ||= 'perl'; + + my @vers; + + # X.Y.Z style + if ( $v =~ / ^ (\d+) \. (\d{1,3}) (?: \. (\d{1,3}) )? $ /x ) { + push @vers, $1, $2, $3; + } + + # XYYZZ (mysql) style + elsif ( $v =~ / ^ (\d) (\d{2}) (\d{2}) $ /x ) { + push @vers, $1, $2, $3; + } + + # XX.YYYZZZ (perl) style or simply X + elsif ( $v =~ / ^ (\d+) (?: \. (\d{3}) (\d{3}) )? $ /x ) { + push @vers, $1, $2, $3; + } + else { + #how do I croak sanely here? + die "Unparseable MySQL version '$v'"; + } + + if ($target eq 'perl') { + return sprintf ('%d.%03d%03d', map { $_ || 0 } (@vers) ); + } + elsif ($target eq 'mysql') { + return sprintf ('%d%02d%02d', map { $_ || 0 } (@vers) ); + } + else { + #how do I croak sanely here? + die "Unknown version target '$target'"; + } +} + +#--------------------------------------------------------------------- +# parse_dbms_version ( $version_string, $target ) +# +# Attempts to parse either a native or perl-style version string into +# a version number format as specified by $target, which can be either +# 'perl' for a perl-style version number, or 'native' for an X.X.X +# style version number. +#--------------------------------------------------------------------- +sub parse_dbms_version { + my ($v, $target) = @_; + + return undef unless $v; + + my @vers; + + # X.Y.Z style + if ( $v =~ / ^ (\d+) \. (\d{1,3}) (?: \. (\d{1,3}) )? $ /x ) { + push @vers, $1, $2, $3; + } + + # XX.YYYZZZ (perl) style or simply X + elsif ( $v =~ / ^ (\d+) (?: \. (\d{3}) (\d{3}) )? $ /x ) { + push @vers, $1, $2, $3; + } + else { + #how do I croak sanely here? + die "Unparseable database server version '$v'"; + } + + if ($target eq 'perl') { + return sprintf ('%d.%03d%03d', map { $_ || 0 } (@vers) ); + } + elsif ($target eq 'native') { + return join '.' => grep defined, @vers; + } + else { + #how do I croak sanely here? + die "Unknown version target '$target'"; + } +} + 1; # ---------------------------------------------------------------------- @@ -250,16 +366,46 @@ All of the following will return equivalent values: 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 C. +=head2 parse_mysql_version + +Used by both L and +L in order to provide a +consistent format for both C<< parser_args->{mysql_parser_version} >> and +C<< producer_args->{mysql_version} >> respectively. Takes any of the following +version specifications: + + 5.0.3 + 4.1 + 3.23.2 + 5 + 5.001005 (perl style) + 30201 (mysql style) + =head1 AUTHORS Darren Chamberlain Edarren@cpan.orgE, Ken Y. Clark Ekclark@cpan.orgE. =cut - -=cut