Remove unnecessary passing of $self->dbh as a separate param to savepoint methods
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI.pm
CommitLineData
8b445e33 1package DBIx::Class::Storage::DBI;
e673f011 2# -*- mode: cperl; cperl-indent-level: 2 -*-
8b445e33 3
a62cf8d4 4use base 'DBIx::Class::Storage';
5
eda28767 6use strict;
20a2c954 7use warnings;
8b445e33 8use DBI;
aeaf3ce2 9use SQL::Abstract::Limit;
28927b50 10use DBIx::Class::Storage::DBI::Cursor;
4c248161 11use DBIx::Class::Storage::Statistics;
664612fb 12use Scalar::Util qw/blessed weaken/;
046ad905 13
541df64a 14__PACKAGE__->mk_group_accessors('simple' =>
15 qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts
e4eb8ee1 16 _conn_pid _conn_tid disable_sth_caching on_connect_do
579ca3f7 17 on_disconnect_do transaction_depth unsafe _dbh_autocommit/
046ad905 18);
19
e4eb8ee1 20__PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor');
21
95ba7ee4 22__PACKAGE__->mk_group_accessors('inherited' => qw/sql_maker_class/);
23__PACKAGE__->sql_maker_class('DBIC::SQL::Abstract');
24
bd7efd39 25BEGIN {
26
cb5f2eea 27package DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :(
bd7efd39 28
29use base qw/SQL::Abstract::Limit/;
30
2cc3a7be 31# This prevents the caching of $dbh in S::A::L, I believe
32sub new {
33 my $self = shift->SUPER::new(@_);
34
35 # If limit_dialect is a ref (like a $dbh), go ahead and replace
36 # it with what it resolves to:
37 $self->{limit_dialect} = $self->_find_syntax($self->{limit_dialect})
38 if ref $self->{limit_dialect};
39
40 $self;
41}
42
260129d8 43sub _RowNumberOver {
44 my ($self, $sql, $order, $rows, $offset ) = @_;
45
46 $offset += 1;
47 my $last = $rows + $offset;
48 my ( $order_by ) = $self->_order_by( $order );
49
50 $sql = <<"";
51SELECT * FROM
52(
53 SELECT Q1.*, ROW_NUMBER() OVER( ) AS ROW_NUM FROM (
54 $sql
55 $order_by
56 ) Q1
57) Q2
58WHERE ROW_NUM BETWEEN $offset AND $last
59
60 return $sql;
61}
62
63
2cc3a7be 64# While we're at it, this should make LIMIT queries more efficient,
65# without digging into things too deeply
758272ec 66use Scalar::Util 'blessed';
2cc3a7be 67sub _find_syntax {
68 my ($self, $syntax) = @_;
758272ec 69 my $dbhname = blessed($syntax) ? $syntax->{Driver}{Name} : $syntax;
260129d8 70 if(ref($self) && $dbhname && $dbhname eq 'DB2') {
71 return 'RowNumberOver';
72 }
73
2cc3a7be 74 $self->{_cached_syntax} ||= $self->SUPER::_find_syntax($syntax);
75}
76
54540863 77sub select {
78 my ($self, $table, $fields, $where, $order, @rest) = @_;
6346a152 79 $table = $self->_quote($table) unless ref($table);
eac29141 80 local $self->{rownum_hack_count} = 1
81 if (defined $rest[0] && $self->{limit_dialect} eq 'RowNum');
54540863 82 @rest = (-1) unless defined $rest[0];
0823196c 83 die "LIMIT 0 Does Not Compute" if $rest[0] == 0;
84 # and anyway, SQL::Abstract::Limit will cause a barf if we don't first
8839560b 85 local $self->{having_bind} = [];
bc0c9800 86 my ($sql, @ret) = $self->SUPER::select(
87 $table, $self->_recurse_fields($fields), $where, $order, @rest
88 );
95ba7ee4 89 $sql .=
90 $self->{for} ?
91 (
92 $self->{for} eq 'update' ? ' FOR UPDATE' :
93 $self->{for} eq 'shared' ? ' FOR SHARE' :
94 ''
95 ) :
96 ''
97 ;
8839560b 98 return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql;
54540863 99}
100
6346a152 101sub insert {
102 my $self = shift;
103 my $table = shift;
104 $table = $self->_quote($table) unless ref($table);
105 $self->SUPER::insert($table, @_);
106}
107
108sub update {
109 my $self = shift;
110 my $table = shift;
111 $table = $self->_quote($table) unless ref($table);
112 $self->SUPER::update($table, @_);
113}
114
115sub delete {
116 my $self = shift;
117 my $table = shift;
118 $table = $self->_quote($table) unless ref($table);
119 $self->SUPER::delete($table, @_);
120}
121
54540863 122sub _emulate_limit {
123 my $self = shift;
124 if ($_[3] == -1) {
125 return $_[1].$self->_order_by($_[2]);
126 } else {
127 return $self->SUPER::_emulate_limit(@_);
128 }
129}
130
131sub _recurse_fields {
e8e971f2 132 my ($self, $fields, $params) = @_;
54540863 133 my $ref = ref $fields;
134 return $self->_quote($fields) unless $ref;
135 return $$fields if $ref eq 'SCALAR';
136
137 if ($ref eq 'ARRAY') {
1d78a406 138 return join(', ', map {
eac29141 139 $self->_recurse_fields($_)
1d78a406 140 .(exists $self->{rownum_hack_count} && !($params && $params->{no_rownum_hack})
141 ? ' AS col'.$self->{rownum_hack_count}++
142 : '')
e8e971f2 143 } @$fields);
54540863 144 } elsif ($ref eq 'HASH') {
145 foreach my $func (keys %$fields) {
146 return $self->_sqlcase($func)
147 .'( '.$self->_recurse_fields($fields->{$func}).' )';
148 }
149 }
150}
151
152sub _order_by {
153 my $self = shift;
154 my $ret = '';
8839560b 155 my @extra;
54540863 156 if (ref $_[0] eq 'HASH') {
157 if (defined $_[0]->{group_by}) {
158 $ret = $self->_sqlcase(' group by ')
1d78a406 159 .$self->_recurse_fields($_[0]->{group_by}, { no_rownum_hack => 1 });
54540863 160 }
8839560b 161 if (defined $_[0]->{having}) {
162 my $frag;
163 ($frag, @extra) = $self->_recurse_where($_[0]->{having});
164 push(@{$self->{having_bind}}, @extra);
165 $ret .= $self->_sqlcase(' having ').$frag;
166 }
54540863 167 if (defined $_[0]->{order_by}) {
7ce5cbe7 168 $ret .= $self->_order_by($_[0]->{order_by});
54540863 169 }
d09c569a 170 } elsif (ref $_[0] eq 'SCALAR') {
e535069e 171 $ret = $self->_sqlcase(' order by ').${ $_[0] };
d09c569a 172 } elsif (ref $_[0] eq 'ARRAY' && @{$_[0]}) {
173 my @order = @{+shift};
174 $ret = $self->_sqlcase(' order by ')
175 .join(', ', map {
176 my $r = $self->_order_by($_, @_);
177 $r =~ s/^ ?ORDER BY //i;
178 $r;
179 } @order);
54540863 180 } else {
181 $ret = $self->SUPER::_order_by(@_);
182 }
183 return $ret;
184}
185
f48dd03f 186sub _order_directions {
187 my ($self, $order) = @_;
188 $order = $order->{order_by} if ref $order eq 'HASH';
189 return $self->SUPER::_order_directions($order);
190}
191
2a816814 192sub _table {
bd7efd39 193 my ($self, $from) = @_;
194 if (ref $from eq 'ARRAY') {
195 return $self->_recurse_from(@$from);
196 } elsif (ref $from eq 'HASH') {
197 return $self->_make_as($from);
198 } else {
6346a152 199 return $from; # would love to quote here but _table ends up getting called
200 # twice during an ->select without a limit clause due to
201 # the way S::A::Limit->select works. should maybe consider
202 # bypassing this and doing S::A::select($self, ...) in
203 # our select method above. meantime, quoting shims have
204 # been added to select/insert/update/delete here
bd7efd39 205 }
206}
207
208sub _recurse_from {
209 my ($self, $from, @join) = @_;
210 my @sqlf;
211 push(@sqlf, $self->_make_as($from));
212 foreach my $j (@join) {
213 my ($to, $on) = @$j;
73856587 214
54540863 215 # check whether a join type exists
216 my $join_clause = '';
ca7b9fdf 217 my $to_jt = ref($to) eq 'ARRAY' ? $to->[0] : $to;
218 if (ref($to_jt) eq 'HASH' and exists($to_jt->{-join_type})) {
219 $join_clause = ' '.uc($to_jt->{-join_type}).' JOIN ';
54540863 220 } else {
221 $join_clause = ' JOIN ';
222 }
73856587 223 push(@sqlf, $join_clause);
224
bd7efd39 225 if (ref $to eq 'ARRAY') {
226 push(@sqlf, '(', $self->_recurse_from(@$to), ')');
227 } else {
96cdbbab 228 push(@sqlf, $self->_make_as($to));
bd7efd39 229 }
230 push(@sqlf, ' ON ', $self->_join_condition($on));
231 }
232 return join('', @sqlf);
233}
234
235sub _make_as {
236 my ($self, $from) = @_;
54540863 237 return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ : $self->_quote($_)) }
bc0c9800 238 reverse each %{$self->_skip_options($from)});
73856587 239}
240
241sub _skip_options {
54540863 242 my ($self, $hash) = @_;
243 my $clean_hash = {};
244 $clean_hash->{$_} = $hash->{$_}
245 for grep {!/^-/} keys %$hash;
246 return $clean_hash;
bd7efd39 247}
248
249sub _join_condition {
250 my ($self, $cond) = @_;
5efe4c79 251 if (ref $cond eq 'HASH') {
252 my %j;
bc0c9800 253 for (keys %$cond) {
635b9634 254 my $v = $cond->{$_};
255 if (ref $v) {
256 # XXX no throw_exception() in this package and croak() fails with strange results
257 Carp::croak(ref($v) . qq{ reference arguments are not supported in JOINS - try using \"..." instead'})
258 if ref($v) ne 'SCALAR';
259 $j{$_} = $v;
260 }
261 else {
262 my $x = '= '.$self->_quote($v); $j{$_} = \$x;
263 }
bc0c9800 264 };
635b9634 265 return scalar($self->_recurse_where(\%j));
5efe4c79 266 } elsif (ref $cond eq 'ARRAY') {
267 return join(' OR ', map { $self->_join_condition($_) } @$cond);
268 } else {
269 die "Can't handle this yet!";
270 }
bd7efd39 271}
272
2a816814 273sub _quote {
274 my ($self, $label) = @_;
275 return '' unless defined $label;
3b24f6ea 276 return "*" if $label eq '*';
41728a6e 277 return $label unless $self->{quote_char};
3b24f6ea 278 if(ref $self->{quote_char} eq "ARRAY"){
279 return $self->{quote_char}->[0] . $label . $self->{quote_char}->[1]
280 if !defined $self->{name_sep};
281 my $sep = $self->{name_sep};
282 return join($self->{name_sep},
283 map { $self->{quote_char}->[0] . $_ . $self->{quote_char}->[1] }
284 split(/\Q$sep\E/,$label));
285 }
2a816814 286 return $self->SUPER::_quote($label);
287}
288
7be93b07 289sub limit_dialect {
290 my $self = shift;
291 $self->{limit_dialect} = shift if @_;
292 return $self->{limit_dialect};
293}
294
2437a1e3 295sub quote_char {
296 my $self = shift;
297 $self->{quote_char} = shift if @_;
298 return $self->{quote_char};
299}
300
301sub name_sep {
302 my $self = shift;
303 $self->{name_sep} = shift if @_;
304 return $self->{name_sep};
305}
306
bd7efd39 307} # End of BEGIN block
308
b327f988 309=head1 NAME
310
311DBIx::Class::Storage::DBI - DBI storage handler
312
313=head1 SYNOPSIS
314
315=head1 DESCRIPTION
316
046ad905 317This class represents the connection to an RDBMS via L<DBI>. See
318L<DBIx::Class::Storage> for general information. This pod only
319documents DBI-specific methods and behaviors.
b327f988 320
321=head1 METHODS
322
9b83fccd 323=cut
324
8b445e33 325sub new {
046ad905 326 my $new = shift->next::method(@_);
82cc0386 327
d79f59b9 328 $new->transaction_depth(0);
2cc3a7be 329 $new->_sql_maker_opts({});
1b994857 330 $new->{_in_dbh_do} = 0;
dbaee748 331 $new->{_dbh_gen} = 0;
82cc0386 332
046ad905 333 $new;
1c339d71 334}
335
1b45b01e 336=head2 connect_info
337
bb4f246d 338The arguments of C<connect_info> are always a single array reference.
1b45b01e 339
bb4f246d 340This is normally accessed via L<DBIx::Class::Schema/connection>, which
341encapsulates its argument list in an arrayref before calling
342C<connect_info> here.
1b45b01e 343
bb4f246d 344The arrayref can either contain the same set of arguments one would
345normally pass to L<DBI/connect>, or a lone code reference which returns
77d76d0f 346a connected database handle. Please note that the L<DBI> docs
347recommend that you always explicitly set C<AutoCommit> to either
348C<0> or C<1>. L<DBIx::Class> further recommends that it be set
349to C<1>, and that you perform transactions via our L</txn_do>
2bc2ddc7 350method. L<DBIx::Class> will set it to C<1> if you do not do explicitly
351set it to zero. This is the default for most DBDs. See below for more
352details.
d7c4c15c 353
2cc3a7be 354In either case, if the final argument in your connect_info happens
355to be a hashref, C<connect_info> will look there for several
356connection-specific options:
357
358=over 4
359
360=item on_connect_do
361
6d2e7a96 362Specifies things to do immediately after connecting or re-connecting to
363the database. Its value may contain:
364
365=over
366
367=item an array reference
368
369This contains SQL statements to execute in order. Each element contains
370a string or a code reference that returns a string.
371
372=item a code reference
373
374This contains some code to execute. Unlike code references within an
375array reference, its return value is ignored.
376
377=back
579ca3f7 378
379=item on_disconnect_do
380
1dafdb2a 381Takes arguments in the same form as L<on_connect_do> and executes them
6d2e7a96 382immediately before disconnecting from the database.
579ca3f7 383
384Note, this only runs if you explicitly call L<disconnect> on the
385storage object.
2cc3a7be 386
b33697ef 387=item disable_sth_caching
388
389If set to a true value, this option will disable the caching of
390statement handles via L<DBI/prepare_cached>.
391
2cc3a7be 392=item limit_dialect
393
394Sets the limit dialect. This is useful for JDBC-bridge among others
395where the remote SQL-dialect cannot be determined by the name of the
396driver alone.
397
398=item quote_char
d7c4c15c 399
2cc3a7be 400Specifies what characters to use to quote table and column names. If
401you use this you will want to specify L<name_sep> as well.
402
403quote_char expects either a single character, in which case is it is placed
404on either side of the table/column, or an arrayref of length 2 in which case the
405table/column name is placed between the elements.
406
407For example under MySQL you'd use C<quote_char =E<gt> '`'>, and user SQL Server you'd
408use C<quote_char =E<gt> [qw/[ ]/]>.
409
410=item name_sep
411
412This only needs to be used in conjunction with L<quote_char>, and is used to
413specify the charecter that seperates elements (schemas, tables, columns) from
414each other. In most cases this is simply a C<.>.
415
61646ebd 416=item unsafe
417
418This Storage driver normally installs its own C<HandleError>, sets
2ab60eb9 419C<RaiseError> and C<ShowErrorStatement> on, and sets C<PrintError> off on
420all database handles, including those supplied by a coderef. It does this
421so that it can have consistent and useful error behavior.
61646ebd 422
423If you set this option to a true value, Storage will not do its usual
2ab60eb9 424modifications to the database handle's attributes, and instead relies on
425the settings in your connect_info DBI options (or the values you set in
426your connection coderef, in the case that you are connecting via coderef).
61646ebd 427
428Note that your custom settings can cause Storage to malfunction,
429especially if you set a C<HandleError> handler that suppresses exceptions
430and/or disable C<RaiseError>.
431
2cc3a7be 432=back
433
434These options can be mixed in with your other L<DBI> connection attributes,
435or placed in a seperate hashref after all other normal L<DBI> connection
436arguments.
437
438Every time C<connect_info> is invoked, any previous settings for
439these options will be cleared before setting the new ones, regardless of
440whether any options are specified in the new C<connect_info>.
441
77d76d0f 442Another Important Note:
443
444DBIC can do some wonderful magic with handling exceptions,
c64db0f4 445disconnections, and transactions when you use C<< AutoCommit => 1 >>
77d76d0f 446combined with C<txn_do> for transaction support.
447
c64db0f4 448If you set C<< AutoCommit => 0 >> in your connect info, then you are always
77d76d0f 449in an assumed transaction between commits, and you're telling us you'd
450like to manage that manually. A lot of DBIC's magic protections
451go away. We can't protect you from exceptions due to database
452disconnects because we don't know anything about how to restart your
453transactions. You're on your own for handling all sorts of exceptional
c64db0f4 454cases if you choose the C<< AutoCommit => 0 >> path, just as you would
77d76d0f 455be with raw DBI.
456
2cc3a7be 457Examples:
458
459 # Simple SQLite connection
bb4f246d 460 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
6789ebe3 461
2cc3a7be 462 # Connect via subref
bb4f246d 463 ->connect_info([ sub { DBI->connect(...) } ]);
6789ebe3 464
2cc3a7be 465 # A bit more complicated
bb4f246d 466 ->connect_info(
467 [
468 'dbi:Pg:dbname=foo',
469 'postgres',
470 'my_pg_password',
77d76d0f 471 { AutoCommit => 1 },
2cc3a7be 472 { quote_char => q{"}, name_sep => q{.} },
473 ]
474 );
475
476 # Equivalent to the previous example
477 ->connect_info(
478 [
479 'dbi:Pg:dbname=foo',
480 'postgres',
481 'my_pg_password',
77d76d0f 482 { AutoCommit => 1, quote_char => q{"}, name_sep => q{.} },
bb4f246d 483 ]
484 );
6789ebe3 485
2cc3a7be 486 # Subref + DBIC-specific connection options
bb4f246d 487 ->connect_info(
488 [
489 sub { DBI->connect(...) },
2cc3a7be 490 {
491 quote_char => q{`},
492 name_sep => q{@},
493 on_connect_do => ['SET search_path TO myschema,otherschema,public'],
b33697ef 494 disable_sth_caching => 1,
2cc3a7be 495 },
bb4f246d 496 ]
497 );
6789ebe3 498
004d31fb 499=cut
500
046ad905 501sub connect_info {
502 my ($self, $info_arg) = @_;
4c248161 503
046ad905 504 return $self->_connect_info if !$info_arg;
4c248161 505
046ad905 506 # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
507 # the new set of options
508 $self->_sql_maker(undef);
509 $self->_sql_maker_opts({});
fdad5fab 510 $self->_connect_info([@$info_arg]); # copy for _connect_info
486ad69b 511
fdad5fab 512 my $dbi_info = [@$info_arg]; # copy for _dbi_connect_info
8df3d107 513
541df64a 514 my $last_info = $dbi_info->[-1];
046ad905 515 if(ref $last_info eq 'HASH') {
9a0891be 516 $last_info = { %$last_info }; # so delete is non-destructive
5322ea52 517 my @storage_option = qw(
518 on_connect_do on_disconnect_do disable_sth_caching unsafe cursor_class
519 );
579ca3f7 520 for my $storage_opt (@storage_option) {
b33697ef 521 if(my $value = delete $last_info->{$storage_opt}) {
522 $self->$storage_opt($value);
523 }
046ad905 524 }
525 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
526 if(my $opt_val = delete $last_info->{$sql_maker_opt}) {
527 $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
528 }
529 }
9a0891be 530 # re-insert modified hashref
531 $dbi_info->[-1] = $last_info;
486ad69b 532
046ad905 533 # Get rid of any trailing empty hashref
541df64a 534 pop(@$dbi_info) if !keys %$last_info;
046ad905 535 }
fdad5fab 536 $self->_dbi_connect_info($dbi_info);
d7c4c15c 537
fdad5fab 538 $self->_connect_info;
046ad905 539}
004d31fb 540
046ad905 541=head2 on_connect_do
4c248161 542
046ad905 543This method is deprecated in favor of setting via L</connect_info>.
486ad69b 544
f11383c2 545=head2 dbh_do
546
3ff1602f 547Arguments: ($subref | $method_name), @extra_coderef_args?
046ad905 548
3ff1602f 549Execute the given $subref or $method_name using the new exception-based
550connection management.
046ad905 551
d4f16b21 552The first two arguments will be the storage object that C<dbh_do> was called
553on and a database handle to use. Any additional arguments will be passed
554verbatim to the called subref as arguments 2 and onwards.
555
556Using this (instead of $self->_dbh or $self->dbh) ensures correct
557exception handling and reconnection (or failover in future subclasses).
558
559Your subref should have no side-effects outside of the database, as
560there is the potential for your subref to be partially double-executed
561if the database connection was stale/dysfunctional.
046ad905 562
56769f7c 563Example:
f11383c2 564
56769f7c 565 my @stuff = $schema->storage->dbh_do(
566 sub {
d4f16b21 567 my ($storage, $dbh, @cols) = @_;
568 my $cols = join(q{, }, @cols);
569 $dbh->selectrow_array("SELECT $cols FROM foo");
046ad905 570 },
571 @column_list
56769f7c 572 );
f11383c2 573
574=cut
575
576sub dbh_do {
046ad905 577 my $self = shift;
3ff1602f 578 my $code = shift;
aa27edf7 579
6ad1059d 580 my $dbh = $self->_dbh;
581
582 return $self->$code($dbh, @_) if $self->{_in_dbh_do}
cb19f4dd 583 || $self->{transaction_depth};
584
1b994857 585 local $self->{_in_dbh_do} = 1;
586
f11383c2 587 my @result;
588 my $want_array = wantarray;
589
590 eval {
6ad1059d 591 $self->_verify_pid if $dbh;
592 if( !$dbh ) {
593 $self->_populate_dbh;
594 $dbh = $self->_dbh;
595 }
596
f11383c2 597 if($want_array) {
6ad1059d 598 @result = $self->$code($dbh, @_);
f11383c2 599 }
56769f7c 600 elsif(defined $want_array) {
6ad1059d 601 $result[0] = $self->$code($dbh, @_);
f11383c2 602 }
56769f7c 603 else {
6ad1059d 604 $self->$code($dbh, @_);
56769f7c 605 }
f11383c2 606 };
56769f7c 607
aa27edf7 608 my $exception = $@;
609 if(!$exception) { return $want_array ? @result : $result[0] }
610
611 $self->throw_exception($exception) if $self->connected;
612
613 # We were not connected - reconnect and retry, but let any
614 # exception fall right through this time
615 $self->_populate_dbh;
3ff1602f 616 $self->$code($self->_dbh, @_);
aa27edf7 617}
618
619# This is basically a blend of dbh_do above and DBIx::Class::Storage::txn_do.
620# It also informs dbh_do to bypass itself while under the direction of txn_do,
1b994857 621# via $self->{_in_dbh_do} (this saves some redundant eval and errorcheck, etc)
aa27edf7 622sub txn_do {
623 my $self = shift;
624 my $coderef = shift;
625
626 ref $coderef eq 'CODE' or $self->throw_exception
627 ('$coderef must be a CODE reference');
628
57c18b65 629 return $coderef->(@_) if $self->{transaction_depth};
630
1b994857 631 local $self->{_in_dbh_do} = 1;
f11383c2 632
aa27edf7 633 my @result;
634 my $want_array = wantarray;
635
d4f16b21 636 my $tried = 0;
637 while(1) {
638 eval {
639 $self->_verify_pid if $self->_dbh;
640 $self->_populate_dbh if !$self->_dbh;
aa27edf7 641
d4f16b21 642 $self->txn_begin;
643 if($want_array) {
644 @result = $coderef->(@_);
645 }
646 elsif(defined $want_array) {
647 $result[0] = $coderef->(@_);
648 }
649 else {
650 $coderef->(@_);
651 }
652 $self->txn_commit;
653 };
aa27edf7 654
d4f16b21 655 my $exception = $@;
656 if(!$exception) { return $want_array ? @result : $result[0] }
657
658 if($tried++ > 0 || $self->connected) {
659 eval { $self->txn_rollback };
660 my $rollback_exception = $@;
661 if($rollback_exception) {
662 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
663 $self->throw_exception($exception) # propagate nested rollback
664 if $rollback_exception =~ /$exception_class/;
665
666 $self->throw_exception(
667 "Transaction aborted: ${exception}. "
668 . "Rollback failed: ${rollback_exception}"
669 );
670 }
671 $self->throw_exception($exception)
aa27edf7 672 }
56769f7c 673
d4f16b21 674 # We were not connected, and was first try - reconnect and retry
675 # via the while loop
676 $self->_populate_dbh;
677 }
f11383c2 678}
679
9b83fccd 680=head2 disconnect
681
046ad905 682Our C<disconnect> method also performs a rollback first if the
9b83fccd 683database is not in C<AutoCommit> mode.
684
685=cut
686
412db1f4 687sub disconnect {
688 my ($self) = @_;
689
92925617 690 if( $self->connected ) {
6d2e7a96 691 my $connection_do = $self->on_disconnect_do;
692 $self->_do_connection_actions($connection_do) if ref($connection_do);
693
57c18b65 694 $self->_dbh->rollback unless $self->_dbh_autocommit;
92925617 695 $self->_dbh->disconnect;
696 $self->_dbh(undef);
dbaee748 697 $self->{_dbh_gen}++;
92925617 698 }
412db1f4 699}
700
f11383c2 701sub connected {
702 my ($self) = @_;
412db1f4 703
1346e22d 704 if(my $dbh = $self->_dbh) {
705 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
dbaee748 706 $self->_dbh(undef);
707 $self->{_dbh_gen}++;
708 return;
1346e22d 709 }
56769f7c 710 else {
711 $self->_verify_pid;
649bfb8c 712 return 0 if !$self->_dbh;
56769f7c 713 }
1346e22d 714 return ($dbh->FETCH('Active') && $dbh->ping);
715 }
716
717 return 0;
412db1f4 718}
719
f11383c2 720# handle pid changes correctly
56769f7c 721# NOTE: assumes $self->_dbh is a valid $dbh
f11383c2 722sub _verify_pid {
723 my ($self) = @_;
724
6ae3f9b9 725 return if defined $self->_conn_pid && $self->_conn_pid == $$;
f11383c2 726
f11383c2 727 $self->_dbh->{InactiveDestroy} = 1;
d3abf3fe 728 $self->_dbh(undef);
dbaee748 729 $self->{_dbh_gen}++;
f11383c2 730
731 return;
732}
733
412db1f4 734sub ensure_connected {
735 my ($self) = @_;
736
737 unless ($self->connected) {
8b445e33 738 $self->_populate_dbh;
739 }
412db1f4 740}
741
c235bbae 742=head2 dbh
743
744Returns the dbh - a data base handle of class L<DBI>.
745
746=cut
747
412db1f4 748sub dbh {
749 my ($self) = @_;
750
751 $self->ensure_connected;
8b445e33 752 return $self->_dbh;
753}
754
f1f56aad 755sub _sql_maker_args {
756 my ($self) = @_;
757
6e399b4f 758 return ( bindtype=>'columns', limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
f1f56aad 759}
760
48c69e7c 761sub sql_maker {
762 my ($self) = @_;
fdc1c3d0 763 unless ($self->_sql_maker) {
95ba7ee4 764 my $sql_maker_class = $self->sql_maker_class;
765 $self->_sql_maker($sql_maker_class->new( $self->_sql_maker_args ));
48c69e7c 766 }
767 return $self->_sql_maker;
768}
769
3ff1602f 770sub _rebless {}
771
8b445e33 772sub _populate_dbh {
773 my ($self) = @_;
7e47ea83 774 my @info = @{$self->_dbi_connect_info || []};
8b445e33 775 $self->_dbh($self->_connect(@info));
2fd24e78 776
77d76d0f 777 # Always set the transaction depth on connect, since
778 # there is no transaction in progress by definition
57c18b65 779 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 780
2fd24e78 781 if(ref $self eq 'DBIx::Class::Storage::DBI') {
782 my $driver = $self->_dbh->{Driver}->{Name};
efe6365b 783 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
2fd24e78 784 bless $self, "DBIx::Class::Storage::DBI::${driver}";
3ff1602f 785 $self->_rebless();
2fd24e78 786 }
843f8ecd 787 }
2fd24e78 788
6d2e7a96 789 my $connection_do = $self->on_connect_do;
790 $self->_do_connection_actions($connection_do) if ref($connection_do);
5ef3e508 791
1346e22d 792 $self->_conn_pid($$);
793 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
8b445e33 794}
795
6d2e7a96 796sub _do_connection_actions {
797 my $self = shift;
798 my $connection_do = shift;
799
800 if (ref $connection_do eq 'ARRAY') {
801 $self->_do_query($_) foreach @$connection_do;
802 }
803 elsif (ref $connection_do eq 'CODE') {
804 $connection_do->();
805 }
806
807 return $self;
808}
809
579ca3f7 810sub _do_query {
811 my ($self, $action) = @_;
812
6d2e7a96 813 if (ref $action eq 'CODE') {
1dafdb2a 814 $action = $action->($self);
815 $self->_do_query($_) foreach @$action;
579ca3f7 816 }
817 else {
1bd1640b 818 my @to_run = (ref $action eq 'ARRAY') ? (@$action) : ($action);
819 $self->_query_start(@to_run);
820 $self->_dbh->do(@to_run);
821 $self->_query_end(@to_run);
579ca3f7 822 }
823
824 return $self;
825}
826
8b445e33 827sub _connect {
828 my ($self, @info) = @_;
5ef3e508 829
9d31f7dc 830 $self->throw_exception("You failed to provide any connection info")
61646ebd 831 if !@info;
9d31f7dc 832
90ec6cad 833 my ($old_connect_via, $dbh);
834
5ef3e508 835 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
61646ebd 836 $old_connect_via = $DBI::connect_via;
837 $DBI::connect_via = 'connect';
5ef3e508 838 }
839
75db246c 840 eval {
f5de3933 841 if(ref $info[0] eq 'CODE') {
842 $dbh = &{$info[0]}
843 }
844 else {
845 $dbh = DBI->connect(@info);
61646ebd 846 }
847
e7827df0 848 if($dbh && !$self->unsafe) {
664612fb 849 my $weak_self = $self;
850 weaken($weak_self);
61646ebd 851 $dbh->{HandleError} = sub {
664612fb 852 $weak_self->throw_exception("DBI Exception: $_[0]")
61646ebd 853 };
2ab60eb9 854 $dbh->{ShowErrorStatement} = 1;
61646ebd 855 $dbh->{RaiseError} = 1;
856 $dbh->{PrintError} = 0;
f5de3933 857 }
75db246c 858 };
90ec6cad 859
860 $DBI::connect_via = $old_connect_via if $old_connect_via;
861
d92a4015 862 $self->throw_exception("DBI Connection failed: " . ($@||$DBI::errstr))
863 if !$dbh || $@;
90ec6cad 864
57c18b65 865 $self->_dbh_autocommit($dbh->{AutoCommit});
866
e571e823 867 $dbh;
8b445e33 868}
869
adb3554a 870sub svp_begin {
871 my ($self, $name) = @_;
872
873 $self->throw_exception("You failed to provide a savepoint name!") if !$name;
874
875 if($self->{transaction_depth} == 0) {
876 warn("Can't use savepoints without a transaction.");
877 return 0;
878 }
879
880 if(!$self->can('_svp_begin')) {
881 warn("Your Storage implementation doesn't support savepoints!");
882 return 0;
883 }
884 $self->debugobj->svp_begin($name) if $self->debug;
eeb8cfeb 885 $self->_svp_begin($name);
adb3554a 886}
887
888sub svp_release {
889 my ($self, $name) = @_;
890
891 $self->throw_exception("You failed to provide a savepoint name!") if !$name;
892
893 if($self->{transaction_depth} == 0) {
894 warn("Can't use savepoints without a transaction.");
895 return 0;
896 }
897
898 if(!$self->can('_svp_release')) {
899 warn("Your Storage implementation doesn't support savepoint releasing!");
900 return 0;
901 }
902 $self->debugobj->svp_release($name) if $self->debug;
eeb8cfeb 903 $self->_svp_release($name);
adb3554a 904}
905
906sub svp_rollback {
907 my ($self, $name) = @_;
908
909 $self->throw_exception("You failed to provide a savepoint name!") if !$name;
910
911 if($self->{transaction_depth} == 0) {
912 warn("Can't use savepoints without a transaction.");
913 return 0;
914 }
915
916 if(!$self->can('_svp_rollback')) {
917 warn("Your Storage implementation doesn't support savepoints!");
918 return 0;
919 }
920 $self->debugobj->svp_rollback($name) if $self->debug;
eeb8cfeb 921 $self->_svp_rollback($name);
adb3554a 922}
d32d82f9 923
8091aa91 924sub txn_begin {
d79f59b9 925 my $self = shift;
291bf95f 926 $self->ensure_connected();
57c18b65 927 if($self->{transaction_depth} == 0) {
77d76d0f 928 $self->debugobj->txn_begin()
929 if $self->debug;
930 # this isn't ->_dbh-> because
931 # we should reconnect on begin_work
932 # for AutoCommit users
933 $self->dbh->begin_work;
986e4fca 934 }
57c18b65 935 $self->{transaction_depth}++;
8091aa91 936}
8b445e33 937
8091aa91 938sub txn_commit {
d79f59b9 939 my $self = shift;
77d76d0f 940 if ($self->{transaction_depth} == 1) {
941 my $dbh = $self->_dbh;
942 $self->debugobj->txn_commit()
943 if ($self->debug);
944 $dbh->commit;
945 $self->{transaction_depth} = 0
57c18b65 946 if $self->_dbh_autocommit;
77d76d0f 947 }
948 elsif($self->{transaction_depth} > 1) {
949 $self->{transaction_depth}--
950 }
d32d82f9 951}
952
77d76d0f 953sub txn_rollback {
954 my $self = shift;
955 my $dbh = $self->_dbh;
77d76d0f 956 eval {
77d76d0f 957 if ($self->{transaction_depth} == 1) {
d32d82f9 958 $self->debugobj->txn_rollback()
959 if ($self->debug);
77d76d0f 960 $self->{transaction_depth} = 0
57c18b65 961 if $self->_dbh_autocommit;
962 $dbh->rollback;
d32d82f9 963 }
77d76d0f 964 elsif($self->{transaction_depth} > 1) {
965 $self->{transaction_depth}--;
986e4fca 966 }
f11383c2 967 else {
d32d82f9 968 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
986e4fca 969 }
77d76d0f 970 };
a62cf8d4 971 if ($@) {
972 my $error = $@;
973 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
974 $error =~ /$exception_class/ and $self->throw_exception($error);
77d76d0f 975 # ensure that a failed rollback resets the transaction depth
57c18b65 976 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 977 $self->throw_exception($error);
8091aa91 978 }
979}
8b445e33 980
b7151206 981# This used to be the top-half of _execute. It was split out to make it
982# easier to override in NoBindVars without duping the rest. It takes up
983# all of _execute's args, and emits $sql, @bind.
984sub _prep_for_execute {
d944c5ae 985 my ($self, $op, $extra_bind, $ident, $args) = @_;
b7151206 986
d944c5ae 987 my ($sql, @bind) = $self->sql_maker->$op($ident, @$args);
db4b5f11 988 unshift(@bind,
989 map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
990 if $extra_bind;
b7151206 991
d944c5ae 992 return ($sql, \@bind);
b7151206 993}
994
e5d9ee92 995sub _fix_bind_params {
996 my ($self, @bind) = @_;
997
998 ### Turn @bind from something like this:
999 ### ( [ "artist", 1 ], [ "cdid", 1, 3 ] )
1000 ### to this:
1001 ### ( "'1'", "'1'", "'3'" )
1002 return
1003 map {
1004 if ( defined( $_ && $_->[1] ) ) {
1005 map { qq{'$_'}; } @{$_}[ 1 .. $#$_ ];
1006 }
1007 else { q{'NULL'}; }
1008 } @bind;
1009}
1010
1011sub _query_start {
1012 my ( $self, $sql, @bind ) = @_;
1013
1014 if ( $self->debug ) {
1015 @bind = $self->_fix_bind_params(@bind);
1016 $self->debugobj->query_start( $sql, @bind );
1017 }
1018}
1019
1020sub _query_end {
1021 my ( $self, $sql, @bind ) = @_;
1022
1023 if ( $self->debug ) {
1024 @bind = $self->_fix_bind_params(@bind);
1025 $self->debugobj->query_end( $sql, @bind );
1026 }
1027}
1028
baa31d2f 1029sub _dbh_execute {
1030 my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
7af8b477 1031
eda28767 1032 if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
b7ce6568 1033 $ident = $ident->from();
1034 }
d944c5ae 1035
1036 my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args);
d92a4015 1037
e5d9ee92 1038 $self->_query_start( $sql, @$bind );
95dad7e2 1039
61646ebd 1040 my $sth = $self->sth($sql,$op);
6e399b4f 1041
61646ebd 1042 my $placeholder_index = 1;
6e399b4f 1043
61646ebd 1044 foreach my $bound (@$bind) {
1045 my $attributes = {};
1046 my($column_name, @data) = @$bound;
6e399b4f 1047
61646ebd 1048 if ($bind_attributes) {
1049 $attributes = $bind_attributes->{$column_name}
1050 if defined $bind_attributes->{$column_name};
1051 }
6e399b4f 1052
61646ebd 1053 foreach my $data (@data) {
1054 $data = ref $data ? ''.$data : $data; # stringify args
0b5dee17 1055
61646ebd 1056 $sth->bind_param($placeholder_index, $data, $attributes);
1057 $placeholder_index++;
95dad7e2 1058 }
61646ebd 1059 }
d92a4015 1060
61646ebd 1061 # Can this fail without throwing an exception anyways???
1062 my $rv = $sth->execute();
1063 $self->throw_exception($sth->errstr) if !$rv;
d92a4015 1064
e5d9ee92 1065 $self->_query_end( $sql, @$bind );
baa31d2f 1066
d944c5ae 1067 return (wantarray ? ($rv, $sth, @$bind) : $rv);
223b8fe3 1068}
1069
baa31d2f 1070sub _execute {
1071 my $self = shift;
3ff1602f 1072 $self->dbh_do('_dbh_execute', @_)
baa31d2f 1073}
1074
8b445e33 1075sub insert {
7af8b477 1076 my ($self, $source, $to_insert) = @_;
1077
1078 my $ident = $source->from;
8b646589 1079 my $bind_attributes = $self->source_bind_attributes($source);
1080
a982c051 1081 foreach my $col ( $source->columns ) {
1082 if ( !defined $to_insert->{$col} ) {
1083 my $col_info = $source->column_info($col);
1084
1085 if ( $col_info->{auto_nextval} ) {
6088eb64 1086 $self->ensure_connected;
a982c051 1087 $to_insert->{$col} = $self->_sequence_fetch( 'nextval', $col_info->{sequence} || $self->_dbh_get_autoinc_seq($self->dbh, $source) );
1088 }
1089 }
1090 }
1091
61646ebd 1092 $self->_execute('insert' => [], $source, $bind_attributes, $to_insert);
8e08ecc4 1093
8b445e33 1094 return $to_insert;
1095}
1096
744076d8 1097## Still not quite perfect, and EXPERIMENTAL
1098## Currently it is assumed that all values passed will be "normal", i.e. not
1099## scalar refs, or at least, all the same type as the first set, the statement is
1100## only prepped once.
54e0bd06 1101sub insert_bulk {
9fdf90df 1102 my ($self, $source, $cols, $data) = @_;
744076d8 1103 my %colvalues;
9fdf90df 1104 my $table = $source->from;
744076d8 1105 @colvalues{@$cols} = (0..$#$cols);
1106 my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
7af8b477 1107
e5d9ee92 1108 $self->_query_start( $sql, @bind );
894328b8 1109 my $sth = $self->sth($sql);
54e0bd06 1110
54e0bd06 1111# @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
1112
744076d8 1113 ## This must be an arrayref, else nothing works!
9fdf90df 1114
744076d8 1115 my $tuple_status = [];
9fdf90df 1116
1117 ##use Data::Dumper;
1118 ##print STDERR Dumper( $data, $sql, [@bind] );
eda28767 1119
61646ebd 1120 my $time = time();
8b646589 1121
61646ebd 1122 ## Get the bind_attributes, if any exist
1123 my $bind_attributes = $self->source_bind_attributes($source);
9fdf90df 1124
61646ebd 1125 ## Bind the values and execute
1126 my $placeholder_index = 1;
9fdf90df 1127
61646ebd 1128 foreach my $bound (@bind) {
9fdf90df 1129
61646ebd 1130 my $attributes = {};
1131 my ($column_name, $data_index) = @$bound;
eda28767 1132
61646ebd 1133 if( $bind_attributes ) {
1134 $attributes = $bind_attributes->{$column_name}
1135 if defined $bind_attributes->{$column_name};
1136 }
9fdf90df 1137
61646ebd 1138 my @data = map { $_->[$data_index] } @$data;
9fdf90df 1139
61646ebd 1140 $sth->bind_param_array( $placeholder_index, [@data], $attributes );
1141 $placeholder_index++;
54e0bd06 1142 }
61646ebd 1143 my $rv = $sth->execute_array({ArrayTupleStatus => $tuple_status});
1144 $self->throw_exception($sth->errstr) if !$rv;
1145
e5d9ee92 1146 $self->_query_end( $sql, @bind );
54e0bd06 1147 return (wantarray ? ($rv, $sth, @bind) : $rv);
1148}
1149
8b445e33 1150sub update {
7af8b477 1151 my $self = shift @_;
1152 my $source = shift @_;
8b646589 1153 my $bind_attributes = $self->source_bind_attributes($source);
8b646589 1154
b7ce6568 1155 return $self->_execute('update' => [], $source, $bind_attributes, @_);
8b445e33 1156}
1157
7af8b477 1158
8b445e33 1159sub delete {
7af8b477 1160 my $self = shift @_;
1161 my $source = shift @_;
1162
1163 my $bind_attrs = {}; ## If ever it's needed...
7af8b477 1164
b7ce6568 1165 return $self->_execute('delete' => [], $source, $bind_attrs, @_);
8b445e33 1166}
1167
de705b51 1168sub _select {
8b445e33 1169 my ($self, $ident, $select, $condition, $attrs) = @_;
223b8fe3 1170 my $order = $attrs->{order_by};
95ba7ee4 1171
223b8fe3 1172 if (ref $condition eq 'SCALAR') {
1173 $order = $1 if $$condition =~ s/ORDER BY (.*)$//i;
1174 }
95ba7ee4 1175
1176 my $for = delete $attrs->{for};
1177 my $sql_maker = $self->sql_maker;
1178 local $sql_maker->{for} = $for;
1179
8839560b 1180 if (exists $attrs->{group_by} || $attrs->{having}) {
bc0c9800 1181 $order = {
1182 group_by => $attrs->{group_by},
1183 having => $attrs->{having},
1184 ($order ? (order_by => $order) : ())
1185 };
54540863 1186 }
7af8b477 1187 my $bind_attrs = {}; ## Future support
1188 my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order);
9229f20a 1189 if ($attrs->{software_limit} ||
1190 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
1191 $attrs->{software_limit} = 1;
5c91499f 1192 } else {
0823196c 1193 $self->throw_exception("rows attribute must be positive if present")
1194 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
e60dc79f 1195
1196 # MySQL actually recommends this approach. I cringe.
1197 $attrs->{rows} = 2**48 if not defined $attrs->{rows} and defined $attrs->{offset};
5c91499f 1198 push @args, $attrs->{rows}, $attrs->{offset};
1199 }
95ba7ee4 1200
de705b51 1201 return $self->_execute(@args);
1202}
1203
8b646589 1204sub source_bind_attributes {
1205 my ($self, $source) = @_;
1206
1207 my $bind_attributes;
1208 foreach my $column ($source->columns) {
1209
1210 my $data_type = $source->column_info($column)->{data_type} || '';
1211 $bind_attributes->{$column} = $self->bind_attribute_by_data_type($data_type)
eda28767 1212 if $data_type;
8b646589 1213 }
1214
1215 return $bind_attributes;
1216}
1217
9b83fccd 1218=head2 select
1219
d3b0e369 1220=over 4
1221
1222=item Arguments: $ident, $select, $condition, $attrs
1223
1224=back
1225
9b83fccd 1226Handle a SQL select statement.
1227
1228=cut
1229
de705b51 1230sub select {
1231 my $self = shift;
1232 my ($ident, $select, $condition, $attrs) = @_;
e4eb8ee1 1233 return $self->cursor_class->new($self, \@_, $attrs);
8b445e33 1234}
1235
1a14aa3f 1236sub select_single {
de705b51 1237 my $self = shift;
1238 my ($rv, $sth, @bind) = $self->_select(@_);
6157db4f 1239 my @row = $sth->fetchrow_array;
a3eaff0e 1240 # Need to call finish() to work round broken DBDs
6157db4f 1241 $sth->finish();
1242 return @row;
1a14aa3f 1243}
1244
9b83fccd 1245=head2 sth
1246
d3b0e369 1247=over 4
1248
1249=item Arguments: $sql
1250
1251=back
1252
9b83fccd 1253Returns a L<DBI> sth (statement handle) for the supplied SQL.
1254
1255=cut
1256
d4f16b21 1257sub _dbh_sth {
1258 my ($self, $dbh, $sql) = @_;
b33697ef 1259
d32d82f9 1260 # 3 is the if_active parameter which avoids active sth re-use
b33697ef 1261 my $sth = $self->disable_sth_caching
1262 ? $dbh->prepare($sql)
1263 : $dbh->prepare_cached($sql, {}, 3);
1264
d92a4015 1265 # XXX You would think RaiseError would make this impossible,
1266 # but apparently that's not true :(
61646ebd 1267 $self->throw_exception($dbh->errstr) if !$sth;
b33697ef 1268
1269 $sth;
d32d82f9 1270}
1271
8b445e33 1272sub sth {
cb5f2eea 1273 my ($self, $sql) = @_;
3ff1602f 1274 $self->dbh_do('_dbh_sth', $sql);
8b445e33 1275}
1276
d4f16b21 1277sub _dbh_columns_info_for {
1278 my ($self, $dbh, $table) = @_;
a32e8402 1279
d32d82f9 1280 if ($dbh->can('column_info')) {
a953d8d9 1281 my %result;
d32d82f9 1282 eval {
1283 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
1284 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
1285 $sth->execute();
1286 while ( my $info = $sth->fetchrow_hashref() ){
1287 my %column_info;
1288 $column_info{data_type} = $info->{TYPE_NAME};
1289 $column_info{size} = $info->{COLUMN_SIZE};
1290 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
1291 $column_info{default_value} = $info->{COLUMN_DEF};
1292 my $col_name = $info->{COLUMN_NAME};
1293 $col_name =~ s/^\"(.*)\"$/$1/;
1294
1295 $result{$col_name} = \%column_info;
0d67fe74 1296 }
d32d82f9 1297 };
093fc7a6 1298 return \%result if !$@ && scalar keys %result;
d32d82f9 1299 }
0d67fe74 1300
d32d82f9 1301 my %result;
88262f96 1302 my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0'));
d32d82f9 1303 $sth->execute;
1304 my @columns = @{$sth->{NAME_lc}};
1305 for my $i ( 0 .. $#columns ){
1306 my %column_info;
248bf0d0 1307 $column_info{data_type} = $sth->{TYPE}->[$i];
d32d82f9 1308 $column_info{size} = $sth->{PRECISION}->[$i];
1309 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
0d67fe74 1310
d32d82f9 1311 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
1312 $column_info{data_type} = $1;
1313 $column_info{size} = $2;
0d67fe74 1314 }
1315
d32d82f9 1316 $result{$columns[$i]} = \%column_info;
1317 }
248bf0d0 1318 $sth->finish;
1319
1320 foreach my $col (keys %result) {
1321 my $colinfo = $result{$col};
1322 my $type_num = $colinfo->{data_type};
1323 my $type_name;
1324 if(defined $type_num && $dbh->can('type_info')) {
1325 my $type_info = $dbh->type_info($type_num);
1326 $type_name = $type_info->{TYPE_NAME} if $type_info;
1327 $colinfo->{data_type} = $type_name if $type_name;
1328 }
1329 }
d32d82f9 1330
1331 return \%result;
1332}
1333
1334sub columns_info_for {
1335 my ($self, $table) = @_;
3ff1602f 1336 $self->dbh_do('_dbh_columns_info_for', $table);
a953d8d9 1337}
1338
9b83fccd 1339=head2 last_insert_id
1340
1341Return the row id of the last insert.
1342
1343=cut
1344
d4f16b21 1345sub _dbh_last_insert_id {
1346 my ($self, $dbh, $source, $col) = @_;
1347 # XXX This is a SQLite-ism as a default... is there a DBI-generic way?
1348 $dbh->func('last_insert_rowid');
1349}
1350
843f8ecd 1351sub last_insert_id {
d4f16b21 1352 my $self = shift;
3ff1602f 1353 $self->dbh_do('_dbh_last_insert_id', @_);
843f8ecd 1354}
1355
9b83fccd 1356=head2 sqlt_type
1357
1358Returns the database driver name.
1359
1360=cut
1361
d4f16b21 1362sub sqlt_type { shift->dbh->{Driver}->{Name} }
1c339d71 1363
a71859b4 1364=head2 bind_attribute_by_data_type
1365
1366Given a datatype from column info, returns a database specific bind attribute for
1367$dbh->bind_param($val,$attribute) or nothing if we will let the database planner
1368just handle it.
1369
1370Generally only needed for special case column types, like bytea in postgres.
1371
1372=cut
1373
1374sub bind_attribute_by_data_type {
1375 return;
1376}
1377
58ded37e 1378=head2 create_ddl_dir
9b83fccd 1379
1380=over 4
1381
c9d2e0a2 1382=item Arguments: $schema \@databases, $version, $directory, $preversion, $sqlt_args
9b83fccd 1383
1384=back
1385
d3b0e369 1386Creates a SQL file based on the Schema, for each of the specified
9b83fccd 1387database types, in the given directory.
1388
9b83fccd 1389=cut
1390
e673f011 1391sub create_ddl_dir
1392{
c9d2e0a2 1393 my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_;
e673f011 1394
1395 if(!$dir || !-d $dir)
1396 {
1397 warn "No directory given, using ./\n";
1398 $dir = "./";
1399 }
1400 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
1401 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
1402 $version ||= $schema->VERSION || '1.x';
9e7b9292 1403 $sqltargs = { ( add_drop_table => 1 ), %{$sqltargs || {}} };
e673f011 1404
b6d9f089 1405 $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.09: '}
40dce2a5 1406 . $self->_check_sqlt_message . q{'})
1407 if !$self->_check_sqlt_version;
e673f011 1408
45f1a484 1409 my $sqlt = SQL::Translator->new( $sqltargs );
b7e303a8 1410
1411 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
1412 my $sqlt_schema = $sqlt->translate({ data => $schema }) or die $sqlt->error;
1413
e673f011 1414 foreach my $db (@$databases)
1415 {
1416 $sqlt->reset();
c9d2e0a2 1417 $sqlt = $self->configure_sqlt($sqlt, $db);
b7e303a8 1418 $sqlt->{schema} = $sqlt_schema;
e673f011 1419 $sqlt->producer($db);
1420
1421 my $file;
1422 my $filename = $schema->ddl_filename($db, $dir, $version);
1423 if(-e $filename)
1424 {
c9d2e0a2 1425 warn("$filename already exists, skipping $db");
b98d9e8a 1426 next unless ($preversion);
1427 } else {
1428 my $output = $sqlt->translate;
1429 if(!$output)
1430 {
1431 warn("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
c9d2e0a2 1432 next;
b98d9e8a 1433 }
1434 if(!open($file, ">$filename"))
1435 {
1436 $self->throw_exception("Can't open $filename for writing ($!)");
1437 next;
1438 }
1439 print $file $output;
1440 close($file);
1441 }
c9d2e0a2 1442 if($preversion)
1443 {
40dce2a5 1444 require SQL::Translator::Diff;
c9d2e0a2 1445
1446 my $prefilename = $schema->ddl_filename($db, $dir, $preversion);
e2c0df8e 1447# print "Previous version $prefilename\n";
c9d2e0a2 1448 if(!-e $prefilename)
1449 {
1450 warn("No previous schema file found ($prefilename)");
1451 next;
1452 }
c9d2e0a2 1453
2dc2cd0f 1454 my $difffile = $schema->ddl_filename($db, $dir, $version, $preversion);
1455 print STDERR "Diff: $difffile: $db, $dir, $version, $preversion \n";
1456 if(-e $difffile)
1457 {
1458 warn("$difffile already exists, skipping");
1459 next;
1460 }
1461
b7e303a8 1462 my $source_schema;
1463 {
45f1a484 1464 my $t = SQL::Translator->new($sqltargs);
c9d2e0a2 1465 $t->debug( 0 );
1466 $t->trace( 0 );
b7e303a8 1467 $t->parser( $db ) or die $t->error;
45f1a484 1468 $t = $self->configure_sqlt($t, $db);
b7e303a8 1469 my $out = $t->translate( $prefilename ) or die $t->error;
1470 $source_schema = $t->schema;
1471 unless ( $source_schema->name ) {
1472 $source_schema->name( $prefilename );
c9d2e0a2 1473 }
b7e303a8 1474 }
c9d2e0a2 1475
2dc2cd0f 1476 # The "new" style of producers have sane normalization and can support
1477 # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't
1478 # And we have to diff parsed SQL against parsed SQL.
1479 my $dest_schema = $sqlt_schema;
1480
3ce95357 1481 unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) {
45f1a484 1482 my $t = SQL::Translator->new($sqltargs);
2dc2cd0f 1483 $t->debug( 0 );
1484 $t->trace( 0 );
1485 $t->parser( $db ) or die $t->error;
45f1a484 1486 $t = $self->configure_sqlt($t, $db);
2dc2cd0f 1487 my $out = $t->translate( $filename ) or die $t->error;
1488 $dest_schema = $t->schema;
1489 $dest_schema->name( $filename )
1490 unless $dest_schema->name;
1491 }
c9d2e0a2 1492
1493 my $diff = SQL::Translator::Diff::schema_diff($source_schema, $db,
2dc2cd0f 1494 $dest_schema, $db,
45f1a484 1495 $sqltargs
c9d2e0a2 1496 );
c9d2e0a2 1497 if(!open $file, ">$difffile")
1498 {
1499 $self->throw_exception("Can't write to $difffile ($!)");
1500 next;
1501 }
1502 print $file $diff;
1503 close($file);
1504 }
e673f011 1505 }
c9d2e0a2 1506}
e673f011 1507
c9d2e0a2 1508sub configure_sqlt() {
1509 my $self = shift;
1510 my $tr = shift;
1511 my $db = shift || $self->sqlt_type;
1512 if ($db eq 'PostgreSQL') {
1513 $tr->quote_table_names(0);
1514 $tr->quote_field_names(0);
1515 }
1516 return $tr;
e673f011 1517}
1518
9b83fccd 1519=head2 deployment_statements
1520
d3b0e369 1521=over 4
1522
1523=item Arguments: $schema, $type, $version, $directory, $sqlt_args
1524
1525=back
1526
1527Returns the statements used by L</deploy> and L<DBIx::Class::Schema/deploy>.
1528The database driver name is given by C<$type>, though the value from
1529L</sqlt_type> is used if it is not specified.
1530
1531C<$directory> is used to return statements from files in a previously created
1532L</create_ddl_dir> directory and is optional. The filenames are constructed
1533from L<DBIx::Class::Schema/ddl_filename>, the schema name and the C<$version>.
1534
1535If no C<$directory> is specified then the statements are constructed on the
1536fly using L<SQL::Translator> and C<$version> is ignored.
1537
1538See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>.
9b83fccd 1539
1540=cut
1541
e673f011 1542sub deployment_statements {
1543 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
915919c5 1544 # Need to be connected to get the correct sqlt_type
c377d939 1545 $self->ensure_connected() unless $type;
e673f011 1546 $type ||= $self->sqlt_type;
1547 $version ||= $schema->VERSION || '1.x';
1548 $dir ||= './';
c9d2e0a2 1549 my $filename = $schema->ddl_filename($type, $dir, $version);
1550 if(-f $filename)
1551 {
1552 my $file;
1553 open($file, "<$filename")
1554 or $self->throw_exception("Can't open $filename ($!)");
1555 my @rows = <$file>;
1556 close($file);
1557 return join('', @rows);
1558 }
1559
b6d9f089 1560 $self->throw_exception(q{Can't deploy without SQL::Translator 0.09: '}
40dce2a5 1561 . $self->_check_sqlt_message . q{'})
1562 if !$self->_check_sqlt_version;
1563
1564 require SQL::Translator::Parser::DBIx::Class;
1565 eval qq{use SQL::Translator::Producer::${type}};
1566 $self->throw_exception($@) if $@;
1567
1568 # sources needs to be a parser arg, but for simplicty allow at top level
1569 # coming in
1570 $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
1571 if exists $sqltargs->{sources};
1572
1573 my $tr = SQL::Translator->new(%$sqltargs);
1574 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
1575 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
e673f011 1576
c9d2e0a2 1577 return;
e673f011 1578
1c339d71 1579}
843f8ecd 1580
1c339d71 1581sub deploy {
260129d8 1582 my ($self, $schema, $type, $sqltargs, $dir) = @_;
1583 foreach my $statement ( $self->deployment_statements($schema, $type, undef, $dir, { no_comments => 1, %{ $sqltargs || {} } } ) ) {
61bf0de5 1584 foreach my $line ( split(";\n", $statement)) {
1585 next if($line =~ /^--/);
1586 next if(!$line);
1587# next if($line =~ /^DROP/m);
1588 next if($line =~ /^BEGIN TRANSACTION/m);
1589 next if($line =~ /^COMMIT/m);
1590 next if $line =~ /^\s+$/; # skip whitespace only
e5d9ee92 1591 $self->_query_start($line);
61bf0de5 1592 eval {
1593 $self->dbh->do($line); # shouldn't be using ->dbh ?
1594 };
1595 if ($@) {
1596 warn qq{$@ (running "${line}")};
1597 }
e5d9ee92 1598 $self->_query_end($line);
e4fe9ba3 1599 }
75d07914 1600 }
1c339d71 1601}
843f8ecd 1602
9b83fccd 1603=head2 datetime_parser
1604
1605Returns the datetime parser class
1606
1607=cut
1608
f86fcf0d 1609sub datetime_parser {
1610 my $self = shift;
114780ee 1611 return $self->{datetime_parser} ||= do {
1612 $self->ensure_connected;
1613 $self->build_datetime_parser(@_);
1614 };
f86fcf0d 1615}
1616
9b83fccd 1617=head2 datetime_parser_type
1618
1619Defines (returns) the datetime parser class - currently hardwired to
1620L<DateTime::Format::MySQL>
1621
1622=cut
1623
f86fcf0d 1624sub datetime_parser_type { "DateTime::Format::MySQL"; }
1625
9b83fccd 1626=head2 build_datetime_parser
1627
1628See L</datetime_parser>
1629
1630=cut
1631
f86fcf0d 1632sub build_datetime_parser {
1633 my $self = shift;
1634 my $type = $self->datetime_parser_type(@_);
1635 eval "use ${type}";
1636 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1637 return $type;
1638}
1639
40dce2a5 1640{
1641 my $_check_sqlt_version; # private
1642 my $_check_sqlt_message; # private
1643 sub _check_sqlt_version {
1644 return $_check_sqlt_version if defined $_check_sqlt_version;
b6d9f089 1645 eval 'use SQL::Translator "0.09"';
b7e303a8 1646 $_check_sqlt_message = $@ || '';
1647 $_check_sqlt_version = !$@;
40dce2a5 1648 }
1649
1650 sub _check_sqlt_message {
1651 _check_sqlt_version if !defined $_check_sqlt_message;
1652 $_check_sqlt_message;
1653 }
1654}
1655
c756145c 1656sub DESTROY {
1657 my $self = shift;
f5de3933 1658 return if !$self->_dbh;
c756145c 1659 $self->_verify_pid;
1660 $self->_dbh(undef);
1661}
92925617 1662
8b445e33 16631;
1664
9b83fccd 1665=head1 SQL METHODS
1666
1667The module defines a set of methods within the DBIC::SQL::Abstract
1668namespace. These build on L<SQL::Abstract::Limit> to provide the
1669SQL query functions.
1670
1671The following methods are extended:-
1672
1673=over 4
1674
1675=item delete
1676
1677=item insert
1678
1679=item select
1680
1681=item update
1682
1683=item limit_dialect
1684
2cc3a7be 1685See L</connect_info> for details.
1686For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1687
9b83fccd 1688=item quote_char
1689
2cc3a7be 1690See L</connect_info> for details.
1691For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1692
9b83fccd 1693=item name_sep
1694
2cc3a7be 1695See L</connect_info> for details.
1696For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1697
9b83fccd 1698=back
1699
8b445e33 1700=head1 AUTHORS
1701
daec44b8 1702Matt S. Trout <mst@shadowcatsystems.co.uk>
8b445e33 1703
9f19b1d6 1704Andy Grundman <andy@hybridized.org>
1705
8b445e33 1706=head1 LICENSE
1707
1708You may distribute this code under the same terms as Perl itself.
1709
1710=cut