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