cleanup cursor class handling
[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
eda28767 6use strict;
20a2c954 7use warnings;
8b445e33 8use DBI;
aeaf3ce2 9use SQL::Abstract::Limit;
28927b50 10use DBIx::Class::Storage::DBI::Cursor;
4c248161 11use DBIx::Class::Storage::Statistics;
664612fb 12use Scalar::Util qw/blessed weaken/;
046ad905 13
541df64a 14__PACKAGE__->mk_group_accessors('simple' =>
15 qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts
e4eb8ee1 16 _conn_pid _conn_tid disable_sth_caching on_connect_do
57c18b65 17 transaction_depth unsafe _dbh_autocommit/
046ad905 18);
19
e4eb8ee1 20__PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor');
21
bd7efd39 22BEGIN {
23
cb5f2eea 24package DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :(
bd7efd39 25
26use base qw/SQL::Abstract::Limit/;
27
2cc3a7be 28# This prevents the caching of $dbh in S::A::L, I believe
29sub new {
30 my $self = shift->SUPER::new(@_);
31
32 # If limit_dialect is a ref (like a $dbh), go ahead and replace
33 # it with what it resolves to:
34 $self->{limit_dialect} = $self->_find_syntax($self->{limit_dialect})
35 if ref $self->{limit_dialect};
36
37 $self;
38}
39
260129d8 40sub _RowNumberOver {
41 my ($self, $sql, $order, $rows, $offset ) = @_;
42
43 $offset += 1;
44 my $last = $rows + $offset;
45 my ( $order_by ) = $self->_order_by( $order );
46
47 $sql = <<"";
48SELECT * FROM
49(
50 SELECT Q1.*, ROW_NUMBER() OVER( ) AS ROW_NUM FROM (
51 $sql
52 $order_by
53 ) Q1
54) Q2
55WHERE ROW_NUM BETWEEN $offset AND $last
56
57 return $sql;
58}
59
60
2cc3a7be 61# While we're at it, this should make LIMIT queries more efficient,
62# without digging into things too deeply
758272ec 63use Scalar::Util 'blessed';
2cc3a7be 64sub _find_syntax {
65 my ($self, $syntax) = @_;
758272ec 66 my $dbhname = blessed($syntax) ? $syntax->{Driver}{Name} : $syntax;
260129d8 67 if(ref($self) && $dbhname && $dbhname eq 'DB2') {
68 return 'RowNumberOver';
69 }
70
2cc3a7be 71 $self->{_cached_syntax} ||= $self->SUPER::_find_syntax($syntax);
72}
73
54540863 74sub select {
75 my ($self, $table, $fields, $where, $order, @rest) = @_;
6346a152 76 $table = $self->_quote($table) unless ref($table);
eac29141 77 local $self->{rownum_hack_count} = 1
78 if (defined $rest[0] && $self->{limit_dialect} eq 'RowNum');
54540863 79 @rest = (-1) unless defined $rest[0];
0823196c 80 die "LIMIT 0 Does Not Compute" if $rest[0] == 0;
81 # and anyway, SQL::Abstract::Limit will cause a barf if we don't first
8839560b 82 local $self->{having_bind} = [];
bc0c9800 83 my ($sql, @ret) = $self->SUPER::select(
84 $table, $self->_recurse_fields($fields), $where, $order, @rest
85 );
8839560b 86 return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql;
54540863 87}
88
6346a152 89sub insert {
90 my $self = shift;
91 my $table = shift;
92 $table = $self->_quote($table) unless ref($table);
93 $self->SUPER::insert($table, @_);
94}
95
96sub update {
97 my $self = shift;
98 my $table = shift;
99 $table = $self->_quote($table) unless ref($table);
100 $self->SUPER::update($table, @_);
101}
102
103sub delete {
104 my $self = shift;
105 my $table = shift;
106 $table = $self->_quote($table) unless ref($table);
107 $self->SUPER::delete($table, @_);
108}
109
54540863 110sub _emulate_limit {
111 my $self = shift;
112 if ($_[3] == -1) {
113 return $_[1].$self->_order_by($_[2]);
114 } else {
115 return $self->SUPER::_emulate_limit(@_);
116 }
117}
118
119sub _recurse_fields {
e8e971f2 120 my ($self, $fields, $params) = @_;
54540863 121 my $ref = ref $fields;
122 return $self->_quote($fields) unless $ref;
123 return $$fields if $ref eq 'SCALAR';
124
125 if ($ref eq 'ARRAY') {
1d78a406 126 return join(', ', map {
eac29141 127 $self->_recurse_fields($_)
1d78a406 128 .(exists $self->{rownum_hack_count} && !($params && $params->{no_rownum_hack})
129 ? ' AS col'.$self->{rownum_hack_count}++
130 : '')
e8e971f2 131 } @$fields);
54540863 132 } elsif ($ref eq 'HASH') {
133 foreach my $func (keys %$fields) {
134 return $self->_sqlcase($func)
135 .'( '.$self->_recurse_fields($fields->{$func}).' )';
136 }
137 }
138}
139
140sub _order_by {
141 my $self = shift;
142 my $ret = '';
8839560b 143 my @extra;
54540863 144 if (ref $_[0] eq 'HASH') {
145 if (defined $_[0]->{group_by}) {
146 $ret = $self->_sqlcase(' group by ')
1d78a406 147 .$self->_recurse_fields($_[0]->{group_by}, { no_rownum_hack => 1 });
54540863 148 }
8839560b 149 if (defined $_[0]->{having}) {
150 my $frag;
151 ($frag, @extra) = $self->_recurse_where($_[0]->{having});
152 push(@{$self->{having_bind}}, @extra);
153 $ret .= $self->_sqlcase(' having ').$frag;
154 }
54540863 155 if (defined $_[0]->{order_by}) {
7ce5cbe7 156 $ret .= $self->_order_by($_[0]->{order_by});
54540863 157 }
d09c569a 158 } elsif (ref $_[0] eq 'SCALAR') {
e535069e 159 $ret = $self->_sqlcase(' order by ').${ $_[0] };
d09c569a 160 } elsif (ref $_[0] eq 'ARRAY' && @{$_[0]}) {
161 my @order = @{+shift};
162 $ret = $self->_sqlcase(' order by ')
163 .join(', ', map {
164 my $r = $self->_order_by($_, @_);
165 $r =~ s/^ ?ORDER BY //i;
166 $r;
167 } @order);
54540863 168 } else {
169 $ret = $self->SUPER::_order_by(@_);
170 }
171 return $ret;
172}
173
f48dd03f 174sub _order_directions {
175 my ($self, $order) = @_;
176 $order = $order->{order_by} if ref $order eq 'HASH';
177 return $self->SUPER::_order_directions($order);
178}
179
2a816814 180sub _table {
bd7efd39 181 my ($self, $from) = @_;
182 if (ref $from eq 'ARRAY') {
183 return $self->_recurse_from(@$from);
184 } elsif (ref $from eq 'HASH') {
185 return $self->_make_as($from);
186 } else {
6346a152 187 return $from; # would love to quote here but _table ends up getting called
188 # twice during an ->select without a limit clause due to
189 # the way S::A::Limit->select works. should maybe consider
190 # bypassing this and doing S::A::select($self, ...) in
191 # our select method above. meantime, quoting shims have
192 # been added to select/insert/update/delete here
bd7efd39 193 }
194}
195
196sub _recurse_from {
197 my ($self, $from, @join) = @_;
198 my @sqlf;
199 push(@sqlf, $self->_make_as($from));
200 foreach my $j (@join) {
201 my ($to, $on) = @$j;
73856587 202
54540863 203 # check whether a join type exists
204 my $join_clause = '';
ca7b9fdf 205 my $to_jt = ref($to) eq 'ARRAY' ? $to->[0] : $to;
206 if (ref($to_jt) eq 'HASH' and exists($to_jt->{-join_type})) {
207 $join_clause = ' '.uc($to_jt->{-join_type}).' JOIN ';
54540863 208 } else {
209 $join_clause = ' JOIN ';
210 }
73856587 211 push(@sqlf, $join_clause);
212
bd7efd39 213 if (ref $to eq 'ARRAY') {
214 push(@sqlf, '(', $self->_recurse_from(@$to), ')');
215 } else {
96cdbbab 216 push(@sqlf, $self->_make_as($to));
bd7efd39 217 }
218 push(@sqlf, ' ON ', $self->_join_condition($on));
219 }
220 return join('', @sqlf);
221}
222
223sub _make_as {
224 my ($self, $from) = @_;
54540863 225 return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ : $self->_quote($_)) }
bc0c9800 226 reverse each %{$self->_skip_options($from)});
73856587 227}
228
229sub _skip_options {
54540863 230 my ($self, $hash) = @_;
231 my $clean_hash = {};
232 $clean_hash->{$_} = $hash->{$_}
233 for grep {!/^-/} keys %$hash;
234 return $clean_hash;
bd7efd39 235}
236
237sub _join_condition {
238 my ($self, $cond) = @_;
5efe4c79 239 if (ref $cond eq 'HASH') {
240 my %j;
bc0c9800 241 for (keys %$cond) {
635b9634 242 my $v = $cond->{$_};
243 if (ref $v) {
244 # XXX no throw_exception() in this package and croak() fails with strange results
245 Carp::croak(ref($v) . qq{ reference arguments are not supported in JOINS - try using \"..." instead'})
246 if ref($v) ne 'SCALAR';
247 $j{$_} = $v;
248 }
249 else {
250 my $x = '= '.$self->_quote($v); $j{$_} = \$x;
251 }
bc0c9800 252 };
635b9634 253 return scalar($self->_recurse_where(\%j));
5efe4c79 254 } elsif (ref $cond eq 'ARRAY') {
255 return join(' OR ', map { $self->_join_condition($_) } @$cond);
256 } else {
257 die "Can't handle this yet!";
258 }
bd7efd39 259}
260
2a816814 261sub _quote {
262 my ($self, $label) = @_;
263 return '' unless defined $label;
3b24f6ea 264 return "*" if $label eq '*';
41728a6e 265 return $label unless $self->{quote_char};
3b24f6ea 266 if(ref $self->{quote_char} eq "ARRAY"){
267 return $self->{quote_char}->[0] . $label . $self->{quote_char}->[1]
268 if !defined $self->{name_sep};
269 my $sep = $self->{name_sep};
270 return join($self->{name_sep},
271 map { $self->{quote_char}->[0] . $_ . $self->{quote_char}->[1] }
272 split(/\Q$sep\E/,$label));
273 }
2a816814 274 return $self->SUPER::_quote($label);
275}
276
7be93b07 277sub limit_dialect {
278 my $self = shift;
279 $self->{limit_dialect} = shift if @_;
280 return $self->{limit_dialect};
281}
282
2437a1e3 283sub quote_char {
284 my $self = shift;
285 $self->{quote_char} = shift if @_;
286 return $self->{quote_char};
287}
288
289sub name_sep {
290 my $self = shift;
291 $self->{name_sep} = shift if @_;
292 return $self->{name_sep};
293}
294
bd7efd39 295} # End of BEGIN block
296
b327f988 297=head1 NAME
298
299DBIx::Class::Storage::DBI - DBI storage handler
300
301=head1 SYNOPSIS
302
303=head1 DESCRIPTION
304
046ad905 305This class represents the connection to an RDBMS via L<DBI>. See
306L<DBIx::Class::Storage> for general information. This pod only
307documents DBI-specific methods and behaviors.
b327f988 308
309=head1 METHODS
310
9b83fccd 311=cut
312
8b445e33 313sub new {
046ad905 314 my $new = shift->next::method(@_);
82cc0386 315
d79f59b9 316 $new->transaction_depth(0);
2cc3a7be 317 $new->_sql_maker_opts({});
1b994857 318 $new->{_in_dbh_do} = 0;
dbaee748 319 $new->{_dbh_gen} = 0;
82cc0386 320
046ad905 321 $new;
1c339d71 322}
323
1b45b01e 324=head2 connect_info
325
bb4f246d 326The arguments of C<connect_info> are always a single array reference.
1b45b01e 327
bb4f246d 328This is normally accessed via L<DBIx::Class::Schema/connection>, which
329encapsulates its argument list in an arrayref before calling
330C<connect_info> here.
1b45b01e 331
bb4f246d 332The arrayref can either contain the same set of arguments one would
333normally pass to L<DBI/connect>, or a lone code reference which returns
77d76d0f 334a connected database handle. Please note that the L<DBI> docs
335recommend that you always explicitly set C<AutoCommit> to either
336C<0> or C<1>. L<DBIx::Class> further recommends that it be set
337to C<1>, and that you perform transactions via our L</txn_do>
2bc2ddc7 338method. L<DBIx::Class> will set it to C<1> if you do not do explicitly
339set it to zero. This is the default for most DBDs. See below for more
340details.
d7c4c15c 341
2cc3a7be 342In either case, if the final argument in your connect_info happens
343to be a hashref, C<connect_info> will look there for several
344connection-specific options:
345
346=over 4
347
348=item on_connect_do
349
350This can be set to an arrayref of literal sql statements, which will
351be executed immediately after making the connection to the database
352every time we [re-]connect.
353
b33697ef 354=item disable_sth_caching
355
356If set to a true value, this option will disable the caching of
357statement handles via L<DBI/prepare_cached>.
358
2cc3a7be 359=item limit_dialect
360
361Sets the limit dialect. This is useful for JDBC-bridge among others
362where the remote SQL-dialect cannot be determined by the name of the
363driver alone.
364
365=item quote_char
d7c4c15c 366
2cc3a7be 367Specifies what characters to use to quote table and column names. If
368you use this you will want to specify L<name_sep> as well.
369
370quote_char expects either a single character, in which case is it is placed
371on either side of the table/column, or an arrayref of length 2 in which case the
372table/column name is placed between the elements.
373
374For example under MySQL you'd use C<quote_char =E<gt> '`'>, and user SQL Server you'd
375use C<quote_char =E<gt> [qw/[ ]/]>.
376
377=item name_sep
378
379This only needs to be used in conjunction with L<quote_char>, and is used to
380specify the charecter that seperates elements (schemas, tables, columns) from
381each other. In most cases this is simply a C<.>.
382
61646ebd 383=item unsafe
384
385This Storage driver normally installs its own C<HandleError>, sets
2ab60eb9 386C<RaiseError> and C<ShowErrorStatement> on, and sets C<PrintError> off on
387all database handles, including those supplied by a coderef. It does this
388so that it can have consistent and useful error behavior.
61646ebd 389
390If you set this option to a true value, Storage will not do its usual
2ab60eb9 391modifications to the database handle's attributes, and instead relies on
392the settings in your connect_info DBI options (or the values you set in
393your connection coderef, in the case that you are connecting via coderef).
61646ebd 394
395Note that your custom settings can cause Storage to malfunction,
396especially if you set a C<HandleError> handler that suppresses exceptions
397and/or disable C<RaiseError>.
398
2cc3a7be 399=back
400
401These options can be mixed in with your other L<DBI> connection attributes,
402or placed in a seperate hashref after all other normal L<DBI> connection
403arguments.
404
405Every time C<connect_info> is invoked, any previous settings for
406these options will be cleared before setting the new ones, regardless of
407whether any options are specified in the new C<connect_info>.
408
77d76d0f 409Another Important Note:
410
411DBIC can do some wonderful magic with handling exceptions,
412disconnections, and transactions when you use C<AutoCommit =&gt; 1>
413combined with C<txn_do> for transaction support.
414
415If you set C<AutoCommit =&gt; 0> in your connect info, then you are always
416in an assumed transaction between commits, and you're telling us you'd
417like to manage that manually. A lot of DBIC's magic protections
418go away. We can't protect you from exceptions due to database
419disconnects because we don't know anything about how to restart your
420transactions. You're on your own for handling all sorts of exceptional
421cases if you choose the C<AutoCommit =&gt 0> path, just as you would
422be with raw DBI.
423
2cc3a7be 424Examples:
425
426 # Simple SQLite connection
bb4f246d 427 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
6789ebe3 428
2cc3a7be 429 # Connect via subref
bb4f246d 430 ->connect_info([ sub { DBI->connect(...) } ]);
6789ebe3 431
2cc3a7be 432 # A bit more complicated
bb4f246d 433 ->connect_info(
434 [
435 'dbi:Pg:dbname=foo',
436 'postgres',
437 'my_pg_password',
77d76d0f 438 { AutoCommit => 1 },
2cc3a7be 439 { quote_char => q{"}, name_sep => q{.} },
440 ]
441 );
442
443 # Equivalent to the previous example
444 ->connect_info(
445 [
446 'dbi:Pg:dbname=foo',
447 'postgres',
448 'my_pg_password',
77d76d0f 449 { AutoCommit => 1, quote_char => q{"}, name_sep => q{.} },
bb4f246d 450 ]
451 );
6789ebe3 452
2cc3a7be 453 # Subref + DBIC-specific connection options
bb4f246d 454 ->connect_info(
455 [
456 sub { DBI->connect(...) },
2cc3a7be 457 {
458 quote_char => q{`},
459 name_sep => q{@},
460 on_connect_do => ['SET search_path TO myschema,otherschema,public'],
b33697ef 461 disable_sth_caching => 1,
2cc3a7be 462 },
bb4f246d 463 ]
464 );
6789ebe3 465
004d31fb 466=cut
467
046ad905 468sub connect_info {
469 my ($self, $info_arg) = @_;
4c248161 470
046ad905 471 return $self->_connect_info if !$info_arg;
4c248161 472
046ad905 473 # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
474 # the new set of options
475 $self->_sql_maker(undef);
476 $self->_sql_maker_opts({});
fdad5fab 477 $self->_connect_info([@$info_arg]); # copy for _connect_info
486ad69b 478
fdad5fab 479 my $dbi_info = [@$info_arg]; # copy for _dbi_connect_info
8df3d107 480
541df64a 481 my $last_info = $dbi_info->[-1];
046ad905 482 if(ref $last_info eq 'HASH') {
9a0891be 483 $last_info = { %$last_info }; # so delete is non-destructive
61646ebd 484 for my $storage_opt (qw/on_connect_do disable_sth_caching unsafe/) {
b33697ef 485 if(my $value = delete $last_info->{$storage_opt}) {
486 $self->$storage_opt($value);
487 }
046ad905 488 }
489 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
490 if(my $opt_val = delete $last_info->{$sql_maker_opt}) {
491 $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
492 }
493 }
9a0891be 494 # re-insert modified hashref
495 $dbi_info->[-1] = $last_info;
486ad69b 496
046ad905 497 # Get rid of any trailing empty hashref
541df64a 498 pop(@$dbi_info) if !keys %$last_info;
046ad905 499 }
fdad5fab 500 $self->_dbi_connect_info($dbi_info);
d7c4c15c 501
fdad5fab 502 $self->_connect_info;
046ad905 503}
004d31fb 504
046ad905 505=head2 on_connect_do
4c248161 506
046ad905 507This method is deprecated in favor of setting via L</connect_info>.
486ad69b 508
f11383c2 509=head2 dbh_do
510
046ad905 511Arguments: $subref, @extra_coderef_args?
512
d4f16b21 513Execute the given subref using the new exception-based connection management.
046ad905 514
d4f16b21 515The first two arguments will be the storage object that C<dbh_do> was called
516on and a database handle to use. Any additional arguments will be passed
517verbatim to the called subref as arguments 2 and onwards.
518
519Using this (instead of $self->_dbh or $self->dbh) ensures correct
520exception handling and reconnection (or failover in future subclasses).
521
522Your subref should have no side-effects outside of the database, as
523there is the potential for your subref to be partially double-executed
524if the database connection was stale/dysfunctional.
046ad905 525
56769f7c 526Example:
f11383c2 527
56769f7c 528 my @stuff = $schema->storage->dbh_do(
529 sub {
d4f16b21 530 my ($storage, $dbh, @cols) = @_;
531 my $cols = join(q{, }, @cols);
532 $dbh->selectrow_array("SELECT $cols FROM foo");
046ad905 533 },
534 @column_list
56769f7c 535 );
f11383c2 536
537=cut
538
539sub dbh_do {
046ad905 540 my $self = shift;
aa27edf7 541 my $coderef = shift;
542
aa27edf7 543 ref $coderef eq 'CODE' or $self->throw_exception
544 ('$coderef must be a CODE reference');
f11383c2 545
cb19f4dd 546 return $coderef->($self, $self->_dbh, @_) if $self->{_in_dbh_do}
547 || $self->{transaction_depth};
548
1b994857 549 local $self->{_in_dbh_do} = 1;
550
f11383c2 551 my @result;
552 my $want_array = wantarray;
553
554 eval {
56769f7c 555 $self->_verify_pid if $self->_dbh;
f11383c2 556 $self->_populate_dbh if !$self->_dbh;
f11383c2 557 if($want_array) {
d4f16b21 558 @result = $coderef->($self, $self->_dbh, @_);
f11383c2 559 }
56769f7c 560 elsif(defined $want_array) {
d4f16b21 561 $result[0] = $coderef->($self, $self->_dbh, @_);
f11383c2 562 }
56769f7c 563 else {
d4f16b21 564 $coderef->($self, $self->_dbh, @_);
56769f7c 565 }
f11383c2 566 };
56769f7c 567
aa27edf7 568 my $exception = $@;
569 if(!$exception) { return $want_array ? @result : $result[0] }
570
571 $self->throw_exception($exception) if $self->connected;
572
573 # We were not connected - reconnect and retry, but let any
574 # exception fall right through this time
575 $self->_populate_dbh;
d4f16b21 576 $coderef->($self, $self->_dbh, @_);
aa27edf7 577}
578
579# This is basically a blend of dbh_do above and DBIx::Class::Storage::txn_do.
580# It also informs dbh_do to bypass itself while under the direction of txn_do,
1b994857 581# via $self->{_in_dbh_do} (this saves some redundant eval and errorcheck, etc)
aa27edf7 582sub txn_do {
583 my $self = shift;
584 my $coderef = shift;
585
586 ref $coderef eq 'CODE' or $self->throw_exception
587 ('$coderef must be a CODE reference');
588
57c18b65 589 return $coderef->(@_) if $self->{transaction_depth};
590
1b994857 591 local $self->{_in_dbh_do} = 1;
f11383c2 592
aa27edf7 593 my @result;
594 my $want_array = wantarray;
595
d4f16b21 596 my $tried = 0;
597 while(1) {
598 eval {
599 $self->_verify_pid if $self->_dbh;
600 $self->_populate_dbh if !$self->_dbh;
aa27edf7 601
d4f16b21 602 $self->txn_begin;
603 if($want_array) {
604 @result = $coderef->(@_);
605 }
606 elsif(defined $want_array) {
607 $result[0] = $coderef->(@_);
608 }
609 else {
610 $coderef->(@_);
611 }
612 $self->txn_commit;
613 };
aa27edf7 614
d4f16b21 615 my $exception = $@;
616 if(!$exception) { return $want_array ? @result : $result[0] }
617
618 if($tried++ > 0 || $self->connected) {
619 eval { $self->txn_rollback };
620 my $rollback_exception = $@;
621 if($rollback_exception) {
622 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
623 $self->throw_exception($exception) # propagate nested rollback
624 if $rollback_exception =~ /$exception_class/;
625
626 $self->throw_exception(
627 "Transaction aborted: ${exception}. "
628 . "Rollback failed: ${rollback_exception}"
629 );
630 }
631 $self->throw_exception($exception)
aa27edf7 632 }
56769f7c 633
d4f16b21 634 # We were not connected, and was first try - reconnect and retry
635 # via the while loop
636 $self->_populate_dbh;
637 }
f11383c2 638}
639
9b83fccd 640=head2 disconnect
641
046ad905 642Our C<disconnect> method also performs a rollback first if the
9b83fccd 643database is not in C<AutoCommit> mode.
644
645=cut
646
412db1f4 647sub disconnect {
648 my ($self) = @_;
649
92925617 650 if( $self->connected ) {
57c18b65 651 $self->_dbh->rollback unless $self->_dbh_autocommit;
92925617 652 $self->_dbh->disconnect;
653 $self->_dbh(undef);
dbaee748 654 $self->{_dbh_gen}++;
92925617 655 }
412db1f4 656}
657
f11383c2 658sub connected {
659 my ($self) = @_;
412db1f4 660
1346e22d 661 if(my $dbh = $self->_dbh) {
662 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
dbaee748 663 $self->_dbh(undef);
664 $self->{_dbh_gen}++;
665 return;
1346e22d 666 }
56769f7c 667 else {
668 $self->_verify_pid;
669 }
1346e22d 670 return ($dbh->FETCH('Active') && $dbh->ping);
671 }
672
673 return 0;
412db1f4 674}
675
f11383c2 676# handle pid changes correctly
56769f7c 677# NOTE: assumes $self->_dbh is a valid $dbh
f11383c2 678sub _verify_pid {
679 my ($self) = @_;
680
56769f7c 681 return if $self->_conn_pid == $$;
f11383c2 682
f11383c2 683 $self->_dbh->{InactiveDestroy} = 1;
d3abf3fe 684 $self->_dbh(undef);
dbaee748 685 $self->{_dbh_gen}++;
f11383c2 686
687 return;
688}
689
412db1f4 690sub ensure_connected {
691 my ($self) = @_;
692
693 unless ($self->connected) {
8b445e33 694 $self->_populate_dbh;
695 }
412db1f4 696}
697
c235bbae 698=head2 dbh
699
700Returns the dbh - a data base handle of class L<DBI>.
701
702=cut
703
412db1f4 704sub dbh {
705 my ($self) = @_;
706
707 $self->ensure_connected;
8b445e33 708 return $self->_dbh;
709}
710
f1f56aad 711sub _sql_maker_args {
712 my ($self) = @_;
713
6e399b4f 714 return ( bindtype=>'columns', limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
f1f56aad 715}
716
48c69e7c 717sub sql_maker {
718 my ($self) = @_;
fdc1c3d0 719 unless ($self->_sql_maker) {
f1f56aad 720 $self->_sql_maker(new DBIC::SQL::Abstract( $self->_sql_maker_args ));
48c69e7c 721 }
722 return $self->_sql_maker;
723}
724
8b445e33 725sub _populate_dbh {
726 my ($self) = @_;
7e47ea83 727 my @info = @{$self->_dbi_connect_info || []};
8b445e33 728 $self->_dbh($self->_connect(@info));
2fd24e78 729
77d76d0f 730 # Always set the transaction depth on connect, since
731 # there is no transaction in progress by definition
57c18b65 732 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 733
2fd24e78 734 if(ref $self eq 'DBIx::Class::Storage::DBI') {
735 my $driver = $self->_dbh->{Driver}->{Name};
efe6365b 736 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
2fd24e78 737 bless $self, "DBIx::Class::Storage::DBI::${driver}";
738 $self->_rebless() if $self->can('_rebless');
739 }
843f8ecd 740 }
2fd24e78 741
d7c4c15c 742 # if on-connect sql statements are given execute them
743 foreach my $sql_statement (@{$self->on_connect_do || []}) {
4c248161 744 $self->debugobj->query_start($sql_statement) if $self->debug();
d7c4c15c 745 $self->_dbh->do($sql_statement);
4c248161 746 $self->debugobj->query_end($sql_statement) if $self->debug();
d7c4c15c 747 }
5ef3e508 748
1346e22d 749 $self->_conn_pid($$);
750 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
8b445e33 751}
752
753sub _connect {
754 my ($self, @info) = @_;
5ef3e508 755
9d31f7dc 756 $self->throw_exception("You failed to provide any connection info")
61646ebd 757 if !@info;
9d31f7dc 758
90ec6cad 759 my ($old_connect_via, $dbh);
760
5ef3e508 761 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
61646ebd 762 $old_connect_via = $DBI::connect_via;
763 $DBI::connect_via = 'connect';
5ef3e508 764 }
765
75db246c 766 eval {
f5de3933 767 if(ref $info[0] eq 'CODE') {
768 $dbh = &{$info[0]}
769 }
770 else {
771 $dbh = DBI->connect(@info);
61646ebd 772 }
773
774 if(!$self->unsafe) {
664612fb 775 my $weak_self = $self;
776 weaken($weak_self);
61646ebd 777 $dbh->{HandleError} = sub {
664612fb 778 $weak_self->throw_exception("DBI Exception: $_[0]")
61646ebd 779 };
2ab60eb9 780 $dbh->{ShowErrorStatement} = 1;
61646ebd 781 $dbh->{RaiseError} = 1;
782 $dbh->{PrintError} = 0;
f5de3933 783 }
75db246c 784 };
90ec6cad 785
786 $DBI::connect_via = $old_connect_via if $old_connect_via;
787
d92a4015 788 $self->throw_exception("DBI Connection failed: " . ($@||$DBI::errstr))
789 if !$dbh || $@;
90ec6cad 790
57c18b65 791 $self->_dbh_autocommit($dbh->{AutoCommit});
792
e571e823 793 $dbh;
8b445e33 794}
795
d32d82f9 796
8091aa91 797sub txn_begin {
d79f59b9 798 my $self = shift;
291bf95f 799 $self->ensure_connected();
57c18b65 800 if($self->{transaction_depth} == 0) {
77d76d0f 801 $self->debugobj->txn_begin()
802 if $self->debug;
803 # this isn't ->_dbh-> because
804 # we should reconnect on begin_work
805 # for AutoCommit users
806 $self->dbh->begin_work;
986e4fca 807 }
57c18b65 808 $self->{transaction_depth}++;
8091aa91 809}
8b445e33 810
8091aa91 811sub txn_commit {
d79f59b9 812 my $self = shift;
77d76d0f 813 if ($self->{transaction_depth} == 1) {
814 my $dbh = $self->_dbh;
815 $self->debugobj->txn_commit()
816 if ($self->debug);
817 $dbh->commit;
818 $self->{transaction_depth} = 0
57c18b65 819 if $self->_dbh_autocommit;
77d76d0f 820 }
821 elsif($self->{transaction_depth} > 1) {
822 $self->{transaction_depth}--
823 }
d32d82f9 824}
825
77d76d0f 826sub txn_rollback {
827 my $self = shift;
828 my $dbh = $self->_dbh;
77d76d0f 829 eval {
77d76d0f 830 if ($self->{transaction_depth} == 1) {
d32d82f9 831 $self->debugobj->txn_rollback()
832 if ($self->debug);
77d76d0f 833 $self->{transaction_depth} = 0
57c18b65 834 if $self->_dbh_autocommit;
835 $dbh->rollback;
d32d82f9 836 }
77d76d0f 837 elsif($self->{transaction_depth} > 1) {
838 $self->{transaction_depth}--;
986e4fca 839 }
f11383c2 840 else {
d32d82f9 841 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
986e4fca 842 }
77d76d0f 843 };
a62cf8d4 844 if ($@) {
845 my $error = $@;
846 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
847 $error =~ /$exception_class/ and $self->throw_exception($error);
77d76d0f 848 # ensure that a failed rollback resets the transaction depth
57c18b65 849 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 850 $self->throw_exception($error);
8091aa91 851 }
852}
8b445e33 853
b7151206 854# This used to be the top-half of _execute. It was split out to make it
855# easier to override in NoBindVars without duping the rest. It takes up
856# all of _execute's args, and emits $sql, @bind.
857sub _prep_for_execute {
d944c5ae 858 my ($self, $op, $extra_bind, $ident, $args) = @_;
b7151206 859
d944c5ae 860 my ($sql, @bind) = $self->sql_maker->$op($ident, @$args);
db4b5f11 861 unshift(@bind,
862 map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
863 if $extra_bind;
b7151206 864
d944c5ae 865 return ($sql, \@bind);
b7151206 866}
867
baa31d2f 868sub _dbh_execute {
869 my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
7af8b477 870
eda28767 871 if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
b7ce6568 872 $ident = $ident->from();
873 }
d944c5ae 874
875 my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args);
d92a4015 876
f59ffc79 877 if ($self->debug) {
db4b5f11 878 my @debug_bind =
d944c5ae 879 map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @$bind;
4c248161 880 $self->debugobj->query_start($sql, @debug_bind);
f59ffc79 881 }
95dad7e2 882
61646ebd 883 my $sth = $self->sth($sql,$op);
6e399b4f 884
61646ebd 885 my $placeholder_index = 1;
6e399b4f 886
61646ebd 887 foreach my $bound (@$bind) {
888 my $attributes = {};
889 my($column_name, @data) = @$bound;
6e399b4f 890
61646ebd 891 if ($bind_attributes) {
892 $attributes = $bind_attributes->{$column_name}
893 if defined $bind_attributes->{$column_name};
894 }
6e399b4f 895
61646ebd 896 foreach my $data (@data) {
897 $data = ref $data ? ''.$data : $data; # stringify args
0b5dee17 898
61646ebd 899 $sth->bind_param($placeholder_index, $data, $attributes);
900 $placeholder_index++;
95dad7e2 901 }
61646ebd 902 }
d92a4015 903
61646ebd 904 # Can this fail without throwing an exception anyways???
905 my $rv = $sth->execute();
906 $self->throw_exception($sth->errstr) if !$rv;
d92a4015 907
4c248161 908 if ($self->debug) {
f4afcd5d 909 my @debug_bind =
d944c5ae 910 map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @$bind;
f4afcd5d 911 $self->debugobj->query_end($sql, @debug_bind);
4c248161 912 }
baa31d2f 913
d944c5ae 914 return (wantarray ? ($rv, $sth, @$bind) : $rv);
223b8fe3 915}
916
baa31d2f 917sub _execute {
918 my $self = shift;
919 $self->dbh_do($self->can('_dbh_execute'), @_)
920}
921
8b445e33 922sub insert {
7af8b477 923 my ($self, $source, $to_insert) = @_;
924
925 my $ident = $source->from;
8b646589 926 my $bind_attributes = $self->source_bind_attributes($source);
927
61646ebd 928 $self->_execute('insert' => [], $source, $bind_attributes, $to_insert);
8e08ecc4 929
8b445e33 930 return $to_insert;
931}
932
744076d8 933## Still not quite perfect, and EXPERIMENTAL
934## Currently it is assumed that all values passed will be "normal", i.e. not
935## scalar refs, or at least, all the same type as the first set, the statement is
936## only prepped once.
54e0bd06 937sub insert_bulk {
9fdf90df 938 my ($self, $source, $cols, $data) = @_;
744076d8 939 my %colvalues;
9fdf90df 940 my $table = $source->from;
744076d8 941 @colvalues{@$cols} = (0..$#$cols);
942 my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
7af8b477 943
54e0bd06 944 if ($self->debug) {
9fdf90df 945 my @debug_bind = map { defined $_->[1] ? qq{$_->[1]} : q{'NULL'} } @bind;
54e0bd06 946 $self->debugobj->query_start($sql, @debug_bind);
947 }
894328b8 948 my $sth = $self->sth($sql);
54e0bd06 949
54e0bd06 950# @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
951
744076d8 952 ## This must be an arrayref, else nothing works!
9fdf90df 953
744076d8 954 my $tuple_status = [];
9fdf90df 955
956 ##use Data::Dumper;
957 ##print STDERR Dumper( $data, $sql, [@bind] );
eda28767 958
61646ebd 959 my $time = time();
8b646589 960
61646ebd 961 ## Get the bind_attributes, if any exist
962 my $bind_attributes = $self->source_bind_attributes($source);
9fdf90df 963
61646ebd 964 ## Bind the values and execute
965 my $placeholder_index = 1;
9fdf90df 966
61646ebd 967 foreach my $bound (@bind) {
9fdf90df 968
61646ebd 969 my $attributes = {};
970 my ($column_name, $data_index) = @$bound;
eda28767 971
61646ebd 972 if( $bind_attributes ) {
973 $attributes = $bind_attributes->{$column_name}
974 if defined $bind_attributes->{$column_name};
975 }
9fdf90df 976
61646ebd 977 my @data = map { $_->[$data_index] } @$data;
9fdf90df 978
61646ebd 979 $sth->bind_param_array( $placeholder_index, [@data], $attributes );
980 $placeholder_index++;
54e0bd06 981 }
61646ebd 982 my $rv = $sth->execute_array({ArrayTupleStatus => $tuple_status});
983 $self->throw_exception($sth->errstr) if !$rv;
984
54e0bd06 985 if ($self->debug) {
986 my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
987 $self->debugobj->query_end($sql, @debug_bind);
988 }
989 return (wantarray ? ($rv, $sth, @bind) : $rv);
990}
991
8b445e33 992sub update {
7af8b477 993 my $self = shift @_;
994 my $source = shift @_;
8b646589 995 my $bind_attributes = $self->source_bind_attributes($source);
8b646589 996
b7ce6568 997 return $self->_execute('update' => [], $source, $bind_attributes, @_);
8b445e33 998}
999
7af8b477 1000
8b445e33 1001sub delete {
7af8b477 1002 my $self = shift @_;
1003 my $source = shift @_;
1004
1005 my $bind_attrs = {}; ## If ever it's needed...
7af8b477 1006
b7ce6568 1007 return $self->_execute('delete' => [], $source, $bind_attrs, @_);
8b445e33 1008}
1009
de705b51 1010sub _select {
8b445e33 1011 my ($self, $ident, $select, $condition, $attrs) = @_;
223b8fe3 1012 my $order = $attrs->{order_by};
1013 if (ref $condition eq 'SCALAR') {
1014 $order = $1 if $$condition =~ s/ORDER BY (.*)$//i;
1015 }
8839560b 1016 if (exists $attrs->{group_by} || $attrs->{having}) {
bc0c9800 1017 $order = {
1018 group_by => $attrs->{group_by},
1019 having => $attrs->{having},
1020 ($order ? (order_by => $order) : ())
1021 };
54540863 1022 }
7af8b477 1023 my $bind_attrs = {}; ## Future support
1024 my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order);
9229f20a 1025 if ($attrs->{software_limit} ||
1026 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
1027 $attrs->{software_limit} = 1;
5c91499f 1028 } else {
0823196c 1029 $self->throw_exception("rows attribute must be positive if present")
1030 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
5c91499f 1031 push @args, $attrs->{rows}, $attrs->{offset};
1032 }
de705b51 1033 return $self->_execute(@args);
1034}
1035
8b646589 1036sub source_bind_attributes {
1037 my ($self, $source) = @_;
1038
1039 my $bind_attributes;
1040 foreach my $column ($source->columns) {
1041
1042 my $data_type = $source->column_info($column)->{data_type} || '';
1043 $bind_attributes->{$column} = $self->bind_attribute_by_data_type($data_type)
eda28767 1044 if $data_type;
8b646589 1045 }
1046
1047 return $bind_attributes;
1048}
1049
9b83fccd 1050=head2 select
1051
d3b0e369 1052=over 4
1053
1054=item Arguments: $ident, $select, $condition, $attrs
1055
1056=back
1057
9b83fccd 1058Handle a SQL select statement.
1059
1060=cut
1061
de705b51 1062sub select {
1063 my $self = shift;
1064 my ($ident, $select, $condition, $attrs) = @_;
e4eb8ee1 1065 return $self->cursor_class->new($self, \@_, $attrs);
8b445e33 1066}
1067
1a14aa3f 1068sub select_single {
de705b51 1069 my $self = shift;
1070 my ($rv, $sth, @bind) = $self->_select(@_);
6157db4f 1071 my @row = $sth->fetchrow_array;
a3eaff0e 1072 # Need to call finish() to work round broken DBDs
6157db4f 1073 $sth->finish();
1074 return @row;
1a14aa3f 1075}
1076
9b83fccd 1077=head2 sth
1078
d3b0e369 1079=over 4
1080
1081=item Arguments: $sql
1082
1083=back
1084
9b83fccd 1085Returns a L<DBI> sth (statement handle) for the supplied SQL.
1086
1087=cut
1088
d4f16b21 1089sub _dbh_sth {
1090 my ($self, $dbh, $sql) = @_;
b33697ef 1091
d32d82f9 1092 # 3 is the if_active parameter which avoids active sth re-use
b33697ef 1093 my $sth = $self->disable_sth_caching
1094 ? $dbh->prepare($sql)
1095 : $dbh->prepare_cached($sql, {}, 3);
1096
d92a4015 1097 # XXX You would think RaiseError would make this impossible,
1098 # but apparently that's not true :(
61646ebd 1099 $self->throw_exception($dbh->errstr) if !$sth;
b33697ef 1100
1101 $sth;
d32d82f9 1102}
1103
8b445e33 1104sub sth {
cb5f2eea 1105 my ($self, $sql) = @_;
d4f16b21 1106 $self->dbh_do($self->can('_dbh_sth'), $sql);
8b445e33 1107}
1108
d4f16b21 1109sub _dbh_columns_info_for {
1110 my ($self, $dbh, $table) = @_;
a32e8402 1111
d32d82f9 1112 if ($dbh->can('column_info')) {
a953d8d9 1113 my %result;
d32d82f9 1114 eval {
1115 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
1116 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
1117 $sth->execute();
1118 while ( my $info = $sth->fetchrow_hashref() ){
1119 my %column_info;
1120 $column_info{data_type} = $info->{TYPE_NAME};
1121 $column_info{size} = $info->{COLUMN_SIZE};
1122 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
1123 $column_info{default_value} = $info->{COLUMN_DEF};
1124 my $col_name = $info->{COLUMN_NAME};
1125 $col_name =~ s/^\"(.*)\"$/$1/;
1126
1127 $result{$col_name} = \%column_info;
0d67fe74 1128 }
d32d82f9 1129 };
093fc7a6 1130 return \%result if !$@ && scalar keys %result;
d32d82f9 1131 }
0d67fe74 1132
d32d82f9 1133 my %result;
88262f96 1134 my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0'));
d32d82f9 1135 $sth->execute;
1136 my @columns = @{$sth->{NAME_lc}};
1137 for my $i ( 0 .. $#columns ){
1138 my %column_info;
248bf0d0 1139 $column_info{data_type} = $sth->{TYPE}->[$i];
d32d82f9 1140 $column_info{size} = $sth->{PRECISION}->[$i];
1141 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
0d67fe74 1142
d32d82f9 1143 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
1144 $column_info{data_type} = $1;
1145 $column_info{size} = $2;
0d67fe74 1146 }
1147
d32d82f9 1148 $result{$columns[$i]} = \%column_info;
1149 }
248bf0d0 1150 $sth->finish;
1151
1152 foreach my $col (keys %result) {
1153 my $colinfo = $result{$col};
1154 my $type_num = $colinfo->{data_type};
1155 my $type_name;
1156 if(defined $type_num && $dbh->can('type_info')) {
1157 my $type_info = $dbh->type_info($type_num);
1158 $type_name = $type_info->{TYPE_NAME} if $type_info;
1159 $colinfo->{data_type} = $type_name if $type_name;
1160 }
1161 }
d32d82f9 1162
1163 return \%result;
1164}
1165
1166sub columns_info_for {
1167 my ($self, $table) = @_;
d4f16b21 1168 $self->dbh_do($self->can('_dbh_columns_info_for'), $table);
a953d8d9 1169}
1170
9b83fccd 1171=head2 last_insert_id
1172
1173Return the row id of the last insert.
1174
1175=cut
1176
d4f16b21 1177sub _dbh_last_insert_id {
1178 my ($self, $dbh, $source, $col) = @_;
1179 # XXX This is a SQLite-ism as a default... is there a DBI-generic way?
1180 $dbh->func('last_insert_rowid');
1181}
1182
843f8ecd 1183sub last_insert_id {
d4f16b21 1184 my $self = shift;
1185 $self->dbh_do($self->can('_dbh_last_insert_id'), @_);
843f8ecd 1186}
1187
9b83fccd 1188=head2 sqlt_type
1189
1190Returns the database driver name.
1191
1192=cut
1193
d4f16b21 1194sub sqlt_type { shift->dbh->{Driver}->{Name} }
1c339d71 1195
a71859b4 1196=head2 bind_attribute_by_data_type
1197
1198Given a datatype from column info, returns a database specific bind attribute for
1199$dbh->bind_param($val,$attribute) or nothing if we will let the database planner
1200just handle it.
1201
1202Generally only needed for special case column types, like bytea in postgres.
1203
1204=cut
1205
1206sub bind_attribute_by_data_type {
1207 return;
1208}
1209
58ded37e 1210=head2 create_ddl_dir
9b83fccd 1211
1212=over 4
1213
c9d2e0a2 1214=item Arguments: $schema \@databases, $version, $directory, $preversion, $sqlt_args
9b83fccd 1215
1216=back
1217
d3b0e369 1218Creates a SQL file based on the Schema, for each of the specified
9b83fccd 1219database types, in the given directory.
1220
9b83fccd 1221=cut
1222
e673f011 1223sub create_ddl_dir
1224{
c9d2e0a2 1225 my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_;
e673f011 1226
1227 if(!$dir || !-d $dir)
1228 {
1229 warn "No directory given, using ./\n";
1230 $dir = "./";
1231 }
1232 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
1233 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
1234 $version ||= $schema->VERSION || '1.x';
9e7b9292 1235 $sqltargs = { ( add_drop_table => 1 ), %{$sqltargs || {}} };
e673f011 1236
40dce2a5 1237 $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.08: '}
1238 . $self->_check_sqlt_message . q{'})
1239 if !$self->_check_sqlt_version;
e673f011 1240
c9d2e0a2 1241 my $sqlt = SQL::Translator->new({
1242# debug => 1,
1243 add_drop_table => 1,
1244 });
e673f011 1245 foreach my $db (@$databases)
1246 {
1247 $sqlt->reset();
1248 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
1249# $sqlt->parser_args({'DBIx::Class' => $schema);
c9d2e0a2 1250 $sqlt = $self->configure_sqlt($sqlt, $db);
e673f011 1251 $sqlt->data($schema);
1252 $sqlt->producer($db);
1253
1254 my $file;
1255 my $filename = $schema->ddl_filename($db, $dir, $version);
1256 if(-e $filename)
1257 {
c9d2e0a2 1258 warn("$filename already exists, skipping $db");
e673f011 1259 next;
1260 }
c9d2e0a2 1261
e673f011 1262 my $output = $sqlt->translate;
e673f011 1263 if(!$output)
1264 {
c9d2e0a2 1265 warn("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
e673f011 1266 next;
1267 }
c9d2e0a2 1268 if(!open($file, ">$filename"))
1269 {
1270 $self->throw_exception("Can't open $filename for writing ($!)");
1271 next;
1272 }
e673f011 1273 print $file $output;
1274 close($file);
c9d2e0a2 1275
1276 if($preversion)
1277 {
40dce2a5 1278 require SQL::Translator::Diff;
c9d2e0a2 1279
1280 my $prefilename = $schema->ddl_filename($db, $dir, $preversion);
e2c0df8e 1281# print "Previous version $prefilename\n";
c9d2e0a2 1282 if(!-e $prefilename)
1283 {
1284 warn("No previous schema file found ($prefilename)");
1285 next;
1286 }
1287 #### We need to reparse the SQLite file we just wrote, so that
1288 ## Diff doesnt get all confoosed, and Diff is *very* confused.
1289 ## FIXME: rip Diff to pieces!
1290# my $target_schema = $sqlt->schema;
1291# unless ( $target_schema->name ) {
1292# $target_schema->name( $filename );
1293# }
1294 my @input;
1295 push @input, {file => $prefilename, parser => $db};
1296 push @input, {file => $filename, parser => $db};
1297 my ( $source_schema, $source_db, $target_schema, $target_db ) = map {
1298 my $file = $_->{'file'};
1299 my $parser = $_->{'parser'};
1300
1301 my $t = SQL::Translator->new;
1302 $t->debug( 0 );
1303 $t->trace( 0 );
1304 $t->parser( $parser ) or die $t->error;
1305 my $out = $t->translate( $file ) or die $t->error;
1306 my $schema = $t->schema;
1307 unless ( $schema->name ) {
1308 $schema->name( $file );
1309 }
1310 ($schema, $parser);
1311 } @input;
1312
1313 my $diff = SQL::Translator::Diff::schema_diff($source_schema, $db,
1314 $target_schema, $db,
1315 {}
1316 );
1317 my $difffile = $schema->ddl_filename($db, $dir, $version, $preversion);
1318 print STDERR "Diff: $difffile: $db, $dir, $version, $preversion \n";
1319 if(-e $difffile)
1320 {
1321 warn("$difffile already exists, skipping");
1322 next;
1323 }
1324 if(!open $file, ">$difffile")
1325 {
1326 $self->throw_exception("Can't write to $difffile ($!)");
1327 next;
1328 }
1329 print $file $diff;
1330 close($file);
1331 }
e673f011 1332 }
c9d2e0a2 1333}
e673f011 1334
c9d2e0a2 1335sub configure_sqlt() {
1336 my $self = shift;
1337 my $tr = shift;
1338 my $db = shift || $self->sqlt_type;
1339 if ($db eq 'PostgreSQL') {
1340 $tr->quote_table_names(0);
1341 $tr->quote_field_names(0);
1342 }
1343 return $tr;
e673f011 1344}
1345
9b83fccd 1346=head2 deployment_statements
1347
d3b0e369 1348=over 4
1349
1350=item Arguments: $schema, $type, $version, $directory, $sqlt_args
1351
1352=back
1353
1354Returns the statements used by L</deploy> and L<DBIx::Class::Schema/deploy>.
1355The database driver name is given by C<$type>, though the value from
1356L</sqlt_type> is used if it is not specified.
1357
1358C<$directory> is used to return statements from files in a previously created
1359L</create_ddl_dir> directory and is optional. The filenames are constructed
1360from L<DBIx::Class::Schema/ddl_filename>, the schema name and the C<$version>.
1361
1362If no C<$directory> is specified then the statements are constructed on the
1363fly using L<SQL::Translator> and C<$version> is ignored.
1364
1365See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>.
9b83fccd 1366
1367=cut
1368
e673f011 1369sub deployment_statements {
1370 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
915919c5 1371 # Need to be connected to get the correct sqlt_type
c377d939 1372 $self->ensure_connected() unless $type;
e673f011 1373 $type ||= $self->sqlt_type;
1374 $version ||= $schema->VERSION || '1.x';
1375 $dir ||= './';
c9d2e0a2 1376 my $filename = $schema->ddl_filename($type, $dir, $version);
1377 if(-f $filename)
1378 {
1379 my $file;
1380 open($file, "<$filename")
1381 or $self->throw_exception("Can't open $filename ($!)");
1382 my @rows = <$file>;
1383 close($file);
1384 return join('', @rows);
1385 }
1386
40dce2a5 1387 $self->throw_exception(q{Can't deploy without SQL::Translator 0.08: '}
1388 . $self->_check_sqlt_message . q{'})
1389 if !$self->_check_sqlt_version;
1390
1391 require SQL::Translator::Parser::DBIx::Class;
1392 eval qq{use SQL::Translator::Producer::${type}};
1393 $self->throw_exception($@) if $@;
1394
1395 # sources needs to be a parser arg, but for simplicty allow at top level
1396 # coming in
1397 $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
1398 if exists $sqltargs->{sources};
1399
1400 my $tr = SQL::Translator->new(%$sqltargs);
1401 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
1402 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
e673f011 1403
c9d2e0a2 1404 return;
e673f011 1405
1c339d71 1406}
843f8ecd 1407
1c339d71 1408sub deploy {
260129d8 1409 my ($self, $schema, $type, $sqltargs, $dir) = @_;
1410 foreach my $statement ( $self->deployment_statements($schema, $type, undef, $dir, { no_comments => 1, %{ $sqltargs || {} } } ) ) {
61bf0de5 1411 foreach my $line ( split(";\n", $statement)) {
1412 next if($line =~ /^--/);
1413 next if(!$line);
1414# next if($line =~ /^DROP/m);
1415 next if($line =~ /^BEGIN TRANSACTION/m);
1416 next if($line =~ /^COMMIT/m);
1417 next if $line =~ /^\s+$/; # skip whitespace only
1418 $self->debugobj->query_start($line) if $self->debug;
1419 eval {
1420 $self->dbh->do($line); # shouldn't be using ->dbh ?
1421 };
1422 if ($@) {
1423 warn qq{$@ (running "${line}")};
1424 }
1425 $self->debugobj->query_end($line) if $self->debug;
e4fe9ba3 1426 }
75d07914 1427 }
1c339d71 1428}
843f8ecd 1429
9b83fccd 1430=head2 datetime_parser
1431
1432Returns the datetime parser class
1433
1434=cut
1435
f86fcf0d 1436sub datetime_parser {
1437 my $self = shift;
114780ee 1438 return $self->{datetime_parser} ||= do {
1439 $self->ensure_connected;
1440 $self->build_datetime_parser(@_);
1441 };
f86fcf0d 1442}
1443
9b83fccd 1444=head2 datetime_parser_type
1445
1446Defines (returns) the datetime parser class - currently hardwired to
1447L<DateTime::Format::MySQL>
1448
1449=cut
1450
f86fcf0d 1451sub datetime_parser_type { "DateTime::Format::MySQL"; }
1452
9b83fccd 1453=head2 build_datetime_parser
1454
1455See L</datetime_parser>
1456
1457=cut
1458
f86fcf0d 1459sub build_datetime_parser {
1460 my $self = shift;
1461 my $type = $self->datetime_parser_type(@_);
1462 eval "use ${type}";
1463 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1464 return $type;
1465}
1466
40dce2a5 1467{
1468 my $_check_sqlt_version; # private
1469 my $_check_sqlt_message; # private
1470 sub _check_sqlt_version {
1471 return $_check_sqlt_version if defined $_check_sqlt_version;
1472 eval 'use SQL::Translator 0.08';
1473 $_check_sqlt_message = $@ ? $@ : '';
1474 $_check_sqlt_version = $@ ? 0 : 1;
1475 }
1476
1477 sub _check_sqlt_message {
1478 _check_sqlt_version if !defined $_check_sqlt_message;
1479 $_check_sqlt_message;
1480 }
1481}
1482
c756145c 1483sub DESTROY {
1484 my $self = shift;
f5de3933 1485 return if !$self->_dbh;
c756145c 1486 $self->_verify_pid;
1487 $self->_dbh(undef);
1488}
92925617 1489
8b445e33 14901;
1491
9b83fccd 1492=head1 SQL METHODS
1493
1494The module defines a set of methods within the DBIC::SQL::Abstract
1495namespace. These build on L<SQL::Abstract::Limit> to provide the
1496SQL query functions.
1497
1498The following methods are extended:-
1499
1500=over 4
1501
1502=item delete
1503
1504=item insert
1505
1506=item select
1507
1508=item update
1509
1510=item limit_dialect
1511
2cc3a7be 1512See L</connect_info> for details.
1513For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1514
9b83fccd 1515=item quote_char
1516
2cc3a7be 1517See L</connect_info> for details.
1518For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1519
9b83fccd 1520=item name_sep
1521
2cc3a7be 1522See L</connect_info> for details.
1523For setting, this method is deprecated in favor of L</connect_info>.
bb4f246d 1524
9b83fccd 1525=back
1526
8b445e33 1527=head1 AUTHORS
1528
daec44b8 1529Matt S. Trout <mst@shadowcatsystems.co.uk>
8b445e33 1530
9f19b1d6 1531Andy Grundman <andy@hybridized.org>
1532
8b445e33 1533=head1 LICENSE
1534
1535You may distribute this code under the same terms as Perl itself.
1536
1537=cut