Added cursory parsing of views and procedures
[dbsrgits/SQL-Translator.git] / bin / sqlt-diff
CommitLineData
e12ca55a 1#!/usr/bin/perl -w
2# vim: set ft=perl:
3
4# -------------------------------------------------------------------
0b1b149e 5# $Id: sqlt-diff,v 1.17 2007-03-19 17:15:54 duality72 Exp $
e12ca55a 6# -------------------------------------------------------------------
daf4f623 7# Copyright (C) 2002-4 The SQLFairy Authors
e12ca55a 8#
9# This program is free software; you can redistribute it and/or
10# modify it under the terms of the GNU General Public License as
11# published by the Free Software Foundation; version 2.
12#
13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16# General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21# 02111-1307 USA
22# -------------------------------------------------------------------
23
24=head1 NAME
25
26sqlt-diff - find the differences b/w two schemas
27
28=head1 SYNOPSIS
29
30For help:
31
32 sqlt-diff -h|--help
33
34For a list of all valid parsers:
35
36 sqlt -l|--list
37
38To diff two schemas:
39
fb5ab406 40 sqlt-diff [options] file_name1=parser1 file_name2=parser2
e12ca55a 41
42Options:
43
44 -d|--debug Show debugging info
51ffe5ee 45 -t|--trace Turn on tracing for Parse::RecDescent
0b1b149e 46 -c|--case-insensitive Compare tables/columns case-insensitively
d990d84b 47 --ignore-index-names Ignore index name differences
48 --ignore-constraint-names Ignore constraint name differences
0b1b149e 49 --mysql_parser_version=<#####> Specify a target MySQL parser version
50 for dealing with /*! comments
51 --output-db=<Producer> This Producer will be used instead of one
52 corresponding to parser1 to format output
53 for new tables
e12ca55a 54
55=head1 DESCRIPTION
56
942485ea 57sqlt-diff is a utility for creating a file of SQL commands necessary to
58transform the first schema provided to the second. While not yet
59exhaustive in its ability to mutate the entire schema, it will report the
60following
61
62=over
63
64=item * New tables
65
66Using the Producer class of the target (second) schema, any tables missing
67in the first schema will be generated in their entirety (fields, constraints,
68indices).
69
70=item * Missing/altered fields
71
72Any fields missing or altered between the two schemas will be reported
73as:
74
75 ALTER TABLE <table_name>
76 [DROP <field_name>]
77 [CHANGE <field_name> <datatype> (<size>)] ;
78
79=item * Missing/altered indices
80
81Any indices missing or of a different type or on different fields will be
82indicated. Indices that should be dropped will be reported as such:
83
84 DROP INDEX <index_name> ON <table_name> ;
85
86An index of a different type or on different fields will be reported as a
87new index as such:
88
89 CREATE [<index_type>] INDEX [<index_name>] ON <table_name>
90 ( <field_name>[,<field_name>] ) ;
91
92=back
93
94"ALTER/DROP TABLE" and "CREATE INDEX" statements B<are not> generated by
95the Producer, unfortunately, and may require massaging before being passed to
96your target database.
e12ca55a 97
98=cut
99
100# -------------------------------------------------------------------
101
102use strict;
103use Pod::Usage;
104use Data::Dumper;
105use SQL::Translator;
51ffe5ee 106use SQL::Translator::Diff;
942485ea 107use SQL::Translator::Schema::Constants;
e12ca55a 108
109use vars qw( $VERSION );
0b1b149e 110$VERSION = sprintf "%d.%02d", q$Revision: 1.17 $ =~ /(\d+)\.(\d+)/;
e12ca55a 111
0b1b149e 112my ( @input, $list, $help, $debug, $trace, $caseopt,$ignore_index_names,
113 $ignore_constraint_names, $output_db, $mysql_parser_version );
e12ca55a 114for my $arg ( @ARGV ) {
115 if ( $arg =~ m/^-?-l(ist)?$/ ) {
116 $list = 1;
117 }
118 elsif ( $arg =~ m/^-?-h(elp)?$/ ) {
119 $help = 1;
120 }
121 elsif ( $arg =~ m/^-?-d(ebug)?$/ ) {
122 $debug = 1;
123 }
51ffe5ee 124 elsif ( $arg =~ m/^-?-t(race)?$/ ) {
125 $trace = 1;
126 }
d990d84b 127 elsif ( $arg =~ m/^-?-c(ase-insensitive)?$/ ) {
51ffe5ee 128 $caseopt = 1;
129 }
d990d84b 130 elsif ( $arg =~ m/^--ignore-index-names$/ ) {
131 $ignore_index_names = 1;
132 }
fb5ab406 133 elsif ( $arg =~ m/^--ignore-constraint-names$/ ) {
d990d84b 134 $ignore_constraint_names = 1;
135 }
0b1b149e 136 elsif ( $arg =~ m/^--mysql-parser-version=(.+)$/ ) {
137 $mysql_parser_version = $1;
138 }
fb5ab406 139 elsif ( $arg =~ m/^--output-db=(.+)$/ ) {
140 $output_db = $1;
141 }
e12ca55a 142 elsif ( $arg =~ m/^([^=]+)=(.+)$/ ) {
143 push @input, { file => $1, parser => $2 };
144 }
145 else {
146 pod2usage( msg => "Unknown argument '$arg'" );
147 }
148}
149
51ffe5ee 150pod2usage(1) if $help || !@ARGV;
942485ea 151pod2usage('Please specify only two schemas to diff') if scalar @input > 2;
e12ca55a 152
153my $tr = SQL::Translator->new;
154my @parsers = $tr->list_parsers;
155my %valid_parsers = map { $_, 1 } @parsers;
156
157if ( $list ) {
158 print "\nParsers:\n", map { "\t$_\n" } sort @parsers;
159 print "\n";
160 exit(0);
161}
162
163pod2usage( msg => 'Too many file args' ) if @input > 2;
164
51ffe5ee 165my ( $source_schema, $source_db, $target_schema, $target_db ) = map {
166 my $file = $_->{'file'};
167 my $parser = $_->{'parser'};
e12ca55a 168
169 die "Unable to read file '$file'\n" unless -r $file;
170 die "'$parser' is an invalid parser\n" unless $valid_parsers{ $parser };
171
0b1b149e 172 my $t = SQL::Translator->new(parser_args => {mysql_parser_version => $mysql_parser_version || 0});
e12ca55a 173 $t->debug( $debug );
51ffe5ee 174 $t->trace( $trace );
e12ca55a 175 $t->parser( $parser ) or die $tr->error;
e12ca55a 176 my $out = $t->translate( $file ) or die $tr->error;
177 my $schema = $t->schema;
178 unless ( $schema->name ) {
179 $schema->name( $file );
180 }
181
51ffe5ee 182 ($schema, $parser);
183} @input;
184
185my $result = SQL::Translator::Diff::schema_diff($source_schema, $source_db,
186 $target_schema, $target_db,
d990d84b 187 { caseopt => $caseopt,
188 ignore_index_names => $ignore_index_names,
189 ignore_constraint_names => $ignore_constraint_names,
2d4796c7 190 output_db => $output_db,
d990d84b 191 debug => $debug,
192 trace => $trace });
51ffe5ee 193if($result)
194{
195 print $result;
e12ca55a 196}
51ffe5ee 197else
198{
199 print "No differences found.";
e12ca55a 200}
201
202# -------------------------------------------------------------------
203# Bring out number weight & measure in a year of dearth.
204# William Blake
205# -------------------------------------------------------------------
206
207=pod
208
209=head1 AUTHOR
210
211Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
212
213=head1 SEE ALSO
214
215SQL::Translator, L<http://sqlfairy.sourceforge.net>.
216
217=cut