Actually there was an empty test for it as well :)
[dbsrgits/SQL-Translator.git] / bin / sqlt-diff
CommitLineData
e12ca55a 1#!/usr/bin/perl -w
2# vim: set ft=perl:
3
4# -------------------------------------------------------------------
d4f84dd1 5# $Id: sqlt-diff 1440 2009-01-17 16:31:57Z jawnsy $
e12ca55a 6# -------------------------------------------------------------------
478f608d 7# Copyright (C) 2002-2009 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
d1a895ce 54 --ignore-view-sql Ignore view SQL differences
55 --ignore-proc-sql Ignore procedure SQL differences
54b6e490 56 --no-batch-alters Do not clump multile alters to the same table into a
57 single ALTER TABLE statement where possible.
e12ca55a 58
59=head1 DESCRIPTION
60
942485ea 61sqlt-diff is a utility for creating a file of SQL commands necessary to
62transform the first schema provided to the second. While not yet
63exhaustive in its ability to mutate the entire schema, it will report the
64following
65
66=over
67
68=item * New tables
69
70Using the Producer class of the target (second) schema, any tables missing
71in the first schema will be generated in their entirety (fields, constraints,
72indices).
73
74=item * Missing/altered fields
75
76Any fields missing or altered between the two schemas will be reported
77as:
78
79 ALTER TABLE <table_name>
80 [DROP <field_name>]
81 [CHANGE <field_name> <datatype> (<size>)] ;
82
83=item * Missing/altered indices
84
85Any indices missing or of a different type or on different fields will be
86indicated. Indices that should be dropped will be reported as such:
87
88 DROP INDEX <index_name> ON <table_name> ;
89
90An index of a different type or on different fields will be reported as a
91new index as such:
92
93 CREATE [<index_type>] INDEX [<index_name>] ON <table_name>
94 ( <field_name>[,<field_name>] ) ;
95
96=back
97
da5a1bae 98ALTER, CREATE, DROP statements are created by
99SQL::Translator::Producer::*, see there for support/problems.
100
101Currently (v0.0900), only MySQL is supported by this code.
e12ca55a 102
103=cut
104
105# -------------------------------------------------------------------
106
107use strict;
108use Pod::Usage;
109use Data::Dumper;
110use SQL::Translator;
51ffe5ee 111use SQL::Translator::Diff;
942485ea 112use SQL::Translator::Schema::Constants;
e12ca55a 113
d1a895ce 114my ( @input, $list, $help, $debug, $trace, $caseopt, $ignore_index_names,
115 $ignore_constraint_names, $output_db, $mysql_parser_version,
54b6e490 116 $ignore_view_sql, $ignore_proc_sql, $no_batch_alters );
e12ca55a 117for my $arg ( @ARGV ) {
118 if ( $arg =~ m/^-?-l(ist)?$/ ) {
119 $list = 1;
120 }
121 elsif ( $arg =~ m/^-?-h(elp)?$/ ) {
122 $help = 1;
123 }
124 elsif ( $arg =~ m/^-?-d(ebug)?$/ ) {
125 $debug = 1;
126 }
51ffe5ee 127 elsif ( $arg =~ m/^-?-t(race)?$/ ) {
128 $trace = 1;
129 }
d990d84b 130 elsif ( $arg =~ m/^-?-c(ase-insensitive)?$/ ) {
51ffe5ee 131 $caseopt = 1;
132 }
d990d84b 133 elsif ( $arg =~ m/^--ignore-index-names$/ ) {
134 $ignore_index_names = 1;
135 }
fb5ab406 136 elsif ( $arg =~ m/^--ignore-constraint-names$/ ) {
d990d84b 137 $ignore_constraint_names = 1;
138 }
0b1b149e 139 elsif ( $arg =~ m/^--mysql-parser-version=(.+)$/ ) {
140 $mysql_parser_version = $1;
141 }
fb5ab406 142 elsif ( $arg =~ m/^--output-db=(.+)$/ ) {
143 $output_db = $1;
144 }
d1a895ce 145 elsif ( $arg =~ m/^--ignore-view-sql$/ ) {
146 $ignore_view_sql = 1;
147 }
148 elsif ( $arg =~ m/^--ignore-proc-sql$/ ) {
149 $ignore_proc_sql = 1;
150 }
e12ca55a 151 elsif ( $arg =~ m/^([^=]+)=(.+)$/ ) {
152 push @input, { file => $1, parser => $2 };
153 }
54b6e490 154 elsif ( $arg =~ m/^--no-batch-alters$/ ) {
155 $no_batch_alters = 1;
156 }
e12ca55a 157 else {
158 pod2usage( msg => "Unknown argument '$arg'" );
159 }
160}
161
54b6e490 162print STDERR <<'EOM';
163This code is experimental, currently the new code only supports MySQL or
164SQLite diffing. To add support for other databases, please patch the relevant
165SQL::Translator::Producer:: module. If you need compatibility with the old
166sqlt-diff, please use sqlt-diff-old, and look into helping us make this one
167work for you
168EOM
da5a1bae 169
51ffe5ee 170pod2usage(1) if $help || !@ARGV;
942485ea 171pod2usage('Please specify only two schemas to diff') if scalar @input > 2;
e12ca55a 172
173my $tr = SQL::Translator->new;
174my @parsers = $tr->list_parsers;
175my %valid_parsers = map { $_, 1 } @parsers;
176
177if ( $list ) {
178 print "\nParsers:\n", map { "\t$_\n" } sort @parsers;
179 print "\n";
180 exit(0);
181}
182
183pod2usage( msg => 'Too many file args' ) if @input > 2;
184
51ffe5ee 185my ( $source_schema, $source_db, $target_schema, $target_db ) = map {
186 my $file = $_->{'file'};
187 my $parser = $_->{'parser'};
e12ca55a 188
189 die "Unable to read file '$file'\n" unless -r $file;
190 die "'$parser' is an invalid parser\n" unless $valid_parsers{ $parser };
191
d1a895ce 192 my $t = SQL::Translator->new(parser_args => {mysql_parser_version => $mysql_parser_version});
e12ca55a 193 $t->debug( $debug );
51ffe5ee 194 $t->trace( $trace );
e12ca55a 195 $t->parser( $parser ) or die $tr->error;
e12ca55a 196 my $out = $t->translate( $file ) or die $tr->error;
197 my $schema = $t->schema;
198 unless ( $schema->name ) {
199 $schema->name( $file );
200 }
201
51ffe5ee 202 ($schema, $parser);
203} @input;
204
205my $result = SQL::Translator::Diff::schema_diff($source_schema, $source_db,
206 $target_schema, $target_db,
d990d84b 207 { caseopt => $caseopt,
208 ignore_index_names => $ignore_index_names,
209 ignore_constraint_names => $ignore_constraint_names,
d1a895ce 210 ignore_view_sql => $ignore_view_sql,
211 ignore_proc_sql => $ignore_proc_sql,
2d4796c7 212 output_db => $output_db,
54b6e490 213 no_batch_alters => $no_batch_alters,
d990d84b 214 debug => $debug,
215 trace => $trace });
51ffe5ee 216if($result)
217{
218 print $result;
e12ca55a 219}
51ffe5ee 220else
221{
222 print "No differences found.";
e12ca55a 223}
224
225# -------------------------------------------------------------------
226# Bring out number weight & measure in a year of dearth.
227# William Blake
228# -------------------------------------------------------------------
229
230=pod
231
232=head1 AUTHOR
233
234Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
235
236=head1 SEE ALSO
237
238SQL::Translator, L<http://sqlfairy.sourceforge.net>.
239
240=cut