Fix an fts5 bug in handling writes while there are active cursors.
FossilOrigin-Name: 07f70955392697556ca2951c9b6c3a5204cd5ec0
This commit is contained in:
+67
-3
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -1 +1 @@
|
||||
8e8136f2dc08082c2984462719d9cba0f212c92a
|
||||
07f70955392697556ca2951c9b6c3a5204cd5ec0
|
||||
Reference in New Issue
Block a user