OLD | NEW |
| (Empty) |
1 # 2015 February 16 | |
2 # | |
3 # The author disclaims copyright to this source code. In place of | |
4 # a legal notice, here is a blessing: | |
5 # | |
6 # May you do good and not evil. | |
7 # May you find forgiveness for yourself and forgive others. | |
8 # May you share freely, never taking more than you give. | |
9 # | |
10 #*********************************************************************** | |
11 # | |
12 | |
13 if {![info exists testdir]} { | |
14 set testdir [file join [file dirname [info script]] .. .. test] | |
15 } | |
16 source $testdir/tester.tcl | |
17 source $testdir/lock_common.tcl | |
18 set ::testprefix rbu12 | |
19 | |
20 set setup_sql { | |
21 DROP TABLE IF EXISTS xx; | |
22 DROP TABLE IF EXISTS xy; | |
23 CREATE TABLE xx(a, b, c PRIMARY KEY); | |
24 INSERT INTO xx VALUES(1, 2, 3); | |
25 CREATE TABLE xy(a, b, c PRIMARY KEY); | |
26 | |
27 ATTACH 'rbu.db' AS rbu; | |
28 DROP TABLE IF EXISTS data_xx; | |
29 CREATE TABLE rbu.data_xx(a, b, c, rbu_control); | |
30 INSERT INTO data_xx VALUES(4, 5, 6, 0); | |
31 INSERT INTO data_xx VALUES(7, 8, 9, 0); | |
32 CREATE TABLE rbu.data_xy(a, b, c, rbu_control); | |
33 INSERT INTO data_xy VALUES(10, 11, 12, 0); | |
34 DETACH rbu; | |
35 } | |
36 | |
37 do_multiclient_test tn { | |
38 | |
39 # Initialize a target (test.db) and rbu (rbu.db) database. | |
40 # | |
41 forcedelete rbu.db | |
42 sql1 $setup_sql | |
43 | |
44 # Using connection 2, open a read transaction on the target database. | |
45 # RBU will still be able to generate "test.db-oal", but it will not be | |
46 # able to rename it to "test.db-wal". | |
47 # | |
48 do_test 1.$tn.1 { | |
49 sql2 { BEGIN; SELECT * FROM xx; } | |
50 } {1 2 3} | |
51 do_test 1.$tn.2 { | |
52 sqlite3rbu rbu test.db rbu.db | |
53 while 1 { | |
54 set res [rbu step] | |
55 if {$res!="SQLITE_OK"} break | |
56 } | |
57 set res | |
58 } {SQLITE_BUSY} | |
59 | |
60 do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3} | |
61 do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {} | |
62 do_test 1.$tn.5 { | |
63 list [file exists test.db-wal] [file exists test.db-oal] | |
64 } {0 1} | |
65 do_test 1.$tn.6 { sql2 COMMIT } {} | |
66 | |
67 # The rbu object that hit the SQLITE_BUSY error above cannot be reused. | |
68 # It is stuck in a permanent SQLITE_BUSY state at this point. | |
69 # | |
70 do_test 1.$tn.7 { rbu step } {SQLITE_BUSY} | |
71 do_test 1.$tn.8 { | |
72 list [catch { rbu close } msg] $msg | |
73 } {1 SQLITE_BUSY} | |
74 | |
75 do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {} | |
76 do_test 1.$tn.9.2 { | |
77 sqlite3rbu rbu test.db rbu.db | |
78 rbu step | |
79 } {SQLITE_BUSY} | |
80 do_test 1.$tn.9.3 { | |
81 list [catch { rbu close } msg] $msg | |
82 } {1 {SQLITE_BUSY - database is locked}} | |
83 do_test 1.$tn.9.4 { sql2 COMMIT } {} | |
84 | |
85 sqlite3rbu rbu test.db rbu.db | |
86 do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {} | |
87 do_test 1.$tn.10.2 { | |
88 rbu step | |
89 } {SQLITE_BUSY} | |
90 do_test 1.$tn.10.3 { | |
91 list [catch { rbu close } msg] $msg | |
92 } {1 SQLITE_BUSY} | |
93 do_test 1.$tn.10.4 { sql2 COMMIT } {} | |
94 | |
95 # A new rbu object can finish the work though. | |
96 # | |
97 do_test 1.$tn.11 { | |
98 sqlite3rbu rbu test.db rbu.db | |
99 rbu step | |
100 } {SQLITE_OK} | |
101 do_test 1.$tn.12 { | |
102 list [file exists test.db-wal] [file exists test.db-oal] | |
103 } {1 0} | |
104 do_test 1.$tn.13 { | |
105 while 1 { | |
106 set res [rbu step] | |
107 if {$res!="SQLITE_OK"} break | |
108 } | |
109 set res | |
110 } {SQLITE_DONE} | |
111 | |
112 do_test 1.$tn.14 { | |
113 rbu close | |
114 } {SQLITE_DONE} | |
115 } | |
116 | |
117 do_multiclient_test tn { | |
118 | |
119 # Initialize a target (test.db) and rbu (rbu.db) database. | |
120 # | |
121 forcedelete rbu.db | |
122 sql1 $setup_sql | |
123 | |
124 do_test 2.$tn.1 { | |
125 sqlite3rbu rbu test.db rbu.db | |
126 while {[file exists test.db-wal]==0} { | |
127 if {[rbu step]!="SQLITE_OK"} {error "problem here...."} | |
128 } | |
129 rbu close | |
130 } {SQLITE_OK} | |
131 | |
132 | |
133 do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {} | |
134 | |
135 do_test 2.$tn.3 { | |
136 sqlite3rbu rbu test.db rbu.db | |
137 rbu step | |
138 } {SQLITE_BUSY} | |
139 | |
140 do_test 2.$tn.4 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY} | |
141 | |
142 do_test 2.$tn.5 { | |
143 sql2 { SELECT * FROM xx ; COMMIT } | |
144 } {1 2 3 4 5 6 7 8 9} | |
145 | |
146 do_test 2.$tn.6 { | |
147 sqlite3rbu rbu test.db rbu.db | |
148 rbu step | |
149 rbu close | |
150 } {SQLITE_OK} | |
151 | |
152 do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {} | |
153 | |
154 do_test 2.$tn.8 { | |
155 sqlite3rbu rbu test.db rbu.db | |
156 rbu step | |
157 } {SQLITE_BUSY} | |
158 do_test 2.$tn.9 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY} | |
159 do_test 2.$tn.10 { | |
160 sql2 { SELECT * FROM xx ; COMMIT } | |
161 } {1 2 3 4 5 6 7 8 9} | |
162 | |
163 do_test 2.$tn.11 { | |
164 sqlite3rbu rbu test.db rbu.db | |
165 while {[rbu step]=="SQLITE_OK"} {} | |
166 rbu close | |
167 } {SQLITE_DONE} | |
168 | |
169 } | |
170 | |
171 #------------------------------------------------------------------------- | |
172 # Test that "PRAGMA data_version" works when an RBU client writes the | |
173 # database. | |
174 # | |
175 do_multiclient_test tn { | |
176 | |
177 # Initialize a target (test.db) and rbu (rbu.db) database. | |
178 # | |
179 forcedelete rbu.db | |
180 sql1 $setup_sql | |
181 | |
182 # Check the initial database contains table "xx" with a single row. | |
183 # Also save the current values of "PRAGMA data-version" for [db1] | |
184 # and [db2]. | |
185 # | |
186 do_test 2.$tn.1 { | |
187 list [sql1 { SELECT count(*) FROM xx }] [sql2 { SELECT count(*) FROM xx }] | |
188 } {1 1} | |
189 set V1 [sql1 {PRAGMA data_version}] | |
190 set V2 [sql2 {PRAGMA data_version}] | |
191 | |
192 # Check the values of data-version have not magically changed. | |
193 # | |
194 do_test 2.$tn.2 { | |
195 list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] | |
196 } [list $V1 $V2] | |
197 | |
198 # Start stepping the RBU. From the point of view of [db1] and [db2], the | |
199 # data-version values remain unchanged until the database contents are | |
200 # modified. At which point the values are incremented. | |
201 # | |
202 sqlite3rbu rbu test.db rbu.db | |
203 set x 0 | |
204 while {[db one {SELECT count(*) FROM xx}]==1} { | |
205 do_test 2.$tn.3.[incr x] { | |
206 list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] | |
207 } [list $V1 $V2] | |
208 rbu step | |
209 } | |
210 do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1 | |
211 do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1 | |
212 | |
213 # Check the db contents is as expected. | |
214 # | |
215 do_test 2.$tn.4 { | |
216 list [sql1 {SELECT count(*) FROM xx}] [sql2 {SELECT count(*) FROM xx}] | |
217 } {3 3} | |
218 | |
219 set V1 [sql1 {PRAGMA data_version}] | |
220 set V2 [sql2 {PRAGMA data_version}] | |
221 | |
222 # Finish applying the RBU (i.e. do the incremental checkpoint). Check that | |
223 # this does not cause the data-version values to change. | |
224 # | |
225 while {[rbu step]=="SQLITE_OK"} { } | |
226 rbu close | |
227 | |
228 do_test 2.$tn.6 { | |
229 list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] | |
230 } [list $V1 $V2] | |
231 | |
232 } | |
233 | |
234 finish_test | |
235 | |
OLD | NEW |