Added tests to catch Oracle problem with parser being reused
[dbsrgits/SQL-Translator.git] / bin / sqlt-diff
CommitLineData
e12ca55a 1#!/usr/bin/perl -w
2# vim: set ft=perl:
3
4# -------------------------------------------------------------------
51ffe5ee 5# $Id: sqlt-diff,v 1.13 2006-05-20 09:02:47 schiffbruechige 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
21f5bf40 40 sqlt-diff [options] file_name1=parser file_name2=parser
e12ca55a 41
42Options:
43
44 -d|--debug Show debugging info
51ffe5ee 45 -t|--trace Turn on tracing for Parse::RecDescent
46 -c|--case-insensitive Compare tables/columns case-insenstiviely
e12ca55a 47
48=head1 DESCRIPTION
49
942485ea 50sqlt-diff is a utility for creating a file of SQL commands necessary to
51transform the first schema provided to the second. While not yet
52exhaustive in its ability to mutate the entire schema, it will report the
53following
54
55=over
56
57=item * New tables
58
59Using the Producer class of the target (second) schema, any tables missing
60in the first schema will be generated in their entirety (fields, constraints,
61indices).
62
63=item * Missing/altered fields
64
65Any fields missing or altered between the two schemas will be reported
66as:
67
68 ALTER TABLE <table_name>
69 [DROP <field_name>]
70 [CHANGE <field_name> <datatype> (<size>)] ;
71
72=item * Missing/altered indices
73
74Any indices missing or of a different type or on different fields will be
75indicated. Indices that should be dropped will be reported as such:
76
77 DROP INDEX <index_name> ON <table_name> ;
78
79An index of a different type or on different fields will be reported as a
80new index as such:
81
82 CREATE [<index_type>] INDEX [<index_name>] ON <table_name>
83 ( <field_name>[,<field_name>] ) ;
84
85=back
86
87"ALTER/DROP TABLE" and "CREATE INDEX" statements B<are not> generated by
88the Producer, unfortunately, and may require massaging before being passed to
89your target database.
e12ca55a 90
91=cut
92
93# -------------------------------------------------------------------
94
95use strict;
96use Pod::Usage;
97use Data::Dumper;
98use SQL::Translator;
51ffe5ee 99use SQL::Translator::Diff;
942485ea 100use SQL::Translator::Schema::Constants;
e12ca55a 101
102use vars qw( $VERSION );
51ffe5ee 103$VERSION = sprintf "%d.%02d", q$Revision: 1.13 $ =~ /(\d+)\.(\d+)/;
e12ca55a 104
51ffe5ee 105my ( @input, $list, $help, $debug, $trace, $caseopt );
e12ca55a 106for my $arg ( @ARGV ) {
107 if ( $arg =~ m/^-?-l(ist)?$/ ) {
108 $list = 1;
109 }
110 elsif ( $arg =~ m/^-?-h(elp)?$/ ) {
111 $help = 1;
112 }
113 elsif ( $arg =~ m/^-?-d(ebug)?$/ ) {
114 $debug = 1;
115 }
51ffe5ee 116 elsif ( $arg =~ m/^-?-t(race)?$/ ) {
117 $trace = 1;
118 }
119 elsif ( $arg =~ m/^-?-c(ase-insenstive)?$/ ) {
120 $caseopt = 1;
121 }
e12ca55a 122 elsif ( $arg =~ m/^([^=]+)=(.+)$/ ) {
123 push @input, { file => $1, parser => $2 };
124 }
125 else {
126 pod2usage( msg => "Unknown argument '$arg'" );
127 }
128}
129
51ffe5ee 130pod2usage(1) if $help || !@ARGV;
942485ea 131pod2usage('Please specify only two schemas to diff') if scalar @input > 2;
e12ca55a 132
133my $tr = SQL::Translator->new;
134my @parsers = $tr->list_parsers;
135my %valid_parsers = map { $_, 1 } @parsers;
136
137if ( $list ) {
138 print "\nParsers:\n", map { "\t$_\n" } sort @parsers;
139 print "\n";
140 exit(0);
141}
142
143pod2usage( msg => 'Too many file args' ) if @input > 2;
144
51ffe5ee 145my ( $source_schema, $source_db, $target_schema, $target_db ) = map {
146 my $file = $_->{'file'};
147 my $parser = $_->{'parser'};
e12ca55a 148
149 die "Unable to read file '$file'\n" unless -r $file;
150 die "'$parser' is an invalid parser\n" unless $valid_parsers{ $parser };
151
152 my $t = SQL::Translator->new;
153 $t->debug( $debug );
51ffe5ee 154 $t->trace( $trace );
e12ca55a 155 $t->parser( $parser ) or die $tr->error;
e12ca55a 156 my $out = $t->translate( $file ) or die $tr->error;
157 my $schema = $t->schema;
158 unless ( $schema->name ) {
159 $schema->name( $file );
160 }
161
51ffe5ee 162 ($schema, $parser);
163} @input;
164
165my $result = SQL::Translator::Diff::schema_diff($source_schema, $source_db,
166 $target_schema, $target_db,
167 { caseopt => $caseopt,
168 debug => $debug,
169 trace => $trace });
170if($result)
171{
172 print $result;
e12ca55a 173}
51ffe5ee 174else
175{
176 print "No differences found.";
e12ca55a 177}
178
179# -------------------------------------------------------------------
180# Bring out number weight & measure in a year of dearth.
181# William Blake
182# -------------------------------------------------------------------
183
184=pod
185
186=head1 AUTHOR
187
188Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
189
190=head1 SEE ALSO
191
192SQL::Translator, L<http://sqlfairy.sourceforge.net>.
193
194=cut