From: Ken Youens-Clark Date: Fri, 3 Apr 2009 20:07:45 +0000 (+0000) Subject: Per a suggestion from Darren, changed the skipping of tables in the GraphViz X-Git-Tag: v0.11008~217 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=818e0d98d233abdff53c6dad531ceafb4351675f;p=dbsrgits%2FSQL-Translator.git Per a suggestion from Darren, changed the skipping of tables in the GraphViz producer to either skip on table names or regular expressions: For example, if there are tables named foo, bar, and baz, with join tables foo_bar and foo_baz, and you only want to skip foo but not foo_bar and foo_baz, you would need to use the regex foo$, but this contradicts the "table name" part of the docs. --- diff --git a/bin/sqlt-graph b/bin/sqlt-graph index f20c71c..61c8ec4 100755 --- a/bin/sqlt-graph +++ b/bin/sqlt-graph @@ -59,7 +59,8 @@ sqlt-graph - Automatically create a graph from a database schema --show-sizes Show column sizes for VARCHAR and CHAR fields --show-constraints Show list of constraints for each field -s|--skip Fields to skip in natural joins - --skip-tables Comma-separated list of regexen to exclude tables + --skip-tables Comma-separated list of table names to exclude + --skip-tables-like Comma-separated list of regexen to exclude tables --debug Print debugging information =head1 DESCRIPTION @@ -107,7 +108,7 @@ my ( $layout, $node_shape, $out_file, $output_type, $db_driver, $add_color, $natural_join, $join_pk_only, $skip_fields, $show_datatypes, $show_sizes, $show_constraints, $debug, $help, $height, $width, - $no_fields, $fontsize, $fontname, $skip_tables + $no_fields, $fontsize, $fontname, $skip_tables, $skip_tables_like ); # multi-valued options: @@ -116,29 +117,30 @@ my %nodeattrs = (); my %graphattrs = (); GetOptions( - 'd|db|f|from=s' => \$db_driver, - 'o|output:s' => \$out_file, - 'l|layout:s' => \$layout, - 'n|node-shape:s' => \$node_shape, - 't|output-type:s' => \$output_type, - 'height:f' => \$height, - 'width:f' => \$width, - 'fontsize=i' => \$fontsize, - 'fontname=s' => \$fontname, - 'nodeattr=s' => \%nodeattrs, - 'edgeattr=s' => \%edgeattrs, - 'graphattr=s' => \%graphattrs, - 'c|color' => \$add_color, - 'no-fields' => \$no_fields, - 'natural-join' => \$natural_join, - 'natural-join-pk' => \$join_pk_only, - 's|skip:s' => \$skip_fields, - 'skip-tables:s' => \$skip_tables, - 'show-datatypes' => \$show_datatypes, - 'show-sizes' => \$show_sizes, - 'show-constraints' => \$show_constraints, - 'debug' => \$debug, - 'h|help' => \$help, + 'd|db|f|from =s' => \$db_driver, + 'o|output:s' => \$out_file, + 'l|layout:s' => \$layout, + 'n|node-shape:s' => \$node_shape, + 't|output-type:s' => \$output_type, + 'height:f' => \$height, + 'width:f' => \$width, + 'fontsize =i' => \$fontsize, + 'fontname =s' => \$fontname, + 'nodeattr =s' => \%nodeattrs, + 'edgeattr =s' => \%edgeattrs, + 'graphattr =s' => \%graphattrs, + 'c|color' => \$add_color, + 'no-fields' => \$no_fields, + 'natural-join' => \$natural_join, + 'natural-join-pk' => \$join_pk_only, + 's|skip:s' => \$skip_fields, + 'skip-tables:s' => \$skip_tables, + 'skip-tables-like:s' => \$skip_tables_like, + 'show-datatypes' => \$show_datatypes, + 'show-sizes' => \$show_sizes, + 'show-constraints' => \$show_constraints, + 'debug' => \$debug, + 'h|help' => \$help, ) or die pod2usage; my @files = @ARGV; # the create script(s) for the original db @@ -160,6 +162,7 @@ my $translator = SQL::Translator->new( natural_join_pk => $join_pk_only, skip_fields => $skip_fields, skip_tables => $skip_tables, + skip_tables_like => $skip_tables_like, show_datatypes => $show_datatypes, show_sizes => $show_sizes, show_constraints => $show_constraints, diff --git a/lib/SQL/Translator/Producer/GraphViz.pm b/lib/SQL/Translator/Producer/GraphViz.pm index e76b987..fe6b251 100644 --- a/lib/SQL/Translator/Producer/GraphViz.pm +++ b/lib/SQL/Translator/Producer/GraphViz.pm @@ -173,8 +173,12 @@ the natural_join or join_pk_only options has a true value =item * skip_tables -Determines the tables that will be skipped. Can be a list of -tables or a regular expression. +A comma-separated list of table names that should be skipped. + +=item * skip_tables_like + +A comma-separated list of regular expressions describing table names +that should be skipped. =item * show_indexes @@ -268,13 +272,15 @@ sub produce { my $show_datatypes = $args->{'show_datatypes'}; my $show_sizes = $args->{'show_sizes'}; my $show_indexes = $args->{'show_indexes'}; - my $show_index_names = defined $args->{'show_index_names'} ? $args->{'show_index_names'} : 1; + my $show_index_names = defined $args->{'show_index_names'} + ? $args->{'show_index_names'} : 1; my $friendly_ints = $args->{'friendly_ints'}; my $friendly_ints_ex = $args->{'friendly_ints_extended'}; my $show_constraints = $args->{'show_constraints'}; my $join_pk_only = $args->{'join_pk_only'}; - my $skip_fields = $args->{'skip_fields'} || ''; - my $skip_tables = $args->{'skip_tables'} || ''; + my $skip_fields = $args->{'skip_fields'} || ''; + my $skip_tables = $args->{'skip_tables'} || ''; + my $skip_tables_like = $args->{'skip_tables_like'} || ''; my %skip = map { s/^\s+|\s+$//g; length $_ ? ($_, 1) : () } split ( /,/, $skip_fields ); $natural_join ||= $join_pk_only; @@ -346,7 +352,8 @@ sub produce { eval { $gv->$output_method }; die "Invalid output type: '$output_type'" if $@; - my %skip_table = map { $_, 1 } split /\s*,\s*/, $skip_tables; + my %skip_table = map { $_, 1 } split /\s*,\s*/, $skip_tables; + my @skip_tables_like = map { qr/$_/ } split /\s*,\s*/, $skip_tables_like; my %nj_registry; # for locations of fields for natural joins my @fk_registry; # for locations of fields for foreign keys @@ -357,8 +364,8 @@ sub produce { if ( %skip_table ) { next TABLE if $skip_table{ $tname }; - for my $t ( keys %skip_table ) { - next TABLE if $tname =~ /$t/; + for my $regex ( @skip_tables_like ) { + next TABLE if $tname =~ $regex; } } @@ -368,104 +375,102 @@ sub produce { } my $field_str = ''; - if ($show_fields) { - - my @fmt_fields; - foreach my $field (@fields) { - - my $field_type; - if ($show_datatypes) { - - $field_type = $field->data_type; - - # For the integer type, transform into different types based on - # requested size, if a size is given. - if ($field->size and $friendly_ints and (lc $field_type) eq 'integer') { - # Automatically translate to int2, int4, int8 - # Type (Bits) Max. Signed/Unsigned Length - # tinyint* (8) 128 3 - # 255 3 - # smallint (16) 32767 5 - # 65535 5 - # mediumint* (24) 8388607 7 - # 16777215 8 - # int (32) 2147483647 10 - # 4294967295 11 - # bigint (64) 9223372036854775807 19 - # 18446744073709551615 20 - # - # * tinyint and mediumint are nonstandard extensions which are - # only available under MySQL (to my knowledge) - my $size = $field->size; - if ($size <= 3 and $friendly_ints_ex) { - $field_type = 'tinyint', - } - elsif ($size <= 5) { - $field_type = 'smallint'; - } - elsif ($size <= 8 and $friendly_ints_ex) { - $field_type = 'mediumint'; - } - elsif ($size <= 11) { - $field_type = 'integer'; - } - else { - $field_type = 'bigint'; + if ( $show_fields ) { + my @fmt_fields; + for my $field ( @fields ) { + my $field_type; + if ($show_datatypes) { + $field_type = $field->data_type; + + # For the integer type, transform into different + # types based on requested size, if a size is given. + if ( $field->size + and $friendly_ints + and ( lc $field_type ) eq 'integer' + ) { + # Automatically translate to int2, int4, int8 + # Type (Bits) Max. Signed/Unsigned Length + # tinyint* (8) 128 3 + # 255 3 + # smallint (16) 32767 5 + # 65535 5 + # mediumint* (24) 8388607 7 + # 16777215 8 + # int (32) 2147483647 10 + # 4294967295 11 + # bigint (64) 9223372036854775807 19 + # 18446744073709551615 20 + # + # * tinyint and mediumint are nonstandard extensions + # which are only available under MySQL (to my knowledge) + my $size = $field->size; + if ( $size <= 3 and $friendly_ints_ex ) { + $field_type = 'tinyint',; + } + elsif ( $size <= 5 ) { + $field_type = 'smallint'; + } + elsif ( $size <= 8 and $friendly_ints_ex ) { + $field_type = 'mediumint'; + } + elsif ( $size <= 11 ) { + $field_type = 'integer'; + } + else { + $field_type = 'bigint'; + } + } + + if ( + $show_sizes + and $field->size + and ( $field_type =~ /^(var)?char2?$/ + or $field_type eq 'numeric' + or $field_type eq 'decimal' ) + ) { + $field_type .= '(' . $field->size . ')'; + } } - } - - if ( - $show_sizes - and - $field->size - and - ($field_type =~ /^(var)?char2?$/ or $field_type eq 'numeric' or $field_type eq 'decimal') - ) { - $field_type .= '(' . $field->size . ')'; - } - } - my $constraints; - if ($show_constraints) { - my @constraints; - push(@constraints, 'PK') if $field->is_primary_key; - push(@constraints, 'FK') if $field->is_foreign_key; - push(@constraints, 'U') if $field->is_unique; + my $constraints; + if ( $show_constraints ) { + my @constraints; - $constraints = join (',', @constraints); - } + push( @constraints, 'PK' ) if $field->is_primary_key; + push( @constraints, 'FK' ) if $field->is_foreign_key; + push( @constraints, 'U' ) if $field->is_unique; - # construct the field line from all info gathered so far - push @fmt_fields, join (' ', - '-', - $field->name, - $field_type || (), - $constraints ? "[$constraints]" : (), - ); + $constraints = join( ',', @constraints ); + } - } + # construct the field line from all info gathered so far + push @fmt_fields, join( ' ', + '-', $field->name, + $field_type || (), + $constraints ? "[$constraints]" : (), + ); + } - # join field lines with graphviz formatting - $field_str = join ('\l', @fmt_fields) . '\l'; + # join field lines with graphviz formatting + $field_str = join( '\l', @fmt_fields ) . '\l'; } my $index_str = ''; if ($show_indexes) { + my @fmt_indexes; + for my $index ( $table->get_indices ) { + next unless $index->is_valid; + + push @fmt_indexes, join( ' ', + '*', + $show_index_names ? $index->name . ':' : (), + join( ', ', $index->fields ), + ( $index->type eq 'UNIQUE' ) ? '[U]' : (), + ); + } - my @fmt_indexes; - foreach my $index ($table->get_indices) { - next unless $index->is_valid; - - push @fmt_indexes, join (' ', - '*', - $show_index_names ? $index->name . ':' : (), - join (', ', $index->fields), - ($index->type eq 'UNIQUE') ? '[U]' : (), - ); - } - - # join index lines with graphviz formatting (if any indexes at all) - $index_str = join ('\l', @fmt_indexes) . '\l' if @fmt_indexes; + # join index lines with graphviz formatting (if any indexes at all) + $index_str = join( '\l', @fmt_indexes ) . '\l' if @fmt_indexes; } my $table_name = $table->name; @@ -473,23 +478,18 @@ sub produce { # escape spaces for ($name_str, $field_str, $index_str) { - $_ =~ s/ /\\ /g; + $_ =~ s/ /\\ /g; } # only the 'record' type supports nice formatting - if ($node_shape eq 'record') { - - # the necessity to supply shape => 'record' is a graphviz bug + if ( $node_shape eq 'record' ) { + # the necessity to supply shape => 'record' is a graphviz bug $gv->add_node( $table_name, - shape => 'record', - label => sprintf ('{%s}', - join ('|', - $name_str, - $field_str || (), - $index_str || (), + shape => 'record', + label => sprintf( '{%s}', + join( '|', $name_str, $field_str || (), $index_str || (), ), ), - ), ); } else { @@ -506,7 +506,6 @@ sub produce { ); } - debug("Processing table '$table_name'"); debug("Fields = ", join(', ', map { $_->name } @fields)); @@ -581,18 +580,18 @@ sub produce { # Print the image. # if ( $out_file ) { - if (openhandle ($out_file)) { - print $out_file $gv->$output_method; - } - else { - open my $fh, ">$out_file" or die "Can't write '$out_file': $!\n"; - binmode $fh; - print $fh $gv->$output_method; - close $fh; - } + if ( openhandle( $out_file ) ) { + print $out_file $gv->$output_method; + } + else { + open my $fh, ">$out_file" or die "Can't write '$out_file': $!\n"; + binmode $fh; + print $fh $gv->$output_method; + close $fh; + } } else { - return $gv->$output_method; + return $gv->$output_method; } } @@ -604,14 +603,11 @@ sub produce { =head1 AUTHOR -Ken Y. Clark Ekclark@cpan.orgE - -=head2 CONTRIBUTORS - +Ken Youens-Clark Ekclark@cpan.orgE, Jonathan Yu Efrequency@cpan.orgE =head1 SEE ALSO -SQL::Translator, GraphViz +SQL::Translator, GraphViz. =cut