]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Handle updating the only row of an FTS table correctly. Fix for [9fd058691].
authordan <dan@noemail.net>
Thu, 13 Oct 2011 17:16:45 +0000 (17:16 +0000)
committerdan <dan@noemail.net>
Thu, 13 Oct 2011 17:16:45 +0000 (17:16 +0000)
FossilOrigin-Name: 7e24645be2fe0ffe092212e7bcfa5b4500305811

ext/fts3/fts3.c
ext/fts3/fts3Int.h
ext/fts3/fts3_snippet.c
ext/fts3/fts3_write.c
manifest
manifest.uuid
test/fts-9fd058691.test [new file with mode: 0644]

index 29e071a50f15d8e11ad744fa70522e22f8e1e786..b3780b8349aa865746874c9c2c33ff05de1c02d0 100644 (file)
@@ -1338,7 +1338,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
         ** table is missing a row that is present in the full-text index.
         ** The data structures are corrupt.
         */
-        rc = SQLITE_CORRUPT_VTAB;
+        rc = FTS_CORRUPT_VTAB;
       }
       pCsr->isEof = 1;
       if( pContext ){
@@ -1398,7 +1398,7 @@ static int fts3ScanInteriorNode(
   zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
   zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
   if( zCsr>zEnd ){
-    return SQLITE_CORRUPT_VTAB;
+    return FTS_CORRUPT_VTAB;
   }
   
   while( zCsr<zEnd && (piFirst || piLast) ){
@@ -1416,7 +1416,7 @@ static int fts3ScanInteriorNode(
     zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
     
     if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
-      rc = SQLITE_CORRUPT_VTAB;
+      rc = FTS_CORRUPT_VTAB;
       goto finish_scan;
     }
     if( nPrefix+nSuffix>nAlloc ){
@@ -3859,7 +3859,7 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
     }
     if( nDoc==0 || nByte==0 ){
       sqlite3_reset(pStmt);
-      return SQLITE_CORRUPT_VTAB;
+      return FTS_CORRUPT_VTAB;
     }
 
     pCsr->nDoc = nDoc;
@@ -4826,6 +4826,15 @@ void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
   }
 }
 
+/*
+** Return SQLITE_CORRUPT_VTAB.
+*/
+#ifdef SQLITE_DEBUG
+int sqlite3Fts3Corrupt(){
+  return SQLITE_CORRUPT_VTAB;
+}
+#endif
+
 #if !SQLITE_CORE
 /*
 ** Initialize API pointer table, if required.
index ed8043adf61079613324679276332c66b38acd9f..f210aa4569b12391fb4e0d6e61306038d43ef7a7 100644 (file)
@@ -157,6 +157,13 @@ typedef sqlite3_uint64 u64;       /* 8-byte unsigned integer */
 
 #endif /* SQLITE_AMALGAMATION */
 
+#ifdef SQLITE_DEBUG
+int sqlite3Fts3Corrupt(void);
+# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt()
+#else
+# define FTS_CORRUPT_VTAB SQLITE_CORRUPT_VTAB
+#endif
+
 typedef struct Fts3Table Fts3Table;
 typedef struct Fts3Cursor Fts3Cursor;
 typedef struct Fts3Expr Fts3Expr;
index b569eb131b48b144f73274c1d5ddbc669c54c9bb..3bb47a04add005bc60f6dd6f69f9d31e9dabeb9f 100644 (file)
@@ -848,7 +848,7 @@ static int fts3MatchinfoSelectDoctotal(
 
   a = sqlite3_column_blob(pStmt, 0);
   a += sqlite3Fts3GetVarint(a, &nDoc);
-  if( nDoc==0 ) return SQLITE_CORRUPT_VTAB;
+  if( nDoc==0 ) return FTS_CORRUPT_VTAB;
   *pnDoc = (u32)nDoc;
 
   if( paLen ) *paLen = a;
@@ -1427,7 +1427,7 @@ void sqlite3Fts3Offsets(
           );
           rc = fts3StringAppend(&res, aBuffer, -1);
         }else if( rc==SQLITE_DONE ){
-          rc = SQLITE_CORRUPT_VTAB;
+          rc = FTS_CORRUPT_VTAB;
         }
       }
     }
index 36f2249e12b06f4e2c480c57ce1a452059d18e3a..471feeec9f39925f2b3f0f0e140695a41d5f2058 100644 (file)
@@ -341,7 +341,7 @@ static int fts3SelectDocsize(
     rc = sqlite3_step(pStmt);
     if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
       rc = sqlite3_reset(pStmt);
-      if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT_VTAB;
+      if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
       pStmt = 0;
     }else{
       rc = SQLITE_OK;
@@ -1145,7 +1145,7 @@ static int fts3SegReaderNext(
   if( nPrefix<0 || nSuffix<=0 
    || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] 
   ){
-    return SQLITE_CORRUPT_VTAB;
+    return FTS_CORRUPT_VTAB;
   }
 
   if( nPrefix+nSuffix>pReader->nTermAlloc ){
@@ -1175,7 +1175,7 @@ static int fts3SegReaderNext(
   if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode] 
    || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
   ){
-    return SQLITE_CORRUPT_VTAB;
+    return FTS_CORRUPT_VTAB;
   }
   return SQLITE_OK;
 }
@@ -3129,7 +3129,6 @@ int sqlite3Fts3UpdateMethod(
   Fts3Table *p = (Fts3Table *)pVtab;
   int rc = SQLITE_OK;             /* Return Code */
   int isRemove = 0;               /* True for an UPDATE or DELETE */
-  sqlite3_int64 iRemove = 0;      /* Rowid removed by UPDATE or DELETE */
   u32 *aSzIns = 0;                /* Sizes of inserted documents */
   u32 *aSzDel;                    /* Sizes of deleted documents */
   int nChng = 0;                  /* Net change in number of documents */
@@ -3212,19 +3211,19 @@ int sqlite3Fts3UpdateMethod(
     assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
     rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
     isRemove = 1;
-    iRemove = sqlite3_value_int64(apVal[0]);
   }
   
   /* If this is an INSERT or UPDATE operation, insert the new record. */
   if( nArg>1 && rc==SQLITE_OK ){
     if( bInsertDone==0 ){
       rc = fts3InsertData(p, apVal, pRowid);
-      if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT_VTAB;
+      if( rc==SQLITE_CONSTRAINT ) rc = FTS_CORRUPT_VTAB;
     }
-    if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
+    if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
       rc = fts3PendingTermsDocid(p, *pRowid);
     }
     if( rc==SQLITE_OK ){
+      assert( p->iPrevDocid==*pRowid );
       rc = fts3InsertTerms(p, apVal, aSzIns);
     }
     if( p->bHasDocsize ){
index fc7425da2c160fe8ea729218c136966ebdb1801e..a6cd78f5fa84a52853277c5036760894bb7cf5bf 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C An\simproved\sfix\sfor\sthe\spage_count\sand\squick_check\sproblem\spreviously\npatched\sat\s[150592b4b4d8637]
-D 2011-10-13T17:09:01.247
+C Handle\supdating\sthe\sonly\srow\sof\san\sFTS\stable\scorrectly.\sFix\sfor\s[9fd058691].
+D 2011-10-13T17:16:45.272
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -62,22 +62,22 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
 F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 195e4da669741c1f097434ec48c0ba5739193af9
+F ext/fts3/fts3.c 0ace6b45d62338b35f095c7e7d1851965e477e4e
 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 30063fdd0bc433b5db1532e3a363cb0f2f7e8eb3
+F ext/fts3/fts3Int.h 59c5a9475fed5d76c70a4763103b3c8e60424a68
 F ext/fts3/fts3_aux.c 0ebfa7b86cf8ff6a0861605fcc63b83ec1b70691
 F ext/fts3/fts3_expr.c 23791de01b3a5d313d76e02befd2601d4096bc2b
 F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
 F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
 F ext/fts3/fts3_icu.c 6c8f395cdf9e1e3afa7fadb7e523dbbf381c6dfa
 F ext/fts3/fts3_porter.c 8d946908f4812c005d3d33fcbe78418b1f4eb70c
-F ext/fts3/fts3_snippet.c 58b2ba2b934c1e2a2f6ac857d7f3c7e1a14b4532
+F ext/fts3/fts3_snippet.c 19a906f8ed73ad8b670dfc271ceae7b3338c157e
 F ext/fts3/fts3_term.c a5457992723455a58804cb75c8cbd8978db5c2ef
 F ext/fts3/fts3_test.c 24fa13f330db011500acb95590da9eee24951894
 F ext/fts3/fts3_tokenizer.c 9ff7ec66ae3c5c0340fa081958e64f395c71a106
 F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
 F ext/fts3/fts3_tokenizer1.c 0dde8f307b8045565cf63797ba9acfaff1c50c68
-F ext/fts3/fts3_write.c 194829c8fd024a448fc899e5ff02a8ed06595529
+F ext/fts3/fts3_write.c ffe13acc3867ea6b0fc8b9cfbf904bfae64eac84
 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
 F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
@@ -408,6 +408,7 @@ F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e
 F test/fkey4.test c6c8f9f9be885f95c85c7bceb26f243ad906fd49
 F test/fkey_malloc.test a5ede29bd2f6e56dea78c3d43fb86dd696c068c8
 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
+F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
 F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
 F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5
 F test/fts1c.test 85a525ce7428907469b4cce13d5563ce542ce64c
@@ -968,7 +969,7 @@ F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 8bf13b036a77af9984f8f3d3a93da589fafd773f
-R 2d14ac4e9551c84e90407929f7ce1d30
-U drh
-Z 0f1ef2a0c533d691837cc1c484eedc14
+P c3cb7f4fad725d5fa4d5acd9da63fc4538ce8e13
+R ec95a62db79b84d7111fda3a8be06ca9
+U dan
+Z 25dbdd79336e5688c7ffd1d8a10e1ab3
index b18b5e460625cb79c2b7aa8d4171de53d6394538..49e0787bce908a9716c548d3b963dfbf4e982350 100644 (file)
@@ -1 +1 @@
-c3cb7f4fad725d5fa4d5acd9da63fc4538ce8e13
\ No newline at end of file
+7e24645be2fe0ffe092212e7bcfa5b4500305811
\ No newline at end of file
diff --git a/test/fts-9fd058691.test b/test/fts-9fd058691.test
new file mode 100644 (file)
index 0000000..b228482
--- /dev/null
@@ -0,0 +1,59 @@
+# 2011 October 13
+#
+#    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 implements regression tests for the FTS SQLite module.
+#
+# This file implements tests to verify that ticket [9fd058691] has been
+# fixed.  
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
+ifcapable !fts3 {
+  finish_test
+  return
+}
+
+set ::testprefix fts3-9fd058691
+
+do_execsql_test 1.0 {
+  CREATE VIRTUAL TABLE fts USING fts3( tags TEXT);
+  INSERT INTO fts (tags) VALUES ('tag1');
+  SELECT * FROM fts WHERE tags MATCH 'tag1';
+} {tag1}
+
+do_test 1.1 {
+  db close
+  sqlite3 db test.db
+  execsql {
+    UPDATE fts SET tags = 'tag1' WHERE rowid = 1;
+    SELECT * FROM fts WHERE tags MATCH 'tag1';
+  }
+} {tag1}
+
+db close
+forcedelete test.db
+sqlite3 db test.db
+
+do_execsql_test 2.0 {
+  CREATE VIRTUAL TABLE fts USING fts3(tags TEXT);
+  INSERT INTO fts (docid, tags) VALUES (1, 'tag1');
+  INSERT INTO fts (docid, tags) VALUES (2, NULL);
+  INSERT INTO fts (docid, tags) VALUES (3, 'three');
+} {}
+
+do_test 2.1 {
+  execsql {
+    UPDATE fts SET tags = 'two' WHERE rowid = 2;
+    SELECT * FROM fts WHERE tags MATCH 'two';
+  }
+} {two}
+
+finish_test