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