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