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 |