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