sqlt-diff option to quote names
[dbsrgits/SQL-Translator.git] / script / sqlt-diff
CommitLineData
969049ba 1#!/usr/bin/env perl
e12ca55a 2# vim: set ft=perl:
3
44659089 4# -------------------------------------------------------------------
5# Copyright (C) 2002-2009 The SQLFairy Authors
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
e12ca55a 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.
d4c5bb75 56 --quote=<character> Use <character> to quote all table and field
57 names in statements
e12ca55a 58
59=head1 DESCRIPTION
60
942485ea 61sqlt-diff is a utility for creating a file of SQL commands necessary to
aee4b66e 62transform the first schema provided to the second. While not yet
63exhaustive in its ability to mutate the entire schema, it will report the
942485ea 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
aee4b66e 76Any fields missing or altered between the two schemas will be reported
942485ea 77as:
78
aee4b66e 79 ALTER TABLE <table_name>
80 [DROP <field_name>]
942485ea 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:
aee4b66e 87
942485ea 88 DROP INDEX <index_name> ON <table_name> ;
89
aee4b66e 90An index of a different type or on different fields will be reported as a
942485ea 91new index as such:
92
aee4b66e 93 CREATE [<index_type>] INDEX [<index_name>] ON <table_name>
942485ea 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;
969049ba 108use warnings;
e12ca55a 109use Pod::Usage;
110use Data::Dumper;
111use SQL::Translator;
51ffe5ee 112use SQL::Translator::Diff;
942485ea 113use SQL::Translator::Schema::Constants;
e12ca55a 114
da06ac74 115use vars qw( $VERSION );
11ad2df9 116$VERSION = '1.59';
da06ac74 117
aee4b66e 118my ( @input, $list, $help, $debug, $trace, $caseopt, $ignore_index_names,
119 $ignore_constraint_names, $output_db, $mysql_parser_version,
d4c5bb75 120 $ignore_view_sql, $ignore_proc_sql, $no_batch_alters, $quote
121);
e12ca55a 122for my $arg ( @ARGV ) {
123 if ( $arg =~ m/^-?-l(ist)?$/ ) {
124 $list = 1;
125 }
126 elsif ( $arg =~ m/^-?-h(elp)?$/ ) {
127 $help = 1;
128 }
129 elsif ( $arg =~ m/^-?-d(ebug)?$/ ) {
aee4b66e 130 $debug = 1;
e12ca55a 131 }
51ffe5ee 132 elsif ( $arg =~ m/^-?-t(race)?$/ ) {
aee4b66e 133 $trace = 1;
51ffe5ee 134 }
d990d84b 135 elsif ( $arg =~ m/^-?-c(ase-insensitive)?$/ ) {
aee4b66e 136 $caseopt = 1;
51ffe5ee 137 }
d990d84b 138 elsif ( $arg =~ m/^--ignore-index-names$/ ) {
aee4b66e 139 $ignore_index_names = 1;
d990d84b 140 }
fb5ab406 141 elsif ( $arg =~ m/^--ignore-constraint-names$/ ) {
aee4b66e 142 $ignore_constraint_names = 1;
d990d84b 143 }
0b1b149e 144 elsif ( $arg =~ m/^--mysql-parser-version=(.+)$/ ) {
aee4b66e 145 $mysql_parser_version = $1;
0b1b149e 146 }
fb5ab406 147 elsif ( $arg =~ m/^--output-db=(.+)$/ ) {
aee4b66e 148 $output_db = $1;
fb5ab406 149 }
d1a895ce 150 elsif ( $arg =~ m/^--ignore-view-sql$/ ) {
aee4b66e 151 $ignore_view_sql = 1;
d1a895ce 152 }
153 elsif ( $arg =~ m/^--ignore-proc-sql$/ ) {
aee4b66e 154 $ignore_proc_sql = 1;
d1a895ce 155 }
d4c5bb75 156 elsif ( $arg =~ m/^--quote=(.)$/ ) {
157 $quote = $1;
158 }
e12ca55a 159 elsif ( $arg =~ m/^([^=]+)=(.+)$/ ) {
160 push @input, { file => $1, parser => $2 };
161 }
54b6e490 162 elsif ( $arg =~ m/^--no-batch-alters$/ ) {
d4c5bb75 163 $no_batch_alters = 1;
54b6e490 164 }
e12ca55a 165 else {
166 pod2usage( msg => "Unknown argument '$arg'" );
167 }
168}
169
d4c5bb75 170print STDERR <<'EOM' unless $ENV{SQLT_NEWDIFF_NOWARN};
aee4b66e 171This code is experimental, currently the new code only supports MySQL or
54b6e490 172SQLite diffing. To add support for other databases, please patch the relevant
173SQL::Translator::Producer:: module. If you need compatibility with the old
174sqlt-diff, please use sqlt-diff-old, and look into helping us make this one
175work for you
176EOM
da5a1bae 177
51ffe5ee 178pod2usage(1) if $help || !@ARGV;
942485ea 179pod2usage('Please specify only two schemas to diff') if scalar @input > 2;
e12ca55a 180
181my $tr = SQL::Translator->new;
182my @parsers = $tr->list_parsers;
183my %valid_parsers = map { $_, 1 } @parsers;
184
185if ( $list ) {
186 print "\nParsers:\n", map { "\t$_\n" } sort @parsers;
187 print "\n";
188 exit(0);
189}
190
191pod2usage( msg => 'Too many file args' ) if @input > 2;
192
51ffe5ee 193my ( $source_schema, $source_db, $target_schema, $target_db ) = map {
194 my $file = $_->{'file'};
195 my $parser = $_->{'parser'};
e12ca55a 196
197 die "Unable to read file '$file'\n" unless -r $file;
198 die "'$parser' is an invalid parser\n" unless $valid_parsers{ $parser };
199
d1a895ce 200 my $t = SQL::Translator->new(parser_args => {mysql_parser_version => $mysql_parser_version});
e12ca55a 201 $t->debug( $debug );
51ffe5ee 202 $t->trace( $trace );
e12ca55a 203 $t->parser( $parser ) or die $tr->error;
e12ca55a 204 my $out = $t->translate( $file ) or die $tr->error;
205 my $schema = $t->schema;
206 unless ( $schema->name ) {
207 $schema->name( $file );
208 }
209
51ffe5ee 210 ($schema, $parser);
211} @input;
212
aee4b66e 213my $result = SQL::Translator::Diff::schema_diff($source_schema, $source_db,
51ffe5ee 214 $target_schema, $target_db,
d990d84b 215 { caseopt => $caseopt,
216 ignore_index_names => $ignore_index_names,
217 ignore_constraint_names => $ignore_constraint_names,
d1a895ce 218 ignore_view_sql => $ignore_view_sql,
219 ignore_proc_sql => $ignore_proc_sql,
2d4796c7 220 output_db => $output_db,
54b6e490 221 no_batch_alters => $no_batch_alters,
d990d84b 222 debug => $debug,
d4c5bb75 223 trace => $trace,
224 producer_args => {
225 quote_table_names => $quote,
226 quote_field_names => $quote,
227 },
228 });
51ffe5ee 229if($result)
230{
231 print $result;
e12ca55a 232}
51ffe5ee 233else
234{
235 print "No differences found.";
e12ca55a 236}
237
238# -------------------------------------------------------------------
239# Bring out number weight & measure in a year of dearth.
240# William Blake
241# -------------------------------------------------------------------
242
243=pod
244
245=head1 AUTHOR
246
969049ba 247Ken Youens-Clark E<lt>kclark@cpan.orgE<gt>.
e12ca55a 248
249=head1 SEE ALSO
250
251SQL::Translator, L<http://sqlfairy.sourceforge.net>.
252
253=cut