From: dan Date: Fri, 1 May 2015 12:14:23 +0000 (+0000) Subject: Improve test coverage of fts5.c. X-Git-Tag: version-3.8.11~114^2~52 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=557085a5a1bb0f6a2d60215e87d78b6e8729e442;p=thirdparty%2Fsqlite.git Improve test coverage of fts5.c. FossilOrigin-Name: add4f4681c648dcbecaa68d08f7b2f4e6d63003c --- diff --git a/ext/fts5/fts5.c b/ext/fts5/fts5.c index b37f72d58d..a753d671da 100644 --- a/ext/fts5/fts5.c +++ b/ext/fts5/fts5.c @@ -1495,6 +1495,9 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){ return rc; } +/* +** Implementation of the xSetAuxdata() method. +*/ static int fts5ApiSetAuxdata( Fts5Context *pCtx, /* Fts5 context */ void *pPtr, /* Pointer to save as auxdata */ @@ -1503,6 +1506,8 @@ static int fts5ApiSetAuxdata( Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; Fts5Auxdata *pData; + /* Search through the cursors list of Fts5Auxdata objects for one that + ** corresponds to the currently executing auxiliary function. */ for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){ if( pData->pAux==pCsr->pAux ) break; } @@ -1512,12 +1517,12 @@ static int fts5ApiSetAuxdata( pData->xDelete(pData->pPtr); } }else{ - pData = (Fts5Auxdata*)sqlite3_malloc(sizeof(Fts5Auxdata)); + int rc = SQLITE_OK; + pData = (Fts5Auxdata*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Auxdata)); if( pData==0 ){ if( xDelete ) xDelete(pPtr); - return SQLITE_NOMEM; + return rc; } - memset(pData, 0, sizeof(Fts5Auxdata)); pData->pAux = pCsr->pAux; pData->pNext = pCsr->pAuxdata; pCsr->pAuxdata = pData; @@ -1644,6 +1649,7 @@ static void fts5ApiCallback( if( pCsr==0 ){ char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId); sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); }else{ fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]); } diff --git a/ext/fts5/fts5_tcl.c b/ext/fts5/fts5_tcl.c index 431533afcc..171b4849a5 100644 --- a/ext/fts5/fts5_tcl.c +++ b/ext/fts5/fts5_tcl.c @@ -61,6 +61,27 @@ static int f5tDbPointer(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **ppDb){ /* End of code that accesses the SqliteDb struct. **************************************************************************/ +static int f5tResultToErrorCode(const char *zRes){ + struct ErrorCode { + int rc; + const char *zError; + } aErr[] = { + { SQLITE_DONE, "SQLITE_DONE" }, + { SQLITE_ERROR, "SQLITE_ERROR" }, + { SQLITE_OK, "SQLITE_OK" }, + { SQLITE_OK, "" }, + }; + int i; + + for(i=0; iinterp, zCmd); + if( rc==TCL_OK ){ + rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp)); + } + return rc; } @@ -195,20 +220,22 @@ static int xF5tApi( int nArg; const char *zMsg; } aSub[] = { - { "xColumnCount", 0, "" }, - { "xRowCount", 0, "" }, - { "xColumnTotalSize", 1, "COL" }, - { "xTokenize", 2, "TEXT SCRIPT" }, - { "xPhraseCount", 0, "" }, - { "xPhraseSize", 1, "PHRASE" }, - { "xInstCount", 0, "" }, - { "xInst", 1, "IDX" }, - { "xRowid", 0, "" }, - { "xColumnText", 1, "COL" }, - { "xColumnSize", 1, "COL" }, - { "xQueryPhrase", 2, "PHRASE SCRIPT" }, - { "xSetAuxdata", 1, "VALUE" }, - { "xGetAuxdata", 1, "CLEAR" }, + { "xColumnCount", 0, "" }, /* 0 */ + { "xRowCount", 0, "" }, /* 1 */ + { "xColumnTotalSize", 1, "COL" }, /* 2 */ + { "xTokenize", 2, "TEXT SCRIPT" }, /* 3 */ + { "xPhraseCount", 0, "" }, /* 4 */ + { "xPhraseSize", 1, "PHRASE" }, /* 5 */ + { "xInstCount", 0, "" }, /* 6 */ + { "xInst", 1, "IDX" }, /* 7 */ + { "xRowid", 0, "" }, /* 8 */ + { "xColumnText", 1, "COL" }, /* 9 */ + { "xColumnSize", 1, "COL" }, /* 10 */ + { "xQueryPhrase", 2, "PHRASE SCRIPT" }, /* 11 */ + { "xSetAuxdata", 1, "VALUE" }, /* 12 */ + { "xGetAuxdata", 1, "CLEAR" }, /* 13 */ + { "xSetAuxdataInt", 1, "INTEGER" }, /* 14 */ + { "xGetAuxdataInt", 1, "CLEAR" }, /* 15 */ { 0, 0, 0} }; @@ -386,6 +413,25 @@ static int xF5tApi( break; } + /* These two - xSetAuxdataInt and xGetAuxdataInt - are similar to the + ** xSetAuxdata and xGetAuxdata methods implemented above. The difference + ** is that they may only save an integer value as auxiliary data, and + ** do not specify a destructor function. */ + CASE(14, "xSetAuxdataInt") { + int iVal; + if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ) return TCL_ERROR; + rc = p->pApi->xSetAuxdata(p->pFts, (void*)iVal, 0); + break; + } + CASE(15, "xGetAuxdataInt") { + int iVal; + int bClear; + if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR; + iVal = (int)p->pApi->xGetAuxdata(p->pFts, bClear); + Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); + break; + } + default: assert( 0 ); break; diff --git a/ext/fts5/test/fts5aux.test b/ext/fts5/test/fts5aux.test index b5cbc6e9a3..61a28e50fb 100644 --- a/ext/fts5/test/fts5aux.test +++ b/ext/fts5/test/fts5aux.test @@ -52,6 +52,134 @@ do_execsql_test 2.2 { } {2 3} +#------------------------------------------------------------------------- +# Test the xSet and xGetAuxdata APIs with a NULL destructor. +# +proc prevrowid {add cmd} { + set res [$cmd xGetAuxdataInt 0] + set r [$cmd xRowid] + $cmd xSetAuxdataInt $r + return [expr $res + $add] +} +sqlite3_fts5_create_function db prevrowid [list prevrowid 0] +sqlite3_fts5_create_function db prevrowid1 [list prevrowid 1] + +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE e5 USING fts5(x); + INSERT INTO e5 VALUES('a b c'); + INSERT INTO e5 VALUES('d e f'); + INSERT INTO e5 VALUES('a b c'); + INSERT INTO e5 VALUES('d e f'); + INSERT INTO e5 VALUES('a b c'); +} + +do_execsql_test 3.1 { + SELECT prevrowid(e5) || '+' || rowid FROM e5 WHERE e5 MATCH 'c' +} {0+1 1+3 3+5} + +do_execsql_test 3.2 { + SELECT prevrowid(e5) || '+' || prevrowid1(e5) || '+' || rowid + FROM e5 WHERE e5 MATCH 'e' +} {0+1+2 2+3+4} + +#------------------------------------------------------------------------- +# Test that if the xQueryPhrase callback returns other than SQLITE_OK, +# the query is abandoned. And that if it returns an error code other than +# SQLITE_DONE, the error is propagated back to the caller. +# +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE e7 USING fts5(x); + INSERT INTO e7 VALUES('a x a'); + INSERT INTO e7 VALUES('b x b'); + INSERT INTO e7 VALUES('c x c'); + INSERT INTO e7 VALUES('d x d'); + INSERT INTO e7 VALUES('e x e'); +} + +proc xCallback {rowid code cmd} { + set r [$cmd xRowid] + lappend ::cb $r + if {$r==$rowid} { return $code } + return "" +} + +proc phrasequery {cmd code} { + set ::cb [list] + $cmd xQueryPhrase 1 [list xCallback [$cmd xRowid] $code] + set ::cb +} + +sqlite3_fts5_create_function db phrasequery phrasequery + +do_execsql_test 4.1 { + SELECT phrasequery(e7, 'SQLITE_OK') FROM e7 WHERE e7 MATCH 'c x' +} {{1 2 3 4 5}} + +do_execsql_test 4.2 { + SELECT phrasequery(e7, 'SQLITE_DONE') FROM e7 WHERE e7 MATCH 'c x' +} {{1 2 3}} + +do_catchsql_test 4.3 { + SELECT phrasequery(e7, 'SQLITE_ERROR') FROM e7 WHERE e7 MATCH 'c x' +} {1 SQLITE_ERROR} + +#------------------------------------------------------------------------- +# Auxiliary function calls with many cursors in the global cursor list. +# +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE e9 USING fts5(y); + INSERT INTO e9(rowid, y) VALUES(1, 'i iii'); + INSERT INTO e9(rowid, y) VALUES(2, 'ii iv'); + INSERT INTO e9(rowid, y) VALUES(3, 'ii'); + INSERT INTO e9(rowid, y) VALUES(4, 'i iv'); + INSERT INTO e9(rowid, y) VALUES(5, 'iii'); +} + +proc my_rowid {cmd} { $cmd xRowid } +sqlite3_fts5_create_function db my_rowid my_rowid + +foreach {var q} { + s1 i + s2 ii + s3 iii + s4 iv +} { + set sql "SELECT my_rowid(e9) FROM e9 WHERE e9 MATCH '$q'" + set $var [sqlite3_prepare db $sql -1 dummy] +} + +do_test 5.1.1 { sqlite3_step $s1 ; sqlite3_column_int $s1 0 } 1 +do_test 5.1.2 { sqlite3_step $s2 ; sqlite3_column_int $s2 0 } 2 +do_test 5.1.3 { sqlite3_step $s3 ; sqlite3_column_int $s3 0 } 1 +do_test 5.1.4 { sqlite3_step $s4 ; sqlite3_column_int $s4 0 } 2 + +do_test 5.2.1 { sqlite3_step $s1 ; sqlite3_column_int $s1 0 } 4 +do_test 5.2.2 { sqlite3_step $s2 ; sqlite3_column_int $s2 0 } 3 +do_test 5.2.3 { sqlite3_step $s3 ; sqlite3_column_int $s3 0 } 5 +do_test 5.2.4 { sqlite3_step $s4 ; sqlite3_column_int $s4 0 } 4 + +sqlite3_finalize $s1 +sqlite3_finalize $s2 +sqlite3_finalize $s3 +sqlite3_finalize $s4 + +#------------------------------------------------------------------------- +# Passing an invalid first argument to an auxiliary function is detected. +# +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE e11 USING fts5(y, z); + INSERT INTO e11(rowid, y, z) VALUES(1, 'a b', 45); + INSERT INTO e11(rowid, y, z) VALUES(2, 'b c', 46); +} + +do_catchsql_test 6.1 { + SELECT my_rowid(z) FROM e11 WHERE e11 MATCH 'b' +} {1 {no such cursor: 45}} + +do_catchsql_test 6.2 { + SELECT my_rowid(y) FROM e11 WHERE e11 MATCH 'b' +} {1 {no such cursor: 0}} + finish_test diff --git a/ext/fts5/test/fts5fault4.test b/ext/fts5/test/fts5fault4.test index d7ced10c72..c0c9dd1d6c 100644 --- a/ext/fts5/test/fts5fault4.test +++ b/ext/fts5/test/fts5fault4.test @@ -168,6 +168,8 @@ reset_db do_execsql_test 6.0 { CREATE VIRTUAL TABLE x3 USING fts5(xxx); INSERT INTO x3 VALUES('a b c d c b a'); + INSERT INTO x3 VALUES('a a a a a a a'); + INSERT INTO x3 VALUES('a a a a a a a'); } do_faultsim_test 6.1 -faults oom-t* -body { @@ -188,6 +190,20 @@ do_faultsim_test 6.2 -faults oom-t* -body { faultsim_test_result {0 2} {1 SQLITE_NOMEM} } +proc previc {cmd} { + set res [$cmd xGetAuxdataInt 0] + $cmd xSetAuxdataInt [$cmd xInstCount] + return $res +} +sqlite3_fts5_create_function db previc previc + +do_faultsim_test 6.2 -faults oom-t* -body { + db eval { SELECT previc(x3) FROM x3 WHERE x3 MATCH 'a' } +} -test { + faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM} +} + + diff --git a/manifest b/manifest index 199e150b25..5f785b7ee6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sfts5\stests. -D 2015-04-29T20:54:08.849 +C Improve\stest\scoverage\sof\sfts5.c. +D 2015-05-01T12:14:23.640 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -104,7 +104,7 @@ 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 932284a253cc9bb32caf047879669720680be2c3 +F ext/fts5/fts5.c 3a0a73bcfbcb7e65ccda099cfb8fd268d2480c7e F ext/fts5/fts5.h 24a2cc35b5e76eec57b37ba48c12d9d2cb522b3a F ext/fts5/fts5Int.h 2e0a1a6b77e1e014b7e9b1479ca686ff79930457 F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971 @@ -114,7 +114,7 @@ F ext/fts5/fts5_expr.c 663c75dfdb1bfd8809d696357d7b55f507815098 F ext/fts5/fts5_hash.c 29d8b0668727863cc1f1efa65efe4dd78635b016 F ext/fts5/fts5_index.c de588982b0237b1605d6c37afd115b34c95c3da1 F ext/fts5/fts5_storage.c ef60fc9dcc4e274f9589165e26833173c273ae18 -F ext/fts5/fts5_tcl.c 19ab8cfa642950648968dcf25075d6d969900524 +F ext/fts5/fts5_tcl.c aa3b102bb01f366174718be7ce8e9311b9abb482 F ext/fts5/fts5_tokenize.c 830eae0d35a5a5a90af34df65da3427f46d942fc F ext/fts5/fts5_unicode2.c f74f53316377068812a1fa5a37819e6b8124631d F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9 @@ -132,7 +132,7 @@ F ext/fts5/test/fts5ai.test f20e53bbf0c55bc596f1fd47f2740dae028b8f37 F ext/fts5/test/fts5aj.test 05b569f5c16ea3098fb1984eec5cf50dbdaae5d8 F ext/fts5/test/fts5ak.test 7b8c5df96df599293f920b7e5521ebc79f647592 F ext/fts5/test/fts5al.test e6bddd2c11c0d1e3ae189ee51081899d2f4ea570 -F ext/fts5/test/fts5aux.test 1e475d928a3d1decf74167394db20330d7beeb0f +F ext/fts5/test/fts5aux.test d9c724351d8e4dc46cad1308c0b4b8ac94d07660 F ext/fts5/test/fts5auxdata.test c69b86092bf1a157172de5f9169731af3403179b F ext/fts5/test/fts5bigpl.test b1cfd00561350ab04994ba7dd9d48468e5e0ec3b F ext/fts5/test/fts5content.test 532e15b541254410adc7bfb51f94631cfe82de8f @@ -145,7 +145,7 @@ 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 aea710bbf5680ed41afb9d3313c297d429f9feac +F ext/fts5/test/fts5fault4.test 087066bae36f41227eb85968a2436c8a9c960501 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 07f70955392697556ca2951c9b6c3a5204cd5ec0 -R 07c0e8a626b67779b0890a98070e21c4 +P c1f07a3aa98eac87e2747527d15e5e5562221ceb +R 67c24377157269f998af5007c163ea4c U dan -Z 5236003ea42b936c8f2a3578dc6f6593 +Z 082bd0388383a4ef8c727daa5b60df05 diff --git a/manifest.uuid b/manifest.uuid index 615ae11606..0a40e5a487 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c1f07a3aa98eac87e2747527d15e5e5562221ceb \ No newline at end of file +add4f4681c648dcbecaa68d08f7b2f4e6d63003c \ No newline at end of file