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