X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI.pm;h=1f66d713adc8dda34f11ea333b4358ca6eb2f9ec;hb=5c33c8be;hp=0c388ed0546311ff7398add3bb017509d5da9366;hpb=84efb6d7f74f92330bf03e923a5386bbf5e7cf7e;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index 0c388ed..1f66d71 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -13,7 +13,12 @@ use List::Util qw/first/; use Context::Preserve 'preserve_context'; use Try::Tiny; use SQL::Abstract qw(is_plain_value is_literal_value); -use DBIx::Class::_Util qw(quote_sub perlstring serialize detected_reinvoked_destructor scope_guard); +use DBIx::Class::_Util qw( + quote_sub perlstring serialize + dbic_internal_try + detected_reinvoked_destructor scope_guard + mkdir_p +); use namespace::clean; # default cursor class, overridable in connect_info attributes @@ -221,6 +226,11 @@ sub new { weaken ( $seek_and_destroy{ refaddr($_[0]) } = $_[0] ); + + # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage + # collected before leaving this scope. Depending on the code above, this + # may very well be just a preventive measure guarding future modifications + undef; } END { @@ -235,6 +245,11 @@ sub new { # disarm the handle if not native to this process (see comment on top) $_->_verify_pid for @instances; } + + # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage + # collected before leaving this scope. Depending on the code above, this + # may very well be just a preventive measure guarding future modifications + undef; } sub CLONE { @@ -251,6 +266,11 @@ sub new { # properly renumber existing refs $_->_arm_global_destructor } + + # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage + # collected before leaving this scope. Depending on the code above, this + # may very well be just a preventive measure guarding future modifications + undef; } } @@ -266,11 +286,10 @@ sub DESTROY { $_[0]->_dbh(undef); # not calling ->disconnect here - we are being destroyed - nothing to reset - # this op is necessary, since the very last perl runtime statement - # triggers a global destruction shootout, and the $SIG localization - # may very well be destroyed before perl actually gets to do the - # $dbh undef - 1; + # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage + # collected before leaving this scope. Depending on the code above, this + # may very well be just a preventive measure guarding future modifications + undef; } # handle pid changes correctly - do not destroy parent's connection @@ -284,7 +303,10 @@ sub _verify_pid { $_[0]->disconnect; } - return; + # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage + # collected before leaving this scope. Depending on the code above, this + # may very well be just a preventive measure guarding future modifications + undef; } =head2 connect_info @@ -881,6 +903,10 @@ sub disconnect { # in order to unambiguously reset the state - do the cleanup in guard my $g = scope_guard { + + defined( $self->_dbh ) + and dbic_internal_try { $self->_dbh->disconnect }; + $self->_dbh(undef); $self->_dbh_details({}); $self->transaction_depth(undef); @@ -891,7 +917,7 @@ sub disconnect { #$self->_sql_maker(undef); # this may also end up being different }; - if( my $dbh = $self->_dbh ) { + if( $self->_dbh ) { $self->_do_connection_actions(disconnect_call_ => $_) for ( ( $self->on_disconnect_call || () ), @@ -900,11 +926,12 @@ sub disconnect { # stops the "implicit rollback on disconnect" warning $self->_exec_txn_rollback unless $self->_dbh_autocommit; - - %{ $dbh->{CachedKids} } = (); - - $dbh->disconnect; } + + # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage + # collected before leaving this scope. Depending on the code above, this + # may very well be just a preventive measure guarding future modifications + undef; } =head2 with_deferred_fk_checks @@ -956,7 +983,15 @@ sub connected { sub _seems_connected { $_[0]->_verify_pid unless DBIx::Class::_ENV_::BROKEN_FORK; - ($_[0]->_dbh || return 0)->FETCH('Active'); + $_[0]->_dbh + and + $_[0]->_dbh->FETCH('Active') + and + return 1; + + # explicitly reset all state + $_[0]->disconnect; + return 0; } sub _ping { @@ -1138,7 +1173,7 @@ sub _server_info { my $info = {}; - my $server_version = try { + my $server_version = dbic_internal_try { $self->_get_server_version } catch { # driver determination *may* use this codepath @@ -1199,7 +1234,7 @@ sub _describe_connection { my $self = shift; my $drv; - try { + dbic_internal_try { $drv = $self->_extract_driver_from_connect_info; $self->ensure_connected; }; @@ -1213,7 +1248,7 @@ sub _describe_connection { DBIC_DRIVER => ref $self, $drv ? ( DBD => $drv, - DBD_VER => try { $drv->VERSION }, + DBD_VER => dbic_internal_try { $drv->VERSION }, ) : (), }; @@ -1254,7 +1289,7 @@ sub _describe_connection { ) { # some drivers barf on things they do not know about instead # of returning undef - my $v = try { $self->_dbh_get_info($inf) }; + my $v = dbic_internal_try { $self->_dbh_get_info($inf) }; next unless defined $v; #my $key = sprintf( '%s(%s)', $inf, $DBI::Const::GetInfoType::GetInfoType{$inf} ); @@ -1396,7 +1431,7 @@ sub _warn_undetermined_driver { sub _do_connection_actions { my ($self, $method_prefix, $call, @args) = @_; - try { + dbic_internal_try { if (not ref($call)) { my $method = $method_prefix . $call; $self->$method(@args); @@ -1520,7 +1555,7 @@ sub _connect { }, '__DBIC__DBH__ERROR__HANDLER__'; }; - try { + dbic_internal_try { if(ref $info->[0] eq 'CODE') { $dbh = $info->[0]->(); } @@ -1990,7 +2025,7 @@ sub insert { if (my $retlist = $sqla_opts->{returning}) { # if IR is supported - we will get everything in one set unless( @ir_container ) { - try { + dbic_internal_try { # FIXME - need to investigate why Caelum silenced this in 4d4dc518 local $SIG{__WARN__} = sub {}; @@ -2335,7 +2370,7 @@ sub _dbh_execute_for_fetch { my $tuple_status = []; my ($rv, $err); - try { + dbic_internal_try { $rv = $sth->execute_for_fetch( $fetch_tuple, $tuple_status, @@ -2354,7 +2389,7 @@ sub _dbh_execute_for_fetch { ); # Statement must finish even if there was an exception. - try { + dbic_internal_try { $sth->finish } catch { @@ -2382,7 +2417,7 @@ sub _dbh_execute_inserts_with_no_binds { my ($self, $sth, $count) = @_; my $err; - try { + dbic_internal_try { my $dbh = $self->_get_dbh; local $dbh->{RaiseError} = 1; local $dbh->{PrintError} = 0; @@ -2394,7 +2429,7 @@ sub _dbh_execute_inserts_with_no_binds { }; # Make sure statement is finished even if there was an exception. - try { + dbic_internal_try { $sth->finish } catch { @@ -2493,7 +2528,7 @@ sub _select_args { and @{$attrs->{group_by}} and - my $grp_aliases = try { # try{} because $attrs->{from} may be unreadable + my $grp_aliases = dbic_internal_try { # internal_try{} because $attrs->{from} may be unreadable $self->_resolve_aliastypes_from_select_args({ from => $attrs->{from}, group_by => $attrs->{group_by} }) } ) { @@ -2610,7 +2645,7 @@ sub _dbh_columns_info_for { my %result; if (! DBIx::Class::_ENV_::STRESSTEST_COLUMN_INFO_UNAWARE_STORAGE and $dbh->can('column_info')) { - try { + dbic_internal_try { my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table); my $sth = $dbh->column_info( undef,$schema, $tab, '%' ); $sth->execute(); @@ -2714,7 +2749,7 @@ Return the row id of the last insert. sub _dbh_last_insert_id { my ($self, $dbh, $source, $col) = @_; - my $id = try { $dbh->last_insert_id (undef, undef, $source->name, $col) }; + my $id = dbic_internal_try { $dbh->last_insert_id (undef, undef, $source->name, $col) }; return $id if defined $id; @@ -2765,15 +2800,15 @@ sub _determine_supports_placeholders { # some drivers provide a $dbh attribute (e.g. Sybase and $dbh->{syb_dynamic_supported}) # but it is inaccurate more often than not - return try { + ( dbic_internal_try { local $dbh->{PrintError} = 0; local $dbh->{RaiseError} = 1; $dbh->do('select ?', {}, 1); 1; - } - catch { - 0; - }; + } ) + ? 1 + : 0 + ; } # Check if placeholders bound to non-string types throw exceptions @@ -2782,16 +2817,16 @@ sub _determine_supports_typeless_placeholders { my $self = shift; my $dbh = $self->_get_dbh; - return try { + ( dbic_internal_try { local $dbh->{PrintError} = 0; local $dbh->{RaiseError} = 1; # this specifically tests a bind that is NOT a string $dbh->do('select 1 where 1 = ?', {}, 1); 1; - } - catch { - 0; - }; + } ) + ? 1 + : 0 + ; } =head2 sqlt_type @@ -2901,20 +2936,18 @@ them. sub create_ddl_dir { my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_; - unless ($dir) { + require DBIx::Class::Optional::Dependencies; + if (my $missing = DBIx::Class::Optional::Dependencies->req_missing_for ('deploy')) { + $self->throw_exception("Can't create a ddl file without $missing"); + } + + if (!$dir) { carp "No directory given, using ./\n"; $dir = './'; - } else { - -d $dir - or - (require File::Path and File::Path::mkpath (["$dir"])) # mkpath does not like objects (i.e. Path::Class::Dir) - or - $self->throw_exception( - "Failed to create '$dir': " . ($! || $@ || 'error unknown') - ); } - - $self->throw_exception ("Directory '$dir' does not exist\n") unless(-d $dir); + else { + mkdir_p( $dir ) unless -d $dir; + } $databases ||= ['MySQL', 'SQLite', 'PostgreSQL']; $databases = [ $databases ] if(ref($databases) ne 'ARRAY'); @@ -2930,10 +2963,6 @@ sub create_ddl_dir { %{$sqltargs || {}} }; - if (my $missing = DBIx::Class::Optional::Dependencies->req_missing_for ('deploy')) { - $self->throw_exception("Can't create a ddl file without $missing"); - } - my $sqlt = SQL::Translator->new( $sqltargs ); $sqlt->parser('SQL::Translator::Parser::DBIx::Class'); @@ -3087,6 +3116,7 @@ sub deployment_statements { return join('', @rows); } + require DBIx::Class::Optional::Dependencies; if (my $missing = DBIx::Class::Optional::Dependencies->req_missing_for ('deploy') ) { $self->throw_exception("Can't deploy without a pregenerated 'ddl_dir' directory or $missing"); } @@ -3127,7 +3157,7 @@ sub deploy { return if($line =~ /^COMMIT/m); return if $line =~ /^\s+$/; # skip whitespace only $self->_query_start($line); - try { + dbic_internal_try { # do a dbh_do cycle here, as we need some error checking in # place (even though we will ignore errors) $self->dbh_do (sub { $_[1]->do($line) });