Subject: | patch - add sqlt-graph/GraphViz global and item-specific display options |
Add GraphViz options to the sqlt-graph command (-g) and the
SQL::Translator::Producer::GraphViz module (graphviz_options). This
accepts all GraphViz display options, not just those that the producer
knows about. These can be applied globally, or to individual tables,
joins, or constraints (selected by name or regular expression).
See the SQL::Translator::Producer::GraphViz POD for details.
Change sqlt-graph --width and --height defaults to 8.5x11, to agree with
help text (defaults were 0).
Also, for completeness, allow 'circo' and 'fdp' layouts and 'debug'
output type. Small fixes to the sqlt-graph help.
(Linux 2.4.21-47.EL, perl 5.8.0, SQL-Translator-0.08_04)
Subject: | SQL-Translator-0.08-2.patch |
diff -ur SQL-Translator-0.08-orig/bin/sqlt-graph SQL-Translator-0.08/bin/sqlt-graph
--- SQL-Translator-0.08-orig/bin/sqlt-graph 2006-12-07 14:05:17.000000000 +0000
+++ SQL-Translator-0.08/bin/sqlt-graph 2007-01-08 19:13:31.000000000 +0000
@@ -31,16 +31,18 @@
Options:
-l|--layout Layout schema for GraphViz
- ("dot," "neato," "twopi"; default "dot")
- -n|--node-shape Shape of the nodes ("record," "plaintext,"
- "ellipse," "circle," "egg," "triangle," "box,"
- "diamond," "trapezium," "parallelogram," "house,"
- "hexagon," "octagon," default "record")
+ ("dot," "neato," "twopi", "circo", "fdp";
+ default "dot")
+ -n|--node-shape Shape of the nodes ("record", "plaintext",
+ "ellipse", "circle", "egg", "triangle", "box",
+ "diamond", "trapezium", "parallelogram", "house",
+ "hexagon", "octagon", default "record")
-o|--output Output file name (default STDOUT)
- -t|--output-type Output file type ("canon", "text," "ps," "hpgl,"
- "pcl," "mif," "pic," "gd," "gd2," "gif," "jpeg,"
- "png," "wbmp," "cmap," "ismap," "imap," "vrml,"
- "vtx," "mp," "fig," "svg," "plain," default "png")
+ -t|--output-type Output file type ("canon", "text", "ps", "hpgl",
+ "pcl", "mif", "pic", "gd", "gd2", "gif", "jpeg",
+ "png", "wbmp", "cmap", "ismap", "imap", "vrml",
+ "vtx", "mp", "fig", "svg", "plain", "debug",
+ default "png")
-c|--color Add colors
--no-fields Don't show field names
--height Image height (in inches, default "11",
@@ -53,6 +55,10 @@
--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
+ -g|--graphviz-options Detailed GraphViz options, separated with commas
+ or separate -g options. eg.
+ -g directed=0,edge=color=blue
+
--debug Print debugging information
=head1 DESCRIPTION
@@ -100,7 +106,7 @@
$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
+ $no_fields, @graphviz_options
);
GetOptions(
@@ -119,6 +125,7 @@
'show-datatypes' => \$show_datatypes,
'show-sizes' => \$show_sizes,
'show-constraints' => \$show_constraints,
+ 'g|graphviz-options:s'=> \@graphviz_options,
'debug' => \$debug,
'h|help' => \$help,
) or die pod2usage;
@@ -144,9 +151,10 @@
show_datatypes => $show_datatypes,
show_sizes => $show_sizes,
show_constraints => $show_constraints,
- height => $height || 0,
- width => $width || 0,
+ height => $height,
+ width => $width,
show_fields => $no_fields ? 0 : 1,
+ graphviz_options => [map split(/,/), @graphviz_options],
},
) or die SQL::Translator->error;
diff -ur SQL-Translator-0.08-orig/lib/SQL/Translator/Producer/GraphViz.pm SQL-Translator-0.08/lib/SQL/Translator/Producer/GraphViz.pm
--- SQL-Translator-0.08-orig/lib/SQL/Translator/Producer/GraphViz.pm 2006-12-07 14:05:17.000000000 +0000
+++ SQL-Translator-0.08/lib/SQL/Translator/Producer/GraphViz.pm 2007-01-08 19:10:17.000000000 +0000
@@ -62,8 +62,10 @@
determines which layout algorithm GraphViz will use; possible
values are 'dot' (the default GraphViz layout for directed graph
-layouts), 'neato' (for undirected graph layouts - spring model)
-or 'twopi' (for undirected graph layouts - circular)
+layouts), 'neato' (for undirected graph layouts - spring model),
+'twopi' (for undirected graph layouts - circular),
+'circo' (for undirected graph layouts - circular), or 'fdp'
+(for undirected graph layouts - force directed spring model)
=item * node_shape (DEFAULT: 'record')
@@ -77,7 +79,7 @@
sets the file type of the output graphic; possible values are
'ps', 'hpgl', 'pcl', 'mif', 'pic', 'gd', 'gd2', 'gif', 'jpeg',
'png', 'wbmp', 'cmap', 'ismap', 'imap', 'vrml', 'vtx', 'mp',
-'fig', 'svg', 'canon', 'plain' or 'text' (see GraphViz for
+'fig', 'svg', 'canon', 'plain', 'text', or 'debug' (see GraphViz for
details on each of these)
=item * width (DEFAULT: 8.5)
@@ -146,6 +148,54 @@
natural_join above) of SQL::Translator::Schema, if either
the natural_join or join_pk_only options has a true value
+=item * graphviz_options
+
+additional GraphViz formatting options array reference.
+Each option can be of the form:-
+
+=over 4
+
+=item OPTION=VALUE
+
+set option globally
+
+=item node=OPTION=VALUE
+
+=item edge=OPTION=VALUE
+
+=item graph=OPTION=VALUE
+
+set node, edge, or graph option
+
+=item table=TABLE=OPTION=VALUE
+
+=item join=TABLE1-TABLE2=OPTION=VALUE
+
+=item constraint=CONSTRAINT=OPTION=VALUE
+
+set option for a particular table, join, or constraint.
+TABLE specifies the table name, TABLE1-TABLE2 specifies a join
+(can be in either order), and CONSTRAINT specifies a constraint name
+(all ignoring case).
+Can also be given as (anchored) regular expressions to select
+multiple items.
+
+=back
+
+In all cases, =VALUE can be ommitted to set the option to 1.
+See the GraphViz module documentation for a full list of options.
+
+example:
+
+ producer_args => {
+ ...
+ graphviz_options => [qw(
+ directed=0
+ edge=color=blue
+ table=priority_table=style=bold
+ join=priority_table-.*=color=red
+ )]}
+
=back
=cut
@@ -164,6 +214,8 @@
dot => 1,
neato => 1,
twopi => 1,
+ circo => 1,
+ fdp => 1,
};
use constant VALID_NODE_SHAPE => {
@@ -183,6 +235,7 @@
};
use constant VALID_OUTPUT => {
+ debug => 1,
canon => 1,
text => 1,
ps => 1,
@@ -235,6 +288,26 @@
split ( /,/, $skip_fields );
$natural_join ||= $join_pk_only;
+ my %graphviz_options;
+ my %element_options= (node => {}, edge => {}, graph => {});
+ my %schema_options= (table => [], join => [], constraint => []);
+ foreach (@{$args->{'graphviz_options'}}) {
+ my ($key, $val);
+ ($key, $val)= /^([^=]*)=(.*)$/ or ($key, $val)= ($_, 1);
+ if ($schema_options{$key} && (my ($sel, $rest)= ($val =~ /^([^=]*)=(.*)$/))) {
+ $sel= qr/^$sel$/i;
+ my ($xkey, $xval);
+ ($xkey, $xval)= ($rest =~ /^([^=]*)=(.*)$/) or ($xkey, $xval)= ($rest, 1);
+ push (@{$schema_options{$key}}, {sel => $sel, key => $xkey, val => $xval});
+ } elsif ($element_options{$key}) {
+ my ($xkey, $xval);
+ ($xkey, $xval)= ($val =~ /^([^=]*)=(.*)$/) or ($xkey, $xval)= ($val, 1);
+ $element_options{$key}{$xkey}= $xval;
+ } else {
+ $graphviz_options{$key}= $val;
+ }
+ }
+
$schema->make_natural_joins(
join_pk_only => $join_pk_only,
skip_fields => $args->{'skip_fields'},
@@ -262,9 +335,13 @@
node => {
shape => $node_shape,
style => 'filled',
- fillcolor => 'white'
- }
+ fillcolor => 'white',
+ %{$element_options{'node'}}
+ },
+ %graphviz_options,
);
+ $args{'edge'} = $element_options{'edge'} if %{$element_options{'edge'}};
+ $args{'graph'} = $element_options{'graph'} if %{$element_options{'graph'}};
$args{'width'} = $width if $width;
$args{'height'} = $height if $height;
@@ -301,7 +378,14 @@
} @fields
) . '\l';
my $label = $show_fields ? "{$table_name|$field_str}" : $table_name;
- $gv->add_node( $table_name, label => $label );
+
+ my %opt;
+ if ($schema_options{'table'}) {
+ for my $table (@{$schema_options{'table'}}) {
+ $table_name =~ /$table->{'sel'}/ and $opt{$table->{'key'}}= $table->{'val'};
+ }
+ }
+ $gv->add_node( $table_name, label => $label, %opt );
debug("Processing table '$table_name'");
@@ -330,11 +414,17 @@
for my $c ( $table->get_constraints ) {
next unless $c->type eq FOREIGN_KEY;
my $fk_table = $c->reference_table or next;
+ my %opt;
+ if ($schema_options{'constraint'}) {
+ for my $constraint (@{$schema_options{'constraint'}}) {
+ $c->name =~ /$constraint->{'sel'}/ and $opt{$constraint->{'key'}}= $constraint->{'val'};
+ }
+ }
for my $field_name ( $c->fields ) {
for my $fk_field ( $c->reference_fields ) {
next unless defined $schema->get_table( $fk_table );
- push @fk_registry, [ $table_name, $fk_table ];
+ push @fk_registry, [ $table_name, $fk_table, (%opt ? (\%opt) : ())];
}
}
}
@@ -358,7 +448,9 @@
my %done;
for my $bunch ( @table_bunches ) {
- my @tables = @$bunch;
+ my @tables = @{$bunch};
+ my $opt;
+ $opt= pop @tables if ref $tables[-1];
for my $i ( 0 .. $#tables ) {
my $table1 = $tables[ $i ];
@@ -366,7 +458,16 @@
my $table2 = $tables[ $j ];
next if $table1 eq $table2;
next if $done{ $table1 }{ $table2 };
- $gv->add_edge( $table2, $table1 );
+ my %jopt;
+ %jopt= %$opt if $opt;
+ if ($schema_options{'join'}) {
+ for my $join (@{$schema_options{'join'}}) {
+ if (("$table1-$table2" =~ /$join->{'sel'}/) || ("$table2-$table1" =~ /$join->{'sel'}/)) {
+ $jopt{$join->{'key'}}= $join->{'val'};
+ }
+ }
+ }
+ $gv->add_edge( $table2, $table1, %jopt );
$done{ $table1 }{ $table2 } = 1;
$done{ $table2 }{ $table1 } = 1;
}