mirror of https://github.com/sqlite/sqlite
Further tests for fts5.
FossilOrigin-Name: ffeb3ef3cfec3681b72bb28cfa612aa15e07887d
This commit is contained in:
parent
26c84373c4
commit
c1cea8f731
|
@ -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{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
22
manifest
22
manifest
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
e5aaa01306597ffd2475dcb83ae889393f68d315
|
||||
ffeb3ef3cfec3681b72bb28cfa612aa15e07887d
|
Loading…
Reference in New Issue