Added PG support, more POD.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Parser / DBI.pm
1 package SQL::Translator::Parser::DBI;
2
3 # -------------------------------------------------------------------
4 # $Id: DBI.pm,v 1.4 2003-10-10 15:52:07 kycl4rk Exp $
5 # -------------------------------------------------------------------
6 # Copyright (C) 2003 Ken Y. Clark <kclark@cpan.org>,
7 #                    darren chamberlain <darren@cpan.org>
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
26 SQL::Translator::Parser::DBI - "parser" for DBI handles
27
28 =head1 SYNOPSIS
29
30   use DBI;
31   use SQL::Translator;
32
33   my $dbh = DBI->connect(...);
34
35   my $translator  =  SQL::Translator->new(
36       parser      => 'DBI',
37       dbh         => $dbh,
38   );
39
40 Or:
41
42   use SQL::Translator;
43
44   my $translator  =  SQL::Translator->new(
45       parser      => 'DBI',
46       dsn         => 'dbi:mysql:FOO',
47       db_user     => 'guest',
48       db_password => 'password',
49   );
50
51 =head1 DESCRIPTION
52
53 This parser accepts an open database handle (or the arguments to create 
54 one) and queries the database directly for the information.  
55
56 The following are acceptable arguments:
57
58 =over 4
59
60 =item * dbh
61
62 An open DBI database handle.
63
64 =item * dsn
65
66 The DSN to use for connecting to a database.
67
68 =item * db_user
69
70 The user name to use for connecting to a database.
71
72 =item * db_password
73
74 The password to use for connecting to a database.
75
76 =back
77
78 There is no need to specify which type of database you are querying as
79 this is determined automatically by inspecting $dbh->{'Driver'}{'Name'}.
80 If a parser exists for your database, it will be used automatically;
81 if not, the code will fail automatically (and you can write the parser
82 and contribute it to the project!).  
83
84 Currently parsers exist for the following databases:
85
86 =over 4
87
88 =item * MySQL
89
90 =item * SQLite
91
92 =item * Sybase
93
94 =item * PostgreSQL (still experimental)
95
96 =back
97
98 Most of these parsers are able to query the database directly for the
99 structure rather than parsing a text file.  For large schemas, this is
100 probably orders of magnitude faster than traditional parsing (which
101 uses Parse::RecDescent, an amazing module but really quite slow).
102
103 Though no Oracle parser currently exists, it would be fairly easy to
104 query an Oracle database directly by using DDL::Oracle to generate a
105 DDL for the schema and then using the normal Oracle parser on this.
106 Perhaps future versions of SQL::Translator will include the ability to
107 query Oracle directly and skip the parsing of a text file, too.
108
109 =cut
110
111 # -------------------------------------------------------------------
112
113 use strict;
114 use DBI;
115 use vars qw($VERSION @EXPORT);
116 $VERSION = sprintf "%d.%02d", q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/;
117
118 use constant DRIVERS => {
119     mysql            => 'MySQL',
120     sqlite           => 'SQLite',
121     sybase           => 'Sybase',
122     pg               => 'PostgreSQL',
123 };
124
125 use Exporter;
126
127 use SQL::Translator::Utils qw(debug);
128
129 use SQL::Translator::Parser::DBI::MySQL;
130 use SQL::Translator::Parser::DBI::SQLite;
131 use SQL::Translator::Parser::DBI::Sybase;
132 use SQL::Translator::Parser::DBI::PostgreSQL;
133
134 use base qw(Exporter);
135 @EXPORT = qw(parse);
136
137 #
138 # Passed a SQL::Translator instance and a string containing the data
139 #
140 sub parse {
141     my ( $tr, $data ) = @_;
142
143     my $args          = $tr->parser_args;
144     my $dbh           = $args->{'dbh'};
145     my $dsn           = $args->{'dsn'};
146     my $db_user       = $args->{'db_user'};
147     my $db_password   = $args->{'db_password'};
148
149     unless ( $dbh ) {
150         die 'No DSN' unless $dsn;
151         $dbh = DBI->connect( $dsn, $db_user, $db_password, 
152             {
153                 FetchHashKeyName => 'NAME_lc',
154                 LongReadLen      => 3000,
155                 LongTruncOk      => 1,
156                 RaiseError       => 1,
157             } 
158         );
159     }
160
161     die 'No database handle' unless defined $dbh;
162
163     my $db_type = $dbh->{'Driver'}{'Name'} or die 'Cannot determine DBI type';
164     my $driver  = DRIVERS->{ lc $db_type } or die "$db_type not supported";
165     my $pkg     = "SQL::Translator::Parser::DBI::$driver";
166     my $sub     = $pkg.'::parse';
167
168     #
169     # I can't get this to work.  I seem to have to have the "use"
170     # statements above.
171     #
172 #    $tr->load( $pkg );
173
174     eval {
175         no strict 'refs';
176         &{ $sub }( $tr, $dbh ) or die "No result from $pkg";
177     };
178
179     $dbh->disconnect if defined $dbh;
180
181     die $@ if $@;
182
183     return 1;
184 }
185
186 1;
187
188 # -------------------------------------------------------------------
189 =pod
190
191 =head1 AUTHOR
192
193 Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
194
195 =head1 SEE ALSO
196
197 DBI, SQL::Translator.
198
199 =cut