=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');
my $wantarray = wantarray; # Need to save this since the context
# inside the try{} block is independent
# of the context that called txn_do()
+ 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;
}
local $self->{_in_dbh_do} = 1;
- my @args = @_;
+ # take a ref instead of a copy, to preserve coderef @_ aliasing semantics
+ my $args = \@_;
return try {
- $self->$code ($dbh, @args);
+ $self->$code ($dbh, @$args);
} catch {
$self->throw_exception($_) if $self->connected;
if $ENV{DBIC_DBIRETRY_DEBUG};
$self->_populate_dbh;
- $self->$code($self->_dbh, @args);
+ $self->$code($self->_dbh, @$args);
};
}
my $tried = 0;
while(1) {
my $exception;
- my @args = @_;
+
+ # take a ref instead of a copy, to preserve coderef @_ aliasing semantics
+ my $args = \@_;
+
try {
$self->_get_dbh;
$self->txn_begin;
if($want_array) {
- @result = $coderef->(@args);
+ @result = $coderef->(@$args);
}
elsif(defined $want_array) {
- $result[0] = $coderef->(@args);
+ $result[0] = $coderef->(@$args);
}
else {
- $coderef->(@args);
+ $coderef->(@$args);
}
$self->txn_commit;
} catch {
[ $storage, $storage->dbh, "baz", "buz" ],
);
+# test aliasing
+my $res = 'original';
+$storage->dbh_do (sub { $_[2] = 'changed' }, $res);
+
+is ($res, 'changed', "Arguments properly aliased for dbh_do");
+
done_testing;
is( $schema->storage->{transaction_depth}, 0, 'txn depth has been reset');
}
+# Test txn_do() @_ aliasing support
+{
+ my $res = 'original';
+ $schema->storage->txn_do (sub { $_[0] = 'changed' }, $res);
+ is ($res, 'changed', "Arguments properly aliased for txn_do");
+}
+
# Test nested successful txn_do()
{
is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
is($schema->storage->transaction_depth, 0, "Correct transaction depth");
my $artist_rs = $schema->resultset('Artist');
+ my $fn = __FILE__;
throws_ok {
my $guard = $schema->txn_scope_guard;
});
$guard->commit;
- } qr/No such column made_up_column .*? at .*?81transactions.t line \d+/s, "Error propogated okay";
+ } qr/No such column made_up_column .*? at .*?$fn line \d+/s, "Error propogated okay";
ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");