Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improve coverage of fts5 tests. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | fts5 |
Files: | files | file ages | folders |
SHA1: |
8e8136f2dc08082c2984462719d9cba0 |
User & Date: | dan 2015-04-28 18:35:28.633 |
Context
2015-04-28
| ||
20:24 | Fix an fts5 bug in handling writes while there are active cursors. (check-in: 07f7095539 user: dan tags: fts5) | |
18:35 | Improve coverage of fts5 tests. (check-in: 8e8136f2dc user: dan tags: fts5) | |
2015-04-27
| ||
16:21 | Change the fts5 content= option so that it matches fts5 columns with the underlying table columns by name, not by their position within the CREATE TABLE statement. (check-in: e38e2bb637 user: dan tags: fts5) | |
Changes
Changes to ext/fts5/fts5.c.
︙ | ︙ | |||
262 263 264 265 266 267 268 | ** Return true if pTab is a contentless table. */ static int fts5IsContentless(Fts5Table *pTab){ return pTab->pConfig->eContent==FTS5_CONTENT_NONE; } /* | | < | < | < | < | > > > > | > > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | ** Return true if pTab is a contentless table. */ static int fts5IsContentless(Fts5Table *pTab){ return pTab->pConfig->eContent==FTS5_CONTENT_NONE; } /* ** Delete a virtual table handle allocated by fts5InitVtab(). */ static void fts5FreeVtab(Fts5Table *pTab){ int rc = SQLITE_OK; if( pTab ){ sqlite3Fts5IndexClose(pTab->pIndex); sqlite3Fts5StorageClose(pTab->pStorage); sqlite3Fts5ConfigFree(pTab->pConfig); sqlite3_free(pTab); } return rc; } /* ** The xDisconnect() virtual table method. */ static int fts5DisconnectMethod(sqlite3_vtab *pVtab){ fts5FreeVtab((Fts5Table*)pVtab); return SQLITE_OK; } /* ** The xDestroy() virtual table method. */ static int fts5DestroyMethod(sqlite3_vtab *pVtab){ Fts5Table *pTab = (Fts5Table*)pVtab; int rc = sqlite3Fts5DropAll(pTab->pConfig); if( rc==SQLITE_OK ){ fts5FreeVtab((Fts5Table*)pVtab); } return rc; } /* ** This function is the implementation of both the xConnect and xCreate ** methods of the FTS3 virtual table. ** ** The argv[] array contains the following: |
︙ | ︙ | |||
348 349 350 351 352 353 354 | /* Call sqlite3_declare_vtab() */ if( rc==SQLITE_OK ){ rc = sqlite3Fts5ConfigDeclareVtab(pConfig); } if( rc!=SQLITE_OK ){ | | | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | /* Call sqlite3_declare_vtab() */ if( rc==SQLITE_OK ){ rc = sqlite3Fts5ConfigDeclareVtab(pConfig); } if( rc!=SQLITE_OK ){ fts5FreeVtab(pTab); pTab = 0; }else if( bCreate ){ fts5CheckTransactionState(pTab, FTS5_BEGIN, 0); } *ppVTab = (sqlite3_vtab*)pTab; return rc; } |
︙ | ︙ |
Changes to ext/fts5/fts5Int.h.
︙ | ︙ | |||
173 174 175 176 177 178 179 | void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64); void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, int, const u8*); void sqlite3Fts5BufferAppendString(int *, Fts5Buffer*, const char*); void sqlite3Fts5BufferFree(Fts5Buffer*); void sqlite3Fts5BufferZero(Fts5Buffer*); void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*); void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...); | < | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64); void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, int, const u8*); void sqlite3Fts5BufferAppendString(int *, Fts5Buffer*, const char*); void sqlite3Fts5BufferFree(Fts5Buffer*); void sqlite3Fts5BufferZero(Fts5Buffer*); void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*); void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...); void sqlite3Fts5BufferAppend32(int*, Fts5Buffer*, int); #define fts5BufferZero(x) sqlite3Fts5BufferZero(x) #define fts5BufferGrow(a,b,c) sqlite3Fts5BufferGrow(a,b,c) #define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c) #define fts5BufferFree(a) sqlite3Fts5BufferFree(a) #define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d) |
︙ | ︙ | |||
216 217 218 219 220 221 222 | typedef struct Fts5PoslistWriter Fts5PoslistWriter; struct Fts5PoslistWriter { i64 iPrev; }; int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); | < < < < < < < | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | typedef struct Fts5PoslistWriter Fts5PoslistWriter; struct Fts5PoslistWriter { i64 iPrev; }; int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); int sqlite3Fts5PoslistNext64( const u8 *a, int n, /* Buffer containing poslist */ int *pi, /* IN/OUT: Offset within a[] */ i64 *piOff /* IN/OUT: Current offset */ ); /* Malloc utility */ |
︙ | ︙ | |||
255 256 257 258 259 260 261 | #define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ /* ** Create/destroy an Fts5Index object. */ int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); | | | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | #define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ /* ** Create/destroy an Fts5Index object. */ int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); int sqlite3Fts5IndexClose(Fts5Index *p); /* ** for( ** pIter = sqlite3Fts5IndexQuery(p, "token", 5, 0); ** 0==sqlite3Fts5IterEof(pIter); ** sqlite3Fts5IterNext(pIter) ** ){ |
︙ | ︙ | |||
440 441 442 443 444 445 446 | #define FTS5_STMT_SCAN_ASC 0 /* SELECT rowid, * FROM ... ORDER BY 1 ASC */ #define FTS5_STMT_SCAN_DESC 1 /* SELECT rowid, * FROM ... ORDER BY 1 DESC */ #define FTS5_STMT_LOOKUP 2 /* SELECT rowid, * FROM ... WHERE rowid=? */ typedef struct Fts5Storage Fts5Storage; int sqlite3Fts5StorageOpen(Fts5Config*, Fts5Index*, int, Fts5Storage**, char**); | | | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | #define FTS5_STMT_SCAN_ASC 0 /* SELECT rowid, * FROM ... ORDER BY 1 ASC */ #define FTS5_STMT_SCAN_DESC 1 /* SELECT rowid, * FROM ... ORDER BY 1 DESC */ #define FTS5_STMT_LOOKUP 2 /* SELECT rowid, * FROM ... WHERE rowid=? */ typedef struct Fts5Storage Fts5Storage; int sqlite3Fts5StorageOpen(Fts5Config*, Fts5Index*, int, Fts5Storage**, char**); int sqlite3Fts5StorageClose(Fts5Storage *p); int sqlite3Fts5DropAll(Fts5Config*); int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **); int sqlite3Fts5StorageDelete(Fts5Storage *p, i64); int sqlite3Fts5StorageInsert(Fts5Storage *p, sqlite3_value **apVal, int, i64*); int sqlite3Fts5StorageIntegrity(Fts5Storage *p); |
︙ | ︙ |
Changes to ext/fts5/fts5_buffer.c.
︙ | ︙ | |||
88 89 90 91 92 93 94 | */ void sqlite3Fts5BufferAppendString( int *pRc, Fts5Buffer *pBuf, const char *zStr ){ int nStr = strlen(zStr); | < | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | */ void sqlite3Fts5BufferAppendString( int *pRc, Fts5Buffer *pBuf, const char *zStr ){ int nStr = strlen(zStr); sqlite3Fts5BufferAppendBlob(pRc, pBuf, nStr+1, (const u8*)zStr); pBuf->n--; } /* ** Argument zFmt is a printf() style format string. This function performs ** the printf() style processing, then appends the results to buffer pBuf. ** ** Like sqlite3Fts5BufferAppendString(), this function ensures that the byte |
︙ | ︙ | |||
224 225 226 227 228 229 230 | pWriter->iPrev = (iPos & colmask); } fts5BufferAppendVarint(&rc, pBuf, (iPos - pWriter->iPrev) + 2); pWriter->iPrev = iPos; return rc; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | pWriter->iPrev = (iPos & colmask); } fts5BufferAppendVarint(&rc, pBuf, (iPos - pWriter->iPrev) + 2); pWriter->iPrev = iPos; return rc; } void *sqlite3Fts5MallocZero(int *pRc, int nByte){ void *pRet = 0; if( *pRc==SQLITE_OK ){ pRet = sqlite3_malloc(nByte); if( pRet==0 && nByte>0 ){ *pRc = SQLITE_NOMEM; }else{ |
︙ | ︙ |
Changes to ext/fts5/fts5_hash.c.
︙ | ︙ | |||
413 414 415 416 417 418 419 | Fts5Hash *p, /* Hash table to query */ const char *pTerm, int nTerm /* Query prefix */ ){ return fts5HashEntrySort(p, pTerm, nTerm, &p->pScan); } void sqlite3Fts5HashScanNext(Fts5Hash *p){ | | | | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 | Fts5Hash *p, /* Hash table to query */ const char *pTerm, int nTerm /* Query prefix */ ){ return fts5HashEntrySort(p, pTerm, nTerm, &p->pScan); } void sqlite3Fts5HashScanNext(Fts5Hash *p){ assert( !sqlite3Fts5HashScanEof(p) ); p->pScan = p->pScan->pScanNext; } int sqlite3Fts5HashScanEof(Fts5Hash *p){ return (p->pScan==0); } void sqlite3Fts5HashScanEntry( |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
698 699 700 701 702 703 704 | /* ** Allocate and return a buffer at least nByte bytes in size. ** ** If an OOM error is encountered, return NULL and set the error code in ** the Fts5Index handle passed as the first argument. */ static void *fts5IdxMalloc(Fts5Index *p, int nByte){ | < < < < < < < < < | | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | /* ** Allocate and return a buffer at least nByte bytes in size. ** ** If an OOM error is encountered, return NULL and set the error code in ** the Fts5Index handle passed as the first argument. */ static void *fts5IdxMalloc(Fts5Index *p, int nByte){ return sqlite3Fts5MallocZero(&p->rc, nByte); } /* ** Compare the contents of the pLeft buffer with the pRight/nRight blob. ** ** Return -ve if pLeft is smaller than pRight, 0 if they are equal or ** +ve if pRight is smaller than pLeft. In other words: |
︙ | ︙ | |||
4209 4210 4211 4212 4213 4214 4215 | int bCreate, Fts5Index **pp, char **pzErr ){ int rc = SQLITE_OK; Fts5Index *p; /* New object */ | | < | < | | | | | | | | | | | | | | | > | | | < < < | 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 | int bCreate, Fts5Index **pp, char **pzErr ){ int rc = SQLITE_OK; Fts5Index *p; /* New object */ *pp = p = (Fts5Index*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Index)); if( rc==SQLITE_OK ){ p->pConfig = pConfig; p->nWorkUnit = FTS5_WORK_UNIT; p->nMaxPendingData = 1024*1024; p->zDataTbl = sqlite3_mprintf("%s_data", pConfig->zName); if( p->zDataTbl==0 ){ rc = SQLITE_NOMEM; }else if( bCreate ){ rc = sqlite3Fts5CreateTable( pConfig, "data", "id INTEGER PRIMARY KEY, block BLOB", 0, pzErr ); if( rc==SQLITE_OK ){ rc = sqlite3Fts5IndexReinit(p); } } } assert( rc!=SQLITE_OK || p->rc==SQLITE_OK ); if( rc ){ sqlite3Fts5IndexClose(p); *pp = 0; } return rc; } /* ** Close a handle opened by an earlier call to sqlite3Fts5IndexOpen(). */ int sqlite3Fts5IndexClose(Fts5Index *p){ int rc = SQLITE_OK; if( p ){ assert( p->pReader==0 ); sqlite3_finalize(p->pWriter); sqlite3_finalize(p->pDeleter); if( p->apHash ){ int i; for(i=0; i<=p->pConfig->nPrefix; i++){ sqlite3Fts5HashFree(p->apHash[i]); |
︙ | ︙ |
Changes to ext/fts5/fts5_storage.c.
︙ | ︙ | |||
150 151 152 153 154 155 156 | } va_end(ap); return rc; } /* | < | > | > > > > > > > > > | > | | > > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | } va_end(ap); return rc; } /* ** Drop all shadow tables. Return SQLITE_OK if successful or an SQLite error ** code otherwise. */ int sqlite3Fts5DropAll(Fts5Config *pConfig){ int rc = fts5ExecPrintf(pConfig->db, 0, "DROP TABLE IF EXISTS %Q.'%q_data';" "DROP TABLE IF EXISTS %Q.'%q_docsize';" "DROP TABLE IF EXISTS %Q.'%q_config';", pConfig->zDb, pConfig->zName, pConfig->zDb, pConfig->zName, pConfig->zDb, pConfig->zName ); if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ rc = fts5ExecPrintf(pConfig->db, 0, "DROP TABLE IF EXISTS %Q.'%q_content';", pConfig->zDb, pConfig->zName ); } return rc; } /* ** Create the shadow table named zPost, with definition zDefn. Return ** SQLITE_OK if successful, or an SQLite error code otherwise. */ int sqlite3Fts5CreateTable( |
︙ | ︙ | |||
244 245 246 247 248 249 250 | rc = sqlite3Fts5CreateTable( pConfig, "config", "k PRIMARY KEY, v", 1, pzErr ); } } if( rc ){ | | | < < < < < < < < < | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | rc = sqlite3Fts5CreateTable( pConfig, "config", "k PRIMARY KEY, v", 1, pzErr ); } } if( rc ){ sqlite3Fts5StorageClose(p); *pp = 0; } return rc; } /* ** Close a handle opened by an earlier call to sqlite3Fts5StorageOpen(). */ int sqlite3Fts5StorageClose(Fts5Storage *p){ int rc = SQLITE_OK; if( p ){ int i; /* Finalize all SQL statements */ for(i=0; i<ArraySize(p->aStmt); i++){ sqlite3_finalize(p->aStmt[i]); } sqlite3_free(p); } return rc; } typedef struct Fts5InsertCtx Fts5InsertCtx; struct Fts5InsertCtx { |
︙ | ︙ |
Changes to ext/fts5/fts5_tcl.c.
︙ | ︙ | |||
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 | sqlite3_fts5_may_be_corrupt = bNew; } Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld)); return TCL_OK; } /* ** Entry point. */ int Fts5tcl_Init(Tcl_Interp *interp){ static struct Cmd { char *zName; Tcl_ObjCmdProc *xProc; int bTokenizeCtx; } aCmd[] = { { "sqlite3_fts5_create_tokenizer", f5tCreateTokenizer, 1 }, { "sqlite3_fts5_token", f5tTokenizerReturn, 1 }, { "sqlite3_fts5_tokenize", f5tTokenize, 0 }, { "sqlite3_fts5_create_function", f5tCreateFunction, 0 }, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | sqlite3_fts5_may_be_corrupt = bNew; } Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld)); return TCL_OK; } static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){ int i; unsigned int h = 13; for(i=n-1; i>=0; i--){ h = (h << 3) ^ h ^ p[i]; } return (h % nSlot); } static int f5tTokenHash( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int bOld = sqlite3_fts5_may_be_corrupt; char *z; int n; unsigned int iVal; int nSlot; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "NSLOT TOKEN"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &nSlot) ){ return TCL_ERROR; } z = Tcl_GetStringFromObj(objv[2], &n); iVal = f5t_fts5HashKey(nSlot, z, n); Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); return TCL_OK; } /* ** Entry point. */ int Fts5tcl_Init(Tcl_Interp *interp){ static struct Cmd { char *zName; Tcl_ObjCmdProc *xProc; int bTokenizeCtx; } aCmd[] = { { "sqlite3_fts5_create_tokenizer", f5tCreateTokenizer, 1 }, { "sqlite3_fts5_token", f5tTokenizerReturn, 1 }, { "sqlite3_fts5_tokenize", f5tTokenize, 0 }, { "sqlite3_fts5_create_function", f5tCreateFunction, 0 }, { "sqlite3_fts5_may_be_corrupt", f5tMayBeCorrupt, 0 }, { "sqlite3_fts5_token_hash", f5tTokenHash, 0 } }; int i; F5tTokenizerContext *pContext; pContext = ckalloc(sizeof(F5tTokenizerContext)); memset(pContext, 0, sizeof(*pContext)); |
︙ | ︙ |
Changes to ext/fts5/test/fts5fault3.test.
︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 | faultsim_restore_and_reopen } -body { execsql { INSERT INTO xx(x) VALUES ($::doc) } } -test { faultsim_test_result [list 0 {}] } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | faultsim_restore_and_reopen } -body { execsql { INSERT INTO xx(x) VALUES ($::doc) } } -test { faultsim_test_result [list 0 {}] } #------------------------------------------------------------------------- # An OOM while flushing an unusually large term to disk. # reset_db do_execsql_test 3.0 { CREATE VIRTUAL TABLE xx USING fts5(x); } faultsim_save_and_close set doc [fts5_rnddoc 1000] do_faultsim_test 3.1 -faults oom-* -prep { faultsim_restore_and_reopen } -body { execsql { INSERT INTO xx(x) VALUES ($::doc) } } -test { faultsim_test_result [list 0 {}] } set doc [string repeat "abc " 100] do_faultsim_test 3.2 -faults oom-* -prep { faultsim_restore_and_reopen } -body { execsql { INSERT INTO xx(x) VALUES ($::doc) } } -test { faultsim_test_result [list 0 {}] } finish_test |
Added ext/fts5/test/fts5fault4.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | # 2014 June 17 # # 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. # #************************************************************************* # # This file is focused on OOM errors. # source [file join [file dirname [info script]] fts5_common.tcl] source $testdir/malloc_common.tcl set testprefix fts5fault4 # If SQLITE_ENABLE_FTS3 is defined, omit this file. ifcapable !fts5 { finish_test return } #------------------------------------------------------------------------- # An OOM while dropping an fts5 table. # db func rnddoc fts5_rnddoc do_test 1.0 { execsql { CREATE VIRTUAL TABLE xx USING fts5(x) } } {} faultsim_save_and_close do_faultsim_test 1 -faults oom-* -prep { faultsim_restore_and_reopen execsql { SELECT * FROM xx } } -body { execsql { DROP TABLE xx } } -test { faultsim_test_result [list 0 {}] } finish_test |
Added ext/fts5/test/fts5hash.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | # 2015 April 21 # # 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. # #*********************************************************************** # # The tests in this file are focused on the code in fts5_hash.c. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5hash #------------------------------------------------------------------------- # Return a list of tokens (a vocabulary) that all share the same hash # key value. This can be used to test hash collisions. # proc build_vocab1 {args} { set O(-nslot) 1024 set O(-nword) 20 set O(-hash) 88 set O(-prefix) "" if {[llength $args] % 2} { error "bad args" } array set O2 $args foreach {k v} $args { if {[info exists O($k)]==0} { error "bad option: $k" } set O($k) $v } set L [list] while {[llength $L] < $O(-nword)} { set t "$O(-prefix)[random_token]" set h [sqlite3_fts5_token_hash $O(-nslot) $t] if {$O(-hash)==$h} { lappend L $t } } return $L } proc random_token {} { set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] set iVal [expr int(rand() * 2000000)] return [string map $map $iVal] } proc random_doc {vocab nWord} { set doc "" set nVocab [llength $vocab] for {set i 0} {$i<$nWord} {incr i} { set j [expr {int(rand() * $nVocab)}] lappend doc [lindex $vocab $j] } return $doc } set vocab [build_vocab1] db func r random_doc do_execsql_test 1.0 { CREATE VIRTUAL TABLE eee USING fts5(e, ee); BEGIN; WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii; INSERT INTO eee(eee) VALUES('integrity-check'); COMMIT; INSERT INTO eee(eee) VALUES('integrity-check'); } set hash [sqlite3_fts5_token_hash 1024 xyz] set vocab [build_vocab1 -prefix xyz -hash $hash] lappend vocab xyz do_execsql_test 1.1 { BEGIN; WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii; INSERT INTO eee(eee) VALUES('integrity-check'); COMMIT; INSERT INTO eee(eee) VALUES('integrity-check'); } finish_test |
Changes to ext/fts5/test/fts5prefix.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # 2015 Jan 13 # # 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. # #*********************************************************************** # # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5prefix #------------------------------------------------------------------------- | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 2015 Jan 13 # # 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. # #*********************************************************************** # # This file containst tests focused on prefix indexes. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5prefix #------------------------------------------------------------------------- |
︙ | ︙ |