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