Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add test cases. And some fixes. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | fts5 |
Files: | files | file ages | folders |
SHA1: |
adee788586197445672013d434e7ba47 |
User & Date: | dan 2015-05-15 12:18:39.221 |
Context
2015-05-15
| ||
18:13 | Improve test coverage of fts5_index.c. (check-in: 7aea8c6d99 user: dan tags: fts5) | |
12:18 | Add test cases. And some fixes. (check-in: adee788586 user: dan tags: fts5) | |
2015-05-13
| ||
18:12 | Merge latest trunk changes with this branch. (check-in: b5f0e8c5b4 user: dan tags: fts5) | |
Changes
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
2067 2068 2069 2070 2071 2072 2073 | */ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ Fts5DlidxIter *pDlidx = pIter->pDlidx; Fts5Data *pLast = 0; int pgnoLast = 0; if( pDlidx ){ | < < < | | | < < < | 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 | */ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ Fts5DlidxIter *pDlidx = pIter->pDlidx; Fts5Data *pLast = 0; int pgnoLast = 0; if( pDlidx ){ int iSegid = pIter->pSeg->iSegid; pgnoLast = fts5DlidxIterPgno(pDlidx); pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, 0, pgnoLast)); }else{ int iOff; /* Byte offset within pLeaf */ Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */ /* Currently, Fts5SegIter.iLeafOffset (and iOff) points to the first ** byte of position-list content for the current rowid. Back it up ** so that it points to the start of the position-list size field. */ |
︙ | ︙ | |||
3426 3427 3428 3429 3430 3431 3432 | Fts5SegWriter *pWriter, int iSegid ){ memset(pWriter, 0, sizeof(Fts5SegWriter)); pWriter->iSegid = iSegid; pWriter->aWriter = (Fts5PageWriter*)fts5IdxMalloc(p, sizeof(Fts5PageWriter)); | < | | 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 | Fts5SegWriter *pWriter, int iSegid ){ memset(pWriter, 0, sizeof(Fts5SegWriter)); pWriter->iSegid = iSegid; pWriter->aWriter = (Fts5PageWriter*)fts5IdxMalloc(p, sizeof(Fts5PageWriter)); if( fts5WriteDlidxGrow(p, pWriter, 1) ) return; pWriter->nWriter = 1; pWriter->nDlidx = 1; pWriter->aWriter[0].pgno = 1; pWriter->bFirstTermInPage = 1; } static void fts5WriteInitForAppend( |
︙ | ︙ | |||
3898 3899 3900 3901 3902 3903 3904 | int iOff = 0; writer.bFirstRowidInPage = 0; /* The entire doclist will not fit on this leaf. The following ** loop iterates through the poslists that make up the current ** doclist. */ | | | 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 | int iOff = 0; writer.bFirstRowidInPage = 0; /* The entire doclist will not fit on this leaf. The following ** loop iterates through the poslists that make up the current ** doclist. */ while( p->rc==SQLITE_OK && iOff<nDoclist ){ int nPos; int nCopy; int bDummy; iOff += getVarint(&pDoclist[iOff], (u64*)&iDelta); nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy); nCopy += nPos; iRowid += iDelta; |
︙ | ︙ | |||
3927 3928 3929 3930 3931 3932 3933 | fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); }else{ /* The entire poslist will not fit on this leaf. So it needs ** to be broken into sections. The only qualification being ** that each varint must be stored contiguously. */ const u8 *pPoslist = &pDoclist[iOff]; int iPos = 0; | | | 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 | fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); }else{ /* The entire poslist will not fit on this leaf. So it needs ** to be broken into sections. The only qualification being ** that each varint must be stored contiguously. */ const u8 *pPoslist = &pDoclist[iOff]; int iPos = 0; while( p->rc==SQLITE_OK ){ int nSpace = pgsz - pBuf->n; int n = 0; if( (nCopy - iPos)<=nSpace ){ n = nCopy - iPos; }else{ n = fts5PoslistPrefix(&pPoslist[iPos], nSpace); } |
︙ | ︙ | |||
3986 3987 3988 3989 3990 3991 3992 | } /* ** Flush any data stored in the in-memory hash tables to the database. */ static void fts5IndexFlush(Fts5Index *p){ /* Unless it is empty, flush the hash table to disk */ | | | 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 | } /* ** Flush any data stored in the in-memory hash tables to the database. */ static void fts5IndexFlush(Fts5Index *p){ /* Unless it is empty, flush the hash table to disk */ if( p->nPendingData ){ assert( p->pHash ); p->nPendingData = 0; fts5FlushOneHash(p); } } |
︙ | ︙ | |||
4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 | assert( p->rc==SQLITE_OK ); /* Allocate the hash table if it has not already been allocated */ if( p->pHash==0 ){ p->rc = sqlite3Fts5HashNew(&p->pHash, &p->nPendingData); } if( iRowid<=p->iWriteRowid || (p->nPendingData > p->nMaxPendingData) ){ fts5IndexFlush(p); } p->iWriteRowid = iRowid; return fts5IndexReturn(p); } | > | 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 | assert( p->rc==SQLITE_OK ); /* Allocate the hash table if it has not already been allocated */ if( p->pHash==0 ){ p->rc = sqlite3Fts5HashNew(&p->pHash, &p->nPendingData); } /* Flush the hash table to disk if required */ if( iRowid<=p->iWriteRowid || (p->nPendingData > p->nMaxPendingData) ){ fts5IndexFlush(p); } p->iWriteRowid = iRowid; return fts5IndexReturn(p); } |
︙ | ︙ | |||
4928 4929 4930 4931 4932 4933 4934 | for(pDlidx=fts5DlidxIterInit(p, 1, iSegid, iLeaf); fts5DlidxIterEof(p, pDlidx)==0; fts5DlidxIterPrev(p, pDlidx) ){ i64 iRowid = fts5DlidxIterRowid(pDlidx); int pgno = fts5DlidxIterPgno(pDlidx); | < | 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 | for(pDlidx=fts5DlidxIterInit(p, 1, iSegid, iLeaf); fts5DlidxIterEof(p, pDlidx)==0; fts5DlidxIterPrev(p, pDlidx) ){ i64 iRowid = fts5DlidxIterRowid(pDlidx); int pgno = fts5DlidxIterPgno(pDlidx); assert( fts5DlidxIterPgno(pDlidx)>iLeaf ); cksum2 += iRowid + ((i64)pgno<<32); } fts5DlidxIterFree(pDlidx); pDlidx = 0; if( p->rc==SQLITE_OK && cksum1!=cksum2 ) p->rc = FTS5_CORRUPT; |
︙ | ︙ | |||
4967 4968 4969 4970 4971 4972 4973 | ** ignore this b-tree entry. Otherwise, load it into memory. */ if( iter.iLeaf<pSeg->pgnoFirst ) continue; iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, 0, iter.iLeaf); pLeaf = fts5DataRead(p, iRow); if( pLeaf==0 ) break; /* Check that the leaf contains at least one term, and that it is equal | | > > > > > > > > | | | < | > | 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 | ** ignore this b-tree entry. Otherwise, load it into memory. */ if( iter.iLeaf<pSeg->pgnoFirst ) continue; iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, 0, iter.iLeaf); pLeaf = fts5DataRead(p, iRow); if( pLeaf==0 ) break; /* Check that the leaf contains at least one term, and that it is equal ** to or larger than the split-key in iter.term. Also check that if there ** is also a rowid pointer within the leaf page header, it points to a ** location before the term. */ iOff = fts5GetU16(&pLeaf->p[2]); if( iOff==0 ){ p->rc = FTS5_CORRUPT; }else{ int iRowidOff; int nTerm; /* Size of term on leaf in bytes */ int res; /* Comparison of term and split-key */ iRowidOff = fts5GetU16(&pLeaf->p[0]); if( iRowidOff>=iOff ){ p->rc = FTS5_CORRUPT; }else{ iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm); res = memcmp(&pLeaf->p[iOff], iter.term.p, MIN(nTerm, iter.term.n)); if( res==0 ) res = nTerm - iter.term.n; if( res<0 ) p->rc = FTS5_CORRUPT; } } fts5DataRelease(pLeaf); if( p->rc ) break; /* Now check that the iter.nEmpty leaves following the current leaf ** (a) exist and (b) contain no terms. */ for(i=1; p->rc==SQLITE_OK && i<=iter.nEmpty; i++){ pLeaf = fts5DataRead(p, iRow+i); if( pLeaf && 0!=fts5GetU16(&pLeaf->p[2]) ){ p->rc = FTS5_CORRUPT; |
︙ | ︙ |
Changes to ext/fts5/fts5_vocab.c.
︙ | ︙ | |||
340 341 342 343 344 345 346 | sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); memset(pCsr->aVal, 0, sizeof(pCsr->aVal)); memset(pCsr->aCnt, 0, pCsr->nCol * sizeof(i64)); memset(pCsr->aDoc, 0, pCsr->nCol * sizeof(i64)); pCsr->iCol = 0; assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); | | | < | | | | | | | | | | | | | | | | < | > | | | | > | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); memset(pCsr->aVal, 0, sizeof(pCsr->aVal)); memset(pCsr->aCnt, 0, pCsr->nCol * sizeof(i64)); memset(pCsr->aDoc, 0, pCsr->nCol * sizeof(i64)); pCsr->iCol = 0; assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); while( rc==SQLITE_OK ){ const u8 *pPos; int nPos; /* Position list */ i64 iPos = 0; /* 64-bit position read from poslist */ int iOff = 0; /* Current offset within position list */ rc = sqlite3Fts5IterPoslist(pCsr->pIter, &pPos, &nPos); if( rc==SQLITE_OK ){ if( pTab->eType==FTS5_VOCAB_ROW ){ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ pCsr->aVal[1]++; } pCsr->aVal[0]++; }else{ int iCol = -1; while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ int ii = FTS5_POS2COLUMN(iPos); pCsr->aCnt[ii]++; if( iCol!=ii ){ pCsr->aDoc[ii]++; iCol = ii; } } } rc = sqlite3Fts5IterNextScan(pCsr->pIter); } if( rc==SQLITE_OK ){ zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ) break; if( sqlite3Fts5IterEof(pCsr->pIter) ) break; } } } } if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++; pCsr->aVal[0] = pCsr->iCol; |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt2.test.
︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100) INSERT INTO t1 SELECT rnddoc(10) FROM ii; } set mask [expr 31 << 31] # Test 1: # # For each page in the t1_data table, open a transaction and DELETE # the t1_data entry. Then run: # # * an integrity-check, and | > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100) INSERT INTO t1 SELECT rnddoc(10) FROM ii; } set mask [expr 31 << 31] if 1 { # Test 1: # # For each page in the t1_data table, open a transaction and DELETE # the t1_data entry. Then run: # # * an integrity-check, and |
︙ | ︙ | |||
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 | } 1 do_execsql_test 2.$i.4 { ROLLBACK; INSERT INTO t1(t1) VALUES('integrity-check'); } {} } #------------------------------------------------------------------------- # Test that corruption in leaf page headers is detected by queries that use # doclist-indexes. # set doc "A B C D E F G H I J " do_execsql_test 3.0 { CREATE VIRTUAL TABLE x3 USING fts5(tt); INSERT INTO x3(x3, rank) VALUES('pgsz', 32); WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<1000) INSERT INTO x3 SELECT ($doc || CASE WHEN (i%50)==0 THEN 'X' ELSE 'Y' END) FROM ii; } foreach {tn hdr} { 1 "\x00\x00\x00\x00" 2 "\xFF\xFF\xFF\xFF" } { set tn2 0 set nCorrupt 0 foreach rowid [db eval {SELECT rowid FROM x3_data WHERE rowid>10}] { if {$rowid & $mask} continue incr tn2 | > > > > | > > > > > > > > | 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 | } 1 do_execsql_test 2.$i.4 { ROLLBACK; INSERT INTO t1(t1) VALUES('integrity-check'); } {} } } #------------------------------------------------------------------------- # Test that corruption in leaf page headers is detected by queries that use # doclist-indexes. # set doc "A B C D E F G H I J " do_execsql_test 3.0 { CREATE VIRTUAL TABLE x3 USING fts5(tt); INSERT INTO x3(x3, rank) VALUES('pgsz', 32); WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<1000) INSERT INTO x3 SELECT ($doc || CASE WHEN (i%50)==0 THEN 'X' ELSE 'Y' END) FROM ii; } foreach {tn hdr} { 1 "\x00\x00\x00\x00" 2 "\xFF\xFF\xFF\xFF" 3 "\x44\x45" } { set tn2 0 set nCorrupt 0 set nCorrupt2 0 foreach rowid [db eval {SELECT rowid FROM x3_data WHERE rowid>10}] { if {$rowid & $mask} continue incr tn2 do_test 3.$tn.$tn2.1 { execsql BEGIN set fd [db incrblob main x3_data block $rowid] fconfigure $fd -encoding binary -translation binary set existing [read $fd [string length $hdr]] seek $fd 0 puts -nonewline $fd $hdr close $fd set res [catchsql {SELECT rowid FROM x3 WHERE x3 MATCH 'x AND a'}] if {$res == "1 {database disk image is malformed}"} {incr nCorrupt} set {} 1 } {1} if {($tn2 % 10)==0 && $existing != $hdr} { do_test 3.$tn.$tn2.2 { catchsql { INSERT INTO x3(x3) VALUES('integrity-check') } } {1 {database disk image is malformed}} } execsql ROLLBACK } do_test 3.$tn.x { expr $nCorrupt>0 } 1 } |
︙ | ︙ |
Changes to ext/fts5/test/fts5dlidx.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 | proc do_fb_test {tn sql res} { set res2 [lsort -integer -decr $res] uplevel [list do_execsql_test $tn.1 $sql $res] uplevel [list do_execsql_test $tn.2 "$sql ORDER BY rowid DESC" $res2] } | < < < < < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | proc do_fb_test {tn sql res} { set res2 [lsort -integer -decr $res] uplevel [list do_execsql_test $tn.1 $sql $res] uplevel [list do_execsql_test $tn.2 "$sql ORDER BY rowid DESC" $res2] } # This test populates the FTS5 table containing $nEntry entries. Rows are # numbered from 0 to ($nEntry-1). The rowid for row $i is: # # ($iFirst + $i*$nStep) # # Each document is of the form "a b c a b c a b c...". If the row number ($i) # is an integer multiple of $spc1, then an "x" token is appended to the |
︙ | ︙ | |||
57 58 59 60 61 62 63 | if {($i % $spc2)==0} { lappend ydoc $rowid append doc " y" } } execsql { INSERT INTO t1(rowid, x) VALUES($rowid, $doc) } } | < > > > > > > > > > > > | | | | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | if {($i % $spc2)==0} { lappend ydoc $rowid append doc " y" } } execsql { INSERT INTO t1(rowid, x) VALUES($rowid, $doc) } } execsql COMMIT breakpoint do_test $tn.1 { execsql { INSERT INTO t1(t1) VALUES('integrity-check') } } {} do_fb_test $tn.3.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'a AND x' } $xdoc do_fb_test $tn.3.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'x AND a' } $xdoc do_fb_test $tn.4.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'a AND y' } $ydoc do_fb_test $tn.4.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'y AND a' } $ydoc do_fb_test $tn.5.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'a + b + c + x' } $xdoc do_fb_test $tn.5.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'b + c + x + y' } $ydoc } foreach {tn pgsz} { 1 32 2 200 } { do_execsql_test $tn.0 { DROP TABLE IF EXISTS t1; CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz); } do_dlidx_test1 1.$tn.1 10 100 10000 0 1000 do_dlidx_test1 1.$tn.2 10 10 10000 0 128 do_dlidx_test1 1.$tn.3 10 10 66 0 36028797018963970 do_dlidx_test1 1.$tn.4 10 10 50 0 150000000000000000 do_dlidx_test1 1.$tn.5 10 10 200 0 [expr 1<<55] do_dlidx_test1 1.$tn.6 10 10 30 0 [expr 1<<58] } proc do_dlidx_test2 {tn nEntry iFirst nStep} { set str [string repeat "a " 500] execsql { BEGIN; DROP TABLE IF EXISTS t1; CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', 64); INSERT INTO t1 VALUES('b a'); WITH iii(ii, i) AS ( SELECT 1, $iFirst UNION ALL SELECT ii+1, i+$nStep FROM iii WHERE ii<$nEntry ) INSERT INTO t1(rowid,x) SELECT i, $str FROM iii; COMMIT; } do_execsql_test $tn.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' } {1} breakpoint do_execsql_test $tn.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC } {1} } do_dlidx_test2 2.1 [expr 20] [expr 1<<57] [expr (1<<57) + 128] finish_test |
Changes to ext/fts5/test/fts5fault4.test.
︙ | ︙ | |||
313 314 315 316 317 318 319 | WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<200) INSERT INTO tt(rowid, x) SELECT i, CASE WHEN (i%50)==0 THEN 'a a a a a a' ELSE 'a x a x a x' END FROM ii; COMMIT; } | < < > > > < | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<200) INSERT INTO tt(rowid, x) SELECT i, CASE WHEN (i%50)==0 THEN 'a a a a a a' ELSE 'a x a x a x' END FROM ii; COMMIT; } do_faultsim_test 10.1 -faults oom-t* -body { db one { SELECT fts5_expr('a AND b NEAR(a b)') } } -test { faultsim_test_result {0 {"a" AND ("b" AND NEAR("a" "b", 10))}} } } #do_faultsim_test 10.2 -faults oom-t* -body { # db one { SELECT fts5_expr_tcl('x:"a b c" AND b NEAR(a b)', 'ns', 'x') } #} -test { # set res {[ns -col 0 -- {a b c}] && ([ns -- {b}] && [ns -near 10 -- {a} {b}]} # faultsim_test_result [list 0 $res] #} finish_test |
Added ext/fts5/test/fts5fault5.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 | # 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 fts5fault5 # If SQLITE_ENABLE_FTS3 is defined, omit this file. ifcapable !fts5 { finish_test return } #------------------------------------------------------------------------- # OOM while creating an FTS5 table. # do_faultsim_test 1.1 -faults oom-t* -prep { db eval { DROP TABLE IF EXISTS abc } } -body { db eval { CREATE VIRTUAL TABLE abc USING fts5(x,y) } } -test { faultsim_test_result {0 {}} } #------------------------------------------------------------------------- # OOM while writing a multi-tier doclist-index. And while running # integrity-check on the same. # reset_db do_execsql_test 2.0 { CREATE VIRTUAL TABLE tt USING fts5(x); INSERT INTO tt(tt, rank) VALUES('pgsz', 32); } faultsim_save_and_close do_faultsim_test 2.1 -faults oom-t* -prep { faultsim_restore_and_reopen db eval { SELECT * FROM tt } } -body { set str [string repeat "abc " 50] db eval { WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) INSERT INTO tt(rowid, x) SELECT i, $str FROM ii; } } -test { faultsim_test_result {0 {}} } do_faultsim_test 2.2 -faults oom-t* -body { db eval { INSERT INTO tt(tt) VALUES('integrity-check') } } -test { faultsim_test_result {0 {}} } #------------------------------------------------------------------------- # OOM while scanning an fts5vocab table. # reset_db do_test 3.0 { execsql { CREATE VIRTUAL TABLE tt USING fts5(x); CREATE VIRTUAL TABLE tv USING fts5vocab(tt, 'row'); INSERT INTO tt(tt, rank) VALUES('pgsz', 32); BEGIN; } for {set i 0} {$i < 20} {incr i} { set str [string repeat "$i " 20] execsql { INSERT INTO tt VALUES($str) } } execsql COMMIT } {} do_faultsim_test 2.1 -faults oom-t* -body { db eval { SELECT term FROM tv; } } -test { faultsim_test_result {0 {0 1 10 11 12 13 14 15 16 17 18 19 2 3 4 5 6 7 8 9}} } finish_test |