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