Per a suggestion from Darren, changed the skipping of tables in the GraphViz
[dbsrgits/SQL-Translator.git] / bin / sqlt-graph
1 #!/usr/bin/perl
2
3 # -------------------------------------------------------------------
4 # Copyright (C) 2002-2009 SQLFairy Authors
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; version 2.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 # 02111-1307  USA
19 # -------------------------------------------------------------------
20
21 =head1 NAME 
22
23 sqlt-graph - Automatically create a graph from a database schema
24
25 =head1 SYNOPSIS
26
27   ./sqlt-graph -d|--db|-f|--from=db_parser [options] schema.sql
28
29   Options:
30
31     -l|--layout        Layout schema for GraphViz
32                        ("dot," "neato," "twopi"; default "dot")
33     -n|--node-shape    Shape of the nodes ("record," "plaintext," 
34                        "ellipse," "circle," "egg," "triangle," "box," 
35                        "diamond," "trapezium," "parallelogram," "house," 
36                        "hexagon," "octagon," default "record")
37     -o|--output        Output file name (default STDOUT)
38     -t|--output-type   Output file type ("canon", "text," "ps," "hpgl,"
39                        "pcl," "mif," "pic," "gd," "gd2," "gif," "jpeg,"
40                        "png," "wbmp," "cmap," "ismap," "imap," "vrml,"
41                        "vtx," "mp," "fig," "svg," "plain," default "png")
42     -c|--color         Add colors
43     --no-fields        Don't show field names
44     --height           Image height (in inches, default "11",
45                        set to "0" to undefine)
46     --width            Image width (in inches, default "8.5", 
47                        set to "0" to undefine)
48     --fontsize         custom font size for node and edge labels
49     --fontname         name of custom font (or full path to font file) for 
50                        node, edge, and graph labels
51     --nodeattr         attribute name and value (in key=val syntax) for
52                        nodes; this option may be repeated to specify 
53                        multiple node attributes
54     --edgeattr         same as --nodeattr, but for edge attributes
55     --graphattr        same as --nodeattr, but for graph attributes
56     --natural-join     Perform natural joins
57     --natural-join-pk  Perform natural joins from primary keys only
58     --show-datatypes   Show datatype of each field
59     --show-sizes       Show column sizes for VARCHAR and CHAR fields
60     --show-constraints Show list of constraints for each field
61     -s|--skip          Fields to skip in natural joins
62     --skip-tables      Comma-separated list of table names to exclude 
63     --skip-tables-like Comma-separated list of regexen to exclude tables
64     --debug            Print debugging information
65
66 =head1 DESCRIPTION
67
68 This script will create a graph of your schema.  Only the database
69 driver argument (for SQL::Translator) is required.  If no output file
70 name is given, then image will be printed to STDOUT, so you should
71 redirect the output into a file.
72
73 The default action is to assume the presence of foreign key
74 relationships defined via "REFERNCES" or "FOREIGN KEY" constraints on
75 the tables.  If you are parsing the schema of a file that does not
76 have these, you will find the natural join options helpful.  With
77 natural joins, like-named fields will be considered foreign keys.
78 This can prove too permissive, however, as you probably don't want a
79 field called "name" to be considered a foreign key, so you could
80 include it in the "skip" option, and all fields called "name" will be
81 excluded from natural joins.  A more efficient method, however, might
82 be to simply deduce the foriegn keys from primary keys to other fields
83 named the same in other tables.  Use the "natural-join-pk" option
84 to acheive this.
85
86 If the schema defines foreign keys, then the graph produced will be
87 directed showing the direction of the relationship.  If the foreign
88 keys are intuited via natural joins, the graph will be undirected.
89
90 =cut
91
92 # -------------------------------------------------------------------
93
94 use strict;
95 use Data::Dumper;
96 use Getopt::Long;
97 use GraphViz;
98 use Pod::Usage;
99 use SQL::Translator;
100
101 use vars '$VERSION';
102 $VERSION = '1.59';
103
104 #
105 # Get arguments.
106 #
107 my ( 
108     $layout, $node_shape, $out_file, $output_type, $db_driver, $add_color, 
109     $natural_join, $join_pk_only, $skip_fields, $show_datatypes,
110     $show_sizes, $show_constraints, $debug, $help, $height, $width,
111     $no_fields, $fontsize, $fontname, $skip_tables, $skip_tables_like
112 );
113
114 # multi-valued options:
115 my %edgeattrs = ();
116 my %nodeattrs = ();
117 my %graphattrs = ();
118
119 GetOptions(
120     'd|db|f|from  =s'    => \$db_driver,
121     'o|output:s'         => \$out_file,
122     'l|layout:s'         => \$layout,
123     'n|node-shape:s'     => \$node_shape,
124     't|output-type:s'    => \$output_type,
125     'height:f'           => \$height,
126     'width:f'            => \$width,
127     'fontsize  =i'       => \$fontsize,
128     'fontname  =s'       => \$fontname,
129     'nodeattr  =s'       => \%nodeattrs,
130     'edgeattr  =s'       => \%edgeattrs,
131     'graphattr  =s'      => \%graphattrs,
132     'c|color'            => \$add_color,
133     'no-fields'          => \$no_fields,
134     'natural-join'       => \$natural_join,
135     'natural-join-pk'    => \$join_pk_only,
136     's|skip:s'           => \$skip_fields,
137     'skip-tables:s'      => \$skip_tables,
138     'skip-tables-like:s' => \$skip_tables_like,
139     'show-datatypes'     => \$show_datatypes,
140     'show-sizes'         => \$show_sizes,
141     'show-constraints'   => \$show_constraints,
142     'debug'              => \$debug,
143     'h|help'             => \$help,
144 ) or die pod2usage;
145 my @files = @ARGV; # the create script(s) for the original db
146
147 pod2usage(1) if $help;
148 pod2usage( -message => "No db driver specified" ) unless $db_driver;
149 pod2usage( -message => 'No input file'          ) unless @files;
150
151 my $translator           =  SQL::Translator->new( 
152     from                 => $db_driver,
153     to                   => 'GraphViz',
154     debug                => $debug || 0,
155     producer_args        => {
156         out_file         => $out_file,
157         layout           => $layout,
158         node_shape       => $node_shape,
159         output_type      => $output_type,
160         add_color        => $add_color,
161         natural_join     => $natural_join,
162         natural_join_pk  => $join_pk_only,
163         skip_fields      => $skip_fields,
164         skip_tables      => $skip_tables,
165         skip_tables_like => $skip_tables_like,
166         show_datatypes   => $show_datatypes,
167         show_sizes       => $show_sizes,
168         show_constraints => $show_constraints,
169         height           => $height || 0,
170         width            => $width  || 0,
171         fontsize         => $fontsize,
172         fontname         => $fontname,
173         nodeattrs        => \%nodeattrs,
174         edgeattrs        => \%edgeattrs,
175         graphattrs       => \%graphattrs,
176         show_fields      => $no_fields ? 0 : 1,
177     },
178 ) or die SQL::Translator->error;
179
180 for my $file (@files) {
181     my $output = $translator->translate( $file ) or die
182                  "Error: " . $translator->error;
183     if ( $out_file ) {
184         print "Image written to '$out_file'.  Done.\n";
185     }
186     else {
187         print $output;
188     }
189 }
190
191 # -------------------------------------------------------------------
192
193 =pod
194
195 =head1 AUTHOR
196
197 Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
198
199 =head1 SEE ALSO
200
201 perl, SQL::Translator.
202
203 =cut