return rc;
}
+/*
+** Implementation of the xSetAuxdata() method.
+*/
static int fts5ApiSetAuxdata(
Fts5Context *pCtx, /* Fts5 context */
void *pPtr, /* Pointer to save as auxdata */
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;
}
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;
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]);
}
/* 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; i<sizeof(aErr)/sizeof(aErr[0]); i++){
+ if( 0==sqlite3_stricmp(zRes, aErr[i].zError) ){
+ return aErr[i].rc;
+ }
+ }
+
+ return SQLITE_ERROR;
+}
+
static int f5tDbAndApi(
Tcl_Interp *interp,
Tcl_Obj *pObj,
Tcl_DecrRefCount(pEval);
Tcl_DeleteCommand(p->interp, zCmd);
+ if( rc==TCL_OK ){
+ rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp));
+ }
+
return rc;
}
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}
};
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;
} {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
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 {
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}
+}
+
+
-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
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
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
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
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
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
-c1f07a3aa98eac87e2747527d15e5e5562221ceb
\ No newline at end of file
+add4f4681c648dcbecaa68d08f7b2f4e6d63003c
\ No newline at end of file