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