Merge the last bits of indirect callchain optimization
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Exception.pm
index 77a3a96..a5e9945 100644 (file)
@@ -3,8 +3,12 @@ package DBIx::Class::Exception;
 use strict;
 use warnings;
 
-use Carp::Clan qw/^DBIx::Class/;
-use Scalar::Util qw/blessed/;
+# load Carp early to prevent tickling of the ::Internal stash being
+# interpreted as "Carp is already loaded" by some braindead loader
+use Carp ();
+$Carp::Internal{ (__PACKAGE__) }++;
+
+use DBIx::Class::Carp ();
 
 use overload
     '""' => sub { shift->{msg} },
@@ -16,10 +20,9 @@ DBIx::Class::Exception - Exception objects for DBIx::Class
 
 =head1 DESCRIPTION
 
-Exception objects of this class are used in internally by
-he default error handling of L<DBIx::Class::Schema/throw_exception>
-to prevent confusing and/or redundant re-application of L<Carp>'s
-stack trace information.
+Exception objects of this class are used internally by
+the default error handling of L<DBIx::Class::Schema/throw_exception>
+and derivatives.
 
 These objects stringify to the contained error message, and use
 overload fallback to give natural boolean/numeric values.
@@ -37,31 +40,37 @@ overload fallback to give natural boolean/numeric values.
 This is meant for internal use by L<DBIx::Class>'s C<throw_exception>
 code, and shouldn't be used directly elsewhere.
 
-Expects a scalar exception message.  The optional argument
-C<$stacktrace> tells it to use L<Carp/longmess> instead of
-L<Carp::Clan/croak>.
+Expects a scalar exception message. The optional boolean C<$stacktrace>
+causes it to output a full trace similar to L<confess|Carp/DESCRIPTION>.
 
   DBIx::Class::Exception->throw('Foo');
-  eval { ... }; DBIx::Class::Exception->throw($@) if $@;
+  try { ... } catch { DBIx::Class::Exception->throw(shift) }
 
 =cut
 
 sub throw {
     my ($class, $msg, $stacktrace) = @_;
 
-    # Don't re-encapsulate multiple times
-    die $msg if blessed($msg) && $msg->isa('DBIx::Class::Exception');
+    # Don't re-encapsulate exception objects of any kind
+    die $msg if ref($msg);
+
+    # all exceptions include a caller
+    $msg =~ s/\n$//;
 
-    # use Carp::Clan's croak if we're not stack tracing
     if(!$stacktrace) {
-        local $@;
-        eval { croak $msg };
-        $msg = $@
+        # skip all frames that match the original caller, or any of
+        # the dbic-wide classdata patterns
+        my ($ln, $calling) = DBIx::Class::Carp::__find_caller(
+          '^' . CORE::caller() . '$',
+          'DBIx::Class',
+        );
+
+        $msg = "${calling}${msg} ${ln}\n";
     }
     else {
         $msg = Carp::longmess($msg);
     }
-    
+
     my $self = { msg => $msg };
     bless $self => $class;
 
@@ -79,13 +88,16 @@ sub rethrow {
     die shift;
 }
 
-=head1 AUTHORS
+=head1 FURTHER QUESTIONS?
 
-Brandon L. Black <blblack@gmail.com>
+Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
 
-=head1 LICENSE
+=head1 COPYRIGHT AND LICENSE
 
-You may distribute this code under the same terms as Perl itself.
+This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
+by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
+redistribute it and/or modify it under the same terms as the
+L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
 
 =cut