Fixes default log output to console for macOS
[sqlcipher.git] / ext / rbu / rbuvacuum.test
blobad377a4bebf569c483289811bafff9f8037d11fd
1 # 2016 April 15
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
12 # This file contains tests for the RBU module. More specifically, it
13 # contains tests to ensure that the sqlite3rbu_vacuum() API works as
14 # expected.
17 source [file join [file dirname [info script]] rbu_common.tcl]
18 if_no_rbu_support { finish_test ; return }
19 set ::testprefix rbuvacuum
21 foreach step {0 1} {
23   set ::testprefix rbuvacuum-step=$step
24   reset_db
26   # Simplest possible vacuum.
27   do_execsql_test 1.0 {
28     PRAGMA page_size = 1024;
29     CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
30     INSERT INTO t1 VALUES(1, 2, 3);
31     INSERT INTO t1 VALUES(4, 5, 6);
32     INSERT INTO t1 VALUES(7, 8, 9);
33     PRAGMA integrity_check;
34   } {ok}
35   do_rbu_vacuum_test 1.1 $step
37   # A vacuum that actually reclaims space.
38   do_execsql_test 1.2.1 {
39     INSERT INTO t1 VALUES(8, randomblob(900), randomblob(900));
40     INSERT INTO t1 VALUES(9, randomblob(900), randomblob(900));
41     INSERT INTO t1 VALUES(10, randomblob(900), randomblob(900));
42     INSERT INTO t1 VALUES(11, randomblob(900), randomblob(900));
43     INSERT INTO t1 VALUES(12, randomblob(900), randomblob(900));
44     PRAGMA page_count;
45   } {12}
46   do_execsql_test 1.2.2 {
47     DELETE FROM t1 WHERE rowid BETWEEN 8 AND 11;
48     PRAGMA page_count;
49   } {12}
50   do_rbu_vacuum_test 1.2.3 $step
51   do_execsql_test 1.2.4 {
52     PRAGMA page_count;
53   } {3}
54   
55   # Add an index to the table.
56   do_execsql_test 1.3.1 {
57     CREATE INDEX t1b ON t1(b);
58     INSERT INTO t1 VALUES(13, randomblob(900), randomblob(900));
59     INSERT INTO t1 VALUES(14, randomblob(900), randomblob(900));
60     INSERT INTO t1 VALUES(15, randomblob(900), randomblob(900));
61     INSERT INTO t1 VALUES(16, randomblob(900), randomblob(900));
62     PRAGMA page_count;
63   } {18}
64   do_execsql_test 1.3.2 {
65     DELETE FROM t1 WHERE rowid BETWEEN 12 AND 15;
66     PRAGMA page_count;
67   } {18}
68   do_rbu_vacuum_test 1.3.3 $step
69   do_execsql_test 1.3.4 {
70     PRAGMA page_count;
71   } {5}
73   # WITHOUT ROWID table.
74   do_execsql_test 1.4.1 {
75     CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
77     INSERT INTO t2 VALUES(randomblob(900), 1, randomblob(900));
78     INSERT INTO t2 VALUES(randomblob(900), 2, randomblob(900));
79     INSERT INTO t2 VALUES(randomblob(900), 3, randomblob(900));
80     INSERT INTO t2 VALUES(randomblob(900), 4, randomblob(900));
81     INSERT INTO t2 VALUES(randomblob(900), 6, randomblob(900));
82     INSERT INTO t2 VALUES(randomblob(900), 7, randomblob(900));
83     INSERT INTO t2 VALUES(randomblob(900), 8, randomblob(900));
85     DELETE FROM t2 WHERE b BETWEEN 2 AND 7;
86     PRAGMA page_count;
87   } {20}
88   do_rbu_vacuum_test 1.4.2 $step
89   do_execsql_test 1.4.3 {
90     PRAGMA page_count;
91   } {10}
92   
93   # WITHOUT ROWID table with an index.
94   do_execsql_test 1.4.1 {
95     CREATE INDEX t2c ON t2(c);
97     INSERT INTO t2 VALUES(randomblob(900), 9, randomblob(900));
98     INSERT INTO t2 VALUES(randomblob(900), 10, randomblob(900));
99     INSERT INTO t2 VALUES(randomblob(900), 11, randomblob(900));
100     INSERT INTO t2 VALUES(randomblob(900), 12, randomblob(900));
101     INSERT INTO t2 VALUES(randomblob(900), 13, randomblob(900));
103     DELETE FROM t2 WHERE b BETWEEN 8 AND 12;
104     PRAGMA page_count;
105   } {35}
106   do_rbu_vacuum_test 1.4.2 $step
107   do_execsql_test 1.4.3 {
108     PRAGMA page_count;
109   } {15}
110   do_execsql_test 1.4.4 {
111     VACUUM;
112     PRAGMA page_count;
113   } {15}
115   do_execsql_test 1.5.1 {
116     CREATE TABLE t3(a, b, c);
117     INSERT INTO t3 VALUES('a', 'b', 'c');
118     INSERT INTO t3 VALUES('d', 'e', 'f');
119     INSERT INTO t3 VALUES('g', 'h', 'i');
120   }
121   do_rbu_vacuum_test 1.5.2 $step
122   do_execsql_test 1.5.3 {
123     SELECT * FROM t3
124   } {a b c d e f g h i}
125   do_execsql_test 1.5.4 {
126     CREATE INDEX t3a ON t3(a);
127     CREATE INDEX t3b ON t3(b);
128     CREATE INDEX t3c ON t3(c);
129     INSERT INTO t3 VALUES('j', 'k', 'l');
130     DELETE FROM t3 WHERE a = 'g';
131   }
132   do_rbu_vacuum_test 1.5.5 $step
133   do_execsql_test 1.5.6 {
134     SELECT rowid, * FROM t3 ORDER BY b
135   } {1 a b c 2 d e f 4 j k l}
137   do_execsql_test 1.6.1 {
138     CREATE TABLE t4(a PRIMARY KEY, b, c);
139     INSERT INTO t4 VALUES('a', 'b', 'c');
140     INSERT INTO t4 VALUES('d', 'e', 'f');
141     INSERT INTO t4 VALUES('g', 'h', 'i');
142   }
143   do_rbu_vacuum_test 1.6.2 $step
144   do_execsql_test 1.6.3 {
145     SELECT * FROM t4
146   } {a b c d e f g h i}
147   do_execsql_test 1.6.4 {
148     CREATE INDEX t4a ON t4(a);
149     CREATE INDEX t4b ON t4(b);
150     CREATE INDEX t4c ON t4(c);
151     
152     INSERT INTO t4 VALUES('j', 'k', 'l');
153     DELETE FROM t4 WHERE a='g';
154   }
155   do_rbu_vacuum_test 1.6.5 $step
156   do_execsql_test 1.6.6 {
157     SELECT * FROM t4 ORDER BY b
158   } {a b c d e f j k l}
160   reset_db
161   do_execsql_test 1.7.0 {
162     CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
163     INSERT INTO t1 VALUES(NULL, 'one');
164     INSERT INTO t1 VALUES(NULL, 'two');
165     DELETE FROM t1 WHERE a=2;
166     INSERT INTO t1 VALUES(NULL, 'three');
167     INSERT INTO t1 VALUES(NULL, 'four');
168     DELETE FROM t1 WHERE a=4;
169     INSERT INTO t1 VALUES(NULL, 'five');
170     INSERT INTO t1 VALUES(NULL, 'six');
171     DELETE FROM t1 WHERE a=6;
172     SELECT * FROM t1;
173   } {1 one 3 three 5 five}
174   do_rbu_vacuum_test 1.7.1 $step
175   do_execsql_test 1.7.2 {
176     INSERT INTO t1 VALUES(NULL, 'seven');
177     SELECT * FROM t1;
178   } {1 one 3 three 5 five 7 seven}
180   reset_db
181   do_execsql_test 1.8.0 {
182     CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
183     CREATE INDEX i1 ON t1(b);
184     INSERT INTO t1 VALUES(NULL, 'one');
185     INSERT INTO t1 VALUES(NULL, 'two');
186     INSERT INTO t1 VALUES(NULL, 'three');
187     INSERT INTO t1 VALUES(NULL, 'four');
188     INSERT INTO t1 VALUES(NULL, 'five');
189     INSERT INTO t1 VALUES(NULL, 'six');
190     ANALYZE;
191     SELECT * FROM sqlite_stat1;
192   } {t1 i1 {6 1}}
193   do_rbu_vacuum_test 1.8.1 $step
194   do_execsql_test 1.7.2 {
195     SELECT * FROM sqlite_stat1;
196   } {t1 i1 {6 1}}
198   reset_db
199   do_execsql_test 1.9.0 {
200     PRAGMA page_size = 8192;
201     PRAGMA auto_vacuum = 2;
202     PRAGMA user_version = 412;
203     PRAGMA application_id = 413;
205     CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
206     CREATE INDEX i1 ON t1(b);
207     INSERT INTO t1 VALUES(NULL, 'one');
208     INSERT INTO t1 VALUES(NULL, 'two');
209     INSERT INTO t1 VALUES(NULL, 'three');
210     INSERT INTO t1 VALUES(NULL, 'four');
211     INSERT INTO t1 VALUES(NULL, 'five');
212     INSERT INTO t1 VALUES(NULL, 'six');
214     PRAGMA main.page_size;
215     PRAGMA main.auto_vacuum;
216     PRAGMA main.user_version;
217     PRAGMA main.application_id;
218   } {8192 2 412 413}
220   do_rbu_vacuum_test 1.9.1 $step
221   do_execsql_test 1.9.2 {
222     PRAGMA main.page_size;
223     PRAGMA main.auto_vacuum;
224     PRAGMA main.user_version;
225     PRAGMA main.application_id;
226   } {8192 2 412 413}
228   # Vacuum a database with a large sqlite_master table.
229   #
230   reset_db
231   do_test 1.10.1 {
232     for {set i 1} {$i < 50} {incr i} {
233       execsql "PRAGMA page_size = 1024"
234       execsql "CREATE TABLE t$i (a, b, c, PRIMARY KEY(a, b));"
235       execsql "
236         INSERT INTO t$i VALUES(1, 2, 3);
237         INSERT INTO t$i VALUES(4, 5, 6);
238       "
239     }
240   } {}
241   do_rbu_vacuum_test 1.10.2 $step
243   # Database with empty tables.
244   #
245   reset_db
246   do_execsql_test 1.11.1 {
247     CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
248     CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
249     CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
250     CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
251     INSERT INTO t4 VALUES(1, 2);
252   }
253   do_rbu_vacuum_test 1.11.2 $step
254   do_execsql_test 1.11.3 {
255     SELECT * FROM t1;
256     SELECT * FROM t2;
257     SELECT * FROM t3;
258     SELECT * FROM t4;
259   } {1 2}
260   reset_db
261   do_execsql_test 1.12.1 {
262     CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
263     CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
264     CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
265     CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
266     INSERT INTO t1 VALUES(1, 2);
267   }
268   do_rbu_vacuum_test 1.12.2 $step
269   do_execsql_test 1.12.3 {
270     SELECT * FROM t1;
271     SELECT * FROM t2;
272     SELECT * FROM t3;
273     SELECT * FROM t4;
274   } {1 2}
276 set ::testprefix rbuvacuum
278 #-------------------------------------------------------------------------
279 # Test some error cases:
281 #   2.1.* the db being vacuumed being in wal mode already.
282 #   2.2.* database modified mid vacuum.
284 reset_db
285 do_execsql_test 2.1.0 {
286   CREATE TABLE t1(a, b);
287   INSERT INTO t1 VALUES(1, 2);
288   INSERT INTO t1 VALUES(3, 4);
289   INSERT INTO t1 VALUES(5, 6);
290   INSERT INTO t1 VALUES(7, 8);
291   PRAGMA journal_mode = wal;
292   INSERT INTO t1 VALUES(9, 10);
293 } wal
294 do_test 2.1.1 {
295   sqlite3rbu_vacuum rbu test.db state.db
296   rbu step
297 } {SQLITE_ERROR}
298 do_test 2.1.2 {
299   list [catch { rbu close } msg] $msg
300 } {1 {SQLITE_ERROR - cannot vacuum wal mode database}}
302 do_test 2.1.3 {
303   sqlite3rbu_vacuum rbu test.db state.db
304   rbu step
305 } {SQLITE_ERROR}
306 do_test 2.1.4 {
307   list [catch { rbu close_no_error } msg] $msg
308 } {1 SQLITE_ERROR}
310 reset_db
311 do_execsql_test 2.2.0 {
312   CREATE TABLE tx(a PRIMARY KEY, b BLOB);
313   INSERT INTO tx VALUES(1, randomblob(900));
314   INSERT INTO tx SELECT a+1, randomblob(900) FROM tx;
315   INSERT INTO tx SELECT a+2, randomblob(900) FROM tx;
316   INSERT INTO tx SELECT a+4, randomblob(900) FROM tx;
317   INSERT INTO tx SELECT a+8, randomblob(900) FROM tx;
319 db_save_and_close
320 for {set i 1} 1 {incr i} {
321   db_restore_and_reopen
323   sqlite3rbu_vacuum rbu test.db state.db
324   for {set step 0} {$step<$i} {incr step} { rbu step }
325   rbu close
326   if {[file exists test.db-wal]} break
328   execsql { INSERT INTO tx VALUES(20, 20) }
330   do_test 2.2.$i.1 {
331     sqlite3rbu_vacuum rbu test.db state.db 
332     rbu step
333   } {SQLITE_BUSY}
334   do_test 2.2.$i.2 {
335     list [catch { rbu close } msg] $msg
336   } {1 {SQLITE_BUSY - database modified during rbu vacuum}}
339 #-------------------------------------------------------------------------
340 # Test that a database that uses custom collation sequences can be RBU
341 # vacuumed.
343 reset_db
344 forcedelete state.db
345 proc noop {args} {}
346 proc length_cmp {x y} {
347   set n1 [string length $x]
348   set n2 [string length $y]
349   return [expr $n1 - $n2]
351 sqlite3_create_collation_v2 db length length_cmp noop
353 do_execsql_test 3.0 {
354   CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
355   INSERT INTO t1 VALUES(1, 'i');
356   INSERT INTO t1 VALUES(2, 'iiii');
357   INSERT INTO t1 VALUES(3, 'ii');
358   INSERT INTO t1 VALUES(4, 'iii');
359   SELECT a FROM t1 ORDER BY b COLLATE length;
360 } {1 3 4 2}
361 do_execsql_test 3.1 {
362   CREATE INDEX i1 ON t1(b COLLATE length);
365 do_test 3.2 {
366   sqlite3rbu_vacuum rbu test.db state.db
367   while {[rbu step]=="SQLITE_OK"} {}
368   list [catch { rbu close } msg] $msg
369 } {1 {SQLITE_ERROR - no such collation sequence: length}}
371 do_test 3.3 {
372   sqlite3rbu_vacuum rbu test.db state.db
373   set db1 [rbu db 0]
374   sqlite3_create_collation_v2 $db1 length length_cmp noop
375   while {[rbu step]=="SQLITE_OK"} {}
376   list [catch { rbu close } msg] $msg
377 } {1 {SQLITE_ERROR - no such collation sequence: length}}
379 do_test 3.4 {
380   sqlite3rbu_vacuum rbu test.db state.db
381   set db1 [rbu db 1]
382   sqlite3_create_collation_v2 $db1 length length_cmp noop
383   while {[rbu step]=="SQLITE_OK"} {}
384   list [catch { rbu close } msg] $msg
385 } {1 {SQLITE_ERROR - no such collation sequence: length}}
387 do_test 3.5 {
388   sqlite3rbu_vacuum rbu test.db state.db
389   set db1 [rbu db 0]
390   set db2 [rbu db 1]
392   sqlite3_create_collation_v2 $db1 length length_cmp noop
393   sqlite3_create_collation_v2 $db2 length length_cmp noop
395   while {[rbu step]=="SQLITE_OK"} {}
396   list [catch { rbu close } msg] $msg
397 } {0 SQLITE_DONE}
399 catch { db close }
400 finish_test