add some things to castaway's rewrite
[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
362 $connect_info_args = [ $dsn, $user, $pass, \%dbi_attributes, \%extra_attributes ];
363
364=item *
1b45b01e 365
92fe2181 366A lone code reference which returns a connected L<DBI database handle|DBI/connect>
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
374A lone hashref with all the attributes and the dsn/user/pass mixed together:
375
376 $connect_info_args = [{
377 dsn => $dsn,
378 user => $user,
379 pass => $pass,
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
2cc3a7be 500=back
501
92fe2181 502Some real-life examples of arguments to L</connect_info> and L<DBIx::Class::Schema/connect>
2cc3a7be 503
504 # Simple SQLite connection
bb4f246d 505 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
6789ebe3 506
2cc3a7be 507 # Connect via subref
bb4f246d 508 ->connect_info([ sub { DBI->connect(...) } ]);
6789ebe3 509
2cc3a7be 510 # A bit more complicated
bb4f246d 511 ->connect_info(
512 [
513 'dbi:Pg:dbname=foo',
514 'postgres',
515 'my_pg_password',
77d76d0f 516 { AutoCommit => 1 },
2cc3a7be 517 { quote_char => q{"}, name_sep => q{.} },
518 ]
519 );
520
521 # Equivalent to the previous example
522 ->connect_info(
523 [
524 'dbi:Pg:dbname=foo',
525 'postgres',
526 'my_pg_password',
77d76d0f 527 { AutoCommit => 1, quote_char => q{"}, name_sep => q{.} },
bb4f246d 528 ]
529 );
6789ebe3 530
92fe2181 531 # Same, but with hashref as argument
532 # See C<parse_connect_info> for explanation
533 ->connect_info(
534 [{
535 dsn => 'dbi:Pg:dbname=foo',
536 user => 'postgres',
537 password => 'my_pg_password',
538 AutoCommit => 1,
539 quote_char => q{"},
540 name_sep => q{.},
541 }]
542 );
543
544 # Subref + DBIx::Class-specific connection options
bb4f246d 545 ->connect_info(
546 [
547 sub { DBI->connect(...) },
2cc3a7be 548 {
549 quote_char => q{`},
550 name_sep => q{@},
551 on_connect_do => ['SET search_path TO myschema,otherschema,public'],
b33697ef 552 disable_sth_caching => 1,
2cc3a7be 553 },
bb4f246d 554 ]
555 );
6789ebe3 556
92fe2181 557
558
004d31fb 559=cut
560
046ad905 561sub connect_info {
562 my ($self, $info_arg) = @_;
4c248161 563
046ad905 564 return $self->_connect_info if !$info_arg;
4c248161 565
92fe2181 566 my @args = @$info_arg; # take a shallow copy for further mutilation
567 $self->_connect_info([@args]); # copy for _connect_info
568
569
570 # combine/pre-parse arguments depending on invocation style
571
572 my %attrs;
573 if (ref $args[0] eq 'CODE') { # coderef with optional \%extra_attributes
574 %attrs = %{ $args[1] || {} };
575 @args = $args[0];
576 }
577 elsif (ref $args[0] eq 'HASH') { # single hashref (i.e. Catalyst config)
578 %attrs = %{$args[0]};
579 @args = ();
580 for (qw/password user dsn/) {
581 unshift @args, delete $attrs{$_};
582 }
583 }
584 else { # otherwise assume dsn/user/pass + \%attrs + \%extra_attrs
585 %attrs = (
586 % { $args[3] || {} },
587 % { $args[4] || {} },
588 );
589 @args = @args[0,1,2];
590 }
591
046ad905 592 # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
593 # the new set of options
594 $self->_sql_maker(undef);
595 $self->_sql_maker_opts({});
8df3d107 596
92fe2181 597 if(keys %attrs) {
598 for my $storage_opt (@storage_options, 'cursor_class') { # @storage_options is declared at the top of the module
599 if(my $value = delete $attrs{$storage_opt}) {
b33697ef 600 $self->$storage_opt($value);
601 }
046ad905 602 }
603 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
92fe2181 604 if(my $opt_val = delete $attrs{$sql_maker_opt}) {
046ad905 605 $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
606 }
607 }
046ad905 608 }
d7c4c15c 609
92fe2181 610 %attrs = () if (ref $args[0] eq 'CODE'); # _connect() never looks past $args[0] in this case
611
612 $self->_dbi_connect_info([@args, keys %attrs ? \%attrs : ()]);
fdad5fab 613 $self->_connect_info;
046ad905 614}
004d31fb 615
046ad905 616=head2 on_connect_do
4c248161 617
046ad905 618This method is deprecated in favor of setting via L</connect_info>.
486ad69b 619
92fe2181 620
f11383c2 621=head2 dbh_do
622
3ff1602f 623Arguments: ($subref | $method_name), @extra_coderef_args?
046ad905 624
3ff1602f 625Execute the given $subref or $method_name using the new exception-based
626connection management.
046ad905 627
d4f16b21 628The first two arguments will be the storage object that C<dbh_do> was called
629on and a database handle to use. Any additional arguments will be passed
630verbatim to the called subref as arguments 2 and onwards.
631
632Using this (instead of $self->_dbh or $self->dbh) ensures correct
633exception handling and reconnection (or failover in future subclasses).
634
635Your subref should have no side-effects outside of the database, as
636there is the potential for your subref to be partially double-executed
637if the database connection was stale/dysfunctional.
046ad905 638
56769f7c 639Example:
f11383c2 640
56769f7c 641 my @stuff = $schema->storage->dbh_do(
642 sub {
d4f16b21 643 my ($storage, $dbh, @cols) = @_;
644 my $cols = join(q{, }, @cols);
645 $dbh->selectrow_array("SELECT $cols FROM foo");
046ad905 646 },
647 @column_list
56769f7c 648 );
f11383c2 649
650=cut
651
652sub dbh_do {
046ad905 653 my $self = shift;
3ff1602f 654 my $code = shift;
aa27edf7 655
6ad1059d 656 my $dbh = $self->_dbh;
657
658 return $self->$code($dbh, @_) if $self->{_in_dbh_do}
cb19f4dd 659 || $self->{transaction_depth};
660
1b994857 661 local $self->{_in_dbh_do} = 1;
662
f11383c2 663 my @result;
664 my $want_array = wantarray;
665
666 eval {
6ad1059d 667 $self->_verify_pid if $dbh;
37976db0 668 if(!$self->_dbh) {
6ad1059d 669 $self->_populate_dbh;
670 $dbh = $self->_dbh;
671 }
672
f11383c2 673 if($want_array) {
6ad1059d 674 @result = $self->$code($dbh, @_);
f11383c2 675 }
56769f7c 676 elsif(defined $want_array) {
6ad1059d 677 $result[0] = $self->$code($dbh, @_);
f11383c2 678 }
56769f7c 679 else {
6ad1059d 680 $self->$code($dbh, @_);
56769f7c 681 }
f11383c2 682 };
56769f7c 683
aa27edf7 684 my $exception = $@;
685 if(!$exception) { return $want_array ? @result : $result[0] }
686
687 $self->throw_exception($exception) if $self->connected;
688
689 # We were not connected - reconnect and retry, but let any
690 # exception fall right through this time
691 $self->_populate_dbh;
3ff1602f 692 $self->$code($self->_dbh, @_);
aa27edf7 693}
694
695# This is basically a blend of dbh_do above and DBIx::Class::Storage::txn_do.
696# It also informs dbh_do to bypass itself while under the direction of txn_do,
1b994857 697# via $self->{_in_dbh_do} (this saves some redundant eval and errorcheck, etc)
aa27edf7 698sub txn_do {
699 my $self = shift;
700 my $coderef = shift;
701
702 ref $coderef eq 'CODE' or $self->throw_exception
703 ('$coderef must be a CODE reference');
704
d6feb60f 705 return $coderef->(@_) if $self->{transaction_depth} && ! $self->auto_savepoint;
57c18b65 706
1b994857 707 local $self->{_in_dbh_do} = 1;
f11383c2 708
aa27edf7 709 my @result;
710 my $want_array = wantarray;
711
d4f16b21 712 my $tried = 0;
713 while(1) {
714 eval {
715 $self->_verify_pid if $self->_dbh;
716 $self->_populate_dbh if !$self->_dbh;
aa27edf7 717
d4f16b21 718 $self->txn_begin;
719 if($want_array) {
720 @result = $coderef->(@_);
721 }
722 elsif(defined $want_array) {
723 $result[0] = $coderef->(@_);
724 }
725 else {
726 $coderef->(@_);
727 }
728 $self->txn_commit;
729 };
aa27edf7 730
d4f16b21 731 my $exception = $@;
732 if(!$exception) { return $want_array ? @result : $result[0] }
733
734 if($tried++ > 0 || $self->connected) {
735 eval { $self->txn_rollback };
736 my $rollback_exception = $@;
737 if($rollback_exception) {
738 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
739 $self->throw_exception($exception) # propagate nested rollback
740 if $rollback_exception =~ /$exception_class/;
741
742 $self->throw_exception(
743 "Transaction aborted: ${exception}. "
744 . "Rollback failed: ${rollback_exception}"
745 );
746 }
747 $self->throw_exception($exception)
aa27edf7 748 }
56769f7c 749
d4f16b21 750 # We were not connected, and was first try - reconnect and retry
751 # via the while loop
752 $self->_populate_dbh;
753 }
f11383c2 754}
755
9b83fccd 756=head2 disconnect
757
046ad905 758Our C<disconnect> method also performs a rollback first if the
9b83fccd 759database is not in C<AutoCommit> mode.
760
761=cut
762
412db1f4 763sub disconnect {
764 my ($self) = @_;
765
92925617 766 if( $self->connected ) {
6d2e7a96 767 my $connection_do = $self->on_disconnect_do;
768 $self->_do_connection_actions($connection_do) if ref($connection_do);
769
57c18b65 770 $self->_dbh->rollback unless $self->_dbh_autocommit;
92925617 771 $self->_dbh->disconnect;
772 $self->_dbh(undef);
dbaee748 773 $self->{_dbh_gen}++;
92925617 774 }
412db1f4 775}
776
e96a93df 777=head2 with_deferred_fk_checks
778
779=over 4
780
781=item Arguments: C<$coderef>
782
783=item Return Value: The return value of $coderef
784
785=back
786
787Storage specific method to run the code ref with FK checks deferred or
788in MySQL's case disabled entirely.
789
790=cut
791
792# Storage subclasses should override this
793sub with_deferred_fk_checks {
794 my ($self, $sub) = @_;
795
796 $sub->();
797}
798
f11383c2 799sub connected {
800 my ($self) = @_;
412db1f4 801
1346e22d 802 if(my $dbh = $self->_dbh) {
803 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
dbaee748 804 $self->_dbh(undef);
805 $self->{_dbh_gen}++;
806 return;
1346e22d 807 }
56769f7c 808 else {
809 $self->_verify_pid;
649bfb8c 810 return 0 if !$self->_dbh;
56769f7c 811 }
1346e22d 812 return ($dbh->FETCH('Active') && $dbh->ping);
813 }
814
815 return 0;
412db1f4 816}
817
f11383c2 818# handle pid changes correctly
56769f7c 819# NOTE: assumes $self->_dbh is a valid $dbh
f11383c2 820sub _verify_pid {
821 my ($self) = @_;
822
6ae3f9b9 823 return if defined $self->_conn_pid && $self->_conn_pid == $$;
f11383c2 824
f11383c2 825 $self->_dbh->{InactiveDestroy} = 1;
d3abf3fe 826 $self->_dbh(undef);
dbaee748 827 $self->{_dbh_gen}++;
f11383c2 828
829 return;
830}
831
412db1f4 832sub ensure_connected {
833 my ($self) = @_;
834
835 unless ($self->connected) {
8b445e33 836 $self->_populate_dbh;
837 }
412db1f4 838}
839
c235bbae 840=head2 dbh
841
842Returns the dbh - a data base handle of class L<DBI>.
843
844=cut
845
412db1f4 846sub dbh {
847 my ($self) = @_;
848
849 $self->ensure_connected;
8b445e33 850 return $self->_dbh;
851}
852
f1f56aad 853sub _sql_maker_args {
854 my ($self) = @_;
855
6e399b4f 856 return ( bindtype=>'columns', limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
f1f56aad 857}
858
48c69e7c 859sub sql_maker {
860 my ($self) = @_;
fdc1c3d0 861 unless ($self->_sql_maker) {
95ba7ee4 862 my $sql_maker_class = $self->sql_maker_class;
863 $self->_sql_maker($sql_maker_class->new( $self->_sql_maker_args ));
48c69e7c 864 }
865 return $self->_sql_maker;
866}
867
3ff1602f 868sub _rebless {}
869
8b445e33 870sub _populate_dbh {
871 my ($self) = @_;
7e47ea83 872 my @info = @{$self->_dbi_connect_info || []};
8b445e33 873 $self->_dbh($self->_connect(@info));
2fd24e78 874
77d76d0f 875 # Always set the transaction depth on connect, since
876 # there is no transaction in progress by definition
57c18b65 877 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 878
2fd24e78 879 if(ref $self eq 'DBIx::Class::Storage::DBI') {
880 my $driver = $self->_dbh->{Driver}->{Name};
efe6365b 881 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
2fd24e78 882 bless $self, "DBIx::Class::Storage::DBI::${driver}";
3ff1602f 883 $self->_rebless();
2fd24e78 884 }
843f8ecd 885 }
2fd24e78 886
6d2e7a96 887 my $connection_do = $self->on_connect_do;
888 $self->_do_connection_actions($connection_do) if ref($connection_do);
5ef3e508 889
1346e22d 890 $self->_conn_pid($$);
891 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
8b445e33 892}
893
6d2e7a96 894sub _do_connection_actions {
895 my $self = shift;
896 my $connection_do = shift;
897
898 if (ref $connection_do eq 'ARRAY') {
899 $self->_do_query($_) foreach @$connection_do;
900 }
901 elsif (ref $connection_do eq 'CODE') {
902 $connection_do->();
903 }
904
905 return $self;
906}
907
579ca3f7 908sub _do_query {
909 my ($self, $action) = @_;
910
6d2e7a96 911 if (ref $action eq 'CODE') {
1dafdb2a 912 $action = $action->($self);
913 $self->_do_query($_) foreach @$action;
579ca3f7 914 }
915 else {
1bd1640b 916 my @to_run = (ref $action eq 'ARRAY') ? (@$action) : ($action);
917 $self->_query_start(@to_run);
918 $self->_dbh->do(@to_run);
919 $self->_query_end(@to_run);
579ca3f7 920 }
921
922 return $self;
923}
924
8b445e33 925sub _connect {
926 my ($self, @info) = @_;
5ef3e508 927
9d31f7dc 928 $self->throw_exception("You failed to provide any connection info")
61646ebd 929 if !@info;
9d31f7dc 930
90ec6cad 931 my ($old_connect_via, $dbh);
932
5ef3e508 933 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
61646ebd 934 $old_connect_via = $DBI::connect_via;
935 $DBI::connect_via = 'connect';
5ef3e508 936 }
937
75db246c 938 eval {
f5de3933 939 if(ref $info[0] eq 'CODE') {
940 $dbh = &{$info[0]}
941 }
942 else {
943 $dbh = DBI->connect(@info);
61646ebd 944 }
945
e7827df0 946 if($dbh && !$self->unsafe) {
664612fb 947 my $weak_self = $self;
948 weaken($weak_self);
61646ebd 949 $dbh->{HandleError} = sub {
9bf06dc0 950 if ($weak_self) {
951 $weak_self->throw_exception("DBI Exception: $_[0]");
952 }
953 else {
954 croak ("DBI Exception: $_[0]");
955 }
61646ebd 956 };
2ab60eb9 957 $dbh->{ShowErrorStatement} = 1;
61646ebd 958 $dbh->{RaiseError} = 1;
959 $dbh->{PrintError} = 0;
f5de3933 960 }
75db246c 961 };
90ec6cad 962
963 $DBI::connect_via = $old_connect_via if $old_connect_via;
964
d92a4015 965 $self->throw_exception("DBI Connection failed: " . ($@||$DBI::errstr))
966 if !$dbh || $@;
90ec6cad 967
57c18b65 968 $self->_dbh_autocommit($dbh->{AutoCommit});
969
e571e823 970 $dbh;
8b445e33 971}
972
adb3554a 973sub svp_begin {
974 my ($self, $name) = @_;
adb3554a 975
ddf66ced 976 $name = $self->_svp_generate_name
977 unless defined $name;
978
979 $self->throw_exception ("You can't use savepoints outside a transaction")
980 if $self->{transaction_depth} == 0;
981
982 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
983 unless $self->can('_svp_begin');
984
985 push @{ $self->{savepoints} }, $name;
adb3554a 986
adb3554a 987 $self->debugobj->svp_begin($name) if $self->debug;
ddf66ced 988
989 return $self->_svp_begin($name);
adb3554a 990}
991
992sub svp_release {
993 my ($self, $name) = @_;
994
ddf66ced 995 $self->throw_exception ("You can't use savepoints outside a transaction")
996 if $self->{transaction_depth} == 0;
adb3554a 997
ddf66ced 998 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
999 unless $self->can('_svp_release');
1000
1001 if (defined $name) {
1002 $self->throw_exception ("Savepoint '$name' does not exist")
1003 unless grep { $_ eq $name } @{ $self->{savepoints} };
1004
1005 # Dig through the stack until we find the one we are releasing. This keeps
1006 # the stack up to date.
1007 my $svp;
adb3554a 1008
ddf66ced 1009 do { $svp = pop @{ $self->{savepoints} } } while $svp ne $name;
1010 } else {
1011 $name = pop @{ $self->{savepoints} };
adb3554a 1012 }
ddf66ced 1013
adb3554a 1014 $self->debugobj->svp_release($name) if $self->debug;
ddf66ced 1015
1016 return $self->_svp_release($name);
adb3554a 1017}
1018
1019sub svp_rollback {
1020 my ($self, $name) = @_;
1021
ddf66ced 1022 $self->throw_exception ("You can't use savepoints outside a transaction")
1023 if $self->{transaction_depth} == 0;
adb3554a 1024
ddf66ced 1025 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
1026 unless $self->can('_svp_rollback');
1027
1028 if (defined $name) {
1029 # If they passed us a name, verify that it exists in the stack
1030 unless(grep({ $_ eq $name } @{ $self->{savepoints} })) {
1031 $self->throw_exception("Savepoint '$name' does not exist!");
1032 }
adb3554a 1033
ddf66ced 1034 # Dig through the stack until we find the one we are releasing. This keeps
1035 # the stack up to date.
1036 while(my $s = pop(@{ $self->{savepoints} })) {
1037 last if($s eq $name);
1038 }
1039 # Add the savepoint back to the stack, as a rollback doesn't remove the
1040 # named savepoint, only everything after it.
1041 push(@{ $self->{savepoints} }, $name);
1042 } else {
1043 # We'll assume they want to rollback to the last savepoint
1044 $name = $self->{savepoints}->[-1];
adb3554a 1045 }
ddf66ced 1046
adb3554a 1047 $self->debugobj->svp_rollback($name) if $self->debug;
ddf66ced 1048
1049 return $self->_svp_rollback($name);
1050}
1051
1052sub _svp_generate_name {
1053 my ($self) = @_;
1054
1055 return 'savepoint_'.scalar(@{ $self->{'savepoints'} });
adb3554a 1056}
d32d82f9 1057
8091aa91 1058sub txn_begin {
d79f59b9 1059 my $self = shift;
291bf95f 1060 $self->ensure_connected();
57c18b65 1061 if($self->{transaction_depth} == 0) {
77d76d0f 1062 $self->debugobj->txn_begin()
1063 if $self->debug;
1064 # this isn't ->_dbh-> because
1065 # we should reconnect on begin_work
1066 # for AutoCommit users
1067 $self->dbh->begin_work;
d6feb60f 1068 } elsif ($self->auto_savepoint) {
ddf66ced 1069 $self->svp_begin;
986e4fca 1070 }
57c18b65 1071 $self->{transaction_depth}++;
8091aa91 1072}
8b445e33 1073
8091aa91 1074sub txn_commit {
d79f59b9 1075 my $self = shift;
77d76d0f 1076 if ($self->{transaction_depth} == 1) {
1077 my $dbh = $self->_dbh;
1078 $self->debugobj->txn_commit()
1079 if ($self->debug);
1080 $dbh->commit;
1081 $self->{transaction_depth} = 0
57c18b65 1082 if $self->_dbh_autocommit;
77d76d0f 1083 }
1084 elsif($self->{transaction_depth} > 1) {
d6feb60f 1085 $self->{transaction_depth}--;
ddf66ced 1086 $self->svp_release
d6feb60f 1087 if $self->auto_savepoint;
77d76d0f 1088 }
d32d82f9 1089}
1090
77d76d0f 1091sub txn_rollback {
1092 my $self = shift;
1093 my $dbh = $self->_dbh;
77d76d0f 1094 eval {
77d76d0f 1095 if ($self->{transaction_depth} == 1) {
d32d82f9 1096 $self->debugobj->txn_rollback()
1097 if ($self->debug);
77d76d0f 1098 $self->{transaction_depth} = 0
57c18b65 1099 if $self->_dbh_autocommit;
1100 $dbh->rollback;
d32d82f9 1101 }
77d76d0f 1102 elsif($self->{transaction_depth} > 1) {
1103 $self->{transaction_depth}--;
d6feb60f 1104 if ($self->auto_savepoint) {
ddf66ced 1105 $self->svp_rollback;
1106 $self->svp_release;
d6feb60f 1107 }
986e4fca 1108 }
f11383c2 1109 else {
d32d82f9 1110 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
986e4fca 1111 }
77d76d0f 1112 };
a62cf8d4 1113 if ($@) {
1114 my $error = $@;
1115 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
1116 $error =~ /$exception_class/ and $self->throw_exception($error);
77d76d0f 1117 # ensure that a failed rollback resets the transaction depth
57c18b65 1118 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 1119 $self->throw_exception($error);
8091aa91 1120 }
1121}
8b445e33 1122
b7151206 1123# This used to be the top-half of _execute. It was split out to make it
1124# easier to override in NoBindVars without duping the rest. It takes up
1125# all of _execute's args, and emits $sql, @bind.
1126sub _prep_for_execute {
d944c5ae 1127 my ($self, $op, $extra_bind, $ident, $args) = @_;
b7151206 1128
d944c5ae 1129 my ($sql, @bind) = $self->sql_maker->$op($ident, @$args);
db4b5f11 1130 unshift(@bind,
1131 map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
1132 if $extra_bind;
b7151206 1133
d944c5ae 1134 return ($sql, \@bind);
b7151206 1135}
1136
e5d9ee92 1137sub _fix_bind_params {
1138 my ($self, @bind) = @_;
1139
1140 ### Turn @bind from something like this:
1141 ### ( [ "artist", 1 ], [ "cdid", 1, 3 ] )
1142 ### to this:
1143 ### ( "'1'", "'1'", "'3'" )
1144 return
1145 map {
1146 if ( defined( $_ && $_->[1] ) ) {
1147 map { qq{'$_'}; } @{$_}[ 1 .. $#$_ ];
1148 }
1149 else { q{'NULL'}; }
1150 } @bind;
1151}
1152
1153sub _query_start {
1154 my ( $self, $sql, @bind ) = @_;
1155
1156 if ( $self->debug ) {
1157 @bind = $self->_fix_bind_params(@bind);
50336325 1158
e5d9ee92 1159 $self->debugobj->query_start( $sql, @bind );
1160 }
1161}
1162
1163sub _query_end {
1164 my ( $self, $sql, @bind ) = @_;
1165
1166 if ( $self->debug ) {
1167 @bind = $self->_fix_bind_params(@bind);
1168 $self->debugobj->query_end( $sql, @bind );
1169 }
1170}
1171
baa31d2f 1172sub _dbh_execute {
1173 my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
7af8b477 1174
eda28767 1175 if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
b7ce6568 1176 $ident = $ident->from();
1177 }
d944c5ae 1178
1179 my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args);
d92a4015 1180
e5d9ee92 1181 $self->_query_start( $sql, @$bind );
95dad7e2 1182
61646ebd 1183 my $sth = $self->sth($sql,$op);
6e399b4f 1184
61646ebd 1185 my $placeholder_index = 1;
6e399b4f 1186
61646ebd 1187 foreach my $bound (@$bind) {
1188 my $attributes = {};
1189 my($column_name, @data) = @$bound;
6e399b4f 1190
61646ebd 1191 if ($bind_attributes) {
1192 $attributes = $bind_attributes->{$column_name}
1193 if defined $bind_attributes->{$column_name};
1194 }
6e399b4f 1195
61646ebd 1196 foreach my $data (@data) {
1197 $data = ref $data ? ''.$data : $data; # stringify args
0b5dee17 1198
61646ebd 1199 $sth->bind_param($placeholder_index, $data, $attributes);
1200 $placeholder_index++;
95dad7e2 1201 }
61646ebd 1202 }
d92a4015 1203
61646ebd 1204 # Can this fail without throwing an exception anyways???
1205 my $rv = $sth->execute();
1206 $self->throw_exception($sth->errstr) if !$rv;
d92a4015 1207
e5d9ee92 1208 $self->_query_end( $sql, @$bind );
baa31d2f 1209
d944c5ae 1210 return (wantarray ? ($rv, $sth, @$bind) : $rv);
223b8fe3 1211}
1212
baa31d2f 1213sub _execute {
1214 my $self = shift;
3ff1602f 1215 $self->dbh_do('_dbh_execute', @_)
baa31d2f 1216}
1217
8b445e33 1218sub insert {
7af8b477 1219 my ($self, $source, $to_insert) = @_;
1220
1221 my $ident = $source->from;
8b646589 1222 my $bind_attributes = $self->source_bind_attributes($source);
1223
2eebd801 1224 $self->ensure_connected;
a982c051 1225 foreach my $col ( $source->columns ) {
1226 if ( !defined $to_insert->{$col} ) {
1227 my $col_info = $source->column_info($col);
1228
1229 if ( $col_info->{auto_nextval} ) {
1230 $to_insert->{$col} = $self->_sequence_fetch( 'nextval', $col_info->{sequence} || $self->_dbh_get_autoinc_seq($self->dbh, $source) );
1231 }
1232 }
1233 }
1234
61646ebd 1235 $self->_execute('insert' => [], $source, $bind_attributes, $to_insert);
8e08ecc4 1236
8b445e33 1237 return $to_insert;
1238}
1239
744076d8 1240## Still not quite perfect, and EXPERIMENTAL
1241## Currently it is assumed that all values passed will be "normal", i.e. not
1242## scalar refs, or at least, all the same type as the first set, the statement is
1243## only prepped once.
54e0bd06 1244sub insert_bulk {
9fdf90df 1245 my ($self, $source, $cols, $data) = @_;
744076d8 1246 my %colvalues;
9fdf90df 1247 my $table = $source->from;
744076d8 1248 @colvalues{@$cols} = (0..$#$cols);
1249 my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
7af8b477 1250
e5d9ee92 1251 $self->_query_start( $sql, @bind );
894328b8 1252 my $sth = $self->sth($sql);
54e0bd06 1253
54e0bd06 1254# @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
1255
744076d8 1256 ## This must be an arrayref, else nothing works!
9fdf90df 1257
744076d8 1258 my $tuple_status = [];
9fdf90df 1259
1260 ##use Data::Dumper;
1261 ##print STDERR Dumper( $data, $sql, [@bind] );
eda28767 1262
61646ebd 1263 my $time = time();
8b646589 1264
61646ebd 1265 ## Get the bind_attributes, if any exist
1266 my $bind_attributes = $self->source_bind_attributes($source);
9fdf90df 1267
61646ebd 1268 ## Bind the values and execute
1269 my $placeholder_index = 1;
9fdf90df 1270
61646ebd 1271 foreach my $bound (@bind) {
9fdf90df 1272
61646ebd 1273 my $attributes = {};
1274 my ($column_name, $data_index) = @$bound;
eda28767 1275
61646ebd 1276 if( $bind_attributes ) {
1277 $attributes = $bind_attributes->{$column_name}
1278 if defined $bind_attributes->{$column_name};
1279 }
9fdf90df 1280
61646ebd 1281 my @data = map { $_->[$data_index] } @$data;
9fdf90df 1282
61646ebd 1283 $sth->bind_param_array( $placeholder_index, [@data], $attributes );
1284 $placeholder_index++;
54e0bd06 1285 }
61646ebd 1286 my $rv = $sth->execute_array({ArrayTupleStatus => $tuple_status});
1287 $self->throw_exception($sth->errstr) if !$rv;
1288
e5d9ee92 1289 $self->_query_end( $sql, @bind );
54e0bd06 1290 return (wantarray ? ($rv, $sth, @bind) : $rv);
1291}
1292
8b445e33 1293sub update {
7af8b477 1294 my $self = shift @_;
1295 my $source = shift @_;
8b646589 1296 my $bind_attributes = $self->source_bind_attributes($source);
8b646589 1297
b7ce6568 1298 return $self->_execute('update' => [], $source, $bind_attributes, @_);
8b445e33 1299}
1300
7af8b477 1301
8b445e33 1302sub delete {
7af8b477 1303 my $self = shift @_;
1304 my $source = shift @_;
1305
1306 my $bind_attrs = {}; ## If ever it's needed...
7af8b477 1307
b7ce6568 1308 return $self->_execute('delete' => [], $source, $bind_attrs, @_);
8b445e33 1309}
1310
de705b51 1311sub _select {
8b445e33 1312 my ($self, $ident, $select, $condition, $attrs) = @_;
223b8fe3 1313 my $order = $attrs->{order_by};
95ba7ee4 1314
223b8fe3 1315 if (ref $condition eq 'SCALAR') {
68f3b0dd 1316 my $unwrap = ${$condition};
1317 if ($unwrap =~ s/ORDER BY (.*)$//i) {
1318 $order = $1;
1319 $condition = \$unwrap;
1320 }
223b8fe3 1321 }
95ba7ee4 1322
1323 my $for = delete $attrs->{for};
1324 my $sql_maker = $self->sql_maker;
1325 local $sql_maker->{for} = $for;
1326
8839560b 1327 if (exists $attrs->{group_by} || $attrs->{having}) {
bc0c9800 1328 $order = {
1329 group_by => $attrs->{group_by},
1330 having => $attrs->{having},
1331 ($order ? (order_by => $order) : ())
1332 };
54540863 1333 }
7af8b477 1334 my $bind_attrs = {}; ## Future support
1335 my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order);
9229f20a 1336 if ($attrs->{software_limit} ||
1337 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
1338 $attrs->{software_limit} = 1;
5c91499f 1339 } else {
0823196c 1340 $self->throw_exception("rows attribute must be positive if present")
1341 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
e60dc79f 1342
1343 # MySQL actually recommends this approach. I cringe.
1344 $attrs->{rows} = 2**48 if not defined $attrs->{rows} and defined $attrs->{offset};
5c91499f 1345 push @args, $attrs->{rows}, $attrs->{offset};
1346 }
95ba7ee4 1347
de705b51 1348 return $self->_execute(@args);
1349}
1350
8b646589 1351sub source_bind_attributes {
1352 my ($self, $source) = @_;
1353
1354 my $bind_attributes;
1355 foreach my $column ($source->columns) {
1356
1357 my $data_type = $source->column_info($column)->{data_type} || '';
1358 $bind_attributes->{$column} = $self->bind_attribute_by_data_type($data_type)
eda28767 1359 if $data_type;
8b646589 1360 }
1361
1362 return $bind_attributes;
1363}
1364
9b83fccd 1365=head2 select
1366
d3b0e369 1367=over 4
1368
1369=item Arguments: $ident, $select, $condition, $attrs
1370
1371=back
1372
9b83fccd 1373Handle a SQL select statement.
1374
1375=cut
1376
de705b51 1377sub select {
1378 my $self = shift;
1379 my ($ident, $select, $condition, $attrs) = @_;
e4eb8ee1 1380 return $self->cursor_class->new($self, \@_, $attrs);
8b445e33 1381}
1382
1a14aa3f 1383sub select_single {
de705b51 1384 my $self = shift;
1385 my ($rv, $sth, @bind) = $self->_select(@_);
6157db4f 1386 my @row = $sth->fetchrow_array;
1a4e8d7c 1387 if(@row && $sth->fetchrow_array) {
1388 carp "Query returned more than one row. SQL that returns multiple rows is DEPRECATED for ->find and ->single";
1389 }
a3eaff0e 1390 # Need to call finish() to work round broken DBDs
6157db4f 1391 $sth->finish();
1392 return @row;
1a14aa3f 1393}
1394
9b83fccd 1395=head2 sth
1396
d3b0e369 1397=over 4
1398
1399=item Arguments: $sql
1400
1401=back
1402
9b83fccd 1403Returns a L<DBI> sth (statement handle) for the supplied SQL.
1404
1405=cut
1406
d4f16b21 1407sub _dbh_sth {
1408 my ($self, $dbh, $sql) = @_;
b33697ef 1409
d32d82f9 1410 # 3 is the if_active parameter which avoids active sth re-use
b33697ef 1411 my $sth = $self->disable_sth_caching
1412 ? $dbh->prepare($sql)
1413 : $dbh->prepare_cached($sql, {}, 3);
1414
d92a4015 1415 # XXX You would think RaiseError would make this impossible,
1416 # but apparently that's not true :(
61646ebd 1417 $self->throw_exception($dbh->errstr) if !$sth;
b33697ef 1418
1419 $sth;
d32d82f9 1420}
1421
8b445e33 1422sub sth {
cb5f2eea 1423 my ($self, $sql) = @_;
3ff1602f 1424 $self->dbh_do('_dbh_sth', $sql);
8b445e33 1425}
1426
d4f16b21 1427sub _dbh_columns_info_for {
1428 my ($self, $dbh, $table) = @_;
a32e8402 1429
d32d82f9 1430 if ($dbh->can('column_info')) {
a953d8d9 1431 my %result;
d32d82f9 1432 eval {
1433 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
1434 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
1435 $sth->execute();
1436 while ( my $info = $sth->fetchrow_hashref() ){
1437 my %column_info;
1438 $column_info{data_type} = $info->{TYPE_NAME};
1439 $column_info{size} = $info->{COLUMN_SIZE};
1440 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
1441 $column_info{default_value} = $info->{COLUMN_DEF};
1442 my $col_name = $info->{COLUMN_NAME};
1443 $col_name =~ s/^\"(.*)\"$/$1/;
1444
1445 $result{$col_name} = \%column_info;
0d67fe74 1446 }
d32d82f9 1447 };
093fc7a6 1448 return \%result if !$@ && scalar keys %result;
d32d82f9 1449 }
0d67fe74 1450
d32d82f9 1451 my %result;
88262f96 1452 my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0'));
d32d82f9 1453 $sth->execute;
1454 my @columns = @{$sth->{NAME_lc}};
1455 for my $i ( 0 .. $#columns ){
1456 my %column_info;
248bf0d0 1457 $column_info{data_type} = $sth->{TYPE}->[$i];
d32d82f9 1458 $column_info{size} = $sth->{PRECISION}->[$i];
1459 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
0d67fe74 1460
d32d82f9 1461 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
1462 $column_info{data_type} = $1;
1463 $column_info{size} = $2;
0d67fe74 1464 }
1465
d32d82f9 1466 $result{$columns[$i]} = \%column_info;
1467 }
248bf0d0 1468 $sth->finish;
1469
1470 foreach my $col (keys %result) {
1471 my $colinfo = $result{$col};
1472 my $type_num = $colinfo->{data_type};
1473 my $type_name;
1474 if(defined $type_num && $dbh->can('type_info')) {
1475 my $type_info = $dbh->type_info($type_num);
1476 $type_name = $type_info->{TYPE_NAME} if $type_info;
1477 $colinfo->{data_type} = $type_name if $type_name;
1478 }
1479 }
d32d82f9 1480
1481 return \%result;
1482}
1483
1484sub columns_info_for {
1485 my ($self, $table) = @_;
3ff1602f 1486 $self->dbh_do('_dbh_columns_info_for', $table);
a953d8d9 1487}
1488
9b83fccd 1489=head2 last_insert_id
1490
1491Return the row id of the last insert.
1492
1493=cut
1494
d4f16b21 1495sub _dbh_last_insert_id {
1496 my ($self, $dbh, $source, $col) = @_;
1497 # XXX This is a SQLite-ism as a default... is there a DBI-generic way?
1498 $dbh->func('last_insert_rowid');
1499}
1500
843f8ecd 1501sub last_insert_id {
d4f16b21 1502 my $self = shift;
3ff1602f 1503 $self->dbh_do('_dbh_last_insert_id', @_);
843f8ecd 1504}
1505
9b83fccd 1506=head2 sqlt_type
1507
1508Returns the database driver name.
1509
1510=cut
1511
d4f16b21 1512sub sqlt_type { shift->dbh->{Driver}->{Name} }
1c339d71 1513
a71859b4 1514=head2 bind_attribute_by_data_type
1515
1516Given a datatype from column info, returns a database specific bind attribute for
1517$dbh->bind_param($val,$attribute) or nothing if we will let the database planner
1518just handle it.
1519
1520Generally only needed for special case column types, like bytea in postgres.
1521
1522=cut
1523
1524sub bind_attribute_by_data_type {
1525 return;
1526}
1527
58ded37e 1528=head2 create_ddl_dir
9b83fccd 1529
1530=over 4
1531
348d7c84 1532=item Arguments: $schema \@databases, $version, $directory, $preversion, \%sqlt_args
9b83fccd 1533
1534=back
1535
d3b0e369 1536Creates a SQL file based on the Schema, for each of the specified
9b83fccd 1537database types, in the given directory.
1538
348d7c84 1539By default, C<\%sqlt_args> will have
1540
1541 { add_drop_table => 1, ignore_constraint_names => 1, ignore_index_names => 1 }
1542
1543merged with the hash passed in. To disable any of those features, pass in a
1544hashref like the following
1545
1546 { ignore_constraint_names => 0, # ... other options }
1547
9b83fccd 1548=cut
1549
99a74c4a 1550sub create_ddl_dir {
c9d2e0a2 1551 my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_;
e673f011 1552
99a74c4a 1553 if(!$dir || !-d $dir) {
e673f011 1554 warn "No directory given, using ./\n";
1555 $dir = "./";
1556 }
1557 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
1558 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
1559 $version ||= $schema->VERSION || '1.x';
d4d46d19 1560 $sqltargs = {
1561 add_drop_table => 1,
1562 ignore_constraint_names => 1,
1563 ignore_index_names => 1,
1564 %{$sqltargs || {}}
1565 };
e673f011 1566
b6d9f089 1567 $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.09: '}
40dce2a5 1568 . $self->_check_sqlt_message . q{'})
1569 if !$self->_check_sqlt_version;
e673f011 1570
45f1a484 1571 my $sqlt = SQL::Translator->new( $sqltargs );
b7e303a8 1572
1573 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
1574 my $sqlt_schema = $sqlt->translate({ data => $schema }) or die $sqlt->error;
1575
99a74c4a 1576 foreach my $db (@$databases) {
e673f011 1577 $sqlt->reset();
c9d2e0a2 1578 $sqlt = $self->configure_sqlt($sqlt, $db);
b7e303a8 1579 $sqlt->{schema} = $sqlt_schema;
e673f011 1580 $sqlt->producer($db);
1581
1582 my $file;
99a74c4a 1583 my $filename = $schema->ddl_filename($db, $version, $dir);
1584 if (-e $filename && (!$version || ($version == $schema->schema_version()))) {
1585 # if we are dumping the current version, overwrite the DDL
1586 warn "Overwriting existing DDL file - $filename";
1587 unlink($filename);
1588 }
c9d2e0a2 1589
99a74c4a 1590 my $output = $sqlt->translate;
1591 if(!$output) {
1592 warn("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
1593 next;
1594 }
1595 if(!open($file, ">$filename")) {
1596 $self->throw_exception("Can't open $filename for writing ($!)");
1597 next;
1598 }
1599 print $file $output;
1600 close($file);
1601
1602 next unless ($preversion);
c9d2e0a2 1603
99a74c4a 1604 require SQL::Translator::Diff;
2dc2cd0f 1605
99a74c4a 1606 my $prefilename = $schema->ddl_filename($db, $preversion, $dir);
1607 if(!-e $prefilename) {
1608 warn("No previous schema file found ($prefilename)");
1609 next;
1610 }
c9d2e0a2 1611
99a74c4a 1612 my $difffile = $schema->ddl_filename($db, $version, $dir, $preversion);
1613 if(-e $difffile) {
1614 warn("Overwriting existing diff file - $difffile");
1615 unlink($difffile);
1616 }
1617
1618 my $source_schema;
1619 {
1620 my $t = SQL::Translator->new($sqltargs);
1621 $t->debug( 0 );
1622 $t->trace( 0 );
1623 $t->parser( $db ) or die $t->error;
1624 $t = $self->configure_sqlt($t, $db);
1625 my $out = $t->translate( $prefilename ) or die $t->error;
1626 $source_schema = $t->schema;
1627 unless ( $source_schema->name ) {
1628 $source_schema->name( $prefilename );
2dc2cd0f 1629 }
99a74c4a 1630 }
c9d2e0a2 1631
99a74c4a 1632 # The "new" style of producers have sane normalization and can support
1633 # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't
1634 # And we have to diff parsed SQL against parsed SQL.
1635 my $dest_schema = $sqlt_schema;
1636
1637 unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) {
1638 my $t = SQL::Translator->new($sqltargs);
1639 $t->debug( 0 );
1640 $t->trace( 0 );
1641 $t->parser( $db ) or die $t->error;
1642 $t = $self->configure_sqlt($t, $db);
1643 my $out = $t->translate( $filename ) or die $t->error;
1644 $dest_schema = $t->schema;
1645 $dest_schema->name( $filename )
1646 unless $dest_schema->name;
1647 }
1648
1649 my $diff = SQL::Translator::Diff::schema_diff($source_schema, $db,
1650 $dest_schema, $db,
1651 $sqltargs
1652 );
1653 if(!open $file, ">$difffile") {
1654 $self->throw_exception("Can't write to $difffile ($!)");
1655 next;
c9d2e0a2 1656 }
99a74c4a 1657 print $file $diff;
1658 close($file);
e673f011 1659 }
c9d2e0a2 1660}
e673f011 1661
c9d2e0a2 1662sub configure_sqlt() {
1663 my $self = shift;
1664 my $tr = shift;
1665 my $db = shift || $self->sqlt_type;
1666 if ($db eq 'PostgreSQL') {
1667 $tr->quote_table_names(0);
1668 $tr->quote_field_names(0);
1669 }
1670 return $tr;
e673f011 1671}
1672
9b83fccd 1673=head2 deployment_statements
1674
d3b0e369 1675=over 4
1676
1677=item Arguments: $schema, $type, $version, $directory, $sqlt_args
1678
1679=back
1680
1681Returns the statements used by L</deploy> and L<DBIx::Class::Schema/deploy>.
1682The database driver name is given by C<$type>, though the value from
1683L</sqlt_type> is used if it is not specified.
1684
1685C<$directory> is used to return statements from files in a previously created
1686L</create_ddl_dir> directory and is optional. The filenames are constructed
1687from L<DBIx::Class::Schema/ddl_filename>, the schema name and the C<$version>.
1688
1689If no C<$directory> is specified then the statements are constructed on the
1690fly using L<SQL::Translator> and C<$version> is ignored.
1691
1692See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>.
9b83fccd 1693
1694=cut
1695
e673f011 1696sub deployment_statements {
1697 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
915919c5 1698 # Need to be connected to get the correct sqlt_type
c377d939 1699 $self->ensure_connected() unless $type;
e673f011 1700 $type ||= $self->sqlt_type;
1701 $version ||= $schema->VERSION || '1.x';
1702 $dir ||= './';
c9d2e0a2 1703 my $filename = $schema->ddl_filename($type, $dir, $version);
1704 if(-f $filename)
1705 {
1706 my $file;
1707 open($file, "<$filename")
1708 or $self->throw_exception("Can't open $filename ($!)");
1709 my @rows = <$file>;
1710 close($file);
1711 return join('', @rows);
1712 }
1713
b6d9f089 1714 $self->throw_exception(q{Can't deploy without SQL::Translator 0.09: '}
40dce2a5 1715 . $self->_check_sqlt_message . q{'})
1716 if !$self->_check_sqlt_version;
1717
1718 require SQL::Translator::Parser::DBIx::Class;
1719 eval qq{use SQL::Translator::Producer::${type}};
1720 $self->throw_exception($@) if $@;
1721
1722 # sources needs to be a parser arg, but for simplicty allow at top level
1723 # coming in
1724 $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
1725 if exists $sqltargs->{sources};
1726
1727 my $tr = SQL::Translator->new(%$sqltargs);
1728 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
1729 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
1c339d71 1730}
843f8ecd 1731
1c339d71 1732sub deploy {
260129d8 1733 my ($self, $schema, $type, $sqltargs, $dir) = @_;
1734 foreach my $statement ( $self->deployment_statements($schema, $type, undef, $dir, { no_comments => 1, %{ $sqltargs || {} } } ) ) {
61bf0de5 1735 foreach my $line ( split(";\n", $statement)) {
1736 next if($line =~ /^--/);
1737 next if(!$line);
1738# next if($line =~ /^DROP/m);
1739 next if($line =~ /^BEGIN TRANSACTION/m);
1740 next if($line =~ /^COMMIT/m);
1741 next if $line =~ /^\s+$/; # skip whitespace only
e5d9ee92 1742 $self->_query_start($line);
61bf0de5 1743 eval {
1744 $self->dbh->do($line); # shouldn't be using ->dbh ?
1745 };
1746 if ($@) {
1747 warn qq{$@ (running "${line}")};
1748 }
e5d9ee92 1749 $self->_query_end($line);
e4fe9ba3 1750 }
75d07914 1751 }
1c339d71 1752}
843f8ecd 1753
9b83fccd 1754=head2 datetime_parser
1755
1756Returns the datetime parser class
1757
1758=cut
1759
f86fcf0d 1760sub datetime_parser {
1761 my $self = shift;
114780ee 1762 return $self->{datetime_parser} ||= do {
1763 $self->ensure_connected;
1764 $self->build_datetime_parser(@_);
1765 };
f86fcf0d 1766}
1767
9b83fccd 1768=head2 datetime_parser_type
1769
1770Defines (returns) the datetime parser class - currently hardwired to
1771L<DateTime::Format::MySQL>
1772
1773=cut
1774
f86fcf0d 1775sub datetime_parser_type { "DateTime::Format::MySQL"; }
1776
9b83fccd 1777=head2 build_datetime_parser
1778
1779See L</datetime_parser>
1780
1781=cut
1782
f86fcf0d 1783sub build_datetime_parser {
1784 my $self = shift;
1785 my $type = $self->datetime_parser_type(@_);
1786 eval "use ${type}";
1787 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1788 return $type;
1789}
1790
40dce2a5 1791{
1792 my $_check_sqlt_version; # private
1793 my $_check_sqlt_message; # private
1794 sub _check_sqlt_version {
1795 return $_check_sqlt_version if defined $_check_sqlt_version;
b6d9f089 1796 eval 'use SQL::Translator "0.09"';
b7e303a8 1797 $_check_sqlt_message = $@ || '';
1798 $_check_sqlt_version = !$@;
40dce2a5 1799 }
1800
1801 sub _check_sqlt_message {
1802 _check_sqlt_version if !defined $_check_sqlt_message;
1803 $_check_sqlt_message;
1804 }
1805}
1806
106d5f3b 1807=head2 is_replicating
1808
1809A boolean that reports if a particular L<DBIx::Class::Storage::DBI> is set to
1810replicate from a master database. Default is undef, which is the result
1811returned by databases that don't support replication.
1812
1813=cut
1814
1815sub is_replicating {
1816 return;
1817
1818}
1819
1820=head2 lag_behind_master
1821
1822Returns a number that represents a certain amount of lag behind a master db
1823when a given storage is replicating. The number is database dependent, but
1824starts at zero and increases with the amount of lag. Default in undef
1825
1826=cut
1827
1828sub lag_behind_master {
1829 return;
1830}
1831
c756145c 1832sub DESTROY {
1833 my $self = shift;
f5de3933 1834 return if !$self->_dbh;
c756145c 1835 $self->_verify_pid;
1836 $self->_dbh(undef);
1837}
92925617 1838
8b445e33 18391;
1840
92fe2181 1841=head1 USAGE NOTES
1842
1843=head2 DBIx::Class and AutoCommit
1844
1845DBIx::Class can do some wonderful magic with handling exceptions,
1846disconnections, and transactions when you use C<< AutoCommit => 1 >>
1847combined with C<txn_do> for transaction support.
1848
1849If you set C<< AutoCommit => 0 >> in your connect info, then you are always
1850in an assumed transaction between commits, and you're telling us you'd
1851like to manage that manually. A lot of the magic protections offered by
1852this module will go away. We can't protect you from exceptions due to database
1853disconnects because we don't know anything about how to restart your
1854transactions. You're on your own for handling all sorts of exceptional
1855cases if you choose the C<< AutoCommit => 0 >> path, just as you would
1856be with raw DBI.
1857
1858
9b83fccd 1859=head1 SQL METHODS
1860
1861The module defines a set of methods within the DBIC::SQL::Abstract
1862namespace. These build on L<SQL::Abstract::Limit> to provide the
1863SQL query functions.
1864
1865The following methods are extended:-
1866
1867=over 4
1868
1869=item delete
1870
1871=item insert
1872
1873=item select
1874
1875=item update
1876
1877=item limit_dialect
1878
2cc3a7be 1879See L</connect_info> for details.
1880For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1881
9b83fccd 1882=item quote_char
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 name_sep
1888
2cc3a7be 1889See L</connect_info> for details.
1890For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1891
9b83fccd 1892=back
1893
8b445e33 1894=head1 AUTHORS
1895
daec44b8 1896Matt S. Trout <mst@shadowcatsystems.co.uk>
8b445e33 1897
9f19b1d6 1898Andy Grundman <andy@hybridized.org>
1899
8b445e33 1900=head1 LICENSE
1901
1902You may distribute this code under the same terms as Perl itself.
1903
1904=cut