1 package DBIx::Class::Storage;
6 package # Hide from PAUSE
7 DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION;
9 use overload '"' => sub {
10 'DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION'
16 return bless $self, $class;
19 package DBIx::Class::Storage;
21 sub new { die "Virtual method!" }
22 sub set_schema { die "Virtual method!" }
23 sub debug { die "Virtual method!" }
24 sub debugcb { die "Virtual method!" }
25 sub debugfh { die "Virtual method!" }
26 sub debugobj { die "Virtual method!" }
27 sub cursor { die "Virtual method!" }
28 sub disconnect { die "Virtual method!" }
29 sub connected { die "Virtual method!" }
30 sub ensure_connected { die "Virtual method!" }
31 sub on_connect_do { die "Virtual method!" }
32 sub connect_info { die "Virtual method!" }
33 sub sql_maker { die "Virtual method!" }
34 sub txn_begin { die "Virtual method!" }
35 sub txn_commit { die "Virtual method!" }
36 sub txn_rollback { die "Virtual method!" }
37 sub insert { die "Virtual method!" }
38 sub update { die "Virtual method!" }
39 sub delete { die "Virtual method!" }
40 sub select { die "Virtual method!" }
41 sub select_single { die "Virtual method!" }
42 sub columns_info_for { die "Virtual method!" }
43 sub throw_exception { die "Virtual method!" }
49 =item Arguments: C<$coderef>, @coderef_args?
51 =item Return Value: The return value of $coderef
55 Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
56 returning its result (if any). If an exception is caught, a rollback is issued
57 and the exception is rethrown. If the rollback fails, (i.e. throws an
58 exception) an exception is thrown that includes a "Rollback failed" message.
62 my $author_rs = $schema->resultset('Author')->find(1);
63 my @titles = qw/Night Day It/;
66 # If any one of these fails, the entire transaction fails
67 $author_rs->create_related('books', {
71 return $author->books;
76 $rs = $schema->txn_do($coderef);
79 if ($@) { # Transaction failed
80 die "something terrible has happened!" #
81 if ($@ =~ /Rollback failed/); # Rollback failed
83 deal_with_failed_transaction();
86 In a nested transaction (calling txn_do() from within a txn_do() coderef) only
87 the outermost transaction will issue a L</txn_commit>, and txn_do() can be
88 called in void, scalar and list context and it will behave as expected.
93 my ($self, $coderef, @args) = @_;
95 ref $coderef eq 'CODE' or $self->throw_exception
96 ('$coderef must be a CODE reference');
98 my (@return_values, $return_value);
100 $self->txn_begin; # If this throws an exception, no rollback is needed
102 my $wantarray = wantarray; # Need to save this since the context
103 # inside the eval{} block is independent
104 # of the context that called txn_do()
107 # Need to differentiate between scalar/list context to allow for
108 # returning a list in scalar context to get the size of the list
111 @return_values = $coderef->(@args);
112 } elsif (defined $wantarray) {
114 $return_value = $coderef->(@args);
130 my $rollback_error = $@;
131 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
132 $self->throw_exception($error) # propagate nested rollback
133 if $rollback_error =~ /$exception_class/;
135 $self->throw_exception(
136 "Transaction aborted: $error. Rollback failed: ${rollback_error}"
139 $self->throw_exception($error); # txn failed but rollback succeeded
143 return $wantarray ? @return_values : $return_value;