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