]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further fts3 coverage tests.
authordan <dan@noemail.net>
Sat, 12 Dec 2009 16:04:32 +0000 (16:04 +0000)
committerdan <dan@noemail.net>
Sat, 12 Dec 2009 16:04:32 +0000 (16:04 +0000)
FossilOrigin-Name: d2a8c0f683271f5fb8c9badfb13e4e46fd78db71

ext/fts3/fts3_write.c
manifest
manifest.uuid
test/fts3cov.test

index 1f82e61d31a84dff9bc423fc3ecdf1df92d4bcf6..1a48f385e0aef78585b02b585f0a9ef17b9884b8 100644 (file)
@@ -1959,7 +1959,8 @@ int sqlite3Fts3SegReaderIterate(
       nMerge++;
     }
 
-    if( nMerge==1 && !isIgnoreEmpty && !isColFilter && isRequirePos ){
+    assert( isIgnoreEmpty==0 || (isRequirePos && isColFilter==0) );
+    if( nMerge==1 && !isIgnoreEmpty ){
       Fts3SegReader *p0 = apSegment[0];
       rc = xFunc(p, pContext, zTerm, nTerm, p0->aDoclist, p0->nDoclist);
       if( rc!=SQLITE_OK ) goto finished;
@@ -2061,7 +2062,7 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
   int rc;                         /* Return code */
   int iIdx;                       /* Index of new segment */
   int iNewLevel;                  /* Level to create new segment at */
-  sqlite3_stmt *pStmt;
+  sqlite3_stmt *pStmt = 0;
   SegmentWriter *pWriter = 0;
   int nSegment = 0;               /* Number of segments being merged */
   Fts3SegReader **apSegment = 0;  /* Array of Segment iterators */
@@ -2074,12 +2075,11 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
     ** greatest segment level currently present in the database. The index
     ** of the new segment is always 0.
     */
-    rc = sqlite3Fts3SegReaderPending(p, 0, 0, 1, &pPending);
-    if( rc!=SQLITE_OK ){
-      return rc;
-    }
     iIdx = 0;
+    rc = sqlite3Fts3SegReaderPending(p, 0, 0, 1, &pPending);
+    if( rc!=SQLITE_OK ) goto finished;
     rc = fts3SegmentCountMax(p, &nSegment, &iNewLevel);
+    if( rc!=SQLITE_OK ) goto finished;
     nSegment += (pPending!=0);
     if( nSegment<=1 ){
       return SQLITE_DONE;
@@ -2092,17 +2092,18 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
     */
     iNewLevel = iLevel+1;
     rc = fts3AllocateSegdirIdx(p, iNewLevel, &iIdx);
-    if( rc!=SQLITE_OK ) return rc;
+    if( rc!=SQLITE_OK ) goto finished;
     rc = fts3SegmentCount(p, iLevel, &nSegment);
+    if( rc!=SQLITE_OK ) goto finished;
   }
-  if( rc!=SQLITE_OK ) return rc;
   assert( nSegment>0 );
   assert( iNewLevel>=0 );
 
   /* Allocate space for an array of pointers to segment iterators. */
   apSegment = (Fts3SegReader**)sqlite3_malloc(sizeof(Fts3SegReader *)*nSegment);
   if( !apSegment ){
-    return SQLITE_NOMEM;
+    rc = SQLITE_NOMEM;
+    goto finished;
   }
   memset(apSegment, 0, sizeof(Fts3SegReader *)*nSegment);
 
@@ -2123,6 +2124,7 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
   rc = sqlite3_reset(pStmt);
   if( pPending ){
     apSegment[i] = pPending;
+    pPending = 0;
   }
   pStmt = 0;
   if( rc!=SQLITE_OK ) goto finished;
@@ -2148,6 +2150,7 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
     }
     sqlite3_free(apSegment);
   }
+  sqlite3Fts3SegReaderFree(p, pPending);
   sqlite3_reset(pStmt);
   return rc;
 }
index a3d53d0ec83f987adbfc828f62e2e8e937069967..7355ac2e41973717a57dff7ef0350805983f5a91 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,5 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Rename\stkt-d82e3f3721.txt\sto\suse\sthe\s(correct)\s.test\ssuffix.
-D 2009-12-12T13:58:19
+C Further\sfts3\scoverage\stests.
+D 2009-12-12T16:04:32
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -71,7 +68,7 @@ F ext/fts3/fts3_snippet.c 6c2eb6d872d66b2a9aa5663f2662e993f18a6496
 F ext/fts3/fts3_tokenizer.c 1a49ee3d79cbf0b9386250370d9cbfe4bb89c8ff
 F ext/fts3/fts3_tokenizer.h 7ff73caa3327589bf6550f60d93ebdd1f6a0fb5c
 F ext/fts3/fts3_tokenizer1.c 11a604a53cff5e8c28882727bf794e5252e5227b
-F ext/fts3/fts3_write.c 8fa73906993c46d1add03367d658b4b2f2214bb8
+F ext/fts3/fts3_write.c c2e0ef39df121b291fda42992ef1387f7938dea1
 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
 F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
 F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
@@ -399,7 +396,7 @@ F test/fts3ao.test 0aa29dd4fc1c8d46b1f7cfe5926f7ac97551bea9
 F test/fts3atoken.test 25c2070e1e8755d414bf9c8200427b277a9f99fa
 F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
-F test/fts3cov.test ce49852ac727c74cfce8e5a4cc017c7edfab7b7e
+F test/fts3cov.test f2d27d29628941e4814473345603b20421b93c78
 F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
 F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
 F test/fts3expr.test 05dab77387801e4900009917bb18f556037d82da
@@ -782,14 +779,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P eee921a99e69a9cd868a89de620bf47c4e26e4b5
-R 5d65e226c3987e06982591864693cc96
-U drh
-Z b6b0937ebc754fff562e435d0e81894c
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFLI6F/oxKgR168RlERAv3/AKCGxXDpk/BocjexCfeSDuJTQRc0JwCeOdSJ
-ZSbD17MSKkOO16NEgcCVaWk=
-=0ws+
------END PGP SIGNATURE-----
+P 68cccd62b71f7b55bf7f2f56dc8507cbe80229ba
+R 24dafc1291b25c037b068505da647d63
+U dan
+Z f50ab64261ebba22ef3131cb9e897960
index 35de3d6e5c29c68e0a25d4e738c15390badc3631..521448761d4c1cc0d4e94414e210b86b2a939fbc 100644 (file)
@@ -1 +1 @@
-68cccd62b71f7b55bf7f2f56dc8507cbe80229ba
\ No newline at end of file
+d2a8c0f683271f5fb8c9badfb13e4e46fd78db71
\ No newline at end of file
index 8537afdc8201bc057461f084214ebb49a0cc0da9..dab208bd543d47c77fa2c11e2ad5fe1c58ddb85d 100644 (file)
@@ -18,6 +18,7 @@ source $testdir/tester.tcl
 #
 ifcapable !fts3 { finish_test ; return }
 source $testdir/fts3_common.tcl
+source $testdir/malloc_common.tcl
 
 set DO_MALLOC_TEST 0
 
@@ -173,6 +174,12 @@ do_write_test fts3cov-4.2 t3_content {
 # by inserting insert a document with some fairly large terms into a
 # full-text table with a very small node-size. 
 #
+# Test this handling of large terms in three contexts:
+#
+#   1. When flushing the pending-terms table.
+#   2. When optimizing the data structures using the INSERT syntax. 
+#   2. When optimizing the data structures using the deprecated SELECT syntax. 
+#
 do_test fts3cov-5.1 {
   execsql {
     CREATE VIRTUAL TABLE t4 USING fts3(x);
@@ -180,6 +187,8 @@ do_test fts3cov-5.1 {
   }
 } {}
 set DO_MALLOC_TEST 1
+
+# Test when flushing pending-terms table.
 do_write_test fts3cov-5.2 t4_content {
   INSERT INTO t4
     SELECT 'ItisanancientMarinerAndhestoppethoneofthreeAA' UNION ALL
@@ -189,14 +198,155 @@ do_write_test fts3cov-5.2 t4_content {
     SELECT 'BythylonggreybeardandglitteringeyeNowwhereforestoppstBB' UNION ALL
     SELECT 'BythylonggreybeardandglitteringeyeNowwhereforestoppstCC'
 }
-do_test fts3cov-5.3 {
-  execsql { INSERT INTO t4 VALUES('extra!') }
-} {}
-do_write_test fts3cov-5.2 t4_segments {
-  INSERT INTO t4(t4) VALUES('optimize')
+
+# Test when optimizing via INSERT.
+do_test fts3cov-5.3 { execsql { INSERT INTO t4 VALUES('extra!') } } {}
+do_write_test fts3cov-5.2 t4_segments { INSERT INTO t4(t4) VALUES('optimize') }
+
+# Test when optimizing via SELECT.
+do_test fts3cov-5.5 { execsql { INSERT INTO t4 VALUES('more extra!') } } {}
+do_write_test fts3cov-5.6 t4_segments {
+  SELECT * FROM (SELECT optimize(t4) FROM t4 LIMIT 1)
+  EXCEPT SELECT 'Index optimized'
+}
+
+#-------------------------------------------------------------------------
+# When merging all segments at a given level to create a single segment
+# at level+1, FTS3 runs a query of the form:
+#
+#   SELECT count(*) FROM %_segdir WHERE level = ?
+#
+# The query is compiled the first time this operation is required and
+# reused thereafter. This test aims to test the effects of an OOM while
+# preparing and executing this query for the first time.
+#
+# Then, keep inserting rows into the table so that the effects of an OOM
+# while re-executing the same query can also be tested.
+#
+do_test fts3cov-6.1 {
+  execsql { CREATE VIRTUAL TABLE t5 USING fts3(x) }
+  for {set i 0} {$i<16} {incr i} { execsql "INSERT INTO t5 VALUES('term$i')" }
+  execsql { SELECT count(*) FROM t5_segdir }
+} {16}
+
+# First time.
+db close
+sqlite3 db test.db
+do_write_test fts3cov-6.2 t5_content {
+  INSERT INTO t5 VALUES('segment number 16!');
+}
+
+# Second time.
+do_test fts3cov-6.3 {
+  for {set i 1} {$i<16} {incr i} { execsql "INSERT INTO t5 VALUES('term$i')" }
+  execsql { SELECT count(*) FROM t5_segdir }
+} {17}
+do_write_test fts3cov-6.4 t5_content {
+  INSERT INTO t5 VALUES('segment number 16!');
+}
+
+#-------------------------------------------------------------------------
+# Update the docid of a row. Test this in two scenarios:
+#
+#   1. When the row being updated is the only row in the table.
+#   2. When it is not.
+#
+# The two cases above take different paths because in case 1 all data 
+# structures can simply be emptied before inserting the new row record.
+# In case 2, the data structures actually have to be updated.
+#
+do_test fts3cov-7.1 {
+  execsql {
+    CREATE VIRTUAL TABLE t7 USING fts3(a, b, c);
+    INSERT INTO t7 VALUES('A', 'B', 'C');
+    UPDATE t7 SET docid = 5;
+    SELECT docid, * FROM t7;
+  }
+} {5 A B C}
+do_test fts3cov-7.2 {
+  execsql {
+    INSERT INTO t7 VALUES('D', 'E', 'F');
+    UPDATE t7 SET docid = 1 WHERE docid = 6;
+    SELECT docid, * FROM t7;
+  }
+} {1 D E F 5 A B C}
+
+#-------------------------------------------------------------------------
+# If a set of documents are modified within a transaction, the 
+# pending-terms table must be flushed each time a document with a docid
+# less than or equal to the previous docid is modified. 
+#
+# This test checks the effects of an OOM error occuring when the 
+# pending-terms table is flushed for this reason as part of a DELETE 
+# statement.
+#
+do_malloc_test fts3cov-8 -sqlprep {
+  BEGIN;
+    CREATE VIRTUAL TABLE t8 USING fts3;
+    INSERT INTO t8 VALUES('the output of each batch run');
+    INSERT INTO t8 VALUES('(possibly a day''s work)');
+    INSERT INTO t8 VALUES('was written to two separate disks');
+  COMMIT;
+} -sqlbody {
+  BEGIN;
+    DELETE FROM t8 WHERE rowid = 3;
+    DELETE FROM t8 WHERE rowid = 2;
+    DELETE FROM t8 WHERE rowid = 1;
+  COMMIT;
 }
 
+#-------------------------------------------------------------------------
+# Test some branches in the code that handles "special" inserts like:
+#
+#   INSERT INTO t1(t1) VALUES('optimize');
+#
+# Also test that an optimize (INSERT method) works on an empty table.
+#
+set DO_MALLOC_TEST 0
+do_test fts3cov-9.1 {
+  execsql { CREATE VIRTUAL TABLE xx USING fts3 }
+} {}
+do_error_test fts3cov-9.2 {
+  INSERT INTO xx(xx) VALUES('optimise');   -- British spelling
+} {SQL logic error or missing database}
+do_error_test fts3cov-9.3 {
+  INSERT INTO xx(xx) VALUES('short');
+} {SQL logic error or missing database}
+do_error_test fts3cov-9.4 {
+  INSERT INTO xx(xx) VALUES('waytoolongtobecorrect');
+} {SQL logic error or missing database}
+do_test fts3cov-9.5 {
+  execsql { INSERT INTO xx(xx) VALUES('optimize') }
+} {}
+
+#-------------------------------------------------------------------------
+# Test that a table can be optimized in the middle of a transaction when
+# the pending-terms table is non-empty. This case involves some extra
+# branches because data must be read not only from the database, but
+# also from the pending-terms table.
+#
+do_malloc_test fts3cov-10 -sqlprep {
+  CREATE VIRTUAL TABLE t10 USING fts3;
+  INSERT INTO t10 VALUES('Optimising images for the web is a tricky business');
+  BEGIN;
+    INSERT INTO t10 VALUES('You have to get the right balance between');
+} -sqlbody {
+  INSERT INTO t10(t10) VALUES('optimize');
+}
 
+#-------------------------------------------------------------------------
+# Test a full-text query for a term that was once in the index, but is
+# no longer.
+#
+do_test fts3cov-11.1 {
+  execsql { 
+    CREATE VIRTUAL TABLE xx USING fts3;
+    INSERT INTO xx VALUES('one two three');
+    INSERT INTO xx VALUES('four five six');
+    DELETE FROM xx WHERE docid = 1;
+  }
+  execsql { SELECT * FROM xx WHERE xx MATCH 'two' }
+} {}
 
 finish_test