X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI.pm;h=d07bb76d34b533aa7329dff0db75462e7e0130e9;hb=ea95892eb6a71366db32b04137c7f2ee3b4ef841;hp=ef0209244ffaf2a9f25a3601c724152c76ed16c2;hpb=05b22e331fab6a8c8773eb7bd52cb360ade69180;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index ef02092..d07bb76 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -54,10 +54,13 @@ __PACKAGE__->mk_group_accessors('simple' => @storage_options); # will get the same rdbms version). _determine_supports_X does not need to # exist on a driver, as we ->can for it before calling. -my @capabilities = (qw/insert_returning placeholders typeless_placeholders/); +my @capabilities = (qw/insert_returning placeholders typeless_placeholders join_optimizer/); __PACKAGE__->mk_group_accessors( dbms_capability => map { "_supports_$_" } @capabilities ); -__PACKAGE__->mk_group_accessors( use_dbms_capability => map { "_use_$_" } @capabilities ); +__PACKAGE__->mk_group_accessors( use_dbms_capability => map { "_use_$_" } (@capabilities ) ); +# on by default, not strictly a capability (pending rewrite) +__PACKAGE__->_use_join_optimizer (1); +sub _determine_supports_join_optimizer { 1 }; # Each of these methods need _determine_driver called before itself # in order to function reliably. This is a purely DRY optimization @@ -81,6 +84,9 @@ my @rdbms_specific_methods = qw/ get_use_dbms_capability get_dbms_capability + + _server_info + _get_server_version /; for my $meth (@rdbms_specific_methods) { @@ -93,7 +99,13 @@ for my $meth (@rdbms_specific_methods) { *{__PACKAGE__ ."::$meth"} = subname $meth => sub { if (not $_[0]->_driver_determined and not $_[0]->{_in_determine_driver}) { $_[0]->_determine_driver; - goto $_[0]->can($meth); + + # This for some reason crashes and burns on perl 5.8.1 + # IFF the method ends up throwing an exception + #goto $_[0]->can ($meth); + + my $cref = $_[0]->can ($meth); + goto $cref; } goto $orig; }; @@ -178,17 +190,8 @@ sub new { sub DESTROY { my $self = shift; - # destroy just the object if not native to this process/thread - $self->_preserve_foreign_dbh; - - # some databases need this to stop spewing warnings - if (my $dbh = $self->_dbh) { - try { - %{ $dbh->{CachedKids} } = (); - $dbh->disconnect; - }; - } - + # some databases spew warnings on implicit disconnect + local $SIG{__WARN__} = sub {}; $self->_dbh(undef); } @@ -453,8 +456,7 @@ of available limit dialects see L. =item quote_char -Specifies what characters to use to quote table and column names. If -you use this you will want to specify L as well. +Specifies what characters to use to quote table and column names. C expects either a single character, in which case is it is placed on either side of the table/column name, or an arrayref of length @@ -465,14 +467,9 @@ SQL Server you should use C<< quote_char => [qw/[ ]/] >>. =item name_sep -This only needs to be used in conjunction with C, and is used to +This parameter is only useful in conjunction with C, and is used to specify the character that separates elements (schemas, tables, columns) from -each other. In most cases this is simply a C<.>. - -The consequences of not supplying this value is that L -will assume DBIx::Class' uses of aliases to be complete column -names. The output will look like I<"me.name"> when it should actually -be I<"me"."name">. +each other. If unspecified it defaults to the most commonly used C<.>. =item unsafe @@ -525,7 +522,7 @@ L 'postgres', 'my_pg_password', { AutoCommit => 1 }, - { quote_char => q{"}, name_sep => q{.} }, + { quote_char => q{"} }, ] ); @@ -784,8 +781,6 @@ sub txn_do { ref $coderef eq 'CODE' or $self->throw_exception ('$coderef must be a CODE reference'); - return $coderef->(@_) if $self->{transaction_depth} && ! $self->auto_savepoint; - local $self->{_in_dbh_do} = 1; my @result; @@ -799,9 +794,8 @@ sub txn_do { my $args = \@_; try { - $self->_get_dbh; - $self->txn_begin; + my $txn_start_depth = $self->transaction_depth; if($want_array) { @result = $coderef->(@$args); } @@ -811,14 +805,22 @@ sub txn_do { else { $coderef->(@$args); } - $self->txn_commit; + + my $delta_txn = $txn_start_depth - $self->transaction_depth; + if ($delta_txn == 0) { + $self->txn_commit; + } + elsif ($delta_txn != 1) { + # an off-by-one would mean we fired a rollback + carp "Unexpected reduction of transaction depth by $delta_txn after execution of $coderef"; + } } catch { $exception = $_; }; if(! defined $exception) { return $want_array ? @result : $result[0] } - if($tried++ || $self->connected) { + if($self->transaction_depth > 1 || $tried++ || $self->connected) { my $rollback_exception; try { $self->txn_rollback } catch { $rollback_exception = shift }; if(defined $rollback_exception) { @@ -837,7 +839,7 @@ sub txn_do { # We were not connected, and was first try - reconnect and retry # via the while loop carp "Retrying $coderef after catching disconnected exception: $exception" - if $ENV{DBIC_DBIRETRY_DEBUG}; + if $ENV{DBIC_TXNRETRY_DEBUG}; $self->_populate_dbh; } } @@ -1001,6 +1003,7 @@ sub sql_maker { bindtype=>'columns', array_datatypes => 1, limit_dialect => $dialect, + name_sep => '.', %opts, )); } @@ -1375,9 +1378,8 @@ sub svp_rollback { } sub _svp_generate_name { - my ($self) = @_; - - return 'savepoint_'.scalar(@{ $self->{'savepoints'} }); + my ($self) = @_; + return 'savepoint_'.scalar(@{ $self->{'savepoints'} }); } sub txn_begin { @@ -1385,9 +1387,18 @@ sub txn_begin { # this means we have not yet connected and do not know the AC status # (e.g. coderef $dbh) - $self->ensure_connected if (! defined $self->_dbh_autocommit); + if (! defined $self->_dbh_autocommit) { + $self->ensure_connected; + } + # otherwise re-connect on pid changes, so + # that the txn_depth is adjusted properly + # the lightweight _get_dbh is good enoug here + # (only superficial handle check, no pings) + else { + $self->_get_dbh; + } - if($self->{transaction_depth} == 0) { + if($self->transaction_depth == 0) { $self->debugobj->txn_begin() if $self->debug; $self->_dbh_begin_work; @@ -1427,6 +1438,9 @@ sub txn_commit { $self->svp_release if $self->auto_savepoint; } + else { + $self->throw_exception( 'Refusing to commit without a started transaction' ); + } } sub _dbh_commit { @@ -1772,15 +1786,14 @@ sub _execute_array { } catch { $err = shift; + }; + + # Statement must finish even if there was an exception. + try { + $sth->finish } - finally { - # Statement must finish even if there was an exception. - try { - $sth->finish - } - catch { - $err = shift unless defined $err - }; + catch { + $err = shift unless defined $err }; $err = $sth->errstr