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