Fix func_rs() and as_subselect_rs() to start behaving as advertised
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Exception.pm
index 0580202..a5e9945 100644 (file)
 package DBIx::Class::Exception;
 
 use strict;
-use vars qw[@ISA $DBIC_EXCEPTION_CLASS];
-use UNIVERSAL::require;
+use warnings;
 
-BEGIN {
-    push( @ISA, $DBIC_EXCEPTION_CLASS || 'DBIx::Class::Exception::Base' );
-}
+# 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__) }++;
 
-package DBIx::Class::Exception::Base;
+use DBIx::Class::Carp ();
 
-use strict;
-use Carp ();
+use overload
+    '""' => sub { shift->{msg} },
+    fallback => 1;
 
 =head1 NAME
 
-DBIx::Class::Exception - DBIC Exception Class
+DBIx::Class::Exception - Exception objects for DBIx::Class
 
-=head1 SYNOPSIS
+=head1 DESCRIPTION
 
-   DBIx::Class::Exception->throw( qq/Fatal exception/ );
+Exception objects of this class are used internally by
+the default error handling of L<DBIx::Class::Schema/throw_exception>
+and derivatives.
 
-See also L<DBIx::Class>.
+These objects stringify to the contained error message, and use
+overload fallback to give natural boolean/numeric values.
 
-=head1 DESCRIPTION
+=head1 METHODS
 
-This is a generic Exception class for DBIx::Class. You can easily
-replace this with any mechanism implementing 'throw' by setting
-$DBix::Class::Exception::DBIC_EXCEPTION_CLASS
+=head2 throw
 
-=head1 METHODS
+=over 4
 
-=head2 throw( $message )
+=item Arguments: $exception_scalar, $stacktrace
 
-=head2 throw( message => $message )
+=back
 
-=head2 throw( error => $error )
+This is meant for internal use by L<DBIx::Class>'s C<throw_exception>
+code, and shouldn't be used directly elsewhere.
 
-Throws a fatal exception.
+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');
+  try { ... } catch { DBIx::Class::Exception->throw(shift) }
 
 =cut
 
 sub throw {
-    my $class  = shift;
-    my %params = @_ == 1 ? ( error => $_[0] ) : @_;
+    my ($class, $msg, $stacktrace) = @_;
+
+    # Don't re-encapsulate exception objects of any kind
+    die $msg if ref($msg);
+
+    # all exceptions include a caller
+    $msg =~ s/\n$//;
+
+    if(!$stacktrace) {
+        # 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',
+        );
 
-    my $message = $params{message} || $params{error} || $! || '';
+        $msg = "${calling}${msg} ${ln}\n";
+    }
+    else {
+        $msg = Carp::longmess($msg);
+    }
 
-    local $Carp::CarpLevel = (caller(1) eq 'NEXT' ? 2 : 1);
+    my $self = { msg => $msg };
+    bless $self => $class;
 
-    Carp::croak($message);
+    die $self;
 }
 
-=head1 AUTHOR
+=head2 rethrow
 
-Marcus Ramberg <mramberg@cpan.org>
+This method provides some syntactic sugar in order to
+re-throw exceptions.
+
+=cut
+
+sub rethrow {
+    die shift;
+}
 
-=head1 THANKS
+=head1 FURTHER QUESTIONS?
 
-Thanks to the L<Catalyst> framework, where this module was borrowed
-from.
+Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
 
-=head1 COPYRIGHT
+=head1 COPYRIGHT AND LICENSE
 
-This program is free software, you can redistribute it and/or modify
-it 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