Fix an fts5 bug in handling writes while there are active cursors.

FossilOrigin-Name: 07f70955392697556ca2951c9b6c3a5204cd5ec0
This commit is contained in:
dan
2015-04-28 20:24:50 +00:00
parent cdbd150170
commit 90dd70226f
5 changed files with 128 additions and 11 deletions
+67 -3
View File
@@ -186,6 +186,7 @@ struct Fts5Cursor {
#define FTS5CSR_REQUIRE_DOCSIZE 0x02
#define FTS5CSR_EOF 0x04
#define FTS5CSR_FREE_ZRANK 0x08
#define FTS5CSR_REQUIRE_RESEEK 0x10
/*
** Macros to Set(), Clear() and Test() cursor flags.
@@ -269,14 +270,12 @@ static int fts5IsContentless(Fts5Table *pTab){
** Delete a virtual table handle allocated by fts5InitVtab().
*/
static void fts5FreeVtab(Fts5Table *pTab){
int rc = SQLITE_OK;
if( pTab ){
sqlite3Fts5IndexClose(pTab->pIndex);
sqlite3Fts5StorageClose(pTab->pStorage);
sqlite3Fts5ConfigFree(pTab->pConfig);
sqlite3_free(pTab);
}
return rc;
}
/*
@@ -608,6 +607,63 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
return rc;
}
/*
** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
** open on table pTab.
*/
static void fts5TripCursors(Fts5Table *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( FTS5_PLAN(pCsr->idxNum)==FTS5_PLAN_MATCH
&& pCsr->base.pVtab==(sqlite3_vtab*)pTab
){
CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK);
}
}
}
/*
** If the REQUIRE_RESEEK flag is set on the cursor passed as the first
** argument, close and reopen all Fts5IndexIter iterators that the cursor
** is using. Then attempt to move the cursor to a rowid equal to or laster
** (in the cursors sort order - ASC or DESC) than the current rowid.
**
** If the new rowid is not equal to the old, set output parameter *pbSkip
** to 1 before returning. Otherwise, leave it unchanged.
**
** Return SQLITE_OK if successful or if no reseek was required, or an
** error code if an error occurred.
*/
static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
int rc = SQLITE_OK;
assert( *pbSkip==0 );
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
int bDesc = ((pCsr->idxNum & FTS5_ORDER_DESC) ? 1 : 0);
i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, bDesc);
while( rc==SQLITE_OK && sqlite3Fts5ExprEof(pCsr->pExpr)==0 ){
i64 ii = sqlite3Fts5ExprRowid(pCsr->pExpr);
if( ii==iRowid ) break;
if( (bDesc && ii<iRowid) || (bDesc==0 && ii>iRowid) ){
*pbSkip = 1;
break;
}
rc = sqlite3Fts5ExprNext(pCsr->pExpr);
}
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
fts5CsrNewrow(pCsr);
if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
CsrFlagSet(pCsr, FTS5CSR_EOF);
}
}
return rc;
}
/*
** Advance the cursor to the next row in the table that matches the
** search criteria.
@@ -619,7 +675,10 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int ePlan = FTS5_PLAN(pCsr->idxNum);
int rc = SQLITE_OK;
int bSkip = 0;
int rc;
if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
switch( ePlan ){
case FTS5_PLAN_MATCH:
@@ -1156,6 +1215,7 @@ static int fts5UpdateMethod(
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
assert( pVtab->zErrMsg==0 );
fts5TripCursors(pTab);
if( rc==SQLITE_OK && eType0==SQLITE_INTEGER ){
if( fts5IsContentless(pTab) ){
pTab->base.zErrMsg = sqlite3_mprintf(
@@ -1196,6 +1256,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
int rc;
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
fts5TripCursors(pTab);
rc = sqlite3Fts5StorageSync(pTab->pStorage, 1);
return rc;
}
@@ -1717,6 +1778,7 @@ static int fts5RenameMethod(
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
}
@@ -1728,6 +1790,7 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
}
@@ -1739,6 +1802,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
fts5TripCursors(pTab);
return sqlite3Fts5StorageRollback(pTab->pStorage);
}
+4
View File
@@ -776,6 +776,10 @@ static int fts5ExprNearInitAll(
pPhrase = pNear->apPhrase[i];
for(j=0; j<pPhrase->nTerm; j++){
pTerm = &pPhrase->aTerm[j];
if( pTerm->pIter ){
sqlite3Fts5IterClose(pTerm->pIter);
pTerm->pIter = 0;
}
rc = sqlite3Fts5IndexQuery(
pExpr->pIndex, pTerm->zTerm, strlen(pTerm->zTerm),
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
+48
View File
@@ -0,0 +1,48 @@
# 2015 April 28
#
# 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.
#
#***********************************************************************
#
# This file focuses on testing the planner (xBestIndex function).
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5restart
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE f1 USING fts5(ff);
}
do_test 1.1 {
for {set i 1} {$i < 1000} {incr i} {
execsql { INSERT INTO f1 VALUES('a b c d e') }
lappend lRowid $i
}
} {}
do_execsql_test 1.2 {
SELECT rowid FROM f1 WHERE f1 MATCH 'c';
} $lRowid
breakpoint
do_test 1.3 {
set res [list]
db eval { SELECT rowid FROM f1 WHERE f1 MATCH 'c' } {
if {$rowid == 100} {
execsql { INSERT INTO f1(f1) VALUES('optimize') }
}
lappend res $rowid
}
set res
} $lRowid
finish_test
+8 -7
View File
@@ -1,5 +1,5 @@
C Improve\scoverage\sof\sfts5\stests.
D 2015-04-28T18:35:28.633
C Fix\san\sfts5\sbug\sin\shandling\swrites\swhile\sthere\sare\sactive\scursors.
D 2015-04-28T20:24:50.023
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -104,13 +104,13 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl 159c1194da0bc72f51b3c2eb71022568006dc5ad
F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a
F ext/fts5/fts5.c d9a99a595c0e341cb24918bc67c323d2444a3036
F ext/fts5/fts5.c 45e82b584bb3fce22c82d8521bccaa2a6e9202fe
F ext/fts5/fts5.h 24a2cc35b5e76eec57b37ba48c12d9d2cb522b3a
F ext/fts5/fts5Int.h f573fe6c50471f1d66682fce282da801009c54e1
F ext/fts5/fts5_aux.c fcea18b1a2a3f95a498b52aba2983557d7678a22
F ext/fts5/fts5_buffer.c 8c8cfe7f09ca2767ab53ea883f9a0af0edb6bbae
F ext/fts5/fts5_config.c f344ffa24d2add70fd5bde2b73c44846ad7a06bd
F ext/fts5/fts5_expr.c 05da381ab26031243266069302c6eb4094b2c5dd
F ext/fts5/fts5_expr.c e647a2626af5c80a6325532b23eea6d1eb252a78
F ext/fts5/fts5_hash.c 29d8b0668727863cc1f1efa65efe4dd78635b016
F ext/fts5/fts5_index.c de588982b0237b1605d6c37afd115b34c95c3da1
F ext/fts5/fts5_storage.c ef60fc9dcc4e274f9589165e26833173c273ae18
@@ -152,6 +152,7 @@ F ext/fts5/test/fts5optimize.test 0028c90a7817d3e576d1148fc8dff17d89054e54
F ext/fts5/test/fts5porter.test 50322599823cb8080a99f0ec0c39f7d0c12bcb5e
F ext/fts5/test/fts5prefix.test 1287803c3df0e43f536196256fb9e0e6baccb4f1
F ext/fts5/test/fts5rebuild.test ee6792715c6c528cc188e7869d67c3c655889ddb
F ext/fts5/test/fts5restart.test 4934233dd2633665198d563c79f1015e3a2b9518
F ext/fts5/test/fts5rowid.test a1b2a6d76648c734c1aab11ee1a619067e8d90e6
F ext/fts5/test/fts5tokenizer.test 7a6ee24db908c09a0dc1eba634ffa17afcc05d86
F ext/fts5/test/fts5unicode.test 79b3e34eb29ce4929628aa514a40cb467fdabe4d
@@ -1310,7 +1311,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P e38e2bb637844dae8ae5d5f3e23d8369e1b91e45
R 36584b17863acf9c4ced66420a8dd86e
P 8e8136f2dc08082c2984462719d9cba0f212c92a
R 65017a9d42efb9cfacfe6e269e92cdbd
U dan
Z 4aeb27eb1cd105a6fffeab8d10b6e855
Z 91e05f6f4d01e29ed38305d1f49be921
+1 -1
View File
@@ -1 +1 @@
8e8136f2dc08082c2984462719d9cba0f212c92a
07f70955392697556ca2951c9b6c3a5204cd5ec0