Further tests for fts5.

FossilOrigin-Name: ffeb3ef3cfec3681b72bb28cfa612aa15e07887d
This commit is contained in:
dan 2015-04-27 11:31:56 +00:00
parent 26c84373c4
commit c1cea8f731
9 changed files with 337 additions and 76 deletions

View File

@ -1055,7 +1055,7 @@ static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
static int fts5SpecialInsert(
Fts5Table *pTab, /* Fts5 table object */
sqlite3_value *pCmd, /* Value inserted into special column */
sqlite3_value *pVal /* Value inserted into rowid column */
sqlite3_value *pVal /* Value inserted into rank column */
){
Fts5Config *pConfig = pTab->pConfig;
const char *z = (const char*)sqlite3_value_text(pCmd);
@ -1083,6 +1083,9 @@ static int fts5SpecialInsert(
}
}else if( 0==sqlite3_stricmp("optimize", z) ){
rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
}else if( 0==sqlite3_stricmp("merge", z) ){
int nMerge = sqlite3_value_int(pVal);
rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
}else if( 0==sqlite3_stricmp("integrity-check", z) ){
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
}else{

View File

@ -360,6 +360,7 @@ int sqlite3Fts5IndexReads(Fts5Index *p);
int sqlite3Fts5IndexReinit(Fts5Index *p);
int sqlite3Fts5IndexOptimize(Fts5Index *p);
int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge);
int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
@ -459,6 +460,7 @@ int sqlite3Fts5StorageSpecialDelete(Fts5Storage *p, i64 iDel, sqlite3_value**);
int sqlite3Fts5StorageDeleteAll(Fts5Storage *p);
int sqlite3Fts5StorageRebuild(Fts5Storage *p);
int sqlite3Fts5StorageOptimize(Fts5Storage *p);
int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge);
/*
** End of interface to code in fts5_storage.c.

View File

@ -823,16 +823,20 @@ static Fts5Data *fts5DataReadOrBuffer(
/* This call may return SQLITE_ABORT if there has been a savepoint
** rollback since it was last used. In this case a new blob handle
** is required. */
rc = sqlite3_blob_reopen(p->pReader, iRowid);
if( rc==SQLITE_ABORT ){
sqlite3_blob *pBlob = p->pReader;
p->pReader = 0;
rc = sqlite3_blob_reopen(pBlob, iRowid);
assert( p->pReader==0 );
p->pReader = pBlob;
if( rc!=SQLITE_OK ){
fts5CloseReader(p);
rc = SQLITE_OK;
}
if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
}
/* If the blob handle is not yet open, open and seek it. Otherwise, use
** the blob_reopen() API to reseek the existing blob handle. */
if( p->pReader==0 ){
if( p->pReader==0 && rc==SQLITE_OK ){
Fts5Config *pConfig = p->pConfig;
rc = sqlite3_blob_open(pConfig->db,
pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader
@ -2770,7 +2774,6 @@ static void fts5ChunkIterRelease(Fts5ChunkIter *pIter){
** returned in this case.
*/
static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
int i;
u32 iSegid = 0;
if( p->rc==SQLITE_OK ){
@ -3227,11 +3230,11 @@ static void fts5WriteInitForAppend(
pWriter->iIdx = iIdx;
pWriter->iSegid = pSeg->iSegid;
pWriter->aWriter = (Fts5PageWriter*)fts5IdxMalloc(p, nByte);
pWriter->nWriter = pSeg->nHeight;
if( p->rc==SQLITE_OK ){
int pgno = 1;
int i;
pWriter->nWriter = pSeg->nHeight;
pWriter->aWriter[0].pgno = pSeg->pgnoLast+1;
for(i=pSeg->nHeight-1; i>0; i--){
i64 iRowid = FTS5_SEGMENT_ROWID(pWriter->iIdx, pWriter->iSegid, i, pgno);
@ -3250,7 +3253,7 @@ static void fts5WriteInitForAppend(
if( pSeg->nHeight==1 ){
pWriter->nEmpty = pSeg->pgnoLast-1;
}
assert( (pgno+pWriter->nEmpty)==pSeg->pgnoLast );
assert( p->rc!=SQLITE_OK || (pgno+pWriter->nEmpty)==pSeg->pgnoLast );
pWriter->bFirstTermInPage = 1;
assert( pWriter->aWriter[0].term.n==0 );
}
@ -3351,7 +3354,6 @@ static void fts5IndexMergeLevel(
fts5WriteInit(p, &writer, iIdx, iSegid);
/* Add the new segment to the output level */
if( iLvl+1==pStruct->nLevel ) pStruct->nLevel++;
pSeg = &pLvlOut->aSeg[pLvlOut->nSeg];
pLvlOut->nSeg++;
pSeg->pgnoFirst = 1;
@ -3447,6 +3449,59 @@ fflush(stdout);
if( pnRem ) *pnRem -= writer.nLeafWritten;
}
/*
** Do up to nPg pages of automerge work on index iIdx.
*/
static void fts5IndexMerge(
Fts5Index *p, /* FTS5 backend object */
int iIdx, /* Index to work on */
Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
int nPg /* Pages of work to do */
){
int nRem = nPg;
Fts5Structure *pStruct = *ppStruct;
while( nRem>0 && p->rc==SQLITE_OK ){
int iLvl; /* To iterate through levels */
int iBestLvl = 0; /* Level offering the most input segments */
int nBest = 0; /* Number of input segments on best level */
/* Set iBestLvl to the level to read input segments from. */
assert( pStruct->nLevel>0 );
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
if( pLvl->nMerge ){
if( pLvl->nMerge>nBest ){
iBestLvl = iLvl;
nBest = pLvl->nMerge;
}
break;
}
if( pLvl->nSeg>nBest ){
nBest = pLvl->nSeg;
iBestLvl = iLvl;
}
}
/* If nBest is still 0, then the index must be empty. */
#ifdef SQLITE_DEBUG
for(iLvl=0; nBest==0 && iLvl<pStruct->nLevel; iLvl++){
assert( pStruct->aLevel[iLvl].nSeg==0 );
}
#endif
if( nBest<p->pConfig->nAutomerge
&& pStruct->aLevel[iBestLvl].nMerge==0
){
break;
}
fts5IndexMergeLevel(p, iIdx, &pStruct, iBestLvl, &nRem);
if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
fts5StructurePromote(p, iBestLvl+1, pStruct);
}
}
*ppStruct = pStruct;
}
/*
** A total of nLeaf leaf pages of data has just been flushed to a level-0
** segments in index iIdx with structure pStruct. This function updates the
@ -3456,13 +3511,13 @@ fflush(stdout);
** If an error occurs, set the Fts5Index.rc error code. If an error has
** already occurred, this function is a no-op.
*/
static void fts5IndexWork(
static void fts5IndexAutomerge(
Fts5Index *p, /* FTS5 backend object */
int iIdx, /* Index to work on */
Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
int nLeaf /* Number of output leaves just written */
){
if( p->rc==SQLITE_OK ){
if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 ){
Fts5Structure *pStruct = *ppStruct;
i64 nWrite; /* Initial value of write-counter */
int nWork; /* Number of work-quanta to perform */
@ -3474,62 +3529,21 @@ static void fts5IndexWork(
pStruct->nWriteCounter += nLeaf;
nRem = p->nWorkUnit * nWork * pStruct->nLevel;
while( nRem>0 ){
int iLvl; /* To iterate through levels */
int iBestLvl = 0; /* Level offering the most input segments */
int nBest = 0; /* Number of input segments on best level */
/* Set iBestLvl to the level to read input segments from. */
assert( pStruct->nLevel>0 );
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
if( pLvl->nMerge ){
if( pLvl->nMerge>nBest ){
iBestLvl = iLvl;
nBest = pLvl->nMerge;
}
break;
}
if( pLvl->nSeg>nBest ){
nBest = pLvl->nSeg;
iBestLvl = iLvl;
}
}
/* If nBest is still 0, then the index must be empty. */
#ifdef SQLITE_DEBUG
for(iLvl=0; nBest==0 && iLvl<pStruct->nLevel; iLvl++){
assert( pStruct->aLevel[iLvl].nSeg==0 );
}
#endif
if( nBest<p->pConfig->nAutomerge
&& pStruct->aLevel[iBestLvl].nMerge==0
){
break;
}
fts5IndexMergeLevel(p, iIdx, &pStruct, iBestLvl, &nRem);
assert( nRem==0 || p->rc==SQLITE_OK );
if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
fts5StructurePromote(p, iBestLvl+1, pStruct);
}
*ppStruct = pStruct;
}
fts5IndexMerge(p, iIdx, ppStruct, nRem);
}
}
static void fts5IndexCrisisMerge(
static void fts5IndexCrisismerge(
Fts5Index *p, /* FTS5 backend object */
int iIdx, /* Index to work on */
Fts5Structure **ppStruct /* IN/OUT: Current structure of index */
){
const int nCrisis = p->pConfig->nCrisisMerge;
Fts5Structure *pStruct = *ppStruct;
int iLvl = 0;
while( p->rc==SQLITE_OK
&& iLvl<pStruct->nLevel
&& pStruct->aLevel[iLvl].nSeg>=p->pConfig->nCrisisMerge
){
assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 );
while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){
fts5IndexMergeLevel(p, iIdx, &pStruct, iLvl, 0);
fts5StructurePromote(p, iLvl+1, pStruct);
iLvl++;
@ -3744,8 +3758,8 @@ static void fts5FlushOneHash(Fts5Index *p, int iHash, int *pnLeaf){
}
if( p->pConfig->nAutomerge>0 ) fts5IndexWork(p, iHash, &pStruct, pgnoLast);
fts5IndexCrisisMerge(p, iHash, &pStruct);
fts5IndexAutomerge(p, iHash, &pStruct, pgnoLast);
fts5IndexCrisismerge(p, iHash, &pStruct);
fts5StructureWrite(p, iHash, pStruct);
fts5StructureRelease(pStruct);
}
@ -3759,7 +3773,7 @@ static void fts5IndexFlush(Fts5Index *p){
int nLeaf = 0; /* Number of leaves written */
/* If an error has already occured this call is a no-op. */
if( p->rc!=SQLITE_OK || p->nPendingData==0 ) return;
if( p->nPendingData==0 ) return;
assert( p->apHash );
/* Flush the terms and each prefix index to disk */
@ -3774,6 +3788,7 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){
Fts5Config *pConfig = p->pConfig;
int i;
assert( p->rc==SQLITE_OK );
fts5IndexFlush(p);
for(i=0; i<=pConfig->nPrefix; i++){
Fts5Structure *pStruct = fts5StructureRead(p, i);
@ -3828,6 +3843,16 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){
return fts5IndexReturn(p);
}
int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
Fts5Structure *pStruct;
pStruct = fts5StructureRead(p, 0);
fts5IndexMerge(p, 0, &pStruct, nMerge);
fts5StructureWrite(p, 0, pStruct);
fts5StructureRelease(pStruct);
return fts5IndexReturn(p);
}
/*
@ -4122,6 +4147,7 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, i64 iRowid){
}
if( iRowid<=p->iWriteRowid || (p->nPendingData > p->nMaxPendingData) ){
assert( p->rc==SQLITE_OK );
fts5IndexFlush(p);
}
p->iWriteRowid = iRowid;
@ -4703,6 +4729,8 @@ static void fts5IndexIntegrityCheckSegment(
){
Fts5BtreeIter iter; /* Used to iterate through b-tree hierarchy */
if( pSeg->pgnoFirst==0 && pSeg->pgnoLast==0 ) return;
/* Iterate through the b-tree hierarchy. */
for(fts5BtreeIterInit(p, iIdx, pSeg, &iter);
p->rc==SQLITE_OK && iter.bEof==0;

View File

@ -596,6 +596,10 @@ int sqlite3Fts5StorageOptimize(Fts5Storage *p){
return sqlite3Fts5IndexOptimize(p->pIndex);
}
int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge){
return sqlite3Fts5IndexMerge(p->pIndex, nMerge);
}
/*
** Allocate a new rowid. This is used for "external content" tables when
** a NULL value is inserted into the rowid column. The new rowid is allocated

View File

@ -22,8 +22,6 @@ ifcapable !fts5 {
return
}
if 0 {
set doc [string trim [string repeat "x y z " 200]]
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, x);
@ -75,8 +73,6 @@ do_faultsim_test 2.1 -faults oom-trans* -prep {
catchsql { ROLLBACK }
}
}
#-------------------------------------------------------------------------
# OOM within an 'optimize' operation that writes multiple pages to disk.
#

View File

@ -0,0 +1,87 @@
# 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 fts5fault3
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
#-------------------------------------------------------------------------
# An OOM while resuming a partially completed segment merge.
#
db func rnddoc fts5_rnddoc
do_test 1.0 {
expr srand(0)
execsql {
CREATE VIRTUAL TABLE xx USING fts5(x);
INSERT INTO xx(xx, rank) VALUES('pgsz', 32);
INSERT INTO xx(xx, rank) VALUES('automerge', 16);
}
for {set i 0} {$i < 10} {incr i} {
execsql {
BEGIN;
INSERT INTO xx(x) VALUES(rnddoc(20));
INSERT INTO xx(x) VALUES(rnddoc(20));
INSERT INTO xx(x) VALUES(rnddoc(20));
COMMIT
}
}
execsql {
INSERT INTO xx(xx, rank) VALUES('automerge', 2);
INSERT INTO xx(xx, rank) VALUES('merge', 50);
}
} {}
faultsim_save_and_close
do_faultsim_test 1 -faults oom-* -prep {
faultsim_restore_and_reopen
} -body {
execsql { INSERT INTO xx(xx, rank) VALUES('merge', 1) }
} -test {
faultsim_test_result [list 0 {}]
}
#-------------------------------------------------------------------------
# An OOM while flushing an unusually large term to disk.
#
reset_db
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE xx USING fts5(x);
INSERT INTO xx(xx, rank) VALUES('pgsz', 32);
}
faultsim_save_and_close
set doc "a long term abcdefghijklmnopqrstuvwxyz "
append doc "and then abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz "
append doc [string repeat "abcdefghijklmnopqrstuvwxyz" 10]
do_faultsim_test 2 -faults oom-* -prep {
faultsim_restore_and_reopen
} -body {
execsql { INSERT INTO xx(x) VALUES ($::doc) }
} -test {
faultsim_test_result [list 0 {}]
}
finish_test

View File

@ -0,0 +1,139 @@
# 2014 Dec 20
#
# 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.
#
#***********************************************************************
#
# Test that focus on incremental merges of segments.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5merge
db func repeat [list string repeat]
#-------------------------------------------------------------------------
# Create an fts index so that:
#
# * the index consists of two top-level segments
# * each segment contains records related to $nRowPerSeg rows
# * all rows consist of tokens "x" and "y" only.
#
# Then run ('merge', 1) until everything is completely merged.
#
proc do_merge1_test {testname nRowPerSeg} {
set ::nRowPerSeg [expr $nRowPerSeg]
do_execsql_test $testname.0 {
DROP TABLE IF EXISTS x8;
CREATE VIRTUAL TABLE x8 USING fts5(i);
INSERT INTO x8(x8, rank) VALUES('pgsz', 32);
WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
INSERT INTO x8(x8, rank) VALUES('automerge', 2);
}
for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} {
do_execsql_test $testname.$tn {
INSERT INTO x8(x8, rank) VALUES('merge', 1);
INSERT INTO x8(x8) VALUES('integrity-check');
}
if {$tn>5} break
}
do_test $testname.x [list expr "$tn < 5"] 1
}
do_merge1_test 1.1 1
do_merge1_test 1.2 2
do_merge1_test 1.3 3
do_merge1_test 1.4 4
do_merge1_test 1.5 10
do_merge1_test 1.6 20
do_merge1_test 1.7 100
#-------------------------------------------------------------------------
#
proc do_merge2_test {testname nRow} {
db func rnddoc fts5_rnddoc
do_execsql_test $testname.0 {
DROP TABLE IF EXISTS x8;
CREATE VIRTUAL TABLE x8 USING fts5(i);
INSERT INTO x8(x8, rank) VALUES('pgsz', 32);
}
set ::nRow $nRow
do_test $testname.1 {
for {set i 0} {$i < $::nRow} {incr i} {
execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) }
while {[not_merged x8]} {
execsql {
INSERT INTO x8(x8, rank) VALUES('automerge', 2);
INSERT INTO x8(x8, rank) VALUES('merge', 1);
INSERT INTO x8(x8, rank) VALUES('automerge', 16);
INSERT INTO x8(x8) VALUES('integrity-check');
}
}
}
} {}
}
proc not_merged {tbl} {
set segs [fts5_level_segs $tbl]
foreach s $segs { if {$s>1} { return 1 } }
return 0
}
do_merge2_test 2.1 5
do_merge2_test 2.2 10
do_merge2_test 2.3 20
#-------------------------------------------------------------------------
# Test that an auto-merge will complete any merge that has already been
# started, even if the number of input segments is less than the current
# value of the 'automerge' configuration parameter.
#
db func rnddoc fts5_rnddoc
do_execsql_test 3.1 {
DROP TABLE IF EXISTS x8;
CREATE VIRTUAL TABLE x8 USING fts5(i);
INSERT INTO x8(x8, rank) VALUES('pgsz', 32);
INSERT INTO x8 VALUES(rnddoc(100));
INSERT INTO x8 VALUES(rnddoc(100));
}
do_test 3.2 {
execsql {
INSERT INTO x8(x8, rank) VALUES('automerge', 4);
INSERT INTO x8(x8, rank) VALUES('merge', 1);
}
fts5_level_segs x8
} {2}
do_test 3.3 {
execsql {
INSERT INTO x8(x8, rank) VALUES('automerge', 2);
INSERT INTO x8(x8, rank) VALUES('merge', 1);
}
fts5_level_segs x8
} {2 1}
do_test 3.4 {
execsql { INSERT INTO x8(x8, rank) VALUES('automerge', 4) }
while {[not_merged x8]} {
execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) }
}
fts5_level_segs x8
} {0 1}
finish_test

View File

@ -1,5 +1,5 @@
C Improve\scoverage\sof\sfts5_index.c\sslightly.
D 2015-04-25T20:29:46.707
C Further\stests\sfor\sfts5.
D 2015-04-27T11:31:56.573
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -104,16 +104,16 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl 159c1194da0bc72f51b3c2eb71022568006dc5ad
F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a
F ext/fts5/fts5.c 1eb8ca073be5222c43e4eee5408764c2cbb4200b
F ext/fts5/fts5.c 3383b8a44766c68bda812b68ce74684c6b87787f
F ext/fts5/fts5.h 24a2cc35b5e76eec57b37ba48c12d9d2cb522b3a
F ext/fts5/fts5Int.h 803fd2fc03e3799a38ebb404f2f1309ded5d3e8b
F ext/fts5/fts5Int.h 7dc902e195e00c5820b85d71c2476500c2cf9027
F ext/fts5/fts5_aux.c fcea18b1a2a3f95a498b52aba2983557d7678a22
F ext/fts5/fts5_buffer.c 3ba56cc6824c9f7b1e0695159e0a9c636f6b4a23
F ext/fts5/fts5_config.c 43fcf838d3a3390d1245e3d5e651fa5cc1df575b
F ext/fts5/fts5_expr.c 05da381ab26031243266069302c6eb4094b2c5dd
F ext/fts5/fts5_hash.c 3cb5a3d04dd2030eb0ac8d544711dfd37c0e6529
F ext/fts5/fts5_index.c 699b716f1b84ef78da9ccee25a8b6fe020cff32a
F ext/fts5/fts5_storage.c b3a4cbbcd197fe587789398e51a631f92fc9196c
F ext/fts5/fts5_index.c 5f969f5b6f5e022c9c62973dd6e4e82e1d5f3f30
F ext/fts5/fts5_storage.c 87f85986a6d07391f4e0ddfa9799dbecc40fa165
F ext/fts5/fts5_tcl.c 10bf0eb678d34c1bfdcfaf653d2e6dd92afa8b38
F ext/fts5/fts5_tokenize.c c07f2c2f749282c1dbbf46bde1f6d7095c740b8b
F ext/fts5/fts5_unicode2.c f74f53316377068812a1fa5a37819e6b8124631d
@ -141,8 +141,10 @@ F ext/fts5/test/fts5dlidx.test 748a84ceb74a4154725096a26dfa854260b0182f
F ext/fts5/test/fts5ea.test 04695560a444fcc00c3c4f27783bdcfbf71f030c
F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e
F ext/fts5/test/fts5fault1.test ed71717a479bef32d05f02d9c48691011d160d4d
F ext/fts5/test/fts5fault2.test 0476720b3fcbb3f30c26da4cc8bda4f020d3e408
F ext/fts5/test/fts5fault2.test 37c325cb3e6e27c74c122bb49673b4ae0862df33
F ext/fts5/test/fts5fault3.test f8935b92976ae645d43205562fdbb0c8511dd049
F ext/fts5/test/fts5full.test 0924bdca5416a242103239ace79c6f5aa34bab8d
F ext/fts5/test/fts5merge.test 453a0717881aa7784885217b2040f3f275caff03
F ext/fts5/test/fts5near.test 3f9f64e16cac82725d03d4e04c661090f0b3b947
F ext/fts5/test/fts5optimize.test 0028c90a7817d3e576d1148fc8dff17d89054e54
F ext/fts5/test/fts5porter.test 50322599823cb8080a99f0ec0c39f7d0c12bcb5e
@ -1305,7 +1307,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P e748651c940eae2389fe826cf5c25f1166a5e611
R 0f1e32978d2225a38a865fc7c17144a3
P e5aaa01306597ffd2475dcb83ae889393f68d315
R 328723993a482062ac5cfa3f373fa969
U dan
Z 504cb23846c7efd7bba629c51f43c91a
Z dd82cb2122e4379a606aef38aa888497

View File

@ -1 +1 @@
e5aaa01306597ffd2475dcb83ae889393f68d315
ffeb3ef3cfec3681b72bb28cfa612aa15e07887d