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