e2cad9ef4e73b51884a314a461a59a02cbd3b860
[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 # -------------------------------------------------------------------
100
101 use strict;
102 use DBI;
103 use vars qw($VERSION @EXPORT);
104 $VERSION = '1.59';
105
106 use constant DRIVERS => {
107     mysql            => 'MySQL',
108     odbc             => 'SQLServer',
109     oracle           => 'Oracle',
110     pg               => 'PostgreSQL',
111     sqlite           => 'SQLite',
112     sybase           => 'Sybase',
113     pg               => 'PostgreSQL',
114     db2              => 'DB2',
115 };
116
117 use Exporter;
118
119 use SQL::Translator::Utils qw(debug);
120
121 use base qw(Exporter);
122 @EXPORT = qw(parse);
123
124 #
125 # Passed a SQL::Translator instance and a string containing the data
126 #
127 sub parse {
128     my ( $tr, $data ) = @_;
129
130     my $args          = $tr->parser_args;
131     my $dbh           = $args->{'dbh'};
132     my $dsn           = $args->{'dsn'};
133     my $db_user       = $args->{'db_user'};
134     my $db_password   = $args->{'db_password'};
135
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     }
147
148     die 'No database handle' unless defined $dbh;
149
150     my $db_type = $dbh->{'Driver'}{'Name'} or die 'Cannot determine DBI type';
151     my $driver  = DRIVERS->{ lc $db_type } or die "$db_type not supported";
152     my $pkg     = "SQL::Translator::Parser::DBI::$driver";
153     my $sub     = $pkg.'::parse';
154
155     SQL::Translator::load( $pkg );
156
157     eval {
158         no strict 'refs';
159         &{ $sub }( $tr, $dbh ) or die "No result from $pkg";
160     };
161
162     $dbh->disconnect if defined $dbh;
163
164     die $@ if $@;
165
166     return 1;
167 }
168
169 1;
170
171 # -------------------------------------------------------------------
172 =pod
173
174 =head1 AUTHOR
175
176 Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
177
178 =head1 SEE ALSO
179
180 DBI, SQL::Translator.
181
182 =cut