X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage.pm;h=edfef850866823dcb37f38fc6fd71b3c2f33528d;hb=3b80fa31b60050d4c8df91457ba6fd51b579a7a6;hp=0def31530b0b2a400fef9323b9b83581de485aa6;hpb=48580715af3072905f2c71dc27e7f70f21a11338;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage.pm b/lib/DBIx/Class/Storage.pm index 0def315..edfef85 100644 --- a/lib/DBIx/Class/Storage.pm +++ b/lib/DBIx/Class/Storage.pm @@ -7,11 +7,12 @@ use base qw/DBIx::Class/; use mro 'c3'; use DBIx::Class::Exception; -use Scalar::Util(); -use IO::File; +use Scalar::Util 'weaken'; use DBIx::Class::Storage::TxnScopeGuard; +use Try::Tiny; +use namespace::clean; -__PACKAGE__->mk_group_accessors('simple' => qw/debug debugobj schema/); +__PACKAGE__->mk_group_accessors('simple' => qw/debug schema/); __PACKAGE__->mk_group_accessors('inherited' => 'cursor_class'); __PACKAGE__->cursor_class('DBIx::Class::Cursor'); @@ -61,14 +62,8 @@ sub new { bless $new, $self; $new->set_schema($schema); - $new->debugobj(new DBIx::Class::Storage::Statistics()); - - #my $fh; - - my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} - || $ENV{DBIC_TRACE}; - - $new->debug(1) if $debug_env; + $new->debug(1) + if $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} || $ENV{DBIC_TRACE}; $new; } @@ -83,7 +78,7 @@ storage object, such as during L. sub set_schema { my ($self, $schema) = @_; $self->schema($schema); - Scalar::Util::weaken($self->{schema}) if ref $self->{schema}; + weaken $self->{schema} if ref $self->{schema}; } =head2 connected @@ -120,7 +115,7 @@ Throws an exception - croaks. sub throw_exception { my $self = shift; - if ($self->schema) { + if (ref $self and $self->schema) { $self->schema->throw_exception(@_); } else { @@ -158,16 +153,16 @@ For example, }; my $rs; - eval { + try { $rs = $schema->txn_do($coderef); - }; - - if ($@) { # Transaction failed + } catch { + my $error = shift; + # Transaction failed die "something terrible has happened!" # - if ($@ =~ /Rollback failed/); # Rollback failed + if ($error =~ /Rollback failed/); # Rollback failed deal_with_failed_transaction(); - } + }; In a nested transaction (calling txn_do() from within a txn_do() coderef) only the outermost transaction will issue a L, and txn_do() can be @@ -185,7 +180,8 @@ transaction failure. =cut sub txn_do { - my ($self, $coderef, @args) = @_; + my $self = shift; + my $coderef = shift; ref $coderef eq 'CODE' or $self->throw_exception ('$coderef must be a CODE reference'); @@ -195,47 +191,44 @@ sub txn_do { $self->txn_begin; # If this throws an exception, no rollback is needed my $wantarray = wantarray; # Need to save this since the context - # inside the eval{} block is independent + # inside the try{} block is independent # of the context that called txn_do() - eval { + my $args = \@_; + + try { # Need to differentiate between scalar/list context to allow for # returning a list in scalar context to get the size of the list if ($wantarray) { # list context - @return_values = $coderef->(@args); + @return_values = $coderef->(@$args); } elsif (defined $wantarray) { # scalar context - $return_value = $coderef->(@args); + $return_value = $coderef->(@$args); } else { # void context - $coderef->(@args); + $coderef->(@$args); } $self->txn_commit; - }; - - if ($@) { - my $error = $@; + } + catch { + my $error = shift; - eval { + try { $self->txn_rollback; - }; - - if ($@) { - my $rollback_error = $@; + } catch { my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION"; $self->throw_exception($error) # propagate nested rollback - if $rollback_error =~ /$exception_class/; + if $_ =~ /$exception_class/; $self->throw_exception( - "Transaction aborted: $error. Rollback failed: ${rollback_error}" + "Transaction aborted: $error. Rollback failed: $_" ); - } else { - $self->throw_exception($error); # txn failed but rollback succeeded } - } + $self->throw_exception($error); # txn failed but rollback succeeded + }; - return $wantarray ? @return_values : $return_value; + return wantarray ? @return_values : $return_value; } =head2 txn_begin @@ -336,7 +329,7 @@ sub txn_scope_guard { =head2 sql_maker Returns a C object - normally an object of class -C. +C. =cut @@ -344,8 +337,8 @@ sub sql_maker { die "Virtual method!" } =head2 debug -Causes trace information to be emitted on the C object. -(or C if C has not specifically been set). +Causes trace information to be emitted on the L object. +(or C if L has not specifically been set). This is the equivalent to setting L in your shell environment. @@ -374,13 +367,49 @@ of L that is compatible with the original method of using a coderef as a callback. See the aforementioned Statistics class for more information. +=cut + +sub debugobj { + my $self = shift; + + if (@_) { + return $self->{debugobj} = $_[0]; + } + + $self->{debugobj} ||= do { + if (my $profile = $ENV{DBIC_TRACE_PROFILE}) { + require DBIx::Class::Storage::Debug::PrettyPrint; + if ($profile =~ /^\.?\//) { + require Config::Any; + + my $cfg = try { + Config::Any->load_files({ files => [$profile], use_ext => 1 }); + } catch { + # sanitize the error message a bit + $_ =~ s/at \s+ .+ Storage\.pm \s line \s \d+ $//x; + $self->throw_exception("Failure processing \$ENV{DBIC_TRACE_PROFILE}: $_"); + }; + + DBIx::Class::Storage::Debug::PrettyPrint->new(values %{$cfg->[0]}); + } + else { + DBIx::Class::Storage::Debug::PrettyPrint->new({ profile => $profile }); + } + } + else { + require DBIx::Class::Storage::Statistics; + DBIx::Class::Storage::Statistics->new + } + }; +} + =head2 debugcb Sets a callback to be executed each time a statement is run; takes a sub reference. Callback is executed as $sub->($op, $info) where $op is SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed. -See L for a better way. +See L for a better way. =cut @@ -477,16 +506,26 @@ sub columns_info_for { die "Virtual method!" } =head2 DBIC_TRACE If C is set then trace information -is produced (as when the L method is set). +is produced (as when the L method is set). If the value is of the form C<1=/path/name> then the trace output is written to the file C. This environment variable is checked when the storage object is first -created (when you call connect on your schema). So, run-time changes -to this environment variable will not take effect unless you also +created (when you call connect on your schema). So, run-time changes +to this environment variable will not take effect unless you also re-connect on your schema. +=head2 DBIC_TRACE_PROFILE + +If C is set, L +will be used to format the output from C. The value it +is set to is the C that it will be used. If the value is a +filename the file is read with L and the results are +used as the configuration for tracing. See L +for what that structure should look like. + + =head2 DBIX_CLASS_STORAGE_DBI_DEBUG Old name for DBIC_TRACE