]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add another test for the fts4 content= option.
authordan <dan@noemail.net>
Fri, 11 Jan 2013 09:58:54 +0000 (09:58 +0000)
committerdan <dan@noemail.net>
Fri, 11 Jan 2013 09:58:54 +0000 (09:58 +0000)
FossilOrigin-Name: 7e6007a0002f6989bd489abeba8db52acb4a6854

main.mk
manifest
manifest.uuid
src/tclsqlite.c
src/test_fs.c [new file with mode: 0644]
test/fts4content.test

diff --git a/main.mk b/main.mk
index fdabcb4636e5b4b649722c612ff42d5193a4436a..2430d3ffe9d9d56a21f5d01e9d64b247e3497132 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -240,6 +240,7 @@ TESTSRC = \
   $(TOP)/src/test_config.c \
   $(TOP)/src/test_demovfs.c \
   $(TOP)/src/test_devsym.c \
+  $(TOP)/src/test_fs.c \
   $(TOP)/src/test_func.c \
   $(TOP)/src/test_fuzzer.c \
   $(TOP)/src/test_hexio.c \
index 10fec36728e213595417473a42cac00461233b7e..e4306e9a89ff8677770becfbd8edaa3bcd5815f7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Check\sin\san\sextra\stest\sfor\sthe\sfts4\s"content="\soption.\sNo\scode\schanges.
-D 2013-01-09T15:44:23.023
+C Add\sanother\stest\sfor\sthe\sfts4\scontent=\soption.
+D 2013-01-11T09:58:54.381
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -103,7 +103,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
-F main.mk 718265bbf49a846c6898b4da09593eef4068fa39
+F main.mk 404cd38114d1a94ef6ad5aa01a1c8bb46da36161
 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
 F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@@ -183,7 +183,7 @@ F src/sqliteInt.h e998703742455b2241731424c6ec142fd8d0258f
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
-F src/tclsqlite.c 5203bb7b71a302bea8896f176cd178e38d7803a4
+F src/tclsqlite.c 3213f3101e3b85f047d6e389da5a53d76d3d7540
 F src/test1.c f62769c989146149590662ab02de4a813813a9c5
 F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
 F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
@@ -200,6 +200,7 @@ F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
 F src/test_config.c 09781397ccc24268cb895be0d4c21b4aad651486
 F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
+F src/test_fs.c 7d3337933e92c198d06dd600375cc39259cc66b3
 F src/test_func.c 3a8dd37c08ab43b76d38eea2836e34a3897bf170
 F src/test_fuzzer.c 1d26aa965120420bc14807da29d4d4541bfa6148
 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
@@ -500,7 +501,7 @@ F test/fts3snippet.test 8e956051221a34c7daeb504f023cb54d5fa5a8b2
 F test/fts3sort.test 95be0b19d7e41c44b29014f13ea8bddd495fd659
 F test/fts4aa.test 95f448fb02c4a976968b08d1b4ce134e720946ae
 F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
-F test/fts4content.test b8032a15a6cd91df41cf6f335167e02b4a037ed5
+F test/fts4content.test 6efc53b4fd03cab167e6998d2b0b7d4b7d419ee6
 F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
 F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
 F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
@@ -1032,7 +1033,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 5774f2175ce621dfc4b6b93f7ee13fd66f3ec2b9
-R 55e61a393f7fda758ca2247ac64f35c5
+P 0d0e5ab8f16c890629ec1120c78168ef6be9e419
+R 8314e970c84b41ce51cf4e3af788943a
 U dan
-Z 742a4d1e5d57ee15d6514285ba4dd6df
+Z af1374dc5de33897a8a4ab326451d45f
index 562f951683dd6aa42cc3a5aa6fbf5584c461feb3..909c82e7f359788c7c07f0e64f60af2f3a57b15c 100644 (file)
@@ -1 +1 @@
-0d0e5ab8f16c890629ec1120c78168ef6be9e419
\ No newline at end of file
+7e6007a0002f6989bd489abeba8db52acb4a6854
\ No newline at end of file
index 267f759701664ed460d17975104c812b43e511a9..2777d2f9f8b52644c7059fcb167a4de51f569fa8 100644 (file)
@@ -3671,6 +3671,7 @@ static void init_all(Tcl_Interp *interp){
     extern int Sqlitetestschema_Init(Tcl_Interp*);
     extern int Sqlitetestsse_Init(Tcl_Interp*);
     extern int Sqlitetesttclvar_Init(Tcl_Interp*);
+    extern int Sqlitetestfs_Init(Tcl_Interp*);
     extern int SqlitetestThread_Init(Tcl_Interp*);
     extern int SqlitetestOnefile_Init();
     extern int SqlitetestOsinst_Init(Tcl_Interp*);
@@ -3715,6 +3716,7 @@ static void init_all(Tcl_Interp *interp){
     Sqlitetest_mutex_Init(interp);
     Sqlitetestschema_Init(interp);
     Sqlitetesttclvar_Init(interp);
+    Sqlitetestfs_Init(interp);
     SqlitetestThread_Init(interp);
     SqlitetestOnefile_Init(interp);
     SqlitetestOsinst_Init(interp);
diff --git a/src/test_fs.c b/src/test_fs.c
new file mode 100644 (file)
index 0000000..9678005
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+** 2013 Jan 11
+**
+** 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.
+**
+*************************************************************************
+** Code for testing the virtual table interfaces.  This code
+** is not included in the SQLite library.  It is used for automated
+** testing of the SQLite library.
+**
+** The FS virtual table is created as follows:
+**
+**   CREATE VIRTUAL TABLE tbl USING fs(idx);
+**
+** where idx is the name of a table in the db with 2 columns.  The virtual
+** table also has two columns - file path and file contents.
+**
+** The first column of table idx must be an IPK, and the second contains file
+** paths. For example:
+**
+**   CREATE TABLE idx(id INTEGER PRIMARY KEY, path TEXT);
+**   INSERT INTO idx VALUES(4, '/etc/passwd');
+**
+** Adding the row to the idx table automatically creates a row in the 
+** virtual table with rowid=4, path=/etc/passwd and a text field that 
+** contains data read from file /etc/passwd on disk.
+*/
+#include "sqliteInt.h"
+#include "tcl.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+typedef struct fs_vtab fs_vtab;
+typedef struct fs_cursor fs_cursor;
+
+/* 
+** A fs virtual-table object 
+*/
+struct fs_vtab {
+  sqlite3_vtab base;
+  sqlite3 *db;
+  char *zDb;                      /* Name of db containing zTbl */
+  char *zTbl;                     /* Name of docid->file map table */
+};
+
+/* A fs cursor object */
+struct fs_cursor {
+  sqlite3_vtab_cursor base;
+  sqlite3_stmt *pStmt;
+  char *zBuf;
+  int nBuf;
+  int nAlloc;
+};
+
+/*
+** This function is the implementation of both the xConnect and xCreate
+** methods of the fs virtual table.
+**
+** The argv[] array contains the following:
+**
+**   argv[0]   -> module name  ("fs")
+**   argv[1]   -> database name
+**   argv[2]   -> table name
+**   argv[...] -> other module argument fields.
+*/
+static int fsConnect(
+  sqlite3 *db,
+  void *pAux,
+  int argc, const char *const*argv,
+  sqlite3_vtab **ppVtab,
+  char **pzErr
+){
+  fs_vtab *pVtab;
+  int nByte;
+  const char *zTbl;
+  const char *zDb = argv[1];
+
+  if( argc!=4 ){
+    *pzErr = sqlite3_mprintf("wrong number of arguments");
+    return SQLITE_ERROR;
+  }
+  zTbl = argv[3];
+
+  nByte = sizeof(fs_vtab) + strlen(zTbl) + 1 + strlen(zDb) + 1;
+  pVtab = (fs_vtab *)sqlite3MallocZero( nByte );
+  if( !pVtab ) return SQLITE_NOMEM;
+
+  pVtab->zTbl = (char *)&pVtab[1];
+  pVtab->zDb = &pVtab->zTbl[strlen(zTbl)+1];
+  pVtab->db = db;
+  memcpy(pVtab->zTbl, zTbl, strlen(zTbl));
+  memcpy(pVtab->zDb, zDb, strlen(zDb));
+  *ppVtab = &pVtab->base;
+  sqlite3_declare_vtab(db, "CREATE TABLE xyz(path TEXT, data TEXT)");
+
+  return SQLITE_OK;
+}
+/* Note that for this virtual table, the xCreate and xConnect
+** methods are identical. */
+
+static int fsDisconnect(sqlite3_vtab *pVtab){
+  sqlite3_free(pVtab);
+  return SQLITE_OK;
+}
+/* The xDisconnect and xDestroy methods are also the same */
+
+/*
+** Open a new fs cursor.
+*/
+static int fsOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
+  fs_cursor *pCur;
+  pCur = sqlite3MallocZero(sizeof(fs_cursor));
+  *ppCursor = &pCur->base;
+  return SQLITE_OK;
+}
+
+/*
+** Close a fs cursor.
+*/
+static int fsClose(sqlite3_vtab_cursor *cur){
+  fs_cursor *pCur = (fs_cursor *)cur;
+  sqlite3_finalize(pCur->pStmt);
+  sqlite3_free(pCur->zBuf);
+  sqlite3_free(pCur);
+  return SQLITE_OK;
+}
+
+static int fsNext(sqlite3_vtab_cursor *cur){
+  fs_cursor *pCur = (fs_cursor *)cur;
+  int rc;
+
+  rc = sqlite3_step(pCur->pStmt);
+  if( rc==SQLITE_ROW || rc==SQLITE_DONE ) rc = SQLITE_OK;
+
+  return rc;
+}
+
+static int fsFilter(
+  sqlite3_vtab_cursor *pVtabCursor, 
+  int idxNum, const char *idxStr,
+  int argc, sqlite3_value **argv
+){
+  int rc;
+  fs_cursor *pCur = (fs_cursor *)pVtabCursor;
+  fs_vtab *p = (fs_vtab *)(pVtabCursor->pVtab);
+
+  assert( (idxNum==0 && argc==0) || (idxNum==1 && argc==1) );
+  if( idxNum==1 ){
+    char *zStmt = sqlite3_mprintf(
+        "SELECT * FROM %Q.%Q WHERE rowid=?", p->zDb, p->zTbl);
+    if( !zStmt ) return SQLITE_NOMEM;
+    rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0);
+    sqlite3_free(zStmt);
+    if( rc==SQLITE_OK ){
+      sqlite3_bind_value(pCur->pStmt, 1, argv[0]);
+    }
+  }else{
+    char *zStmt = sqlite3_mprintf("SELECT * FROM %Q.%Q", p->zDb, p->zTbl);
+    if( !zStmt ) return SQLITE_NOMEM;
+    rc = sqlite3_prepare_v2(p->db, zStmt, -1, &pCur->pStmt, 0);
+    sqlite3_free(zStmt);
+  }
+
+  if( rc==SQLITE_OK ){
+    rc = fsNext(pVtabCursor); 
+  }
+  return rc;
+}
+
+static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
+  fs_cursor *pCur = (fs_cursor*)cur;
+
+  assert( i==0 || i==1 );
+  if( i==0 ){
+    sqlite3_result_value(ctx, sqlite3_column_value(pCur->pStmt, 0));
+  }else{
+    const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1);
+    struct stat sbuf;
+    int fd;
+
+    fd = open(zFile, O_RDONLY);
+    if( fd<0 ) return SQLITE_IOERR;
+    fstat(fd, &sbuf);
+
+    if( sbuf.st_size>=pCur->nAlloc ){
+      int nNew = sbuf.st_size*2;
+      char *zNew;
+      if( nNew<1024 ) nNew = 1024;
+
+      zNew = sqlite3Realloc(pCur->zBuf, nNew);
+      if( zNew==0 ){
+        close(fd);
+        return SQLITE_NOMEM;
+      }
+      pCur->zBuf = zNew;
+      pCur->nAlloc = nNew;
+    }
+
+    read(fd, pCur->zBuf, sbuf.st_size);
+    close(fd);
+    pCur->nBuf = sbuf.st_size;
+    pCur->zBuf[pCur->nBuf] = '\0';
+
+    sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT);
+  }
+  return SQLITE_OK;
+}
+
+static int fsRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+  fs_cursor *pCur = (fs_cursor*)cur;
+  *pRowid = sqlite3_column_int64(pCur->pStmt, 0);
+  return SQLITE_OK;
+}
+
+static int fsEof(sqlite3_vtab_cursor *cur){
+  fs_cursor *pCur = (fs_cursor*)cur;
+  return (sqlite3_data_count(pCur->pStmt)==0);
+}
+
+static int fsBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+  int ii;
+
+  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
+    struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
+    if( pCons->iColumn<0 && pCons->usable
+           && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+      struct sqlite3_index_constraint_usage *pUsage;
+      pUsage = &pIdxInfo->aConstraintUsage[ii];
+      pUsage->omit = 0;
+      pUsage->argvIndex = 1;
+      pIdxInfo->idxNum = 1;
+      pIdxInfo->estimatedCost = 1.0;
+      break;
+    }
+  }
+
+  return SQLITE_OK;
+}
+
+/*
+** A virtual table module that provides read-only access to a
+** Tcl global variable namespace.
+*/
+static sqlite3_module fsModule = {
+  0,                         /* iVersion */
+  fsConnect,
+  fsConnect,
+  fsBestIndex,
+  fsDisconnect, 
+  fsDisconnect,
+  fsOpen,                      /* xOpen - open a cursor */
+  fsClose,                     /* xClose - close a cursor */
+  fsFilter,                    /* xFilter - configure scan constraints */
+  fsNext,                      /* xNext - advance a cursor */
+  fsEof,                       /* xEof - check for end of scan */
+  fsColumn,                    /* xColumn - read data */
+  fsRowid,                     /* xRowid - read data */
+  0,                           /* xUpdate */
+  0,                           /* xBegin */
+  0,                           /* xSync */
+  0,                           /* xCommit */
+  0,                           /* xRollback */
+  0,                           /* xFindMethod */
+  0,                           /* xRename */
+};
+
+/*
+** Decode a pointer to an sqlite3 object.
+*/
+extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
+
+/*
+** Register the echo virtual table module.
+*/
+static int register_fs_module(
+  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int objc,              /* Number of arguments */
+  Tcl_Obj *CONST objv[]  /* Command arguments */
+){
+  sqlite3 *db;
+  if( objc!=2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB");
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+  sqlite3_create_module(db, "fs", &fsModule, (void *)interp);
+#endif
+  return TCL_OK;
+}
+
+#endif
+
+
+/*
+** Register commands with the TCL interpreter.
+*/
+int Sqlitetestfs_Init(Tcl_Interp *interp){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+  static struct {
+     char *zName;
+     Tcl_ObjCmdProc *xProc;
+     void *clientData;
+  } aObjCmd[] = {
+     { "register_fs_module",   register_fs_module, 0 },
+  };
+  int i;
+  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
+    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
+        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
+  }
+#endif
+  return TCL_OK;
+}
index 1b25e0818f8eaa618cf669dd20f12c34cf72906e..302f14e51096e014917a8b5d06568572b2913979 100644 (file)
@@ -561,5 +561,66 @@ do_execsql_test 9.6 {
 } {1 {a b} {c d} 2 {e f} {a b}}
 
 
+#-------------------------------------------------------------------------
+# Test cases 10.*
+# 
+reset_db
+register_fs_module [sqlite3_connection_pointer db]
+
+proc write_file {path text} {
+  set fd [open $path w]
+  puts -nonewline $fd $text
+  close $fd
+}
+
+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}
+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}
+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}
+
+do_execsql_test 10.1 {
+  CREATE TABLE idx(id INTEGER PRIMARY KEY, path TEXT);
+  INSERT INTO idx VALUES (1, 't1.txt');
+  INSERT INTO idx VALUES (2, 't2.txt');
+  INSERT INTO idx VALUES (3, 't3.txt');
+
+  CREATE VIRTUAL TABLE vt USING fs(idx);
+  SELECT * FROM vt;
+} {
+  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} 
+  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}
+  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}
+}
+
+do_execsql_test 10.2 {
+  SELECT * FROM vt WHERE rowid = 2;
+} {
+  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}
+}
+
+do_execsql_test 10.3 {
+  CREATE VIRTUAL TABLE ft USING fts4(content=vt);
+  INSERT INTO ft(ft) VALUES('rebuild');
+}
+
+do_execsql_test 10.4 {
+  SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 'e'
+} {
+  {...c d [e] f g...} {...c d [e] f g...}
+}
+
+do_execsql_test 10.5 {
+  SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 't'
+} {
+  {...r s [t] u v...} {...r s [t] u v...}
+}
+
+do_execsql_test 10.6 { DELETE FROM ft WHERE docid=2 }
+
+do_execsql_test 10.7 {
+  SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 'e'
+} {
+  {...c d [e] f g...}
+}
 
 finish_test
+