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