SL::DB::with_transaction: Rückgabewert konsistenter gemacht
authorMoritz Bunkus <m.bunkus@linet-services.de>
Wed, 15 May 2013 10:02:06 +0000 (12:02 +0200)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Wed, 15 May 2013 10:02:30 +0000 (12:02 +0200)
Vorher gibt es mal den Rückgabewert von $code_ref, mal den von
Rose::DB::do_transaction. Nun ist es immer der von $code_ref, sofern
alles OK, und undef/() andernfalls -- inklusive Berücksichtigung des
Aufrufkontextes.

SL/DB.pm

index 90e08c5..5a22c5d 100644 (file)
--- a/SL/DB.pm
+++ b/SL/DB.pm
@@ -129,7 +129,15 @@ sub _flatten_settings {
 sub with_transaction {
   my ($self, $code, @args) = @_;
 
-  return $self->in_transaction ? $code->(@args) : $self->do_transaction(sub { $code->(@args) });
+  return $code->(@args) if $self->in_transaction;
+  if (wantarray) {
+    my @result;
+    return $self->do_transaction(sub { @result = $code->(@args) }) ? @result : ();
+
+  } else {
+    my $result;
+    return $self->do_transaction(sub { $result = $code->(@args) }) ? $result : undef;
+  }
 }
 
 1;
@@ -162,21 +170,27 @@ configuration.
 
 =item C<with_transaction $code_ref, @args>
 
-Executes C<$code_ref> within a transaction, starting one if none is
-currently active. This is just a shortcut for the following code:
-
-  # Verbose code in caller (an RDBO instance):
-  my $worker = sub {
-    # do stuff with $self
-  };
-  return $self->db->in_transaction ? $worker->() : $self->db->do_transaction($worker);
-
-Now the version using C<with_transaction>:
+Executes C<$code_ref> with parameters C<@args> within a transaction,
+starting one if none is currently active. Example:
 
   return $self->db->with_transaction(sub {
     # do stuff with $self
   });
 
+One big difference to L<Rose::DB/do_transaction> is the return code
+handling. If a transaction is already active then C<with_transcation>
+simply returns the result of calling C<$code_ref> as-is.
+
+Otherwise the return value depends on the result of the underlying
+transaction. If the transaction fails then C<undef> is returned in
+scalar context and an empty list in list context. If the transaction
+succeeds then the return value of C<$code_ref> is returned preserving
+context.
+
+So if you want to differentiate between "transaction failed" and
+"succeeded" then your C<$code_ref> should never return C<undef>
+itself.
+
 =back
 
 =head1 BUGS