Bring back the old code from resolve_prefetch so ash's code can work
[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;
550adccc 8use Carp::Clan qw/^DBIx::Class/;
8b445e33 9use DBI;
6f4ddea1 10use DBIx::Class::SQLAHacks;
28927b50 11use DBIx::Class::Storage::DBI::Cursor;
4c248161 12use DBIx::Class::Storage::Statistics;
664612fb 13use Scalar::Util qw/blessed weaken/;
046ad905 14
541df64a 15__PACKAGE__->mk_group_accessors('simple' =>
16 qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts
92fe2181 17 _conn_pid _conn_tid transaction_depth _dbh_autocommit savepoints/
046ad905 18);
19
92fe2181 20# the values for these accessors are picked out (and deleted) from
21# the attribute hashref passed to connect_info
22my @storage_options = qw/
23 on_connect_do on_disconnect_do disable_sth_caching unsafe auto_savepoint
24/;
25__PACKAGE__->mk_group_accessors('simple' => @storage_options);
26
27
28# default cursor class, overridable in connect_info attributes
e4eb8ee1 29__PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor');
30
95ba7ee4 31__PACKAGE__->mk_group_accessors('inherited' => qw/sql_maker_class/);
6f4ddea1 32__PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks');
95ba7ee4 33
bd7efd39 34
b327f988 35=head1 NAME
36
37DBIx::Class::Storage::DBI - DBI storage handler
38
39=head1 SYNOPSIS
40
5d52945a 41 my $schema = MySchema->connect('dbi:SQLite:my.db');
42
43 $schema->storage->debug(1);
44 $schema->dbh_do("DROP TABLE authors");
45
46 $schema->resultset('Book')->search({
47 written_on => $schema->storage->datetime_parser(DateTime->now)
48 });
49
b327f988 50=head1 DESCRIPTION
51
046ad905 52This class represents the connection to an RDBMS via L<DBI>. See
53L<DBIx::Class::Storage> for general information. This pod only
54documents DBI-specific methods and behaviors.
b327f988 55
56=head1 METHODS
57
9b83fccd 58=cut
59
8b445e33 60sub new {
046ad905 61 my $new = shift->next::method(@_);
82cc0386 62
d79f59b9 63 $new->transaction_depth(0);
2cc3a7be 64 $new->_sql_maker_opts({});
ddf66ced 65 $new->{savepoints} = [];
1b994857 66 $new->{_in_dbh_do} = 0;
dbaee748 67 $new->{_dbh_gen} = 0;
82cc0386 68
046ad905 69 $new;
1c339d71 70}
71
1b45b01e 72=head2 connect_info
73
92fe2181 74This method is normally called by L<DBIx::Class::Schema/connection>, which
75encapsulates its argument list in an arrayref before passing them here.
76
77The argument list may contain:
78
79=over
80
81=item *
82
5d52945a 83The same 4-element argument set one would normally pass to
40911cb3 84L<DBI/connect>, optionally followed by
85L<extra attributes|/DBIx::Class specific connection attributes>
86recognized by DBIx::Class:
92fe2181 87
5d52945a 88 $connect_info_args = [ $dsn, $user, $password, \%dbi_attributes?, \%extra_attributes? ];
92fe2181 89
90=item *
1b45b01e 91
40911cb3 92A single code reference which returns a connected
93L<DBI database handle|DBI/connect> optionally followed by
94L<extra attributes|/DBIx::Class specific connection attributes> recognized
95by DBIx::Class:
1b45b01e 96
5d52945a 97 $connect_info_args = [ sub { DBI->connect (...) }, \%extra_attributes? ];
92fe2181 98
99=item *
100
5d52945a 101A single hashref with all the attributes and the dsn/user/password
102mixed together:
92fe2181 103
104 $connect_info_args = [{
105 dsn => $dsn,
106 user => $user,
34f1f658 107 password => $pass,
92fe2181 108 %dbi_attributes,
109 %extra_attributes,
110 }];
111
112This is particularly useful for L<Catalyst> based applications, allowing the
40911cb3 113following config (L<Config::General> style):
92fe2181 114
115 <Model::DB>
116 schema_class App::DB
117 <connect_info>
118 dsn dbi:mysql:database=test
119 user testuser
120 password TestPass
121 AutoCommit 1
122 </connect_info>
123 </Model::DB>
124
125=back
126
5d52945a 127Please note that the L<DBI> docs recommend that you always explicitly
128set C<AutoCommit> to either I<0> or I<1>. L<DBIx::Class> further
129recommends that it be set to I<1>, and that you perform transactions
40911cb3 130via our L<DBIx::Class::Schema/txn_do> method. L<DBIx::Class> will set it
131to I<1> if you do not do explicitly set it to zero. This is the default
132for most DBDs. See L</DBIx::Class and AutoCommit> for details.
92fe2181 133
134=head3 DBIx::Class specific connection attributes
135
136In addition to the standard L<DBI|DBI/ATTRIBUTES_COMMON_TO_ALL_HANDLES>
137L<connection|DBI/Database_Handle_Attributes> attributes, DBIx::Class recognizes
138the following connection options. These options can be mixed in with your other
139L<DBI> connection attributes, or placed in a seperate hashref
140(C<\%extra_attributes>) as shown above.
141
142Every time C<connect_info> is invoked, any previous settings for
143these options will be cleared before setting the new ones, regardless of
144whether any options are specified in the new C<connect_info>.
d7c4c15c 145
2cc3a7be 146
5d52945a 147=over
2cc3a7be 148
149=item on_connect_do
150
6d2e7a96 151Specifies things to do immediately after connecting or re-connecting to
152the database. Its value may contain:
153
154=over
155
156=item an array reference
157
158This contains SQL statements to execute in order. Each element contains
159a string or a code reference that returns a string.
160
161=item a code reference
162
163This contains some code to execute. Unlike code references within an
164array reference, its return value is ignored.
165
166=back
579ca3f7 167
168=item on_disconnect_do
169
5d52945a 170Takes arguments in the same form as L</on_connect_do> and executes them
6d2e7a96 171immediately before disconnecting from the database.
579ca3f7 172
5d52945a 173Note, this only runs if you explicitly call L</disconnect> on the
579ca3f7 174storage object.
2cc3a7be 175
b33697ef 176=item disable_sth_caching
177
178If set to a true value, this option will disable the caching of
179statement handles via L<DBI/prepare_cached>.
180
2cc3a7be 181=item limit_dialect
182
183Sets the limit dialect. This is useful for JDBC-bridge among others
184where the remote SQL-dialect cannot be determined by the name of the
5d52945a 185driver alone. See also L<SQL::Abstract::Limit>.
2cc3a7be 186
187=item quote_char
d7c4c15c 188
2cc3a7be 189Specifies what characters to use to quote table and column names. If
5d52945a 190you use this you will want to specify L</name_sep> as well.
2cc3a7be 191
5d52945a 192C<quote_char> expects either a single character, in which case is it
193is placed on either side of the table/column name, or an arrayref of length
1942 in which case the table/column name is placed between the elements.
2cc3a7be 195
5d52945a 196For example under MySQL you should use C<< quote_char => '`' >>, and for
197SQL Server you should use C<< quote_char => [qw/[ ]/] >>.
2cc3a7be 198
199=item name_sep
200
40911cb3 201This only needs to be used in conjunction with C<quote_char>, and is used to
2cc3a7be 202specify the charecter that seperates elements (schemas, tables, columns) from
203each other. In most cases this is simply a C<.>.
204
5d52945a 205The consequences of not supplying this value is that L<SQL::Abstract>
206will assume DBIx::Class' uses of aliases to be complete column
207names. The output will look like I<"me.name"> when it should actually
208be I<"me"."name">.
209
61646ebd 210=item unsafe
211
212This Storage driver normally installs its own C<HandleError>, sets
2ab60eb9 213C<RaiseError> and C<ShowErrorStatement> on, and sets C<PrintError> off on
214all database handles, including those supplied by a coderef. It does this
215so that it can have consistent and useful error behavior.
61646ebd 216
217If you set this option to a true value, Storage will not do its usual
2ab60eb9 218modifications to the database handle's attributes, and instead relies on
219the settings in your connect_info DBI options (or the values you set in
220your connection coderef, in the case that you are connecting via coderef).
61646ebd 221
222Note that your custom settings can cause Storage to malfunction,
223especially if you set a C<HandleError> handler that suppresses exceptions
224and/or disable C<RaiseError>.
225
a3628767 226=item auto_savepoint
227
228If this option is true, L<DBIx::Class> will use savepoints when nesting
229transactions, making it possible to recover from failure in the inner
230transaction without having to abort all outer transactions.
231
34f1f658 232=item cursor_class
233
234Use this argument to supply a cursor class other than the default
235L<DBIx::Class::Storage::DBI::Cursor>.
236
2cc3a7be 237=back
238
5d52945a 239Some real-life examples of arguments to L</connect_info> and
240L<DBIx::Class::Schema/connect>
2cc3a7be 241
242 # Simple SQLite connection
bb4f246d 243 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
6789ebe3 244
2cc3a7be 245 # Connect via subref
bb4f246d 246 ->connect_info([ sub { DBI->connect(...) } ]);
6789ebe3 247
2cc3a7be 248 # A bit more complicated
bb4f246d 249 ->connect_info(
250 [
251 'dbi:Pg:dbname=foo',
252 'postgres',
253 'my_pg_password',
77d76d0f 254 { AutoCommit => 1 },
2cc3a7be 255 { quote_char => q{"}, name_sep => q{.} },
256 ]
257 );
258
259 # Equivalent to the previous example
260 ->connect_info(
261 [
262 'dbi:Pg:dbname=foo',
263 'postgres',
264 'my_pg_password',
77d76d0f 265 { AutoCommit => 1, quote_char => q{"}, name_sep => q{.} },
bb4f246d 266 ]
267 );
6789ebe3 268
92fe2181 269 # Same, but with hashref as argument
5d52945a 270 # See parse_connect_info for explanation
92fe2181 271 ->connect_info(
272 [{
273 dsn => 'dbi:Pg:dbname=foo',
274 user => 'postgres',
275 password => 'my_pg_password',
276 AutoCommit => 1,
277 quote_char => q{"},
278 name_sep => q{.},
279 }]
280 );
281
282 # Subref + DBIx::Class-specific connection options
bb4f246d 283 ->connect_info(
284 [
285 sub { DBI->connect(...) },
2cc3a7be 286 {
287 quote_char => q{`},
288 name_sep => q{@},
289 on_connect_do => ['SET search_path TO myschema,otherschema,public'],
b33697ef 290 disable_sth_caching => 1,
2cc3a7be 291 },
bb4f246d 292 ]
293 );
6789ebe3 294
92fe2181 295
296
004d31fb 297=cut
298
046ad905 299sub connect_info {
300 my ($self, $info_arg) = @_;
4c248161 301
046ad905 302 return $self->_connect_info if !$info_arg;
4c248161 303
92fe2181 304 my @args = @$info_arg; # take a shallow copy for further mutilation
305 $self->_connect_info([@args]); # copy for _connect_info
306
307
308 # combine/pre-parse arguments depending on invocation style
309
310 my %attrs;
311 if (ref $args[0] eq 'CODE') { # coderef with optional \%extra_attributes
312 %attrs = %{ $args[1] || {} };
313 @args = $args[0];
314 }
315 elsif (ref $args[0] eq 'HASH') { # single hashref (i.e. Catalyst config)
316 %attrs = %{$args[0]};
317 @args = ();
318 for (qw/password user dsn/) {
319 unshift @args, delete $attrs{$_};
320 }
321 }
34f1f658 322 else { # otherwise assume dsn/user/password + \%attrs + \%extra_attrs
92fe2181 323 %attrs = (
324 % { $args[3] || {} },
325 % { $args[4] || {} },
326 );
327 @args = @args[0,1,2];
328 }
329
046ad905 330 # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
331 # the new set of options
332 $self->_sql_maker(undef);
333 $self->_sql_maker_opts({});
8df3d107 334
92fe2181 335 if(keys %attrs) {
336 for my $storage_opt (@storage_options, 'cursor_class') { # @storage_options is declared at the top of the module
337 if(my $value = delete $attrs{$storage_opt}) {
b33697ef 338 $self->$storage_opt($value);
339 }
046ad905 340 }
341 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
92fe2181 342 if(my $opt_val = delete $attrs{$sql_maker_opt}) {
046ad905 343 $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
344 }
345 }
046ad905 346 }
d7c4c15c 347
92fe2181 348 %attrs = () if (ref $args[0] eq 'CODE'); # _connect() never looks past $args[0] in this case
349
350 $self->_dbi_connect_info([@args, keys %attrs ? \%attrs : ()]);
fdad5fab 351 $self->_connect_info;
046ad905 352}
004d31fb 353
046ad905 354=head2 on_connect_do
4c248161 355
5d52945a 356This method is deprecated in favour of setting via L</connect_info>.
486ad69b 357
92fe2181 358
f11383c2 359=head2 dbh_do
360
3ff1602f 361Arguments: ($subref | $method_name), @extra_coderef_args?
046ad905 362
3ff1602f 363Execute the given $subref or $method_name using the new exception-based
364connection management.
046ad905 365
d4f16b21 366The first two arguments will be the storage object that C<dbh_do> was called
367on and a database handle to use. Any additional arguments will be passed
368verbatim to the called subref as arguments 2 and onwards.
369
370Using this (instead of $self->_dbh or $self->dbh) ensures correct
371exception handling and reconnection (or failover in future subclasses).
372
373Your subref should have no side-effects outside of the database, as
374there is the potential for your subref to be partially double-executed
375if the database connection was stale/dysfunctional.
046ad905 376
56769f7c 377Example:
f11383c2 378
56769f7c 379 my @stuff = $schema->storage->dbh_do(
380 sub {
d4f16b21 381 my ($storage, $dbh, @cols) = @_;
382 my $cols = join(q{, }, @cols);
383 $dbh->selectrow_array("SELECT $cols FROM foo");
046ad905 384 },
385 @column_list
56769f7c 386 );
f11383c2 387
388=cut
389
390sub dbh_do {
046ad905 391 my $self = shift;
3ff1602f 392 my $code = shift;
aa27edf7 393
6ad1059d 394 my $dbh = $self->_dbh;
395
396 return $self->$code($dbh, @_) if $self->{_in_dbh_do}
cb19f4dd 397 || $self->{transaction_depth};
398
1b994857 399 local $self->{_in_dbh_do} = 1;
400
f11383c2 401 my @result;
402 my $want_array = wantarray;
403
404 eval {
6ad1059d 405 $self->_verify_pid if $dbh;
37976db0 406 if(!$self->_dbh) {
6ad1059d 407 $self->_populate_dbh;
408 $dbh = $self->_dbh;
409 }
410
f11383c2 411 if($want_array) {
6ad1059d 412 @result = $self->$code($dbh, @_);
f11383c2 413 }
56769f7c 414 elsif(defined $want_array) {
6ad1059d 415 $result[0] = $self->$code($dbh, @_);
f11383c2 416 }
56769f7c 417 else {
6ad1059d 418 $self->$code($dbh, @_);
56769f7c 419 }
f11383c2 420 };
56769f7c 421
aa27edf7 422 my $exception = $@;
423 if(!$exception) { return $want_array ? @result : $result[0] }
424
425 $self->throw_exception($exception) if $self->connected;
426
427 # We were not connected - reconnect and retry, but let any
428 # exception fall right through this time
429 $self->_populate_dbh;
3ff1602f 430 $self->$code($self->_dbh, @_);
aa27edf7 431}
432
433# This is basically a blend of dbh_do above and DBIx::Class::Storage::txn_do.
434# It also informs dbh_do to bypass itself while under the direction of txn_do,
1b994857 435# via $self->{_in_dbh_do} (this saves some redundant eval and errorcheck, etc)
aa27edf7 436sub txn_do {
437 my $self = shift;
438 my $coderef = shift;
439
440 ref $coderef eq 'CODE' or $self->throw_exception
441 ('$coderef must be a CODE reference');
442
d6feb60f 443 return $coderef->(@_) if $self->{transaction_depth} && ! $self->auto_savepoint;
57c18b65 444
1b994857 445 local $self->{_in_dbh_do} = 1;
f11383c2 446
aa27edf7 447 my @result;
448 my $want_array = wantarray;
449
d4f16b21 450 my $tried = 0;
451 while(1) {
452 eval {
453 $self->_verify_pid if $self->_dbh;
454 $self->_populate_dbh if !$self->_dbh;
aa27edf7 455
d4f16b21 456 $self->txn_begin;
457 if($want_array) {
458 @result = $coderef->(@_);
459 }
460 elsif(defined $want_array) {
461 $result[0] = $coderef->(@_);
462 }
463 else {
464 $coderef->(@_);
465 }
466 $self->txn_commit;
467 };
aa27edf7 468
d4f16b21 469 my $exception = $@;
470 if(!$exception) { return $want_array ? @result : $result[0] }
471
472 if($tried++ > 0 || $self->connected) {
473 eval { $self->txn_rollback };
474 my $rollback_exception = $@;
475 if($rollback_exception) {
476 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
477 $self->throw_exception($exception) # propagate nested rollback
478 if $rollback_exception =~ /$exception_class/;
479
480 $self->throw_exception(
481 "Transaction aborted: ${exception}. "
482 . "Rollback failed: ${rollback_exception}"
483 );
484 }
485 $self->throw_exception($exception)
aa27edf7 486 }
56769f7c 487
d4f16b21 488 # We were not connected, and was first try - reconnect and retry
489 # via the while loop
490 $self->_populate_dbh;
491 }
f11383c2 492}
493
9b83fccd 494=head2 disconnect
495
046ad905 496Our C<disconnect> method also performs a rollback first if the
9b83fccd 497database is not in C<AutoCommit> mode.
498
499=cut
500
412db1f4 501sub disconnect {
502 my ($self) = @_;
503
92925617 504 if( $self->connected ) {
6d2e7a96 505 my $connection_do = $self->on_disconnect_do;
506 $self->_do_connection_actions($connection_do) if ref($connection_do);
507
57c18b65 508 $self->_dbh->rollback unless $self->_dbh_autocommit;
92925617 509 $self->_dbh->disconnect;
510 $self->_dbh(undef);
dbaee748 511 $self->{_dbh_gen}++;
92925617 512 }
412db1f4 513}
514
e96a93df 515=head2 with_deferred_fk_checks
516
517=over 4
518
519=item Arguments: C<$coderef>
520
521=item Return Value: The return value of $coderef
522
523=back
524
525Storage specific method to run the code ref with FK checks deferred or
526in MySQL's case disabled entirely.
527
528=cut
529
530# Storage subclasses should override this
531sub with_deferred_fk_checks {
532 my ($self, $sub) = @_;
533
534 $sub->();
535}
536
f11383c2 537sub connected {
538 my ($self) = @_;
412db1f4 539
1346e22d 540 if(my $dbh = $self->_dbh) {
541 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
dbaee748 542 $self->_dbh(undef);
543 $self->{_dbh_gen}++;
544 return;
1346e22d 545 }
56769f7c 546 else {
547 $self->_verify_pid;
649bfb8c 548 return 0 if !$self->_dbh;
56769f7c 549 }
1346e22d 550 return ($dbh->FETCH('Active') && $dbh->ping);
551 }
552
553 return 0;
412db1f4 554}
555
f11383c2 556# handle pid changes correctly
56769f7c 557# NOTE: assumes $self->_dbh is a valid $dbh
f11383c2 558sub _verify_pid {
559 my ($self) = @_;
560
6ae3f9b9 561 return if defined $self->_conn_pid && $self->_conn_pid == $$;
f11383c2 562
f11383c2 563 $self->_dbh->{InactiveDestroy} = 1;
d3abf3fe 564 $self->_dbh(undef);
dbaee748 565 $self->{_dbh_gen}++;
f11383c2 566
567 return;
568}
569
412db1f4 570sub ensure_connected {
571 my ($self) = @_;
572
573 unless ($self->connected) {
8b445e33 574 $self->_populate_dbh;
575 }
412db1f4 576}
577
c235bbae 578=head2 dbh
579
580Returns the dbh - a data base handle of class L<DBI>.
581
582=cut
583
412db1f4 584sub dbh {
585 my ($self) = @_;
586
587 $self->ensure_connected;
8b445e33 588 return $self->_dbh;
589}
590
f1f56aad 591sub _sql_maker_args {
592 my ($self) = @_;
593
e5938571 594 return ( bindtype=>'columns', array_datatypes => 1, limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
f1f56aad 595}
596
48c69e7c 597sub sql_maker {
598 my ($self) = @_;
fdc1c3d0 599 unless ($self->_sql_maker) {
95ba7ee4 600 my $sql_maker_class = $self->sql_maker_class;
601 $self->_sql_maker($sql_maker_class->new( $self->_sql_maker_args ));
48c69e7c 602 }
603 return $self->_sql_maker;
604}
605
3ff1602f 606sub _rebless {}
607
8b445e33 608sub _populate_dbh {
609 my ($self) = @_;
7e47ea83 610 my @info = @{$self->_dbi_connect_info || []};
8b445e33 611 $self->_dbh($self->_connect(@info));
2fd24e78 612
77d76d0f 613 # Always set the transaction depth on connect, since
614 # there is no transaction in progress by definition
57c18b65 615 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 616
2fd24e78 617 if(ref $self eq 'DBIx::Class::Storage::DBI') {
618 my $driver = $self->_dbh->{Driver}->{Name};
efe6365b 619 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
2fd24e78 620 bless $self, "DBIx::Class::Storage::DBI::${driver}";
3ff1602f 621 $self->_rebless();
2fd24e78 622 }
843f8ecd 623 }
2fd24e78 624
1346e22d 625 $self->_conn_pid($$);
626 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
361ca8e5 627
628 my $connection_do = $self->on_connect_do;
629 $self->_do_connection_actions($connection_do) if ref($connection_do);
8b445e33 630}
631
6d2e7a96 632sub _do_connection_actions {
633 my $self = shift;
634 my $connection_do = shift;
635
636 if (ref $connection_do eq 'ARRAY') {
637 $self->_do_query($_) foreach @$connection_do;
638 }
639 elsif (ref $connection_do eq 'CODE') {
257d8d68 640 $connection_do->($self);
6d2e7a96 641 }
642
643 return $self;
644}
645
579ca3f7 646sub _do_query {
647 my ($self, $action) = @_;
648
6d2e7a96 649 if (ref $action eq 'CODE') {
1dafdb2a 650 $action = $action->($self);
651 $self->_do_query($_) foreach @$action;
579ca3f7 652 }
653 else {
c9225efc 654 # Most debuggers expect ($sql, @bind), so we need to exclude
655 # the attribute hash which is the second argument to $dbh->do
656 # furthermore the bind values are usually to be presented
657 # as named arrayref pairs, so wrap those here too
658 my @do_args = (ref $action eq 'ARRAY') ? (@$action) : ($action);
659 my $sql = shift @do_args;
660 my $attrs = shift @do_args;
661 my @bind = map { [ undef, $_ ] } @do_args;
662
663 $self->_query_start($sql, @bind);
664 $self->_dbh->do($sql, $attrs, @do_args);
665 $self->_query_end($sql, @bind);
579ca3f7 666 }
667
668 return $self;
669}
670
8b445e33 671sub _connect {
672 my ($self, @info) = @_;
5ef3e508 673
9d31f7dc 674 $self->throw_exception("You failed to provide any connection info")
61646ebd 675 if !@info;
9d31f7dc 676
90ec6cad 677 my ($old_connect_via, $dbh);
678
5ef3e508 679 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
61646ebd 680 $old_connect_via = $DBI::connect_via;
681 $DBI::connect_via = 'connect';
5ef3e508 682 }
683
75db246c 684 eval {
f5de3933 685 if(ref $info[0] eq 'CODE') {
686 $dbh = &{$info[0]}
687 }
688 else {
689 $dbh = DBI->connect(@info);
61646ebd 690 }
691
e7827df0 692 if($dbh && !$self->unsafe) {
664612fb 693 my $weak_self = $self;
694 weaken($weak_self);
61646ebd 695 $dbh->{HandleError} = sub {
9bf06dc0 696 if ($weak_self) {
697 $weak_self->throw_exception("DBI Exception: $_[0]");
698 }
699 else {
700 croak ("DBI Exception: $_[0]");
701 }
61646ebd 702 };
2ab60eb9 703 $dbh->{ShowErrorStatement} = 1;
61646ebd 704 $dbh->{RaiseError} = 1;
705 $dbh->{PrintError} = 0;
f5de3933 706 }
75db246c 707 };
90ec6cad 708
709 $DBI::connect_via = $old_connect_via if $old_connect_via;
710
d92a4015 711 $self->throw_exception("DBI Connection failed: " . ($@||$DBI::errstr))
712 if !$dbh || $@;
90ec6cad 713
57c18b65 714 $self->_dbh_autocommit($dbh->{AutoCommit});
715
e571e823 716 $dbh;
8b445e33 717}
718
adb3554a 719sub svp_begin {
720 my ($self, $name) = @_;
adb3554a 721
ddf66ced 722 $name = $self->_svp_generate_name
723 unless defined $name;
724
725 $self->throw_exception ("You can't use savepoints outside a transaction")
726 if $self->{transaction_depth} == 0;
727
728 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
729 unless $self->can('_svp_begin');
730
731 push @{ $self->{savepoints} }, $name;
adb3554a 732
adb3554a 733 $self->debugobj->svp_begin($name) if $self->debug;
ddf66ced 734
735 return $self->_svp_begin($name);
adb3554a 736}
737
738sub svp_release {
739 my ($self, $name) = @_;
740
ddf66ced 741 $self->throw_exception ("You can't use savepoints outside a transaction")
742 if $self->{transaction_depth} == 0;
adb3554a 743
ddf66ced 744 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
745 unless $self->can('_svp_release');
746
747 if (defined $name) {
748 $self->throw_exception ("Savepoint '$name' does not exist")
749 unless grep { $_ eq $name } @{ $self->{savepoints} };
750
751 # Dig through the stack until we find the one we are releasing. This keeps
752 # the stack up to date.
753 my $svp;
adb3554a 754
ddf66ced 755 do { $svp = pop @{ $self->{savepoints} } } while $svp ne $name;
756 } else {
757 $name = pop @{ $self->{savepoints} };
adb3554a 758 }
ddf66ced 759
adb3554a 760 $self->debugobj->svp_release($name) if $self->debug;
ddf66ced 761
762 return $self->_svp_release($name);
adb3554a 763}
764
765sub svp_rollback {
766 my ($self, $name) = @_;
767
ddf66ced 768 $self->throw_exception ("You can't use savepoints outside a transaction")
769 if $self->{transaction_depth} == 0;
adb3554a 770
ddf66ced 771 $self->throw_exception ("Your Storage implementation doesn't support savepoints")
772 unless $self->can('_svp_rollback');
773
774 if (defined $name) {
775 # If they passed us a name, verify that it exists in the stack
776 unless(grep({ $_ eq $name } @{ $self->{savepoints} })) {
777 $self->throw_exception("Savepoint '$name' does not exist!");
778 }
adb3554a 779
ddf66ced 780 # Dig through the stack until we find the one we are releasing. This keeps
781 # the stack up to date.
782 while(my $s = pop(@{ $self->{savepoints} })) {
783 last if($s eq $name);
784 }
785 # Add the savepoint back to the stack, as a rollback doesn't remove the
786 # named savepoint, only everything after it.
787 push(@{ $self->{savepoints} }, $name);
788 } else {
789 # We'll assume they want to rollback to the last savepoint
790 $name = $self->{savepoints}->[-1];
adb3554a 791 }
ddf66ced 792
adb3554a 793 $self->debugobj->svp_rollback($name) if $self->debug;
ddf66ced 794
795 return $self->_svp_rollback($name);
796}
797
798sub _svp_generate_name {
799 my ($self) = @_;
800
801 return 'savepoint_'.scalar(@{ $self->{'savepoints'} });
adb3554a 802}
d32d82f9 803
8091aa91 804sub txn_begin {
d79f59b9 805 my $self = shift;
291bf95f 806 $self->ensure_connected();
57c18b65 807 if($self->{transaction_depth} == 0) {
77d76d0f 808 $self->debugobj->txn_begin()
809 if $self->debug;
810 # this isn't ->_dbh-> because
811 # we should reconnect on begin_work
812 # for AutoCommit users
813 $self->dbh->begin_work;
d6feb60f 814 } elsif ($self->auto_savepoint) {
ddf66ced 815 $self->svp_begin;
986e4fca 816 }
57c18b65 817 $self->{transaction_depth}++;
8091aa91 818}
8b445e33 819
8091aa91 820sub txn_commit {
d79f59b9 821 my $self = shift;
77d76d0f 822 if ($self->{transaction_depth} == 1) {
823 my $dbh = $self->_dbh;
824 $self->debugobj->txn_commit()
825 if ($self->debug);
826 $dbh->commit;
827 $self->{transaction_depth} = 0
57c18b65 828 if $self->_dbh_autocommit;
77d76d0f 829 }
830 elsif($self->{transaction_depth} > 1) {
d6feb60f 831 $self->{transaction_depth}--;
ddf66ced 832 $self->svp_release
d6feb60f 833 if $self->auto_savepoint;
77d76d0f 834 }
d32d82f9 835}
836
77d76d0f 837sub txn_rollback {
838 my $self = shift;
839 my $dbh = $self->_dbh;
77d76d0f 840 eval {
77d76d0f 841 if ($self->{transaction_depth} == 1) {
d32d82f9 842 $self->debugobj->txn_rollback()
843 if ($self->debug);
77d76d0f 844 $self->{transaction_depth} = 0
57c18b65 845 if $self->_dbh_autocommit;
846 $dbh->rollback;
d32d82f9 847 }
77d76d0f 848 elsif($self->{transaction_depth} > 1) {
849 $self->{transaction_depth}--;
d6feb60f 850 if ($self->auto_savepoint) {
ddf66ced 851 $self->svp_rollback;
852 $self->svp_release;
d6feb60f 853 }
986e4fca 854 }
f11383c2 855 else {
d32d82f9 856 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
986e4fca 857 }
77d76d0f 858 };
a62cf8d4 859 if ($@) {
860 my $error = $@;
861 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
862 $error =~ /$exception_class/ and $self->throw_exception($error);
77d76d0f 863 # ensure that a failed rollback resets the transaction depth
57c18b65 864 $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
77d76d0f 865 $self->throw_exception($error);
8091aa91 866 }
867}
8b445e33 868
b7151206 869# This used to be the top-half of _execute. It was split out to make it
870# easier to override in NoBindVars without duping the rest. It takes up
871# all of _execute's args, and emits $sql, @bind.
872sub _prep_for_execute {
d944c5ae 873 my ($self, $op, $extra_bind, $ident, $args) = @_;
b7151206 874
59af6677 875 if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
876 $ident = $ident->from();
877 }
878
d944c5ae 879 my ($sql, @bind) = $self->sql_maker->$op($ident, @$args);
59af6677 880
db4b5f11 881 unshift(@bind,
882 map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
883 if $extra_bind;
d944c5ae 884 return ($sql, \@bind);
b7151206 885}
886
e5d9ee92 887sub _fix_bind_params {
888 my ($self, @bind) = @_;
889
890 ### Turn @bind from something like this:
891 ### ( [ "artist", 1 ], [ "cdid", 1, 3 ] )
892 ### to this:
893 ### ( "'1'", "'1'", "'3'" )
894 return
895 map {
896 if ( defined( $_ && $_->[1] ) ) {
897 map { qq{'$_'}; } @{$_}[ 1 .. $#$_ ];
898 }
899 else { q{'NULL'}; }
900 } @bind;
901}
902
903sub _query_start {
904 my ( $self, $sql, @bind ) = @_;
905
906 if ( $self->debug ) {
907 @bind = $self->_fix_bind_params(@bind);
50336325 908
e5d9ee92 909 $self->debugobj->query_start( $sql, @bind );
910 }
911}
912
913sub _query_end {
914 my ( $self, $sql, @bind ) = @_;
915
916 if ( $self->debug ) {
917 @bind = $self->_fix_bind_params(@bind);
918 $self->debugobj->query_end( $sql, @bind );
919 }
920}
921
baa31d2f 922sub _dbh_execute {
923 my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_;
d944c5ae 924
925 my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args);
d92a4015 926
e5d9ee92 927 $self->_query_start( $sql, @$bind );
95dad7e2 928
61646ebd 929 my $sth = $self->sth($sql,$op);
6e399b4f 930
61646ebd 931 my $placeholder_index = 1;
6e399b4f 932
61646ebd 933 foreach my $bound (@$bind) {
934 my $attributes = {};
935 my($column_name, @data) = @$bound;
6e399b4f 936
61646ebd 937 if ($bind_attributes) {
938 $attributes = $bind_attributes->{$column_name}
939 if defined $bind_attributes->{$column_name};
940 }
6e399b4f 941
61646ebd 942 foreach my $data (@data) {
272ffdb8 943 my $ref = ref $data;
944 $data = $ref && $ref ne 'ARRAY' ? ''.$data : $data; # stringify args (except arrayrefs)
0b5dee17 945
61646ebd 946 $sth->bind_param($placeholder_index, $data, $attributes);
947 $placeholder_index++;
95dad7e2 948 }
61646ebd 949 }
d92a4015 950
61646ebd 951 # Can this fail without throwing an exception anyways???
952 my $rv = $sth->execute();
953 $self->throw_exception($sth->errstr) if !$rv;
d92a4015 954
e5d9ee92 955 $self->_query_end( $sql, @$bind );
baa31d2f 956
d944c5ae 957 return (wantarray ? ($rv, $sth, @$bind) : $rv);
223b8fe3 958}
959
baa31d2f 960sub _execute {
961 my $self = shift;
3ff1602f 962 $self->dbh_do('_dbh_execute', @_)
baa31d2f 963}
964
8b445e33 965sub insert {
7af8b477 966 my ($self, $source, $to_insert) = @_;
967
968 my $ident = $source->from;
8b646589 969 my $bind_attributes = $self->source_bind_attributes($source);
970
c3af542a 971 my $updated_cols = {};
972
2eebd801 973 $self->ensure_connected;
a982c051 974 foreach my $col ( $source->columns ) {
975 if ( !defined $to_insert->{$col} ) {
976 my $col_info = $source->column_info($col);
977
978 if ( $col_info->{auto_nextval} ) {
c3af542a 979 $updated_cols->{$col} = $to_insert->{$col} = $self->_sequence_fetch( 'nextval', $col_info->{sequence} || $self->_dbh_get_autoinc_seq($self->dbh, $source) );
a982c051 980 }
981 }
982 }
983
61646ebd 984 $self->_execute('insert' => [], $source, $bind_attributes, $to_insert);
8e08ecc4 985
c3af542a 986 return $updated_cols;
8b445e33 987}
988
744076d8 989## Still not quite perfect, and EXPERIMENTAL
990## Currently it is assumed that all values passed will be "normal", i.e. not
991## scalar refs, or at least, all the same type as the first set, the statement is
992## only prepped once.
54e0bd06 993sub insert_bulk {
9fdf90df 994 my ($self, $source, $cols, $data) = @_;
744076d8 995 my %colvalues;
9fdf90df 996 my $table = $source->from;
744076d8 997 @colvalues{@$cols} = (0..$#$cols);
998 my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
7af8b477 999
e5d9ee92 1000 $self->_query_start( $sql, @bind );
894328b8 1001 my $sth = $self->sth($sql);
54e0bd06 1002
54e0bd06 1003# @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
1004
744076d8 1005 ## This must be an arrayref, else nothing works!
1006 my $tuple_status = [];
8b646589 1007
61646ebd 1008 ## Get the bind_attributes, if any exist
1009 my $bind_attributes = $self->source_bind_attributes($source);
9fdf90df 1010
61646ebd 1011 ## Bind the values and execute
1012 my $placeholder_index = 1;
9fdf90df 1013
61646ebd 1014 foreach my $bound (@bind) {
9fdf90df 1015
61646ebd 1016 my $attributes = {};
1017 my ($column_name, $data_index) = @$bound;
eda28767 1018
61646ebd 1019 if( $bind_attributes ) {
1020 $attributes = $bind_attributes->{$column_name}
1021 if defined $bind_attributes->{$column_name};
1022 }
9fdf90df 1023
61646ebd 1024 my @data = map { $_->[$data_index] } @$data;
9fdf90df 1025
61646ebd 1026 $sth->bind_param_array( $placeholder_index, [@data], $attributes );
1027 $placeholder_index++;
54e0bd06 1028 }
61646ebd 1029 my $rv = $sth->execute_array({ArrayTupleStatus => $tuple_status});
1030 $self->throw_exception($sth->errstr) if !$rv;
1031
e5d9ee92 1032 $self->_query_end( $sql, @bind );
54e0bd06 1033 return (wantarray ? ($rv, $sth, @bind) : $rv);
1034}
1035
8b445e33 1036sub update {
7af8b477 1037 my $self = shift @_;
1038 my $source = shift @_;
8b646589 1039 my $bind_attributes = $self->source_bind_attributes($source);
8b646589 1040
b7ce6568 1041 return $self->_execute('update' => [], $source, $bind_attributes, @_);
8b445e33 1042}
1043
7af8b477 1044
8b445e33 1045sub delete {
7af8b477 1046 my $self = shift @_;
1047 my $source = shift @_;
1048
1049 my $bind_attrs = {}; ## If ever it's needed...
7af8b477 1050
b7ce6568 1051 return $self->_execute('delete' => [], $source, $bind_attrs, @_);
8b445e33 1052}
1053
b2f73c30 1054# We were sent here because the $rs contains a complex search
1055# which will require a subquery to select the correct rows
1056# (i.e. joined or limited resultsets)
1057#
1058# Genarating a single PK column subquery is trivial and supported
1059# by all RDBMS. However if we have a multicolumn PK, things get ugly.
1060# Look at multipk_update_delete()
1061sub subq_update_delete {
1062 my $self = shift;
1063 my ($rs, $op, $values) = @_;
1064
1065 if ($rs->result_source->primary_columns == 1) {
1066 return $self->_onepk_update_delete (@_);
1067 }
1068 else {
1069 return $self->_multipk_update_delete (@_);
1070 }
1071}
1072
1073# Generally a single PK resultset operation is trivially expressed
1074# with PK IN (subquery). However some databases (mysql) do not support
1075# modification of a table mentioned in the subselect. This method
1076# should be overriden in the appropriate storage class to be smarter
1077# in such situations
1078sub _onepk_update_delete {
1079
1080 my $self = shift;
1081 my ($rs, $op, $values) = @_;
1082
1083 my $rsrc = $rs->result_source;
1084 my @pcols = $rsrc->primary_columns;
1085
1086 return $self->$op (
1087 $rsrc,
1088 $op eq 'update' ? $values : (),
1089 { $pcols[0] => { -in => $rs->get_column ($pcols[0])->as_query } },
1090 );
1091}
1092
1093# ANSI SQL does not provide a reliable way to perform a multicol-PK
1094# resultset update/delete involving subqueries. So resort to simple
1095# (and inefficient) delete_all style per-row opearations, while allowing
1096# specific storages to override this with a faster implementation.
1097#
1098# We do not use $row->$op style queries, because resultset update/delete
1099# is not expected to cascade (this is what delete_all/update_all is for).
1100#
1101# There should be no race conditions as the entire operation is rolled
1102# in a transaction.
1103sub _multipk_update_delete {
1104 my $self = shift;
1105 my ($rs, $op, $values) = @_;
1106
1107 my $rsrc = $rs->result_source;
1108 my @pcols = $rsrc->primary_columns;
1109
1110 my $guard = $self->txn_scope_guard;
1111
1112 my $subrs_cur = $rs->search ({}, { columns => \@pcols })->cursor;
1113 while (my @pks = $subrs_cur->next) {
1114
1115 my $cond;
1116 for my $i (0.. $#pcols) {
1117 $cond->{$pcols[$i]} = $pks[$i];
1118 }
1119
1120 $self->$op (
1121 $rsrc,
1122 $op eq 'update' ? $values : (),
1123 $cond,
1124 );
1125 }
1126
1127 $guard->commit;
1128
1129 return 1;
1130}
1131
1132
de705b51 1133sub _select {
59af6677 1134 my $self = shift;
1135 my $sql_maker = $self->sql_maker;
1136 local $sql_maker->{for};
1137 return $self->_execute($self->_select_args(@_));
1138}
1139
1140sub _select_args {
8b445e33 1141 my ($self, $ident, $select, $condition, $attrs) = @_;
223b8fe3 1142 my $order = $attrs->{order_by};
95ba7ee4 1143
95ba7ee4 1144 my $for = delete $attrs->{for};
1145 my $sql_maker = $self->sql_maker;
cc3b7709 1146 $sql_maker->{for} = $for;
95ba7ee4 1147
8839560b 1148 if (exists $attrs->{group_by} || $attrs->{having}) {
bc0c9800 1149 $order = {
1150 group_by => $attrs->{group_by},
1151 having => $attrs->{having},
1152 ($order ? (order_by => $order) : ())
1153 };
54540863 1154 }
7af8b477 1155 my $bind_attrs = {}; ## Future support
1156 my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order);
9229f20a 1157 if ($attrs->{software_limit} ||
1158 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
1159 $attrs->{software_limit} = 1;
5c91499f 1160 } else {
0823196c 1161 $self->throw_exception("rows attribute must be positive if present")
1162 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
e60dc79f 1163
1164 # MySQL actually recommends this approach. I cringe.
1165 $attrs->{rows} = 2**48 if not defined $attrs->{rows} and defined $attrs->{offset};
5c91499f 1166 push @args, $attrs->{rows}, $attrs->{offset};
1167 }
59af6677 1168 return @args;
de705b51 1169}
1170
8b646589 1171sub source_bind_attributes {
1172 my ($self, $source) = @_;
1173
1174 my $bind_attributes;
1175 foreach my $column ($source->columns) {
1176
1177 my $data_type = $source->column_info($column)->{data_type} || '';
1178 $bind_attributes->{$column} = $self->bind_attribute_by_data_type($data_type)
eda28767 1179 if $data_type;
8b646589 1180 }
1181
1182 return $bind_attributes;
1183}
1184
9b83fccd 1185=head2 select
1186
d3b0e369 1187=over 4
1188
1189=item Arguments: $ident, $select, $condition, $attrs
1190
1191=back
1192
9b83fccd 1193Handle a SQL select statement.
1194
1195=cut
1196
de705b51 1197sub select {
1198 my $self = shift;
1199 my ($ident, $select, $condition, $attrs) = @_;
e4eb8ee1 1200 return $self->cursor_class->new($self, \@_, $attrs);
8b445e33 1201}
1202
1a14aa3f 1203sub select_single {
de705b51 1204 my $self = shift;
1205 my ($rv, $sth, @bind) = $self->_select(@_);
6157db4f 1206 my @row = $sth->fetchrow_array;
27252a4a 1207 my @nextrow = $sth->fetchrow_array if @row;
1208 if(@row && @nextrow) {
1a4e8d7c 1209 carp "Query returned more than one row. SQL that returns multiple rows is DEPRECATED for ->find and ->single";
1210 }
a3eaff0e 1211 # Need to call finish() to work round broken DBDs
6157db4f 1212 $sth->finish();
1213 return @row;
1a14aa3f 1214}
1215
9b83fccd 1216=head2 sth
1217
d3b0e369 1218=over 4
1219
1220=item Arguments: $sql
1221
1222=back
1223
9b83fccd 1224Returns a L<DBI> sth (statement handle) for the supplied SQL.
1225
1226=cut
1227
d4f16b21 1228sub _dbh_sth {
1229 my ($self, $dbh, $sql) = @_;
b33697ef 1230
d32d82f9 1231 # 3 is the if_active parameter which avoids active sth re-use
b33697ef 1232 my $sth = $self->disable_sth_caching
1233 ? $dbh->prepare($sql)
1234 : $dbh->prepare_cached($sql, {}, 3);
1235
d92a4015 1236 # XXX You would think RaiseError would make this impossible,
1237 # but apparently that's not true :(
61646ebd 1238 $self->throw_exception($dbh->errstr) if !$sth;
b33697ef 1239
1240 $sth;
d32d82f9 1241}
1242
8b445e33 1243sub sth {
cb5f2eea 1244 my ($self, $sql) = @_;
3ff1602f 1245 $self->dbh_do('_dbh_sth', $sql);
8b445e33 1246}
1247
d4f16b21 1248sub _dbh_columns_info_for {
1249 my ($self, $dbh, $table) = @_;
a32e8402 1250
d32d82f9 1251 if ($dbh->can('column_info')) {
a953d8d9 1252 my %result;
d32d82f9 1253 eval {
1254 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
1255 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
1256 $sth->execute();
1257 while ( my $info = $sth->fetchrow_hashref() ){
1258 my %column_info;
1259 $column_info{data_type} = $info->{TYPE_NAME};
1260 $column_info{size} = $info->{COLUMN_SIZE};
1261 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
1262 $column_info{default_value} = $info->{COLUMN_DEF};
1263 my $col_name = $info->{COLUMN_NAME};
1264 $col_name =~ s/^\"(.*)\"$/$1/;
1265
1266 $result{$col_name} = \%column_info;
0d67fe74 1267 }
d32d82f9 1268 };
093fc7a6 1269 return \%result if !$@ && scalar keys %result;
d32d82f9 1270 }
0d67fe74 1271
d32d82f9 1272 my %result;
88262f96 1273 my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0'));
d32d82f9 1274 $sth->execute;
1275 my @columns = @{$sth->{NAME_lc}};
1276 for my $i ( 0 .. $#columns ){
1277 my %column_info;
248bf0d0 1278 $column_info{data_type} = $sth->{TYPE}->[$i];
d32d82f9 1279 $column_info{size} = $sth->{PRECISION}->[$i];
1280 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
0d67fe74 1281
d32d82f9 1282 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
1283 $column_info{data_type} = $1;
1284 $column_info{size} = $2;
0d67fe74 1285 }
1286
d32d82f9 1287 $result{$columns[$i]} = \%column_info;
1288 }
248bf0d0 1289 $sth->finish;
1290
1291 foreach my $col (keys %result) {
1292 my $colinfo = $result{$col};
1293 my $type_num = $colinfo->{data_type};
1294 my $type_name;
1295 if(defined $type_num && $dbh->can('type_info')) {
1296 my $type_info = $dbh->type_info($type_num);
1297 $type_name = $type_info->{TYPE_NAME} if $type_info;
1298 $colinfo->{data_type} = $type_name if $type_name;
1299 }
1300 }
d32d82f9 1301
1302 return \%result;
1303}
1304
1305sub columns_info_for {
1306 my ($self, $table) = @_;
3ff1602f 1307 $self->dbh_do('_dbh_columns_info_for', $table);
a953d8d9 1308}
1309
9b83fccd 1310=head2 last_insert_id
1311
1312Return the row id of the last insert.
1313
1314=cut
1315
d4f16b21 1316sub _dbh_last_insert_id {
93b7182b 1317 # All Storage's need to register their own _dbh_last_insert_id
1318 # the old SQLite-based method was highly inappropriate
1319
1320 my $self = shift;
1321 my $class = ref $self;
1322 $self->throw_exception (<<EOE);
1323
1324No _dbh_last_insert_id() method found in $class.
1325Since the method of obtaining the autoincrement id of the last insert
1326operation varies greatly between different databases, this method must be
1327individually implemented for every storage class.
1328EOE
d4f16b21 1329}
1330
843f8ecd 1331sub last_insert_id {
d4f16b21 1332 my $self = shift;
3ff1602f 1333 $self->dbh_do('_dbh_last_insert_id', @_);
843f8ecd 1334}
1335
9b83fccd 1336=head2 sqlt_type
1337
1338Returns the database driver name.
1339
1340=cut
1341
d4f16b21 1342sub sqlt_type { shift->dbh->{Driver}->{Name} }
1c339d71 1343
a71859b4 1344=head2 bind_attribute_by_data_type
1345
5d52945a 1346Given a datatype from column info, returns a database specific bind
40911cb3 1347attribute for C<< $dbh->bind_param($val,$attribute) >> or nothing if we will
5d52945a 1348let the database planner just handle it.
a71859b4 1349
1350Generally only needed for special case column types, like bytea in postgres.
1351
1352=cut
1353
1354sub bind_attribute_by_data_type {
1355 return;
1356}
1357
58ded37e 1358=head2 create_ddl_dir
9b83fccd 1359
1360=over 4
1361
348d7c84 1362=item Arguments: $schema \@databases, $version, $directory, $preversion, \%sqlt_args
9b83fccd 1363
1364=back
1365
d3b0e369 1366Creates a SQL file based on the Schema, for each of the specified
9b83fccd 1367database types, in the given directory.
1368
348d7c84 1369By default, C<\%sqlt_args> will have
1370
1371 { add_drop_table => 1, ignore_constraint_names => 1, ignore_index_names => 1 }
1372
1373merged with the hash passed in. To disable any of those features, pass in a
1374hashref like the following
1375
1376 { ignore_constraint_names => 0, # ... other options }
1377
9b83fccd 1378=cut
1379
99a74c4a 1380sub create_ddl_dir {
c9d2e0a2 1381 my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_;
e673f011 1382
99a74c4a 1383 if(!$dir || !-d $dir) {
341d5ede 1384 carp "No directory given, using ./\n";
e673f011 1385 $dir = "./";
1386 }
1387 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
1388 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
b1f9d92e 1389
1390 my $schema_version = $schema->schema_version || '1.x';
1391 $version ||= $schema_version;
1392
d4d46d19 1393 $sqltargs = {
1394 add_drop_table => 1,
1395 ignore_constraint_names => 1,
1396 ignore_index_names => 1,
1397 %{$sqltargs || {}}
1398 };
e673f011 1399
228d5eae 1400 $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.09003: '}
40dce2a5 1401 . $self->_check_sqlt_message . q{'})
1402 if !$self->_check_sqlt_version;
e673f011 1403
45f1a484 1404 my $sqlt = SQL::Translator->new( $sqltargs );
b7e303a8 1405
1406 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
341d5ede 1407 my $sqlt_schema = $sqlt->translate({ data => $schema })
1408 or $self->throw_exception ($sqlt->error);
b7e303a8 1409
99a74c4a 1410 foreach my $db (@$databases) {
e673f011 1411 $sqlt->reset();
b7e303a8 1412 $sqlt->{schema} = $sqlt_schema;
e673f011 1413 $sqlt->producer($db);
1414
1415 my $file;
99a74c4a 1416 my $filename = $schema->ddl_filename($db, $version, $dir);
b1f9d92e 1417 if (-e $filename && ($version eq $schema_version )) {
99a74c4a 1418 # if we are dumping the current version, overwrite the DDL
341d5ede 1419 carp "Overwriting existing DDL file - $filename";
99a74c4a 1420 unlink($filename);
1421 }
c9d2e0a2 1422
99a74c4a 1423 my $output = $sqlt->translate;
1424 if(!$output) {
341d5ede 1425 carp("Failed to translate to $db, skipping. (" . $sqlt->error . ")");
99a74c4a 1426 next;
1427 }
1428 if(!open($file, ">$filename")) {
1429 $self->throw_exception("Can't open $filename for writing ($!)");
1430 next;
1431 }
1432 print $file $output;
1433 close($file);
1434
1435 next unless ($preversion);
c9d2e0a2 1436
99a74c4a 1437 require SQL::Translator::Diff;
2dc2cd0f 1438
99a74c4a 1439 my $prefilename = $schema->ddl_filename($db, $preversion, $dir);
1440 if(!-e $prefilename) {
341d5ede 1441 carp("No previous schema file found ($prefilename)");
99a74c4a 1442 next;
1443 }
c9d2e0a2 1444
99a74c4a 1445 my $difffile = $schema->ddl_filename($db, $version, $dir, $preversion);
1446 if(-e $difffile) {
341d5ede 1447 carp("Overwriting existing diff file - $difffile");
99a74c4a 1448 unlink($difffile);
1449 }
1450
1451 my $source_schema;
1452 {
1453 my $t = SQL::Translator->new($sqltargs);
1454 $t->debug( 0 );
1455 $t->trace( 0 );
341d5ede 1456
1457 $t->parser( $db )
1458 or $self->throw_exception ($t->error);
1459
1460 my $out = $t->translate( $prefilename )
1461 or $self->throw_exception ($t->error);
1462
99a74c4a 1463 $source_schema = $t->schema;
341d5ede 1464
1465 $source_schema->name( $prefilename )
1466 unless ( $source_schema->name );
99a74c4a 1467 }
c9d2e0a2 1468
99a74c4a 1469 # The "new" style of producers have sane normalization and can support
1470 # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't
1471 # And we have to diff parsed SQL against parsed SQL.
1472 my $dest_schema = $sqlt_schema;
341d5ede 1473
99a74c4a 1474 unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) {
1475 my $t = SQL::Translator->new($sqltargs);
1476 $t->debug( 0 );
1477 $t->trace( 0 );
341d5ede 1478
1479 $t->parser( $db )
1480 or $self->throw_exception ($t->error);
1481
1482 my $out = $t->translate( $filename )
1483 or $self->throw_exception ($t->error);
1484
99a74c4a 1485 $dest_schema = $t->schema;
341d5ede 1486
99a74c4a 1487 $dest_schema->name( $filename )
1488 unless $dest_schema->name;
1489 }
1490
1491 my $diff = SQL::Translator::Diff::schema_diff($source_schema, $db,
1492 $dest_schema, $db,
1493 $sqltargs
1494 );
1495 if(!open $file, ">$difffile") {
1496 $self->throw_exception("Can't write to $difffile ($!)");
1497 next;
c9d2e0a2 1498 }
99a74c4a 1499 print $file $diff;
1500 close($file);
e673f011 1501 }
c9d2e0a2 1502}
e673f011 1503
9b83fccd 1504=head2 deployment_statements
1505
d3b0e369 1506=over 4
1507
1508=item Arguments: $schema, $type, $version, $directory, $sqlt_args
1509
1510=back
1511
1512Returns the statements used by L</deploy> and L<DBIx::Class::Schema/deploy>.
1513The database driver name is given by C<$type>, though the value from
1514L</sqlt_type> is used if it is not specified.
1515
1516C<$directory> is used to return statements from files in a previously created
1517L</create_ddl_dir> directory and is optional. The filenames are constructed
1518from L<DBIx::Class::Schema/ddl_filename>, the schema name and the C<$version>.
1519
1520If no C<$directory> is specified then the statements are constructed on the
1521fly using L<SQL::Translator> and C<$version> is ignored.
1522
1523See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>.
9b83fccd 1524
1525=cut
1526
e673f011 1527sub deployment_statements {
1528 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
915919c5 1529 # Need to be connected to get the correct sqlt_type
c377d939 1530 $self->ensure_connected() unless $type;
e673f011 1531 $type ||= $self->sqlt_type;
b1f9d92e 1532 $version ||= $schema->schema_version || '1.x';
e673f011 1533 $dir ||= './';
0233fc64 1534 my $filename = $schema->ddl_filename($type, $version, $dir);
c9d2e0a2 1535 if(-f $filename)
1536 {
1537 my $file;
1538 open($file, "<$filename")
1539 or $self->throw_exception("Can't open $filename ($!)");
1540 my @rows = <$file>;
1541 close($file);
1542 return join('', @rows);
1543 }
1544
228d5eae 1545 $self->throw_exception(q{Can't deploy without SQL::Translator 0.09003: '}
40dce2a5 1546 . $self->_check_sqlt_message . q{'})
1547 if !$self->_check_sqlt_version;
1548
1549 require SQL::Translator::Parser::DBIx::Class;
1550 eval qq{use SQL::Translator::Producer::${type}};
1551 $self->throw_exception($@) if $@;
1552
1553 # sources needs to be a parser arg, but for simplicty allow at top level
1554 # coming in
1555 $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
1556 if exists $sqltargs->{sources};
1557
1558 my $tr = SQL::Translator->new(%$sqltargs);
1559 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
1560 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
1c339d71 1561}
843f8ecd 1562
1c339d71 1563sub deploy {
260129d8 1564 my ($self, $schema, $type, $sqltargs, $dir) = @_;
11d8c781 1565 my $deploy = sub {
1566 my $line = shift;
1567 return if($line =~ /^--/);
1568 return if(!$line);
1569 # next if($line =~ /^DROP/m);
1570 return if($line =~ /^BEGIN TRANSACTION/m);
1571 return if($line =~ /^COMMIT/m);
1572 return if $line =~ /^\s+$/; # skip whitespace only
1573 $self->_query_start($line);
1574 eval {
1575 $self->dbh->do($line); # shouldn't be using ->dbh ?
1576 };
1577 if ($@) {
341d5ede 1578 carp qq{$@ (running "${line}")};
11d8c781 1579 }
1580 $self->_query_end($line);
1581 };
1582 my @statements = $self->deployment_statements($schema, $type, undef, $dir, { no_comments => 1, %{ $sqltargs || {} } } );
1583 if (@statements > 1) {
1584 foreach my $statement (@statements) {
1585 $deploy->( $statement );
1586 }
1587 }
1588 elsif (@statements == 1) {
1589 foreach my $line ( split(";\n", $statements[0])) {
1590 $deploy->( $line );
e4fe9ba3 1591 }
75d07914 1592 }
1c339d71 1593}
843f8ecd 1594
9b83fccd 1595=head2 datetime_parser
1596
1597Returns the datetime parser class
1598
1599=cut
1600
f86fcf0d 1601sub datetime_parser {
1602 my $self = shift;
114780ee 1603 return $self->{datetime_parser} ||= do {
1604 $self->ensure_connected;
1605 $self->build_datetime_parser(@_);
1606 };
f86fcf0d 1607}
1608
9b83fccd 1609=head2 datetime_parser_type
1610
1611Defines (returns) the datetime parser class - currently hardwired to
1612L<DateTime::Format::MySQL>
1613
1614=cut
1615
f86fcf0d 1616sub datetime_parser_type { "DateTime::Format::MySQL"; }
1617
9b83fccd 1618=head2 build_datetime_parser
1619
1620See L</datetime_parser>
1621
1622=cut
1623
f86fcf0d 1624sub build_datetime_parser {
1625 my $self = shift;
1626 my $type = $self->datetime_parser_type(@_);
1627 eval "use ${type}";
1628 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1629 return $type;
1630}
1631
40dce2a5 1632{
1633 my $_check_sqlt_version; # private
1634 my $_check_sqlt_message; # private
1635 sub _check_sqlt_version {
1636 return $_check_sqlt_version if defined $_check_sqlt_version;
228d5eae 1637 eval 'use SQL::Translator "0.09003"';
b7e303a8 1638 $_check_sqlt_message = $@ || '';
1639 $_check_sqlt_version = !$@;
40dce2a5 1640 }
1641
1642 sub _check_sqlt_message {
1643 _check_sqlt_version if !defined $_check_sqlt_message;
1644 $_check_sqlt_message;
1645 }
1646}
1647
106d5f3b 1648=head2 is_replicating
1649
1650A boolean that reports if a particular L<DBIx::Class::Storage::DBI> is set to
1651replicate from a master database. Default is undef, which is the result
1652returned by databases that don't support replication.
1653
1654=cut
1655
1656sub is_replicating {
1657 return;
1658
1659}
1660
1661=head2 lag_behind_master
1662
1663Returns a number that represents a certain amount of lag behind a master db
1664when a given storage is replicating. The number is database dependent, but
1665starts at zero and increases with the amount of lag. Default in undef
1666
1667=cut
1668
1669sub lag_behind_master {
1670 return;
1671}
1672
c756145c 1673sub DESTROY {
1674 my $self = shift;
f5de3933 1675 return if !$self->_dbh;
c756145c 1676 $self->_verify_pid;
1677 $self->_dbh(undef);
1678}
92925617 1679
8b445e33 16801;
1681
92fe2181 1682=head1 USAGE NOTES
1683
1684=head2 DBIx::Class and AutoCommit
1685
1686DBIx::Class can do some wonderful magic with handling exceptions,
1687disconnections, and transactions when you use C<< AutoCommit => 1 >>
1688combined with C<txn_do> for transaction support.
1689
1690If you set C<< AutoCommit => 0 >> in your connect info, then you are always
1691in an assumed transaction between commits, and you're telling us you'd
1692like to manage that manually. A lot of the magic protections offered by
1693this module will go away. We can't protect you from exceptions due to database
1694disconnects because we don't know anything about how to restart your
1695transactions. You're on your own for handling all sorts of exceptional
1696cases if you choose the C<< AutoCommit => 0 >> path, just as you would
1697be with raw DBI.
1698
1699
9b83fccd 1700
8b445e33 1701=head1 AUTHORS
1702
daec44b8 1703Matt S. Trout <mst@shadowcatsystems.co.uk>
8b445e33 1704
9f19b1d6 1705Andy Grundman <andy@hybridized.org>
1706
8b445e33 1707=head1 LICENSE
1708
1709You may distribute this code under the same terms as Perl itself.
1710
1711=cut