1use strict; 2use warnings; 3 4use Test::More; 5use lib qw(t/lib); 6use DBICTest; 7use DBICTest::Stats; 8 9my ($create_sql, $dsn, $user, $pass); 10 11if ($ENV{DBICTEST_PG_DSN}) { 12 ($dsn, $user, $pass) = @ENV{map { "DBICTEST_PG_${_}" } qw/DSN USER PASS/}; 13 14 $create_sql = "CREATE TABLE artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10))"; 15} elsif ($ENV{DBICTEST_MYSQL_DSN}) { 16 ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MYSQL_${_}" } qw/DSN USER PASS/}; 17 18 $create_sql = "CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10)) ENGINE=InnoDB"; 19} else { 20 plan skip_all => 'Set DBICTEST_(PG|MYSQL)_DSN _USER and _PASS if you want to run savepoint tests'; 21} 22 23plan tests => 16; 24 25my $schema = DBICTest::Schema->connect ($dsn,$user,$pass,{ auto_savepoint => 1 }); 26 27my $stats = DBICTest::Stats->new; 28 29$schema->storage->debugobj($stats); 30 31$schema->storage->debug(1); 32 33{ 34 local $SIG{__WARN__} = sub {}; 35 $schema->storage->dbh->do ('DROP TABLE IF EXISTS artist'); 36 $schema->storage->dbh->do ($create_sql); 37} 38 39$schema->resultset('Artist')->create({ name => 'foo' }); 40 41$schema->txn_begin; 42 43my $arty = $schema->resultset('Artist')->find(1); 44 45my $name = $arty->name; 46 47# First off, test a generated savepoint name 48$schema->svp_begin; 49 50cmp_ok($stats->{'SVP_BEGIN'}, '==', 1, 'Statistics svp_begin tickled'); 51 52$arty->update({ name => 'Jheephizzy' }); 53 54$arty->discard_changes; 55 56cmp_ok($arty->name, 'eq', 'Jheephizzy', 'Name changed'); 57 58# Rollback the generated name 59# Active: 0 60$schema->svp_rollback; 61 62cmp_ok($stats->{'SVP_ROLLBACK'}, '==', 1, 'Statistics svp_rollback tickled'); 63 64$arty->discard_changes; 65 66cmp_ok($arty->name, 'eq', $name, 'Name rolled back'); 67 68$arty->update({ name => 'Jheephizzy'}); 69 70# Active: 0 1 71$schema->svp_begin('testing1'); 72 73$arty->update({ name => 'yourmom' }); 74 75# Active: 0 1 2 76$schema->svp_begin('testing2'); 77 78$arty->update({ name => 'gphat' }); 79$arty->discard_changes; 80cmp_ok($arty->name, 'eq', 'gphat', 'name changed'); 81# Active: 0 1 2 82# Rollback doesn't DESTROY the savepoint, it just rolls back to the value 83# at it's conception 84$schema->svp_rollback('testing2'); 85$arty->discard_changes; 86cmp_ok($arty->name, 'eq', 'yourmom', 'testing2 reverted'); 87 88# Active: 0 1 2 3 89$schema->svp_begin('testing3'); 90$arty->update({ name => 'coryg' }); 91# Active: 0 1 2 3 4 92$schema->svp_begin('testing4'); 93$arty->update({ name => 'watson' }); 94 95# Release 3, which implicitly releases 4 96# Active: 0 1 2 97$schema->svp_release('testing3'); 98$arty->discard_changes; 99cmp_ok($arty->name, 'eq', 'watson', 'release left data'); 100# This rolls back savepoint 2 101# Active: 0 1 2 102$schema->svp_rollback; 103$arty->discard_changes; 104cmp_ok($arty->name, 'eq', 'yourmom', 'rolled back to 2'); 105 106# Rollback the original savepoint, taking us back to the beginning, implicitly 107# rolling back savepoint 1 and 2 108$schema->svp_rollback('savepoint_0'); 109$arty->discard_changes; 110cmp_ok($arty->name, 'eq', 'foo', 'rolled back to start'); 111 112$schema->txn_commit; 113 114# And now to see if txn_do will behave correctly 115 116$schema->txn_do (sub { 117 $schema->txn_do (sub { 118 $arty->name ('Muff'); 119 120 $arty->update; 121 }); 122 123 eval { 124 $schema->txn_do (sub { 125 $arty->name ('Moff'); 126 127 $arty->update; 128 129 $arty->discard_changes; 130 131 is($arty->name,'Moff','Value updated in nested transaction'); 132 133 $schema->storage->dbh->do ("GUARANTEED TO PHAIL"); 134 }); 135 }; 136 137 ok ($@,'Nested transaction failed (good)'); 138 139 $arty->discard_changes; 140 141 is($arty->name,'Muff','auto_savepoint rollback worked'); 142 143 $arty->name ('Miff'); 144 145 $arty->update; 146 }); 147 148$arty->discard_changes; 149 150is($arty->name,'Miff','auto_savepoint worked'); 151 152cmp_ok($stats->{'SVP_BEGIN'},'==',7,'Correct number of savepoints created'); 153 154cmp_ok($stats->{'SVP_RELEASE'},'==',3,'Correct number of savepoints released'); 155 156cmp_ok($stats->{'SVP_ROLLBACK'},'==',5,'Correct number of savepoint rollbacks'); 157 158END { $schema->storage->dbh->do ("DROP TABLE artist") if defined $schema } 159 160