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