NoBindVars + Sybase + MSSQL stuff
[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));
2fd24e78 501
502 if(ref $self eq 'DBIx::Class::Storage::DBI') {
503 my $driver = $self->_dbh->{Driver}->{Name};
504 eval "require DBIx::Class::Storage::DBI::${driver}";
505 unless ($@) {
506 bless $self, "DBIx::Class::Storage::DBI::${driver}";
507 $self->_rebless() if $self->can('_rebless');
508 }
843f8ecd 509 }
2fd24e78 510
d7c4c15c 511 # if on-connect sql statements are given execute them
512 foreach my $sql_statement (@{$self->on_connect_do || []}) {
4c248161 513 $self->debugobj->query_start($sql_statement) if $self->debug();
d7c4c15c 514 $self->_dbh->do($sql_statement);
4c248161 515 $self->debugobj->query_end($sql_statement) if $self->debug();
d7c4c15c 516 }
5ef3e508 517
1346e22d 518 $self->_conn_pid($$);
519 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
8b445e33 520}
521
522sub _connect {
523 my ($self, @info) = @_;
5ef3e508 524
9d31f7dc 525 $self->throw_exception("You failed to provide any connection info")
526 if !@info;
527
90ec6cad 528 my ($old_connect_via, $dbh);
529
5ef3e508 530 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
90ec6cad 531 $old_connect_via = $DBI::connect_via;
5ef3e508 532 $DBI::connect_via = 'connect';
5ef3e508 533 }
534
75db246c 535 eval {
bb4f246d 536 $dbh = ref $info[0] eq 'CODE'
537 ? &{$info[0]}
538 : DBI->connect(@info);
75db246c 539 };
90ec6cad 540
541 $DBI::connect_via = $old_connect_via if $old_connect_via;
542
75db246c 543 if (!$dbh || $@) {
544 $self->throw_exception("DBI Connection failed: " . ($@ || $DBI::errstr));
545 }
90ec6cad 546
e571e823 547 $dbh;
8b445e33 548}
549
8091aa91 550=head2 txn_begin
8b445e33 551
8091aa91 552Calls begin_work on the current dbh.
8b445e33 553
181a28f4 554See L<DBIx::Class::Schema> for the txn_do() method, which allows for
555an entire code block to be executed transactionally.
556
8b445e33 557=cut
558
8091aa91 559sub txn_begin {
d79f59b9 560 my $self = shift;
a32e8402 561 if ($self->{transaction_depth}++ == 0) {
562 my $dbh = $self->dbh;
563 if ($dbh->{AutoCommit}) {
4c248161 564 $self->debugobj->txn_begin()
a32e8402 565 if ($self->debug);
566 $dbh->begin_work;
567 }
986e4fca 568 }
8091aa91 569}
8b445e33 570
8091aa91 571=head2 txn_commit
8b445e33 572
8091aa91 573Issues a commit against the current dbh.
8b445e33 574
8091aa91 575=cut
576
577sub txn_commit {
d79f59b9 578 my $self = shift;
7c5a8b60 579 my $dbh = $self->dbh;
d79f59b9 580 if ($self->{transaction_depth} == 0) {
a32e8402 581 unless ($dbh->{AutoCommit}) {
4c248161 582 $self->debugobj->txn_commit()
986e4fca 583 if ($self->debug);
a32e8402 584 $dbh->commit;
986e4fca 585 }
8091aa91 586 }
587 else {
986e4fca 588 if (--$self->{transaction_depth} == 0) {
4c248161 589 $self->debugobj->txn_commit()
986e4fca 590 if ($self->debug);
7c5a8b60 591 $dbh->commit;
986e4fca 592 }
8091aa91 593 }
594}
595
596=head2 txn_rollback
597
181a28f4 598Issues a rollback against the current dbh. A nested rollback will
599throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
600which allows the rollback to propagate to the outermost transaction.
8b445e33 601
602=cut
603
8091aa91 604sub txn_rollback {
d79f59b9 605 my $self = shift;
a62cf8d4 606
607 eval {
7c5a8b60 608 my $dbh = $self->dbh;
a62cf8d4 609 if ($self->{transaction_depth} == 0) {
a32e8402 610 unless ($dbh->{AutoCommit}) {
4c248161 611 $self->debugobj->txn_rollback()
986e4fca 612 if ($self->debug);
a32e8402 613 $dbh->rollback;
986e4fca 614 }
a62cf8d4 615 }
616 else {
986e4fca 617 if (--$self->{transaction_depth} == 0) {
4c248161 618 $self->debugobj->txn_rollback()
986e4fca 619 if ($self->debug);
7c5a8b60 620 $dbh->rollback;
986e4fca 621 }
622 else {
1346e22d 623 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
986e4fca 624 }
a62cf8d4 625 }
626 };
627
628 if ($@) {
629 my $error = $@;
630 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
631 $error =~ /$exception_class/ and $self->throw_exception($error);
632 $self->{transaction_depth} = 0; # ensure that a failed rollback
633 $self->throw_exception($error); # resets the transaction depth
8091aa91 634 }
635}
8b445e33 636
223b8fe3 637sub _execute {
638 my ($self, $op, $extra_bind, $ident, @args) = @_;
639 my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
944f30bf 640 unshift(@bind, @$extra_bind) if $extra_bind;
f59ffc79 641 if ($self->debug) {
e673f011 642 my @debug_bind = map { defined $_ ? qq{'$_'} : q{'NULL'} } @bind;
4c248161 643 $self->debugobj->query_start($sql, @debug_bind);
f59ffc79 644 }
75db246c 645 my $sth = eval { $self->sth($sql,$op) };
646
647 if (!$sth || $@) {
ec0ff6f6 648 $self->throw_exception(
649 'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
650 );
75db246c 651 }
438adc0e 652 @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
701da8c4 653 my $rv;
75d07914 654 if ($sth) {
4c248161 655 my $time = time();
95dad7e2 656 $rv = eval { $sth->execute(@bind) };
657
658 if ($@ || !$rv) {
659 $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr));
660 }
75d07914 661 } else {
1c339d71 662 $self->throw_exception("'$sql' did not generate a statement.");
701da8c4 663 }
4c248161 664 if ($self->debug) {
665 my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
666 $self->debugobj->query_end($sql, @debug_bind);
667 }
223b8fe3 668 return (wantarray ? ($rv, $sth, @bind) : $rv);
669}
670
8b445e33 671sub insert {
672 my ($self, $ident, $to_insert) = @_;
bc0c9800 673 $self->throw_exception(
674 "Couldn't insert ".join(', ',
675 map "$_ => $to_insert->{$_}", keys %$to_insert
676 )." into ${ident}"
677 ) unless ($self->_execute('insert' => [], $ident, $to_insert));
8b445e33 678 return $to_insert;
679}
680
681sub update {
223b8fe3 682 return shift->_execute('update' => [], @_);
8b445e33 683}
684
685sub delete {
223b8fe3 686 return shift->_execute('delete' => [], @_);
8b445e33 687}
688
de705b51 689sub _select {
8b445e33 690 my ($self, $ident, $select, $condition, $attrs) = @_;
223b8fe3 691 my $order = $attrs->{order_by};
692 if (ref $condition eq 'SCALAR') {
693 $order = $1 if $$condition =~ s/ORDER BY (.*)$//i;
694 }
8839560b 695 if (exists $attrs->{group_by} || $attrs->{having}) {
bc0c9800 696 $order = {
697 group_by => $attrs->{group_by},
698 having => $attrs->{having},
699 ($order ? (order_by => $order) : ())
700 };
54540863 701 }
5c91499f 702 my @args = ('select', $attrs->{bind}, $ident, $select, $condition, $order);
9229f20a 703 if ($attrs->{software_limit} ||
704 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
705 $attrs->{software_limit} = 1;
5c91499f 706 } else {
0823196c 707 $self->throw_exception("rows attribute must be positive if present")
708 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
5c91499f 709 push @args, $attrs->{rows}, $attrs->{offset};
710 }
de705b51 711 return $self->_execute(@args);
712}
713
9b83fccd 714=head2 select
715
716Handle a SQL select statement.
717
718=cut
719
de705b51 720sub select {
721 my $self = shift;
722 my ($ident, $select, $condition, $attrs) = @_;
cb5f2eea 723 return $self->cursor->new($self, \@_, $attrs);
8b445e33 724}
725
9b83fccd 726=head2 select_single
727
728Performs a select, fetch and return of data - handles a single row
729only.
730
731=cut
732
6157db4f 733# Need to call finish() to work round broken DBDs
734
1a14aa3f 735sub select_single {
de705b51 736 my $self = shift;
737 my ($rv, $sth, @bind) = $self->_select(@_);
6157db4f 738 my @row = $sth->fetchrow_array;
739 $sth->finish();
740 return @row;
1a14aa3f 741}
742
9b83fccd 743=head2 sth
744
745Returns a L<DBI> sth (statement handle) for the supplied SQL.
746
747=cut
748
8b445e33 749sub sth {
cb5f2eea 750 my ($self, $sql) = @_;
91fa659e 751 # 3 is the if_active parameter which avoids active sth re-use
752 return $self->dbh->prepare_cached($sql, {}, 3);
8b445e33 753}
754
a953d8d9 755=head2 columns_info_for
756
757Returns database type info for a given table columns.
758
759=cut
760
761sub columns_info_for {
0d67fe74 762 my ($self, $table) = @_;
bfe10d87 763
a32e8402 764 my $dbh = $self->dbh;
765
766 if ($dbh->can('column_info')) {
a953d8d9 767 my %result;
a32e8402 768 my $old_raise_err = $dbh->{RaiseError};
769 my $old_print_err = $dbh->{PrintError};
770 $dbh->{RaiseError} = 1;
771 $dbh->{PrintError} = 0;
0d67fe74 772 eval {
4d272ce5 773 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
774 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
0d67fe74 775 $sth->execute();
776 while ( my $info = $sth->fetchrow_hashref() ){
bfe10d87 777 my %column_info;
0d67fe74 778 $column_info{data_type} = $info->{TYPE_NAME};
779 $column_info{size} = $info->{COLUMN_SIZE};
780 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
781 $column_info{default_value} = $info->{COLUMN_DEF};
0b88a5bb 782 my $col_name = $info->{COLUMN_NAME};
783 $col_name =~ s/^\"(.*)\"$/$1/;
0d67fe74 784
0b88a5bb 785 $result{$col_name} = \%column_info;
0d67fe74 786 }
787 };
a32e8402 788 $dbh->{RaiseError} = $old_raise_err;
789 $dbh->{PrintError} = $old_print_err;
0d67fe74 790 return \%result if !$@;
791 }
792
793 my %result;
a32e8402 794 my $sth = $dbh->prepare("SELECT * FROM $table WHERE 1=0");
0d67fe74 795 $sth->execute;
796 my @columns = @{$sth->{NAME_lc}};
797 for my $i ( 0 .. $#columns ){
798 my %column_info;
799 my $type_num = $sth->{TYPE}->[$i];
800 my $type_name;
a32e8402 801 if(defined $type_num && $dbh->can('type_info')) {
802 my $type_info = $dbh->type_info($type_num);
0d67fe74 803 $type_name = $type_info->{TYPE_NAME} if $type_info;
a953d8d9 804 }
0d67fe74 805 $column_info{data_type} = $type_name ? $type_name : $type_num;
806 $column_info{size} = $sth->{PRECISION}->[$i];
807 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
808
809 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
810 $column_info{data_type} = $1;
811 $column_info{size} = $2;
812 }
813
814 $result{$columns[$i]} = \%column_info;
815 }
bfe10d87 816
0d67fe74 817 return \%result;
a953d8d9 818}
819
9b83fccd 820=head2 last_insert_id
821
822Return the row id of the last insert.
823
824=cut
825
843f8ecd 826sub last_insert_id {
827 my ($self, $row) = @_;
828
829 return $self->dbh->func('last_insert_rowid');
830
831}
832
9b83fccd 833=head2 sqlt_type
834
835Returns the database driver name.
836
837=cut
838
90ec6cad 839sub sqlt_type { shift->dbh->{Driver}->{Name} }
1c339d71 840
9b83fccd 841=head2 create_ddl_dir (EXPERIMENTAL)
842
843=over 4
844
845=item Arguments: $schema \@databases, $version, $directory, $sqlt_args
846
847=back
848
849Creates an SQL file based on the Schema, for each of the specified
850database types, in the given directory.
851
852Note that this feature is currently EXPERIMENTAL and may not work correctly
853across all databases, or fully handle complex relationships.
854
855=cut
856
e673f011 857sub create_ddl_dir
858{
859 my ($self, $schema, $databases, $version, $dir, $sqltargs) = @_;
860
861 if(!$dir || !-d $dir)
862 {
863 warn "No directory given, using ./\n";
864 $dir = "./";
865 }
866 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
867 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
868 $version ||= $schema->VERSION || '1.x';
869
1c339d71 870 eval "use SQL::Translator";
871 $self->throw_exception("Can't deploy without SQL::Translator: $@") if $@;
e673f011 872
873 my $sqlt = SQL::Translator->new({
874# debug => 1,
875 add_drop_table => 1,
876 });
877 foreach my $db (@$databases)
878 {
879 $sqlt->reset();
880 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
881# $sqlt->parser_args({'DBIx::Class' => $schema);
882 $sqlt->data($schema);
883 $sqlt->producer($db);
884
885 my $file;
886 my $filename = $schema->ddl_filename($db, $dir, $version);
887 if(-e $filename)
888 {
889 $self->throw_exception("$filename already exists, skipping $db");
890 next;
891 }
892 open($file, ">$filename")
893 or $self->throw_exception("Can't open $filename for writing ($!)");
894 my $output = $sqlt->translate;
895#use Data::Dumper;
896# print join(":", keys %{$schema->source_registrations});
897# print Dumper($sqlt->schema);
898 if(!$output)
899 {
900 $self->throw_exception("Failed to translate to $db. (" . $sqlt->error . ")");
901 next;
902 }
903 print $file $output;
904 close($file);
905 }
906
907}
908
9b83fccd 909=head2 deployment_statements
910
911Create the statements for L</deploy> and
912L<DBIx::Class::Schema/deploy>.
913
914=cut
915
e673f011 916sub deployment_statements {
917 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
918 $type ||= $self->sqlt_type;
919 $version ||= $schema->VERSION || '1.x';
920 $dir ||= './';
0382d607 921 eval "use SQL::Translator";
922 if(!$@)
923 {
924 eval "use SQL::Translator::Parser::DBIx::Class;";
925 $self->throw_exception($@) if $@;
926 eval "use SQL::Translator::Producer::${type};";
927 $self->throw_exception($@) if $@;
928 my $tr = SQL::Translator->new(%$sqltargs);
929 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
930 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
931 }
e673f011 932
933 my $filename = $schema->ddl_filename($type, $dir, $version);
934 if(!-f $filename)
935 {
0382d607 936# $schema->create_ddl_dir([ $type ], $version, $dir, $sqltargs);
937 $self->throw_exception("No SQL::Translator, and no Schema file found, aborting deploy");
938 return;
e673f011 939 }
940 my $file;
941 open($file, "<$filename")
942 or $self->throw_exception("Can't open $filename ($!)");
943 my @rows = <$file>;
944 close($file);
945
946 return join('', @rows);
947
1c339d71 948}
843f8ecd 949
9b83fccd 950=head2 deploy
951
952Sends the appropriate statements to create or modify tables to the
953db. This would normally be called through
954L<DBIx::Class::Schema/deploy>.
955
956=cut
957
1c339d71 958sub deploy {
cb561d1a 959 my ($self, $schema, $type, $sqltargs) = @_;
e673f011 960 foreach my $statement ( $self->deployment_statements($schema, $type, undef, undef, $sqltargs) ) {
e4fe9ba3 961 for ( split(";\n", $statement)) {
e673f011 962 next if($_ =~ /^--/);
963 next if(!$_);
964# next if($_ =~ /^DROP/m);
965 next if($_ =~ /^BEGIN TRANSACTION/m);
966 next if($_ =~ /^COMMIT/m);
4c248161 967 $self->debugobj->query_begin($_) if $self->debug;
e4fe9ba3 968 $self->dbh->do($_) or warn "SQL was:\n $_";
4c248161 969 $self->debugobj->query_end($_) if $self->debug;
e4fe9ba3 970 }
75d07914 971 }
1c339d71 972}
843f8ecd 973
9b83fccd 974=head2 datetime_parser
975
976Returns the datetime parser class
977
978=cut
979
f86fcf0d 980sub datetime_parser {
981 my $self = shift;
982 return $self->{datetime_parser} ||= $self->build_datetime_parser(@_);
983}
984
9b83fccd 985=head2 datetime_parser_type
986
987Defines (returns) the datetime parser class - currently hardwired to
988L<DateTime::Format::MySQL>
989
990=cut
991
f86fcf0d 992sub datetime_parser_type { "DateTime::Format::MySQL"; }
993
9b83fccd 994=head2 build_datetime_parser
995
996See L</datetime_parser>
997
998=cut
999
f86fcf0d 1000sub build_datetime_parser {
1001 my $self = shift;
1002 my $type = $self->datetime_parser_type(@_);
1003 eval "use ${type}";
1004 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1005 return $type;
1006}
1007
92925617 1008sub DESTROY { shift->disconnect }
1009
8b445e33 10101;
1011
9b83fccd 1012=head1 SQL METHODS
1013
1014The module defines a set of methods within the DBIC::SQL::Abstract
1015namespace. These build on L<SQL::Abstract::Limit> to provide the
1016SQL query functions.
1017
1018The following methods are extended:-
1019
1020=over 4
1021
1022=item delete
1023
1024=item insert
1025
1026=item select
1027
1028=item update
1029
1030=item limit_dialect
1031
bb4f246d 1032Accessor for setting limit dialect. This is useful
1033for JDBC-bridge among others where the remote SQL-dialect cannot
1034be determined by the name of the driver alone.
1035
1036This option can also be set via L</connect_info>.
1037
9b83fccd 1038=item quote_char
1039
bb4f246d 1040Specifies what characters to use to quote table and column names. If
1041you use this you will want to specify L<name_sep> as well.
1042
1043quote_char expectes either a single character, in which case is it is placed
1044on either side of the table/column, or an arrayref of length 2 in which case the
1045table/column name is placed between the elements.
1046
1047For example under MySQL you'd use C<quote_char('`')>, and user SQL Server you'd
1048use C<quote_char(qw/[ ]/)>.
1049
1050This option can also be set via L</connect_info>.
1051
9b83fccd 1052=item name_sep
1053
bb4f246d 1054This only needs to be used in conjunction with L<quote_char>, and is used to
1055specify the charecter that seperates elements (schemas, tables, columns) from
1056each other. In most cases this is simply a C<.>.
1057
1058This option can also be set via L</connect_info>.
1059
9b83fccd 1060=back
1061
92b858c9 1062=head1 ENVIRONMENT VARIABLES
1063
1064=head2 DBIX_CLASS_STORAGE_DBI_DEBUG
1065
1066If C<DBIX_CLASS_STORAGE_DBI_DEBUG> is set then SQL trace information
1067is produced (as when the L<debug> method is set).
1068
1069If the value is of the form C<1=/path/name> then the trace output is
1070written to the file C</path/name>.
1071
d1cceec4 1072This environment variable is checked when the storage object is first
1073created (when you call connect on your schema). So, run-time changes
1074to this environment variable will not take effect unless you also
1075re-connect on your schema.
1076
8b445e33 1077=head1 AUTHORS
1078
daec44b8 1079Matt S. Trout <mst@shadowcatsystems.co.uk>
8b445e33 1080
9f19b1d6 1081Andy Grundman <andy@hybridized.org>
1082
8b445e33 1083=head1 LICENSE
1084
1085You may distribute this code under the same terms as Perl itself.
1086
1087=cut
1088