From 82d25da5b08cc1358b1b19fdb625575dc923879e Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 12 Mar 2014 19:20:36 +0000 Subject: [PATCH] Changes to FTS to ensure that it does not access the database from within the xConnect method. FossilOrigin-Name: c67a52c356416cc200f51f9168d942e78db11d34 --- ext/fts3/fts3.c | 44 ++++++++++++++++++++++++++++++++++++------- ext/fts3/fts3Int.h | 2 +- ext/fts3/fts3_write.c | 4 ++++ manifest | 18 +++++++++--------- manifest.uuid | 2 +- test/fts3d.test | 11 +++++++++++ 6 files changed, 63 insertions(+), 18 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 44b7f431df..f7b2232902 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1410,10 +1410,7 @@ static int fts3InitVtab( ** addition of a %_stat table so that it can use incremental merge. */ if( !isFts4 && !isCreate ){ - int rc2 = SQLITE_OK; - fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2", - p->zDb, p->zName); - if( rc2==SQLITE_OK ) p->bHasStat = 1; + p->bHasStat = 2; } /* Figure out the page-size for the database. This is required in order to @@ -3320,7 +3317,34 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){ } /* -** Implementation of xBegin() method. This is a no-op. +** If it is currently unknown whether or not the FTS table has an %_stat +** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat +** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code +** if an error occurs. +*/ +static int fts3SetHasStat(Fts3Table *p){ + int rc = SQLITE_OK; + if( p->bHasStat==2 ){ + const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'"; + char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName); + if( zSql ){ + sqlite3_stmt *pStmt = 0; + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + if( rc==SQLITE_OK ){ + int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW); + rc = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ) p->bHasStat = bHasStat; + } + sqlite3_free(zSql); + }else{ + rc = SQLITE_NOMEM; + } + } + return rc; +} + +/* +** Implementation of xBegin() method. */ static int fts3BeginMethod(sqlite3_vtab *pVtab){ Fts3Table *p = (Fts3Table*)pVtab; @@ -3331,7 +3355,7 @@ static int fts3BeginMethod(sqlite3_vtab *pVtab){ TESTONLY( p->inTransaction = 1 ); TESTONLY( p->mxSavepoint = -1; ); p->nLeafAdd = 0; - return SQLITE_OK; + return fts3SetHasStat(p); } /* @@ -3580,6 +3604,10 @@ static int fts3RenameMethod( sqlite3 *db = p->db; /* Database connection */ int rc; /* Return Code */ + /* At this point it must be known if the %_stat table exists or not. + ** So bHasStat may not be 2. */ + rc = fts3SetHasStat(p); + /* As it happens, the pending terms table is always empty here. This is ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction ** always opens a savepoint transaction. And the xSavepoint() method @@ -3587,7 +3615,9 @@ static int fts3RenameMethod( ** PendingTermsFlush() in in case that changes. */ assert( p->nPendingData==0 ); - rc = sqlite3Fts3PendingTermsFlush(p); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts3PendingTermsFlush(p); + } if( p->zContentTbl==0 ){ fts3DbExec(&rc, db, diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 7f71736888..a5bb2f0041 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -223,7 +223,7 @@ struct Fts3Table { int nNodeSize; /* Soft limit for node size */ u8 bFts4; /* True for FTS4, false for FTS3 */ - u8 bHasStat; /* True if %_stat table exists */ + u8 bHasStat; /* True if %_stat table exists (2==unknown) */ u8 bHasDocsize; /* True if %_docsize table exists */ u8 bDescIdx; /* True if doclists are in reverse order */ u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */ diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 3564cf8206..90d1609226 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -5271,6 +5271,10 @@ int sqlite3Fts3UpdateMethod( int nChng = 0; /* Net change in number of documents */ int bInsertDone = 0; + /* At this point it must be known if the %_stat table exists or not. + ** So bHasStat may not be 2. */ + assert( p->bHasStat==0 || p->bHasStat==1 ); + assert( p->pSegments==0 ); assert( nArg==1 /* DELETE operations */ diff --git a/manifest b/manifest index 8dd646f40a..313f580784 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prevent\sthe\srtree\smodule\sfrom\sreading\ssqlite_stat1\sdata\sfrom\sthe\swrong\sdatabase. -D 2014-03-12T12:44:46.777 +C Changes\sto\sFTS\sto\sensure\sthat\sit\sdoes\snot\saccess\sthe\sdatabase\sfrom\swithin\sthe\sxConnect\smethod. +D 2014-03-12T19:20:36.904 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -78,9 +78,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 3fe91e36a0304ad4b35020f0e22ff37e95873166 +F ext/fts3/fts3.c 41b1920b9a8657963f09cb93b208c2671c5568db F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h eb5f8029589f3d8f1dc7fd50c773326a640388b1 +F ext/fts3/fts3Int.h bdeb9015405e8facffb8fc7e09174521a2a780f4 F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365 F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 @@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c 92391b4b4fb043564c6539ea9b8661e3bcba47b9 F ext/fts3/fts3_unicode2.c 0113d3acf13429e6dc38e0647d1bc71211c31a4d -F ext/fts3/fts3_write.c cdebe72171a217b1465032dec103f8d17f7dad4d +F ext/fts3/fts3_write.c 74c00329006c3ed6325ba4e5ab7c9b5fc99c8934 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197 @@ -535,7 +535,7 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7 -F test/fts3d.test c8a193513a269ec4c205ca09645e26e0bc71b860 +F test/fts3d.test 597b0b76e41f0d672e2731c4d7b631d628efd13f F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963 F test/fts3defer2.test a3b6cbeabaf28c9398652a4d101ea224d9358479 F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd @@ -1156,7 +1156,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 018d317b1257ce68a92908b05c9c7cf1494050d0 -R 771148b6f32577641865e57d520a643c +P 7ce03c1b5552d830300575c5b41a874db7a2ec77 +R deefc2d49a0ad1f14f370fa09b6f4e09 U dan -Z 84dfe23ccda2d3e1d846c6ac2ce685a0 +Z 287a2bd2233940be3dc25c35e9cb956e diff --git a/manifest.uuid b/manifest.uuid index b36a223a45..1a5538a0a1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7ce03c1b5552d830300575c5b41a874db7a2ec77 \ No newline at end of file +c67a52c356416cc200f51f9168d942e78db11d34 \ No newline at end of file diff --git a/test/fts3d.test b/test/fts3d.test index 818456bfae..2914818d4e 100644 --- a/test/fts3d.test +++ b/test/fts3d.test @@ -354,6 +354,17 @@ do_test fts3d-6.5 { SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1; } } {xyz_content xyz_segdir xyz_segments} + +# ALTER TABLE RENAME on an FTS3 table following an incr-merge op. +# +do_test fts3d-6.6 { + execsql { INSERT INTO xyz(xyz) VALUES('merge=2,2') } + sqlite3 db test.db + execsql { + ALTER TABLE xyz RENAME TO ott; + SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1; + } +} {ott_content ott_segdir ott_segments ott_stat} finish_test -- 2.47.2