From: dan Date: Wed, 14 Mar 2012 20:01:52 +0000 (+0000) Subject: Add tests for incremental merge code. X-Git-Tag: mountain-lion~3^2~9^2~36 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5730ef599ce6570a54d35d0abf3e7d17b933a4d8;p=thirdparty%2Fsqlite.git Add tests for incremental merge code. FossilOrigin-Name: 570473729d6561d81e6e5f8884fd18487008636e --- diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index b34ca63052..1cd14d304a 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -124,7 +124,7 @@ extern const sqlite3_api_routines *sqlite3_api; # define NEVER(X) (0) #else # define ALWAYS(x) (x) -# define NEVER(X) (x) +# define NEVER(x) (x) #endif /* diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 35da283df3..08f07c10b2 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -3272,10 +3272,16 @@ typedef struct LayerWriter LayerWriter; typedef struct Blob Blob; typedef struct NodeReader NodeReader; +/* +** An instance of the following structure is used as a dynamic buffer +** to build up nodes or other blobs of data in. +** +** The function blobGrowBuffer() is used to extend the allocation. +*/ struct Blob { - char *a; - int n; - int nAlloc; + char *a; /* Pointer to allocation */ + int n; /* Number of valid bytes of data in a[] */ + int nAlloc; /* Allocated size of a[] (nAlloc>=n) */ }; struct LayerWriter { @@ -3405,7 +3411,7 @@ static int fts3IncrmergePush( int iLayer; assert( nTerm>0 ); - for(iLayer=1; iLayeraLayer[iLayer]; int rc = SQLITE_OK; @@ -3565,9 +3571,12 @@ static void fts3IncrmergeRelease( /* Find the root node */ for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){ - if( pWriter->aLayer[iRoot].block.n>0 ) break; - assert( pWriter->aLayer[iRoot].block.nAlloc==0 ); - assert( pWriter->aLayer[iRoot].key.nAlloc==0 ); + LayerWriter *pLayer = &pWriter->aLayer[iRoot]; + if( pLayer->block.n>0 ) break; + assert( *pRc || pLayer->block.nAlloc==0 ); + assert( *pRc || pLayer->key.nAlloc==0 ); + sqlite3_free(pLayer->block.a); + sqlite3_free(pLayer->key.a); } /* Empty output segment. This is a no-op. */ @@ -3628,22 +3637,20 @@ static int fts3TermCmp( } -static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pRc){ +static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){ int bRes = 0; - if( *pRc==SQLITE_OK ){ - sqlite3_stmt *pCheck = 0; - int rc; + sqlite3_stmt *pCheck = 0; + int rc; - rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pCheck, 1, iEnd); - if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1; - rc = sqlite3_reset(pCheck); - } - *pRc = rc; + rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pCheck, 1, iEnd); + if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1; + rc = sqlite3_reset(pCheck); } - return bRes; + *pbRes = bRes; + return rc; } /* @@ -3682,16 +3689,14 @@ static int fts3IncrmergeLoad( } /* Check for the zero-length marker in the %_segments table */ - bAppendable = fts3IsAppendable(p, iEnd, &rc); + rc = fts3IsAppendable(p, iEnd, &bAppendable); /* Check that zKey/nKey is larger than the largest key the candidate */ if( rc==SQLITE_OK && bAppendable ){ - char *aLeaf = (char *)aRoot; - int nLeaf = nRoot; + char *aLeaf = 0; + int nLeaf = 0; - if( aRoot[0] ){ - rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0); - } + rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0); if( rc==SQLITE_OK ){ NodeReader reader; for(rc = nodeReaderInit(&reader, aLeaf, nLeaf); @@ -3705,7 +3710,7 @@ static int fts3IncrmergeLoad( } nodeReaderRelease(&reader); } - if( aLeaf!=aRoot ) sqlite3_free(aLeaf); + sqlite3_free(aLeaf); } if( rc==SQLITE_OK && bAppendable ){ @@ -3866,9 +3871,8 @@ static int fts3IncrmergeWriter( /* Insert the marker in the %_segments table to make sure nobody tries ** to steal the space just allocated. This is also used to identify ** appendable segments. */ - if( rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0); - } + rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0); + if( rc!=SQLITE_OK ) return rc; pWriter->iAbsLevel = iAbsLevel; pWriter->nLeafEst = nLeafEst; @@ -4010,6 +4014,7 @@ static int fts3TruncateNode( pNew, &prev, reader.term.a, reader.term.n, reader.aDoclist, reader.nDoclist ); + if( rc!=SQLITE_OK ) break; } if( bStarted==0 ){ fts3StartNode(pNew, (int)aNode[0], reader.iChild); @@ -4029,68 +4034,66 @@ static int fts3TruncateSegment( const char *zTerm, /* Remove terms smaller than this */ int nTerm /* Number of bytes in buffer zTerm */ ){ - int rc; /* Return code */ + int rc = SQLITE_OK; /* Return code */ Blob root = {0,0,0}; /* New root page image */ Blob block = {0,0,0}; /* Buffer used for any other block */ - + sqlite3_int64 iBlock = 0; /* Block id */ + sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */ + sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */ + int rc2; /* sqlite3_reset() return code */ sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */ - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0); - if( rc==SQLITE_OK ){ - sqlite3_int64 iBlock = 0; /* Block id */ - sqlite3_int64 iNewStart = 0; - sqlite3_int64 iOldStart = 0; - int rc2; /* sqlite3_reset() return code */ - - sqlite3_bind_int64(pFetch, 1, iAbsLevel); - sqlite3_bind_int(pFetch, 2, iIdx); - if( SQLITE_ROW==sqlite3_step(pFetch) ){ - const char *aRoot = sqlite3_column_blob(pFetch, 4); - int nRoot = sqlite3_column_bytes(pFetch, 4); - iOldStart = sqlite3_column_int64(pFetch, 1); - rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock); - } - rc2 = sqlite3_reset(pFetch); - if( rc==SQLITE_OK ) rc = rc2; + assert( p->aStmt[SQL_SELECT_SEGDIR] ); + pFetch = p->aStmt[SQL_SELECT_SEGDIR]; - while( rc==SQLITE_OK && iBlock ){ - char *aBlock = 0; - int nBlock = 0; - iNewStart = iBlock; + sqlite3_bind_int64(pFetch, 1, iAbsLevel); + sqlite3_bind_int(pFetch, 2, iIdx); + if( SQLITE_ROW==sqlite3_step(pFetch) ){ + const char *aRoot = sqlite3_column_blob(pFetch, 4); + int nRoot = sqlite3_column_bytes(pFetch, 4); + iOldStart = sqlite3_column_int64(pFetch, 1); + rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock); + } + rc2 = sqlite3_reset(pFetch); + if( rc==SQLITE_OK ) rc = rc2; - rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0); - if( rc==SQLITE_OK ){ - rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock); - } - if( rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, iNewStart, block.a, block.n); - } - sqlite3_free(aBlock); + while( rc==SQLITE_OK && iBlock ){ + char *aBlock = 0; + int nBlock = 0; + iNewStart = iBlock; + + rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0); + if( rc==SQLITE_OK ){ + rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock); + } + if( rc==SQLITE_OK ){ + rc = fts3WriteSegment(p, iNewStart, block.a, block.n); } + sqlite3_free(aBlock); + } - /* Variable iNewStart now contains the first valid leaf node. */ - if( rc==SQLITE_OK && iNewStart ){ - sqlite3_stmt *pDel = 0; - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDel, 1, iOldStart); - sqlite3_bind_int64(pDel, 2, iNewStart-1); - sqlite3_step(pDel); - rc = sqlite3_reset(pDel); - } + /* Variable iNewStart now contains the first valid leaf node. */ + if( rc==SQLITE_OK && iNewStart ){ + sqlite3_stmt *pDel = 0; + rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pDel, 1, iOldStart); + sqlite3_bind_int64(pDel, 2, iNewStart-1); + sqlite3_step(pDel); + rc = sqlite3_reset(pDel); } + } + if( rc==SQLITE_OK ){ + sqlite3_stmt *pChomp = 0; + rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0); if( rc==SQLITE_OK ){ - sqlite3_stmt *pChomp = 0; - rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pChomp, 1, iNewStart); - sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC); - sqlite3_bind_int64(pChomp, 3, iAbsLevel); - sqlite3_bind_int(pChomp, 4, iIdx); - sqlite3_step(pChomp); - rc = sqlite3_reset(pChomp); - } + sqlite3_bind_int64(pChomp, 1, iNewStart); + sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC); + sqlite3_bind_int64(pChomp, 3, iAbsLevel); + sqlite3_bind_int(pChomp, 4, iIdx); + sqlite3_step(pChomp); + rc = sqlite3_reset(pChomp); } } @@ -4122,7 +4125,7 @@ static int fts3IncrmergeChomp( || (pCsr->apSegment[1]->iIdx==0 && pCsr->apSegment[0]->iIdx==1) ); - for(i=1; i>=0; i--){ + for(i=1; i>=0 && rc==SQLITE_OK; i--){ Fts3SegReader *pSeg = pCsr->apSegment[0]; if( pSeg->iIdx!=i ) pSeg = pCsr->apSegment[1]; assert( pSeg->iIdx==i ); @@ -4149,10 +4152,10 @@ static int fts3IncrmergeChomp( /* ** Attempt an incremental merge that writes nMerge leaf pages. ** -** Incremental merges happen two segments at a time. The two +** Incremental merges happen two segments at a time. The two ** segments to be merged are the two oldest segments (the ones with ** the smallest index) in the highest level that has at least -** nMin segments. Multiple segment pair merges might occur in +** nMin segments. Multiple segment pair merges might occur in ** an attempt to write the quota of nMerge leaf pages. */ static int fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ @@ -4178,8 +4181,7 @@ static int fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ return sqlite3_reset(pFindLevel); } iAbsLevel = sqlite3_column_int64(pFindLevel, 0); - rc = sqlite3_reset(pFindLevel); - if( rc!=SQLITE_OK ) return rc; + sqlite3_reset(pFindLevel); /* Allocate space for the cursor, filter and writer objects */ pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc); @@ -4195,6 +4197,8 @@ static int fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ if( rc==SQLITE_OK ){ rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter); + } + if( rc==SQLITE_OK ){ if( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr)) ){ rc = fts3IncrmergeWriter(p, iAbsLevel, pCsr->zTerm,pCsr->nTerm,pWriter); if( rc==SQLITE_OK ){ @@ -4230,7 +4234,10 @@ static int fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ ** written for the merge, and the minimum number of segments on a level ** before it will be selected for a merge, respectively. */ -static int fts3DoIncrmerge(Fts3Table *p, const char *zParam){ +static int fts3DoIncrmerge( + Fts3Table *p, /* FTS3 table handle */ + const char *zParam /* Nul-terminated string containing "A,B" */ +){ int rc; int nMin = (FTS3_MERGE_COUNT / 2); int nMerge = 0; @@ -4252,11 +4259,12 @@ static int fts3DoIncrmerge(Fts3Table *p, const char *zParam){ } } - if( z[0]!='\0' ) return SQLITE_ERROR; - if( nMin<2 ) nMin = 2; - - rc = fts3Incrmerge(p, nMerge, nMin); - sqlite3Fts3SegmentsClose(p); + if( z[0]!='\0' || nMin<2 ){ + rc = SQLITE_ERROR; + }else{ + rc = fts3Incrmerge(p, nMerge, nMin); + sqlite3Fts3SegmentsClose(p); + } return rc; } @@ -4476,7 +4484,7 @@ static int fts3DeleteByRowid( ** tables. The schema of the virtual table being: ** ** CREATE TABLE ( -** , +** , **
HIDDEN, ** docid HIDDEN, ** HIDDEN diff --git a/manifest b/manifest index 2ce91db0a4..06d7ae13ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sallocating\sa\slarge\sobject\son\sthe\sstack\sin\sthe\sincremental\smerge\scode.\sUse\ssqlite3_malloc()\sinstead. -D 2012-03-14T12:17:40.405 +C Add\stests\sfor\sincremental\smerge\scode. +D 2012-03-14T20:01:52.250 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -65,7 +65,7 @@ F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d F ext/fts3/fts3.c 806632fd0020eed966ab82ea25fe09f1a4c86907 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h cc8991daf660b926ef77a004fe92b97adaf10d97 +F ext/fts3/fts3Int.h 1da6d2af6b079cdd74cd2350761182dedb8bd892 F ext/fts3/fts3_aux.c 72de4cb43db7bfc2f68fbda04b7d8095ae9a6239 F ext/fts3/fts3_expr.c dbc7ba4c3a6061adde0f38ed8e9b349568299551 F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914 @@ -78,7 +78,7 @@ F ext/fts3/fts3_test.c 6b7cc68aef4efb084e1449f7d20c4b20d3bdf6b4 F ext/fts3/fts3_tokenizer.c 3da7254a9881f7e270ab28e2004e0d22b3212bce F ext/fts3/fts3_tokenizer.h 66dec98e365854b6cd2d54f1a96bb6d428fc5a68 F ext/fts3/fts3_tokenizer1.c 0dde8f307b8045565cf63797ba9acfaff1c50c68 -F ext/fts3/fts3_write.c 772b8c32b93c60b85b60c635de2ff5b3f49fd779 +F ext/fts3/fts3_write.c 355121666034ece7d2472caa3f322d0cb61b0f0d F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9 @@ -448,7 +448,7 @@ F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682 F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654 -F test/fts3_common.tcl 91c29230c428443e6552add9b18cf94a3dc23074 +F test/fts3_common.tcl 1b2e522476236a018c1a4b8ae4f7599ce29b7be0 F test/fts3aa.test 909d5f530d30a8e36b9328d67285eae6537c79c0 F test/fts3ab.test 09aeaa162aee6513d9ff336b6932211008b9d1f9 F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63 @@ -497,7 +497,8 @@ F test/fts3sort.test 95be0b19d7e41c44b29014f13ea8bddd495fd659 F test/fts4aa.test 6e7f90420b837b2c685f3bcbe84c868492d40a68 F test/fts4content.test 17b2360f7d1a9a7e5aa8022783f5c5731b6dfd4f F test/fts4langid.test fabdd5a8db0fa00292e0704809f566e3fb6dba3a -F test/fts4merge.test 3af8fa8fd9f27a9eb402b9ae399aa53fbaae8481 +F test/fts4merge.test d841f283bf9557d549afde513fe38d0b48adc4f7 +F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/func.test 6c5ce11e3a0021ca3c0649234e2d4454c89110ca F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a @@ -636,7 +637,7 @@ F test/pageropt.test 9191867ed19a2b3db6c42d1b36b6fbc657cd1ab0 F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 -F test/permutations.test 2b5a1b64a8e5114757457fbce9010387d1fe7682 +F test/permutations.test 0ab1e7748de5d29c4c648ba5ce3b983ab80653d1 F test/pragma.test f11c59ec935a52edb4d3d5676d456588121fcefa F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -993,7 +994,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P f97b12e0955c4c29f9c31a186d72d87f7407782e -R 86bb2bcb41aa5bde569f19117ae756eb +P 36ae510de45be44efd34cff242d02fb21b7419ac +R 326f29ae3378aab5424c0bd2deaa1142 U dan -Z da9e601d088fda8ad57ce1fc3070902a +Z 9fe983241614f7794efd59c0386308c4 diff --git a/manifest.uuid b/manifest.uuid index 137182d9b7..9cec3849f5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36ae510de45be44efd34cff242d02fb21b7419ac \ No newline at end of file +570473729d6561d81e6e5f8884fd18487008636e \ No newline at end of file diff --git a/test/fts3_common.tcl b/test/fts3_common.tcl index 23a8cfca67..6c9c2fcec9 100644 --- a/test/fts3_common.tcl +++ b/test/fts3_common.tcl @@ -14,6 +14,67 @@ # to use Tcl. # + +#------------------------------------------------------------------------- +# USAGE: fts3_build_db_1 N +# +# Build a sample FTS table in the database opened by database connection +# [db]. The name of the new table is "t1". +# +proc fts3_build_db_1 {n} { + + if {$n > 10000} {error "n must be <= 10000"} + + db eval { CREATE VIRTUAL TABLE t1 USING fts4(x, y) } + + set xwords [list zero one two three four five six seven eight nine ten] + set ywords [list alpha beta gamma delta epsilon zeta eta theta iota kappa] + + for {set i 0} {$i < $n} {incr i} { + set x "" + set y "" + + set x [list] + lappend x [lindex $xwords [expr ($i / 1000) % 10]] + lappend x [lindex $xwords [expr ($i / 100) % 10]] + lappend x [lindex $xwords [expr ($i / 10) % 10]] + lappend x [lindex $xwords [expr ($i / 1) % 10]] + + set y [list] + lappend y [lindex $ywords [expr ($i / 1000) % 10]] + lappend y [lindex $ywords [expr ($i / 100) % 10]] + lappend y [lindex $ywords [expr ($i / 10) % 10]] + lappend y [lindex $ywords [expr ($i / 1) % 10]] + + db eval { INSERT INTO t1(docid, x, y) VALUES($i, $x, $y) } + } +} + +#------------------------------------------------------------------------- +# USAGE: fts3_build_db_2 N +# +# Build a sample FTS table in the database opened by database connection +# [db]. The name of the new table is "t2". +# +proc fts3_build_db_2 {n} { + + if {$n > 100000} {error "n must be <= 100000"} + + db eval { CREATE VIRTUAL TABLE t2 USING fts4 } + + set chars [list a b c d e f g h i j k l m n o p q r s t u v w x y z ""] + + for {set i 0} {$i < $n} {incr i} { + set word "" + set n [llength $chars] + append word [lindex $chars [expr {($i / 1) % $n}]] + append word [lindex $chars [expr {($i / $n) % $n}]] + append word [lindex $chars [expr {($i / ($n*$n)) % $n}]] + + db eval { INSERT INTO t2(docid, content) VALUES($i, $word) } + } +} + #------------------------------------------------------------------------- # USAGE: fts3_integrity_check TBL # @@ -98,7 +159,7 @@ proc fts3_integrity_check {tbl} { set es "Error at docid=$iDoc col=$iCol pos=$pos. Index is missing" lappend errors $es } else { - if {$C($iDoc,$iCol,$pos) != "$term"} { + if {[string compare $C($iDoc,$iCol,$pos) $term]} { set es "Error at docid=$iDoc col=$iCol pos=$pos. Index " append es "has \"$C($iDoc,$iCol,$pos)\", document has \"$term\"" lappend errors $es diff --git a/test/fts4merge.test b/test/fts4merge.test index 805a78cf97..a5995921f3 100644 --- a/test/fts4merge.test +++ b/test/fts4merge.test @@ -23,35 +23,6 @@ ifcapable !fts3 { return } -proc fts3_build_db_1 {n} { - - if {$n > 10000} {error "n must be <= 10000"} - - db eval { CREATE VIRTUAL TABLE t1 USING fts4(x, y) } - - set xwords [list zero one two three four five six seven eight nine ten] - set ywords [list alpha beta gamma delta epsilon zeta eta theta iota kappa] - - for {set i 0} {$i < $n} {incr i} { - set x "" - set y "" - - set x [list] - lappend x [lindex $xwords [expr ($i / 1000) % 10]] - lappend x [lindex $xwords [expr ($i / 100) % 10]] - lappend x [lindex $xwords [expr ($i / 10) % 10]] - lappend x [lindex $xwords [expr ($i / 1) % 10]] - - set y [list] - lappend y [lindex $ywords [expr ($i / 1000) % 10]] - lappend y [lindex $ywords [expr ($i / 100) % 10]] - lappend y [lindex $ywords [expr ($i / 10) % 10]] - lappend y [lindex $ywords [expr ($i / 1) % 10]] - - db eval { INSERT INTO t1(docid, x, y) VALUES($i, $x, $y) } - } -} - #------------------------------------------------------------------------- # Test cases 1.* # @@ -98,6 +69,57 @@ do_execsql_test 1.5 { 3 {0 1 2} } +#------------------------------------------------------------------------- +# Test cases 2.* test that errors in the xxx part of the 'merge=xxx' are +# handled correctly. +# +do_execsql_test 2.0 { CREATE VIRTUAL TABLE t2 USING fts4 } + +foreach {tn arg} { + 1 {merge=abc} + 2 {merge=%%%} + 3 {merge=,} + 4 {merge=5,} + 5 {merge=6,%} + 6 {merge=6,six} + 7 {merge=6,1} + 8 {merge=6,0} +} { + do_catchsql_test 2.$tn { + INSERT INTO t2(t2) VALUES($arg); + } {1 {SQL logic error or missing database}} +} + +#------------------------------------------------------------------------- +# Test cases 3.* +# +do_test 3.0 { + reset_db + execsql { PRAGMA page_size = 512 } + fts3_build_db_2 30040 +} {} +do_test 3.1 { fts3_integrity_check t2 } {ok} + +do_execsql_test 3.2 { + SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level +} { + 0 {0 1 2 3 4 5 6 7} + 1 {0 1 2 3 4} + 2 {0 1 2 3 4} + 3 {0 1 2 3 4 5 6} +} + +do_execsql_test 3.3 { + INSERT INTO t2(t2) VALUES('merge=1000000,2'); + SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level +} { + 0 {0 1} + 1 {0 1} + 2 0 + 3 {0 1} + 4 {0 1} + 5 0 +} finish_test diff --git a/test/fts4merge2.test b/test/fts4merge2.test new file mode 100644 index 0000000000..308b6929fa --- /dev/null +++ b/test/fts4merge2.test @@ -0,0 +1,38 @@ + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/fts3_common.tcl +source $testdir/malloc_common.tcl +set ::testprefix fts4merge2 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +do_test 1.0 { + fts3_build_db_1 1000 + faultsim_save_and_close +} {} + +do_faultsim_test 1.1 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO t1(t1) VALUES('merge=32,4') } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 1.2 -faults oom-t* -prep { + if {$iFail<100} {set iFail 803} + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO t1(t1) VALUES('merge=1,2') } + execsql { INSERT INTO t1(t1) VALUES('merge=1,2') } +} -test { + faultsim_test_result {0 {}} +} + +finish_test diff --git a/test/permutations.test b/test/permutations.test index 26c1b2a514..6f66e85e94 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -184,7 +184,7 @@ test_suite "fts3" -prefix "" -description { fts3aux1.test fts3comp1.test fts3auto.test fts4aa.test fts4content.test fts3conf.test fts3prefix.test fts3fault2.test fts3corrupt.test - fts3corrupt2.test fts3first.test fts4langid.test + fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test }