Some POD changes.
[dbsrgits/SQL-Translator.git] / bin / sqlt-dumper.pl
1 #!/usr/bin/perl
2
3 # -------------------------------------------------------------------
4 # $Id: sqlt-dumper.pl,v 1.3 2003-08-21 00:29:57 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
25 sqlt-dumper.pl - create a dumper script from a schema
26
27 =head1 SYNOPSIS
28
29   ./sqlt-dumper.pl -d Oracle [options] schema.sql > dumper.pl
30   ./dumper.pl > data.sql
31
32   Options:
33
34     -h|--help       Show help and exit
35     --add-truncate  Add "TRUNCATE TABLE" statements for each table
36     --skip=t1[,t2]  Skip tables in comma-separated list
37     -u|--user       Database username
38     -p|--password   Database password
39     --dsn           DSN for DBI
40
41 =head1 DESCRIPTION
42
43 This script uses SQL::Translator to parse the SQL schema and create a
44 Perl script that can connect to the database and dump the data as
45 INSERT statements a la mysqldump.  If you enable "add-truncate" or
46 specify tables to "skip," then the generated dumper script will have
47 those hardcoded.  However, these will also be options in the generated
48 dumper, so you can wait to specify these options when you dump your
49 database.  The database username, password, and DSN can be hardcoded
50 into the generated script, or part of the DSN can be intuited from the
51 "database" argument.
52
53 =cut
54
55 use strict;
56 use Pod::Usage;
57 use Getopt::Long;
58 use SQL::Translator;
59
60 my ( $help, $db, $add_truncate, $skip, $db_user, $db_pass, $dsn );
61 GetOptions(
62     'h|help'        => \$help,
63     'd|f|from|db=s' => \$db,
64     'add-truncate'  => \$add_truncate,
65     'skip:s'        => \$skip,
66     'u|user:s'      => \$db_user,
67     'p|password:s'  => \$db_pass,
68     'dsn:s'         => \$dsn,
69 ) or pod2usage;
70
71 pod2usage(0) if $help;
72 pod2usage( 'No database driver specified' ) unless $db;
73 $db_user ||= 'username';
74 $db_pass ||= 'password';
75 $dsn     ||= "dbi:$db:_";
76
77 my $file = shift @ARGV or pod2usage( -msg => 'No input file' );
78
79 my $t = SQL::Translator->new;
80 $t->parser( $db ) or die $t->error, "\n";
81 $t->filename( $file ) or die $t->error, "\n";
82
83 my %skip = map { $_, 1 } map { s/^\s+|\s+$//; $_ } split (/,/, $skip);
84 my $parser = $t->parser or die $t->error;
85 $parser->($t, $t->data);
86 my $schema = $t->schema;
87 my $now    = localtime;
88
89 my $out = <<"EOF";
90 #!/usr/bin/perl
91
92 #
93 # Generated $now
94 # By sqlt-dumper.pl, part of the SQLFairy project
95 # For more info, see http://sqlfairy.sourceforge.net/
96 #
97
98 use strict;
99 use DBI;
100 use Getopt::Long;
101
102 my ( \$help, \$add_truncate, \$skip );
103 GetOptions(
104     'h|help'        => \\\$help,
105     'add-truncate'  => \\\$add_truncate,
106     'skip:s'        => \\\$skip,
107 );
108
109 if ( \$help ) {
110     print <<"USAGE";
111 Usage:
112   \$0 [options]
113
114   Options:
115     -h|--help       Show help and exit
116     --add-truncate  Add "TRUNCATE TABLE" statements
117     --skip=t1[,t2]  Comma-separated list of tables to skip
118
119 USAGE
120     exit(0);
121 }
122
123 my \%skip = map { \$_, 1 } map { s/^\\s+|\\s+\$//; \$_ } split (/,/, \$skip);
124 my \$db = DBI->connect('$dsn', '$db_user', '$db_pass');
125
126 EOF
127
128 for my $table ( $schema->get_tables ) {
129     my $table_name  = $table->name;
130     next if $skip{ $table_name };
131     my ( @field_names, %types );
132     for my $field ( $table->get_fields ) {
133         $types{ $field->name } = $field->data_type =~ m/(char|str|long|text)/
134             ? 'string' : 'number';
135         push @field_names, $field->name;
136     }
137
138     $out .= join('',
139         "#\n# Table: $table_name\n#\n{\n",
140         "    next if \$skip{'$table_name'};\n",
141         "    print \"--\\n-- Data for table '$table_name'\\n--\\n\";\n\n",
142         "    if ( \$add_truncate ) {\n",
143         "        print \"TRUNCATE TABLE $table_name;\\n\";\n",
144         "    }\n\n",
145     );
146
147     my $insert = "INSERT INTO $table_name (". join(', ', @field_names).
148             ') VALUES (';
149
150     if ( $add_truncate ) {
151         $out .= "    print \"TRUNCATE TABLE $table_name;\\n\";\n";
152     }
153
154     $out .= join('',
155         "    my \%types = (\n",
156         join("\n", map { "        $_ => '$types{ $_ }'," } @field_names), 
157         "\n    );\n\n",
158         "    my \$data  = \$db->selectall_arrayref(\n",
159         "        'select ", join(', ', @field_names), " from $table_name',\n",
160         "        { Columns => {} },\n",
161         "    );\n\n",
162         "    for my \$rec ( \@{ \$data } ) {\n",
163         "        my \@vals;\n",
164         "        for my \$fld ( qw[", join(' ', @field_names), "] ) {\n",
165         "            my \$val = \$rec->{ \$fld };\n",
166         "            if ( \$types{ \$fld } eq 'string' ) {\n",
167         "                \$val =~ s/'/\\'/g;\n",
168         "                \$val = defined \$val ? qq['\$val'] : qq[''];\n",
169         "            }\n",
170         "            else {\n",
171         "                \$val = defined \$val ? \$val : 'NULL';\n",
172         "            }\n",
173         "            push \@vals, \$val;\n",
174         "        }\n",
175         "        print \"$insert\", join(', ', \@vals), \");\\n\";\n",
176         "    }\n",
177         "    print \"\\n\";\n",
178         "}\n\n",
179     );
180 }
181
182 print $out;