SQLite

Check-in [4dfe2e5871]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improve test coverage of fts5_storage.c.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | fts5
Files: files | file ages | folders
SHA1: 4dfe2e5871704125338620705e6638f36baaacd7
User & Date: dan 2015-05-18 20:34:59.915
Context
2015-05-19
11:32
Fix a memory leak that could follow an OOM condition in fts5. (check-in: de9f8ef6eb user: dan tags: fts5)
2015-05-18
20:34
Improve test coverage of fts5_storage.c. (check-in: 4dfe2e5871 user: dan tags: fts5)
18:24
Fix a bug in test script fts5fault4.test. (check-in: a508059305 user: dan tags: fts5)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/fts5/fts5_storage.c.
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
        *piRowid = sqlite3_value_int64(apVal[1]);
      }else{
        rc = fts5StorageNewRowid(p, piRowid);
      }
    }else{
      if( eConflict==SQLITE_REPLACE ){
        eStmt = FTS5_STMT_REPLACE_CONTENT;
        if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
          rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
        }
      }else{
        eStmt = FTS5_STMT_INSERT_CONTENT;
      }
      if( rc==SQLITE_OK ){
        rc = fts5StorageGetStmt(p, eStmt, &pInsert, 0);
      }
      for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){







<
|
<







659
660
661
662
663
664
665

666

667
668
669
670
671
672
673
        *piRowid = sqlite3_value_int64(apVal[1]);
      }else{
        rc = fts5StorageNewRowid(p, piRowid);
      }
    }else{
      if( eConflict==SQLITE_REPLACE ){
        eStmt = FTS5_STMT_REPLACE_CONTENT;

        rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));

      }else{
        eStmt = FTS5_STMT_INSERT_CONTENT;
      }
      if( rc==SQLITE_OK ){
        rc = fts5StorageGetStmt(p, eStmt, &pInsert, 0);
      }
      for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
Changes to ext/fts5/test/fts5aa.test.
138
139
140
141
142
143
144








145
146
147
148
149
150
151
  INSERT  INTO t1(rowid, x, y) VALUES(22, 'a b c', 'c b a');
  REPLACE INTO t1(rowid, x, y) VALUES(22, 'd e f', 'f e d');
}

do_execsql_test 6.2 {
  INSERT INTO t1(t1) VALUES('integrity-check') 
}









#-------------------------------------------------------------------------
#
reset_db
expr srand(0)
do_execsql_test 7.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x,y,z);







>
>
>
>
>
>
>
>







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  INSERT  INTO t1(rowid, x, y) VALUES(22, 'a b c', 'c b a');
  REPLACE INTO t1(rowid, x, y) VALUES(22, 'd e f', 'f e d');
}

do_execsql_test 6.2 {
  INSERT INTO t1(t1) VALUES('integrity-check') 
}

do_execsql_test 6.3 {
  REPLACE INTO t1(rowid, x, y) VALUES('22', 'l l l', 'l l l');
}

do_execsql_test 6.4 {
  INSERT INTO t1(t1) VALUES('integrity-check') 
}

#-------------------------------------------------------------------------
#
reset_db
expr srand(0)
do_execsql_test 7.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x,y,z);
395
396
397
398
399
400
401



















402
403
404
405
  db eval { UPDATE n1_config SET v=50 WHERE k='version' }
}
db func funk funk

do_catchsql_test 16.2 {
  SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
} {1 {SQL logic error or missing database}}




















finish_test









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  db eval { UPDATE n1_config SET v=50 WHERE k='version' }
}
db func funk funk

do_catchsql_test 16.2 {
  SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
} {1 {SQL logic error or missing database}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 17.1 {
  CREATE VIRTUAL TABLE b2 USING fts5(x);
  INSERT INTO b2 VALUES('a');
  INSERT INTO b2 VALUES('b');
  INSERT INTO b2 VALUES('c');
}

do_test 17.2 {
  set res [list]
  db eval { SELECT * FROM b2 ORDER BY rowid ASC } {
    lappend res [execsql { SELECT * FROM b2 ORDER BY rowid ASC }]
  }
  set res
} {{a b c} {a b c} {a b c}}


finish_test


Changes to ext/fts5/test/fts5aux.test.
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
sqlite3_fts5_create_function db inst inst

proc colsize {cmd i} { 
  $cmd xColumnSize $i
}
sqlite3_fts5_create_function db colsize colsize






do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE f1 USING fts5(a, b);
  INSERT INTO f1 VALUES('one two', 'two one zero');

}

do_catchsql_test 1.1 {
  SELECT inst(f1, -1) FROM f1 WHERE f1 MATCH 'two';
} {1 SQLITE_RANGE}
do_catchsql_test 1.2 {
  SELECT inst(f1, 0) FROM f1 WHERE f1 MATCH 'two';
} {0 {{0 0 1}}}
do_catchsql_test 1.3 {
  SELECT inst(f1, 1) FROM f1 WHERE f1 MATCH 'two';
} {0 {{0 1 0}}}
do_catchsql_test 1.4 {
  SELECT inst(f1, 2) FROM f1 WHERE f1 MATCH 'two';
} {1 SQLITE_RANGE}

do_catchsql_test 2.1 {
  SELECT colsize(f1, 2) FROM f1 WHERE f1 MATCH 'two';
} {1 SQLITE_RANGE}

do_execsql_test 2.2 {
  SELECT colsize(f1, 0), colsize(f1, 1) FROM f1 WHERE f1 MATCH 'zero';
} {2 3}

















#-------------------------------------------------------------------------
# Test the xSet and xGetAuxdata APIs with a NULL destructor.
#
proc prevrowid {add cmd} {
  set res [$cmd xGetAuxdataInt 0]
  set r [$cmd xRowid]







>
>
>
>
>



>


















<



>
>
>

>
>
>
>
>
>
>
>
>
>
>
>







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
sqlite3_fts5_create_function db inst inst

proc colsize {cmd i} { 
  $cmd xColumnSize $i
}
sqlite3_fts5_create_function db colsize colsize

proc totalsize {cmd i} { 
  $cmd xColumnTotalSize $i
}
sqlite3_fts5_create_function db totalsize totalsize

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE f1 USING fts5(a, b);
  INSERT INTO f1 VALUES('one two', 'two one zero');
  INSERT INTO f1 VALUES('one one', 'one one one');
}

do_catchsql_test 1.1 {
  SELECT inst(f1, -1) FROM f1 WHERE f1 MATCH 'two';
} {1 SQLITE_RANGE}
do_catchsql_test 1.2 {
  SELECT inst(f1, 0) FROM f1 WHERE f1 MATCH 'two';
} {0 {{0 0 1}}}
do_catchsql_test 1.3 {
  SELECT inst(f1, 1) FROM f1 WHERE f1 MATCH 'two';
} {0 {{0 1 0}}}
do_catchsql_test 1.4 {
  SELECT inst(f1, 2) FROM f1 WHERE f1 MATCH 'two';
} {1 SQLITE_RANGE}

do_catchsql_test 2.1 {
  SELECT colsize(f1, 2) FROM f1 WHERE f1 MATCH 'two';
} {1 SQLITE_RANGE}

do_execsql_test 2.2 {
  SELECT colsize(f1, 0), colsize(f1, 1) FROM f1 WHERE f1 MATCH 'zero';
} {2 3}
do_execsql_test 2.3 {
  SELECT colsize(f1, -1) FROM f1 WHERE f1 MATCH 'zero';
} {5}

do_execsql_test 2.4.1 {
  SELECT totalsize(f1, -1) FROM f1 WHERE f1 MATCH 'zero';
} {10}
do_execsql_test 2.4.2 {
  SELECT totalsize(f1, 0) FROM f1 WHERE f1 MATCH 'zero';
} {4}
do_execsql_test 2.4.3 {
  SELECT totalsize(f1, 1) FROM f1 WHERE f1 MATCH 'zero';
} {6}
do_catchsql_test 2.4.4 {
  SELECT totalsize(f1, 2) FROM f1 WHERE f1 MATCH 'zero';
} {1 SQLITE_RANGE}

#-------------------------------------------------------------------------
# Test the xSet and xGetAuxdata APIs with a NULL destructor.
#
proc prevrowid {add cmd} {
  set res [$cmd xGetAuxdataInt 0]
  set r [$cmd xRowid]
Changes to ext/fts5/test/fts5content.test.
230
231
232
233
234
235
236












237
238

239

do_execsql_test 5.1 {
  INSERT INTO t5(t5, rowid, a, b) VALUES('delete', NULL, 'three', 'four');
  SELECT md5sum(id, block) FROM t5_data;
} $::checksum














finish_test










>
>
>
>
>
>
>
>
>
>
>
>
|

>

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252

do_execsql_test 5.1 {
  INSERT INTO t5(t5, rowid, a, b) VALUES('delete', NULL, 'three', 'four');
  SELECT md5sum(id, block) FROM t5_data;
} $::checksum


#-------------------------------------------------------------------------
# Check that a contentless table can be dropped.
#
reset_db
do_execsql_test 6.1 {
  CREATE VIRTUAL TABLE xx USING fts5(x, y, content="");
  SELECT name FROM sqlite_master;
} {xx xx_data xx_docsize xx_config}
do_execsql_test 6.2 {
  DROP TABLE xx;
  SELECT name FROM sqlite_master;
} {}


finish_test

Changes to ext/fts5/test/fts5corrupt2.test.
235
236
237
238
239
240
241




















242
243
244
245
246
      catchsql { INSERT INTO x5(x5) VALUES('integrity-check') }
      set {} {}
    } {}

    execsql ROLLBACK
  }
}






















sqlite3_fts5_may_be_corrupt 0
finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
      catchsql { INSERT INTO x5(x5) VALUES('integrity-check') }
      set {} {}
    } {}

    execsql ROLLBACK
  }
}

#--------------------------------------------------------------------
reset_db
do_execsql_test 5.1 {
  CREATE VIRTUAL TABLE x5 USING fts5(tt);
  INSERT INTO x5 VALUES('a');
  INSERT INTO x5 VALUES('a a');
  INSERT INTO x5 VALUES('a a a');
  INSERT INTO x5 VALUES('a a a a');

  UPDATE x5_docsize SET sz = X'' WHERE id=3;
}
proc colsize {cmd i} { 
  $cmd xColumnSize $i
}
sqlite3_fts5_create_function db colsize colsize

do_catchsql_test 5.2 {
  SELECT colsize(x5, 0) FROM x5 WHERE x5 MATCH 'a'
} {1 SQLITE_CORRUPT_VTAB}


sqlite3_fts5_may_be_corrupt 0
finish_test

Changes to ext/fts5/test/fts5corrupt3.test.
47
48
49
50
51
52
53

















54
55
56
57
      UPDATE t1_data SET block = substr(block, 1, $i) WHERE id = $rowid;
      INSERT INTO t1(t1) VALUES('integrity-check');
    }
  } {1 {database disk image is malformed}}
  catchsql ROLLBACK
}
 


















sqlite3_fts5_may_be_corrupt 0
finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




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
      UPDATE t1_data SET block = substr(block, 1, $i) WHERE id = $rowid;
      INSERT INTO t1(t1) VALUES('integrity-check');
    }
  } {1 {database disk image is malformed}}
  catchsql ROLLBACK
}
 
#-------------------------------------------------------------------------
# Test that trailing bytes appended to the averages record are ignored.
#
do_execsql_test 2.1 {
  CREATE VIRTUAL TABLE t2 USING fts5(x);
  INSERT INTO t2 VALUES(rnddoc(10));
  INSERT INTO t2 VALUES(rnddoc(10));
  SELECT length(block) FROM t2_data WHERE id=1;
} {2}
do_execsql_test 2.2 {
  UPDATE t2_data SET block = block || 'abcd' WHERE id=1;
  SELECT length(block) FROM t2_data WHERE id=1;
} {6}
do_execsql_test 2.2 {
  INSERT INTO t2 VALUES(rnddoc(10));
  SELECT length(block) FROM t2_data WHERE id=1;
} {2}

sqlite3_fts5_may_be_corrupt 0
finish_test

Added ext/fts5/test/fts5fault6.test.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# 2014 June 17
#
# 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 is focused on OOM errors.
#

source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5fault6

# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
  finish_test
  return
}

#-------------------------------------------------------------------------
# OOM while rebuilding an FTS5 table.
#
do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE tt USING fts5(a, b);
  INSERT INTO tt VALUES('c d c g g f', 'a a a d g a');
  INSERT INTO tt VALUES('c d g b f d', 'b g e c g c');
  INSERT INTO tt VALUES('c c f d e d', 'c e g d b c');
  INSERT INTO tt VALUES('e a f c e f', 'g b a c d g');
  INSERT INTO tt VALUES('c g f b b d', 'g c d c f g');
  INSERT INTO tt VALUES('d a g a b b', 'g c g g c e');
  INSERT INTO tt VALUES('e f a b c e', 'f d c d c c');
  INSERT INTO tt VALUES('e c a g c d', 'b b g f f b');
  INSERT INTO tt VALUES('g b d d e b', 'f f b d a c');
  INSERT INTO tt VALUES('e a d a e d', 'c e a e f g');
}
faultsim_save_and_close

do_faultsim_test 1.1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { INSERT INTO tt(tt) VALUES('rebuild') }
} -test {
  faultsim_test_result {0 {}}
}

do_faultsim_test 1.2 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { REPLACE INTO tt(rowid, a, b) VALUES(6, 'x y z', 'l l l'); }
} -test {
  faultsim_test_result {0 {}}
}


#-------------------------------------------------------------------------
# OOM within a special delete.
#
reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE tt USING fts5(a, content="");
  INSERT INTO tt VALUES('c d c g g f');
  INSERT INTO tt VALUES('c d g b f d');
  INSERT INTO tt VALUES('c c f d e d');
  INSERT INTO tt VALUES('e a f c e f');
  INSERT INTO tt VALUES('c g f b b d');
  INSERT INTO tt VALUES('d a g a b b');
  INSERT INTO tt VALUES('e f a b c e');
  INSERT INTO tt VALUES('e c a g c d');
  INSERT INTO tt VALUES('g b d d e b');
  INSERT INTO tt VALUES('e a d a e d');
}
faultsim_save_and_close

do_faultsim_test 2.1 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { INSERT INTO tt(tt, rowid, a) VALUES('delete', 3, 'c d g b f d'); }
} -test {
  faultsim_test_result {0 {}}
}

do_faultsim_test 2.2 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { INSERT INTO tt(tt) VALUES('delete-all') }
} -test {
  faultsim_test_result {0 {}}
}

do_faultsim_test 2.3 -faults oom-t* -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { INSERT INTO tt VALUES('x y z') }
} -test {
  faultsim_test_result {0 {}}
}

finish_test

Changes to ext/fts5/test/fts5integrity.test.
44
45
46
47
48
49
50












































51
52
53
54
55
56
57
  INSERT INTO zz SELECT z FROM zz;
  INSERT INTO zz SELECT z FROM zz;
  INSERT INTO zz(zz) VALUES('optimize');
}

do_execsql_test 3.1 { INSERT INTO zz(zz) VALUES('integrity-check'); }














































#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM zz_data} {puts $r}
#exit


finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  INSERT INTO zz SELECT z FROM zz;
  INSERT INTO zz SELECT z FROM zz;
  INSERT INTO zz(zz) VALUES('optimize');
}

do_execsql_test 3.1 { INSERT INTO zz(zz) VALUES('integrity-check'); }

#--------------------------------------------------------------------
# Mess around with a docsize record. And the averages record. Then
# check that integrity-check picks it up.
#
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE aa USING fts5(zz);
  INSERT INTO aa(zz) VALUES('a b c d e');
  INSERT INTO aa(zz) VALUES('a b c d');
  INSERT INTO aa(zz) VALUES('a b c');
  INSERT INTO aa(zz) VALUES('a b');
  INSERT INTO aa(zz) VALUES('a');
  SELECT length(sz) FROM aa_docsize;
} {1 1 1 1 1}
do_execsql_test 4.1 { 
  INSERT INTO aa(aa) VALUES('integrity-check'); 
}

do_catchsql_test 4.2 { 
  BEGIN;
    UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3;
    INSERT INTO aa(aa) VALUES('integrity-check'); 
} {1 {database disk image is malformed}}

do_catchsql_test 4.3 { 
  ROLLBACK;
  BEGIN;
    UPDATE aa_data SET block = X'44' WHERE rowid = 1;
    INSERT INTO aa(aa) VALUES('integrity-check'); 
} {1 {database disk image is malformed}}

do_catchsql_test 4.4 { 
  ROLLBACK;
  BEGIN;
    INSERT INTO aa_docsize VALUES(23, X'04');
    INSERT INTO aa(aa) VALUES('integrity-check'); 
} {1 {database disk image is malformed}}

do_catchsql_test 4.5 { 
  ROLLBACK;
  BEGIN;
    INSERT INTO aa_docsize VALUES(23, X'00');
    INSERT INTO aa_content VALUES(23, '');
    INSERT INTO aa(aa) VALUES('integrity-check'); 
} {1 {database disk image is malformed}}

#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM zz_data} {puts $r}
#exit


finish_test