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