POD update for m:n stuff.
[dbsrgits/SQL-Translator.git] / bin / sqlt-dumper
CommitLineData
354b1807 1#!/usr/bin/perl
2
3# -------------------------------------------------------------------
4# $Id: sqlt-dumper,v 1.1 2003-08-26 03:56:43 kycl4rk Exp $
5# -------------------------------------------------------------------
6# Copyright (C) 2003 Ken Y. Clark <kclark@cpan.org>
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License as
10# published by the Free Software Foundation; version 2.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15# General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20# 02111-1307 USA
21# -------------------------------------------------------------------
22
23=head1 NAME
24
25sqlt-dumper - create a dumper script from a schema
26
27=head1 SYNOPSIS
28
29 sqlt-dumper -d Oracle [options] schema.sql > dumper.pl
30
31 ./dumper.pl > data.sql
32
33 Options:
34
35 -h|--help Show help and exit
36 --add-truncate Add "TRUNCATE TABLE" statements for each table
37 --skip=t1[,t2] Skip tables in comma-separated list
38 -u|--user Database username
39 -p|--password Database password
40 --dsn DSN for DBI
41
42=head1 DESCRIPTION
43
44This script uses SQL::Translator to parse the SQL schema and create a
45Perl script that can connect to the database and dump the data as
46INSERT statements a la mysqldump. If you enable "add-truncate" or
47specify tables to "skip," then the generated dumper script will have
48those hardcoded. However, these will also be options in the generated
49dumper, so you can wait to specify these options when you dump your
50database. The database username, password, and DSN can be hardcoded
51into the generated script, or part of the DSN can be intuited from the
52"database" argument.
53
54=cut
55
56# -------------------------------------------------------------------
57
58use strict;
59use Pod::Usage;
60use Getopt::Long;
61use SQL::Translator;
62
63use vars '$VERSION';
64$VERSION = sprintf "%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/;
65
66my ( $help, $db, $add_truncate, $skip, $db_user, $db_pass, $dsn );
67GetOptions(
68 'h|help' => \$help,
69 'd|f|from|db=s' => \$db,
70 'add-truncate' => \$add_truncate,
71 'skip:s' => \$skip,
72 'u|user:s' => \$db_user,
73 'p|password:s' => \$db_pass,
74 'dsn:s' => \$dsn,
75) or pod2usage;
76
77pod2usage(0) if $help;
78pod2usage( 'No database driver specified' ) unless $db;
79$db_user ||= 'username';
80$db_pass ||= 'password';
81$dsn ||= "dbi:$db:_";
82
83my $file = shift @ARGV or pod2usage( -msg => 'No input file' );
84
85my $t = SQL::Translator->new;
86$t->parser( $db ) or die $t->error, "\n";
87$t->filename( $file ) or die $t->error, "\n";
88
89my %skip = map { $_, 1 } map { s/^\s+|\s+$//; $_ } split (/,/, $skip);
90my $parser = $t->parser or die $t->error;
91$parser->($t, $t->data);
92my $schema = $t->schema;
93my $now = localtime;
94
95my $out = <<"EOF";
96#!/usr/bin/perl
97
98#
99# Generated $now
100# By sqlt-dumper.pl, part of the SQLFairy project
101# For more info, see http://sqlfairy.sourceforge.net/
102#
103
104use strict;
105use DBI;
106use Getopt::Long;
107
108my ( \$help, \$add_truncate, \$skip );
109GetOptions(
110 'h|help' => \\\$help,
111 'add-truncate' => \\\$add_truncate,
112 'skip:s' => \\\$skip,
113);
114
115if ( \$help ) {
116 print <<"USAGE";
117Usage:
118 \$0 [options]
119
120 Options:
121 -h|--help Show help and exit
122 --add-truncate Add "TRUNCATE TABLE" statements
123 --skip=t1[,t2] Comma-separated list of tables to skip
124
125USAGE
126 exit(0);
127}
128
129my \%skip = map { \$_, 1 } map { s/^\\s+|\\s+\$//; \$_ } split (/,/, \$skip);
130my \$db = DBI->connect('$dsn', '$db_user', '$db_pass');
131
132EOF
133
134for my $table ( $schema->get_tables ) {
135 my $table_name = $table->name;
136 next if $skip{ $table_name };
137 my ( @field_names, %types );
138 for my $field ( $table->get_fields ) {
139 $types{ $field->name } = $field->data_type =~ m/(char|str|long|text)/
140 ? 'string' : 'number';
141 push @field_names, $field->name;
142 }
143
144 $out .= join('',
145 "#\n# Table: $table_name\n#\n{\n",
146 " next if \$skip{'$table_name'};\n",
147 " print \"--\\n-- Data for table '$table_name'\\n--\\n\";\n\n",
148 " if ( \$add_truncate ) {\n",
149 " print \"TRUNCATE TABLE $table_name;\\n\";\n",
150 " }\n\n",
151 );
152
153 my $insert = "INSERT INTO $table_name (". join(', ', @field_names).
154 ') VALUES (';
155
156 if ( $add_truncate ) {
157 $out .= " print \"TRUNCATE TABLE $table_name;\\n\";\n";
158 }
159
160 $out .= join('',
161 " my \%types = (\n",
162 join("\n", map { " $_ => '$types{ $_ }'," } @field_names),
163 "\n );\n\n",
164 " my \$data = \$db->selectall_arrayref(\n",
165 " 'select ", join(', ', @field_names), " from $table_name',\n",
166 " { Columns => {} },\n",
167 " );\n\n",
168 " for my \$rec ( \@{ \$data } ) {\n",
169 " my \@vals;\n",
170 " for my \$fld ( qw[", join(' ', @field_names), "] ) {\n",
171 " my \$val = \$rec->{ \$fld };\n",
172 " if ( \$types{ \$fld } eq 'string' ) {\n",
173 " \$val =~ s/'/\\'/g;\n",
174 " \$val = defined \$val ? qq['\$val'] : qq[''];\n",
175 " }\n",
176 " else {\n",
177 " \$val = defined \$val ? \$val : 'NULL';\n",
178 " }\n",
179 " push \@vals, \$val;\n",
180 " }\n",
181 " print \"$insert\", join(', ', \@vals), \");\\n\";\n",
182 " }\n",
183 " print \"\\n\";\n",
184 "}\n\n",
185 );
186}
187
188print $out;
189exit(0);
190
191# -------------------------------------------------------------------
192
193=pod
194
195=head1 AUTHOR
196
197Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
198
199=head1 SEE ALSO
200
201perl, SQL::Translator.
202
203=cut