1d0219d1e07e7009a408b19e205718cab8261041
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Parser / DBI.pm
1 package SQL::Translator::Parser::DBI;
2
3 # -------------------------------------------------------------------
4 # Copyright (C) 2002-2009 SQLFairy Authors
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; version 2.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 # 02111-1307  USA
19 # -------------------------------------------------------------------
20
21 =head1 NAME
22
23 SQL::Translator::Parser::DBI - "parser" for DBI handles
24
25 =head1 SYNOPSIS
26
27   use DBI;
28   use SQL::Translator;
29
30   my $dbh = DBI->connect('dsn', 'user', 'pass', 
31       {
32           RaiseError       => 1,
33           FetchHashKeyName => 'NAME_lc',
34       }
35   );
36
37   my $translator  =  SQL::Translator->new(
38       parser      => 'DBI',
39       dbh         => $dbh,
40   );
41
42 Or:
43
44   use SQL::Translator;
45
46   my $translator      =  SQL::Translator->new(
47       parser          => 'DBI',
48       parser_args     => {
49           dsn         => 'dbi:mysql:FOO',
50           db_user     => 'guest',
51           db_password => 'password',
52     }
53   );
54
55 =head1 DESCRIPTION
56
57 This parser accepts an open database handle (or the arguments to create 
58 one) and queries the database directly for the information.  
59
60 The following are acceptable arguments:
61
62 =over 4
63
64 =item * dbh
65
66 An open DBI database handle.  NB:  Be sure to create the database with the 
67 "FetchHashKeyName => 'NAME_lc'" option as all the DBI parsers expect 
68 lowercased column names.
69
70 =item * dsn
71
72 The DSN to use for connecting to a database.
73
74 =item * db_user
75
76 The user name to use for connecting to a database.
77
78 =item * db_password
79
80 The password to use for connecting to a database.
81
82 =back
83
84 There is no need to specify which type of database you are querying as
85 this is determined automatically by inspecting $dbh->{'Driver'}{'Name'}.
86 If a parser exists for your database, it will be used automatically;
87 if not, the code will fail automatically (and you can write the parser
88 and contribute it to the project!).  
89
90 Currently parsers exist for the following databases:
91
92 =over 4
93
94 =item * MySQL
95
96 =item * SQLite
97
98 =item * Sybase
99
100 =item * PostgreSQL (still experimental)
101
102 =back
103
104 Most of these parsers are able to query the database directly for the
105 structure rather than parsing a text file.  For large schemas, this is
106 probably orders of magnitude faster than traditional parsing (which
107 uses Parse::RecDescent, an amazing module but really quite slow).
108
109 Though no Oracle parser currently exists, it would be fairly easy to
110 query an Oracle database directly by using DDL::Oracle to generate a
111 DDL for the schema and then using the normal Oracle parser on this.
112 Perhaps future versions of SQL::Translator will include the ability to
113 query Oracle directly and skip the parsing of a text file, too.
114
115 =cut
116
117 # -------------------------------------------------------------------
118
119 use strict;
120 use DBI;
121 use vars qw($VERSION @EXPORT);
122 $VERSION = '1.59';
123
124 use constant DRIVERS => {
125     mysql            => 'MySQL',
126     odbc             => 'SQLServer',
127     oracle           => 'Oracle',
128     pg               => 'PostgreSQL',
129     sqlite           => 'SQLite',
130     sybase           => 'Sybase',
131     pg               => 'PostgreSQL',
132     db2              => 'DB2',
133 };
134
135 use Exporter;
136
137 use SQL::Translator::Utils qw(debug);
138
139 use base qw(Exporter);
140 @EXPORT = qw(parse);
141
142 #
143 # Passed a SQL::Translator instance and a string containing the data
144 #
145 sub parse {
146     my ( $tr, $data ) = @_;
147
148     my $args          = $tr->parser_args;
149     my $dbh           = $args->{'dbh'};
150     my $dsn           = $args->{'dsn'};
151     my $db_user       = $args->{'db_user'};
152     my $db_password   = $args->{'db_password'};
153
154     unless ( $dbh ) {
155         die 'No DSN' unless $dsn;
156         $dbh = DBI->connect( $dsn, $db_user, $db_password, 
157             {
158                 FetchHashKeyName => 'NAME_lc',
159                 LongReadLen      => 3000,
160                 LongTruncOk      => 1,
161                 RaiseError       => 1,
162             } 
163         );
164     }
165
166     die 'No database handle' unless defined $dbh;
167
168     my $db_type = $dbh->{'Driver'}{'Name'} or die 'Cannot determine DBI type';
169     my $driver  = DRIVERS->{ lc $db_type } or die "$db_type not supported";
170     my $pkg     = "SQL::Translator::Parser::DBI::$driver";
171     my $sub     = $pkg.'::parse';
172
173     SQL::Translator::load( $pkg );
174
175     eval {
176         no strict 'refs';
177         &{ $sub }( $tr, $dbh ) or die "No result from $pkg";
178     };
179
180     $dbh->disconnect if defined $dbh;
181
182     die $@ if $@;
183
184     return 1;
185 }
186
187 1;
188
189 # -------------------------------------------------------------------
190 =pod
191
192 =head1 AUTHOR
193
194 Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
195
196 =head1 SEE ALSO
197
198 DBI, SQL::Translator.
199
200 =cut