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