| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2014 Dec 01 | 2 ** 2014 Dec 01 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| 11 ****************************************************************************** | 11 ****************************************************************************** |
| 12 ** | 12 ** |
| 13 */ | 13 */ |
| 14 | 14 |
| 15 | 15 |
| 16 #ifdef SQLITE_TEST | 16 #ifdef SQLITE_TEST |
| 17 #include <tcl.h> | 17 #if defined(INCLUDE_SQLITE_TCL_H) |
| 18 # include "sqlite_tcl.h" |
| 19 #else |
| 20 # include "tcl.h" |
| 21 # ifndef SQLITE_TCLAPI |
| 22 # define SQLITE_TCLAPI |
| 23 # endif |
| 24 #endif |
| 18 | 25 |
| 19 #ifdef SQLITE_ENABLE_FTS5 | 26 #ifdef SQLITE_ENABLE_FTS5 |
| 20 | 27 |
| 21 #include "fts5.h" | 28 #include "fts5.h" |
| 22 #include <string.h> | 29 #include <string.h> |
| 23 #include <assert.h> | 30 #include <assert.h> |
| 24 | 31 |
| 25 extern int sqlite3_fts5_may_be_corrupt; | 32 extern int sqlite3_fts5_may_be_corrupt; |
| 26 extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *); | 33 extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*); |
| 34 extern int sqlite3Fts5TestRegisterTok(sqlite3*, fts5_api*); |
| 27 | 35 |
| 28 /************************************************************************* | 36 /************************************************************************* |
| 29 ** This is a copy of the first part of the SqliteDb structure in | 37 ** This is a copy of the first part of the SqliteDb structure in |
| 30 ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine | 38 ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine |
| 31 ** can extract the sqlite3* pointer from an existing Tcl SQLite | 39 ** can extract the sqlite3* pointer from an existing Tcl SQLite |
| 32 ** connection. | 40 ** connection. |
| 33 */ | 41 */ |
| 34 | 42 |
| 35 extern const char *sqlite3ErrName(int); | 43 extern const char *sqlite3ErrName(int); |
| 36 | 44 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 78 |
| 71 for(i=0; i<sizeof(aErr)/sizeof(aErr[0]); i++){ | 79 for(i=0; i<sizeof(aErr)/sizeof(aErr[0]); i++){ |
| 72 if( 0==sqlite3_stricmp(zRes, aErr[i].zError) ){ | 80 if( 0==sqlite3_stricmp(zRes, aErr[i].zError) ){ |
| 73 return aErr[i].rc; | 81 return aErr[i].rc; |
| 74 } | 82 } |
| 75 } | 83 } |
| 76 | 84 |
| 77 return SQLITE_ERROR; | 85 return SQLITE_ERROR; |
| 78 } | 86 } |
| 79 | 87 |
| 80 static int f5tDbAndApi( | 88 static int SQLITE_TCLAPI f5tDbAndApi( |
| 81 Tcl_Interp *interp, | 89 Tcl_Interp *interp, |
| 82 Tcl_Obj *pObj, | 90 Tcl_Obj *pObj, |
| 83 sqlite3 **ppDb, | 91 sqlite3 **ppDb, |
| 84 fts5_api **ppApi | 92 fts5_api **ppApi |
| 85 ){ | 93 ){ |
| 86 sqlite3 *db = 0; | 94 sqlite3 *db = 0; |
| 87 int rc = f5tDbPointer(interp, pObj, &db); | 95 int rc = f5tDbPointer(interp, pObj, &db); |
| 88 if( rc!=TCL_OK ){ | 96 if( rc!=TCL_OK ){ |
| 89 return TCL_ERROR; | 97 return TCL_ERROR; |
| 90 }else{ | 98 }else{ |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 164 |
| 157 rc = Tcl_EvalObjEx(p->interp, pEval, 0); | 165 rc = Tcl_EvalObjEx(p->interp, pEval, 0); |
| 158 Tcl_DecrRefCount(pEval); | 166 Tcl_DecrRefCount(pEval); |
| 159 if( rc==TCL_OK ){ | 167 if( rc==TCL_OK ){ |
| 160 rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp)); | 168 rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp)); |
| 161 } | 169 } |
| 162 | 170 |
| 163 return rc; | 171 return rc; |
| 164 } | 172 } |
| 165 | 173 |
| 166 static int xF5tApi(void*, Tcl_Interp*, int, Tcl_Obj *CONST []); | 174 static int SQLITE_TCLAPI xF5tApi(void*, Tcl_Interp*, int, Tcl_Obj *CONST []); |
| 167 | 175 |
| 168 static int xQueryPhraseCb( | 176 static int xQueryPhraseCb( |
| 169 const Fts5ExtensionApi *pApi, | 177 const Fts5ExtensionApi *pApi, |
| 170 Fts5Context *pFts, | 178 Fts5Context *pFts, |
| 171 void *pCtx | 179 void *pCtx |
| 172 ){ | 180 ){ |
| 173 F5tFunction *p = (F5tFunction*)pCtx; | 181 F5tFunction *p = (F5tFunction*)pCtx; |
| 174 static sqlite3_int64 iCmd = 0; | 182 static sqlite3_int64 iCmd = 0; |
| 175 Tcl_Obj *pEval; | 183 Tcl_Obj *pEval; |
| 176 int rc; | 184 int rc; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 201 F5tAuxData *pData = (F5tAuxData*)p; | 209 F5tAuxData *pData = (F5tAuxData*)p; |
| 202 Tcl_DecrRefCount(pData->pObj); | 210 Tcl_DecrRefCount(pData->pObj); |
| 203 sqlite3_free(pData); | 211 sqlite3_free(pData); |
| 204 } | 212 } |
| 205 | 213 |
| 206 /* | 214 /* |
| 207 ** api sub-command... | 215 ** api sub-command... |
| 208 ** | 216 ** |
| 209 ** Description... | 217 ** Description... |
| 210 */ | 218 */ |
| 211 static int xF5tApi( | 219 static int SQLITE_TCLAPI xF5tApi( |
| 212 void * clientData, | 220 void * clientData, |
| 213 Tcl_Interp *interp, | 221 Tcl_Interp *interp, |
| 214 int objc, | 222 int objc, |
| 215 Tcl_Obj *CONST objv[] | 223 Tcl_Obj *CONST objv[] |
| 216 ){ | 224 ){ |
| 217 struct Sub { | 225 struct Sub { |
| 218 const char *zName; | 226 const char *zName; |
| 219 int nArg; | 227 int nArg; |
| 220 const char *zMsg; | 228 const char *zMsg; |
| 221 } aSub[] = { | 229 } aSub[] = { |
| 222 { "xColumnCount", 0, "" }, /* 0 */ | 230 { "xColumnCount", 0, "" }, /* 0 */ |
| 223 { "xRowCount", 0, "" }, /* 1 */ | 231 { "xRowCount", 0, "" }, /* 1 */ |
| 224 { "xColumnTotalSize", 1, "COL" }, /* 2 */ | 232 { "xColumnTotalSize", 1, "COL" }, /* 2 */ |
| 225 { "xTokenize", 2, "TEXT SCRIPT" }, /* 3 */ | 233 { "xTokenize", 2, "TEXT SCRIPT" }, /* 3 */ |
| 226 { "xPhraseCount", 0, "" }, /* 4 */ | 234 { "xPhraseCount", 0, "" }, /* 4 */ |
| 227 { "xPhraseSize", 1, "PHRASE" }, /* 5 */ | 235 { "xPhraseSize", 1, "PHRASE" }, /* 5 */ |
| 228 { "xInstCount", 0, "" }, /* 6 */ | 236 { "xInstCount", 0, "" }, /* 6 */ |
| 229 { "xInst", 1, "IDX" }, /* 7 */ | 237 { "xInst", 1, "IDX" }, /* 7 */ |
| 230 { "xRowid", 0, "" }, /* 8 */ | 238 { "xRowid", 0, "" }, /* 8 */ |
| 231 { "xColumnText", 1, "COL" }, /* 9 */ | 239 { "xColumnText", 1, "COL" }, /* 9 */ |
| 232 { "xColumnSize", 1, "COL" }, /* 10 */ | 240 { "xColumnSize", 1, "COL" }, /* 10 */ |
| 233 { "xQueryPhrase", 2, "PHRASE SCRIPT" }, /* 11 */ | 241 { "xQueryPhrase", 2, "PHRASE SCRIPT" }, /* 11 */ |
| 234 { "xSetAuxdata", 1, "VALUE" }, /* 12 */ | 242 { "xSetAuxdata", 1, "VALUE" }, /* 12 */ |
| 235 { "xGetAuxdata", 1, "CLEAR" }, /* 13 */ | 243 { "xGetAuxdata", 1, "CLEAR" }, /* 13 */ |
| 236 { "xSetAuxdataInt", 1, "INTEGER" }, /* 14 */ | 244 { "xSetAuxdataInt", 1, "INTEGER" }, /* 14 */ |
| 237 { "xGetAuxdataInt", 1, "CLEAR" }, /* 15 */ | 245 { "xGetAuxdataInt", 1, "CLEAR" }, /* 15 */ |
| 246 { "xPhraseForeach", 4, "IPHRASE COLVAR OFFVAR SCRIPT" }, /* 16 */ |
| 247 { "xPhraseColumnForeach", 3, "IPHRASE COLVAR SCRIPT" }, /* 17 */ |
| 238 { 0, 0, 0} | 248 { 0, 0, 0} |
| 239 }; | 249 }; |
| 240 | 250 |
| 241 int rc; | 251 int rc; |
| 242 int iSub = 0; | 252 int iSub = 0; |
| 243 F5tApi *p = (F5tApi*)clientData; | 253 F5tApi *p = (F5tApi*)clientData; |
| 244 | 254 |
| 245 if( objc<2 ){ | 255 if( objc<2 ){ |
| 246 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND"); | 256 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND"); |
| 247 return TCL_ERROR; | 257 return TCL_ERROR; |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 } | 434 } |
| 425 CASE(15, "xGetAuxdataInt") { | 435 CASE(15, "xGetAuxdataInt") { |
| 426 int iVal; | 436 int iVal; |
| 427 int bClear; | 437 int bClear; |
| 428 if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR; | 438 if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR; |
| 429 iVal = ((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0); | 439 iVal = ((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0); |
| 430 Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); | 440 Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); |
| 431 break; | 441 break; |
| 432 } | 442 } |
| 433 | 443 |
| 444 CASE(16, "xPhraseForeach") { |
| 445 int iPhrase; |
| 446 int iCol; |
| 447 int iOff; |
| 448 const char *zColvar; |
| 449 const char *zOffvar; |
| 450 Tcl_Obj *pScript = objv[5]; |
| 451 Fts5PhraseIter iter; |
| 452 |
| 453 if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR; |
| 454 zColvar = Tcl_GetString(objv[3]); |
| 455 zOffvar = Tcl_GetString(objv[4]); |
| 456 |
| 457 rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff); |
| 458 if( rc!=SQLITE_OK ){ |
| 459 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); |
| 460 return TCL_ERROR; |
| 461 } |
| 462 for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){ |
| 463 Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0); |
| 464 Tcl_SetVar2Ex(interp, zOffvar, 0, Tcl_NewIntObj(iOff), 0); |
| 465 rc = Tcl_EvalObjEx(interp, pScript, 0); |
| 466 if( rc==TCL_CONTINUE ) rc = TCL_OK; |
| 467 if( rc!=TCL_OK ){ |
| 468 if( rc==TCL_BREAK ) rc = TCL_OK; |
| 469 break; |
| 470 } |
| 471 } |
| 472 |
| 473 break; |
| 474 } |
| 475 |
| 476 CASE(17, "xPhraseColumnForeach") { |
| 477 int iPhrase; |
| 478 int iCol; |
| 479 const char *zColvar; |
| 480 Tcl_Obj *pScript = objv[4]; |
| 481 Fts5PhraseIter iter; |
| 482 |
| 483 if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR; |
| 484 zColvar = Tcl_GetString(objv[3]); |
| 485 |
| 486 rc = p->pApi->xPhraseFirstColumn(p->pFts, iPhrase, &iter, &iCol); |
| 487 if( rc!=SQLITE_OK ){ |
| 488 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); |
| 489 return TCL_ERROR; |
| 490 } |
| 491 for( ; iCol>=0; p->pApi->xPhraseNextColumn(p->pFts, &iter, &iCol)){ |
| 492 Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0); |
| 493 rc = Tcl_EvalObjEx(interp, pScript, 0); |
| 494 if( rc==TCL_CONTINUE ) rc = TCL_OK; |
| 495 if( rc!=TCL_OK ){ |
| 496 if( rc==TCL_BREAK ) rc = TCL_OK; |
| 497 break; |
| 498 } |
| 499 } |
| 500 |
| 501 break; |
| 502 } |
| 503 |
| 434 default: | 504 default: |
| 435 assert( 0 ); | 505 assert( 0 ); |
| 436 break; | 506 break; |
| 437 } | 507 } |
| 438 #undef CASE | 508 #undef CASE |
| 439 | 509 |
| 440 if( rc!=SQLITE_OK ){ | 510 if( rc!=SQLITE_OK ){ |
| 441 Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); | 511 Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); |
| 442 return TCL_ERROR; | 512 return TCL_ERROR; |
| 443 } | 513 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 F5tFunction *p = (F5tFunction*)pCtx; | 602 F5tFunction *p = (F5tFunction*)pCtx; |
| 533 Tcl_DecrRefCount(p->pScript); | 603 Tcl_DecrRefCount(p->pScript); |
| 534 ckfree((char *)p); | 604 ckfree((char *)p); |
| 535 } | 605 } |
| 536 | 606 |
| 537 /* | 607 /* |
| 538 ** sqlite3_fts5_create_function DB NAME SCRIPT | 608 ** sqlite3_fts5_create_function DB NAME SCRIPT |
| 539 ** | 609 ** |
| 540 ** Description... | 610 ** Description... |
| 541 */ | 611 */ |
| 542 static int f5tCreateFunction( | 612 static int SQLITE_TCLAPI f5tCreateFunction( |
| 543 void * clientData, | 613 void * clientData, |
| 544 Tcl_Interp *interp, | 614 Tcl_Interp *interp, |
| 545 int objc, | 615 int objc, |
| 546 Tcl_Obj *CONST objv[] | 616 Tcl_Obj *CONST objv[] |
| 547 ){ | 617 ){ |
| 548 char *zName; | 618 char *zName; |
| 549 Tcl_Obj *pScript; | 619 Tcl_Obj *pScript; |
| 550 sqlite3 *db = 0; | 620 sqlite3 *db = 0; |
| 551 fts5_api *pApi = 0; | 621 fts5_api *pApi = 0; |
| 552 F5tFunction *pCtx = 0; | 622 F5tFunction *pCtx = 0; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 } | 672 } |
| 603 return SQLITE_OK; | 673 return SQLITE_OK; |
| 604 } | 674 } |
| 605 | 675 |
| 606 | 676 |
| 607 /* | 677 /* |
| 608 ** sqlite3_fts5_tokenize DB TOKENIZER TEXT | 678 ** sqlite3_fts5_tokenize DB TOKENIZER TEXT |
| 609 ** | 679 ** |
| 610 ** Description... | 680 ** Description... |
| 611 */ | 681 */ |
| 612 static int f5tTokenize( | 682 static int SQLITE_TCLAPI f5tTokenize( |
| 613 void * clientData, | 683 void * clientData, |
| 614 Tcl_Interp *interp, | 684 Tcl_Interp *interp, |
| 615 int objc, | 685 int objc, |
| 616 Tcl_Obj *CONST objv[] | 686 Tcl_Obj *CONST objv[] |
| 617 ){ | 687 ){ |
| 618 char *zText; | 688 char *zText; |
| 619 int nText; | 689 int nText; |
| 620 sqlite3 *db = 0; | 690 sqlite3 *db = 0; |
| 621 fts5_api *pApi = 0; | 691 fts5_api *pApi = 0; |
| 622 Fts5Tokenizer *pTok = 0; | 692 Fts5Tokenizer *pTok = 0; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 Tcl_DecrRefCount(pEval); | 878 Tcl_DecrRefCount(pEval); |
| 809 | 879 |
| 810 pInst->pContext->pCtx = pOldCtx; | 880 pInst->pContext->pCtx = pOldCtx; |
| 811 pInst->pContext->xToken = xOldToken; | 881 pInst->pContext->xToken = xOldToken; |
| 812 return rc; | 882 return rc; |
| 813 } | 883 } |
| 814 | 884 |
| 815 /* | 885 /* |
| 816 ** sqlite3_fts5_token ?-colocated? TEXT START END | 886 ** sqlite3_fts5_token ?-colocated? TEXT START END |
| 817 */ | 887 */ |
| 818 static int f5tTokenizerReturn( | 888 static int SQLITE_TCLAPI f5tTokenizerReturn( |
| 819 void * clientData, | 889 void * clientData, |
| 820 Tcl_Interp *interp, | 890 Tcl_Interp *interp, |
| 821 int objc, | 891 int objc, |
| 822 Tcl_Obj *CONST objv[] | 892 Tcl_Obj *CONST objv[] |
| 823 ){ | 893 ){ |
| 824 F5tTokenizerContext *p = (F5tTokenizerContext*)clientData; | 894 F5tTokenizerContext *p = (F5tTokenizerContext*)clientData; |
| 825 int iStart; | 895 int iStart; |
| 826 int iEnd; | 896 int iEnd; |
| 827 int nToken; | 897 int nToken; |
| 828 int tflags = 0; | 898 int tflags = 0; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 ** | 949 ** |
| 880 ** The value returned by (SCRIPT + args) is itself a tcl script. This | 950 ** The value returned by (SCRIPT + args) is itself a tcl script. This |
| 881 ** script - call it SCRIPT2 - is executed to tokenize text using the | 951 ** script - call it SCRIPT2 - is executed to tokenize text using the |
| 882 ** tokenizer instance "returned" by SCRIPT. Specifically, to tokenize | 952 ** tokenizer instance "returned" by SCRIPT. Specifically, to tokenize |
| 883 ** text SCRIPT2 is invoked with a single argument appended to it - the | 953 ** text SCRIPT2 is invoked with a single argument appended to it - the |
| 884 ** text to tokenize. | 954 ** text to tokenize. |
| 885 ** | 955 ** |
| 886 ** SCRIPT2 should invoke the [sqlite3_fts5_token] command once for each | 956 ** SCRIPT2 should invoke the [sqlite3_fts5_token] command once for each |
| 887 ** token within the tokenized text. | 957 ** token within the tokenized text. |
| 888 */ | 958 */ |
| 889 static int f5tCreateTokenizer( | 959 static int SQLITE_TCLAPI f5tCreateTokenizer( |
| 890 ClientData clientData, | 960 ClientData clientData, |
| 891 Tcl_Interp *interp, | 961 Tcl_Interp *interp, |
| 892 int objc, | 962 int objc, |
| 893 Tcl_Obj *CONST objv[] | 963 Tcl_Obj *CONST objv[] |
| 894 ){ | 964 ){ |
| 895 F5tTokenizerContext *pContext = (F5tTokenizerContext*)clientData; | 965 F5tTokenizerContext *pContext = (F5tTokenizerContext*)clientData; |
| 896 sqlite3 *db; | 966 sqlite3 *db; |
| 897 fts5_api *pApi; | 967 fts5_api *pApi; |
| 898 char *zName; | 968 char *zName; |
| 899 Tcl_Obj *pScript; | 969 Tcl_Obj *pScript; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 922 Tcl_IncrRefCount(pScript); | 992 Tcl_IncrRefCount(pScript); |
| 923 rc = pApi->xCreateTokenizer(pApi, zName, (void*)pMod, &t, f5tDelTokenizer); | 993 rc = pApi->xCreateTokenizer(pApi, zName, (void*)pMod, &t, f5tDelTokenizer); |
| 924 if( rc!=SQLITE_OK ){ | 994 if( rc!=SQLITE_OK ){ |
| 925 Tcl_AppendResult(interp, "error in fts5_api.xCreateTokenizer()", 0); | 995 Tcl_AppendResult(interp, "error in fts5_api.xCreateTokenizer()", 0); |
| 926 return TCL_ERROR; | 996 return TCL_ERROR; |
| 927 } | 997 } |
| 928 | 998 |
| 929 return TCL_OK; | 999 return TCL_OK; |
| 930 } | 1000 } |
| 931 | 1001 |
| 932 static void xF5tFree(ClientData clientData){ | 1002 static void SQLITE_TCLAPI xF5tFree(ClientData clientData){ |
| 933 ckfree(clientData); | 1003 ckfree(clientData); |
| 934 } | 1004 } |
| 935 | 1005 |
| 936 /* | 1006 /* |
| 937 ** sqlite3_fts5_may_be_corrupt BOOLEAN | 1007 ** sqlite3_fts5_may_be_corrupt BOOLEAN |
| 938 ** | 1008 ** |
| 939 ** Set or clear the global "may-be-corrupt" flag. Return the old value. | 1009 ** Set or clear the global "may-be-corrupt" flag. Return the old value. |
| 940 */ | 1010 */ |
| 941 static int f5tMayBeCorrupt( | 1011 static int SQLITE_TCLAPI f5tMayBeCorrupt( |
| 942 void * clientData, | 1012 void * clientData, |
| 943 Tcl_Interp *interp, | 1013 Tcl_Interp *interp, |
| 944 int objc, | 1014 int objc, |
| 945 Tcl_Obj *CONST objv[] | 1015 Tcl_Obj *CONST objv[] |
| 946 ){ | 1016 ){ |
| 947 int bOld = sqlite3_fts5_may_be_corrupt; | 1017 int bOld = sqlite3_fts5_may_be_corrupt; |
| 948 | 1018 |
| 949 if( objc!=2 && objc!=1 ){ | 1019 if( objc!=2 && objc!=1 ){ |
| 950 Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?"); | 1020 Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?"); |
| 951 return TCL_ERROR; | 1021 return TCL_ERROR; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 963 | 1033 |
| 964 static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){ | 1034 static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){ |
| 965 int i; | 1035 int i; |
| 966 unsigned int h = 13; | 1036 unsigned int h = 13; |
| 967 for(i=n-1; i>=0; i--){ | 1037 for(i=n-1; i>=0; i--){ |
| 968 h = (h << 3) ^ h ^ p[i]; | 1038 h = (h << 3) ^ h ^ p[i]; |
| 969 } | 1039 } |
| 970 return (h % nSlot); | 1040 return (h % nSlot); |
| 971 } | 1041 } |
| 972 | 1042 |
| 973 static int f5tTokenHash( | 1043 static int SQLITE_TCLAPI f5tTokenHash( |
| 974 void * clientData, | 1044 void * clientData, |
| 975 Tcl_Interp *interp, | 1045 Tcl_Interp *interp, |
| 976 int objc, | 1046 int objc, |
| 977 Tcl_Obj *CONST objv[] | 1047 Tcl_Obj *CONST objv[] |
| 978 ){ | 1048 ){ |
| 979 char *z; | 1049 char *z; |
| 980 int n; | 1050 int n; |
| 981 unsigned int iVal; | 1051 unsigned int iVal; |
| 982 int nSlot; | 1052 int nSlot; |
| 983 | 1053 |
| 984 if( objc!=3 ){ | 1054 if( objc!=3 ){ |
| 985 Tcl_WrongNumArgs(interp, 1, objv, "NSLOT TOKEN"); | 1055 Tcl_WrongNumArgs(interp, 1, objv, "NSLOT TOKEN"); |
| 986 return TCL_ERROR; | 1056 return TCL_ERROR; |
| 987 } | 1057 } |
| 988 if( Tcl_GetIntFromObj(interp, objv[1], &nSlot) ){ | 1058 if( Tcl_GetIntFromObj(interp, objv[1], &nSlot) ){ |
| 989 return TCL_ERROR; | 1059 return TCL_ERROR; |
| 990 } | 1060 } |
| 991 z = Tcl_GetStringFromObj(objv[2], &n); | 1061 z = Tcl_GetStringFromObj(objv[2], &n); |
| 992 | 1062 |
| 993 iVal = f5t_fts5HashKey(nSlot, z, n); | 1063 iVal = f5t_fts5HashKey(nSlot, z, n); |
| 994 Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); | 1064 Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); |
| 995 return TCL_OK; | 1065 return TCL_OK; |
| 996 } | 1066 } |
| 997 | 1067 |
| 998 static int f5tRegisterMatchinfo( | 1068 static int SQLITE_TCLAPI f5tRegisterMatchinfo( |
| 999 void * clientData, | 1069 void * clientData, |
| 1000 Tcl_Interp *interp, | 1070 Tcl_Interp *interp, |
| 1001 int objc, | 1071 int objc, |
| 1002 Tcl_Obj *CONST objv[] | 1072 Tcl_Obj *CONST objv[] |
| 1003 ){ | 1073 ){ |
| 1004 int rc; | 1074 int rc; |
| 1005 sqlite3 *db = 0; | 1075 sqlite3 *db = 0; |
| 1006 | 1076 |
| 1007 if( objc!=2 ){ | 1077 if( objc!=2 ){ |
| 1008 Tcl_WrongNumArgs(interp, 1, objv, "DB"); | 1078 Tcl_WrongNumArgs(interp, 1, objv, "DB"); |
| 1009 return TCL_ERROR; | 1079 return TCL_ERROR; |
| 1010 } | 1080 } |
| 1011 if( f5tDbPointer(interp, objv[1], &db) ){ | 1081 if( f5tDbPointer(interp, objv[1], &db) ){ |
| 1012 return TCL_ERROR; | 1082 return TCL_ERROR; |
| 1013 } | 1083 } |
| 1014 | 1084 |
| 1015 rc = sqlite3Fts5TestRegisterMatchinfo(db); | 1085 rc = sqlite3Fts5TestRegisterMatchinfo(db); |
| 1016 if( rc!=SQLITE_OK ){ | 1086 if( rc!=SQLITE_OK ){ |
| 1017 Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); | 1087 Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); |
| 1018 return TCL_ERROR; | 1088 return TCL_ERROR; |
| 1019 } | 1089 } |
| 1020 return TCL_OK; | 1090 return TCL_OK; |
| 1021 } | 1091 } |
| 1022 | 1092 |
| 1093 static int SQLITE_TCLAPI f5tRegisterTok( |
| 1094 void * clientData, |
| 1095 Tcl_Interp *interp, |
| 1096 int objc, |
| 1097 Tcl_Obj *CONST objv[] |
| 1098 ){ |
| 1099 int rc; |
| 1100 sqlite3 *db = 0; |
| 1101 fts5_api *pApi = 0; |
| 1102 |
| 1103 if( objc!=2 ){ |
| 1104 Tcl_WrongNumArgs(interp, 1, objv, "DB"); |
| 1105 return TCL_ERROR; |
| 1106 } |
| 1107 if( f5tDbAndApi(interp, objv[1], &db, &pApi) ){ |
| 1108 return TCL_ERROR; |
| 1109 } |
| 1110 |
| 1111 rc = sqlite3Fts5TestRegisterTok(db, pApi); |
| 1112 if( rc!=SQLITE_OK ){ |
| 1113 Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); |
| 1114 return TCL_ERROR; |
| 1115 } |
| 1116 return TCL_OK; |
| 1117 } |
| 1118 |
| 1023 /* | 1119 /* |
| 1024 ** Entry point. | 1120 ** Entry point. |
| 1025 */ | 1121 */ |
| 1026 int Fts5tcl_Init(Tcl_Interp *interp){ | 1122 int Fts5tcl_Init(Tcl_Interp *interp){ |
| 1027 static struct Cmd { | 1123 static struct Cmd { |
| 1028 char *zName; | 1124 char *zName; |
| 1029 Tcl_ObjCmdProc *xProc; | 1125 Tcl_ObjCmdProc *xProc; |
| 1030 int bTokenizeCtx; | 1126 int bTokenizeCtx; |
| 1031 } aCmd[] = { | 1127 } aCmd[] = { |
| 1032 { "sqlite3_fts5_create_tokenizer", f5tCreateTokenizer, 1 }, | 1128 { "sqlite3_fts5_create_tokenizer", f5tCreateTokenizer, 1 }, |
| 1033 { "sqlite3_fts5_token", f5tTokenizerReturn, 1 }, | 1129 { "sqlite3_fts5_token", f5tTokenizerReturn, 1 }, |
| 1034 { "sqlite3_fts5_tokenize", f5tTokenize, 0 }, | 1130 { "sqlite3_fts5_tokenize", f5tTokenize, 0 }, |
| 1035 { "sqlite3_fts5_create_function", f5tCreateFunction, 0 }, | 1131 { "sqlite3_fts5_create_function", f5tCreateFunction, 0 }, |
| 1036 { "sqlite3_fts5_may_be_corrupt", f5tMayBeCorrupt, 0 }, | 1132 { "sqlite3_fts5_may_be_corrupt", f5tMayBeCorrupt, 0 }, |
| 1037 { "sqlite3_fts5_token_hash", f5tTokenHash, 0 }, | 1133 { "sqlite3_fts5_token_hash", f5tTokenHash, 0 }, |
| 1038 { "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 } | 1134 { "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 }, |
| 1135 { "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 } |
| 1039 }; | 1136 }; |
| 1040 int i; | 1137 int i; |
| 1041 F5tTokenizerContext *pContext; | 1138 F5tTokenizerContext *pContext; |
| 1042 | 1139 |
| 1043 pContext = (F5tTokenizerContext*)ckalloc(sizeof(F5tTokenizerContext)); | 1140 pContext = (F5tTokenizerContext*)ckalloc(sizeof(F5tTokenizerContext)); |
| 1044 memset(pContext, 0, sizeof(*pContext)); | 1141 memset(pContext, 0, sizeof(*pContext)); |
| 1045 | 1142 |
| 1046 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ | 1143 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ |
| 1047 struct Cmd *p = &aCmd[i]; | 1144 struct Cmd *p = &aCmd[i]; |
| 1048 void *pCtx = 0; | 1145 void *pCtx = 0; |
| 1049 if( p->bTokenizeCtx ) pCtx = (void*)pContext; | 1146 if( p->bTokenizeCtx ) pCtx = (void*)pContext; |
| 1050 Tcl_CreateObjCommand(interp, p->zName, p->xProc, pCtx, (i ? 0 : xF5tFree)); | 1147 Tcl_CreateObjCommand(interp, p->zName, p->xProc, pCtx, (i ? 0 : xF5tFree)); |
| 1051 } | 1148 } |
| 1052 | 1149 |
| 1053 return TCL_OK; | 1150 return TCL_OK; |
| 1054 } | 1151 } |
| 1055 #else /* SQLITE_ENABLE_FTS5 */ | 1152 #else /* SQLITE_ENABLE_FTS5 */ |
| 1056 int Fts5tcl_Init(Tcl_Interp *interp){ | 1153 int Fts5tcl_Init(Tcl_Interp *interp){ |
| 1057 return TCL_OK; | 1154 return TCL_OK; |
| 1058 } | 1155 } |
| 1059 #endif /* SQLITE_ENABLE_FTS5 */ | 1156 #endif /* SQLITE_ENABLE_FTS5 */ |
| 1060 #endif /* SQLITE_TEST */ | 1157 #endif /* SQLITE_TEST */ |
| OLD | NEW |