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