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