Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(802)

Side by Side Diff: third_party/sqlite/sqlite-src-3170000/ext/fts5/test/fts5corrupt3.test

Issue 2747283002: [sql] Import reference version of SQLite 3.17.. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # 2015 Apr 24
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 # This file tests that FTS5 handles corrupt databases (i.e. internal
13 # inconsistencies in the backing tables) correctly. In this case
14 # "correctly" means without crashing.
15 #
16
17 source [file join [file dirname [info script]] fts5_common.tcl]
18 set testprefix fts5corrupt3
19
20 # If SQLITE_ENABLE_FTS5 is defined, omit this file.
21 ifcapable !fts5 {
22 finish_test
23 return
24 }
25 sqlite3_fts5_may_be_corrupt 1
26
27 proc create_t1 {} {
28 expr srand(0)
29 db func rnddoc fts5_rnddoc
30 db eval {
31 CREATE VIRTUAL TABLE t1 USING fts5(x);
32 INSERT INTO t1(t1, rank) VALUES('pgsz', 64);
33 WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100)
34 INSERT INTO t1 SELECT rnddoc(10) FROM ii;
35 }
36 }
37
38 if 1 {
39
40 # Create a simple FTS5 table containing 100 documents. Each document
41 # contains 10 terms, each of which start with the character "x".
42 #
43 do_test 1.0 { create_t1 } {}
44
45 do_test 1.1 {
46 # Pick out the rowid of the right-most b-tree leaf in the new segment.
47 set rowid [db one {
48 SELECT max(rowid) FROM t1_data WHERE ((rowid>>31) & 0x0F)==1
49 }]
50 set L [db one {SELECT length(block) FROM t1_data WHERE rowid = $rowid}]
51 set {} {}
52 } {}
53
54 for {set i 0} {$i < $L} {incr i} {
55 do_test 1.2.$i {
56 catchsql {
57 BEGIN;
58 UPDATE t1_data SET block = substr(block, 1, $i) WHERE id = $rowid;
59 INSERT INTO t1(t1) VALUES('integrity-check');
60 }
61 } {1 {database disk image is malformed}}
62 catchsql ROLLBACK
63 }
64
65 #-------------------------------------------------------------------------
66 # Test that trailing bytes appended to the averages record are ignored.
67 #
68 do_execsql_test 2.1 {
69 CREATE VIRTUAL TABLE t2 USING fts5(x);
70 INSERT INTO t2 VALUES(rnddoc(10));
71 INSERT INTO t2 VALUES(rnddoc(10));
72 SELECT length(block) FROM t2_data WHERE id=1;
73 } {2}
74 do_execsql_test 2.2 {
75 UPDATE t2_data SET block = block || 'abcd' WHERE id=1;
76 SELECT length(block) FROM t2_data WHERE id=1;
77 } {6}
78 do_execsql_test 2.2 {
79 INSERT INTO t2 VALUES(rnddoc(10));
80 SELECT length(block) FROM t2_data WHERE id=1;
81 } {2}
82
83
84 #-------------------------------------------------------------------------
85 # Test that missing leaf pages are recognized as corruption.
86 #
87 reset_db
88 do_test 3.0 { create_t1 } {}
89
90 do_execsql_test 3.1 {
91 SELECT count(*) FROM t1_data;
92 } {105}
93
94 proc do_3_test {tn} {
95 set i 0
96 foreach ::rowid [db eval "SELECT rowid FROM t1_data WHERE rowid>100"] {
97 incr i
98 do_test $tn.$i {
99 db eval BEGIN
100 db eval {DELETE FROM t1_data WHERE rowid = $::rowid}
101 list [
102 catch { db eval {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'} } msg
103 ] $msg
104 } {1 {database disk image is malformed}}
105 catch { db eval ROLLBACK }
106 }
107 }
108
109 do_3_test 3.2
110
111 do_execsql_test 3.3 {
112 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
113 INSERT INTO t1 SELECT x FROM t1;
114 INSERT INTO t1(t1) VALUES('optimize');
115 } {}
116
117 do_3_test 3.4
118
119 do_test 3.5 {
120 execsql {
121 DELETE FROM t1;
122 INSERT INTO t1(t1, rank) VALUES('pgsz', 40);
123 }
124 for {set i 0} {$i < 1000} {incr i} {
125 set rnd [expr int(rand() * 1000)]
126 set doc [string repeat "x$rnd " [expr int(rand() * 3) + 1]]
127 execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) }
128 }
129 } {}
130
131 do_3_test 3.6
132
133 do_test 3.7 {
134 execsql {
135 INSERT INTO t1(t1, rank) VALUES('pgsz', 40);
136 INSERT INTO t1 SELECT x FROM t1;
137 INSERT INTO t1(t1) VALUES('optimize');
138 }
139 } {}
140
141 do_3_test 3.8
142
143 do_test 3.9 {
144 execsql {
145 DELETE FROM t1;
146 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
147 }
148 for {set i 0} {$i < 100} {incr i} {
149 set rnd [expr int(rand() * 100)]
150 set doc "x[string repeat $rnd 20]"
151 execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) }
152 }
153 } {}
154
155 do_3_test 3.10
156
157 #-------------------------------------------------------------------------
158 # Test that segments that end unexpectedly are identified as corruption.
159 #
160 reset_db
161 do_test 4.0 {
162 execsql {
163 CREATE VIRTUAL TABLE t1 USING fts5(x);
164 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
165 }
166 for {set i 0} {$i < 100} {incr i} {
167 set rnd [expr int(rand() * 100)]
168 set doc "x[string repeat $rnd 20]"
169 execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) }
170 }
171 execsql { INSERT INTO t1(t1) VALUES('optimize') }
172 } {}
173
174 set nErr 0
175 for {set i 1} {1} {incr i} {
176 set struct [db one {SELECT block FROM t1_data WHERE id=10}]
177 binary scan $struct c* var
178 set end [lindex $var end]
179 if {$end<=$i} break
180 lset var end [expr $end - $i]
181 set struct [binary format c* $var]
182
183 db close
184 sqlite3 db test.db
185
186 db eval {
187 BEGIN;
188 UPDATE t1_data SET block = $struct WHERE id=10;
189 }
190 do_test 4.1.$i {
191 incr nErr [catch { db eval { SELECT rowid FROM t1 WHERE t1 MATCH 'x*' } }]
192 set {} {}
193 } {}
194 catch { db eval ROLLBACK }
195 }
196 do_test 4.1.x { expr $nErr>45 } 1
197
198 #-------------------------------------------------------------------------
199 #
200
201 # The first argument passed to this command must be a binary blob
202 # containing an FTS5 leaf page. This command returns a copy of this
203 # blob, with the pgidx of the leaf page replaced by a single varint
204 # containing value $iVal.
205 #
206 proc rewrite_pgidx {blob iVal} {
207 binary scan $blob SS off1 szLeaf
208 if {$iVal<0 || $iVal>=128} {
209 error "$iVal out of range!"
210 } else {
211 set pgidx [binary format c $iVal]
212 }
213
214 binary format a${szLeaf}a* $blob $pgidx
215 }
216
217 reset_db
218 do_execsql_test 5.1 {
219 CREATE VIRTUAL TABLE x1 USING fts5(x);
220 INSERT INTO x1(x1, rank) VALUES('pgsz', 40);
221 BEGIN;
222 INSERT INTO x1 VALUES('xaaa xabb xccc xcdd xeee xeff xggg xghh xiii xijj');
223 INSERT INTO x1 SELECT x FROM x1;
224 INSERT INTO x1 SELECT x FROM x1;
225 INSERT INTO x1 SELECT x FROM x1;
226 INSERT INTO x1 SELECT x FROM x1;
227 INSERT INTO x1(x1) VALUES('optimize');
228 COMMIT;
229 }
230
231 #db eval { SELECT fts5_decode(id, block) b from x1_data } { puts $b }
232 #
233 db func rewrite_pgidx rewrite_pgidx
234 set i 0
235 foreach rowid [db eval {SELECT rowid FROM x1_data WHERE rowid>100}] {
236 foreach val {2 100} {
237 do_test 5.2.$val.[incr i] {
238 catchsql {
239 BEGIN;
240 UPDATE x1_data SET block=rewrite_pgidx(block, $val) WHERE id=$rowid;
241 SELECT rowid FROM x1 WHERE x1 MATCH 'xa*';
242 SELECT rowid FROM x1 WHERE x1 MATCH 'xb*';
243 SELECT rowid FROM x1 WHERE x1 MATCH 'xc*';
244 SELECT rowid FROM x1 WHERE x1 MATCH 'xd*';
245 SELECT rowid FROM x1 WHERE x1 MATCH 'xe*';
246 SELECT rowid FROM x1 WHERE x1 MATCH 'xf*';
247 SELECT rowid FROM x1 WHERE x1 MATCH 'xg*';
248 SELECT rowid FROM x1 WHERE x1 MATCH 'xh*';
249 SELECT rowid FROM x1 WHERE x1 MATCH 'xi*';
250 }
251 set {} {}
252 } {}
253 catch { db eval ROLLBACK }
254 }
255 }
256
257 #------------------------------------------------------------------------
258 #
259 reset_db
260 do_execsql_test 6.1.0 {
261 CREATE VIRTUAL TABLE t1 USING fts5(a);
262 INSERT INTO t1 VALUES('bbbbb ccccc');
263 SELECT quote(block) FROM t1_data WHERE rowid>100;
264 } {X'000000180630626262626201020201056363636363010203040A'}
265 do_execsql_test 6.1.1 {
266 UPDATE t1_data SET block =
267 X'000000180630626262626201020201056161616161010203040A'
268 WHERE rowid>100;
269 }
270 do_catchsql_test 6.1.2 {
271 INSERT INTO t1(t1) VALUES('integrity-check');
272 } {1 {database disk image is malformed}}
273
274 #-------
275 reset_db
276 do_execsql_test 6.2.0 {
277 CREATE VIRTUAL TABLE t1 USING fts5(a);
278 INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
279 INSERT INTO t1 VALUES('aa bb cc dd ee');
280 SELECT pgno, quote(term) FROM t1_idx;
281 } {2 X'' 4 X'3064'}
282 do_execsql_test 6.2.1 {
283 UPDATE t1_idx SET term = X'3065' WHERE pgno=4;
284 }
285 do_catchsql_test 6.2.2 {
286 INSERT INTO t1(t1) VALUES('integrity-check');
287 } {1 {database disk image is malformed}}
288
289 #-------
290 reset_db
291 do_execsql_test 6.3.0 {
292 CREATE VIRTUAL TABLE t1 USING fts5(a);
293 INSERT INTO t1 VALUES('abc abcdef abcdefghi');
294 SELECT quote(block) FROM t1_data WHERE id>100;
295 } {X'0000001C043061626301020204036465660102030703676869010204040808'}
296 do_execsql_test 6.3.1 {
297 BEGIN;
298 UPDATE t1_data SET block =
299 X'0000001C043061626301020204036465660102035003676869010204040808'
300 ------------------------------------------^^---------------------
301 WHERE id>100;
302 }
303 do_catchsql_test 6.3.2 {
304 INSERT INTO t1(t1) VALUES('integrity-check');
305 } {1 {database disk image is malformed}}
306 do_execsql_test 6.3.3 {
307 ROLLBACK;
308 BEGIN;
309 UPDATE t1_data SET block =
310 X'0000001C043061626301020204036465660102030750676869010204040808'
311 --------------------------------------------^^-------------------
312 WHERE id>100;
313 }
314 do_catchsql_test 6.3.3 {
315 INSERT INTO t1(t1) VALUES('integrity-check');
316 } {1 {database disk image is malformed}}
317 do_execsql_test 6.3.4 {
318 ROLLBACK;
319 BEGIN;
320 UPDATE t1_data SET block =
321 X'0000001C043061626301020204036465660102030707676869010204040850'
322 --------------------------------------------------------------^^-
323 WHERE id>100;
324 }
325 do_catchsql_test 6.3.5 {
326 INSERT INTO t1(t1) VALUES('integrity-check');
327 } {1 {database disk image is malformed}}
328 do_execsql_test 6.3.6 {
329 ROLLBACK;
330 BEGIN;
331 UPDATE t1_data SET block =
332 X'0000001C503061626301020204036465660102030707676869010204040808'
333 ----------^^-----------------------------------------------------
334 WHERE id>100;
335 }
336 do_catchsql_test 6.3.5 {
337 INSERT INTO t1(t1) VALUES('integrity-check');
338 } {1 {database disk image is malformed}}
339
340
341 #------------------------------------------------------------------------
342 #
343 reset_db
344 proc rnddoc {n} {
345 set map [list a b c d]
346 set doc [list]
347 for {set i 0} {$i < $n} {incr i} {
348 lappend doc "x[lindex $map [expr int(rand()*4)]]"
349 }
350 set doc
351 }
352
353 db func rnddoc rnddoc
354 do_test 7.0 {
355 execsql {
356 CREATE VIRTUAL TABLE t5 USING fts5(x);
357 INSERT INTO t5 VALUES( rnddoc(10000) );
358 INSERT INTO t5 VALUES( rnddoc(10000) );
359 INSERT INTO t5 VALUES( rnddoc(10000) );
360 INSERT INTO t5 VALUES( rnddoc(10000) );
361 INSERT INTO t5(t5) VALUES('optimize');
362 }
363 } {}
364
365 do_test 7.1 {
366 foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] {
367 db eval BEGIN
368 db eval {DELETE FROM t5_data WHERE rowid = $i}
369 set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ]
370 if {$r != "1 {database disk image is malformed}"} { error $r }
371 db eval ROLLBACK
372 }
373 } {}
374
375 }
376
377 #------------------------------------------------------------------------
378 # Corruption within the structure record.
379 #
380 reset_db
381 do_execsql_test 8.1 {
382 CREATE VIRTUAL TABLE t1 USING fts5(x, y);
383 INSERT INTO t1 VALUES('one', 'two');
384 }
385
386 do_test 9.1.1 {
387 set blob "12345678" ;# cookie
388 append blob "0105" ;# 1 level, total of 5 segments
389 append blob "06" ;# write counter
390 append blob "0002" ;# first level has 0 segments merging, 2 other.
391 append blob "450108" ;# first segment
392 execsql "REPLACE INTO t1_data VALUES(10, X'$blob')"
393 } {}
394 do_catchsql_test 9.1.2 {
395 SELECT * FROM t1('one AND two');
396 } {1 {database disk image is malformed}}
397
398 do_test 9.2.1 {
399 set blob "12345678" ;# cookie
400 append blob "0205" ;# 2 levels, total of 5 segments
401 append blob "06" ;# write counter
402 append blob "0001" ;# first level has 0 segments merging, 1 other.
403 append blob "450108" ;# first segment
404 execsql "REPLACE INTO t1_data VALUES(10, X'$blob')"
405 } {}
406 do_catchsql_test 9.2.2 {
407 SELECT * FROM t1('one AND two');
408 } {1 {database disk image is malformed}}
409
410 sqlite3_fts5_may_be_corrupt 0
411 finish_test
412
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698