- All limit dialects (except for the older Top and FetchFirst) are
now using bind parameters for the limits/offsets, making DBI's
prepare_cached useful across paged resutsets
+ - Support for savepoints for SQLite
- Support for MS Access databases via DBD::ODBC and DBD::ADO (only
Win32 support currently tested)
- Support for the Firebird RDBMS over the new DBD::Firebird driver
return $backupfile;
}
+sub _exec_svp_begin {
+ my ($self, $name) = @_;
+
+ $self->_dbh->do("SAVEPOINT $name");
+}
+
+sub _exec_svp_release {
+ my ($self, $name) = @_;
+
+ $self->_dbh->do("RELEASE SAVEPOINT $name");
+}
+
+sub _exec_svp_rollback {
+ my ($self, $name) = @_;
+
+ # For some reason this statement changes the value of $dbh->{AutoCommit}, so
+ # we localize it here to preserve the original value.
+ local $self->_dbh->{AutoCommit} = $self->_dbh->{AutoCommit};
+
+ $self->_dbh->do("ROLLBACK TRANSACTION TO SAVEPOINT $name");
+}
+
sub deployment_statements {
my $self = shift;
my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_;
--- /dev/null
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use DBICTest;
+
+my $schema = DBICTest->init_schema(auto_savepoint => 1);
+
+my $ars = $schema->resultset('Artist');
+
+# test two-phase commit and inner transaction rollback from nested transactions
+$schema->txn_do(sub {
+ $ars->create({ name => 'in_outer_transaction' });
+ $schema->txn_do(sub {
+ $ars->create({ name => 'in_inner_transaction' });
+ });
+ ok($ars->search({ name => 'in_inner_transaction' })->first,
+ 'commit from inner transaction visible in outer transaction');
+ throws_ok {
+ $schema->txn_do(sub {
+ $ars->create({ name => 'in_inner_transaction_rolling_back' });
+ die 'rolling back inner transaction';
+ });
+ } qr/rolling back inner transaction/, 'inner transaction rollback executed';
+ $ars->create({ name => 'in_outer_transaction2' });
+});
+ok($ars->search({ name => 'in_outer_transaction' })->first,
+ 'commit from outer transaction');
+ok($ars->search({ name => 'in_outer_transaction2' })->first,
+ 'second commit from outer transaction');
+ok($ars->search({ name => 'in_inner_transaction' })->first,
+ 'commit from inner transaction');
+is $ars->search({ name => 'in_inner_transaction_rolling_back' })->first,
+ undef,
+ 'rollback from inner transaction';
+
+done_testing;
+
+# vim:sts=2 sw=2: