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