From: dan Date: Thu, 13 Oct 2011 17:16:45 +0000 (+0000) Subject: Handle updating the only row of an FTS table correctly. Fix for [9fd058691]. X-Git-Tag: version-3.7.9~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8dab211632ad34bbfbf809eac10a3883e1c12601;p=thirdparty%2Fsqlite.git Handle updating the only row of an FTS table correctly. Fix for [9fd058691]. FossilOrigin-Name: 7e24645be2fe0ffe092212e7bcfa5b4500305811 --- diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 29e071a50f..b3780b8349 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -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( zCsrzEnd ){ - 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. diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index ed8043adf6..f210aa4569 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -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; diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c index b569eb131b..3bb47a04ad 100644 --- a/ext/fts3/fts3_snippet.c +++ b/ext/fts3/fts3_snippet.c @@ -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; } } } diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 36f2249e12..471feeec9f 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -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 ){ diff --git a/manifest b/manifest index fc7425da2c..a6cd78f5fa 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index b18b5e4606..49e0787bce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -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 index 0000000000..b228482d46 --- /dev/null +++ b/test/fts-9fd058691.test @@ -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