SQLite
Check-in [7e6007a000]
Not logged in
Overview
SHA1 Hash:7e6007a0002f6989bd489abeba8db52acb4a6854
Date: 2013-01-11 09:58:54
User: dan
Comment:Add another test for the fts4 content= option.
Tags And Properties
Changes
hide diffs unified diffs patch

Changes to main.mk

236 $(TOP)/src/test_autoext.c \ 236 $(TOP)/src/test_autoext.c \ 237 $(TOP)/src/test_async.c \ 237 $(TOP)/src/test_async.c \ 238 $(TOP)/src/test_backup.c \ 238 $(TOP)/src/test_backup.c \ 239 $(TOP)/src/test_btree.c \ 239 $(TOP)/src/test_btree.c \ 240 $(TOP)/src/test_config.c \ 240 $(TOP)/src/test_config.c \ 241 $(TOP)/src/test_demovfs.c \ 241 $(TOP)/src/test_demovfs.c \ 242 $(TOP)/src/test_devsym.c \ 242 $(TOP)/src/test_devsym.c \ > 243 $(TOP)/src/test_fs.c \ 243 $(TOP)/src/test_func.c \ 244 $(TOP)/src/test_func.c \ 244 $(TOP)/src/test_fuzzer.c \ 245 $(TOP)/src/test_fuzzer.c \ 245 $(TOP)/src/test_hexio.c \ 246 $(TOP)/src/test_hexio.c \ 246 $(TOP)/src/test_init.c \ 247 $(TOP)/src/test_init.c \ 247 $(TOP)/src/test_intarray.c \ 248 $(TOP)/src/test_intarray.c \ 248 $(TOP)/src/test_journal.c \ 249 $(TOP)/src/test_journal.c \ 249 $(TOP)/src/test_malloc.c \ 250 $(TOP)/src/test_malloc.c \

Changes to src/tclsqlite.c

3667 extern int Sqlitetest_hexio_Init(Tcl_Interp*); 3667 extern int Sqlitetest_hexio_Init(Tcl_Interp*); 3668 extern int Sqlitetest_init_Init(Tcl_Interp*); 3668 extern int Sqlitetest_init_Init(Tcl_Interp*); 3669 extern int Sqlitetest_malloc_Init(Tcl_Interp*); 3669 extern int Sqlitetest_malloc_Init(Tcl_Interp*); 3670 extern int Sqlitetest_mutex_Init(Tcl_Interp*); 3670 extern int Sqlitetest_mutex_Init(Tcl_Interp*); 3671 extern int Sqlitetestschema_Init(Tcl_Interp*); 3671 extern int Sqlitetestschema_Init(Tcl_Interp*); 3672 extern int Sqlitetestsse_Init(Tcl_Interp*); 3672 extern int Sqlitetestsse_Init(Tcl_Interp*); 3673 extern int Sqlitetesttclvar_Init(Tcl_Interp*); 3673 extern int Sqlitetesttclvar_Init(Tcl_Interp*); > 3674 extern int Sqlitetestfs_Init(Tcl_Interp*); 3674 extern int SqlitetestThread_Init(Tcl_Interp*); 3675 extern int SqlitetestThread_Init(Tcl_Interp*); 3675 extern int SqlitetestOnefile_Init(); 3676 extern int SqlitetestOnefile_Init(); 3676 extern int SqlitetestOsinst_Init(Tcl_Interp*); 3677 extern int SqlitetestOsinst_Init(Tcl_Interp*); 3677 extern int Sqlitetestbackup_Init(Tcl_Interp*); 3678 extern int Sqlitetestbackup_Init(Tcl_Interp*); 3678 extern int Sqlitetestintarray_Init(Tcl_Interp*); 3679 extern int Sqlitetestintarray_Init(Tcl_Interp*); 3679 extern int Sqlitetestvfs_Init(Tcl_Interp *); 3680 extern int Sqlitetestvfs_Init(Tcl_Interp *); 3680 extern int Sqlitetestrtree_Init(Tcl_Interp*); 3681 extern int Sqlitetestrtree_Init(Tcl_Interp*); ................................................................................................................................................................................ 3711 Sqlitetest_func_Init(interp); 3712 Sqlitetest_func_Init(interp); 3712 Sqlitetest_hexio_Init(interp); 3713 Sqlitetest_hexio_Init(interp); 3713 Sqlitetest_init_Init(interp); 3714 Sqlitetest_init_Init(interp); 3714 Sqlitetest_malloc_Init(interp); 3715 Sqlitetest_malloc_Init(interp); 3715 Sqlitetest_mutex_Init(interp); 3716 Sqlitetest_mutex_Init(interp); 3716 Sqlitetestschema_Init(interp); 3717 Sqlitetestschema_Init(interp); 3717 Sqlitetesttclvar_Init(interp); 3718 Sqlitetesttclvar_Init(interp); > 3719 Sqlitetestfs_Init(interp); 3718 SqlitetestThread_Init(interp); 3720 SqlitetestThread_Init(interp); 3719 SqlitetestOnefile_Init(interp); 3721 SqlitetestOnefile_Init(interp); 3720 SqlitetestOsinst_Init(interp); 3722 SqlitetestOsinst_Init(interp); 3721 Sqlitetestbackup_Init(interp); 3723 Sqlitetestbackup_Init(interp); 3722 Sqlitetestintarray_Init(interp); 3724 Sqlitetestintarray_Init(interp); 3723 Sqlitetestvfs_Init(interp); 3725 Sqlitetestvfs_Init(interp); 3724 Sqlitetestrtree_Init(interp); 3726 Sqlitetestrtree_Init(interp);

Added src/test_fs.c

> 1 /* > 2 ** 2013 Jan 11 > 3 ** > 4 ** The author disclaims copyright to this source code. In place of > 5 ** a legal notice, here is a blessing: > 6 ** > 7 ** May you do good and not evil. > 8 ** May you find forgiveness for yourself and forgive others. > 9 ** May you share freely, never taking more than you give. > 10 ** > 11 ************************************************************************* > 12 ** Code for testing the virtual table interfaces. This code > 13 ** is not included in the SQLite library. It is used for automated > 14 ** testing of the SQLite library. > 15 ** > 16 ** The FS virtual table is created as follows: > 17 ** > 18 ** CREATE VIRTUAL TABLE tbl USING fs(idx); > 19 ** > 20 ** where idx is the name of a table in the db with 2 columns. The virtual > 21 ** table also has two columns - file path and file contents. > 22 ** > 23 ** The first column of table idx must be an IPK, and the second contains file > 24 ** paths. For example: > 25 ** > 26 ** CREATE TABLE idx(id INTEGER PRIMARY KEY, path TEXT); > 27 ** INSERT INTO idx VALUES(4, '/etc/passwd'); > 28 ** > 29 ** Adding the row to the idx table automatically creates a row in the > 30 ** virtual table with rowid=4, path=/etc/passwd and a text field that > 31 ** contains data read from file /etc/passwd on disk. > 32 */ > 33 #include "sqliteInt.h" > 34 #include "tcl.h" > 35 > 36 #include <stdlib.h> > 37 #include <string.h> > 38 #include <sys/types.h> > 39 #include <sys/stat.h> > 40 #include <unistd.h> > 41 #include <fcntl.h> > 42 > 43 #ifndef SQLITE_OMIT_VIRTUALTABLE > 44 > 45 typedef struct fs_vtab fs_vtab; > 46 typedef struct fs_cursor fs_cursor; > 47 > 48 /* > 49 ** A fs virtual-table object > 50 */ > 51 struct fs_vtab { > 52 sqlite3_vtab base; > 53 sqlite3 *db; > 54 char *zDb; /* Name of db containing zTbl */ > 55 char *zTbl; /* Name of docid->file map table */ > 56 }; > 57 > 58 /* A fs cursor object */ > 59 struct fs_cursor { > 60 sqlite3_vtab_cursor base; > 61 sqlite3_stmt *pStmt; > 62 char *zBuf; > 63 int nBuf; > 64 int nAlloc; > 65 }; > 66 > 67 /* > 68 ** This function is the implementation of both the xConnect and xCreate > 69 ** methods of the fs virtual table. > 70 ** > 71 ** The argv[] array contains the following: > 72 ** > 73 ** argv[0] -> module name ("fs") > 74 ** argv[1] -> database name > 75 ** argv[2] -> table name > 76 ** argv[...] -> other module argument fields. > 77 */ > 78 static int fsConnect( > 79 sqlite3 *db, > 80 void *pAux, > 81 int argc, const char *const*argv, > 82 sqlite3_vtab **ppVtab, > 83 char **pzErr > 84 ){ > 85 fs_vtab *pVtab; > 86 int nByte; > 87 const char *zTbl; > 88 const char *zDb = argv[1]; > 89 > 90 if( argc!=4 ){ > 91 *pzErr = sqlite3_mprintf("wrong number of arguments"); > 92 return SQLITE_ERROR; > 93 } > 94 zTbl = argv[3]; > 95 > 96 nByte = sizeof(fs_vtab) + strlen(zTbl) + 1 + strlen(zDb) + 1; > 97 pVtab = (fs_vtab *)sqlite3MallocZero( nByte ); > 98 if( !pVtab ) return SQLITE_NOMEM; > 99 > 100 pVtab->zTbl = (char *)&pVtab[1]; > 101 pVtab->zDb = &pVtab->zTbl[strlen(zTbl)+1]; > 102 pVtab->db = db; > 103 memcpy(pVtab->zTbl, zTbl, strlen(zTbl)); > 104 memcpy(pVtab->zDb, zDb, strlen(zDb)); > 105 *ppVtab = &pVtab->base; > 106 sqlite3_declare_vtab(db, "CREATE TABLE xyz(path TEXT, data TEXT)"); > 107 > 108 return SQLITE_OK; > 109 } > 110 /* Note that for this virtual table, the xCreate and xConnect > 111 ** methods are identical. */ > 112 > 113 static int fsDisconnect(sqlite3_vtab *pVtab){ > 114 sqlite3_free(pVtab); > 115 return SQLITE_OK; > 116 } > 117 /* The xDisconnect and xDestroy methods are also the same */ > 118 > 119 /* > 120 ** Open a new fs cursor. > 121 */ > 122 static int fsOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ > 123 fs_cursor *pCur; > 124 pCur = sqlite3MallocZero(sizeof(fs_cursor)); > 125 *ppCursor = &pCur->base; > 126 return SQLITE_OK; > 127 } > 128 > 129 /* > 130 ** Close a fs cursor. > 131 */ > 132 static int fsClose(sqlite3_vtab_cursor *cur){ > 133 fs_cursor *pCur = (fs_cursor *)cur; > 134 sqlite3_finalize(pCur->pStmt); > 135 sqlite3_free(pCur->zBuf); > 136 sqlite3_free(pCur); > 137 return SQLITE_OK; > 138 } > 139 > 140 static int fsNext(sqlite3_vtab_cursor *cur){ > 141 fs_cursor *pCur = (fs_cursor *)cur; > 142 int rc; > 143 > 144 rc = sqlite3_step(pCur->pStmt); > 145 if( rc==SQLITE_ROW || rc==SQLITE_DONE ) rc = SQLITE_OK; > 146 > 147 return rc; > 148 } > 149 > 150 static int fsFilter( > 151 sqlite3_vtab_cursor *pVtabCursor, > 152 int idxNum, const char *idxStr, > 153 int argc, sqlite3_value **argv > 154 ){ > 155 int rc; > 156 fs_cursor *pCur = (fs_cursor *)pVtabCursor; > 157 fs_vtab *p = (fs_vtab *)(pVtabCursor->pVtab); > 158 > 159 assert( (idxNum==0 && argc==0) || (idxNum==1 && argc==1) ); > 160 if( idxNum==1 ){ > 161 char *zStmt = sqlite3_mprintf( > 162 "SELECT * FROM %Q.%Q WHERE rowid=?", p->zDb, p->zTbl); > 163 if( !zStmt ) return SQLITE_NOMEM; > 164 rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0); > 165 sqlite3_free(zStmt); > 166 if( rc==SQLITE_OK ){ > 167 sqlite3_bind_value(pCur->pStmt, 1, argv[0]); > 168 } > 169 }else{ > 170 char *zStmt = sqlite3_mprintf("SELECT * FROM %Q.%Q", p->zDb, p->zTbl); > 171 if( !zStmt ) return SQLITE_NOMEM; > 172 rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0); > 173 sqlite3_free(zStmt); > 174 } > 175 > 176 if( rc==SQLITE_OK ){ > 177 rc = fsNext(pVtabCursor); > 178 } > 179 return rc; > 180 } > 181 > 182 static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ > 183 fs_cursor *pCur = (fs_cursor*)cur; > 184 > 185 assert( i==0 || i==1 ); > 186 if( i==0 ){ > 187 sqlite3_result_value(ctx, sqlite3_column_value(pCur->pStmt, 0)); > 188 }else{ > 189 const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1); > 190 struct stat sbuf; > 191 int fd; > 192 > 193 fd = open(zFile, O_RDONLY); > 194 if( fd<0 ) return SQLITE_IOERR; > 195 fstat(fd, &sbuf); > 196 > 197 if( sbuf.st_size>=pCur->nAlloc ){ > 198 int nNew = sbuf.st_size*2; > 199 char *zNew; > 200 if( nNew<1024 ) nNew = 1024; > 201 > 202 zNew = sqlite3Realloc(pCur->zBuf, nNew); > 203 if( zNew==0 ){ > 204 close(fd); > 205 return SQLITE_NOMEM; > 206 } > 207 pCur->zBuf = zNew; > 208 pCur->nAlloc = nNew; > 209 } > 210 > 211 read(fd, pCur->zBuf, sbuf.st_size); > 212 close(fd); > 213 pCur->nBuf = sbuf.st_size; > 214 pCur->zBuf[pCur->nBuf] = '\0'; > 215 > 216 sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT); > 217 } > 218 return SQLITE_OK; > 219 } > 220 > 221 static int fsRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ > 222 fs_cursor *pCur = (fs_cursor*)cur; > 223 *pRowid = sqlite3_column_int64(pCur->pStmt, 0); > 224 return SQLITE_OK; > 225 } > 226 > 227 static int fsEof(sqlite3_vtab_cursor *cur){ > 228 fs_cursor *pCur = (fs_cursor*)cur; > 229 return (sqlite3_data_count(pCur->pStmt)==0); > 230 } > 231 > 232 static int fsBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ > 233 int ii; > 234 > 235 for(ii=0; ii<pIdxInfo->nConstraint; ii++){ > 236 struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; > 237 if( pCons->iColumn<0 && pCons->usable > 238 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ > 239 struct sqlite3_index_constraint_usage *pUsage; > 240 pUsage = &pIdxInfo->aConstraintUsage[ii]; > 241 pUsage->omit = 0; > 242 pUsage->argvIndex = 1; > 243 pIdxInfo->idxNum = 1; > 244 pIdxInfo->estimatedCost = 1.0; > 245 break; > 246 } > 247 } > 248 > 249 return SQLITE_OK; > 250 } > 251 > 252 /* > 253 ** A virtual table module that provides read-only access to a > 254 ** Tcl global variable namespace. > 255 */ > 256 static sqlite3_module fsModule = { > 257 0, /* iVersion */ > 258 fsConnect, > 259 fsConnect, > 260 fsBestIndex, > 261 fsDisconnect, > 262 fsDisconnect, > 263 fsOpen, /* xOpen - open a cursor */ > 264 fsClose, /* xClose - close a cursor */ > 265 fsFilter, /* xFilter - configure scan constraints */ > 266 fsNext, /* xNext - advance a cursor */ > 267 fsEof, /* xEof - check for end of scan */ > 268 fsColumn, /* xColumn - read data */ > 269 fsRowid, /* xRowid - read data */ > 270 0, /* xUpdate */ > 271 0, /* xBegin */ > 272 0, /* xSync */ > 273 0, /* xCommit */ > 274 0, /* xRollback */ > 275 0, /* xFindMethod */ > 276 0, /* xRename */ > 277 }; > 278 > 279 /* > 280 ** Decode a pointer to an sqlite3 object. > 281 */ > 282 extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); > 283 > 284 /* > 285 ** Register the echo virtual table module. > 286 */ > 287 static int register_fs_module( > 288 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ > 289 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ > 290 int objc, /* Number of arguments */ > 291 Tcl_Obj *CONST objv[] /* Command arguments */ > 292 ){ > 293 sqlite3 *db; > 294 if( objc!=2 ){ > 295 Tcl_WrongNumArgs(interp, 1, objv, "DB"); > 296 return TCL_ERROR; > 297 } > 298 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; > 299 #ifndef SQLITE_OMIT_VIRTUALTABLE > 300 sqlite3_create_module(db, "fs", &fsModule, (void *)interp); > 301 #endif > 302 return TCL_OK; > 303 } > 304 > 305 #endif > 306 > 307 > 308 /* > 309 ** Register commands with the TCL interpreter. > 310 */ > 311 int Sqlitetestfs_Init(Tcl_Interp *interp){ > 312 #ifndef SQLITE_OMIT_VIRTUALTABLE > 313 static struct { > 314 char *zName; > 315 Tcl_ObjCmdProc *xProc; > 316 void *clientData; > 317 } aObjCmd[] = { > 318 { "register_fs_module", register_fs_module, 0 }, > 319 }; > 320 int i; > 321 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ > 322 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, > 323 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); > 324 } > 325 #endif > 326 return TCL_OK; > 327 }

Changes to test/fts4content.test

557 557 558 do_execsql_test 9.6 { 558 do_execsql_test 9.6 { 559 INSERT INTO ft1(ft1) VALUES('rebuild'); 559 INSERT INTO ft1(ft1) VALUES('rebuild'); 560 SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a' 560 SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a' 561 } {1 {a b} {c d} 2 {e f} {a b}} 561 } {1 {a b} {c d} 2 {e f} {a b}} 562 562 563 563 > 564 #------------------------------------------------------------------------- > 565 # Test cases 10.* 564 | 566 # > 567 reset_db > 568 register_fs_module [sqlite3_connection_pointer db] > 569 > 570 proc write_file {path text} { > 571 set fd [open $path w] > 572 puts -nonewline $fd $text > 573 close $fd > 574 } > 575 > 576 write_file t1.txt {a b c d e f g h i j k l m n o p q r s t u v w x y z} > 577 write_file t2.txt {a b c d e f g h i j k l m a b c d e f g h i j k l m} > 578 write_file t3.txt {n o p q r s t u v w x y z n o p q r s t u v w x y z} > 579 > 580 do_execsql_test 10.1 { > 581 CREATE TABLE idx(id INTEGER PRIMARY KEY, path TEXT); > 582 INSERT INTO idx VALUES (1, 't1.txt'); > 583 INSERT INTO idx VALUES (2, 't2.txt'); > 584 INSERT INTO idx VALUES (3, 't3.txt'); > 585 > 586 CREATE VIRTUAL TABLE vt USING fs(idx); > 587 SELECT * FROM vt; > 588 } { > 589 1 {a b c d e f g h i j k l m n o p q r s t u v w x y z} > 590 2 {a b c d e f g h i j k l m a b c d e f g h i j k l m} > 591 3 {n o p q r s t u v w x y z n o p q r s t u v w x y z} > 592 } > 593 > 594 do_execsql_test 10.2 { > 595 SELECT * FROM vt WHERE rowid = 2; > 596 } { > 597 2 {a b c d e f g h i j k l m a b c d e f g h i j k l m} > 598 } > 599 > 600 do_execsql_test 10.3 { > 601 CREATE VIRTUAL TABLE ft USING fts4(content=vt); > 602 INSERT INTO ft(ft) VALUES('rebuild'); > 603 } > 604 > 605 do_execsql_test 10.4 { > 606 SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 'e' > 607 } { > 608 {...c d [e] f g...} {...c d [e] f g...} > 609 } > 610 > 611 do_execsql_test 10.5 { > 612 SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 't' > 613 } { > 614 {...r s [t] u v...} {...r s [t] u v...} > 615 } > 616 > 617 do_execsql_test 10.6 { DELETE FROM ft WHERE docid=2 } > 618 > 619 do_execsql_test 10.7 { > 620 SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 'e' > 621 } { > 622 {...c d [e] f g...} > 623 } > 624 565 finish_test 625 finish_test > 626