1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
# 2016 June 1
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for the RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#
source [file join [file dirname [info script]] rbu_common.tcl]
if_no_rbu_support { finish_test ; return }
foreach {step} {0 1} {
foreach {ttt state} {
s state.db t test.db-vacuum n {}
} {
set ::testprefix rbuvacuum2-$step$ttt
#-------------------------------------------------------------------------
# Test that a database that contains fts3 tables can be vacuumed.
#
ifcapable fts3 {
reset_db
do_execsql_test 1.1 {
CREATE VIRTUAL TABLE t1 USING fts3(z, y);
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
do_rbu_vacuum_test 1.2 $step $state
do_execsql_test 1.3 {
SELECT * FROM t1;
} {{fix this issue} {at some point}}
do_execsql_test 1.4 {
SELECT rowid FROM t1 WHERE t1 MATCH 'fix';
} {1}
do_execsql_test 1.5 {
INSERT INTO t1 VALUES('a b c', 'd e f');
INSERT INTO t1 VALUES('l h i', 'd e f');
DELETE FROM t1 WHERE docid = 2;
INSERT INTO t1 VALUES('a b c', 'x y z');
}
do_rbu_vacuum_test 1.6 $step $state
do_execsql_test 1.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
} {
{fix this issue} {at some point}
{l h i} {d e f}
{a b c} {x y z}
}
}
#-------------------------------------------------------------------------
# Test that a database that contains fts5 tables can be vacuumed.
#
ifcapable fts5 {
reset_db
do_execsql_test 2.1 {
CREATE VIRTUAL TABLE t1 USING fts5(z, y);
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
do_rbu_vacuum_test 2.2 $step $state
do_execsql_test 2.3 {
SELECT * FROM t1;
} {{fix this issue} {at some point}}
do_execsql_test 2.4 {
SELECT rowid FROM t1 ('fix');
} {1}
do_execsql_test 2.5 {
INSERT INTO t1 VALUES('a b c', 'd e f');
INSERT INTO t1 VALUES('l h i', 'd e f');
DELETE FROM t1 WHERE rowid = 2;
INSERT INTO t1 VALUES('a b c', 'x y z');
}
do_rbu_vacuum_test 2.6 $step $state
do_execsql_test 2.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
} {
{fix this issue} {at some point}
{l h i} {d e f}
{a b c} {x y z}
}
}
#-------------------------------------------------------------------------
# Test that a database that contains an rtree table can be vacuumed.
#
ifcapable rtree {
reset_db
do_execsql_test 3.1 {
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
INSERT INTO rt VALUES(1, 45, 55);
INSERT INTO rt VALUES(2, 50, 60);
INSERT INTO rt VALUES(3, 55, 65);
}
do_rbu_vacuum_test 3.2 $step $state
do_execsql_test 3.3 {
SELECT * FROM rt;
} {1 45.0 55.0 2 50.0 60.0 3 55.0 65.0}
do_execsql_test 3.4.1 {
SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
} {1 2}
do_execsql_test 3.4.2 {
SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
} {2 3}
do_rbu_vacuum_test 3.5 $step $state
do_execsql_test 3.6.1 {
SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
} {1 2}
do_execsql_test 3.6.2 {
SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
} {2 3}
}
ifcapable trigger {
reset_db
do_execsql_test 4.1 {
CREATE TABLE t1(a, b, c);
INSERT INTO t1 VALUES(1, 2, 3);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END;
}
do_execsql_test 4.2 {
SELECT * FROM sqlite_master;
} {
table t1 t1 2 {CREATE TABLE t1(a, b, c)}
view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t1}
trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
}
do_rbu_vacuum_test 4.3 $step $state
do_execsql_test 4.4 {
SELECT * FROM sqlite_master;
} {
table t1 t1 2 {CREATE TABLE t1(a, b, c)}
view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t1}
trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
}
}
}
}
#-------------------------------------------------------------------------
# Test that passing a NULL value as the second argument to
# sqlite3rbu_vacuum() causes it to:
#
# * Use <database>-vacuum as the state db, and
# * Set the state db permissions to the same as those on the db file.
#
db close
if {$::tcl_platform(platform)=="unix"} {
forcedelete test.db
sqlite3 db test.db
do_execsql_test 5.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
INSERT INTO t1 VALUES(7, 8);
}
db close
foreach {tn perm} {
1 00755
2 00666
3 00644
4 00444
} {
forcedelete test.db-vacuum
do_test 5.$tn.1 {
file attributes test.db -permissions $perm
sqlite3rbu_vacuum rbu test.db
rbu step
} {SQLITE_OK}
do_test 5.$tn.2 { file exists test.db-vacuum } 1
# The result pattern might be 00xxx or 0oxxx depending on which
# version of TCL is being used. So make perm2 into a regexp that
# will match either
regsub {^00} $perm {0.} perm2
do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} /$perm2/
rbu close
}
}
#-------------------------------------------------------------------------
# Test the outcome of some other connection running a checkpoint while
# the incremental checkpoint is suspended.
#
reset_db
do_execsql_test 6.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1b ON t1(b);
CREATE INDEX i1c ON t1(c);
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
}
forcedelete test.db2
do_test 6.1 {
sqlite3rbu_vacuum rbu test.db test.db2
while {[rbu state]!="checkpoint"} { rbu step }
rbu close
} {SQLITE_OK}
do_test 6.2 {
execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
execsql { PRAGMA wal_checkpoint }
execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
} {1}
do_test 6.3 {
sqlite3rbu_vacuum rbu test.db test.db2
while {[rbu step]!="SQLITE_DONE"} { rbu step }
rbu close
execsql { PRAGMA integrity_check }
} {ok}
do_test 6.4 {
sqlite3rbu_vacuum rbu test.db test.db-vactmp
list [catch { rbu close } msg] $msg
} {1 SQLITE_MISUSE}
finish_test
|