More descriptive error messages courtesy of Marc Espie
[dbsrgits/DBIx-Class-Historic.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
20a2c954 6use strict;
7use warnings;
8b445e33 8use DBI;
aeaf3ce2 9use SQL::Abstract::Limit;
28927b50 10use DBIx::Class::Storage::DBI::Cursor;
4c248161 11use DBIx::Class::Storage::Statistics;
92b858c9 12use IO::File;
701da8c4 13use Carp::Clan qw/DBIx::Class/;
bd7efd39 14BEGIN {
15
cb5f2eea 16package DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :(
bd7efd39 17
18use base qw/SQL::Abstract::Limit/;
19
2cc3a7be 20# This prevents the caching of $dbh in S::A::L, I believe
21sub new {
22 my $self = shift->SUPER::new(@_);
23
24 # If limit_dialect is a ref (like a $dbh), go ahead and replace
25 # it with what it resolves to:
26 $self->{limit_dialect} = $self->_find_syntax($self->{limit_dialect})
27 if ref $self->{limit_dialect};
28
29 $self;
30}
31
260129d8 32sub _RowNumberOver {
33 my ($self, $sql, $order, $rows, $offset ) = @_;
34
35 $offset += 1;
36 my $last = $rows + $offset;
37 my ( $order_by ) = $self->_order_by( $order );
38
39 $sql = <<"";
40SELECT * FROM
41(
42 SELECT Q1.*, ROW_NUMBER() OVER( ) AS ROW_NUM FROM (
43 $sql
44 $order_by
45 ) Q1
46) Q2
47WHERE ROW_NUM BETWEEN $offset AND $last
48
49 return $sql;
50}
51
52
2cc3a7be 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;
59# print STDERR "Found DBH $syntax >$dbhname< ", $syntax->{Driver}->{Name}, "\n";
260129d8 60 if(ref($self) && $dbhname && $dbhname eq 'DB2') {
61 return 'RowNumberOver';
62 }
63
2cc3a7be 64 $self->{_cached_syntax} ||= $self->SUPER::_find_syntax($syntax);
65}
66
54540863 67sub select {
68 my ($self, $table, $fields, $where, $order, @rest) = @_;
6346a152 69 $table = $self->_quote($table) unless ref($table);
eac29141 70 local $self->{rownum_hack_count} = 1
71 if (defined $rest[0] && $self->{limit_dialect} eq 'RowNum');
54540863 72 @rest = (-1) unless defined $rest[0];
0823196c 73 die "LIMIT 0 Does Not Compute" if $rest[0] == 0;
74 # and anyway, SQL::Abstract::Limit will cause a barf if we don't first
8839560b 75 local $self->{having_bind} = [];
bc0c9800 76 my ($sql, @ret) = $self->SUPER::select(
77 $table, $self->_recurse_fields($fields), $where, $order, @rest
78 );
8839560b 79 return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql;
54540863 80}
81
6346a152 82sub insert {
83 my $self = shift;
84 my $table = shift;
85 $table = $self->_quote($table) unless ref($table);
86 $self->SUPER::insert($table, @_);
87}
88
89sub update {
90 my $self = shift;
91 my $table = shift;
92 $table = $self->_quote($table) unless ref($table);
93 $self->SUPER::update($table, @_);
94}
95
96sub delete {
97 my $self = shift;
98 my $table = shift;
99 $table = $self->_quote($table) unless ref($table);
100 $self->SUPER::delete($table, @_);
101}
102
54540863 103sub _emulate_limit {
104 my $self = shift;
105 if ($_[3] == -1) {
106 return $_[1].$self->_order_by($_[2]);
107 } else {
108 return $self->SUPER::_emulate_limit(@_);
109 }
110}
111
112sub _recurse_fields {
113 my ($self, $fields) = @_;
114 my $ref = ref $fields;
115 return $self->_quote($fields) unless $ref;
116 return $$fields if $ref eq 'SCALAR';
117
118 if ($ref eq 'ARRAY') {
eac29141 119 return join(', ', map {
120 $self->_recurse_fields($_)
121 .(exists $self->{rownum_hack_count}
122 ? ' AS col'.$self->{rownum_hack_count}++
123 : '')
124 } @$fields);
54540863 125 } elsif ($ref eq 'HASH') {
126 foreach my $func (keys %$fields) {
127 return $self->_sqlcase($func)
128 .'( '.$self->_recurse_fields($fields->{$func}).' )';
129 }
130 }
131}
132
133sub _order_by {
134 my $self = shift;
135 my $ret = '';
8839560b 136 my @extra;
54540863 137 if (ref $_[0] eq 'HASH') {
138 if (defined $_[0]->{group_by}) {
139 $ret = $self->_sqlcase(' group by ')
140 .$self->_recurse_fields($_[0]->{group_by});
141 }
8839560b 142 if (defined $_[0]->{having}) {
143 my $frag;
144 ($frag, @extra) = $self->_recurse_where($_[0]->{having});
145 push(@{$self->{having_bind}}, @extra);
146 $ret .= $self->_sqlcase(' having ').$frag;
147 }
54540863 148 if (defined $_[0]->{order_by}) {
7ce5cbe7 149 $ret .= $self->_order_by($_[0]->{order_by});
54540863 150 }
d09c569a 151 } elsif (ref $_[0] eq 'SCALAR') {
e535069e 152 $ret = $self->_sqlcase(' order by ').${ $_[0] };
d09c569a 153 } elsif (ref $_[0] eq 'ARRAY' && @{$_[0]}) {
154 my @order = @{+shift};
155 $ret = $self->_sqlcase(' order by ')
156 .join(', ', map {
157 my $r = $self->_order_by($_, @_);
158 $r =~ s/^ ?ORDER BY //i;
159 $r;
160 } @order);
54540863 161 } else {
162 $ret = $self->SUPER::_order_by(@_);
163 }
164 return $ret;
165}
166
f48dd03f 167sub _order_directions {
168 my ($self, $order) = @_;
169 $order = $order->{order_by} if ref $order eq 'HASH';
170 return $self->SUPER::_order_directions($order);
171}
172
2a816814 173sub _table {
bd7efd39 174 my ($self, $from) = @_;
175 if (ref $from eq 'ARRAY') {
176 return $self->_recurse_from(@$from);
177 } elsif (ref $from eq 'HASH') {
178 return $self->_make_as($from);
179 } else {
6346a152 180 return $from; # would love to quote here but _table ends up getting called
181 # twice during an ->select without a limit clause due to
182 # the way S::A::Limit->select works. should maybe consider
183 # bypassing this and doing S::A::select($self, ...) in
184 # our select method above. meantime, quoting shims have
185 # been added to select/insert/update/delete here
bd7efd39 186 }
187}
188
189sub _recurse_from {
190 my ($self, $from, @join) = @_;
191 my @sqlf;
192 push(@sqlf, $self->_make_as($from));
193 foreach my $j (@join) {
194 my ($to, $on) = @$j;
73856587 195
54540863 196 # check whether a join type exists
197 my $join_clause = '';
ca7b9fdf 198 my $to_jt = ref($to) eq 'ARRAY' ? $to->[0] : $to;
199 if (ref($to_jt) eq 'HASH' and exists($to_jt->{-join_type})) {
200 $join_clause = ' '.uc($to_jt->{-join_type}).' JOIN ';
54540863 201 } else {
202 $join_clause = ' JOIN ';
203 }
73856587 204 push(@sqlf, $join_clause);
205
bd7efd39 206 if (ref $to eq 'ARRAY') {
207 push(@sqlf, '(', $self->_recurse_from(@$to), ')');
208 } else {
96cdbbab 209 push(@sqlf, $self->_make_as($to));
bd7efd39 210 }
211 push(@sqlf, ' ON ', $self->_join_condition($on));
212 }
213 return join('', @sqlf);
214}
215
216sub _make_as {
217 my ($self, $from) = @_;
54540863 218 return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ : $self->_quote($_)) }
bc0c9800 219 reverse each %{$self->_skip_options($from)});
73856587 220}
221
222sub _skip_options {
54540863 223 my ($self, $hash) = @_;
224 my $clean_hash = {};
225 $clean_hash->{$_} = $hash->{$_}
226 for grep {!/^-/} keys %$hash;
227 return $clean_hash;
bd7efd39 228}
229
230sub _join_condition {
231 my ($self, $cond) = @_;
5efe4c79 232 if (ref $cond eq 'HASH') {
233 my %j;
bc0c9800 234 for (keys %$cond) {
235 my $x = '= '.$self->_quote($cond->{$_}); $j{$_} = \$x;
236 };
5efe4c79 237 return $self->_recurse_where(\%j);
238 } elsif (ref $cond eq 'ARRAY') {
239 return join(' OR ', map { $self->_join_condition($_) } @$cond);
240 } else {
241 die "Can't handle this yet!";
242 }
bd7efd39 243}
244
2a816814 245sub _quote {
246 my ($self, $label) = @_;
247 return '' unless defined $label;
3b24f6ea 248 return "*" if $label eq '*';
41728a6e 249 return $label unless $self->{quote_char};
3b24f6ea 250 if(ref $self->{quote_char} eq "ARRAY"){
251 return $self->{quote_char}->[0] . $label . $self->{quote_char}->[1]
252 if !defined $self->{name_sep};
253 my $sep = $self->{name_sep};
254 return join($self->{name_sep},
255 map { $self->{quote_char}->[0] . $_ . $self->{quote_char}->[1] }
256 split(/\Q$sep\E/,$label));
257 }
2a816814 258 return $self->SUPER::_quote($label);
259}
260
7be93b07 261sub limit_dialect {
262 my $self = shift;
263 $self->{limit_dialect} = shift if @_;
264 return $self->{limit_dialect};
265}
266
2437a1e3 267sub quote_char {
268 my $self = shift;
269 $self->{quote_char} = shift if @_;
270 return $self->{quote_char};
271}
272
273sub name_sep {
274 my $self = shift;
275 $self->{name_sep} = shift if @_;
276 return $self->{name_sep};
277}
278
bd7efd39 279} # End of BEGIN block
280
8b445e33 281use base qw/DBIx::Class/;
282
1f692767 283__PACKAGE__->load_components(qw/AccessorGroup/);
8b445e33 284
223b8fe3 285__PACKAGE__->mk_group_accessors('simple' =>
2cc3a7be 286 qw/_connect_info _dbh _sql_maker _sql_maker_opts _conn_pid _conn_tid
287 debug debugobj cursor on_connect_do transaction_depth/);
8091aa91 288
b327f988 289=head1 NAME
290
291DBIx::Class::Storage::DBI - DBI storage handler
292
293=head1 SYNOPSIS
294
295=head1 DESCRIPTION
296
297This class represents the connection to the database
298
299=head1 METHODS
300
9b83fccd 301=head2 new
302
303=cut
304
8b445e33 305sub new {
04786a4c 306 my $new = {};
307 bless $new, (ref $_[0] || $_[0]);
308
28927b50 309 $new->cursor("DBIx::Class::Storage::DBI::Cursor");
d79f59b9 310 $new->transaction_depth(0);
4c248161 311
312 $new->debugobj(new DBIx::Class::Storage::Statistics());
313
314 my $fh;
6fe735fa 315
316 my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
317 || $ENV{DBIC_TRACE};
318
319 if (defined($debug_env) && ($debug_env =~ /=(.+)$/)) {
4c248161 320 $fh = IO::File->new($1, 'w')
bc0c9800 321 or $new->throw_exception("Cannot open trace file $1");
92b858c9 322 } else {
4c248161 323 $fh = IO::File->new('>&STDERR');
92b858c9 324 }
004d31fb 325 $new->debugfh($fh);
6fe735fa 326 $new->debug(1) if $debug_env;
2cc3a7be 327 $new->_sql_maker_opts({});
223b8fe3 328 return $new;
8b445e33 329}
330
9b83fccd 331=head2 throw_exception
332
333Throws an exception - croaks.
334
335=cut
336
1c339d71 337sub throw_exception {
338 my ($self, $msg) = @_;
3b042bcb 339 croak($msg);
1c339d71 340}
341
1b45b01e 342=head2 connect_info
343
bb4f246d 344The arguments of C<connect_info> are always a single array reference.
1b45b01e 345
bb4f246d 346This is normally accessed via L<DBIx::Class::Schema/connection>, which
347encapsulates its argument list in an arrayref before calling
348C<connect_info> here.
1b45b01e 349
bb4f246d 350The arrayref can either contain the same set of arguments one would
351normally pass to L<DBI/connect>, or a lone code reference which returns
352a connected database handle.
d7c4c15c 353
2cc3a7be 354In either case, if the final argument in your connect_info happens
355to be a hashref, C<connect_info> will look there for several
356connection-specific options:
357
358=over 4
359
360=item on_connect_do
361
362This can be set to an arrayref of literal sql statements, which will
363be executed immediately after making the connection to the database
364every time we [re-]connect.
365
366=item limit_dialect
367
368Sets the limit dialect. This is useful for JDBC-bridge among others
369where the remote SQL-dialect cannot be determined by the name of the
370driver alone.
371
372=item quote_char
d7c4c15c 373
2cc3a7be 374Specifies what characters to use to quote table and column names. If
375you use this you will want to specify L<name_sep> as well.
376
377quote_char expects either a single character, in which case is it is placed
378on either side of the table/column, or an arrayref of length 2 in which case the
379table/column name is placed between the elements.
380
381For example under MySQL you'd use C<quote_char =E<gt> '`'>, and user SQL Server you'd
382use C<quote_char =E<gt> [qw/[ ]/]>.
383
384=item name_sep
385
386This only needs to be used in conjunction with L<quote_char>, and is used to
387specify the charecter that seperates elements (schemas, tables, columns) from
388each other. In most cases this is simply a C<.>.
389
390=back
391
392These options can be mixed in with your other L<DBI> connection attributes,
393or placed in a seperate hashref after all other normal L<DBI> connection
394arguments.
395
396Every time C<connect_info> is invoked, any previous settings for
397these options will be cleared before setting the new ones, regardless of
398whether any options are specified in the new C<connect_info>.
399
400Examples:
401
402 # Simple SQLite connection
bb4f246d 403 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
6789ebe3 404
2cc3a7be 405 # Connect via subref
bb4f246d 406 ->connect_info([ sub { DBI->connect(...) } ]);
6789ebe3 407
2cc3a7be 408 # A bit more complicated
bb4f246d 409 ->connect_info(
410 [
411 'dbi:Pg:dbname=foo',
412 'postgres',
413 'my_pg_password',
414 { AutoCommit => 0 },
2cc3a7be 415 { quote_char => q{"}, name_sep => q{.} },
416 ]
417 );
418
419 # Equivalent to the previous example
420 ->connect_info(
421 [
422 'dbi:Pg:dbname=foo',
423 'postgres',
424 'my_pg_password',
425 { AutoCommit => 0, quote_char => q{"}, name_sep => q{.} },
bb4f246d 426 ]
427 );
6789ebe3 428
2cc3a7be 429 # Subref + DBIC-specific connection options
bb4f246d 430 ->connect_info(
431 [
432 sub { DBI->connect(...) },
2cc3a7be 433 {
434 quote_char => q{`},
435 name_sep => q{@},
436 on_connect_do => ['SET search_path TO myschema,otherschema,public'],
437 },
bb4f246d 438 ]
439 );
6789ebe3 440
bb4f246d 441=head2 on_connect_do
6789ebe3 442
2cc3a7be 443This method is deprecated in favor of setting via L</connect_info>.
6789ebe3 444
92b858c9 445=head2 debug
446
4c248161 447Causes SQL trace information to be emitted on the C<debugobj> object.
448(or C<STDERR> if C<debugobj> has not specifically been set).
92b858c9 449
f7a90adc 450This is the equivalent to setting L</DBIC_TRACE> in your
451shell environment.
452
92b858c9 453=head2 debugfh
454
4c248161 455Set or retrieve the filehandle used for trace/debug output. This should be
456an IO::Handle compatible ojbect (only the C<print> method is used. Initially
457set to be STDERR - although see information on the
6fe735fa 458L<DBIC_TRACE> environment variable.
92b858c9 459
004d31fb 460=cut
461
462sub debugfh {
463 my $self = shift;
464
465 if ($self->debugobj->can('debugfh')) {
466 return $self->debugobj->debugfh(@_);
467 }
468}
469
4c248161 470=head2 debugobj
471
472Sets or retrieves the object used for metric collection. Defaults to an instance
473of L<DBIx::Class::Storage::Statistics> that is campatible with the original
474method of using a coderef as a callback. See the aforementioned Statistics
475class for more information.
476
486ad69b 477=head2 debugcb
478
479Sets a callback to be executed each time a statement is run; takes a sub
4c248161 480reference. Callback is executed as $sub->($op, $info) where $op is
481SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
486ad69b 482
4c248161 483See L<debugobj> for a better way.
d7c4c15c 484
4c248161 485=cut
004d31fb 486
486ad69b 487sub debugcb {
004d31fb 488 my $self = shift;
4c248161 489
004d31fb 490 if ($self->debugobj->can('callback')) {
491 return $self->debugobj->callback(@_);
4c248161 492 }
486ad69b 493}
494
9b83fccd 495=head2 disconnect
496
497Disconnect the L<DBI> handle, performing a rollback first if the
498database is not in C<AutoCommit> mode.
499
500=cut
501
412db1f4 502sub disconnect {
503 my ($self) = @_;
504
92925617 505 if( $self->connected ) {
506 $self->_dbh->rollback unless $self->_dbh->{AutoCommit};
507 $self->_dbh->disconnect;
508 $self->_dbh(undef);
509 }
412db1f4 510}
511
9b83fccd 512=head2 connected
513
514Check if the L<DBI> handle is connected. Returns true if the handle
515is connected.
516
517=cut
518
519sub connected { my ($self) = @_;
412db1f4 520
1346e22d 521 if(my $dbh = $self->_dbh) {
522 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
1346e22d 523 return $self->_dbh(undef);
524 }
525 elsif($self->_conn_pid != $$) {
526 $self->_dbh->{InactiveDestroy} = 1;
2cc3a7be 527 return $self->_dbh(undef);
1346e22d 528 }
529 return ($dbh->FETCH('Active') && $dbh->ping);
530 }
531
532 return 0;
412db1f4 533}
534
9b83fccd 535=head2 ensure_connected
536
537Check whether the database handle is connected - if not then make a
538connection.
539
540=cut
541
412db1f4 542sub ensure_connected {
543 my ($self) = @_;
544
545 unless ($self->connected) {
8b445e33 546 $self->_populate_dbh;
547 }
412db1f4 548}
549
c235bbae 550=head2 dbh
551
552Returns the dbh - a data base handle of class L<DBI>.
553
554=cut
555
412db1f4 556sub dbh {
557 my ($self) = @_;
558
559 $self->ensure_connected;
8b445e33 560 return $self->_dbh;
561}
562
f1f56aad 563sub _sql_maker_args {
564 my ($self) = @_;
565
2cc3a7be 566 return ( limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
f1f56aad 567}
568
9b83fccd 569=head2 sql_maker
570
571Returns a C<sql_maker> object - normally an object of class
572C<DBIC::SQL::Abstract>.
573
574=cut
575
48c69e7c 576sub sql_maker {
577 my ($self) = @_;
fdc1c3d0 578 unless ($self->_sql_maker) {
f1f56aad 579 $self->_sql_maker(new DBIC::SQL::Abstract( $self->_sql_maker_args ));
48c69e7c 580 }
581 return $self->_sql_maker;
582}
583
1b45b01e 584sub connect_info {
bb4f246d 585 my ($self, $info_arg) = @_;
586
587 if($info_arg) {
2cc3a7be 588 # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
589 # the new set of options
590 $self->_sql_maker(undef);
591 $self->_sql_maker_opts({});
592
bb4f246d 593 my $info = [ @$info_arg ]; # copy because we can alter it
594 my $last_info = $info->[-1];
595 if(ref $last_info eq 'HASH') {
2cc3a7be 596 if(my $on_connect_do = delete $last_info->{on_connect_do}) {
bb4f246d 597 $self->on_connect_do($on_connect_do);
598 }
599 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
2cc3a7be 600 if(my $opt_val = delete $last_info->{$sql_maker_opt}) {
601 $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
1b45b01e 602 }
bb4f246d 603 }
1b45b01e 604
2cc3a7be 605 # Get rid of any trailing empty hashref
606 pop(@$info) if !keys %$last_info;
1b45b01e 607 }
608
bb4f246d 609 $self->_connect_info($info);
610 }
611
612 $self->_connect_info;
1b45b01e 613}
614
8b445e33 615sub _populate_dbh {
616 my ($self) = @_;
1b45b01e 617 my @info = @{$self->_connect_info || []};
8b445e33 618 $self->_dbh($self->_connect(@info));
2fd24e78 619
620 if(ref $self eq 'DBIx::Class::Storage::DBI') {
621 my $driver = $self->_dbh->{Driver}->{Name};
efe6365b 622 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
2fd24e78 623 bless $self, "DBIx::Class::Storage::DBI::${driver}";
624 $self->_rebless() if $self->can('_rebless');
625 }
843f8ecd 626 }
2fd24e78 627
d7c4c15c 628 # if on-connect sql statements are given execute them
629 foreach my $sql_statement (@{$self->on_connect_do || []}) {
4c248161 630 $self->debugobj->query_start($sql_statement) if $self->debug();
d7c4c15c 631 $self->_dbh->do($sql_statement);
4c248161 632 $self->debugobj->query_end($sql_statement) if $self->debug();
d7c4c15c 633 }
5ef3e508 634
1346e22d 635 $self->_conn_pid($$);
636 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
8b445e33 637}
638
639sub _connect {
640 my ($self, @info) = @_;
5ef3e508 641
9d31f7dc 642 $self->throw_exception("You failed to provide any connection info")
643 if !@info;
644
90ec6cad 645 my ($old_connect_via, $dbh);
646
5ef3e508 647 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
90ec6cad 648 $old_connect_via = $DBI::connect_via;
5ef3e508 649 $DBI::connect_via = 'connect';
5ef3e508 650 }
651
75db246c 652 eval {
bb4f246d 653 $dbh = ref $info[0] eq 'CODE'
654 ? &{$info[0]}
655 : DBI->connect(@info);
75db246c 656 };
90ec6cad 657
658 $DBI::connect_via = $old_connect_via if $old_connect_via;
659
75db246c 660 if (!$dbh || $@) {
661 $self->throw_exception("DBI Connection failed: " . ($@ || $DBI::errstr));
662 }
90ec6cad 663
e571e823 664 $dbh;
8b445e33 665}
666
8091aa91 667=head2 txn_begin
8b445e33 668
8091aa91 669Calls begin_work on the current dbh.
8b445e33 670
181a28f4 671See L<DBIx::Class::Schema> for the txn_do() method, which allows for
672an entire code block to be executed transactionally.
673
8b445e33 674=cut
675
8091aa91 676sub txn_begin {
d79f59b9 677 my $self = shift;
a32e8402 678 if ($self->{transaction_depth}++ == 0) {
679 my $dbh = $self->dbh;
680 if ($dbh->{AutoCommit}) {
4c248161 681 $self->debugobj->txn_begin()
a32e8402 682 if ($self->debug);
683 $dbh->begin_work;
684 }
986e4fca 685 }
8091aa91 686}
8b445e33 687
8091aa91 688=head2 txn_commit
8b445e33 689
8091aa91 690Issues a commit against the current dbh.
8b445e33 691
8091aa91 692=cut
693
694sub txn_commit {
d79f59b9 695 my $self = shift;
7c5a8b60 696 my $dbh = $self->dbh;
d79f59b9 697 if ($self->{transaction_depth} == 0) {
a32e8402 698 unless ($dbh->{AutoCommit}) {
4c248161 699 $self->debugobj->txn_commit()
986e4fca 700 if ($self->debug);
a32e8402 701 $dbh->commit;
986e4fca 702 }
8091aa91 703 }
704 else {
986e4fca 705 if (--$self->{transaction_depth} == 0) {
4c248161 706 $self->debugobj->txn_commit()
986e4fca 707 if ($self->debug);
7c5a8b60 708 $dbh->commit;
986e4fca 709 }
8091aa91 710 }
711}
712
713=head2 txn_rollback
714
181a28f4 715Issues a rollback against the current dbh. A nested rollback will
716throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
717which allows the rollback to propagate to the outermost transaction.
8b445e33 718
719=cut
720
8091aa91 721sub txn_rollback {
d79f59b9 722 my $self = shift;
a62cf8d4 723
724 eval {
7c5a8b60 725 my $dbh = $self->dbh;
a62cf8d4 726 if ($self->{transaction_depth} == 0) {
a32e8402 727 unless ($dbh->{AutoCommit}) {
4c248161 728 $self->debugobj->txn_rollback()
986e4fca 729 if ($self->debug);
a32e8402 730 $dbh->rollback;
986e4fca 731 }
a62cf8d4 732 }
733 else {
986e4fca 734 if (--$self->{transaction_depth} == 0) {
4c248161 735 $self->debugobj->txn_rollback()
986e4fca 736 if ($self->debug);
7c5a8b60 737 $dbh->rollback;
986e4fca 738 }
739 else {
1346e22d 740 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
986e4fca 741 }
a62cf8d4 742 }
743 };
744
745 if ($@) {
746 my $error = $@;
747 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
748 $error =~ /$exception_class/ and $self->throw_exception($error);
749 $self->{transaction_depth} = 0; # ensure that a failed rollback
750 $self->throw_exception($error); # resets the transaction depth
8091aa91 751 }
752}
8b445e33 753
223b8fe3 754sub _execute {
755 my ($self, $op, $extra_bind, $ident, @args) = @_;
756 my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
944f30bf 757 unshift(@bind, @$extra_bind) if $extra_bind;
f59ffc79 758 if ($self->debug) {
e673f011 759 my @debug_bind = map { defined $_ ? qq{'$_'} : q{'NULL'} } @bind;
4c248161 760 $self->debugobj->query_start($sql, @debug_bind);
f59ffc79 761 }
75db246c 762 my $sth = eval { $self->sth($sql,$op) };
763
764 if (!$sth || $@) {
ec0ff6f6 765 $self->throw_exception(
766 'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
767 );
75db246c 768 }
438adc0e 769 @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
701da8c4 770 my $rv;
75d07914 771 if ($sth) {
4c248161 772 my $time = time();
95dad7e2 773 $rv = eval { $sth->execute(@bind) };
774
775 if ($@ || !$rv) {
776 $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr));
777 }
75d07914 778 } else {
1c339d71 779 $self->throw_exception("'$sql' did not generate a statement.");
701da8c4 780 }
4c248161 781 if ($self->debug) {
758272ec 782 my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
4c248161 783 $self->debugobj->query_end($sql, @debug_bind);
784 }
223b8fe3 785 return (wantarray ? ($rv, $sth, @bind) : $rv);
786}
787
8b445e33 788sub insert {
789 my ($self, $ident, $to_insert) = @_;
bc0c9800 790 $self->throw_exception(
791 "Couldn't insert ".join(', ',
792 map "$_ => $to_insert->{$_}", keys %$to_insert
793 )." into ${ident}"
794 ) unless ($self->_execute('insert' => [], $ident, $to_insert));
8b445e33 795 return $to_insert;
796}
797
798sub update {
223b8fe3 799 return shift->_execute('update' => [], @_);
8b445e33 800}
801
802sub delete {
223b8fe3 803 return shift->_execute('delete' => [], @_);
8b445e33 804}
805
de705b51 806sub _select {
8b445e33 807 my ($self, $ident, $select, $condition, $attrs) = @_;
223b8fe3 808 my $order = $attrs->{order_by};
809 if (ref $condition eq 'SCALAR') {
810 $order = $1 if $$condition =~ s/ORDER BY (.*)$//i;
811 }
8839560b 812 if (exists $attrs->{group_by} || $attrs->{having}) {
bc0c9800 813 $order = {
814 group_by => $attrs->{group_by},
815 having => $attrs->{having},
816 ($order ? (order_by => $order) : ())
817 };
54540863 818 }
5c91499f 819 my @args = ('select', $attrs->{bind}, $ident, $select, $condition, $order);
9229f20a 820 if ($attrs->{software_limit} ||
821 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
822 $attrs->{software_limit} = 1;
5c91499f 823 } else {
0823196c 824 $self->throw_exception("rows attribute must be positive if present")
825 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
5c91499f 826 push @args, $attrs->{rows}, $attrs->{offset};
827 }
de705b51 828 return $self->_execute(@args);
829}
830
9b83fccd 831=head2 select
832
d3b0e369 833=over 4
834
835=item Arguments: $ident, $select, $condition, $attrs
836
837=back
838
9b83fccd 839Handle a SQL select statement.
840
841=cut
842
de705b51 843sub select {
844 my $self = shift;
845 my ($ident, $select, $condition, $attrs) = @_;
cb5f2eea 846 return $self->cursor->new($self, \@_, $attrs);
8b445e33 847}
848
9b83fccd 849=head2 select_single
850
851Performs a select, fetch and return of data - handles a single row
852only.
853
854=cut
855
6157db4f 856# Need to call finish() to work round broken DBDs
857
1a14aa3f 858sub select_single {
de705b51 859 my $self = shift;
860 my ($rv, $sth, @bind) = $self->_select(@_);
6157db4f 861 my @row = $sth->fetchrow_array;
862 $sth->finish();
863 return @row;
1a14aa3f 864}
865
9b83fccd 866=head2 sth
867
d3b0e369 868=over 4
869
870=item Arguments: $sql
871
872=back
873
9b83fccd 874Returns a L<DBI> sth (statement handle) for the supplied SQL.
875
876=cut
877
8b445e33 878sub sth {
cb5f2eea 879 my ($self, $sql) = @_;
91fa659e 880 # 3 is the if_active parameter which avoids active sth re-use
881 return $self->dbh->prepare_cached($sql, {}, 3);
8b445e33 882}
883
a953d8d9 884=head2 columns_info_for
885
d3b0e369 886Returns database type info for a given table column.
a953d8d9 887
888=cut
889
890sub columns_info_for {
0d67fe74 891 my ($self, $table) = @_;
bfe10d87 892
a32e8402 893 my $dbh = $self->dbh;
894
895 if ($dbh->can('column_info')) {
a953d8d9 896 my %result;
955f1590 897 local $dbh->{RaiseError} = 1;
898 local $dbh->{PrintError} = 0;
0d67fe74 899 eval {
4d272ce5 900 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
901 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
0d67fe74 902 $sth->execute();
099049b5 903
0d67fe74 904 while ( my $info = $sth->fetchrow_hashref() ){
bfe10d87 905 my %column_info;
0d67fe74 906 $column_info{data_type} = $info->{TYPE_NAME};
907 $column_info{size} = $info->{COLUMN_SIZE};
908 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
909 $column_info{default_value} = $info->{COLUMN_DEF};
0b88a5bb 910 my $col_name = $info->{COLUMN_NAME};
911 $col_name =~ s/^\"(.*)\"$/$1/;
0d67fe74 912
0b88a5bb 913 $result{$col_name} = \%column_info;
0d67fe74 914 }
915 };
093fc7a6 916 return \%result if !$@ && scalar keys %result;
0d67fe74 917 }
918
919 my %result;
a32e8402 920 my $sth = $dbh->prepare("SELECT * FROM $table WHERE 1=0");
0d67fe74 921 $sth->execute;
922 my @columns = @{$sth->{NAME_lc}};
923 for my $i ( 0 .. $#columns ){
924 my %column_info;
925 my $type_num = $sth->{TYPE}->[$i];
926 my $type_name;
a32e8402 927 if(defined $type_num && $dbh->can('type_info')) {
928 my $type_info = $dbh->type_info($type_num);
0d67fe74 929 $type_name = $type_info->{TYPE_NAME} if $type_info;
a953d8d9 930 }
0d67fe74 931 $column_info{data_type} = $type_name ? $type_name : $type_num;
932 $column_info{size} = $sth->{PRECISION}->[$i];
933 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
934
935 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
936 $column_info{data_type} = $1;
937 $column_info{size} = $2;
938 }
939
940 $result{$columns[$i]} = \%column_info;
941 }
bfe10d87 942
0d67fe74 943 return \%result;
a953d8d9 944}
945
9b83fccd 946=head2 last_insert_id
947
948Return the row id of the last insert.
949
950=cut
951
843f8ecd 952sub last_insert_id {
953 my ($self, $row) = @_;
954
955 return $self->dbh->func('last_insert_rowid');
956
957}
958
9b83fccd 959=head2 sqlt_type
960
961Returns the database driver name.
962
963=cut
964
90ec6cad 965sub sqlt_type { shift->dbh->{Driver}->{Name} }
1c339d71 966
9b83fccd 967=head2 create_ddl_dir (EXPERIMENTAL)
968
969=over 4
970
971=item Arguments: $schema \@databases, $version, $directory, $sqlt_args
972
973=back
974
d3b0e369 975Creates a SQL file based on the Schema, for each of the specified
9b83fccd 976database types, in the given directory.
977
978Note that this feature is currently EXPERIMENTAL and may not work correctly
979across all databases, or fully handle complex relationships.
980
981=cut
982
e673f011 983sub create_ddl_dir
984{
985 my ($self, $schema, $databases, $version, $dir, $sqltargs) = @_;
986
987 if(!$dir || !-d $dir)
988 {
989 warn "No directory given, using ./\n";
990 $dir = "./";
991 }
992 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
993 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
994 $version ||= $schema->VERSION || '1.x';
9e7b9292 995 $sqltargs = { ( add_drop_table => 1 ), %{$sqltargs || {}} };
e673f011 996
1c339d71 997 eval "use SQL::Translator";
998 $self->throw_exception("Can't deploy without SQL::Translator: $@") if $@;
e673f011 999
9e7b9292 1000 my $sqlt = SQL::Translator->new($sqltargs);
e673f011 1001 foreach my $db (@$databases)
1002 {
1003 $sqlt->reset();
1004 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
1005# $sqlt->parser_args({'DBIx::Class' => $schema);
1006 $sqlt->data($schema);
1007 $sqlt->producer($db);
1008
1009 my $file;
1010 my $filename = $schema->ddl_filename($db, $dir, $version);
1011 if(-e $filename)
1012 {
1013 $self->throw_exception("$filename already exists, skipping $db");
1014 next;
1015 }
1016 open($file, ">$filename")
1017 or $self->throw_exception("Can't open $filename for writing ($!)");
1018 my $output = $sqlt->translate;
1019#use Data::Dumper;
1020# print join(":", keys %{$schema->source_registrations});
1021# print Dumper($sqlt->schema);
1022 if(!$output)
1023 {
1024 $self->throw_exception("Failed to translate to $db. (" . $sqlt->error . ")");
1025 next;
1026 }
1027 print $file $output;
1028 close($file);
1029 }
1030
1031}
1032
9b83fccd 1033=head2 deployment_statements
1034
d3b0e369 1035=over 4
1036
1037=item Arguments: $schema, $type, $version, $directory, $sqlt_args
1038
1039=back
1040
1041Returns the statements used by L</deploy> and L<DBIx::Class::Schema/deploy>.
1042The database driver name is given by C<$type>, though the value from
1043L</sqlt_type> is used if it is not specified.
1044
1045C<$directory> is used to return statements from files in a previously created
1046L</create_ddl_dir> directory and is optional. The filenames are constructed
1047from L<DBIx::Class::Schema/ddl_filename>, the schema name and the C<$version>.
1048
1049If no C<$directory> is specified then the statements are constructed on the
1050fly using L<SQL::Translator> and C<$version> is ignored.
1051
1052See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>.
9b83fccd 1053
1054=cut
1055
e673f011 1056sub deployment_statements {
1057 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
915919c5 1058 # Need to be connected to get the correct sqlt_type
c377d939 1059 $self->ensure_connected() unless $type;
e673f011 1060 $type ||= $self->sqlt_type;
1061 $version ||= $schema->VERSION || '1.x';
1062 $dir ||= './';
0382d607 1063 eval "use SQL::Translator";
1064 if(!$@)
1065 {
1066 eval "use SQL::Translator::Parser::DBIx::Class;";
1067 $self->throw_exception($@) if $@;
1068 eval "use SQL::Translator::Producer::${type};";
1069 $self->throw_exception($@) if $@;
1070 my $tr = SQL::Translator->new(%$sqltargs);
1071 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
1072 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
1073 }
e673f011 1074
1075 my $filename = $schema->ddl_filename($type, $dir, $version);
1076 if(!-f $filename)
1077 {
0382d607 1078# $schema->create_ddl_dir([ $type ], $version, $dir, $sqltargs);
1079 $self->throw_exception("No SQL::Translator, and no Schema file found, aborting deploy");
1080 return;
e673f011 1081 }
1082 my $file;
1083 open($file, "<$filename")
1084 or $self->throw_exception("Can't open $filename ($!)");
1085 my @rows = <$file>;
1086 close($file);
1087
1088 return join('', @rows);
1089
1c339d71 1090}
843f8ecd 1091
9b83fccd 1092=head2 deploy
1093
1094Sends the appropriate statements to create or modify tables to the
1095db. This would normally be called through
1096L<DBIx::Class::Schema/deploy>.
1097
1098=cut
1099
1c339d71 1100sub deploy {
260129d8 1101 my ($self, $schema, $type, $sqltargs, $dir) = @_;
ae9a0fa0 1102 foreach my $statement ( $self->deployment_statements($schema, $type, undef, $dir, { no_comments => 1, %{ $sqltargs || {} } } ) ) {
1103 for ( split(";\n", $statement)) {
1104 next if($_ =~ /^--/);
1105 next if(!$_);
1106# next if($_ =~ /^DROP/m);
e673f011 1107 next if($_ =~ /^BEGIN TRANSACTION/m);
1108 next if($_ =~ /^COMMIT/m);
ae9a0fa0 1109 next if $_ =~ /^\s+$/; # skip whitespace only
bdea30e3 1110 $self->debugobj->query_start($_) if $self->debug;
e4fe9ba3 1111 $self->dbh->do($_) or warn "SQL was:\n $_";
4c248161 1112 $self->debugobj->query_end($_) if $self->debug;
ae9a0fa0 1113 }
75d07914 1114 }
1c339d71 1115}
843f8ecd 1116
9b83fccd 1117=head2 datetime_parser
1118
1119Returns the datetime parser class
1120
1121=cut
1122
f86fcf0d 1123sub datetime_parser {
1124 my $self = shift;
1125 return $self->{datetime_parser} ||= $self->build_datetime_parser(@_);
1126}
1127
9b83fccd 1128=head2 datetime_parser_type
1129
1130Defines (returns) the datetime parser class - currently hardwired to
1131L<DateTime::Format::MySQL>
1132
1133=cut
1134
f86fcf0d 1135sub datetime_parser_type { "DateTime::Format::MySQL"; }
1136
9b83fccd 1137=head2 build_datetime_parser
1138
1139See L</datetime_parser>
1140
1141=cut
1142
f86fcf0d 1143sub build_datetime_parser {
1144 my $self = shift;
1145 my $type = $self->datetime_parser_type(@_);
1146 eval "use ${type}";
1147 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1148 return $type;
1149}
1150
89d794d4 1151sub DESTROY {
1152 # NOTE: if there's a merge conflict here when -current is pushed
1153 # back to trunk, take -current's version and ignore this trunk one :)
1154 my $self = shift;
1155
1156 if($self->_dbh && $self->_conn_pid != $$) {
1157 $self->_dbh->{InactiveDestroy} = 1;
1158 }
1159
1160 $self->_dbh(undef);
1161}
92925617 1162
8b445e33 11631;
1164
9b83fccd 1165=head1 SQL METHODS
1166
1167The module defines a set of methods within the DBIC::SQL::Abstract
1168namespace. These build on L<SQL::Abstract::Limit> to provide the
1169SQL query functions.
1170
1171The following methods are extended:-
1172
1173=over 4
1174
1175=item delete
1176
1177=item insert
1178
1179=item select
1180
1181=item update
1182
1183=item limit_dialect
1184
2cc3a7be 1185See L</connect_info> for details.
1186For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1187
9b83fccd 1188=item quote_char
1189
2cc3a7be 1190See L</connect_info> for details.
1191For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1192
9b83fccd 1193=item name_sep
1194
2cc3a7be 1195See L</connect_info> for details.
1196For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1197
9b83fccd 1198=back
1199
92b858c9 1200=head1 ENVIRONMENT VARIABLES
1201
6fe735fa 1202=head2 DBIC_TRACE
92b858c9 1203
6fe735fa 1204If C<DBIC_TRACE> is set then SQL trace information
92b858c9 1205is produced (as when the L<debug> method is set).
1206
1207If the value is of the form C<1=/path/name> then the trace output is
1208written to the file C</path/name>.
1209
d1cceec4 1210This environment variable is checked when the storage object is first
1211created (when you call connect on your schema). So, run-time changes
1212to this environment variable will not take effect unless you also
1213re-connect on your schema.
1214
6fe735fa 1215=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
1216
1217Old name for DBIC_TRACE
1218
8b445e33 1219=head1 AUTHORS
1220
daec44b8 1221Matt S. Trout <mst@shadowcatsystems.co.uk>
8b445e33 1222
9f19b1d6 1223Andy Grundman <andy@hybridized.org>
1224
8b445e33 1225=head1 LICENSE
1226
1227You may distribute this code under the same terms as Perl itself.
1228
1229=cut