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