Improve trigger 'scope' attribute support (RT#119997)
[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     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     my $dbh_is_local;
137     unless ( $dbh ) {
138         die 'No DSN' unless $dsn;
139         $dbh = DBI->connect( $dsn, $db_user, $db_password,
140             {
141                 FetchHashKeyName => 'NAME_lc',
142                 LongReadLen      => 3000,
143                 LongTruncOk      => 1,
144                 RaiseError       => 1,
145             }
146         );
147         $dbh_is_local = 1;
148     }
149
150     die 'No database handle' unless defined $dbh;
151
152     my $db_type = $dbh->{'Driver'}{'Name'} or die 'Cannot determine DBI type';
153     my $driver  = DRIVERS->{ lc $db_type } or die "$db_type not supported";
154     my $pkg     = "SQL::Translator::Parser::DBI::$driver";
155     my $sub     = $pkg.'::parse';
156
157     SQL::Translator::load( $pkg );
158
159     my $s = eval {
160         no strict 'refs';
161         &{ $sub }( $tr, $dbh ) or die "No result from $pkg";
162     };
163     my $err = $@;
164
165     eval { $dbh->disconnect } if (defined $dbh and $dbh_is_local);
166
167     die $err if $err;
168
169     return $s;
170 }
171
172 1;
173
174 =pod
175
176 =head1 AUTHOR
177
178 Ken Y. Clark E<lt>kclark@cpan.orgE<gt>.
179
180 =head1 SEE ALSO
181
182 DBI, SQL::Translator.
183
184 =cut