From: dan Date: Fri, 1 May 2015 20:38:57 +0000 (+0000) Subject: Further improvements to test coverage of fts5 code. X-Git-Tag: version-3.8.11~114^2~51 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0501b2492a63adb781050eef55000955e061f3e1;p=thirdparty%2Fsqlite.git Further improvements to test coverage of fts5 code. FossilOrigin-Name: d4331943dff259380c4025bb740d8aba6972d351 --- diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index a638559310..79dfec5667 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -104,13 +104,13 @@ struct Fts5Parse { }; void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){ + va_list ap; + va_start(ap, zFmt); if( pParse->rc==SQLITE_OK ){ - va_list ap; - va_start(ap, zFmt); pParse->zErr = sqlite3_vmprintf(zFmt, ap); - va_end(ap); pParse->rc = SQLITE_ERROR; } + va_end(ap); } static int fts5ExprIsspace(char t){ @@ -269,52 +269,51 @@ int sqlite3Fts5ExprPhraseExpr( Fts5Expr **ppNew ){ int rc = SQLITE_OK; /* Return code */ - Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */ - int i; /* Used to iterate through phrase terms */ - - /* Components of the new expression object */ - Fts5Expr *pNew; - Fts5ExprPhrase **apPhrase; - Fts5ExprNode *pNode; - Fts5ExprNearset *pNear; - Fts5ExprPhrase *pCopy; + Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ + Fts5ExprPhrase *pCopy; /* Copy of pOrig */ + Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ pOrig = pExpr->apExprPhrase[iPhrase]; pCopy = (Fts5ExprPhrase*)fts5ExprMalloc(&rc, sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * pOrig->nTerm ); - pNew = (Fts5Expr*)fts5ExprMalloc(&rc, sizeof(Fts5Expr)); - apPhrase = (Fts5ExprPhrase**)fts5ExprMalloc(&rc, sizeof(Fts5ExprPhrase*)); - pNode = (Fts5ExprNode*)fts5ExprMalloc(&rc, sizeof(Fts5ExprNode)); - pNear = (Fts5ExprNearset*)fts5ExprMalloc(&rc, - sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*) - ); + if( pCopy ){ + int i; /* Used to iterate through phrase terms */ + Fts5ExprPhrase **apPhrase; + Fts5ExprNode *pNode; + Fts5ExprNearset *pNear; + + pNew = (Fts5Expr*)fts5ExprMalloc(&rc, sizeof(Fts5Expr)); + apPhrase = (Fts5ExprPhrase**)fts5ExprMalloc(&rc, sizeof(Fts5ExprPhrase*)); + pNode = (Fts5ExprNode*)fts5ExprMalloc(&rc, sizeof(Fts5ExprNode)); + pNear = (Fts5ExprNearset*)fts5ExprMalloc(&rc, + sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*) + ); - for(i=0; rc==SQLITE_OK && inTerm; i++){ - pCopy->aTerm[i].zTerm = fts5ExprStrdup(&rc, pOrig->aTerm[i].zTerm); - pCopy->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; - } + for(i=0; inTerm; i++){ + pCopy->aTerm[i].zTerm = fts5ExprStrdup(&rc, pOrig->aTerm[i].zTerm); + pCopy->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + } - if( rc==SQLITE_OK ){ - /* All the allocations succeeded. Put the expression object together. */ - pNew->pIndex = pExpr->pIndex; - pNew->pRoot = pNode; - pNew->nPhrase = 1; - pNew->apExprPhrase = apPhrase; - pNew->apExprPhrase[0] = pCopy; - - pNode->eType = FTS5_STRING; - pNode->pNear = pNear; - - pNear->iCol = -1; - pNear->nPhrase = 1; - pNear->apPhrase[0] = pCopy; - - pCopy->nTerm = pOrig->nTerm; - pCopy->pNode = pNode; - }else{ - /* At least one allocation failed. Free them all. */ - if( pCopy ){ + if( rc==SQLITE_OK ){ + /* All the allocations succeeded. Put the expression object together. */ + pNew->pIndex = pExpr->pIndex; + pNew->pRoot = pNode; + pNew->nPhrase = 1; + pNew->apExprPhrase = apPhrase; + pNew->apExprPhrase[0] = pCopy; + + pNode->eType = FTS5_STRING; + pNode->pNear = pNear; + + pNear->iCol = -1; + pNear->nPhrase = 1; + pNear->apPhrase[0] = pCopy; + + pCopy->nTerm = pOrig->nTerm; + pCopy->pNode = pNode; + }else{ + /* At least one allocation failed. Free them all. */ for(i=0; inTerm; i++){ sqlite3_free(pCopy->aTerm[i].zTerm); } @@ -504,7 +503,7 @@ static int fts5ExprNearIsMatch(Fts5ExprNearset *pNear, int *pbMatch){ /* If the aStatic[] array is not large enough, allocate a large array ** using sqlite3_malloc(). This approach could be improved upon. */ if( pNear->nPhrase>(sizeof(aStatic) / sizeof(aStatic[0])) ){ - int nByte = sizeof(Fts5LookaheadReader) * pNear->nPhrase; + int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; a = (Fts5NearTrimmer*)sqlite3_malloc(nByte); if( !a ) return SQLITE_NOMEM; memset(a, 0, nByte); @@ -719,7 +718,7 @@ static int fts5ExprNearNextMatch( /* Advance the iterators until they all point to the same rowid */ rc = fts5ExprNearNextRowidMatch(pExpr, pNode, bFromValid, iFrom); - if( pNode->bEof || rc!=SQLITE_OK ) break; + if( rc!=SQLITE_OK || pNode->bEof ) break; /* Check that each phrase in the nearset matches the current row. ** Populate the pPhrase->poslist buffers at the same time. If any diff --git a/ext/fts5/test/fts5ea.test b/ext/fts5/test/fts5ea.test index f913006530..7b58d8cd8f 100644 --- a/ext/fts5/test/fts5ea.test +++ b/ext/fts5/test/fts5ea.test @@ -9,6 +9,9 @@ # #************************************************************************* # +# Test the fts5 expression parser directly using the fts5_expr() SQL +# test function. +# source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5ea @@ -40,6 +43,10 @@ foreach {tn expr res} { 8 {one OR two AND three} {"one" OR ("two" AND "three")} 9 {NEAR(one two)} {NEAR("one" "two", 10)} 10 {NEAR("one three"* two, 5)} {NEAR("one" + "three" * "two", 5)} + 11 {a OR b NOT c} {"a" OR ("b" NOT "c")} + 12 "\x20one\x20two\x20three" {("one" AND "two") AND "three"} + 13 "\x09one\x0Atwo\x0Dthree" {("one" AND "two") AND "three"} + 14 {"abc""def"} {"abc" + "def"} } { do_execsql_test 1.$tn {SELECT fts5_expr($expr)} [list $res] } @@ -53,7 +60,6 @@ foreach {tn expr res} { do_execsql_test 2.$tn {SELECT fts5_expr($expr, 'c1', 'c2')} [list $res] } -breakpoint foreach {tn expr err} { 1 {AND} {fts5: syntax error near "AND"} 2 {abc def AND} {fts5: syntax error near ""} @@ -63,21 +69,13 @@ foreach {tn expr err} { 6 {(a OR b) NOT c)} {fts5: syntax error near ")"} 7 {nosuch: a nosuch2: b} {no such column: nosuch} 8 {addr: a nosuch2: b} {no such column: nosuch2} + 9 {NOT} {fts5: syntax error near "NOT"} + 10 {a AND "abc} {unterminated string} } { do_catchsql_test 3.$tn {SELECT fts5_expr($expr, 'name', 'addr')} [list 1 $err] } -# do_syntax_error_test 1.0 {NOT} {syntax error near "NOT"} - - - -# do_catchsql_test 1.1 { - # SELECT fts5_expr('a OR b NOT c') -#} {0 {"a" OR "b" NOT "c"}} - - -#do_execsql_test 1.0 { SELECT fts5_expr('a') } {{"a"}} finish_test diff --git a/ext/fts5/test/fts5fault4.test b/ext/fts5/test/fts5fault4.test index c0c9dd1d6c..8e6c827ad3 100644 --- a/ext/fts5/test/fts5fault4.test +++ b/ext/fts5/test/fts5fault4.test @@ -158,8 +158,6 @@ do_faultsim_test 5.2 -faults oom-* -body { faultsim_test_result "0 {10-$::str {a b c}}" } -} - #------------------------------------------------------------------------- # OOM errors within auxiliary functions. @@ -203,6 +201,64 @@ do_faultsim_test 6.2 -faults oom-t* -body { faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM} } +#------------------------------------------------------------------------- +# OOM error when querying for a phrase with many tokens. +# +reset_db +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE tt USING fts5(x, y); + INSERT INTO tt VALUES('f b g b c b', 'f a d c c b'); -- 1 + INSERT INTO tt VALUES('d a e f e d', 'f b b d e e'); -- 2 + INSERT INTO tt VALUES('f b g a d c', 'e f c f a d'); -- 3 + INSERT INTO tt VALUES('f f c d g f', 'f a e b g b'); -- 4 + INSERT INTO tt VALUES('a g b d a g', 'e g a e a c'); -- 5 + INSERT INTO tt VALUES('c d b d e f', 'f g e g e e'); -- 6 + INSERT INTO tt VALUES('e g f f b c', 'f c e f g f'); -- 7 + INSERT INTO tt VALUES('e g c f c e', 'f e e a f g'); -- 8 + INSERT INTO tt VALUES('e a e b e e', 'd c c f f f'); -- 9 + INSERT INTO tt VALUES('f a g g c c', 'e g d g c e'); -- 10 + INSERT INTO tt VALUES('c d b a e f', 'f g e h e e'); -- 11 +} + +do_faultsim_test 7.2 -faults oom-* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'f+g+e+g+e+e' } +} -test { + faultsim_test_result {0 6} {1 SQLITE_NOMEM} +} + +do_faultsim_test 7.3 -faults oom-* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d e f)' } +} -test { + faultsim_test_result {0 11} {1 SQLITE_NOMEM} +} + +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE tt USING fts5(x); + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); + BEGIN; + INSERT INTO tt(rowid, x) VALUES(1, 'a b c d x x'); + WITH ii(i) AS (SELECT 2 UNION ALL SELECT i+1 FROM ii WHERE i<99) + INSERT INTO tt(rowid, x) SELECT i, 'a b c x x d' FROM ii; + INSERT INTO tt(rowid, x) VALUES(100, 'a b c d x x'); + COMMIT; +} + +do_faultsim_test 8.1 -faults oom-t* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d, 2)' } +} -test { + faultsim_test_result {0 {1 100}} {1 SQLITE_NOMEM} +} + +do_faultsim_test 8.2 -faults oom-t* -body { + db eval { SELECT count(*) FROM tt WHERE tt MATCH 'a OR d' } +} -test { + faultsim_test_result {0 100} {1 SQLITE_NOMEM} +} diff --git a/manifest b/manifest index 5f785b7ee6..92d1a1bb51 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\stest\scoverage\sof\sfts5.c. -D 2015-05-01T12:14:23.640 +C Further\simprovements\sto\stest\scoverage\sof\sfts5\scode. +D 2015-05-01T20:38:57.153 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -110,7 +110,7 @@ F ext/fts5/fts5Int.h 2e0a1a6b77e1e014b7e9b1479ca686ff79930457 F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971 F ext/fts5/fts5_buffer.c 8c8cfe7f09ca2767ab53ea883f9a0af0edb6bbae F ext/fts5/fts5_config.c ecbbd5163758a958106867051892e0dfecf68b5c -F ext/fts5/fts5_expr.c 663c75dfdb1bfd8809d696357d7b55f507815098 +F ext/fts5/fts5_expr.c e2005ba7823f4ac51d46a8e5aaa1ff66c701b32e F ext/fts5/fts5_hash.c 29d8b0668727863cc1f1efa65efe4dd78635b016 F ext/fts5/fts5_index.c de588982b0237b1605d6c37afd115b34c95c3da1 F ext/fts5/fts5_storage.c ef60fc9dcc4e274f9589165e26833173c273ae18 @@ -140,12 +140,12 @@ F ext/fts5/test/fts5corrupt.test 138aecc75c36c3dac9259c7f57c5bc3d009255f8 F ext/fts5/test/fts5corrupt2.test 494111fd4f2dab36499cf97718eaba1f7c11e9d0 F ext/fts5/test/fts5dlidx.test 748a84ceb74a4154725096a26dfa854260b0182f F ext/fts5/test/fts5doclist.test 635b80ac785627841a59c583bac702b55d49fdc5 -F ext/fts5/test/fts5ea.test 04695560a444fcc00c3c4f27783bdcfbf71f030c +F ext/fts5/test/fts5ea.test 7cc498993c16849bb866dbdfb008d91a29f9870b F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e F ext/fts5/test/fts5fault1.test ed71717a479bef32d05f02d9c48691011d160d4d F ext/fts5/test/fts5fault2.test 26c3d70648f691e2cc9391e14bbc11a973656383 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3 -F ext/fts5/test/fts5fault4.test 087066bae36f41227eb85968a2436c8a9c960501 +F ext/fts5/test/fts5fault4.test 4090af395d8d3342c0a0b27349dd71eb7cc6262d F ext/fts5/test/fts5full.test 0924bdca5416a242103239ace79c6f5aa34bab8d F ext/fts5/test/fts5hash.test adb7b0442cc1c77c507f07e16d11490486e75dfa F ext/fts5/test/fts5merge.test 453a0717881aa7784885217b2040f3f275caff03 @@ -1315,7 +1315,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 c1f07a3aa98eac87e2747527d15e5e5562221ceb -R 67c24377157269f998af5007c163ea4c +P add4f4681c648dcbecaa68d08f7b2f4e6d63003c +R 58de859125935eeaf7ecede3ffbb5a07 U dan -Z 082bd0388383a4ef8c727daa5b60df05 +Z fc00d731e9356a3f17b66c35cad599ad diff --git a/manifest.uuid b/manifest.uuid index 0a40e5a487..ee6ce26d11 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -add4f4681c648dcbecaa68d08f7b2f4e6d63003c \ No newline at end of file +d4331943dff259380c4025bb740d8aba6972d351 \ No newline at end of file