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