DBIC_TRACE_PROFILE
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage.pm
index eb87d4f..34c3eac 100644 (file)
@@ -4,11 +4,14 @@ use strict;
 use warnings;
 
 use base qw/DBIx::Class/;
+use mro 'c3';
 
-use Scalar::Util qw/weaken/;
-use Carp::Clan qw/^DBIx::Class/;
+use DBIx::Class::Exception;
+use Scalar::Util 'weaken';
 use IO::File;
 use DBIx::Class::Storage::TxnScopeGuard;
+use Try::Tiny;
+use namespace::clean;
 
 __PACKAGE__->mk_group_accessors('simple' => qw/debug debugobj schema/);
 __PACKAGE__->mk_group_accessors('inherited' => 'cursor_class');
@@ -60,9 +63,22 @@ sub new {
   bless $new, $self;
 
   $new->set_schema($schema);
-  $new->debugobj(new DBIx::Class::Storage::Statistics());
-
-  #my $fh;
+  my $debugobj;
+  if (my $profile = $ENV{DBIC_TRACE_PROFILE}) {
+    require DBIx::Class::Storage::Debug::PrettyPrint;
+    if ($profile =~ /^\.?\//) {
+      require Config::Any;
+      my $cfg = Config::Any->load_files({ files => [$profile], use_ext => 1 });
+
+      my ($filename, $config) = %{$cfg->[0]};
+      $debugobj = DBIx::Class::Storage::Debug::PrettyPrint->new($config)
+    } else {
+      $debugobj = DBIx::Class::Storage::Debug::PrettyPrint->new({ profile => $profile })
+    }
+  } else {
+    $debugobj = DBIx::Class::Storage::Statistics->new
+  }
+  $new->debugobj($debugobj);
 
   my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
                   || $ENV{DBIC_TRACE};
@@ -82,7 +98,7 @@ storage object, such as during L<DBIx::Class::Schema/clone>.
 sub set_schema {
   my ($self, $schema) = @_;
   $self->schema($schema);
-  weaken($self->{schema}) if ref $self->{schema};
+  weaken $self->{schema} if ref $self->{schema};
 }
 
 =head2 connected
@@ -119,8 +135,12 @@ Throws an exception - croaks.
 sub throw_exception {
   my $self = shift;
 
-  $self->schema->throw_exception(@_) if $self->schema;
-  croak @_;
+  if ($self->schema) {
+    $self->schema->throw_exception(@_);
+  }
+  else {
+    DBIx::Class::Exception->throw(@_);
+  }
 }
 
 =head2 txn_do
@@ -153,16 +173,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</txn_commit>, and txn_do() can be
@@ -180,7 +200,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');
@@ -190,45 +211,42 @@ 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;
 }
@@ -248,6 +266,9 @@ sub txn_begin { die "Virtual method!" }
 
 Issues a commit of the current transaction.
 
+It does I<not> perform an actual storage commit unless there's a DBIx::Class
+transaction currently in effect (i.e. you called L</txn_begin>).
+
 =cut
 
 sub txn_commit { die "Virtual method!" }
@@ -328,7 +349,7 @@ sub txn_scope_guard {
 =head2 sql_maker
 
 Returns a C<sql_maker> object - normally an object of class
-C<DBIC::SQL::Abstract>.
+C<DBIx::Class::SQLMaker>.
 
 =cut
 
@@ -345,7 +366,7 @@ shell environment.
 =head2 debugfh
 
 Set or retrieve the filehandle used for trace/debug output.  This should be
-an IO::Handle compatible ojbect (only the C<print> method is used.  Initially
+an IO::Handle compatible object (only the C<print> method is used.  Initially
 set to be STDERR - although see information on the
 L<DBIC_TRACE> environment variable.
 
@@ -475,10 +496,20 @@ If the value is of the form C<1=/path/name> then the trace output is
 written to the file C</path/name>.
 
 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<DBIC_TRACE_PROFILE> is set, L<DBIx::Class::Storage::PrettyPrint>
+will be used to format the output from C<DBIC_TRACE>.  The value it
+is set to is the C<profile> that it will be used.  If the value is a
+filename the file is read with L<Config::Any> and the results are
+used as the configuration for tracing.  See L<SQL::Abstract::Tree/new>
+for what that structure should look like.
+
+
 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
 
 Old name for DBIC_TRACE