#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.
** 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;
}
/*
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.
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:
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(
int rc;
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
+ fts5TripCursors(pTab);
rc = sqlite3Fts5StorageSync(pTab->pStorage, 1);
return rc;
}
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
+ fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
}
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
+ fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
}
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
+ fts5TripCursors(pTab);
return sqlite3Fts5StorageRollback(pTab->pStorage);
}
--- /dev/null
+# 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
+
-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
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
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
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