}
}
-static int fts5TestCallback(
- void *pContext, /* Pointer to Fts5Buffer object */
- const char *pToken, /* Buffer containing token */
- int nToken, /* Size of token in bytes */
- int iStart, /* Start offset of token */
- int iEnd, /* End offset of token */
- int iPos /* Position offset of token */
-){
- int rc = SQLITE_OK;
- Fts5Buffer *pBuf = (Fts5Buffer*)pContext;
- if( pBuf->n!=0 ){
- sqlite3Fts5BufferAppendString(&rc, pBuf, " ");
- }
- sqlite3Fts5BufferAppendListElem(&rc, pBuf, pToken, nToken);
- return rc;
-}
-
-
-static void fts5TestFunction(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- sqlite3_context *pCtx, /* Context for returning result/error */
- int nVal, /* Number of values in apVal[] array */
- sqlite3_value **apVal /* Array of trailing arguments */
-){
- Fts5Buffer s; /* Build up text to return here */
- int nCol; /* Number of columns in table */
- int nPhrase; /* Number of phrases in query */
- i64 iRowid; /* Rowid of current row */
- const char *zReq = 0;
- int rc = SQLITE_OK;
- int i;
-
- if( nVal>=1 ){
- zReq = (const char*)sqlite3_value_text(apVal[0]);
- }
-
- memset(&s, 0, sizeof(Fts5Buffer));
- nCol = pApi->xColumnCount(pFts);
-
- /*
- ** xColumnTotalSize()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "columntotalsize ");
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "columntotalsize") ){
- if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{");
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- i64 colsz = 0;
- rc = pApi->xColumnTotalSize(pFts, i, &colsz);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%s%d", i==0?"":" ", colsz);
- }
- if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "}");
- }
-
- /*
- ** xColumnCount()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " columncount ");
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "columncount") ){
- nCol = pApi->xColumnCount(pFts);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%d", nCol);
- }
-
- /*
- ** xColumnSize()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " columnsize ");
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "columnsize") ){
- if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{");
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- int colsz = 0;
- rc = pApi->xColumnSize(pFts, i, &colsz);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%s%d", i==0?"":" ", colsz);
- }
- if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "}");
- }
-
- /*
- ** xColumnText()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " columntext ");
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "columntext") ){
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- const char *z;
- int n;
- rc = pApi->xColumnText(pFts, i, &z, &n);
- if( i!=0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " ");
- sqlite3Fts5BufferAppendListElem(&rc, &s, z, n);
- }
- }
-
- /*
- ** xInst()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " inst ");
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "inst") ){
- int nInst;
- rc = pApi->xInstCount(pFts, &nInst);
- for(i=0; rc==SQLITE_OK && i<nInst; i++){
- int iPhrase, iCol, iOff;
- rc = pApi->xInst(pFts, i, &iPhrase, &iCol, &iOff);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%s%d.%d.%d",
- (i==0 ? "" : " "), iPhrase, iCol, iOff
- );
- }
- }
-
- /*
- ** xPhraseCount()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " phrasecount ");
- nPhrase = pApi->xPhraseCount(pFts);
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "phrasecount") ){
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%d", nPhrase);
- }
-
- /*
- ** xPhraseSize()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " phrasesize ");
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "phrasesize") ){
- if( nPhrase==1 ){
- int nSize = pApi->xPhraseSize(pFts, 0);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%d", nSize);
- }else{
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "{");
- for(i=0; i<nPhrase; i++){
- int nSize = pApi->xPhraseSize(pFts, i);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%s%d", (i==0?"":" "), nSize);
- }
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "}");
- }
- }
-
- /*
- ** xPoslist()
- */
- if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " poslist ");
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "poslist") ){
- int bParen = 0;
- Fts5Buffer s3;
- memset(&s3, 0, sizeof(s3));
-
- for(i=0; i<nPhrase; i++){
- Fts5Buffer s2; /* List of positions for phrase/column */
- int j = 0;
- i64 iPos = 0;
- int nElem = 0;
-
- memset(&s2, 0, sizeof(s2));
- while( 0==pApi->xPoslist(pFts, i, &j, &iPos) ){
- int iOff = FTS5_POS2OFFSET(iPos);
- int iCol = FTS5_POS2COLUMN(iPos);
- if( nElem!=0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s2, " ");
- sqlite3Fts5BufferAppendPrintf(&rc, &s2, "%d.%d", iCol, iOff);
- nElem++;
- }
-
- if( i!=0 ){
- sqlite3Fts5BufferAppendPrintf(&rc, &s3, " ");
- }
- if( nElem==1 ){
- sqlite3Fts5BufferAppendPrintf(&rc, &s3, "%s", (const char*)s2.p);
- }else{
- sqlite3Fts5BufferAppendPrintf(&rc, &s3, "{%s}", (const char*)s2.p);
- bParen = 1;
- }
- sqlite3_free(s2.p);
- }
-
- if(zReq==0 && (nPhrase>1 || bParen) ){
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "{%s}", (const char*)s3.p);
- }else{
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%s", (const char*)s3.p);
- }
- sqlite3_free(s3.p);
- }
-
- if( zReq==0 ){
- sqlite3Fts5BufferAppendPrintf(&rc, &s, " queryphrase ");
- }
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "queryphrase") ){
- int ic, ip;
- int *anVal = 0;
- Fts5Buffer buf1;
- memset(&buf1, 0, sizeof(Fts5Buffer));
-
- if( rc==SQLITE_OK ){
- anVal = (int*)pApi->xGetAuxdata(pFts, 0);
- if( anVal==0 ){
- rc = fts5GatherTotals(pApi, pFts, &anVal);
- if( rc==SQLITE_OK ){
- rc = pApi->xSetAuxdata(pFts, (void*)anVal, sqlite3_free);
- }
- }
- }
-
- for(ip=0; rc==SQLITE_OK && ip<nPhrase; ip++){
- if( ip>0 ) sqlite3Fts5BufferAppendString(&rc, &buf1, " ");
- if( nCol>1 ) sqlite3Fts5BufferAppendString(&rc, &buf1, "{");
- for(ic=0; ic<nCol; ic++){
- int iVal = anVal[ip * nCol + ic];
- sqlite3Fts5BufferAppendPrintf(&rc, &buf1, "%s%d", ic==0?"":" ", iVal);
- }
- if( nCol>1 ) sqlite3Fts5BufferAppendString(&rc, &buf1, "}");
- }
-
- if( zReq==0 ){
- sqlite3Fts5BufferAppendListElem(&rc, &s, (const char*)buf1.p, buf1.n);
- }else{
- sqlite3Fts5BufferAppendString(&rc, &s, (const char*)buf1.p);
- }
- sqlite3_free(buf1.p);
- }
-
- if( zReq==0 ){
- sqlite3Fts5BufferAppendString(&rc, &s, " rowid ");
- }
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "rowid") ){
- iRowid = pApi->xRowid(pFts);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%lld", iRowid);
- }
-
- if( zReq==0 ){
- sqlite3Fts5BufferAppendString(&rc, &s, " rowcount ");
- }
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "rowcount") ){
- i64 nRow;
- rc = pApi->xRowCount(pFts, &nRow);
- sqlite3Fts5BufferAppendPrintf(&rc, &s, "%lld", nRow);
- }
-
- if( zReq==0 ){
- sqlite3Fts5BufferAppendString(&rc, &s, " tokenize ");
- }
- if( 0==zReq || 0==sqlite3_stricmp(zReq, "tokenize") ){
- Fts5Buffer buf;
- memset(&buf, 0, sizeof(buf));
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- const char *z;
- int n;
- rc = pApi->xColumnText(pFts, i, &z, &n);
- if( rc==SQLITE_OK ){
- Fts5Buffer buf1;
- memset(&buf1, 0, sizeof(Fts5Buffer));
- rc = pApi->xTokenize(pFts, z, n, (void*)&buf1, fts5TestCallback);
- if( i!=0 ) sqlite3Fts5BufferAppendPrintf(&rc, &buf, " ");
- sqlite3Fts5BufferAppendListElem(&rc, &buf, (const char*)buf1.p, buf1.n);
- sqlite3_free(buf1.p);
- }
- }
- if( zReq==0 ){
- sqlite3Fts5BufferAppendListElem(&rc, &s, (const char*)buf.p, buf.n);
- }else{
- sqlite3Fts5BufferAppendString(&rc, &s, (const char*)buf.p);
- }
- sqlite3_free(buf.p);
- }
-
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, (const char*)s.p, -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
- sqlite3Fts5BufferFree(&s);
-}
-
int sqlite3Fts5AuxInit(fts5_api *pApi){
struct Builtin {
const char *zFunc; /* Function name (nul-terminated) */
} aBuiltin [] = {
{ "bm25debug", (void*)1, fts5Bm25Function, 0 },
{ "snippet", 0, fts5SnippetFunction, 0 },
- { "fts5_test", 0, fts5TestFunction, 0 },
{ "highlight", 0, fts5HighlightFunction, 0 },
{ "bm25", 0, fts5Bm25Function, 0 },
};
Fts5Context *pFts;
};
+static int xTokenizeCb(
+ void *pCtx,
+ const char *zToken, int nToken,
+ int iStart, int iEnd, int iPos
+){
+ F5tFunction *p = (F5tFunction*)pCtx;
+ Tcl_Obj *pEval = Tcl_DuplicateObj(p->pScript);
+ int rc;
+
+ Tcl_IncrRefCount(pEval);
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zToken, nToken));
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(iStart));
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(iEnd));
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(iPos));
+
+ rc = Tcl_EvalObjEx(p->interp, pEval, 0);
+ Tcl_DecrRefCount(pEval);
+
+ return rc;
+}
+
+static int xF5tApi(void*, Tcl_Interp*, int, Tcl_Obj *CONST []);
+
+static int xQueryPhraseCb(
+ const Fts5ExtensionApi *pApi,
+ Fts5Context *pFts,
+ void *pCtx
+){
+ F5tFunction *p = (F5tFunction*)pCtx;
+ static sqlite3_int64 iCmd = 0;
+ Tcl_Obj *pEval;
+ int rc;
+
+ char zCmd[64];
+ F5tApi sApi;
+
+ sApi.pApi = pApi;
+ sApi.pFts = pFts;
+ sprintf(zCmd, "f5t_2_%lld", iCmd++);
+ Tcl_CreateObjCommand(p->interp, zCmd, xF5tApi, &sApi, 0);
+
+ pEval = Tcl_DuplicateObj(p->pScript);
+ Tcl_IncrRefCount(pEval);
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zCmd, -1));
+ rc = Tcl_EvalObjEx(p->interp, pEval, 0);
+ Tcl_DecrRefCount(pEval);
+ Tcl_DeleteCommand(p->interp, zCmd);
+
+ return rc;
+}
+
/*
** api sub-command...
**
int nArg;
const char *zMsg;
} aSub[] = {
- { "xRowid", 0, "" },
- { "xInstCount", 0, "" },
- { "xInst", 1, "IDX" },
- { "xColumnText", 1, "COL" },
- { "xColumnSize", 1, "COL" },
+ { "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" },
+ { 0, 0, 0}
};
+
int rc;
int iSub = 0;
F5tApi *p = (F5tApi*)clientData;
return TCL_ERROR;
}
+#define CASE(i,str) case i: assert( strcmp(aSub[i].zName, str)==0 );
switch( iSub ){
- case 0: { /* xRowid */
- sqlite3_int64 iRowid = p->pApi->xRowid(p->pFts);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iRowid));
+ CASE(0, "xColumnCount") {
+ int nCol;
+ nCol = p->pApi->xColumnCount(p->pFts);
+ if( rc==SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol));
+ }
break;
}
-
- case 1: { /* xInstCount */
+ CASE(1, "xRowCount") {
+ sqlite3_int64 nRow;
+ rc = p->pApi->xRowCount(p->pFts, &nRow);
+ if( rc==SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nRow));
+ }
+ break;
+ }
+ CASE(2, "xColumnTotalSize") {
+ int iCol;
+ sqlite3_int64 nSize;
+ if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ) return TCL_ERROR;
+ rc = p->pApi->xColumnTotalSize(p->pFts, iCol, &nSize);
+ if( rc==SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize));
+ }
+ break;
+ }
+ CASE(3, "xTokenize") {
+ int nText;
+ char *zText = Tcl_GetStringFromObj(objv[2], &nText);
+ F5tFunction ctx;
+ ctx.interp = interp;
+ ctx.pScript = objv[3];
+ rc = p->pApi->xTokenize(p->pFts, zText, nText, &ctx, xTokenizeCb);
+ if( rc==SQLITE_OK ){
+ Tcl_ResetResult(interp);
+ }
+ return rc;
+ }
+ CASE(4, "xPhraseCount") {
+ int nPhrase;
+ nPhrase = p->pApi->xPhraseCount(p->pFts);
+ if( rc==SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(nPhrase));
+ }
+ break;
+ }
+ CASE(5, "xPhraseSize") {
+ int iPhrase;
+ int sz;
+ if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ){
+ return TCL_ERROR;
+ }
+ sz = p->pApi->xPhraseSize(p->pFts, iPhrase);
+ if( rc==SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(sz));
+ }
+ break;
+ }
+ CASE(6, "xInstCount") {
int nInst;
rc = p->pApi->xInstCount(p->pFts, &nInst);
if( rc==SQLITE_OK ){
}
break;
}
-
- case 2: { /* xInst */
+ CASE(7, "xInst") {
int iIdx, ip, ic, io;
if( Tcl_GetIntFromObj(interp, objv[2], &iIdx) ){
return TCL_ERROR;
}
break;
}
-
- case 3: { /* xColumnText */
+ CASE(8, "xRowid") {
+ sqlite3_int64 iRowid = p->pApi->xRowid(p->pFts);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iRowid));
+ break;
+ }
+ CASE(9, "xColumnText") {
const char *z = 0;
int n = 0;
int iCol;
}
break;
}
-
- case 4: { /* xColumnSize */
+ CASE(10, "xColumnSize") {
int n = 0;
int iCol;
if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ){
}
break;
}
+ CASE(11, "xQueryPhrase") {
+ int iPhrase;
+ F5tFunction ctx;
+ if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ){
+ return TCL_ERROR;
+ }
+ ctx.interp = interp;
+ ctx.pScript = objv[3];
+ rc = p->pApi->xQueryPhrase(p->pFts, iPhrase, &ctx, xQueryPhraseCb);
+ if( rc==SQLITE_OK ){
+ Tcl_ResetResult(interp);
+ }
+ break;
+ }
default:
assert( 0 );
break;
}
+#undef CASE
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error in api call", 0);
-C Fix\sa\sproblem\swith\sprefix\squeries\sand\sthe\sAND\soperator.
-D 2014-12-18T20:01:15.691
+C Remove\sthe\sfts5_test()\saux\sfunction.\sTest\saux\sfunctions\susing\sthe\stcl\sinterface\sinstead.
+D 2014-12-19T20:53:51.092
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/fts5/fts5.c d1c1722eb661da3e8e3a19909958b97beff7d243
F ext/fts5/fts5.h 72fc1e9995b1ddc254a487b9528614a83bd3dfb6
F ext/fts5/fts5Int.h 36054b1dfc4881a9b94f945b348ab6cc01c0c7a5
-F ext/fts5/fts5_aux.c 0e3e5fea6bf5772805afe14c95cb5f16e03e4b3f
+F ext/fts5/fts5_aux.c b8e5660a05b86dab059c9989835b5df0ac5e3c55
F ext/fts5/fts5_buffer.c 1bc5c762bb2e9b4a40b2e8a820a31b809e72eec1
F ext/fts5/fts5_config.c 5caeb4e77680d635be25b899f97a29cf26fb45ce
F ext/fts5/fts5_expr.c 27d3d2deebae277c34ae2bb3d501dd879c442ba5
F ext/fts5/fts5_hash.c 63fa8379c5f2ac107d47c2b7d9ac04c95ef8a279
F ext/fts5/fts5_index.c 4a8e8535b4303400ddb5f6fb08152da0d88ebf6f
F ext/fts5/fts5_storage.c bfeedb83b095a1018f4f531c3cc3f9099e9f9081
-F ext/fts5/fts5_tcl.c 5272224faf9be129679da5e19d788f0307afc375
+F ext/fts5/fts5_tcl.c d56484fd5cc3b02d268ee11fa4918e98ce3b1d03
F ext/fts5/fts5_tokenize.c 8360c0d1ae0d4696f3cc13f7c67a2db6011cdc5b
F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
+F test/fts5_common.tcl 2488117cd80b7a4de7c20054b89f082b77b4189c
F test/fts5aa.test 27c7d3c865e144a0501dcbfbd6d2ae87f77602ea
F test/fts5ab.test 52f6b9223372ff70b0edb5a3054fbd7bc7fcfefc
-F test/fts5ac.test 60302196b7711176ce872fe2e4c73c75ac2c4038
+F test/fts5ac.test 021e175b809d2baa23792807caae5dfc6bc706f4
F test/fts5ad.test ff518db6b0d7750b51ee6531ffebf82e57094bfd
-F test/fts5ae.test 5de775469d45a2f8218fc89b8d6d5176c226d05e
+F test/fts5ae.test 0877873a2b9df6b3a2d832ed5ea928f838d19faf
F test/fts5af.test d24e3b0f879998ef5f60087272f8ab7b3a8fd4dc
-F test/fts5ag.test 1c6c188d1bdc41b2277db3f4ddfea7d90bf44ceb
+F test/fts5ag.test 8b2bb67cf2a3245eaad5e49ab8daa6be6e64332b
F test/fts5ah.test 788e923e60b5e7a559f672cfbf262b8b260ea176
F test/fts5ai.test aa2b5fd0f8d2cf59ac0211111e63cbca3b40ed7d
F test/fts5aj.test bc3d91bd012c7ca175cdf266c2074920bb5fa5ba
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
-F test/tester.tcl f31bea1483ea1d39620f982130026e76f872d744
+F test/tester.tcl 7d2c97b43e51abde7a35f9d3bc57e886c8503e55
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P e358c3de5c916f2c851ab9324ceaae4e4e7a0fbd
-R d93acda5ed1642f2b9a85bcc5fb79da9
+P 38b3c65e3ee95eb7afadb76e0110570fbbc41e1b
+R a4b205e397ac161e65b87e55d29e5aba
U dan
-Z ee6f25fbcb6953dd4dd423bed7e3ab13
+Z b9d8ce93a014115b155c701f123b4810
-38b3c65e3ee95eb7afadb76e0110570fbbc41e1b
\ No newline at end of file
+67e3ffd950c5347d219a06b33ad51949cffa7d90
\ No newline at end of file
--- /dev/null
+# 2014 Dec 19
+#
+# 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.
+#
+#***********************************************************************
+#
+
+
+
+
+proc fts5_test_poslist {cmd} {
+ set res [list]
+ for {set i 0} {$i < [$cmd xInstCount]} {incr i} {
+ lappend res [string map {{ } .} [$cmd xInst $i]]
+ }
+ set res
+}
+
+proc fts5_test_columnsize {cmd} {
+ set res [list]
+ for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
+ lappend res [$cmd xColumnSize $i]
+ }
+ set res
+}
+
+proc fts5_test_columntext {cmd} {
+ set res [list]
+ for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
+ lappend res [$cmd xColumnText $i]
+ }
+ set res
+}
+
+proc fts5_test_columntotalsize {cmd} {
+ set res [list]
+ for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
+ lappend res [$cmd xColumnTotalSize $i]
+ }
+ set res
+}
+
+proc test_append_token {varname token iStart iEnd iPos} {
+ upvar $varname var
+ lappend var $token
+}
+proc fts5_test_tokenize {cmd} {
+ set res [list]
+ for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
+ set tokens [list]
+ $cmd xTokenize [$cmd xColumnText $i] [list test_append_token tokens]
+ lappend res $tokens
+ }
+ set res
+}
+
+proc fts5_test_rowcount {cmd} {
+ $cmd xRowCount
+}
+
+proc test_queryphrase_cb {cnt cmd} {
+ upvar $cnt L
+ for {set i 0} {$i < [$cmd xInstCount]} {incr i} {
+ foreach {ip ic io} [$cmd xInst $i] break
+ set A($ic) 1
+ }
+ foreach ic [array names A] {
+ lset L $ic [expr {[lindex $L $ic] + 1}]
+ }
+}
+proc fts5_test_queryphrase {cmd} {
+ set res [list]
+ for {set i 0} {$i < [$cmd xPhraseCount]} {incr i} {
+ set cnt [list]
+ for {set j 0} {$j < [$cmd xColumnCount]} {incr j} { lappend cnt 0 }
+ $cmd xQueryPhrase $i [list test_queryphrase_cb cnt]
+ lappend res $cnt
+ }
+ set res
+}
+
+proc fts5_test_all {cmd} {
+ set res [list]
+ lappend res columnsize [fts5_test_columnsize $cmd]
+ lappend res columntext [fts5_test_columntext $cmd]
+ lappend res columntotalsize [fts5_test_columntotalsize $cmd]
+ lappend res poslist [fts5_test_poslist $cmd]
+ lappend res tokenize [fts5_test_tokenize $cmd]
+ lappend res rowcount [fts5_test_rowcount $cmd]
+ set res
+}
+
+proc fts5_aux_test_functions {db} {
+ foreach f {
+ fts5_test_columnsize
+ fts5_test_columntext
+ fts5_test_columntotalsize
+ fts5_test_poslist
+ fts5_test_tokenize
+ fts5_test_rowcount
+ fts5_test_all
+
+ fts5_test_queryphrase
+ } {
+ sqlite3_fts5_create_function $db $f $f
+ }
+}
+
+
# Usage:
#
-# poslist aCol ?-near N? ?-col C? -- phrase1 phrase2...
+# poslist aCol ?-pc VARNAME? ?-near N? ?-col C? -- phrase1 phrase2...
#
proc poslist {aCol args} {
set O(-near) 10
set O(-col) -1
+ set O(-pc) ""
set nOpt [lsearch -exact $args --]
if {$nOpt<0} { error "no -- option" }
set O($k) $v
}
+ if {$O(-pc) == ""} {
+ set counter 0
+ } else {
+ upvar $O(-pc) counter
+ }
+
# Set $phraselist to be a list of phrases. $nPhrase its length.
set phraselist [lrange $args [expr $nOpt+1] end]
set nPhrase [llength $phraselist]
}
set res [list]
+#puts [array names A]
+
for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} {
- set plist [list]
for {set iCol 0} {$iCol < [llength $aCol]} {incr iCol} {
foreach a $A($iCol,$iPhrase) {
- lappend plist "$iCol.$a"
+ lappend res "$counter.$iCol.$a"
}
}
- lappend res $plist
+ incr counter
}
#puts $res
return [expr [llength [lindex $plist 0]]>0]
}
+proc instcompare {lhs rhs} {
+ foreach {p1 c1 o1} [split $lhs .] {}
+ foreach {p2 c2 o2} [split $rhs .] {}
+
+ set res [expr $c1 - $c2]
+ if {$res==0} { set res [expr $o1 - $o2] }
+ if {$res==0} { set res [expr $p1 - $p2] }
+
+ return $res
+}
+
# Argument $expr is an FTS5 match expression designed to be executed against
# an FTS5 table with the following schema:
#
if {$bPos} {
set N [regexp -all -inline {\[nearset [^\]]*\]} $tclexpr]
set rowres [list]
+ set cnt 0
foreach phrase $N {
- set cmd "poslist [string range $phrase 9 end-1]"
+ set arglist [string range $phrase 9 end-1]
+ set cmd "poslist [lindex $arglist 0] -pc cnt [lrange $arglist 1 end]"
set pos [eval $cmd]
set rowres [concat $rowres $pos]
}
+ set rowres [lsort -command instcompare $rowres]
lappend res [list $id $rowres]
} else {
lappend res $id
# End of test code
#-------------------------------------------------------------------------
+proc fts5_test_poslist {cmd} {
+ set res [list]
+ for {set i 0} {$i < [$cmd xInstCount]} {incr i} {
+ lappend res [string map {{ } .} [$cmd xInst $i]]
+ }
+ set res
+}
+
+sqlite3_fts5_create_function db fts5_test_poslist fts5_test_poslist
+
#-------------------------------------------------------------------------
# Test phrase queries.
#
set res [matchdata 1 $expr]
do_execsql_test 1.2.$tn.[llength $res] {
- SELECT rowid, fts5_test(xx, 'poslist') FROM xx WHERE xx match $expr
+ SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr
} $res
}
} {
set res [matchdata 1 $expr]
do_execsql_test 2.$tn.[llength $res] {
- SELECT rowid, fts5_test(xx, 'poslist') FROM xx WHERE xx match $expr
+ SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr
} $res
}
} {
set res [matchdata 1 $expr]
do_execsql_test 3.$tn.[llength $res] {
- SELECT rowid, fts5_test(xx, 'poslist') FROM xx WHERE xx match $expr
+ SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr
} $res
}
} {
set res [matchdata 1 $expr]
do_execsql_test 4.1.$tn.[llength $res] {
- SELECT rowid, fts5_test(xx, 'poslist') FROM xx WHERE xx match $expr
+ SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr
} $res
}
-do_test 4.1 { poslist {{a b c}} -- a } {0.0}
-do_test 4.2 { poslist {{a b c}} -- c } {0.2}
+do_test 4.1 { poslist {{a b c}} -- a } {0.0.0}
+do_test 4.2 { poslist {{a b c}} -- c } {0.0.2}
foreach {tn expr tclexpr} {
1 {a b} {[N $x -- {a}] && [N $x -- {b}]}
SELECT rowid FROM t1 WHERE t1 MATCH 'hello' ORDER BY rowid ASC;
} {1 2 4}
+fts5_aux_test_functions db
#-------------------------------------------------------------------------
#
}
do_execsql_test 2.1 {
- SELECT rowid, fts5_test(t2, 'poslist') FROM t2
+ SELECT rowid, fts5_test_poslist(t2) FROM t2
WHERE t2 MATCH 'm' ORDER BY rowid;
} {
- 1 {{0.5 1.0 1.2}}
- 2 {{0.7 1.5}}
+ 1 {0.0.5 0.1.0 0.1.2}
+ 2 {0.0.7 0.1.5}
}
do_execsql_test 2.2 {
- SELECT rowid, fts5_test(t2, 'poslist') FROM t2
+ SELECT rowid, fts5_test_poslist(t2) FROM t2
WHERE t2 MATCH 'u OR q' ORDER BY rowid;
} {
- 1 {0.0 {}}
- 2 {{} {0.2 0.10}}
+ 1 {0.0.0}
+ 2 {1.0.2 1.0.10}
}
do_execsql_test 2.3 {
- SELECT rowid, fts5_test(t2, 'poslist') FROM t2
+ SELECT rowid, fts5_test_poslist(t2) FROM t2
WHERE t2 MATCH 'y:o' ORDER BY rowid;
} {
- 1 {{1.3 1.7}}
+ 1 {0.1.3 0.1.7}
}
#-------------------------------------------------------------------------
}
do_execsql_test 3.1 {
- SELECT rowid, fts5_test(t3, 'poslist') FROM t3 WHERE t3 MATCH 'NEAR(a b)';
+ SELECT rowid, fts5_test_poslist(t3) FROM t3 WHERE t3 MATCH 'NEAR(a b)';
} {
- 1 {{0.6 0.10 0.12} {0.9 0.15}}
+ 1 {0.0.6 1.0.9 0.0.10 0.0.12 1.0.15}
}
do_execsql_test 3.2 {
- SELECT rowid, fts5_test(t3, 'poslist') FROM t3 WHERE t3 MATCH 'NEAR(r c)';
+ SELECT rowid, fts5_test_poslist(t3) FROM t3 WHERE t3 MATCH 'NEAR(r c)';
} {
- 2 {0.0 0.1}
+ 2 {0.0.0 1.0.1}
}
do_execsql_test 3.3 {
INSERT INTO t3
VALUES('k x j r m a d o i z j', 'r t t t f e b r x i v j v g o');
- SELECT rowid, fts5_test(t3, 'poslist')
+ SELECT rowid, fts5_test_poslist(t3)
FROM t3 WHERE t3 MATCH 'a OR b AND c';
} {
- 3 {0.5 {} {}}
- 1 {{0.6 0.10 0.12} {0.9 0.15} 1.2}
+ 3 0.0.5
+ 1 {0.0.6 1.0.9 0.0.10 0.0.12 1.0.15 2.1.2}
}
#-------------------------------------------------------------------------
}
do_execsql_test 4.1 {
- SELECT rowid, fts5_test(t4, 'poslist') FROM t4 WHERE t4 MATCH 'a OR b AND c';
+ SELECT rowid, fts5_test_poslist(t4) FROM t4 WHERE t4 MATCH 'a OR b AND c';
} {
- 1 {0.5 {} {}}
+ 1 0.0.5
}
#-------------------------------------------------------------------------
# Test that the xColumnSize() and xColumnAvgsize() APIs work.
#
-
reset_db
+fts5_aux_test_functions db
+
do_execsql_test 5.1 {
CREATE VIRTUAL TABLE t5 USING fts5(x, y);
INSERT INTO t5 VALUES('a b c d', 'e f g h i j');
INSERT INTO t5 VALUES('a', '');
}
do_execsql_test 5.2 {
- SELECT rowid, fts5_test(t5, 'columnsize') FROM t5 WHERE t5 MATCH 'a'
+ SELECT rowid, fts5_test_columnsize(t5) FROM t5 WHERE t5 MATCH 'a'
ORDER BY rowid DESC;
} {
3 {1 0}
}
do_execsql_test 5.2 {
- SELECT rowid, fts5_test(t5, 'columntext') FROM t5 WHERE t5 MATCH 'a'
+ SELECT rowid, fts5_test_columntext(t5) FROM t5 WHERE t5 MATCH 'a'
ORDER BY rowid DESC;
} {
3 {a {}}
}
do_execsql_test 5.3 {
- SELECT rowid, fts5_test(t5, 'columntotalsize') FROM t5 WHERE t5 MATCH 'a'
+ SELECT rowid, fts5_test_columntotalsize(t5) FROM t5 WHERE t5 MATCH 'a'
ORDER BY rowid DESC;
} {
3 {5 7}
do_execsql_test 5.4 {
INSERT INTO t5 VALUES('x y z', 'v w x y z');
- SELECT rowid, fts5_test(t5, 'columntotalsize') FROM t5 WHERE t5 MATCH 'a'
+ SELECT rowid, fts5_test_columntotalsize(t5) FROM t5 WHERE t5 MATCH 'a'
ORDER BY rowid DESC;
} {
3 {8 12}
# Test the xTokenize() API
#
reset_db
+fts5_aux_test_functions db
do_execsql_test 6.1 {
CREATE VIRTUAL TABLE t6 USING fts5(x, y);
INSERT INTO t6 VALUES('There are more', 'things in heaven and earth');
}
do_execsql_test 6.2 {
- SELECT rowid, fts5_test(t6, 'tokenize') FROM t6 WHERE t6 MATCH 't*'
+ SELECT rowid, fts5_test_tokenize(t6) FROM t6 WHERE t6 MATCH 't*'
} {
2 {{horatio than are} {dreamt of in your philosophy}}
1 {{there are more} {things in heaven and earth}}
# Test the xQueryPhrase() API
#
reset_db
+fts5_aux_test_functions db
do_execsql_test 7.1 {
CREATE VIRTUAL TABLE t7 USING fts5(x, y);
}
6 {a OR b OR c OR d} {{4 2} {3 4} {2 1} {2 2}}
} {
do_execsql_test 7.3.$tn {
- SELECT fts5_test(t7, 'queryphrase') FROM t7 WHERE t7 MATCH $q LIMIT 1
+ SELECT fts5_test_queryphrase(t7) FROM t7 WHERE t7 MATCH $q LIMIT 1
} [list $res]
}
do_execsql_test 7.4 {
- SELECT fts5_test(t7, 'rowcount') FROM t7 WHERE t7 MATCH 'a';
+ SELECT fts5_test_rowcount(t7) FROM t7 WHERE t7 MATCH 'a';
} {5 5 5 5}
#do_execsql_test 7.4 {
set {} {}
} {}
+fts5_aux_test_functions db
+
proc do_fts5ag_test {tn E} {
- set q1 {SELECT fts5_test(t1) FROM t1 WHERE t1 MATCH $E ORDER BY rank}
- set q2 {SELECT fts5_test(t1) FROM t1 WHERE t1 MATCH $E ORDER BY bm25(t1)}
+ set q1 {SELECT fts5_test_all(t1) FROM t1 WHERE t1 MATCH $E ORDER BY rank}
+ set q2 {SELECT fts5_test_all(t1) FROM t1 WHERE t1 MATCH $E ORDER BY bm25(t1)}
set res [execsql $q1]
set expected [execsql $q2]
source $testdir/thread_common.tcl
source $testdir/malloc_common.tcl
+source $testdir/fts5_common.tcl